summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy.green@linaro.org>2014-12-04 11:32:29 +0800
committerAndy Green <andy.green@linaro.org>2014-12-04 19:00:45 +0800
commit5cde20a8d186df94e7c1c6c931a7a7180c16a75d (patch)
treec48359cedd0c1ea9c56a7c3cfe60e318fb09d80c
parenta717d8b580c536b0b60206489a373c18df927e20 (diff)
Signed-off-by: Andy Green <andy.green@linaro.org>
-rw-r--r--arch/arm/Kconfig131
-rw-r--r--arch/arm/Kconfig.debug23
-rw-r--r--arch/arm/Makefile17
-rw-r--r--arch/arm/boot/.gitignore1
-rw-r--r--arch/arm/boot/Makefile14
-rw-r--r--arch/arm/boot/compressed/head.S4
-rw-r--r--arch/arm/boot/dts/Makefile14
-rw-r--r--arch/arm/boot/dts/msm-gdsc-8916.dtsi63
-rw-r--r--arch/arm/boot/dts/msm-gdsc.dtsi168
-rw-r--r--arch/arm/boot/dts/msm-pm8916-rpm-regulator.dtsi365
-rw-r--r--arch/arm/boot/dts/msm-pm8916.dtsi632
-rw-r--r--arch/arm/boot/dts/msm-rdbg.dtsi75
-rw-r--r--arch/arm/boot/dts/msm8916-bus.dtsi877
-rw-r--r--arch/arm/boot/dts/msm8916-ipcrouter.dtsi37
-rw-r--r--arch/arm/boot/dts/msm8916-memory.dtsi45
-rw-r--r--arch/arm/boot/dts/msm8916-pinctrl.dtsi1374
-rw-r--r--arch/arm/boot/dts/msm8916-pm.dtsi345
-rw-r--r--arch/arm/boot/dts/msm8916-qrd-skui.dts36
-rw-r--r--arch/arm/boot/dts/msm8916-qrd-skui.dtsi67
-rw-r--r--arch/arm/boot/dts/msm8916-qrd.dtsi137
-rw-r--r--arch/arm/boot/dts/msm8916-regulator.dtsi373
-rw-r--r--arch/arm/boot/dts/msm8916.dtsi810
-rw-r--r--arch/arm/boot/dts/skeleton.dtsi7
-rw-r--r--arch/arm/configs/msm8916-qrd-andy_defconfig121
-rw-r--r--arch/arm/include/asm/cacheflush.h29
-rw-r--r--arch/arm/include/asm/cputype.h1
-rw-r--r--arch/arm/include/asm/device.h1
-rw-r--r--arch/arm/include/asm/dma-mapping.h147
-rw-r--r--arch/arm/include/asm/domain.h7
-rw-r--r--arch/arm/include/asm/glue-cache.h2
-rw-r--r--arch/arm/include/asm/io.h25
-rw-r--r--arch/arm/include/asm/mach/arch.h1
-rw-r--r--arch/arm/include/asm/mach/flash.h9
-rw-r--r--arch/arm/include/asm/mach/map.h4
-rw-r--r--arch/arm/include/asm/memory.h6
-rw-r--r--arch/arm/include/asm/mmu_writeable.h31
-rw-r--r--arch/arm/include/asm/page.h5
-rw-r--r--arch/arm/include/asm/pgtable-3level-hwdef.h1
-rw-r--r--arch/arm/include/asm/pgtable-3level.h2
-rw-r--r--arch/arm/include/asm/pgtable.h16
-rw-r--r--arch/arm/include/asm/processor.h3
-rw-r--r--arch/arm/include/asm/setup.h31
-rw-r--r--arch/arm/include/asm/smcmod.h165
-rw-r--r--arch/arm/include/asm/smp.h1
-rw-r--r--arch/arm/include/asm/spinlock.h93
-rw-r--r--arch/arm/include/asm/system_misc.h1
-rw-r--r--arch/arm/include/asm/tlbflush.h4
-rw-r--r--arch/arm/include/uapi/asm/posix_types.h3
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/devtree.c28
-rw-r--r--arch/arm/kernel/entry-armv.S116
-rw-r--r--arch/arm/kernel/fiq.c7
-rw-r--r--arch/arm/kernel/head.S11
-rw-r--r--arch/arm/kernel/hw_breakpoint.c22
-rw-r--r--arch/arm/kernel/patch.c8
-rw-r--r--arch/arm/kernel/setup.c45
-rw-r--r--arch/arm/kernel/smp.c1
-rw-r--r--arch/arm/kernel/vmlinux.lds.S20
-rw-r--r--arch/arm/mach-msm/Makefile.boot32
-rw-r--r--arch/arm/mach-msm/board-8916.c128
-rw-r--r--arch/arm/mach-msm/board-dt.c31
-rw-r--r--arch/arm/mach-msm/board-dt.h15
-rw-r--r--arch/arm/mach-msm/boot_stats.c108
-rw-r--r--arch/arm/mach-msm/cache_erp.c670
-rw-r--r--arch/arm/mach-msm/dma.c869
-rw-r--r--arch/arm/mach-msm/gpiomux-v2.c32
-rw-r--r--arch/arm/mach-msm/gpiomux.c204
-rw-r--r--arch/arm/mach-msm/hotplug.c161
-rw-r--r--arch/arm/mach-msm/include/mach/board.h208
-rw-r--r--arch/arm/mach-msm/include/mach/debug_mm.h33
-rw-r--r--arch/arm/mach-msm/include/mach/dma.h197
-rw-r--r--arch/arm/mach-msm/include/mach/entry-macro.S9
-rw-r--r--arch/arm/mach-msm/include/mach/gpio.h231
-rw-r--r--arch/arm/mach-msm/include/mach/gpiomux.h216
-rw-r--r--arch/arm/mach-msm/include/mach/hardware.h4
-rw-r--r--arch/arm/mach-msm/include/mach/io.h23
-rw-r--r--arch/arm/mach-msm/include/mach/ipc_bridge.h65
-rw-r--r--arch/arm/mach-msm/include/mach/memory.h57
-rw-r--r--arch/arm/mach-msm/include/mach/mpp.h262
-rw-r--r--arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h77
-rw-r--r--arch/arm/mach-msm/include/mach/msm_cache_dump.h69
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap-8916.h34
-rw-r--r--arch/arm/mach-msm/include/mach/msm_iomap.h59
-rw-r--r--arch/arm/mach-msm/include/mach/msm_memtypes.h28
-rw-r--r--arch/arm/mach-msm/include/mach/msm_mpmctr.h21
-rw-r--r--arch/arm/mach-msm/include/mach/msm_pcie.h39
-rw-r--r--arch/arm/mach-msm/include/mach/msm_serial_hsl_regs.h35
-rw-r--r--arch/arm/mach-msm/include/mach/msm_serial_pdata.h28
-rw-r--r--arch/arm/mach-msm/include/mach/msm_spi.h45
-rw-r--r--arch/arm/mach-msm/include/mach/msm_tspp.h108
-rw-r--r--arch/arm/mach-msm/include/mach/msm_tspp2.h759
-rw-r--r--arch/arm/mach-msm/include/mach/msm_xo.h56
-rw-r--r--arch/arm/mach-msm/include/mach/proc_comm.h181
-rw-r--r--arch/arm/mach-msm/include/mach/rpm-regulator.h228
-rw-r--r--arch/arm/mach-msm/include/mach/rpm.h1186
-rw-r--r--arch/arm/mach-msm/include/mach/scm-io.h22
-rw-r--r--arch/arm/mach-msm/include/mach/sirc.h19
-rw-r--r--arch/arm/mach-msm/include/mach/subsystem_restart.h17
-rw-r--r--arch/arm/mach-msm/include/mach/uncompress.h64
-rw-r--r--arch/arm/mach-msm/io.c16
-rw-r--r--arch/arm/mach-msm/keypad-surf-ffa.c0
-rw-r--r--arch/arm/mach-msm/krait-scm.c106
-rw-r--r--arch/arm/mach-msm/memory.c223
-rw-r--r--arch/arm/mach-msm/msm-buspm-dev.c335
-rw-r--r--arch/arm/mach-msm/msm-buspm-dev.h58
-rw-r--r--arch/arm/mach-msm/msm-krait-l2-accessors.c56
-rw-r--r--arch/arm/mach-msm/msm_cache_dump.c274
-rw-r--r--arch/arm/mach-msm/msm_mem_hole.c29
-rw-r--r--arch/arm/mach-msm/msm_mpmctr.c99
-rw-r--r--arch/arm/mach-msm/msm_watchdog.h83
-rw-r--r--arch/arm/mach-msm/perf_debug.c83
-rw-r--r--arch/arm/mach-msm/perf_event_msm_krait_l2.c599
-rw-r--r--arch/arm/mach-msm/perf_trace_counters.c185
-rw-r--r--arch/arm/mach-msm/perf_trace_counters.h161
-rw-r--r--arch/arm/mach-msm/perfmap.c126
-rw-r--r--arch/arm/mach-msm/platsmp.c539
-rw-r--r--arch/arm/mach-msm/platsmp.h26
-rw-r--r--arch/arm/mach-msm/rpm_resources.h263
-rw-r--r--arch/arm/mach-msm/scm-xpu.c44
-rw-r--r--arch/arm/mach-msm/smcmod.c831
-rw-r--r--arch/arm/mach-msm/test-lpm.c692
-rw-r--r--arch/arm/mach-msm/test-lpm.h22
-rw-r--r--arch/arm/mach-msm/test_qmi_client.c450
-rw-r--r--arch/arm/mach-msm/timer.h31
-rw-r--r--arch/arm/mach-msm/tz_log.c785
-rw-r--r--arch/arm/mach-qcom/Kconfig31
-rw-r--r--arch/arm/mm/Kconfig15
-rw-r--r--arch/arm/mm/alignment.c35
-rw-r--r--arch/arm/mm/cache-v7.S1
-rw-r--r--arch/arm/mm/init.c3
-rw-r--r--arch/arm/tools/mach-types37
-rw-r--r--drivers/Makefile3
-rw-r--r--drivers/base/Makefile2
-rw-r--r--drivers/base/dma-contiguous.c526
-rw-r--r--drivers/base/dma-removed.c162
-rw-r--r--drivers/clocksource/qcom-timer.c1126
-rw-r--r--drivers/soc/qcom/Makefile54
-rw-r--r--drivers/soc/qcom/idle-v7.S64
-rw-r--r--drivers/soc/qcom/socinfo.c1355
-rw-r--r--include/asm-generic/dma-contiguous.h16
-rw-r--r--include/asm-generic/percpu-defs.h0
-rw-r--r--include/asm-generic/vmlinux.lds.h17
-rw-r--r--include/dt-bindings/clock/msm-clocks-8916.h222
-rw-r--r--include/linux/dma-attrs.h2
-rw-r--r--include/linux/dma-removed.h16
-rw-r--r--include/linux/msm_rtb.h83
-rw-r--r--include/linux/percpu-defs.h13
-rw-r--r--include/linux/reboot.h1
-rw-r--r--include/linux/regulator/krait-regulator.h39
-rw-r--r--include/linux/sched_clock.h5
-rw-r--r--include/linux/smp.h21
-rw-r--r--include/soc/qcom/boot_stats.h17
-rw-r--r--include/soc/qcom/pm.h155
-rw-r--r--include/soc/qcom/scm-boot.h65
-rw-r--r--include/soc/qcom/scm.h124
-rw-r--r--include/soc/qcom/smem.h241
-rw-r--r--include/soc/qcom/socinfo.h604
-rw-r--r--init/Kconfig6
-rw-r--r--scripts/Makefile.lib6
159 files changed, 24061 insertions, 336 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 89c4b5ccc68d..f65f744418d6 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -217,6 +217,9 @@ config NEED_RET_TO_USER
config ARCH_MTD_XIP
bool
+config ARCH_WANT_KMAP_ATOMIC_FLUSH
+ bool
+
config VECTORS_BASE
hex
default 0xffff0000 if MMU || CPU_HIGH_VECTOR
@@ -283,6 +286,24 @@ config GENERIC_BUG
def_bool y
depends on BUG
+config ARM_USER_ACCESSIBLE_TIMER_BASE
+ hex "Base address of user-accessible timer counter page"
+ default 0xfffef000
+ depends on ARM_USE_USER_ACCESSIBLE_TIMERS
+ help
+ Specify the base user-space virtual address where the user-accessible
+ timer counter page should be mapped by the kernel. User-space apps
+ will read directly from the page at this address.
+
+config ARCH_RANDOM
+ bool "SOC specific random number generation"
+ help
+ Allow the kernel to use an architecture specific implementation for
+ random number generation
+
+ If unsure, say N
+
+
source "init/Kconfig"
source "kernel/Kconfig.freezer"
@@ -639,9 +660,22 @@ config ARCH_PXA
config ARCH_MSM
bool "Qualcomm MSM (non-multiplatform)"
+ select ARCH_HAS_CPUFREQ
select ARCH_REQUIRE_GPIOLIB
select COMMON_CLK
select GENERIC_CLOCKEVENTS
+ select GENERIC_GPIO
+ select GENERIC_TIME
+ select GENERIC_ALLOCATOR
+ select HAVE_CLK
+ select HAVE_CLK_PREPARE
+ select NEED_MACH_MEMORY_H
+ select NEED_MACH_IO_H
+ select NEED_MACH_GPIO_H
+ select SOC_BUS
+ select MULTI_IRQ_HANDLER
+ select SPARSE_IRQ
+ select USE_OF
help
Support for Qualcomm MSM/QSD based systems. This runs on the
apps processor of the MSM/QSD and depends on a shared memory
@@ -1009,6 +1043,15 @@ source "arch/arm/firmware/Kconfig"
source arch/arm/mm/Kconfig
+config RESERVE_FIRST_PAGE
+ bool
+ default n
+ help
+ Reserve the first page at PHYS_OFFSET. The first
+ physical page is used by many platforms for warm
+ boot operations. Reserve this page so that it is
+ not allocated by the kernel.
+
config IWMMXT
bool "Enable iWMMXt support"
depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4 || CPU_PJ4B
@@ -1253,6 +1296,12 @@ config ARM_ERRATA_773022
loop buffer may deliver incorrect instructions. This
workaround disables the loop buffer to avoid the erratum.
+config PERFMAP
+ tristate "Perfmap support (EXPERIMENTAL)"
+ depends on ARCH_MSM_KRAIT
+ help
+ Perfmap: memory mapped interface for performance monitors.
+
endmenu
source "arch/arm/common/Kconfig"
@@ -1707,6 +1756,42 @@ config ARCH_WANT_GENERAL_HUGETLB
source "mm/Kconfig"
+config ARCH_MEMORY_PROBE
+ def_bool n
+
+config ARCH_MEMORY_REMOVE
+ def_bool n
+
+config ENABLE_DMM
+ def_bool n
+
+choice
+ prompt "Virtual Memory Reclaim"
+ default NO_VM_RECLAIM
+ help
+ Select the method of reclaiming virtual memory
+
+config ENABLE_VMALLOC_SAVING
+ bool "Reclaim memory for each subsystem"
+ help
+ Enable this config to reclaim the virtual space belonging
+ to any subsystem which is expected to have a lifetime of
+ the entire system. This feature allows lowmem to be non-
+ contiguous.
+
+config NO_VM_RECLAIM
+ bool "Do not reclaim memory"
+ help
+ Do not reclaim any memory. This might result in less lowmem
+ and wasting virtual memory space which could otherwise be
+ reclaimed by using any of the other two config options.
+
+endchoice
+
+config HOLES_IN_ZONE
+ def_bool n
+ depends on SPARSEMEM
+
config FORCE_MAX_ZONEORDER
int "Maximum zone order" if ARCH_SHMOBILE_LEGACY
range 11 64 if ARCH_SHMOBILE_LEGACY
@@ -1790,6 +1875,26 @@ config XEN
help
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
+config CP_ACCESS
+ tristate "CP register access tool"
+ default m
+ help
+ Provide support for Coprocessor register access using /sys
+ interface. Read and write to CP registers from userspace
+ through sysfs interface. A sys file (cp_rw) will be created under
+ /sys/devices/cpaccess/cpaccess0.
+
+ If unsure, say N.
+
+config ARM_FLUSH_CONSOLE_ON_RESTART
+ bool "Force flush the console on restart"
+ help
+ If the console is locked while the system is rebooted, the messages
+ in the temporary logbuffer would not have propogated to all the
+ console drivers. This option forces the console lock to be
+ released if it failed to be acquired, which will cause all the
+ pending messages to be flushed.
+
endmenu
menu "Boot options"
@@ -1820,6 +1925,21 @@ config DEPRECATED_PARAM_STRUCT
This was deprecated in 2001 and announced to live on for 5 years.
Some old boot loaders still use this way.
+config BUILD_ARM_APPENDED_DTB_IMAGE
+ bool "Build a concatenated zImage/dtb by default"
+ depends on OF
+ help
+ Enabling this option will cause a concatenated zImage and list of
+ DTBs to be built by default (instead of a standalone zImage.)
+ The image will built in arch/arm/boot/zImage-dtb
+
+config BUILD_ARM_APPENDED_DTB_IMAGE_NAMES
+ string "Default dtb names"
+ depends on BUILD_ARM_APPENDED_DTB_IMAGE
+ help
+ Space separated list of names of dtbs to append when
+ building a concatenated zImage-dtb.
+
# Compressed boot loader in ROM. Yes, we really want to ask about
# TEXT and BSS so we preserve their values in the config files.
config ZBOOT_ROM_TEXT
@@ -2043,6 +2163,17 @@ config AUTO_ZRELADDR
0xf8000000. This assumes the zImage being placed in the first 128MB
from start of memory.
+config ARM_DECOMPRESSOR_LIMIT
+ hex "Limit the decompressor memory area"
+ default 0x10000000
+ help
+ Allows overriding of the memory size that decompressor maps with
+ read, write and execute permissions to avoid speculative prefetch.
+
+ By default ARM_DECOMPRESSOR_LIMIT maps first 1GB of memory
+ with read, write and execute permissions and reset of the memory
+ as strongly ordered.
+
endmenu
menu "CPU Power Management"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index d8f6a2ec3d4e..797730343ae6 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -75,6 +75,29 @@ config DEBUG_USER
8 - SIGSEGV faults
16 - SIGBUS faults
+config FORCE_PAGES
+ bool "Force lowmem to be mapped with 4K pages"
+ help
+ There are some advanced debug features that can only be done when
+ memory is mapped with pages instead of sections. Enable this option
+ to always map lowmem pages with pages. This may have a performance
+ cost due to increased TLB pressure.
+
+ If unsure say N.
+
+config FREE_PAGES_RDONLY
+ bool "Set pages as read only while on the buddy list"
+ select FORCE_PAGES
+ select PAGE_POISONING
+ help
+ Pages are always mapped in the kernel. This means that anyone
+ can write to the page if they have the address. Enable this option
+ to mark pages as read only to trigger a fault if any code attempts
+ to write to a page on the buddy list. This may have a performance
+ impact.
+
+ If unsure, say N.
+
# These options are only for real kernel hackers who want to get their hands dirty.
config DEBUG_LL
bool "Kernel low-level debugging functions (read help!)"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 034a94904d69..4d21d84ba867 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -70,6 +70,18 @@ arch-$(CONFIG_CPU_32v3) =-D__LINUX_ARM_ARCH__=3 -march=armv3
# Evaluate arch cc-option calls now
arch-y := $(arch-y)
+# Since 'cortex-a15' is a superset of the 'armv7-a' arch spec, we need to
+# explicitly redefine the arch options to not include '-march=armv7-a' when
+# generating code for Krait, which is compatible with the instruction set of the
+# Cortex-A15, because GCC will warn us about ambiguous ISA restrictions caused
+# by seemingly conflicting -march and -mcpu options.
+# If $(CC) does not support the -mcpu=cortex-a15 option, fall back on passing
+# -march=armv7-a to specify the ISA restriction, though this is suboptimal. To
+# keep things simpler, we don't bother with a fallback option if the compiler
+# doesn't even support -march=armv7-a, since in that situation we would have
+# bigger problems.
+arch-$(CONFIG_ARCH_MSM_KRAIT) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-mcpu=cortex-a15,-march=armv7-a)
+
# This selects how we optimise for the processor.
tune-$(CONFIG_CPU_ARM7TDMI) =-mtune=arm7tdmi
tune-$(CONFIG_CPU_ARM720T) =-mtune=arm7tdmi
@@ -278,6 +290,8 @@ libs-y := arch/arm/lib/ $(libs-y)
# Default target when executing plain make
ifeq ($(CONFIG_XIP_KERNEL),y)
KBUILD_IMAGE := xipImage
+else ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y)
+KBUILD_IMAGE := zImage-dtb
else
KBUILD_IMAGE := zImage
endif
@@ -315,6 +329,9 @@ PHONY += dtbs dtbs_install
dtbs dtbs_install: prepare scripts
$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $@
+zImage-dtb: vmlinux scripts dtbs
+ $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
+
# We use MRPROPER_FILES and CLEAN_FILES now
archclean:
$(Q)$(MAKE) $(clean)=$(boot)
diff --git a/arch/arm/boot/.gitignore b/arch/arm/boot/.gitignore
index 3c79f85975aa..ad7a0253ea96 100644
--- a/arch/arm/boot/.gitignore
+++ b/arch/arm/boot/.gitignore
@@ -4,3 +4,4 @@ xipImage
bootpImage
uImage
*.dtb
+zImage-dtb \ No newline at end of file
diff --git a/arch/arm/boot/Makefile b/arch/arm/boot/Makefile
index ec2f8065f955..13ccec54b094 100644
--- a/arch/arm/boot/Makefile
+++ b/arch/arm/boot/Makefile
@@ -27,6 +27,14 @@ export ZRELADDR INITRD_PHYS PARAMS_PHYS
targets := Image zImage xipImage bootpImage uImage
+DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES))
+ifneq ($(DTB_NAMES),)
+DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
+else
+DTB_LIST := $(dtb-y)
+endif
+DTB_OBJS := $(addprefix $(obj)/dts/,$(DTB_LIST))
+
ifeq ($(CONFIG_XIP_KERNEL),y)
$(obj)/xipImage: vmlinux FORCE
@@ -55,6 +63,12 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
@$(kecho) ' Kernel: $@ is ready'
+$(obj)/zImage-dtb: $(obj)/zImage $(DTB_OBJS) FORCE
+ @echo 1
+ $(call if_changed,cat)
+ @echo 2
+ @echo ' Kernel: $@ is ready'
+
endif
ifneq ($(LOADADDR),)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 68be9017593d..e9e0284fc8f2 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -639,7 +639,7 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size
mov r0, r3
mov r9, r0, lsr #18
mov r9, r9, lsl #18 @ start of RAM
- add r10, r9, #0x10000000 @ a reasonable RAM size
+ add r10, r9, #CONFIG_ARM_DECOMPRESSOR_LIMIT
mov r1, #0x12 @ XN|U + section mapping
orr r1, r1, #3 << 10 @ AP=11
add r2, r3, #16384
@@ -730,6 +730,8 @@ __armv7_mmu_cache_on:
bic r6, r6, #1 << 31 @ 32-bit translation system
bic r6, r6, #3 << 0 @ use only ttbr0
mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer
+ mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs
+ mcr p15, 0, r0, c7, c5, 4 @ ISB
mcrne p15, 0, r1, c3, c0, 0 @ load domain access control
mcrne p15, 0, r6, c2, c0, 2 @ load ttb control
#endif
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 38c89cafa1ab..c0ae2c8f1ab5 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -519,11 +519,23 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt6589-aquaris5.dtb
targets += dtbs dtbs_install
targets += $(dtb-y)
+DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES))
+ifneq ($(DTB_NAMES),)
+DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))
+else
+DTB_LIST := $(dtb-y)
+endif
+
+targets += dtbs
+targets += $(DTB_LIST)
+
+#used for cleaning - not building
+subdir- := qcom
endif
# *.dtb used to be generated in the directory above. Clean out the
# old build results so people don't accidentally use them.
-dtbs: $(addprefix $(obj)/, $(dtb-y))
+dtbs: $(addprefix $(obj)/, $(DTB_LIST))
$(Q)rm -f $(obj)/../*.dtb
clean-files := *.dtb
diff --git a/arch/arm/boot/dts/msm-gdsc-8916.dtsi b/arch/arm/boot/dts/msm-gdsc-8916.dtsi
new file mode 100644
index 000000000000..891e59867d8f
--- /dev/null
+++ b/arch/arm/boot/dts/msm-gdsc-8916.dtsi
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+&soc {
+ gdsc_venus: qcom,gdsc@184c018 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus";
+ reg = <0x184c018 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_mdss: qcom,gdsc@184d078 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_mdss";
+ reg = <0x184d078 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_jpeg: qcom,gdsc@185701c {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_jpeg";
+ reg = <0x185701c 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_vfe: qcom,gdsc@1858034 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_vfe";
+ reg = <0x1858034 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_oxili_gx: qcom,gdsc@185901c {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_oxili_gx";
+ reg = <0x185901c 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_venus_core0: qcom,gdsc@184c028 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus_core0";
+ reg = <0x184c028 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_venus_core1: qcom,gdsc@184c030 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus_core1";
+ reg = <0x184c030 0x4>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/msm-gdsc.dtsi b/arch/arm/boot/dts/msm-gdsc.dtsi
new file mode 100644
index 000000000000..9a1f32eb0c7a
--- /dev/null
+++ b/arch/arm/boot/dts/msm-gdsc.dtsi
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+&soc {
+ gdsc_venus: qcom,gdsc@fd8c1024 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus";
+ reg = <0xfd8c1024 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_venus_core0: qcom,gdsc@fd8c1040 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus_core0";
+ reg = <0xfd8c1040 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_venus_core1: qcom,gdsc@fd8c1044 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus_core1";
+ reg = <0xfd8c1044 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_venus_core2: qcom,gdsc@fd8c1050 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_venus_core2";
+ reg = <0xfd8c1050 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_vpu: qcom,gdsc@fd8c1404 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_vpu";
+ reg = <0xfd8c1404 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_camss_top: qcom,gdsc@fd8c34a0 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_camss_top";
+ reg = <0xfd8c34a0 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_mdss: qcom,gdsc@fd8c2304 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_mdss";
+ reg = <0xfd8c2304 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_jpeg: qcom,gdsc@fd8c35a4 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_jpeg";
+ reg = <0xfd8c35a4 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_vfe: qcom,gdsc@fd8c36a4 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_vfe";
+ reg = <0xfd8c36a4 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_cpp: qcom,gdsc@fd8c36d4 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_cpp";
+ reg = <0xfd8c36d4 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_oxili_gx";
+ reg = <0xfd8c4024 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_oxili_cx: qcom,gdsc@fd8c4034 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_oxili_cx";
+ reg = <0xfd8c4034 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_usb_hsic: qcom,gdsc@fc400404 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_usb_hsic";
+ reg = <0xfc400404 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_pcie: qcom,gdsc@0xfc401e18 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_pcie";
+ reg = <0xfc401e18 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_pcie_0: qcom,gdsc@fc401ac4 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_pcie_0";
+ reg = <0xfc401ac4 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_pcie_1: qcom,gdsc@fc401b44 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_pcie_1";
+ reg = <0xfc401b44 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_usb30: qcom,gdsc@fc401e84 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_usb30";
+ reg = <0xfc401e84 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_usb30_sec: qcom,gdsc@fc401ec0 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_usb30_sec";
+ reg = <0xfc401ec0 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_vcap: qcom,gdsc@fd8c1804 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_vcap";
+ reg = <0xfd8c1804 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_bcss: qcom,gdsc@fc744128 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_bcss";
+ reg = <0xfc744128 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_ufs: qcom,gdsc@fc401d44 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_ufs";
+ reg = <0xfc401d44 0x4>;
+ status = "disabled";
+ };
+
+ gdsc_fd: qcom,gdsc@fd8c3b64 {
+ compatible = "qcom,gdsc";
+ regulator-name = "gdsc_fd";
+ reg = <0xfd8c3b64 0x4>;
+ status = "disabled";
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pm8916-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8916-rpm-regulator.dtsi
new file mode 100644
index 000000000000..d5b7ea55c72b
--- /dev/null
+++ b/arch/arm/boot/dts/msm-pm8916-rpm-regulator.dtsi
@@ -0,0 +1,365 @@
+/* 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.
+ */
+
+&rpm_bus {
+ rpm-regulator-smpa1 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s1 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_s1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa2 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_s2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa3 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s3 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_s3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa4 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <1>;
+ qcom,hpm-min-load = <100000>;
+ status = "disabled";
+
+ regulator-s4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_s4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l1 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l3 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l5 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l6 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l6";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l7 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l7";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <8>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l8 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l8";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l9 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l9";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l10 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l10";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <11>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l11 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l11";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <12>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l12 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l12";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa13 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <13>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l13 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l13";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <14>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l14 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l14";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <15>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l15 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l15";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa16 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <16>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <5000>;
+ status = "disabled";
+
+ regulator-l16 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l16";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <17>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l17 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l17";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa18 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <18>;
+ qcom,regulator-type = <0>;
+ qcom,hpm-min-load = <10000>;
+ status = "disabled";
+
+ regulator-l18 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l18";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pm8916.dtsi b/arch/arm/boot/dts/msm-pm8916.dtsi
new file mode 100644
index 000000000000..1a738de55bb4
--- /dev/null
+++ b/arch/arm/boot/dts/msm-pm8916.dtsi
@@ -0,0 +1,632 @@
+/* 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.
+ */
+
+&spmi_bus {
+
+ qcom,pm8916@0 {
+ spmi-slave-container;
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm8916_revid: qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
+ pm8916_pon: qcom,power-on@800 {
+ compatible = "qcom,qpnp-power-on";
+ reg = <0x800 0x100>;
+ interrupts = <0x0 0x8 0x0>,
+ <0x0 0x8 0x1>;
+ interrupt-names = "kpdpwr", "resin";
+ qcom,pon-dbc-delay = <15625>;
+ qcom,system-reset;
+
+ qcom,pon_1 {
+ qcom,pon-type = <0>;
+ qcom,support-reset = <1>;
+ qcom,pull-up = <1>;
+ qcom,s1-timer = <10256>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <1>;
+ linux,code = <116>;
+ };
+
+ qcom,pon_2 {
+ qcom,pon-type = <1>;
+ qcom,pull-up = <1>;
+ linux,code = <114>;
+ };
+ };
+
+ pm8916_mpps: mpps {
+ compatible = "qcom,qpnp-pin";
+ spmi-dev-container;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "pm8916-mpp";
+
+ mpp@a000 {
+ reg = <0xa000 0x100>;
+ qcom,pin-num = <1>;
+ };
+
+ mpp@a100 {
+ reg = <0xa100 0x100>;
+ qcom,pin-num = <2>;
+ };
+
+ mpp@a200 {
+ reg = <0xa200 0x100>;
+ qcom,pin-num = <3>;
+ };
+
+ mpp@a300 {
+ reg = <0xa300 0x100>;
+ qcom,pin-num = <4>;
+ };
+ };
+
+ pm8916_gpios: gpios {
+ compatible = "qcom,qpnp-pin";
+ spmi-dev-container;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "pm8916-gpio";
+
+ gpio@c000 {
+ reg = <0xc000 0x100>;
+ qcom,pin-num = <1>;
+ };
+
+ gpio@c100 {
+ reg = <0xc100 0x100>;
+ qcom,pin-num = <2>;
+ };
+
+ gpio@c200 {
+ reg = <0xc200 0x100>;
+ qcom,pin-num = <3>;
+ };
+
+ gpio@c300 {
+ reg = <0xc300 0x100>;
+ qcom,pin-num = <4>;
+ };
+ };
+
+ pm8916_rtc: qcom,pm8916_rtc {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-rtc";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ qcom,qpnp-rtc-write = <0>;
+ qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+ qcom,pm8916_rtc_rw@6000 {
+ reg = <0x6000 0x100>;
+ };
+ qcom,pm8916_rtc_alarm@6100 {
+ reg = <0x6100 0x100>;
+ interrupts = <0x0 0x61 0x1>;
+ };
+ };
+
+ pm8916_vadc: vadc@3100 {
+ compatible = "qcom,qpnp-vadc";
+ reg = <0x3100 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x31 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1800>;
+ qcom,vadc-poll-eoc;
+ qcom,pmic-revid = <&pm8916_revid>;
+
+ chan@8 {
+ label = "die_temp";
+ reg = <8>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@9 {
+ label = "ref_625mv";
+ reg = <9>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@a {
+ label = "ref_1250v";
+ reg = <0xa>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+ };
+
+ pm8916_tz: qcom,temp-alarm@2400 {
+ compatible = "qcom,qpnp-temp-alarm";
+ reg = <0x2400 0x100>;
+ interrupts = <0x0 0x24 0x0>;
+ label = "pm8916_tz";
+ qcom,channel-num = <8>;
+ qcom,threshold-set = <0>;
+ qcom,temp_alarm-vadc = <&pm8916_vadc>;
+ };
+
+ pm8916_adc_tm: vadc@3400 {
+ compatible = "qcom,qpnp-adc-tm";
+ reg = <0x3400 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x34 0x0>,
+ <0x0 0x34 0x3>,
+ <0x0 0x34 0x4>;
+ interrupt-names = "eoc-int-en-set",
+ "high-thr-en-set",
+ "low-thr-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1800>;
+ qcom,adc_tm-vadc = <&pm8916_vadc>;
+ };
+
+ pm8916_chg: qcom,charger {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-linear-charger";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qcom,vddmax-mv = <4200>;
+ qcom,vddsafe-mv = <4200>;
+ qcom,vinmin-mv = <4308>;
+ qcom,ibatsafe-ma = <1440>;
+ qcom,thermal-mitigation = <1440 720 630 0>;
+ qcom,cool-bat-decidegc = <100>;
+ qcom,warm-bat-decidegc = <450>;
+ qcom,cool-bat-mv = <4100>;
+ qcom,warm-bat-mv = <4100>;
+ qcom,ibatmax-warm-ma = <360>;
+ qcom,ibatmax-cool-ma = <360>;
+ qcom,batt-hot-percentage = <25>;
+ qcom,batt-cold-percentage = <80>;
+ qcom,tchg-mins = <232>;
+ qcom,resume-soc = <99>;
+ qcom,chg-vadc = <&pm8916_vadc>;
+ qcom,chg-adc_tm = <&pm8916_adc_tm>;
+
+ status = "disabled";
+
+ qcom,chgr@1000 {
+ reg = <0x1000 0x100>;
+ interrupts = <0x0 0x10 0x7>,
+ <0x0 0x10 0x6>,
+ <0x0 0x10 0x5>,
+ <0x0 0x10 0x0>;
+ interrupt-names = "chg-done",
+ "chg-failed",
+ "fast-chg-on",
+ "vbat-det-lo";
+ };
+
+ qcom,bat-if@1200 {
+ reg = <0x1200 0x100>;
+ interrupts = <0x0 0x12 0x1>,
+ <0x0 0x12 0x0>;
+ interrupt-names = "bat-temp-ok",
+ "batt-pres";
+ };
+
+ qcom,usb-chgpth@1300 {
+ reg = <0x1300 0x100>;
+ interrupts = <0 0x13 0x4>,
+ <0 0x13 0x2>,
+ <0 0x13 0x1>;
+ interrupt-names = "usb-over-temp",
+ "chg-gone",
+ "usbin-valid";
+ };
+
+ qcom,chg-misc@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
+
+ pm8916_bms: qcom,vmbms {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-vm-bms";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ status = "disabled";
+
+ qcom,v-cutoff-uv = <3400000>;
+ qcom,max-voltage-uv = <4200000>;
+ qcom,r-conn-mohm = <0>;
+ qcom,shutdown-soc-valid-limit = <100>;
+ qcom,low-soc-calculate-soc-threshold = <15>;
+ qcom,low-voltage-calculate-soc-ms = <1000>;
+ qcom,low-soc-calculate-soc-ms = <5000>;
+ qcom,calculate-soc-ms = <20000>;
+ qcom,volatge-soc-timeout-ms = <60000>;
+ qcom,low-voltage-threshold = <3450000>;
+ qcom,s3-ocv-tolerence-uv = <1200>;
+ qcom,low-soc-fifo-length = <2>;
+ qcom,bms-vadc = <&pm8916_vadc>;
+ qcom,bms-adc_tm = <&pm8916_adc_tm>;
+ qcom,pmic-revid = <&pm8916_revid>;
+
+ qcom,force-s3-on-suspend;
+ qcom,force-s2-in-charging;
+ qcom,report-charger-eoc;
+
+ qcom,batt-pres-status@1208 {
+ reg = <0x1208 0x1>;
+ };
+
+ qcom,qpnp-chg-pres@1008 {
+ reg = <0x1008 0x1>;
+ };
+
+ qcom,vm-bms@4000 {
+ reg = <0x4000 0x100>;
+ interrupts = <0x0 0x40 0x0>,
+ <0x0 0x40 0x1>,
+ <0x0 0x40 0x2>,
+ <0x0 0x40 0x3>,
+ <0x0 0x40 0x4>,
+ <0x0 0x40 0x5>;
+
+ interrupt-names = "leave_cv",
+ "enter_cv",
+ "good_ocv",
+ "ocv_thr",
+ "fifo_update_done",
+ "fsm_state_change";
+ };
+ };
+
+ pm8916_leds: qcom,leds@a100 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xa100 0x100>;
+ label = "mpp";
+ };
+ };
+
+ qcom,pm8916@1 {
+ spmi-slave-container;
+ reg = <0x1>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ regulator@1400 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_s1";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1400 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1400 {
+ reg = <0x1400 0x100>;
+ };
+ qcom,ps@1500 {
+ reg = <0x1500 0x100>;
+ };
+ qcom,freq@1600 {
+ reg = <0x1600 0x100>;
+ };
+ };
+
+ regulator@1700 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_s2";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1700 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1700 {
+ reg = <0x1700 0x100>;
+ };
+ qcom,ps@1800 {
+ reg = <0x1800 0x100>;
+ };
+ qcom,freq@1900 {
+ reg = <0x1900 0x100>;
+ };
+ };
+
+ regulator@1a00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_s3";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1a00 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1a00 {
+ reg = <0x1a00 0x100>;
+ };
+ qcom,ps@1b00 {
+ reg = <0x1b00 0x100>;
+ };
+ qcom,freq@1c00 {
+ reg = <0x1c00 0x100>;
+ };
+ };
+
+ regulator@1d00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_s4";
+ spmi-dev-container;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x1d00 0x300>;
+ status = "disabled";
+
+ qcom,ctl@1d00 {
+ reg = <0x1d00 0x100>;
+ };
+ qcom,ps@1e00 {
+ reg = <0x1e00 0x100>;
+ };
+ qcom,freq@1f00 {
+ reg = <0x1f00 0x100>;
+ };
+ };
+
+ regulator@4000 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l1";
+ reg = <0x4000 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4100 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l2";
+ reg = <0x4100 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4200 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l3";
+ reg = <0x4200 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4300 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l4";
+ reg = <0x4300 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4400 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l5";
+ reg = <0x4400 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4500 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l6";
+ reg = <0x4500 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4600 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l7";
+ reg = <0x4600 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4700 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l8";
+ reg = <0x4700 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4800 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l9";
+ reg = <0x4800 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4900 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l10";
+ reg = <0x4900 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4a00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l11";
+ reg = <0x4a00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4b00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l12";
+ reg = <0x4b00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4c00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l13";
+ reg = <0x4c00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4d00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l14";
+ reg = <0x4d00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4e00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l15";
+ reg = <0x4e00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@4f00 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l16";
+ reg = <0x4f00 0x100>;
+ status = "disabled";
+ };
+
+ regulator@5000 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l17";
+ reg = <0x5000 0x100>;
+ status = "disabled";
+ };
+
+ regulator@5100 {
+ compatible = "qcom,qpnp-regulator";
+ regulator-name = "8916_l18";
+ reg = <0x5100 0x100>;
+ status = "disabled";
+ };
+
+ pm8916_pwm: pwm@bc00 {
+ compatible = "qcom,qpnp-pwm";
+ reg = <0xbc00 0x100>;
+ reg-names = "qpnp-lpg-channel-base";
+ qcom,channel-id = <0>;
+ qcom,supported-sizes = <6>, <9>;
+ };
+
+ pm8916_vib: qcom,vibrator@c000 {
+ compatible = "qcom,qpnp-vibrator";
+ reg = <0xc000 0x100>;
+ label = "vibrator";
+ status = "disabled";
+ };
+
+ pm8916_tombak_dig: msm8x16_wcd_codec@f000{
+ compatible = "qcom,wcd-spmi";
+ reg = <0xf000 0x100>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf0 0x0>,
+ <0x1 0xf0 0x1>,
+ <0x1 0xf0 0x2>,
+ <0x1 0xf0 0x3>,
+ <0x1 0xf0 0x4>,
+ <0x1 0xf0 0x5>,
+ <0x1 0xf0 0x6>,
+ <0x1 0xf0 0x7>;
+ interrupt-names = "spk_cnp_int",
+ "spk_clip_int",
+ "spk_ocp_int",
+ "ins_rem_det1",
+ "but_rel_det",
+ "but_press_det",
+ "ins_rem_det",
+ "mbhc_int";
+
+ cdc-vdda-cp-supply = <&pm8916_s4>;
+ qcom,cdc-vdda-cp-voltage = <1800000 2200000>;
+ qcom,cdc-vdda-cp-current = <770000>;
+
+ cdc-vdda-h-supply = <&pm8916_l5>;
+ qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+ qcom,cdc-vdda-h-current = <20000>;
+
+ cdc-vdd-px-supply = <&pm8916_s4>;
+ qcom,cdc-vdd-px-voltage = <1800000 2200000>;
+ qcom,cdc-vdd-px-current = <770000>;
+
+ cdc-vdd-pa-supply = <&pm8916_l5>;
+ qcom,cdc-vdd-pa-voltage = <1800000 1800000>;
+ qcom,cdc-vdd-pa-current = <5000>;
+
+ cdc-vdd-mic-bias-supply = <&pm8916_l13>;
+ qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+ qcom,cdc-vdd-mic-bias-current = <25000>;
+
+ qcom,cdc-mclk-clk-rate = <9600000>;
+
+ qcom,cdc-static-supplies = "cdc-vdda-h",
+ "cdc-vdd-px",
+ "cdc-vdd-pa",
+ "cdc-vdda-cp";
+
+ qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+ };
+
+ pm8916_tombak_analog: msm8x16_wcd_codec@f100{
+ compatible = "qcom,wcd-spmi";
+ reg = <0xf100 0x100>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x1 0xf1 0x0>,
+ <0x1 0xf1 0x1>,
+ <0x1 0xf1 0x2>,
+ <0x1 0xf1 0x3>,
+ <0x1 0xf1 0x4>,
+ <0x1 0xf1 0x5>;
+ interrupt-names = "ear_ocp_int",
+ "hphr_ocp_int",
+ "hphl_ocp_det",
+ "ear_cnp_int",
+ "hphr_cnp_int",
+ "hphl_cnp_int";
+ };
+
+ pm8916_bcm: qpnp-buck-current-monitor@1800 {
+ compatible = "qcom,qpnp-buck-current-monitor";
+ reg = <0x1800 0x100>;
+ interrupts = <1 0x18 0>, <1 0x18 1>;
+ interrupt-names = "iwarning", "icritical";
+ qcom,enable-current-monitor;
+ qcom,icrit-init-threshold-pc = <90>;
+ qcom,iwarn-init-threshold-pc = <70>;
+ qcom,icrit-polling-delay-msec = <1000>;
+ qcom,iwarn-polling-delay-msec = <2000>;
+
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm-rdbg.dtsi b/arch/arm/boot/dts/msm-rdbg.dtsi
new file mode 100644
index 000000000000..f7f52bed111c
--- /dev/null
+++ b/arch/arm/boot/dts/msm-rdbg.dtsi
@@ -0,0 +1,75 @@
+/* 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.
+ */
+
+&soc {
+ smp2pgpio_rdbg_2_in: qcom,smp2pgpio-rdbg-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "rdbg";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_client_rdbg_2_in {
+ compatible = "qcom,smp2pgpio_client_rdbg_2_in";
+ gpios = <&smp2pgpio_rdbg_2_in 0 0>;
+ };
+
+ smp2pgpio_rdbg_2_out: qcom,smp2pgpio-rdbg-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "rdbg";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_client_rdbg_2_out {
+ compatible = "qcom,smp2pgpio_client_rdbg_2_out";
+ gpios = <&smp2pgpio_rdbg_2_out 0 0>;
+ };
+
+ smp2pgpio_rdbg_1_in: qcom,smp2pgpio-rdbg-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "rdbg";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_client_rdbg_1_in {
+ compatible = "qcom,smp2pgpio_client_rdbg_1_in";
+ gpios = <&smp2pgpio_rdbg_1_in 0 0>;
+ };
+
+ smp2pgpio_rdbg_1_out: qcom,smp2pgpio-rdbg-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "rdbg";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_client_rdbg_1_out {
+ compatible = "qcom,smp2pgpio_client_rdbg_1_out";
+ gpios = <&smp2pgpio_rdbg_1_out 0 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8916-bus.dtsi b/arch/arm/boot/dts/msm8916-bus.dtsi
new file mode 100644
index 000000000000..21ae7a929d1d
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-bus.dtsi
@@ -0,0 +1,877 @@
+/* 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 <dt-bindings/msm/msm-bus-rule-ops.h>
+
+&soc {
+ ad_hoc_bus: ad-hoc-bus { };
+
+ static-rules {
+ compatible = "qcom,msm-bus-static-bw-rules";
+
+ rule0 {
+ qcom,src-nodes = <&mas_apss>;
+ qcom,src-field = <FLD_IB>;
+ qcom,src-op = <OP_LE>;
+ qcom,thresh = <1600000>;
+ qcom,mode = <THROTTLE_ON>;
+ qcom,dest-node = <&mas_apss>;
+ qcom,dest-bw = <600000>;
+ };
+
+
+ rule1 {
+ qcom,src-nodes = <&mas_apss>;
+ qcom,src-field = <FLD_IB>;
+ qcom,src-op = <OP_LE>;
+ qcom,thresh = <3200000>;
+ qcom,mode = <THROTTLE_ON>;
+ qcom,dest-node = <&mas_apss>;
+ qcom,dest-bw = <1200000>;
+ };
+
+ rule2 {
+ qcom,src-nodes = <&mas_apss>;
+ qcom,src-field = <FLD_IB>;
+ qcom,src-op = <OP_GT>;
+ qcom,thresh = <3200000>;
+ qcom,mode = <THROTTLE_OFF>;
+ qcom,dest-node = <&mas_apss>;
+ };
+
+ rule3 {
+ qcom,src-nodes = <&mas_gfx>;
+ qcom,src-field = <FLD_IB>;
+ qcom,src-op = <OP_LE>;
+ qcom,thresh = <1600000>;
+ qcom,mode = <THROTTLE_ON>;
+ qcom,dest-node = <&mas_gfx>;
+ qcom,dest-bw = <600000>;
+ };
+
+ rule4 {
+ qcom,src-nodes = <&mas_gfx>;
+ qcom,src-field = <FLD_IB>;
+ qcom,src-op = <OP_LE>;
+ qcom,thresh = <3200000>;
+ qcom,mode = <THROTTLE_ON>;
+ qcom,dest-node = <&mas_gfx>;
+ qcom,dest-bw = <1200000>;
+ };
+
+ rule5 {
+ qcom,src-nodes = <&mas_gfx>;
+ qcom,src-field = <FLD_IB>;
+ qcom,src-op = <OP_GT>;
+ qcom,thresh = <3200000>;
+ qcom,mode = <THROTTLE_OFF>;
+ qcom,dest-node = <&mas_gfx>;
+ };
+ };
+};
+
+&ad_hoc_bus {
+ compatible = "qcom,msm-bus-device";
+ reg = <0x580000 0x14000>,
+ <0x400000 0x62000>,
+ <0x500000 0x11000>;
+ reg-names = "snoc-base", "bimc-base", "pnoc-base";
+
+ fab_snoc: fab-snoc {
+ cell-id = <1024>;
+ label = "fab-snoc";
+ qcom,fab-dev;
+ qcom,base-name = "snoc-base";
+ qcom,base-offset = <0x7000>;
+ qcom,qos-off = <0x1000>;
+ qcom,bus-type = <1>;
+ clock-names = "bus_clk", "bus_a_clk";
+ clocks = <&clock_rpm clk_snoc_msmbus_clk>,
+ <&clock_rpm clk_snoc_msmbus_a_clk>;
+
+ coresight-id = <50>;
+ coresight-name = "coresight-snoc";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in2>;
+ coresight-child-ports = <5>;
+ };
+
+ fab_bimc: fab-bimc {
+ cell-id = <0>;
+ label = "fab-bimc";
+ qcom,fab-dev;
+ qcom,base-name = "bimc-base";
+ qcom,bus-type = <2>;
+ clock-names = "bus_clk", "bus_a_clk";
+ clocks = <&clock_rpm clk_bimc_msmbus_clk>,
+ <&clock_rpm clk_bimc_msmbus_a_clk>;
+
+ coresight-id = <55>;
+ coresight-name = "coresight-bimc";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in2>;
+ coresight-child-ports = <3>;
+ };
+
+ fab_pnoc: fab-pnoc {
+ cell-id = <4096>;
+ label = "fab-pnoc";
+ qcom,fab-dev;
+ qcom,base-name = "pnoc-base";
+ qcom,base-offset = <0x7000>;
+ qcom,qos-delta = <0x1000>;
+ qcom,bus-type = <1>;
+ clock-names = "bus_clk", "bus_a_clk";
+ clocks = <&clock_rpm clk_pcnoc_msmbus_clk>,
+ <&clock_rpm clk_pcnoc_msmbus_a_clk>;
+
+ coresight-id = <54>;
+ coresight-name = "coresight-pnoc";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in2>;
+ coresight-child-ports = <6>;
+ };
+
+ /* SNOC Devices */
+ mas_video: mas-video {
+ cell-id = <63>;
+ label = "mas-video";
+ qcom,qport = <8>;
+ qcom,ap-owned;
+ qcom,connections = <&mm_int_0 &mm_int_2>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,qos-mode = "bypass";
+ qcom,buswidth = <16>;
+ };
+
+ mas_jpeg: mas-jpeg {
+ cell-id = <62>;
+ label = "mas-jpeg";
+ qcom,ap-owned;
+ qcom,qport = <6>;
+ qcom,connections = <&mm_int_0 &mm_int_2>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,qos-mode = "bypass";
+ qcom,buswidth = <16>;
+ };
+
+ mas_vfe: mas-vfe {
+ cell-id = <29>;
+ label = "mas-vfe";
+ qcom,ap-owned;
+ qcom,qport = <9>;
+ qcom,connections = <&mm_int_1 &mm_int_2>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,qos-mode = "bypass";
+ qcom,buswidth = <16>;
+ };
+
+ mas_mdp: mas-mdp {
+ cell-id = <22>;
+ label = "mas-mdp";
+ qcom,ap-owned;
+ qcom,connections = <&mm_int_0 &mm_int_2>;
+ qcom,qport = <7>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,qos-mode = "bypass";
+ qcom,buswidth = <16>;
+ };
+
+ mas_qdss_bam: mas-qdss-bam {
+ cell-id = <53>;
+ label = "mas-qdss-bam";
+ qcom,connections = <&qdss_int>;
+ qcom,qport = <11>;
+ qcom,bus-dev = <&fab_snoc>;
+ qom,buswidth = <4>;
+ qcom,ap-owned;
+ qcom,qos-mode = "fixed";
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
+ };
+
+ mas_snoc_cfg: mas-snoc-cfg {
+ cell-id = <54>;
+ label = "mas-snoc-cfg";
+ qcom,connections = <&qdss_int>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,qos-mode = "bypass";
+ qom,buswidth = <4>;
+ qcom,mas-rpm-id = <20>;
+ };
+
+ mas_qdss_etr: mas-qdss-etr {
+ cell-id = <60>;
+ label = "mas-qdss-etr";
+ qcom,connections = <&qdss_int>;
+ qcom,qport = <10>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,qos-mode = "fixed";
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
+ qom,buswidth = <8>;
+ qcom,ap-owned;
+ };
+
+ mm_int_0: mm-int-0 {
+ cell-id = <10000>;
+ label = "mm-int-0";
+ qcom,ap-owned;
+ qcom,connections = <&mm_int_bimc>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <16>;
+ };
+
+ mm_int_1: mm-int-1 {
+ cell-id = <10001>;
+ label = "mm-int1";
+ qcom,ap-owned;
+ qcom,connections = <&mm_int_bimc>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <16>;
+ };
+
+ mm_int_2: mm-int-2 {
+ cell-id = <10002>;
+ label = "mm-int2";
+ qcom,ap-owned;
+ qcom,connections = <&snoc_int_0>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <16>;
+ };
+
+ mm_int_bimc: mm-int-bimc {
+ cell-id = <10003>;
+ label = "mm-int-bimc";
+ qcom,ap-owned;
+ qcom,connections = <&snoc_bimc_1_mas>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <16>;
+ };
+
+ snoc_int_0: snoc-int-0 {
+ cell-id = <10004>;
+ label = "snoc-int-0";
+ qcom,connections = <&slv_qdss_stm &slv_imem &snoc_pnoc_mas>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,mas-rpm-id = <99>;
+ qcom,slv-rpm-id = <130>;
+ qcom,buswidth = <8>;
+ };
+
+ snoc_int_1: snoc-int-1 {
+ cell-id = <10005>;
+ label = "snoc-int-1";
+ qcom,connections = <&slv_apss &slv_cats_0 &slv_cats_1>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,mas-rpm-id = <100>;
+ qcom,slv-rpm-id = <131>;
+ qcom,buswidth = <8>;
+ };
+
+ snoc_int_bimc: snoc-int-bmc {
+ cell-id = <10006>;
+ label = "snoc-bimc";
+ qcom,connections = <&snoc_bimc_0_mas>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,mas-rpm-id = <101>;
+ qcom,slv-rpm-id = <132>;
+ qcom,buswidth = <8>;
+ };
+
+ snoc_bimc_0_mas: snoc-bimc-0-mas {
+ cell-id = <10007>;
+ label = "snoc-bimc-0-mas";
+ qcom,connections = <&snoc_bimc_0_slv>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,mas-rpm-id = <3>;
+ qcom,buswidth = <8>;
+ };
+
+ snoc_bimc_1_mas: snoc-bimc-1-mas {
+ cell-id = <10008>;
+ label = "snoc-bimc-1-mas";
+ qcom,connections = <&snoc_bimc_1_slv>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,ap-owned;
+ qcom,buswidth = <16>;
+ };
+
+ qdss_int: qdss-int {
+ cell-id = <10009>;
+ label = "qdss-int";
+ qcom,ap-owned;
+ qcom,connections = <&snoc_int_0 &snoc_int_bimc>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <8>;
+ };
+
+ bimc_snoc_slv: bimc-snoc-slv {
+ cell-id = <10017>;
+ label = "bimc_snoc_slv";
+ qcom,ap-owned;
+ qcom,connections = <&snoc_int_0 &snoc_int_1>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <8>;
+ };
+
+ snoc_pnoc_mas: snoc-pnoc-mas {
+ cell-id = <10027>;
+ label = "snoc-pnoc-mas";
+ qcom,connections = <&snoc_pnoc_slv>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <8>;
+ };
+
+ pnoc_snoc_slv: pnoc-snoc-slv {
+ cell-id = <10011>;
+ label = "snoc-pnoc";
+ qcom,connections = <&snoc_int_0 &snoc_int_bimc &snoc_int_1>;
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,slv-rpm-id = <45>;
+ qcom,buswidth = <8>;
+ };
+
+ slv_srvc_snoc: slv-srvc-snoc {
+ cell-id = <587>;
+ label = "snoc-srvc-snoc";
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,slv-rpm-id = <29>;
+ qcom,buswidth = <8>;
+ };
+
+ slv_qdss_stm: slv-qdss-stm {
+ cell-id = <588>;
+ label = "snoc-qdss-stm";
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <4>;
+ qcom,slv-rpm-id = <30>;
+ };
+
+ slv_imem: slv-imem {
+ cell-id = <519>;
+ label = "slv_imem";
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,buswidth = <8>;
+ qcom,slv-rpm-id = <26>;
+ };
+
+ slv_apss: slv-apss {
+ cell-id = <517>;
+ label = "slv_apss";
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,slv-rpm-id = <20>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_cats_0: slv-cats-0 {
+ cell-id = <663>;
+ label = "slv-cats-0";
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,slv-rpm-id = <106>;
+ qcom,buswidth = <16>;
+ };
+
+ slv_cats_1: slv-cats-1 {
+ cell-id = <664>;
+ label = "slv-cats-1";
+ qcom,bus-dev = <&fab_snoc>;
+ qcom,slv-rpm-id = <107>;
+ qcom,buswidth = <8>;
+ };
+
+ /* BIMC nodes */
+ mas_apss: mas-apss {
+ cell-id = <1>;
+ label = "mas-apss";
+ qcom,ap-owned;
+ qcom,connections = <&slv_ebi_ch0 &bimc_snoc_mas &slv_apps_l2>;
+ qcom,qport = <0>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,qos-mode = "fixed";
+ qcom,prio-lvl = <0>;
+ qcom,prio-rd = <0>;
+ qcom,prio-wr = <0>;
+ qcom,ws = <10000>;
+ qcom,gp = <5000>;
+ qcom,thmp = <50>;
+ qom,buswidth = <8>;
+ };
+
+ mas_tcu0: mas-tcu0 {
+ cell-id = <104>;
+ label = "mas-tcu0";
+ qcom,ap-owned;
+ qcom,connections = <&slv_ebi_ch0 &bimc_snoc_mas &slv_apps_l2>;
+ qcom,qport = <5>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,qos-mode = "fixed";
+ qcom,prio-lvl = <2>;
+ qcom,prio-rd = <2>;
+ qcom,prio-wr = <2>;
+ qom,buswidth = <8>;
+ };
+
+ mas_tcu1: mas-tcu1 {
+ cell-id = <105>;
+ label = "mas-tcu1";
+ qcom,ap-owned;
+ qcom,connections = <&slv_ebi_ch0 &bimc_snoc_mas &slv_apps_l2>;
+ qcom,qport = <6>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,qos-mode = "fixed";
+ qcom,prio-lvl = <2>;
+ qcom,prio-rd = <2>;
+ qcom,prio-wr = <2>;
+ qom,buswidth = <8>;
+ };
+
+ mas_gfx: mas-gfx {
+ cell-id = <26>;
+ label = "mas-gfx";
+ qcom,ap-owned;
+ qcom,connections = <&slv_ebi_ch0 &bimc_snoc_mas &slv_apps_l2>;
+ qcom,qport = <2>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,qos-mode = "fixed";
+ qcom,prio-lvl = <0>;
+ qcom,prio-rd = <0>;
+ qcom,prio-wr = <0>;
+ qom,buswidth = <8>;
+ qcom,ws = <10000>;
+ qcom,gp = <5000>;
+ qcom,thmp = <50>;
+ };
+
+ bimc_snoc_mas: bimc-snoc-mas {
+ cell-id = <10016>;
+ label = "bimc_snoc_mas";
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,connections = <&bimc_snoc_slv>;
+ qom,buswidth = <8>;
+ };
+
+ snoc_bimc_0_slv: snoc-bimc-0-slv {
+ cell-id = <10025>;
+ label = "snoc_bimc_0_slv";
+ qcom,connections = <&slv_ebi_ch0>;
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,slv-rpm-id = <24>;
+ qom,buswidth = <8>;
+ };
+
+ snoc_bimc_1_slv: snoc_bimc_1_slv {
+ cell-id = <10026>;
+ label = "snoc_bimc_1_slv";
+ qcom,connections = <&slv_ebi_ch0>;
+ qcom,ap-owned;
+ qcom,bus-dev = <&fab_bimc>;
+ qom,buswidth = <8>;
+ };
+
+ slv_ebi_ch0: slv-ebi-ch0 {
+ cell-id = <512>;
+ label = "slv-ebi-ch0";
+ qcom,bus-dev = <&fab_bimc>;
+ qcom,slv-rpm-id = <0>;
+ qom,buswidth = <8>;
+ };
+
+ slv_apps_l2: slv-apps-l2 {
+ cell-id = <514>;
+ label = "slv-apps-l2";
+ qcom,bus-dev = <&fab_bimc>;
+ qom,buswidth = <8>;
+ };
+
+ /* PNOC nodes */
+ snoc_pnoc_slv: snoc-pnoc-slv {
+ cell-id = <10028>;
+ label = "snoc-pnoc-slv";
+ qcom,connections = <&pnoc_int_0>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <8>;
+ };
+
+ pnoc_int_0: pnoc-int-0 {
+ cell-id = <10012>;
+ label = "pnoc-int-0";
+ qcom,connections = <&pnoc_snoc_mas &pnoc_s_0 &pnoc_s_1 &pnoc_s_2
+ &pnoc_s_3 &pnoc_s_4 &pnoc_s_8 &pnoc_s_9>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <8>;
+ };
+
+ pnoc_int_1: pnoc-int-1 {
+ cell-id = <10013>;
+ label = "pnoc-int-1";
+ qcom,connections = <&pnoc_snoc_mas>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <8>;
+ };
+
+ pnoc_m_0: pnoc-m-0 {
+ cell-id = <10014>;
+ label = "pnoc-m-0";
+ qcom,connections = <&pnoc_int_0>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <8>;
+ };
+
+ pnoc_m_1: pnoc-m-1 {
+ cell-id = <10015>;
+ label = "pnoc-m-1";
+ qcom,connections = <&pnoc_snoc_mas>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <8>;
+ };
+
+ pnoc_s_0: pnoc-s-0 {
+ cell-id = <10018>;
+ label = "pnoc-s-0";
+ qcom,connections = <&slv_clk_ctl &slv_tlmm &slv_tcsr
+ &slv_security &slv_mss>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <4>;
+ };
+
+ pnoc_s_1: pnoc-s-1 {
+ cell-id = <10019>;
+ label = "pnoc-s-1";
+ qcom,connections = <&slv_imem_cfg &slv_crypto_0_cfg
+ &slv_msg_ram &slv_pdm &slv_prng>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <4>;
+ };
+
+ pnoc_s_2: pnoc-s-2 {
+ cell-id = <10020>;
+ label = "pnoc-s-2";
+ qcom,connections = <&slv_spdm &slv_boot_rom &slv_bimc_cfg
+ &slv_pnoc_cfg &slv_pmic_arb>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <4>;
+ };
+
+ pnoc_s_3: pnoc-s-3 {
+ cell-id = <10021>;
+ label = "pnoc-s-3";
+ qcom,connections = <&slv_mpm &slv_snoc_cfg &slv_rbcpr_cfg
+ &slv_qdss_cfg &slv_dehr_cfg>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <4>;
+ };
+
+ pnoc_s_4: pnoc-s-4 {
+ cell-id = <10022>;
+ label = "pnoc-s-4";
+ qcom,connections = <&slv_venus_cfg &slv_camera_cfg
+ &slv_display_cfg>;
+ qcom,bus-dev = <&fab_pnoc>;
+ };
+
+ pnoc_s_8: pnoc-s-8 {
+ cell-id = <10023>;
+ label = "pnoc-s-8";
+ qcom,connections = <&slv_usb_hs &slv_sdcc_1 &slv_blsp_1>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <4>;
+ };
+
+ pnoc_s_9: pnoc-s-9 {
+ cell-id = <10024>;
+ label = "pnoc-s-9";
+ qcom,connections = <&slv_sdcc_2 &slv_audio &slv_gfx_cfg>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qom,buswidth = <4>;
+ };
+
+ slv_imem_cfg: slv-imem-cfg {
+ cell-id = <627>;
+ label = "slv-imem-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_crypto_0_cfg: slv-crypto-0-cfg {
+ cell-id = <625>;
+ label = "slv-crypto-0-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_msg_ram: slv-msg-ram {
+ cell-id = <535>;
+ label = "slv-msg-ram";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_pdm: slv-pdm {
+ cell-id = <577>;
+ label = "slv-pdm";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_prng: slv-prng {
+ cell-id = <618>;
+ label = "slv-prng";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_clk_ctl: slv-clk-ctl {
+ cell-id = <620>;
+ label = "slv-clk-ctl";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_mss: slv-mss {
+ cell-id = <521>;
+ label = "slv-mss";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_tlmm: slv-tlmm {
+ cell-id = <624>;
+ label = "slv-tlmm";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_tcsr: slv-tcsr {
+ cell-id = <579>;
+ label = "slv-tcsr";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_security: slv-security {
+ cell-id = <622>;
+ label = "slv-security";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_spdm: slv-spdm {
+ cell-id = <533>;
+ label = "slv-spdm";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_pnoc_cfg: slv-pnoc-cfg {
+ cell-id = <641>;
+ label = "slv-pnoc-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_pmic_arb: slv-pmic-arb {
+ cell-id = <632>;
+ label = "slv-pmic-arb";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_bimc_cfg: slv-bimc-cfg {
+ cell-id = <629>;
+ label = "slv-bimc-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_boot_rom: slv-boot-rom {
+ cell-id = <630>;
+ label = "slv-boot-rom";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_mpm: slv-mpm {
+ cell-id = <536>;
+ label = "slv-mpm";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_qdss_cfg: slv-qdss-cfg {
+ cell-id = <635>;
+ label = "slv-qdss-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_rbcpr_cfg: slv-rbcpr-cfg {
+ cell-id = <636>;
+ label = "slv-rbcpr-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_snoc_cfg: slv-snoc-cfg {
+ cell-id = <647>;
+ label = "slv-snoc-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_dehr_cfg: slv-dehr-cfg {
+ cell-id = <634>;
+ label = "slv-dehr-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_venus_cfg: slv-venus-cfg {
+ cell-id = <596>;
+ label = "slv-venus-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_display_cfg: slv-display-cfg {
+ cell-id = <590>;
+ label = "slv-display-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_camera_cfg: slv-camera-cfg {
+ cell-id = <589>;
+ label = "slv-camer-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_usb_hs: slv-usb-hs {
+ cell-id = <614>;
+ label = "slv-usb-hs";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_sdcc_1: slv-sdcc-1 {
+ cell-id = <606>;
+ label = "slv-sdcc-1";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_blsp_1: slv-blsp-1 {
+ cell-id = <613>;
+ label = "slv-blsp-1";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_sdcc_2: slv-sdcc-2 {
+ cell-id = <609>;
+ label = "slv-sdcc-2";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_gfx_cfg: slv-gfx-cfg {
+ cell-id = <598>;
+ label = "slv-gfx-cfg";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ slv_audio: slv-audio {
+ cell-id = <522>;
+ label = "slv-audio";
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ mas_blsp_1: mas-blsp_1 {
+ cell-id = <86>;
+ label = "mas-blsp-1";
+ qcom,connections = <&pnoc_m_1>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ mas_spdm: mas-spdm {
+ cell-id = <36>;
+ label = "mas-spdm";
+ qcom,connections = <&pnoc_m_0>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ mas_dehr: mas-dehr {
+ cell-id = <75>;
+ label = "mas-dehr";
+ qcom,connections = <&pnoc_m_0>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ mas_audio: mas-audio {
+ cell-id = <15>;
+ label = "mas-audio";
+ qcom,connections = <&pnoc_m_0>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ mas_usb_hs: mas-usb-hs {
+ cell-id = <87>;
+ label = "mas-usb-hs";
+ qcom,connections = <&pnoc_m_1>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <4>;
+ };
+
+ mas_pnoc_crypto_0: mas-pnoc-crypto-0 {
+ cell-id = <55>;
+ label = "mas-pnoc-crypto-0";
+ qcom,connections = <&pnoc_int_1>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <8>;
+ };
+
+ mas_pnoc_sdcc_1: mas-pnoc-sdcc-1 {
+ cell-id = <78>;
+ label = "mas-pnoc-sdcc-1";
+ qcom,connections = <&pnoc_int_1>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <8>;
+ };
+
+ mas_pnoc_sdcc_2: mas-pnoc-sdcc-2 {
+ cell-id = <81>;
+ label = "mas-pnoc-sdcc-2";
+ qcom,connections = <&pnoc_int_1>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,buswidth = <8>;
+ };
+
+ pnoc_snoc_mas: pnoc-snoc-mas {
+ cell-id = <10010>;
+ label = "pnoc-snoc-mas";
+ qcom,connections = <&pnoc_snoc_slv>;
+ qcom,bus-dev = <&fab_pnoc>;
+ qcom,mas-rpm-id = <29>;
+ qcom,buswidth = <8>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8916-ipcrouter.dtsi b/arch/arm/boot/dts/msm8916-ipcrouter.dtsi
new file mode 100644
index 000000000000..3b59d159ea8d
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-ipcrouter.dtsi
@@ -0,0 +1,37 @@
+/* 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.
+ */
+
+&soc {
+ qcom,ipc_router {
+ compatible = "qcom,ipc_router";
+ qcom,node-id = <1>;
+ };
+
+ qcom,ipc_router_modem_xprt {
+ compatible = "qcom,ipc_router_smd_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "modem";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ };
+
+ qcom,ipc_router_wcnss_xprt {
+ compatible = "qcom,ipc_router_smd_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "wcnss";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ };
+
+};
diff --git a/arch/arm/boot/dts/msm8916-memory.dtsi b/arch/arm/boot/dts/msm8916-memory.dtsi
new file mode 100644
index 000000000000..5f8302741f66
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-memory.dtsi
@@ -0,0 +1,45 @@
+/* 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 "msm8916-ion.dtsi"
+
+/ {
+ memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ external_image_mem: external_image__region@0 {
+ linux,reserve-contiguous-region;
+ linux,reserve-region;
+ linux,remove-completely;
+ reg = <0x0 0x86000000 0x0 0x0800000>;
+ label = "external_image_mem";
+ };
+
+ modem_adsp_mem: modem_adsp_region@0 {
+ linux,reserve-contiguous-region;
+ linux,reserve-region;
+ linux,remove-completely;
+ reg = <0x0 0x86800000 0x0 0x04e00000>;
+ label = "modem_adsp_mem";
+ };
+
+ peripheral_mem: pheripheral_region@0 {
+ linux,reserve-contiguous-region;
+ linux,reserve-region;
+ linux,remove-completely;
+ reg = <0x0 0x8b600000 0x0 0x0600000>;
+ label = "peripheral_mem";
+ };
+
+ };
+};
diff --git a/arch/arm/boot/dts/msm8916-pinctrl.dtsi b/arch/arm/boot/dts/msm8916-pinctrl.dtsi
new file mode 100644
index 000000000000..dbcaa9824e4f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-pinctrl.dtsi
@@ -0,0 +1,1374 @@
+/* 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.
+ */
+
+&soc {
+ tlmm_pinmux: pinctrl@1000000 {
+ compatible = "qcom,msm-tlmm-v4";
+ reg = <0x1000000 0x300000>;
+ interrupts = <0 208 0>;
+
+ /*General purpose pins*/
+ gp: gp {
+ qcom,pin-type-gp;
+ qcom,num-pins = <122>;
+ #qcom,pin-cells = <1>;
+ msm_gpio: msm_gpio {
+ compatible = "qcom,msm-tlmmv4-gp-intc";
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ num_irqs = <122>;
+ };
+ };
+
+ ext-cdc-tlmm-lines {
+ qcom,pins = <&gp 116>, <&gp 112>, <&gp 117>,
+ <&gp 118>, <&gp 119>;
+ qcom,num-grp-pins = <5>;
+ qcom,pin-func = <1>;
+ label = "ext-cdc-tlmm-lines";
+ ext_cdc_tlmm_lines_act: tlmm_lines_on {
+ drive-strength = <8>;
+ bias-pull-none;
+ };
+ ext_cdc_tlmm_lines_sus: tlmm_lines_off {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ ext-codec-lines {
+ qcom,pins = <&gp 67>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "ext-codec-lines";
+ ext_codec_lines_act: lines_on {
+ drive-strength = <8>;
+ bias-disable;
+ output-high;
+ };
+ ext_codec_lines_sus: lines_off {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ cdc-pdm-lines {
+ qcom,pins = <&gp 63>, <&gp 64>, <&gp 65>,
+ <&gp 66>, <&gp 67>, <&gp 68>;
+ qcom,num-grp-pins = <6>;
+ qcom,pin-func = <1>;
+ label = "cdc-pdm-lines";
+ cdc_pdm_lines_act: pdm_lines_on {
+ drive-strength = <8>;
+ bias-pull-none;
+ };
+ cdc_pdm_lines_sus: pdm_lines_off {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ cdc-ext-pa-lines {
+ qcom,pins = <&gp 113>, <&gp 114>,
+ <&gp 115>, <&gp 116>;
+ qcom,num-grp-pins = <4>;
+ qcom,pin-func = <1>;
+ label = "cdc-ext-pa-lines";
+ cdc_ext_pa_act: ext_pa_on {
+ drive-strength = <8>;
+ bias-pull-none;
+ };
+ cdc_ext_pa_sus: ext_pa_off {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ cdc-ext-pa-ws-line {
+ qcom,pins = <&gp 110>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "cdc-ext-pa-ws-line";
+ cdc_ext_pa_ws_act: ext_pa_on {
+ drive-strength = <8>;
+ bias-pull-none;
+ };
+ cdc_ext_pa_ws_sus: ext_pa_off {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ cross-conn-det {
+ qcom,pins = <&gp 120>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "cross-conn-det-sw";
+ cross_conn_det_act: lines_on {
+ drive-strength = <8>;
+ bias-pull-none;
+ };
+ cross_conn_det_sus: lines_off {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ pmx-uartconsole {
+ qcom,pins = <&gp 4>, <&gp 5>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <2>;
+ label = "uart-console";
+
+ uart_console_sleep: uart-console {
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ blsp1_uart1_active {
+ qcom,pins = <&gp 0>, <&gp 1>, <&gp 2>, <&gp 3>;
+ qcom,num-grp-pins = <4>;
+ qcom,pin-func = <2>;
+ label = "blsp1_uart1_active";
+
+ hsuart_active: default {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ blsp1_uart1_sleep {
+ qcom,pins = <&gp 0>, <&gp 1>, <&gp 2>, <&gp 3>;
+ qcom,num-grp-pins = <4>;
+ qcom,pin-func = <0>;
+ label = "blsp1_uart1_sleep";
+
+ hsuart_sleep: sleep {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ sdhc2_cd_pin {
+ qcom,pins = <&gp 38>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "cd-gpio";
+ sdc2_cd_on: cd_on {
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ sdc2_cd_off: cd_off {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ /* SDC pin type */
+ sdc: sdc {
+ qcom,pin-type-sdc;
+ /* 0-2 for sdc1 4-6 for sdc2 */
+ qcom,num-pins = <7>;
+ /* Order of pins */
+ /* SDC1: CLK -> 0, CMD -> 1, DATA -> 2 */
+ /* SDC2: CLK -> 4, CMD -> 5, DATA -> 6 */
+ #qcom,pin-cells = <1>;
+ };
+
+ pmx_sdc1_clk {
+ qcom,pins = <&sdc 0>;
+ qcom,num-grp-pins = <1>;
+ label = "sdc1-clk";
+ sdc1_clk_on: clk_on {
+ bias-disable; /* NO pull */
+ drive-strength = <16>; /* 16 MA */
+ };
+ sdc1_clk_off: clk_off {
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ pmx_sdc1_cmd {
+ qcom,pins = <&sdc 1>;
+ qcom,num-grp-pins = <1>;
+ label = "sdc1-cmd";
+ sdc1_cmd_on: cmd_on {
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ sdc1_cmd_off: cmd_off {
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ pmx_sdc1_data {
+ qcom,pins = <&sdc 2>;
+ qcom,num-grp-pins = <1>;
+ label = "sdc1-data";
+ sdc1_data_on: data_on {
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ sdc1_data_off: data_off {
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ pmx_sdc2_clk {
+ qcom,pins = <&sdc 4>;
+ qcom,num-grp-pins = <1>;
+ label = "sdc2-clk";
+ sdc2_clk_on: clk_on {
+ bias-disable; /* NO pull */
+ drive-strength = <16>; /* 16 MA */
+ };
+ sdc2_clk_off: clk_off {
+ bias-disable; /* NO pull */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ pmx_sdc2_cmd {
+ qcom,pins = <&sdc 5>;
+ qcom,num-grp-pins = <1>;
+ label = "sdc2-cmd";
+ sdc2_cmd_on: cmd_on {
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ sdc2_cmd_off: cmd_off {
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ pmx_sdc2_data {
+ qcom,pins = <&sdc 6>;
+ qcom,num-grp-pins = <1>;
+ label = "sdc2-data";
+ sdc2_data_on: data_on {
+ bias-pull-up; /* pull up */
+ drive-strength = <10>; /* 10 MA */
+ };
+ sdc2_data_off: data_off {
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ usb-id-pin {
+ qcom,pins = <&gp 110>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "usb-id-pin";
+ usbid_default: default {
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
+
+ spi0_active {
+ /* MOSI, MISO, CLK */
+ qcom,pins = <&gp 8>, <&gp 9>, <&gp 11>;
+ qcom,num-grp-pins = <3>;
+ qcom,pin-func = <1>;
+ label = "spi0-active";
+ /* active state */
+ spi0_default: default {
+ drive-strength = <12>; /* 12 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ spi0_suspend {
+ /* MOSI, MISO, CLK */
+ qcom,pins = <&gp 8>, <&gp 9>, <&gp 11>;
+ qcom,num-grp-pins = <3>;
+ qcom,pin-func = <0>;
+ label = "spi0-suspend";
+ /* suspended state */
+ spi0_sleep: sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* pull down */
+ };
+ };
+ spi0_cs0_active {
+ /* CS */
+ qcom,pins = <&gp 10>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <1>;
+ label = "spi0-cs0-active";
+ spi0_cs0_active: cs0_active {
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+
+
+ spi0_cs0_suspend {
+ /* CS */
+ qcom,pins = <&gp 10>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "spi0-cs0-suspend";
+ spi0_cs0_sleep: cs0_sleep {
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+
+ ice40-spi-usb-pins {
+ qcom,pins = <&gp 0>, <&gp 1>, <&gp 3>, <&gp 114>;
+ qcom,num-grp-pins = <4>;
+ qcom,pin-func = <0>;
+ label = "ice40-spi-usb-pins";
+
+ /* active state */
+ ice40_default: default {
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ /* sleep state */
+ ice40_sleep: sleep {
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+
+ pmx_i2c_0 {
+ /* CLK, DATA */
+ qcom,pins = <&gp 7>, <&gp 6>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <3>;
+ label = "pmx_i2c_0";
+
+ i2c_0_active: i2c_0_active {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable; /* No PULL */
+ };
+
+ i2c_0_sleep: i2c_0_sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ pmx_i2c_5 {
+ /* CLK, DATA */
+ qcom,pins = <&gp 19>, <&gp 18>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <2>;
+ label = "pmx_i2c_5";
+
+ i2c_5_active: i2c_5_active {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+
+ i2c_5_sleep: i2c_5_sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ /* QDSD pin type */
+ qdsd: qdsd {
+ qcom,pin-type-qdsd;
+ /* 0-> clk, 1 -> cmd, 2->data0, 3->data1, 4->data2, 5->data3 */
+ qcom,num-pins = <6>;
+
+ #qcom,pin-cells = <1>;
+ };
+
+ pmx_qdsd_clk {
+ qcom,pins = <&qdsd 0>;
+ qcom,num-grp-pins = <1>;
+ label = "qdsd-clk";
+ qdsd_clk_sdcard: clk_sdcard {
+ bias-disable; /* NO pull */
+ drive-strength = <7>; /* 7 MA */
+ };
+ qdsd_clk_trace: clk_trace {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_clk_swdtrc: clk_swdtrc {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_clk_spmi: clk_spmi {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ };
+
+ pmx_qdsd_cmd {
+ qcom,pins = <&qdsd 1>;
+ qcom,num-grp-pins = <1>;
+ label = "qdsd-cmd";
+ qdsd_cmd_sdcard: cmd_sdcard {
+ bias-pull-down; /* pull down */
+ drive-strength = <3>; /* 3 MA */
+ };
+ qdsd_cmd_trace: cmd_trace {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_cmd_swduart: cmd_uart {
+ bias-pull-up; /* pull up */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_cmd_swdtrc: cmd_swdtrc {
+ bias-pull-up; /* pull up */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_cmd_jtag: cmd_jtag {
+ bias-disable; /* NO pull */
+ drive-strength = <3>; /* 3 MA */
+ };
+ qdsd_cmd_spmi: cmd_spmi {
+ bias-pull-down; /* pull down */
+ drive-strength = <4>; /* 4 MA */
+ };
+ };
+
+ pmx_qdsd_data0 {
+ qcom,pins = <&qdsd 2>;
+ qcom,num-grp-pins = <1>;
+ label = "qdsd-data0";
+ qdsd_data0_sdcard: data0_sdcard {
+ bias-pull-down; /* pull down */
+ drive-strength = <3>; /* 3 MA */
+ };
+ qdsd_data0_trace: data0_trace {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data0_swduart: data0_uart {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data0_swdtrc: data0_swdtrc {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data0_jtag: data0_jtag {
+ bias-pull-up; /* pull up */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data0_spmi: data0_spmi {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ };
+
+ pmx_qdsd_data1 {
+ qcom,pins = <&qdsd 3>;
+ qcom,num-grp-pins = <1>;
+ label = "qdsd-data1";
+ qdsd_data1_sdcard: data1_sdcard {
+ bias-pull-down; /* pull down */
+ drive-strength = <3>; /* 3 MA */
+ };
+ qdsd_data1_trace: data1_trace {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data1_swduart: data1_uart {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data1_swdtrc: data1_swdtrc {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data1_jtag: data1_jtag {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ };
+
+ pmx_qdsd_data2 {
+ qcom,pins = <&qdsd 4>;
+ qcom,num-grp-pins = <1>;
+ label = "qdsd-data2";
+ qdsd_data2_sdcard: data2_sdcard {
+ bias-pull-down; /* pull down */
+ drive-strength = <3>; /* 3 MA */
+ };
+ qdsd_data2_trace: data2_trace {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data2_swduart: data2_uart {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data2_swdtrc: data2_swdtrc {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data2_jtag: data2_jtag {
+ bias-pull-up; /* pull up */
+ drive-strength = <3>; /* 3 MA */
+ };
+ };
+
+ pmx_qdsd_data3 {
+ qcom,pins = <&qdsd 5>;
+ qcom,num-grp-pins = <1>;
+ label = "qdsd-data3";
+ qdsd_data3_sdcard: data3_sdcard {
+ bias-pull-down; /* pull down */
+ drive-strength = <3>; /* 3 MA */
+ };
+ qdsd_data3_trace: data3_trace {
+ bias-pull-down; /* pull down */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data3_swduart: data3_uart {
+ bias-pull-up; /* pull up */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data3_swdtrc: data3_swdtrc {
+ bias-pull-up; /* pull up */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data3_jtag: data3_jtag {
+ bias-pull-up; /* pull up */
+ drive-strength = <0>; /* 0 MA */
+ };
+ qdsd_data3_spmi: data3_spmi {
+ bias-pull-down; /* pull down */
+ drive-strength = <3>; /* 3 MA */
+ };
+ };
+
+ pmx_mdss: pmx_mdss {
+ label = "mdss-pins";
+ qcom,pin-func = <0>;
+ mdss_dsi_active: active {
+ drive-strength = <8>; /* 8 mA */
+ bias-disable = <0>; /* no pull */
+ output-high;
+ };
+ mdss_dsi_suspend: suspend {
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ output-low;
+ };
+ };
+
+ wcnss_pmux_5wire: wcnss_pmux_5wire {
+ /* Uses general purpose pins */
+ qcom,pins = <&gp 40>, <&gp 41>,
+ <&gp 42>, <&gp 43>,
+ <&gp 44>;
+ qcom,num-grp-pins = <5>;
+ qcom,pin-func = <1>;
+ label = "wcnss_5wire_pins";
+ /* Active configuration of bus pins */
+ wcnss_default: wcnss_default {
+ drive-strength = <6>; /* 6 MA */
+ bias-pull-up; /* PULL UP */
+ };
+ wcnss_sleep: wcnss_sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL Down */
+ };
+ };
+
+ wcnss_pmux_gpio: wcnss_pmux_gpio {
+ /* Uses general purpose pins */
+ qcom,pins = <&gp 40>, <&gp 41>,
+ <&gp 42>, <&gp 43>,
+ <&gp 44>;
+ qcom,num-grp-pins = <5>;
+ qcom,pin-func = <0>;
+ label = "wcnss_5gpio_pins";
+ /* Active configuration of bus pins */
+ wcnss_gpio_default: wcnss_gpio_default {
+ drive-strength = <6>; /* 6 MA */
+ bias-pull-up; /* PULL UP */
+ };
+ };
+
+ pmx_i2c_6 {
+ /* CLK, DATA */
+ qcom,pins = <&gp 22>, <&gp 23>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <2>;
+ label = "pmx_i2c_6";
+ /* active state */
+ i2c_6_active: i2c_6_active{
+ drive-strength = <2>; /* 2 MA */
+ bias-disable; /* No PULL */
+ };
+ /*suspended state */
+ i2c_6_sleep: i2c_6_sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ pmx_rd_nfc_int{
+ qcom,pins = <&gp 21>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "pmx_nfc_int";
+
+ nfc_int_active: active {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ nfc_int_suspend: suspend {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ pmx_nfc_reset{
+ qcom,pins = <&gp 20>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "pmx_nfc_disable";
+
+ nfc_disable_active: active {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ nfc_disable_suspend: suspend {
+ drive-strength = <6>;
+ bias-disable;
+ };
+ };
+
+ pmx_mdss_te: pmx_mdss_te {
+ label = "mdss-te-pin";
+ qcom,pin-func = <1>;
+ mdss_te_active: active {
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ input-debounce = <0>;
+ };
+ mdss_te_suspend: suspend {
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* pull down */
+ input-debounce = <0>;
+ };
+ };
+
+ /* CoreSight */
+ tpiu_seta_1 {
+ qcom,pins = <&gp 8>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <3>;
+ label = "tpiu-seta-1";
+ seta_1: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_2 {
+ qcom,pins = <&gp 9>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-2";
+ seta_2: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_3 {
+ qcom,pins = <&gp 10>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <3>;
+ label = "tpiu-seta-3";
+ seta_3: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_4 {
+ qcom,pins = <&gp 39>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-4";
+ seta_4: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_5 {
+ qcom,pins = <&gp 40>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-5";
+ seta_5: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_6 {
+ qcom,pins = <&gp 41>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-6";
+ seta_6: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_7 {
+ qcom,pins = <&gp 42>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-7";
+ seta_7: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_8 {
+ qcom,pins = <&gp 43>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <3>;
+ label = "tpiu-seta-8";
+ seta_8: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_9 {
+ qcom,pins = <&gp 45>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <3>;
+ label = "tpiu-seta-9";
+ seta_9: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_10 {
+ qcom,pins = <&gp 46>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-10";
+ seta_10: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_11 {
+ qcom,pins = <&gp 47>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <3>;
+ label = "tpiu-seta-11";
+ seta_11: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_12 {
+ qcom,pins = <&gp 48>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-12";
+ seta_12: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_13 {
+ qcom,pins = <&gp 62>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-13";
+ seta_13: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_14 {
+ qcom,pins = <&gp 69>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <2>;
+ label = "tpiu-seta-14";
+ seta_14: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_15 {
+ qcom,pins = <&gp 112>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <5>;
+ label = "tpiu-seta-15";
+ seta_15: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_16 {
+ qcom,pins = <&gp 113>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <9>;
+ label = "tpiu-seta-16";
+ seta_16: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_17 {
+ qcom,pins = <&gp 114>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <8>;
+ label = "tpiu-seta-17";
+ seta_17: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_seta_18 {
+ qcom,pins = <&gp 115>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <8>;
+ label = "tpiu-seta-18";
+ seta_18: seta {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_1 {
+ qcom,pins = <&gp 4>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <5>;
+ label = "tpiu-setb-1";
+ setb_1: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_2 {
+ qcom,pins = <&gp 5>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <5>;
+ label = "tpiu-setb-2";
+ setb_2: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_3 {
+ qcom,pins = <&gp 26>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <7>;
+ label = "tpiu-setb-3";
+ setb_3: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_4 {
+ qcom,pins = <&gp 27>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <9>;
+ label = "tpiu-setb-4";
+ setb_4: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_5 {
+ qcom,pins = <&gp 28>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <7>;
+ label = "tpiu-setb-5";
+ setb_5: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_6 {
+ qcom,pins = <&gp 29>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <7>;
+ label = "tpiu-setb-6";
+ setb_6: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_7 {
+ qcom,pins = <&gp 30>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <9>;
+ label = "tpiu-setb-7";
+ setb_7: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_8 {
+ qcom,pins = <&gp 31>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <10>;
+ label = "tpiu-setb-8";
+ setb_8: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_9 {
+ qcom,pins = <&gp 32>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <10>;
+ label = "tpiu-setb-9";
+ setb_9: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_10 {
+ qcom,pins = <&gp 33>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <9>;
+ label = "tpiu-setb-10";
+ setb_10: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_11 {
+ qcom,pins = <&gp 34>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <9>;
+ label = "tpiu-setb-11";
+ setb_11: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_12 {
+ qcom,pins = <&gp 35>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <9>;
+ label = "tpiu-setb-12";
+ setb_12: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_13 {
+ qcom,pins = <&gp 36>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <8>;
+ label = "tpiu-setb-13";
+ setb_13: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_14 {
+ qcom,pins = <&gp 37>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <7>;
+ label = "tpiu-setb-14";
+ setb_14: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_15 {
+ qcom,pins = <&gp 110>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <4>;
+ label = "tpiu-setb-15";
+ setb_15: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_16 {
+ qcom,pins = <&gp 111>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <1>;
+ label = "tpiu-setb-16";
+ setb_16: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_17 {
+ qcom,pins = <&gp 120>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <10>;
+ label = "tpiu-setb-17";
+ setb_17: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tpiu_setb_18 {
+ qcom,pins = <&gp 121>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <11>;
+ label = "tpiu-setb-18";
+ setb_18: setb {
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ tlmm_gpio_key {
+ qcom,pins = <&gp 107>, <&gp 108>, <&gp 109>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <3>;
+ label = "tlmm_gpio_key";
+ gpio_key_active: gpio_key_active {
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ gpio_key_suspend: gpio_key_suspend {
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ gpio_led_pins {
+ qcom,pins = <&gp 8>, <&gp 9>, <&gp 10>;
+ qcom,num-grp-pins = <3>;
+ label = "gpio-led-pins";
+ gpio_led_off: led_off {
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+
+ /* add pingrp for touchscreen */
+ pmx_ts_int_active {
+ qcom,pins = <&gp 13>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "pmx_ts_int_active";
+
+ ts_int_active: ts_int_active {
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+
+ pmx_ts_int_suspend {
+ qcom,pins = <&gp 13>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "pmx_ts_int_suspend";
+
+ ts_int_suspend: ts_int_suspend {
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ pmx_ts_reset_active {
+ qcom,pins = <&gp 12>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "pmx_ts_reset_active";
+
+ ts_reset_active: ts_reset_active {
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+
+ pmx_ts_reset_suspend {
+ qcom,pins = <&gp 12>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "pmx_ts_reset_suspend";
+
+ ts_reset_suspend: ts_reset_suspend {
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ cci0_pinmux {
+ /* CLK, DATA */
+ qcom,pins = <&gp 29>, <&gp 30>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <1>;
+ label = "cci0";
+ /* active state */
+ cci0_default: default {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ /*suspended state */
+ cci0_sleep: sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ cam_sensor_mclk0 {
+ /* MCLK */
+ qcom,pins = <&gp 26>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <1>;
+ label = "cam-sensor-mclk0";
+ /* active state */
+ cam_sensor_mclk0_default: default {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ cam_sensor_mclk0_sleep {
+ /* MCLK */
+ qcom,pins = <&gp 26>;
+ qcom,num-grp-pins = <1>;
+ label = "cam-sensor-mclk0-sleep";
+ /* suspend state */
+ cam_sensor_mclk0_sleep: sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+
+ cam_sensor_mclk1 {
+ /* MCLK */
+ qcom,pins = <&gp 27>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <1>;
+ label = "cam-sensor-mclk1";
+ /* active state */
+ cam_sensor_mclk1_default: default {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ cam_sensor_mclk1_sleep {
+ /* MCLK */
+ qcom,pins = <&gp 27>;
+ qcom,num-grp-pins = <1>;
+ label = "cam-sensor-mclk1-sleep";
+ /* suspend state */
+ cam_sensor_mclk1_sleep: sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+
+ cam_sensor_rear {
+ /* RESET, STANDBY */
+ qcom,pins = <&gp 35>, <&gp 34>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <0>;
+ label = "cam-sensor-rear";
+ /* active state */
+ cam_sensor_rear_default: default {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ cam_sensor_rear_sleep {
+ /* RESET, STANDBY */
+ qcom,pins = <&gp 35>, <&gp 34>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <0>;
+ label = "cam-sensor-rear-sleep";
+ /*suspended state */
+ cam_sensor_rear_sleep: sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down; /* PULL DOWN */
+ };
+ };
+
+ cam_sensor_front {
+ /* RESET, STANDBY */
+ qcom,pins = <&gp 28>, <&gp 33>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <0>;
+ label = "cam_sensor_front";
+ /* active state */
+ cam_sensor_front_default: default {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ };
+
+ cam_sensor_front_sleep {
+ /* RESET, STANDBY */
+ qcom,pins = <&gp 28>, <&gp 33>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <0>;
+ label = "cam_sensor_front";
+ /*suspended state */
+ cam_sensor_front_sleep: sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down = <0>; /* PULL DOWN */
+ };
+ };
+
+ cam_sensor_flash {
+ /* FLSH_RESET,FLASH_EN,FLASH_NOW */
+ qcom,pins = <&gp 36>, <&gp 31>,<&gp 32> ;
+ qcom,num-grp-pins = <3>;
+ qcom,pin-func = <0>;
+ label = "cam_sensor_flash";
+ /* active state */
+ cam_sensor_flash_default: default {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+ /*suspended state */
+ cam_sensor_flash_sleep: sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-down = <0>; /* PULL DOWN */
+ };
+ };
+
+ pmx_i2c_4 {
+ /* CLK, DATA */
+ qcom,pins = <&gp 14>, <&gp 15>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <2>;
+ label = "pmx_i2c_4";
+
+ i2c_4_active: i2c_4_active {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+
+ i2c_4_sleep: i2c_4_sleep {
+ drive-strength = <2>; /* 2 MA */
+ bias-disable = <0>; /* No PULL */
+ };
+
+ };
+
+ smb_int_pin {
+ qcom,pins = <&gp 62>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "smb1360_int_gpio";
+ smb_int_default: smb_int_default {
+ drive-strength = <2>; /* 2 MA */
+ bias-pull-up; /* PULL UP*/
+ };
+ };
+
+ button_backlight_pin {
+ qcom,pins = <&gp 119>;
+ qcom,num-grp-pins = <1>;
+ qcom,pin-func = <0>;
+ label = "button-backlight-pin";
+ button_backlight_off: button_backlight_off {
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+
+ mpu6050_int_pin {
+ qcom,pins = <&gp 115>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "mpu6050-irq";
+ mpu6050_default: mpu6050_default {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ mpu6050_sleep: mpu6050_sleep {
+ drive-strength = <2>;
+ };
+ };
+
+ apds99xx_int_pin {
+ qcom,pins = <&gp 113>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "apds99xx-irq";
+ apds99xx_default: apds99xx_default {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ apds99xx_sleep: apds99xx_sleep {
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ ak8963_int_pin {
+ qcom,pins = <&gp 69>;
+ qcom,pin-func = <0>;
+ qcom,num-grp-pins = <1>;
+ label = "ak8963-irq";
+ ak8963_default: ak8963_default {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ ak8963_sleep: ak8963_sleep {
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8916-pm.dtsi b/arch/arm/boot/dts/msm8916-pm.dtsi
new file mode 100644
index 000000000000..b060b77be254
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-pm.dtsi
@@ -0,0 +1,345 @@
+/* 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.
+ */
+
+&soc {
+ qcom,spm@b089000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb089000 0x1000>;
+ qcom,core-id = <0>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0xe>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0B 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3B 76 76 0B
+ 94 5B 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3B 76 76 0B
+ 94 5B 80 10 26 30 0f];
+ };
+
+ qcom,spm@b099000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb099000 0x1000>;
+ qcom,core-id = <1>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0xe>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0B 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3B 76 76 0B
+ 94 5B 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3B 76 76 0B
+ 94 5B 80 10 26 30 0f];
+ };
+
+ qcom,spm@b0a9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb0a9000 0x1000>;
+ qcom,core-id = <2>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0xe>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0B 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3B 76 76 0B
+ 94 5B 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3B 76 76 0B
+ 94 5B 80 10 26 30 0f];
+ };
+
+ qcom,spm@b0b9000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb0b9000 0x1000>;
+ qcom,core-id = <3>;
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0xe>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0B 0f];
+ qcom,saw2-spm-cmd-spc = [20 10 80 30 90 5b 60 03 60 3B 76 76 0B
+ 94 5B 80 10 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [20 10 80 30 90 5b 60 03 60 3B 76 76 0B
+ 94 5B 80 10 26 30 0f];
+ };
+
+ qcom,spm@b012000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb012000 0x1000>;
+ qcom,core-id = <0xffff>; /* L2/APCS SAW */
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x1F>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0xe>;
+ qcom,saw2-pmic-data0 = <0x04030080>;
+ qcom,saw2-pmic-data1 = <0x01030000>;
+ qcom,vctl-timeout-us = <50>;
+ qcom,vctl-port = <0x0>;
+ qcom,phase-port = <0x1>;
+ qcom,pfm-port = <0x2>;
+ qcom,saw2-spm-cmd-ret = [00 03 00 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 20 32 6B C0 E0 D0 42 F0 03 50 4E
+ 02 02 D0 E0 C0 22 6B 02 32 52 F0 0F];
+ qcom,saw2-spm-cmd-pc = [00 32 B0 10 E0 D0 6B C0 42 11 07 01
+ B0 50 4E 02 02 C0 D0 12 E0 6B 02 32 50 0F];
+ qcom,L2-spm-is-apcs-master;
+ };
+
+
+ qcom,lpm-levels {
+ compatible = "qcom,lpm-levels";
+ qcom,default-l2-state = "l2_cache_active";
+ qcom,allow-synced-levels;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,cpu-modes {
+ compatible = "qcom,cpu-modes";
+
+ qcom,cpu-mode@0 {
+ qcom,mode = "wfi";
+ qcom,latency-us = <1>;
+ qcom,ss-power = <560>;
+ qcom,energy-overhead = <12000>;
+ qcom,time-overhead = <20>;
+ };
+
+ qcom,cpu-mode@1 {
+ qcom,mode = "standalone_pc";
+ qcom,latency-us = <180>;
+ qcom,ss-power = <550>;
+ qcom,energy-overhead = <160000>;
+ qcom,time-overhead = <280>;
+ qcom,use-broadcast-timer;
+ };
+
+ qcom,cpu-mode@2 {
+ qcom,mode = "pc";
+ qcom,latency-us = <230>;
+ qcom,ss-power = <535>;
+ qcom,energy-overhead = <200000>;
+ qcom,time-overhead = <330>;
+ qcom,use-broadcast-timer;
+ };
+ };
+
+ qcom,system-modes {
+ compatible = "qcom,system-modes";
+
+ qcom,system-mode@0 {
+ qcom,l2 = "l2_cache_gdhs";
+ qcom,latency-us = <240>;
+ qcom,ss-power = <530>;
+ qcom,energy-overhead = <210000>;
+ qcom,time-overhead = <350>;
+ qcom,min-cpu-mode= "standalone_pc";
+ qcom,sync-mode;
+ };
+
+ qcom,system-mode@1 {
+ qcom,l2 = "l2_cache_pc";
+ qcom,latency-us = <10900>;
+ qcom,ss-power = <490>;
+ qcom,energy-overhead = <1030563>;
+ qcom,time-overhead = <1656>;
+ qcom,min-cpu-mode= "pc";
+ qcom,send-rpm-sleep-set;
+ qcom,sync-mode;
+ };
+ };
+ };
+ qcom,pm-boot {
+ compatible = "qcom,pm-boot";
+ qcom,mode = "tz";
+ };
+
+ qcom,mpm@601d0 {
+
+ status = "disabled";
+
+ compatible = "qcom,mpm-v2";
+ reg = <0x601d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+ <0xb011008 0x4>;
+ reg-names = "vmpm", "ipc";
+ interrupts = <0 171 1>;
+ clocks = <&clock_rpm clk_xo_lpm_clk>;
+ clock-names = "xo";
+
+ qcom,ipc-bit-offset = <1>;
+
+ qcom,gic-parent = <&intc>;
+ qcom,gic-map = <2 216>, /* tsens_upper_lower_int */
+ <50 172>, /* usb1_hs_async_wakeup_irq */
+ <53 104>, /* mdss_irq */
+ <62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <0xff 18>, /* APC_qgicQTmrSecPhysIrptReq */
+ <0xff 19>, /* APC_qgicQTmrNonSecPhysIrptReq */
+ <0xff 20>, /* qgicQTmrVirtIrptReq */
+ <0xff 35>, /* WDT_barkInt */
+ <0xff 39>, /* arch_mem_timer */
+ <0xff 40>, /* qtmr_phy_irq[0] */
+ <0xff 47>, /* rbif_irq[0] */
+ <0xff 56>, /* q6_wdog_expired_irq */
+ <0xff 57>, /* mss_to_apps_irq(0) */
+ <0xff 58>, /* mss_to_apps_irq(1) */
+ <0xff 59>, /* mss_to_apps_irq(2) */
+ <0xff 60>, /* mss_to_apps_irq(3) */
+ <0xff 61>, /* mss_a2_bam_irq */
+ <0xff 65>, /* o_gc_sys_irq[0] */
+ <0xff 74>, /* venus0_mmu_cirpt[1] */
+ <0xff 75>, /* venus0_mmu_cirpt[0] */
+ <0xff 78>, /* mdss_mmu_cirpt[0] */
+ <0xff 79>, /* mdss_mmu_cirpt[1] */
+ <0xff 97>, /* camss_vfe_mmu_cirpt[1] */
+ <0xff 102>, /* camss_jpeg_mmu_cirpt[1] */
+ <0xff 109>, /* ocmem_dm_nonsec_irq */
+ <0xff 131>, /* blsp1_qup_5_irq */
+ <0xff 140>, /* blsp1_uart_3_irq */
+ <0xff 166>, /* usb_hs_irq */
+ <0xff 155>, /* sdc1_irq(0) */
+ <0xff 157>, /* sdc2_irq(0) */
+ <0xff 170>, /* sdc1_pwr_cmd_irq */
+ <0xff 173>, /* o_wcss_apss_smd_hi */
+ <0xff 174>, /* o_wcss_apss_smd_med */
+ <0xff 175>, /* o_wcss_apss_smd_low */
+ <0xff 176>, /* o_wcss_apss_smsm_irq */
+ <0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
+ <0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
+ <0xff 179>, /* o_wcss_apss_asic_intr */
+ <0xff 181>, /* o_wcss_apss_wdog_bite_and_reset_rdy */
+
+ <0xff 188>, /* lpass_irq_out_apcs(0) */
+ <0xff 189>, /* lpass_irq_out_apcs(1) */
+ <0xff 190>, /* lpass_irq_out_apcs(2) */
+ <0xff 191>, /* lpass_irq_out_apcs(3) */
+ <0xff 192>, /* lpass_irq_out_apcs(4) */
+ <0xff 193>, /* lpass_irq_out_apcs(5) */
+ <0xff 194>, /* lpass_irq_out_apcs(6) */
+ <0xff 195>, /* lpass_irq_out_apcs(7) */
+ <0xff 196>, /* lpass_irq_out_apcs(8) */
+ <0xff 197>, /* lpass_irq_out_apcs(9) */
+ <0xff 198>, /* coresight-tmc-etr interrupt */
+ <0xff 200>, /* rpm_ipc(4) */
+ <0xff 201>, /* rpm_ipc(5) */
+ <0xff 202>, /* rpm_ipc(6) */
+ <0xff 203>, /* rpm_ipc(7) */
+ <0xff 204>, /* rpm_ipc(24) */
+ <0xff 205>, /* rpm_ipc(25) */
+ <0xff 206>, /* rpm_ipc(26) */
+ <0xff 207>, /* rpm_ipc(27) */
+ <0xff 239>, /* crypto_bam_irq[1]*/
+ <0xff 240>, /* summary_irq_kpss */
+ <0xff 253>, /* sdc2_pwr_cmd_irq */
+ <0xff 263>, /* msm_iommu_global_client_irq */
+ <0xff 269>, /* rpm_wdog_expired_irq */
+ <0xff 270>, /* blsp1_bam_irq[0] */
+ <0xff 275>, /* rpm_ipc(30) */
+ <0xff 276>; /* rpm_ipc(31) */
+
+ qcom,gpio-parent = <&msm_gpio>;
+ qcom,gpio-map = <3 108 >,
+ <4 1 >,
+ <5 5 >,
+ <6 9 >,
+ <7 107>,
+ <8 98>,
+ <9 97>,
+ <10 11>,
+ <11 69>,
+ <12 12>,
+ <13 13>,
+ <14 20>,
+ <15 62>,
+ <16 54>,
+ <17 21>,
+ <18 52>,
+ <19 25>,
+ <20 51>,
+ <21 50>,
+ <22 28>,
+ <23 31>,
+ <24 34>,
+ <25 35>,
+ <26 36>,
+ <27 37>,
+ <28 38>,
+ <29 49>,
+ <30 109>,
+ <31 110>,
+ <32 111>,
+ <33 112>,
+ <34 113>,
+ <35 114>,
+ <36 115>,
+ <37 117>,
+ <38 118>,
+ <39 120>,
+ <40 121>,
+ <50 66>,
+ <51 68>;
+ };
+
+ qcom,pm@8600664 {
+ compatible = "qcom,pm";
+ reg = <0x8600664 0x40>;
+ qcom,pc-mode = "tz_l2_int";
+ qcom,use-sync-timer;
+ qcom,synced-clocks;
+ };
+
+ qcom,cpu-sleep-status@b088008{
+ compatible = "qcom,cpu-sleep-status";
+ reg = <0xb088008 0x100>;
+ qcom,cpu-alias-addr = <0x10000>;
+ qcom,sleep-status-mask= <0x40000>;
+ };
+
+ qcom,rpm-log@29dc00 {
+ compatible = "qcom,rpm-log";
+ reg = <0x29dc00 0x4000>;
+ qcom,rpm-addr-phys = <0xfc000000>;
+ qcom,offset-version = <4>;
+ qcom,offset-page-buffer-addr = <36>;
+ qcom,offset-log-len = <40>;
+ qcom,offset-log-len-mask = <44>;
+ qcom,offset-page-indices = <56>;
+ };
+
+ qcom,rpm-stats@29dba0 {
+ compatible = "qcom,rpm-stats";
+ reg = <0x29dba0 0x1000>;
+ reg-names = "phys_addr_base";
+ qcom,sleep-stats-version = <2>;
+ };
+
+ qcom,rpm-master-stats@60150 {
+ compatible = "qcom,rpm-master-stats";
+ reg = <0x60150 0x2030>;
+ qcom,masters = "APSS", "MPSS", "PRONTO";
+ qcom,master-stats-version = <2>;
+ qcom,master-offset = <4096>;
+ };
+ qcom,rpm-rbcpr-stats@0x29daa0 {
+ compatible = "qcom,rpmrbcpr-stats";
+ reg = <0x29daa0 0x1a0000>;
+ qcom,start-offset = <0x190010>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8916-qrd-skui.dts b/arch/arm/boot/dts/msm8916-qrd-skui.dts
new file mode 100644
index 000000000000..6f409f7f8dc9
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-qrd-skui.dts
@@ -0,0 +1,36 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+#include "msm8916-qrd-skui.dtsi"
+#include "msm8916-memory.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM 8916 QRD SKUI";
+ compatible = "qcom,msm8916-qrd-skui", "qcom,msm8916-qrd", "qcom,msm8916", "qcom,qrd";
+ qcom,board-id = <0x1000b 5> , <0x1010b 5> , <0x3010b 5>;
+};
+
+&soc {
+ gen-vkeys {
+ compatible = "qcom,gen-vkeys";
+ label = "ft5x06_ts";
+ qcom,disp-maxx = <480>;
+ qcom,disp-maxy = <854>;
+ qcom,panel-maxx = <480>;
+ qcom,panel-maxy = <946>;
+ qcom,key-codes = <139 172 158>;
+ qcom,y-offset = <0>;
+ };
+};
+
diff --git a/arch/arm/boot/dts/msm8916-qrd-skui.dtsi b/arch/arm/boot/dts/msm8916-qrd-skui.dtsi
new file mode 100644
index 000000000000..e3c1b467af3b
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-qrd-skui.dtsi
@@ -0,0 +1,67 @@
+/* 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 "msm8916-qrd.dtsi"
+
+&tlmm_pinmux {
+ ocp8110_pins {
+ qcom,pins = <&gp 31>, <&gp 32>;
+ qcom,num-grp-pins = <2>;
+ qcom,pin-func = <0>;
+ label = "ocp8110_pins";
+ ocp8110_default: en_default {
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+
+ bma2x2_int1_pin {
+ qcom,pins = <&gp 112>;
+ qcom,num-grp-pins = <1>;
+ label = "bma2x2_int1_pin";
+ bma2x2_int1_default: int1_default {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ bma2x2_int2_pin {
+ qcom,pins = <&gp 114>;
+ qcom,num-grp-pins = <1>;
+ label = "bma2x2_int2_pin";
+ bma2x2_int2_default: int2_default {
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+};
+
+&sdc2_cd_on {
+ /delete-property/ bias-pull-up;
+ bias-pull-down;
+};
+
+&sdc2_cd_off {
+ /delete-property/ bias-disable;
+ bias-pull-down;
+};
+
+&sdhc_2 {
+ qcom,nonremovable;
+
+ interrupts = <0 1>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+ /delete-property/ cd-gpios;
+};
+
diff --git a/arch/arm/boot/dts/msm8916-qrd.dtsi b/arch/arm/boot/dts/msm8916-qrd.dtsi
new file mode 100644
index 000000000000..445dca98a888
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-qrd.dtsi
@@ -0,0 +1,137 @@
+/* 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 "msm8916.dtsi"
+#include "msm8916-pinctrl.dtsi"
+
+/ {
+ aliases {
+ serial0 = &blsp1_uart2;
+ };
+};
+
+
+&blsp1_uart2 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_sleep>;
+};
+
+&soc {
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+ pinctrl-0 = <&gpio_key_active>;
+ pinctrl-1 = <&gpio_key_suspend>;
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&msm_gpio 107 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
+};
+
+&pm8916_gpios {
+ gpio@c000 { /* GPIO 1 */
+ /* Battery UICC Alarm */
+ status = "disabled";
+ };
+
+ gpio@c100 { /* GPIO 2 */
+ /* NFC_CLK_REQ */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
+ };
+
+ gpio@c200 { /* GPIO 3 */
+ /* External regulator control for WTR */
+ status = "disabled";
+ };
+
+ gpio@c300 { /* GPIO 4 */
+ /* External regulator control for APC */
+ status = "disabled";
+ };
+};
+
+&sdhc_1 {
+ vdd-supply = <&pm8916_l8>;
+ qcom,vdd-voltage-level = <2900000 2900000>;
+ qcom,vdd-current-level = <200 400000>;
+
+ vdd-io-supply = <&pm8916_l5>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 60000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>;
+
+ qcom,nonremovable;
+
+ status = "ok";
+};
+
+&sdhc_2 {
+ vdd-supply = <&pm8916_l11>;
+ qcom,vdd-voltage-level = <2800000 2950000>;
+ qcom,vdd-current-level = <15000 400000>;
+
+ vdd-io-supply = <&pm8916_l12>;
+ qcom,vdd-io-voltage-level = <1800000 2950000>;
+ qcom,vdd-io-current-level = <200 50000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0
+ 2 &msm_gpio 38 0>;
+ interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+ cd-gpios = <&msm_gpio 38 0x0>;
+
+ status = "ok";
+};
+
+&spmi_bus {
+ qcom,pm8916@1 {
+ qcom,vibrator@c000 {
+ status = "okay";
+ qcom,vib-timeout-ms = <15000>;
+ qcom,vib-vtg-level-mV = <3100>;
+ };
+ };
+};
+
+&qcom_tzlog {
+ status = "okay";
+};
+
+
+
+
diff --git a/arch/arm/boot/dts/msm8916-regulator.dtsi b/arch/arm/boot/dts/msm8916-regulator.dtsi
new file mode 100644
index 000000000000..7fe4f6d9906b
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916-regulator.dtsi
@@ -0,0 +1,373 @@
+/* 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.
+ */
+
+/* SPM controlled regulators */
+&spmi_bus {
+ qcom,pm8916@1 {
+ pm8916_s2: spm-regulator@1700 {
+ compatible = "qcom,spm-regulator";
+ regulator-name = "8916_s2";
+ reg = <0x1700 0x100>;
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1350000>;
+ };
+ };
+};
+
+/* CPR controlled regulator */
+
+&soc {
+ mem_acc_vreg_corner: regulator@1946000 {
+ compatible = "qcom,mem-acc-regulator";
+ reg = <0x1946000 0x4>, <0x1946000 0x4>, <0x58000 0x1000>;
+ reg-names = "acc-sel-l1", "acc-sel-l2", "efuse_addr";
+ regulator-name = "mem_acc_corner";
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <3>;
+
+ qcom,acc-sel-l1-bit-pos = <0>;
+ qcom,acc-sel-l2-bit-pos = <8>;
+ qcom,corner-acc-map = <0 1 1>;
+ qcom,l1-config-skip-fuse-sel = <0 52 1 1 0>;
+ };
+
+ apc_vreg_corner: regulator@b018000 {
+ compatible = "qcom,cpr-regulator";
+ reg = <0xb018000 0x1000>, <0xb011064 4>, <0x58000 0x1000>;
+ reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
+ interrupts = <0 15 0>;
+ regulator-name = "apc_corner";
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+
+ qcom,cpr-voltage-ceiling = <1050000 1150000 1350000>;
+ qcom,cpr-voltage-floor = <1050000 1050000 1162500>;
+ vdd-apc-supply = <&pm8916_s2>;
+
+ qcom,vdd-mx-corner-map = <4 5 7>;
+ qcom,vdd-mx-vmin-method = <4>;
+ vdd-mx-supply = <&pm8916_l3_corner_ao>;
+ qcom,vdd-mx-vmax = <7>;
+
+ mem-acc-supply = <&mem_acc_vreg_corner>;
+
+ qcom,cpr-ref-clk = <19200>;
+ qcom,cpr-timer-delay = <5000>;
+ qcom,cpr-timer-cons-up = <0>;
+ qcom,cpr-timer-cons-down = <2>;
+ qcom,cpr-irq-line = <0>;
+ qcom,cpr-step-quotient = <26>;
+ qcom,cpr-up-threshold = <0>;
+ qcom,cpr-down-threshold = <2>;
+ qcom,cpr-idle-clocks = <15>;
+ qcom,cpr-gcnt-time = <1>;
+ qcom,vdd-apc-step-up-limit = <1>;
+ qcom,vdd-apc-step-down-limit = <1>;
+ qcom,cpr-apc-volt-step = <12500>;
+
+ qcom,cpr-fuse-row = <27 0>;
+ qcom,cpr-fuse-target-quot = <42 24 6>;
+ qcom,cpr-fuse-ro-sel = <54 54 54>;
+ qcom,cpr-fuse-bp-cpr-disable = <57>;
+ qcom,cpr-fuse-init-voltage =
+ <27 36 6 0>,
+ <27 18 6 0>,
+ <27 0 6 0>;
+ qcom,cpr-init-voltage-step = <10000>;
+ qcom,cpr-corner-map = <1 1 2 2 3 3 3>;
+ qcom,cpr-corner-frequency-map =
+ <1 200000000>,
+ <2 400000000>,
+ <3 533330000>,
+ <4 800000000>,
+ <5 998400000>,
+ <6 1094400000>,
+ <7 1190400000>;
+ qcom,speed-bin-fuse-sel = <1 34 3 0>;
+ qcom,cpr-speed-bin-max-corners =
+ <0 0 2 4 7>;
+ qcom,cpr-quot-adjust-scaling-factor-max = <650>;
+ qcom,cpr-enable;
+ };
+};
+
+
+/* RPM controlled regulators */
+&rpm_bus {
+
+ /* PM8916 S1 VDD_CX supply */
+ rpm-regulator-smpa1 {
+ status = "okay";
+ pm8916_s1_corner: regulator-s1-corner {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_s1_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-corner;
+ };
+ pm8916_s1_corner_ao: regulator-s1-corner-ao {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_s1_corner_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-corner;
+ };
+ pm8916_s1_floor_corner: regulator-s1-floor-corner {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_s1_floor_corner";
+ qcom,set = <3>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-floor-corner;
+ qcom,always-send-voltage;
+ };
+ };
+
+ rpm-regulator-smpa3 {
+ status = "okay";
+ pm8916_s3: regulator-s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,init-voltage = <1200000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa4 {
+ status = "okay";
+ pm8916_s4: regulator-s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2100000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ status = "okay";
+ pm8916_l1: regulator-l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ status = "okay";
+ pm8916_l2: regulator-l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,init-voltage = <1200000>;
+ status = "okay";
+ };
+ };
+
+ /* PM8916 L3 VDD_MX supply */
+ rpm-regulator-ldoa3 {
+ status = "okay";
+ pm8916_l3: regulator-l3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1287500>;
+ status = "okay";
+ };
+
+ pm8916_l3_corner_ao: regulator-l3-corner-ao {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l3_corner_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-corner;
+ };
+
+ pm8916_l3_corner_so: regulator-l3-corner-so {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l3_corner_so";
+ qcom,set = <2>;
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ qcom,use-voltage-corner;
+ qcom,init-voltage = <1>;
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ status = "okay";
+ pm8916_l4: regulator-l4 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,init-voltage = <2050000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ status = "okay";
+ pm8916_l5: regulator-l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ status = "okay";
+ pm8916_l6: regulator-l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ status = "okay";
+ pm8916_l7: regulator-l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+
+ pm8916_l7_ao: regulator-l7-ao {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l7_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ };
+
+ pm8916_l7_so: regulator-l7-so {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "8916_l7_so";
+ qcom,set = <2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-enable = <0>;
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ status = "okay";
+ pm8916_l8: regulator-l8 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2900000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ status = "okay";
+ pm8916_l9: regulator-l9 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <3300000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ status = "okay";
+ pm8916_l10: regulator-l10 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2800000>;
+ qcom,init-voltage = <2700000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ status = "okay";
+ pm8916_l11: regulator-l11 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ status = "okay";
+ pm8916_l12: regulator-l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa13 {
+ status = "okay";
+ pm8916_l13: regulator-l13 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ qcom,init-voltage = <3075000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ status = "okay";
+ pm8916_l14: regulator-l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ status = "okay";
+ pm8916_l15: regulator-l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa16 {
+ status = "okay";
+ pm8916_l16: regulator-l16 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ status = "okay";
+ pm8916_l17: regulator-l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa18 {
+ status = "okay";
+ pm8916_l18: regulator-l18 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ qcom,init-voltage = <2700000>;
+ status = "okay";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8916.dtsi b/arch/arm/boot/dts/msm8916.dtsi
new file mode 100644
index 000000000000..2e7d8c6c6a3d
--- /dev/null
+++ b/arch/arm/boot/dts/msm8916.dtsi
@@ -0,0 +1,810 @@
+/* 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 "skeleton64.dtsi"
+#include <dt-bindings/clock/msm-clocks-8916.h>
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM8916";
+ compatible = "qcom,msm8916";
+ qcom,msm-id = <206 0>,
+ <248 0>,
+ <249 0>,
+ <250 0>;
+
+ interrupt-parent = <&intc>;
+ aliases {
+ sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+ sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+
+ /* smdtty devices */
+ smd1 = &smdtty_apps_fm;
+ smd2 = &smdtty_apps_riva_bt_acl;
+ smd3 = &smdtty_apps_riva_bt_cmd;
+ smd4 = &smdtty_mbalbridge;
+ smd5 = &smdtty_apps_riva_ant_cmd;
+ smd6 = &smdtty_apps_riva_ant_data;
+ smd7 = &smdtty_data1;
+ smd8 = &smdtty_data4;
+ smd11 = &smdtty_data11;
+ smd21 = &smdtty_data21;
+ smd36 = &smdtty_loopback;
+
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0>;
+ enable-method = "qcom,arm-cortex-acc";
+ qcom,acc = <&acc0>;
+ };
+
+ CPU1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x1>;
+ enable-method = "qcom,arm-cortex-acc";
+ qcom,acc = <&acc1>;
+ };
+
+ CPU2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x2>;
+ enable-method = "qcom,arm-cortex-acc";
+ qcom,acc = <&acc2>;
+ };
+
+ CPU3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x3>;
+ enable-method = "qcom,arm-cortex-acc";
+ qcom,acc = <&acc3>;
+ };
+ };
+
+ soc: soc { };
+};
+
+#include "msm8916-ipcrouter.dtsi"
+#include "msm-gdsc-8916.dtsi"
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+
+ acc0:clock-controller@b088000 {
+ compatible = "qcom,arm-cortex-acc";
+ reg = <0x0b088000 0x1000>,
+ <0x0b008000 0x1000>;
+ };
+
+ acc1:clock-controller@b098000 {
+ compatible = "qcom,arm-cortex-acc";
+ reg = <0x0b098000 0x1000>,
+ <0x0b008000 0x1000>;
+ };
+
+ acc2:clock-controller@b0a8000 {
+ compatible = "qcom,arm-cortex-acc";
+ reg = <0x0b0a8000 0x1000>,
+ <0x0b008000 0x1000>;
+ };
+
+ acc3:clock-controller@b0b8000 {
+ compatible = "qcom,arm-cortex-acc";
+ reg = <0x0b0b8000 0x1000>,
+ <0x0b008000 0x1000>;
+ };
+
+ intc: interrupt-controller@b000000 {
+ compatible = "qcom,msm-qgic2";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ reg = <0x0b000000 0x1000>,
+ <0x0b002000 0x1000>;
+ };
+
+ restart@4ab000 {
+ compatible = "qcom,pshold";
+ reg = <0x4ab000 0x4>;
+ };
+
+ qcom,mpm2-sleep-counter@4a3000 {
+ compatible = "qcom,mpm2-sleep-counter";
+ reg = <0x4a3000 0x1000>;
+ clock-frequency = <32768>;
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts = <1 2 0xf08>,
+ <1 3 0xf08>,
+ <1 4 0xf08>,
+ <1 1 0xf08>;
+ clock-frequency = <19200000>;
+ };
+
+ timer@b020000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0xb020000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@b021000 {
+ frame-number = <0>;
+ interrupts = <0 8 0x4>,
+ <0 7 0x4>;
+ reg = <0xb021000 0x1000>,
+ <0xb022000 0x1000>;
+ };
+
+ frame@b023000 {
+ frame-number = <1>;
+ interrupts = <0 9 0x4>;
+ reg = <0xb023000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b024000 {
+ frame-number = <2>;
+ interrupts = <0 10 0x4>;
+ reg = <0xb024000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b025000 {
+ frame-number = <3>;
+ interrupts = <0 11 0x4>;
+ reg = <0xb025000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b026000 {
+ frame-number = <4>;
+ interrupts = <0 12 0x4>;
+ reg = <0xb026000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b027000 {
+ frame-number = <5>;
+ interrupts = <0 13 0x4>;
+ reg = <0xb027000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@b028000 {
+ frame-number = <6>;
+ interrupts = <0 14 0x4>;
+ reg = <0xb028000 0x1000>;
+ status = "disabled";
+ };
+ };
+
+ clock_rpm: qcom,rpmcc@1800000 {
+ compatible = "qcom,rpmcc-8916";
+ reg = <0x1800000 0x80000>;
+ reg-names = "cc_base";
+ #clock-cells = <1>;
+
+ };
+
+ clock_gcc: qcom,gcc@1800000 {
+ compatible = "qcom,gcc-8916";
+ reg = <0x1800000 0x80000>,
+ <0xb016000 0x00040>;
+ reg-names = "cc_base", "apcs_base";
+ vdd_dig-supply = <&pm8916_s1_corner>;
+ vdd_sr2_dig-supply = <&pm8916_s1_corner_ao>;
+ vdd_sr2_pll-supply = <&pm8916_l7_ao>;
+ clocks = <&clock_rpm clk_xo_clk_src>,
+ <&clock_rpm clk_xo_a_clk_src>;
+ clock-names = "xo", "xo_a";
+ #clock-cells = <1>;
+ };
+
+ clock_debug: qcom,cc-debug@1874000 {
+ compatible = "qcom,cc-debug-8916";
+ reg = <0x1874000 0x4>,
+ <0xb01101c 0x8>;
+ reg-names = "cc_base", "meas";
+ clocks = <&clock_rpm clk_rpm_debug_mux>;
+ clock-names = "rpm_debug_mux";
+ #clock-cells = <1>;
+ };
+
+ tsens: tsens@4a8000 {
+ compatible = "qcom,msm8916-tsens";
+ reg = <0x4a8000 0x2000>,
+ <0x5c000 0x1000>;
+ reg-names = "tsens_physical", "tsens_eeprom_physical";
+ interrupts = <0 184 0>;
+ qcom,sensors = <5>;
+ qcom,slope = <3200 3200 3200 3200 3200>;
+ qcom,sensor-id = <0 1 2 4 5>;
+ };
+
+ qcom,clock-a7@0b011050 {
+ compatible = "qcom,clock-a53-8916";
+ reg = <0x0b011050 0x8>,
+ <0x0005c004 0x8>;
+ reg-names = "rcg-base", "efuse1";
+ qcom,safe-freq = < 400000000 >;
+ cpu-vdd-supply = <&apc_vreg_corner>;
+ clocks = <&clock_gcc clk_gpll0_ao_clk_src>,
+ <&clock_gcc clk_a53sspll>;
+ clock-names = "clk-4", "clk-5";
+ qcom,speed0-bin-v0 =
+ < 0 0>,
+ < 200000000 1>,
+ < 400000000 2>,
+ < 533333000 3>,
+ < 800000000 4>,
+ < 998400000 5>,
+ < 1094400000 6>,
+ < 1152000000 7>,
+ < 1209600000 8>;
+
+ qcom,speed1-bin-v0 =
+ < 0 0>,
+ < 200000000 1>,
+ < 400000000 2>,
+ < 533333000 3>,
+ < 800000000 4>,
+ < 998400000 5>,
+ < 1094400000 6>,
+ < 1152000000 7>;
+ };
+
+ qcom,cpubw {
+ compatible = "qcom,cpubw";
+ qcom,cpu-mem-ports = <1 512>;
+ qcom,bw-tbl =
+ /* 73 9.60 MHz */
+ /* 381 50MHz */
+ < 762 /* 100 MHz */>,
+ < 1525 /* 200 MHz */>,
+ < 3051 /* 400 MHz */>,
+ < 4066 /* 533 MHz */>;
+ qcom,ab-tbl =
+ < 229 >,
+ < 458 >,
+ < 915 >,
+ < 1220 >;
+ };
+
+ qcom,msm-cpufreq@0 {
+ reg = <0 4>;
+ compatible = "qcom,msm-cpufreq";
+ qcom,cpufreq-table =
+ < 200000 762>,
+ < 400000 762>,
+ < 533330 1525>,
+ < 800000 1525>,
+ < 998400 3051>,
+ < 1094400 3051>,
+ < 1152000 4066>,
+ < 1209600 4066>;
+ };
+
+ qcom,sps {
+ compatible = "qcom,msm_sps_4k";
+ qcom,device-type = <3>;
+ qcom,pipe-attr-ee;
+ };
+
+ blsp1_uart1: uart@78af000 {
+ compatible = "qcom,msm-hsuart-v14";
+ reg = <0x78af000 0x200>,
+ <0x7884000 0x23000>;
+ reg-names = "core_mem", "bam_mem";
+ interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+ #address-cells = <0>;
+ interrupt-parent = <&blsp1_uart1>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 107 0
+ 1 &intc 0 238 0
+ 2 &msm_gpio 1 0>;
+
+ qcom,inject-rx-on-wakeup = <1>;
+ qcom,rx-char-to-inject = <0xFD>;
+
+ qcom,bam-tx-ep-pipe-index = <0>;
+ qcom,bam-rx-ep-pipe-index = <1>;
+ qcom,master-id = <86>;
+
+ clocks = <&clock_gcc clk_gcc_blsp1_uart1_apps_clk>,
+ <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+ clock-names = "core_clk", "iface_clk";
+
+ qcom,msm-bus,name = "blsp1_uart1";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <86 512 0 0>,
+ <86 512 500 800>;
+ pinctrl-names = "sleep", "default";
+ pinctrl-0 = <&hsuart_sleep>;
+ pinctrl-1 = <&hsuart_active>;
+ status = "disabled";
+ };
+
+ blsp1_uart2: serial@78b0000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0x78b0000 0x200>;
+ interrupts = <0 108 0>;
+ status = "disabled";
+ clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+ <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+ clock-names = "core_clk", "iface_clk";
+ };
+
+ rmtfs_sharedmem {
+ compatible = "qcom,sharedmem-uio";
+ reg = <0x86700000 0xe0000>;
+ reg-names = "rmtfs";
+ };
+
+ dsp_sharedmem {
+ compatible = "qcom,sharedmem-uio";
+ reg = <0x867e0000 0x20000>;
+ reg-names = "rfsa_dsp";
+ };
+
+ mdm_sharedmem {
+ compatible = "qcom,sharedmem-uio";
+ reg = <0x867e0000 0x20000>;
+ reg-names = "rfsa_mdm";
+ };
+
+ jtag_fuse: jtagfuse@5e01c {
+ compatible = "qcom,jtag-fuse";
+ reg = <0x5e01c 0x8>;
+ reg-names = "fuse-base";
+ };
+
+ sdhc_1: sdhci@07824000 {
+ compatible = "qcom,sdhci-msm";
+ reg = <0x07824900 0x11c>, <0x07824000 0x800>;
+ reg-names = "hc_mem", "core_mem";
+
+ interrupts = <0 123 0>, <0 138 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <8>;
+
+ qcom,cpu-dma-latency-us = <701>;
+ qcom,msm-bus,name = "sdhc1";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+ <78 512 1600 3200>, /* 400 KB/s*/
+ <78 512 80000 160000>, /* 20 MB/s */
+ <78 512 100000 200000>, /* 25 MB/s */
+ <78 512 200000 400000>, /* 50 MB/s */
+ <78 512 400000 800000>, /* 100 MB/s */
+ <78 512 400000 800000>, /* 200 MB/s */
+ <78 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+ clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>,
+ <&clock_gcc clk_gcc_sdcc1_apps_clk>;
+ clock-names = "iface_clk", "core_clk";
+
+ qcom,clk-rates = <400000 25000000 50000000 100000000 177770000>;
+ qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+
+ status = "disabled";
+ };
+
+ sdhc_2: sdhci@07864000 {
+ compatible = "qcom,sdhci-msm";
+ reg = <0x07864900 0x11c>, <0x07864000 0x800>;
+ reg-names = "hc_mem", "core_mem";
+
+ interrupts = <0 125 0>, <0 221 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ qcom,bus-width = <4>;
+
+ qcom,cpu-dma-latency-us = <701>;
+ qcom,msm-bus,name = "sdhc2";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+ <81 512 1600 3200>, /* 400 KB/s*/
+ <81 512 80000 160000>, /* 20 MB/s */
+ <81 512 100000 200000>, /* 25 MB/s */
+ <81 512 200000 400000>, /* 50 MB/s */
+ <81 512 400000 800000>, /* 100 MB/s */
+ <81 512 400000 800000>, /* 200 MB/s */
+ <81 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+ clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>,
+ <&clock_gcc clk_gcc_sdcc2_apps_clk>;
+ clock-names = "iface_clk", "core_clk";
+
+ qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+
+ status = "disabled";
+ };
+
+ qcom,ipc-spinlock@1905000 {
+ compatible = "qcom,ipc-spinlock-sfpb";
+ reg = <0x1905000 0x8000>;
+ qcom,num-locks = <8>;
+ };
+
+ qcom,smem@86300000 {
+ compatible = "qcom,smem";
+ reg = <0x86300000 0x100000>,
+ <0x0b011008 0x4>,
+ <0x60000 0x8000>,
+ <0x193D000 0x8>;
+ reg-names = "smem", "irq-reg-base", "aux-mem1", "smem_targ_info_reg";
+ qcom,mpu-enabled;
+
+ qcom,smd-modem {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <0>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x1000>;
+ qcom,pil-string = "modem";
+ interrupts = <0 25 1>;
+ };
+
+ qcom,smsm-modem {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <0>;
+ qcom,smsm-irq-offset = <0x0>;
+ qcom,smsm-irq-bitmask = <0x2000>;
+ interrupts = <0 26 1>;
+ };
+
+ qcom,smd-wcnss {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <6>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x20000>;
+ qcom,pil-string = "wcnss";
+ interrupts = <0 142 1>;
+ };
+
+ qcom,smsm-wcnss {
+ compatible = "qcom,smsm";
+ qcom,smsm-edge = <6>;
+ qcom,smsm-irq-offset = <0x0>;
+ qcom,smsm-irq-bitmask = <0x80000>;
+ interrupts = <0 144 1>;
+ };
+
+ qcom,smd-rpm {
+ compatible = "qcom,smd";
+ qcom,smd-edge = <15>;
+ qcom,smd-irq-offset = <0x0>;
+ qcom,smd-irq-bitmask = <0x1>;
+ interrupts = <0 168 1>;
+ qcom,irq-no-suspend;
+ };
+ };
+
+ rpm_bus: qcom,rpm-smd {
+ compatible = "qcom,rpm-smd";
+ rpm-channel-name = "rpm_requests";
+ rpm-channel-type = <15>; /* SMD_APPS_RPM */
+ };
+
+ qcom,bam_dmux@4044000 {
+ compatible = "qcom,bam_dmux";
+ reg = <0x4044000 0x19000>;
+ interrupts = <0 29 1>;
+ qcom,rx-ring-size = <32>;
+ };
+
+ qcom_tzlog: tz-log@8600720 {
+ compatible = "qcom,tz-log";
+ reg = <0x08600720 0x1000>;
+ status = "disabled";
+ };
+
+ qcom,smdtty {
+ compatible = "qcom,smdtty";
+
+ smdtty_apps_fm: qcom,smdtty-apps-fm {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_FM";
+ };
+
+ smdtty_apps_riva_bt_acl: smdtty-apps-riva-bt-acl {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_BT_ACL";
+ };
+
+ smdtty_apps_riva_bt_cmd: qcom,smdtty-apps-riva-bt-cmd {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_BT_CMD";
+ };
+
+ smdtty_mbalbridge: qcom,smdtty-mbalbridge {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "MBALBRIDGE";
+ };
+
+ smdtty_apps_riva_ant_cmd: smdtty-apps-riva-ant-cmd {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_ANT_CMD";
+ };
+
+ smdtty_apps_riva_ant_data: smdtty-apps-riva-ant-data {
+ qcom,smdtty-remote = "wcnss";
+ qcom,smdtty-port-name = "APPS_RIVA_ANT_DATA";
+ };
+
+ smdtty_data1: qcom,smdtty-data1 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA1";
+ };
+
+ smdtty_data4: qcom,smdtty-data4 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA4";
+ };
+
+ smdtty_data11: qcom,smdtty-data11 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA11";
+ };
+
+ smdtty_data21: qcom,smdtty-data21 {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "DATA21";
+ };
+
+ smdtty_loopback: smdtty-loopback {
+ qcom,smdtty-remote = "modem";
+ qcom,smdtty-port-name = "LOOPBACK";
+ qcom,smdtty-dev-name = "LOOPBACK_TTY";
+ };
+ };
+
+ qcom,smdpkt {
+ compatible = "qcom,smdpkt";
+
+ qcom,smdpkt-data5-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA5_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl0";
+ };
+
+ qcom,smdpkt-data6-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA6_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl1";
+ };
+
+ qcom,smdpkt-data7-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA7_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl2";
+ };
+
+ qcom,smdpkt-data8-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA8_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl3";
+ };
+
+ qcom,smdpkt-data9-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA9_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl4";
+ };
+
+ qcom,smdpkt-data12-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA12_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl5";
+ };
+
+ qcom,smdpkt-data13-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA13_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl6";
+ };
+
+ qcom,smdpkt-data14-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA14_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl7";
+ };
+
+ qcom,smdpkt-data15-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA15_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl9";
+ };
+
+ qcom,smdpkt-data16-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA16_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl10";
+ };
+
+ qcom,smdpkt-data17-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA17_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl11";
+ };
+
+ qcom,smdpkt-data22 {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA22";
+ qcom,smdpkt-dev-name = "smd22";
+ };
+
+ qcom,smdpkt-data23-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA23_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev0";
+ };
+
+ qcom,smdpkt-data24-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA24_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev1";
+ };
+
+ qcom,smdpkt-data25-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA25_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev2";
+ };
+
+ qcom,smdpkt-data26-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA26_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev3";
+ };
+
+ qcom,smdpkt-data27-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA27_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev4";
+ };
+
+ qcom,smdpkt-data28-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA28_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev5";
+ };
+
+ qcom,smdpkt-data29-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA29_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev6";
+ };
+
+ qcom,smdpkt-data30-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA30_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev7";
+ };
+
+ qcom,smdpkt-data31-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA31_CNTL";
+ qcom,smdpkt-dev-name = "smdcnt_rev8";
+ };
+
+ qcom,smdpkt-data40-cntl {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "DATA40_CNTL";
+ qcom,smdpkt-dev-name = "smdcntl8";
+ };
+
+ qcom,smdpkt-apr-apps2 {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "apr_apps2";
+ qcom,smdpkt-dev-name = "apr_apps2";
+ };
+
+ qcom,smdpkt-loopback {
+ qcom,smdpkt-remote = "modem";
+ qcom,smdpkt-port-name = "LOOPBACK";
+ qcom,smdpkt-dev-name = "smd_pkt_loopback";
+ };
+ };
+
+
+ spmi_bus: qcom,spmi@200f000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x200f000 0x1000>,
+ <0x2400000 0x400000>,
+ <0x2c00000 0x400000>,
+ <0x3800000 0x200000>,
+ <0x200a000 0x2100>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupts = <0 190 0>;
+ qcom,pmic-arb-channel = <0>;
+ qcom,pmic-arb-ee = <0>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cell-index = <0>;
+ };
+
+ qcom,msm-imem@8600000 {
+ compatible = "qcom,msm-imem";
+ reg = <0x08600000 0x1000>; /* Address and size of IMEM */
+ ranges = <0x0 0x08600000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mem_dump_table@10 {
+ compatible = "qcom,msm-imem-mem_dump_table";
+ reg = <0x10 8>;
+ };
+
+ restart_reason@65c {
+ compatible = "qcom,msm-imem-restart_reason";
+ reg = <0x65c 4>;
+ };
+
+ boot_stats@6b0 {
+ compatible = "qcom,msm-imem-boot_stats";
+ reg = <0x6b0 32>;
+ };
+
+ pil@94c {
+ compatible = "qcom,msm-imem-pil";
+ reg = <0x94c 200>;
+ };
+ };
+
+ qcom,memshare {
+ compatible = "qcom,memshare";
+ };
+
+ cpu-pmu {
+ compatible = "arm,armv8-pmuv3";
+ qcom,irq-is-percpu;
+ interrupts = <1 7 0xf00>;
+ };
+
+};
+
+// AG 2014-11-29 without this, +40mA idle
+
+&gdsc_mdss {
+ status = "okay";
+};
+
+
+#include "msm-pm8916-rpm-regulator.dtsi"
+#include "msm-pm8916.dtsi"
+#include "msm8916-regulator.dtsi"
+#include "msm8916-pm.dtsi"
diff --git a/arch/arm/boot/dts/skeleton.dtsi b/arch/arm/boot/dts/skeleton.dtsi
index b41d241de2cd..f9988cd78c6a 100644
--- a/arch/arm/boot/dts/skeleton.dtsi
+++ b/arch/arm/boot/dts/skeleton.dtsi
@@ -9,5 +9,10 @@
#size-cells = <1>;
chosen { };
aliases { };
- memory { device_type = "memory"; reg = <0 0>; };
+ memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ device_type = "memory";
+ reg = <0 0>;
+ };
};
diff --git a/arch/arm/configs/msm8916-qrd-andy_defconfig b/arch/arm/configs/msm8916-qrd-andy_defconfig
new file mode 100644
index 000000000000..4282e4b6b5f6
--- /dev/null
+++ b/arch/arm/configs/msm8916-qrd-andy_defconfig
@@ -0,0 +1,121 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+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_MSM8916=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_SMP=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_CMA=y
+CONFIG_CP_ACCESS=y
+CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES="msm8916-qrd-skui"
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="console=ttyHSL0,115200,n8"
+CONFIG_ARM_DECOMPRESSOR_LIMIT=0x3200000
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=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_AH=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=1024
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=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_EXT4_FS_SECURITY=y
+CONFIG_FUSE_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_UART_PHYS=0x078B0000
+CONFIG_DEBUG_UART_VIRT=0xFA0B0000
+CONFIG_EARLY_PRINTK=y
+CONFIG_KEYS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 10e78d00a0bb..5e4f2278242e 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -94,6 +94,21 @@
* DMA Cache Coherency
* ===================
*
+ * dma_inv_range(start, end)
+ *
+ * Invalidate (discard) the specified virtual address range.
+ * May not write back any entries. If 'start' or 'end'
+ * are not cache line aligned, those lines must be written
+ * back.
+ * - start - virtual start address
+ * - end - virtual end address
+ *
+ * dma_clean_range(start, end)
+ *
+ * Clean (write back) the specified virtual address range.
+ * - start - virtual start address
+ * - end - virtual end address
+ *
* dma_flush_range(start, end)
*
* Clean and invalidate the specified virtual address range.
@@ -115,6 +130,8 @@ struct cpu_cache_fns {
void (*dma_map_area)(const void *, size_t, int);
void (*dma_unmap_area)(const void *, size_t, int);
+ void (*dma_inv_range)(const void *, const void *);
+ void (*dma_clean_range)(const void *, const void *);
void (*dma_flush_range)(const void *, const void *);
};
@@ -142,6 +159,8 @@ extern struct cpu_cache_fns cpu_cache;
*/
#define dmac_map_area cpu_cache.dma_map_area
#define dmac_unmap_area cpu_cache.dma_unmap_area
+#define dmac_inv_range cpu_cache.dma_inv_range
+#define dmac_clean_range cpu_cache.dma_clean_range
#define dmac_flush_range cpu_cache.dma_flush_range
#else
@@ -163,6 +182,8 @@ extern void __cpuc_flush_dcache_area(void *, size_t);
*/
extern void dmac_map_area(const void *, size_t, int);
extern void dmac_unmap_area(const void *, size_t, int);
+extern void dmac_inv_range(const void *, const void *);
+extern void dmac_clean_range(const void *, const void *);
extern void dmac_flush_range(const void *, const void *);
#endif
@@ -489,4 +510,12 @@ int set_memory_nx(unsigned long addr, int numpages);
void flush_uprobe_xol_access(struct page *page, unsigned long uaddr,
void *kaddr, unsigned long len);
+#ifdef CONFIG_FREE_PAGES_RDONLY
+#define mark_addr_rdonly(a) set_memory_ro((unsigned long)a, 1);
+#define mark_addr_rdwrite(a) set_memory_rw((unsigned long)a, 1);
+#else
+#define mark_addr_rdonly(a)
+#define mark_addr_rdwrite(a)
+#endif
+
#endif
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 819777d0e91f..867fa5bbc64d 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -61,6 +61,7 @@
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_IMP_INTEL 0x69
+#define ARM_CPU_IMP_QUALCOMM 0x51
/* ARM implemented processors */
#define ARM_CPU_PART_ARM1136 0x4100b360
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h
index dc662fca9230..866f027e5e7c 100644
--- a/arch/arm/include/asm/device.h
+++ b/arch/arm/include/asm/device.h
@@ -25,6 +25,7 @@ struct pdev_archdata {
#ifdef CONFIG_ARCH_OMAP
struct omap_device *od;
#endif
+ u64 dma_mask;
};
#ifdef CONFIG_ARM_DMA_USE_IOMMU
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 85738b200023..b85ecbf3b719 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -189,6 +189,39 @@ extern int dma_supported(struct device *dev, u64 mask);
extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);
+/*
+ * dma_coherent_pre_ops - barrier functions for coherent memory before DMA.
+ * A barrier is required to ensure memory operations are complete before the
+ * initiation of a DMA xfer.
+ * If the coherent memory is Strongly Ordered
+ * - pre ARMv7 and 8x50 guarantees ordering wrt other mem accesses
+ * - ARMv7 guarantees ordering only within a 1KB block, so we need a barrier
+ * If coherent memory is normal then we need a barrier to prevent
+ * reordering
+ */
+static inline void dma_coherent_pre_ops(void)
+{
+#if COHERENT_IS_NORMAL == 1
+ dmb();
+#else
+ barrier();
+#endif
+}
+/*
+ * dma_post_coherent_ops - barrier functions for coherent memory after DMA.
+ * If the coherent memory is Strongly Ordered we dont need a barrier since
+ * there are no speculative fetches to Strongly Ordered memory.
+ * If coherent memory is normal then we need a barrier to prevent reordering
+ */
+static inline void dma_coherent_post_ops(void)
+{
+#if COHERENT_IS_NORMAL == 1
+ dmb();
+#else
+ barrier();
+#endif
+}
+
/**
* arm_dma_alloc - allocate consistent memory for DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -264,6 +297,72 @@ static inline void dma_free_attrs(struct device *dev, size_t size,
extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
struct dma_attrs *attrs);
+#if 0
+static inline void *dma_alloc_writecombine(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ return dma_alloc_attrs(dev, size, dma_handle, flag, &attrs);
+}
+
+static inline void dma_free_writecombine(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
+}
+#endif
+static inline void *dma_alloc_stronglyordered(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs);
+ return dma_alloc_attrs(dev, size, dma_handle, flag, &attrs);
+}
+
+static inline void dma_free_stronglyordered(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs);
+ return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
+}
+
+static inline int dma_mmap_stronglyordered(struct device *dev,
+ struct vm_area_struct *vma, void *cpu_addr,
+ dma_addr_t dma_addr, size_t size)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs);
+ return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
+}
+
+static inline void *dma_alloc_nonconsistent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
+ return dma_alloc_attrs(dev, size, dma_handle, flag, &attrs);
+}
+
+static inline void dma_free_nonconsistent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
+ return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
+}
+
+static inline int dma_mmap_nonconsistent(struct device *dev,
+ struct vm_area_struct *vma, void *cpu_addr,
+ dma_addr_t dma_addr, size_t size)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_NON_CONSISTENT, &attrs);
+ return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
+}
/*
* This can be called during early boot to increase the size of the atomic
@@ -311,7 +410,55 @@ extern int dmabounce_register_dev(struct device *, unsigned long,
*/
extern void dmabounce_unregister_dev(struct device *);
+/**
+ * dma_cache_pre_ops - clean or invalidate cache before dma transfer is
+ * initiated and perform a barrier operation.
+ * @virtual_addr: A kernel logical or kernel virtual address
+ * @size: size of buffer to map
+ * @dir: DMA transfer direction
+ *
+ * Ensure that any data held in the cache is appropriately discarded
+ * or written back.
+ *
+ */
+static inline void dma_cache_pre_ops(void *virtual_addr,
+ size_t size, enum dma_data_direction dir)
+{
+ extern void ___dma_single_cpu_to_dev(const void *, size_t,
+ enum dma_data_direction);
+
+ BUG_ON(!valid_dma_direction(dir));
+
+ ___dma_single_cpu_to_dev(virtual_addr, size, dir);
+}
+/**
+ * dma_cache_post_ops - clean or invalidate cache after dma transfer is
+ * initiated and perform a barrier operation.
+ * @virtual_addr: A kernel logical or kernel virtual address
+ * @size: size of buffer to map
+ * @dir: DMA transfer direction
+ *
+ * Ensure that any data held in the cache is appropriately discarded
+ * or written back.
+ *
+ */
+static inline void dma_cache_post_ops(void *virtual_addr,
+ size_t size, enum dma_data_direction dir)
+{
+ extern void ___dma_single_cpu_to_dev(const void *, size_t,
+ enum dma_data_direction);
+
+ BUG_ON(!valid_dma_direction(dir));
+
+ if (arch_has_speculative_dfetch() && dir != DMA_TO_DEVICE)
+ /*
+ * Treat DMA_BIDIRECTIONAL and DMA_FROM_DEVICE
+ * identically: invalidate
+ */
+ ___dma_single_cpu_to_dev(virtual_addr,
+ size, DMA_FROM_DEVICE);
+}
/*
* The scatter list versions of the above methods.
diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h
index 6ddbe446425e..d5924f65637d 100644
--- a/arch/arm/include/asm/domain.h
+++ b/arch/arm/include/asm/domain.h
@@ -31,8 +31,13 @@
*
* 36-bit addressing and supersections are only available on
* CPUs based on ARMv6+ or the Intel XSC3 core.
+ *
+ * We cannot use domain 0 for the kernel on QSD8x50 since the kernel domain
+ * is set to manager mode when set_fs(KERNEL_DS) is called. Setting domain 0
+ * to manager mode will disable the workaround for a cpu bug that can cause an
+ * invalid fault status and/or tlb corruption (CONFIG_VERIFY_PERMISSION_FAULT).
*/
-#ifndef CONFIG_IO_36
+#if !defined(CONFIG_IO_36) && !defined(CONFIG_VERIFY_PERMISSION_FAULT)
#define DOMAIN_KERNEL 0
#define DOMAIN_TABLE 0
#define DOMAIN_USER 1
diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h
index a3c24cd5b7c8..2681262e5f9b 100644
--- a/arch/arm/include/asm/glue-cache.h
+++ b/arch/arm/include/asm/glue-cache.h
@@ -161,6 +161,8 @@ static inline void nop_dma_unmap_area(const void *s, size_t l, int f) { }
#define dmac_map_area __glue(_CACHE,_dma_map_area)
#define dmac_unmap_area __glue(_CACHE,_dma_unmap_area)
#define dmac_flush_range __glue(_CACHE,_dma_flush_range)
+#define dmac_inv_range __glue(_CACHE,_dma_inv_range)
+#define dmac_clean_range __glue(_CACHE,_dma_clean_range)
#endif
#endif
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 180567408ee8..2ea596dda249 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -100,6 +100,31 @@ static inline void __raw_writel(u32 val, volatile void __iomem *addr)
: "r" (val));
}
+static inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+ register u64 val asm ("r2");
+
+ asm volatile("ldrd %1, %0"
+ : "+Qo" (*(volatile u64 __force *)addr),
+ "=r" (val));
+ return val;
+}
+#define readq_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64) \
+ __raw_readq(c)); __r; })
+
+static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
+ {
+ register u64 v asm ("r2");
+
+ v = val;
+
+ asm volatile("strd %1, %0"
+ : "+Qo" (*(volatile u64 __force *)addr)
+ : "r" (v));
+ }
+
+
+
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
u8 val;
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 0406cb3f1af7..5b2619460fc1 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -54,6 +54,7 @@ struct machine_desc {
void (*init_meminfo)(void);
void (*reserve)(void);/* reserve mem blocks */
void (*map_io)(void);/* IO mapping function */
+ void (*init_very_early)(void);
void (*init_early)(void);
void (*init_irq)(void);
void (*init_time)(void);
diff --git a/arch/arm/include/asm/mach/flash.h b/arch/arm/include/asm/mach/flash.h
index 4ca69fe2c850..7ed96303419b 100644
--- a/arch/arm/include/asm/mach/flash.h
+++ b/arch/arm/include/asm/mach/flash.h
@@ -13,27 +13,36 @@
struct mtd_partition;
struct mtd_info;
+enum sw_version {
+ VERSION_1 = 0,
+ VERSION_2,
+};
+
/*
* map_name: the map probe function name
* name: flash device name (eg, as used with mtdparts=)
* width: width of mapped device
+ * interleave: interleave mode feature support
* init: method called at driver/device initialisation
* exit: method called at driver/device removal
* set_vpp: method called to enable or disable VPP
* mmcontrol: method called to enable or disable Sync. Burst Read in OneNAND
* parts: optional array of mtd_partitions for static partitioning
* nr_parts: number of mtd_partitions for static partitoning
+ * version: software register interface version
*/
struct flash_platform_data {
const char *map_name;
const char *name;
unsigned int width;
+ unsigned int interleave;
int (*init)(void);
void (*exit)(void);
void (*set_vpp)(int on);
void (*mmcontrol)(struct mtd_info *mtd, int sync_read);
struct mtd_partition *parts;
unsigned int nr_parts;
+ enum sw_version version;
};
#endif
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index f98c7f32c9c8..7c079ca16c02 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -36,6 +36,7 @@ enum {
MT_MEMORY_RWX_ITCM,
MT_MEMORY_RW_SO,
MT_MEMORY_DMA_READY,
+ MT_DEVICE_USER_ACCESSIBLE,
};
#ifdef CONFIG_MMU
@@ -57,6 +58,9 @@ extern const struct mem_type *get_mem_type(unsigned int type);
*/
extern int ioremap_page(unsigned long virt, unsigned long phys,
const struct mem_type *mtype);
+
+extern int ioremap_pages(unsigned long virt, unsigned long phys,
+ unsigned long size, const struct mem_type *mtype);
#else
#define iotable_init(map,num) do { } while (0)
#define vm_reserve_area_early(a,s,c) do { } while (0)
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index e731018869a7..6c8d731c2e5f 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -348,6 +348,12 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#define virt_addr_valid(kaddr) (((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory) \
&& pfn_valid(virt_to_pfn(kaddr)))
+/*
+ * Set if the architecture speculatively fetches data into cache.
+ */
+#ifndef arch_has_speculative_dfetch
+#define arch_has_speculative_dfetch() 0
+#endif
#endif
#include <asm-generic/memory_model.h>
diff --git a/arch/arm/include/asm/mmu_writeable.h b/arch/arm/include/asm/mmu_writeable.h
new file mode 100644
index 000000000000..8c64b7fac60d
--- /dev/null
+++ b/arch/arm/include/asm/mmu_writeable.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2011, 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 _MMU_WRITEABLE_H
+#define _MMU_WRITEABLE_H
+
+#ifdef CONFIG_STRICT_MEMORY_RWX
+void mem_text_writeable_spinlock(unsigned long *flags);
+void mem_text_address_writeable(unsigned long);
+void mem_text_address_restore(void);
+void mem_text_writeable_spinunlock(unsigned long *flags);
+#else
+static inline void mem_text_writeable_spinlock(unsigned long *flags) {};
+static inline void mem_text_address_writeable(unsigned long addr) {};
+static inline void mem_text_address_restore(void) {};
+static inline void mem_text_writeable_spinunlock(unsigned long *flags) {};
+#endif
+
+void mem_text_write_kernel_word(unsigned long *addr, unsigned long word);
+
+#endif
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index 4355f0ec44d6..06fa6d07b599 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -160,6 +160,11 @@ typedef struct page *pgtable_t;
extern int pfn_valid(unsigned long);
#endif
+#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
+extern int _early_pfn_valid(unsigned long);
+#define early_pfn_valid(pfn) (_early_pfn_valid(pfn))
+#endif
+
#include <asm/memory.h>
#endif /* !__ASSEMBLY__ */
diff --git a/arch/arm/include/asm/pgtable-3level-hwdef.h b/arch/arm/include/asm/pgtable-3level-hwdef.h
index 9fd61c72a33a..96ddaebaad56 100644
--- a/arch/arm/include/asm/pgtable-3level-hwdef.h
+++ b/arch/arm/include/asm/pgtable-3level-hwdef.h
@@ -52,6 +52,7 @@
#define PMD_SECT_AP_WRITE (_AT(pmdval_t, 0))
#define PMD_SECT_AP_READ (_AT(pmdval_t, 0))
#define PMD_SECT_AP1 (_AT(pmdval_t, 1) << 6)
+#define PMD_SECT_AP2 (_AT(pmdval_t, 1) << 7)
#define PMD_SECT_TEX(x) (_AT(pmdval_t, 0))
/*
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index a31ecdad4b59..a1977728cb1b 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -132,6 +132,8 @@
#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */
+#define L_PMD_S2_RDWR (_AT(pmdval_t, 3) << 6) /* HAP[2:1] */
+
/*
* Hyp-mode PL2 PTE definitions for LPAE.
*/
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 3b30062975b2..c0ee50d7f876 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -120,18 +120,32 @@ extern pgprot_t pgprot_s2_device;
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
#define pgprot_stronglyordered(prot) \
- __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
+
+#define pgprot_device(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_DEV_NONSHARED)
+
+#define pgprot_writethroughcache(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_WRITETHROUGH)
+
+#define pgprot_writebackcache(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_WRITEBACK)
+
+#define pgprot_writebackwacache(prot) \
+ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_WRITEALLOC)
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
#define pgprot_dmacoherent(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
#define __HAVE_PHYS_MEM_ACCESS_PROT
+#define COHERENT_IS_NORMAL 1
struct file;
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t vma_prot);
#else
#define pgprot_dmacoherent(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
+#define COHERENT_IS_NORMAL 0
#endif
#endif /* __ASSEMBLY__ */
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 8a1e8e995dae..b2c5d790840a 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -30,6 +30,9 @@
#define STACK_TOP_MAX TASK_SIZE
#endif
+extern unsigned int boot_reason;
+extern unsigned int cold_boot;
+
struct debug_info {
#ifdef CONFIG_HAVE_HW_BREAKPOINT
struct perf_event *hbp[ARM_MAX_HBP_SLOTS];
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
index e0adb9f1bf94..5eb31adc2833 100644
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -21,6 +21,37 @@
#define __tagtable(tag, fn) \
static const struct tagtable __tagtable_##fn __tag = { tag, fn }
+/*
+ * Memory map description
+ */
+#if !defined(NR_BANKS)
+#define NR_BANKS 16
+#endif
+
+struct membank {
+ phys_addr_t start;
+ phys_addr_t size;
+ unsigned int highmem;
+};
+
+struct meminfo {
+ int nr_banks;
+ struct membank bank[NR_BANKS];
+};
+
+extern struct meminfo meminfo;
+
+#define for_each_bank(iter,mi) \
+ for (iter = 0; iter < (mi)->nr_banks; iter++)
+
+#define bank_pfn_start(bank) __phys_to_pfn((bank)->start)
+#define bank_pfn_end(bank) (__phys_to_pfn((bank)->start) + \
+ __phys_to_pfn((bank)->size))
+#define bank_pfn_size(bank) ((bank)->size >> PAGE_SHIFT)
+#define bank_phys_start(bank) (bank)->start
+#define bank_phys_end(bank) ((bank)->start + (bank)->size)
+#define bank_phys_size(bank) (bank)->size
+
extern int arm_add_memory(u64 start, u64 size);
extern void early_print(const char *str, ...);
extern void dump_machine_table(void);
diff --git a/arch/arm/include/asm/smcmod.h b/arch/arm/include/asm/smcmod.h
new file mode 100644
index 000000000000..6225c1e78421
--- /dev/null
+++ b/arch/arm/include/asm/smcmod.h
@@ -0,0 +1,165 @@
+/* Qualcomm SMC Module API */
+
+#ifndef __SMCMOD_H_
+#define __SMCMOD_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define SMCMOD_DEV "smcmod"
+
+#define SMCMOD_REG_REQ_MAX_ARGS 2
+
+/**
+ * struct smcmod_reg_req - for SMC register ioctl request
+ *
+ * @service_id - requested service.
+ * @command_id - requested command.
+ * @num_args - number of arguments.
+ * @args - argument(s) to be passed to the secure world.
+ * @return_val - return value from secure world operation.
+ */
+struct smcmod_reg_req {
+ uint32_t service_id; /* in */
+ uint32_t command_id; /* in */
+ uint8_t num_args; /* in */
+ uint32_t args[SMCMOD_REG_REQ_MAX_ARGS]; /* in */
+ uint32_t return_val; /* out */
+};
+
+/**
+ * struct smcmod_buf_req - for SMC buffer ioctl request
+ *
+ * @service_id - requested service.
+ * @command_id - requested command.
+ * @ion_cmd_fd - fd obtained from ION_IOC_MAP or ION_IOC_SHARE.
+ * @cmd_len - length of command data buffer in bytes.
+ * @ion_resp_fd - fd obtained from ION_IOC_MAP or ION_IOC_SHARE.
+ * @resp_len - length of response data buffer in bytes.
+ * @return_val - return value from secure world operation.
+ */
+struct smcmod_buf_req {
+ uint32_t service_id;/* in */
+ uint32_t command_id; /* in */
+ int32_t ion_cmd_fd; /* in */
+ uint32_t cmd_len; /* in */
+ int32_t ion_resp_fd; /* in */
+ uint32_t resp_len; /* in */
+ uint32_t return_val; /* out */
+};
+
+/**
+ * struct smcmod_cipher_req - for SMC cipher command ioctl
+ *
+ * @algorithm - specifies the cipher algorithm.
+ * @operation - specifies encryption or decryption.
+ * @mode - specifies cipher mode.
+ * @ion_key_fd - fd obtained form ION_IOC_MAP or ION_IOC_SHARE.
+ * @key_size - key size in bytes.
+ * @ion_plain_text_fd - fd obtained form ION_IOC_MAP or ION_IOC_SHARE.
+ * @plain_text_size - size of plain text in bytes.
+ * @ion_cipher_text_fd - fd obtained form ION_IOC_MAP or ION_IOC_SHARE.
+ * @cipher_text_size - cipher text size in bytes.
+ * @ion_init_vector_fd - fd obtained form ION_IOC_MAP or ION_IOC_SHARE.
+ * @init_vector_size - size of initialization vector in bytes.
+ * @key_is_null - indicates that the key is null.
+ * @return_val - return value from secure world opreation.
+ */
+struct smcmod_cipher_req {
+ uint32_t algorithm; /* in */
+ uint32_t operation; /* in */
+ uint32_t mode; /* in */
+ int32_t ion_key_fd; /* in */
+ uint32_t key_size; /* in */
+ int32_t ion_plain_text_fd; /* in (encrypt)/out (decrypt) */
+ uint32_t plain_text_size; /* in */
+ int32_t ion_cipher_text_fd; /* out (encrypt)/in (decrypt) */
+ uint32_t cipher_text_size; /* in */
+ int32_t ion_init_vector_fd; /* in */
+ uint32_t init_vector_size; /* in */
+ uint32_t key_is_null; /* in */
+ uint32_t return_val; /* out */
+};
+
+/**
+ * struct smcmod_msg_digest_req - for message digest command ioctl
+ *
+ * @algorithm - specifies the cipher algorithm.
+ * @ion_key_fd - fd obtained form ION_IOC_MAP or ION_IOC_SHARE.
+ * @key_size - hash key size in bytes.
+ * @ion_input_fd - fd obtained form ION_IOC_MAP or ION_IOC_SHARE.
+ * @input_size - input data size in bytes.
+ * @ion_output_fd - fd obtained form ION_IOC_MAP or ION_IOC_SHARE.
+ * @output_size - size of output buffer in bytes.
+ * @fixed_block - indicates whether this is a fixed block digest.
+ * @key_is_null - indicates that the key is null.
+ * @return_val - return value from secure world opreation.
+ */
+struct smcmod_msg_digest_req {
+ uint32_t algorithm; /* in */
+ int32_t ion_key_fd; /* in */
+ uint32_t key_size; /* in */
+ int32_t ion_input_fd; /* in */
+ uint32_t input_size; /* in */
+ int32_t ion_output_fd; /* in/out */
+ uint32_t output_size; /* in */
+ uint32_t fixed_block; /* in */
+ uint32_t key_is_null; /* in */
+ uint32_t return_val; /* out */
+} __packed;
+
+/**
+ * struct smcmod_decrypt_req - used to decrypt image fragments.
+ * @service_id - requested service.
+ * @command_id - requested command.
+ * @operation - specifies metadata parsing or image fragment decrypting.
+ * @request - describes request parameters depending on operation.
+ * @response - this is the response of the request.
+ */
+struct smcmod_decrypt_req {
+ uint32_t service_id;
+ uint32_t command_id;
+#define SMCMOD_DECRYPT_REQ_OP_METADATA 1
+#define SMCMOD_DECRYPT_REQ_OP_IMG_FRAG 2
+ uint32_t operation;
+ union {
+ struct {
+ uint32_t len;
+ uint32_t ion_fd;
+ } metadata;
+ struct {
+ uint32_t ctx_id;
+ uint32_t last_frag;
+ uint32_t frag_len;
+ uint32_t ion_fd;
+ uint32_t offset;
+ } img_frag;
+ } request;
+ union {
+ struct {
+ uint32_t status;
+ uint32_t ctx_id;
+ uint32_t end_offset;
+ } metadata;
+ struct {
+ uint32_t status;
+ } img_frag;
+ } response;
+};
+
+#define SMCMOD_IOC_MAGIC 0x97
+
+/* Number chosen to avoid any conflicts */
+#define SMCMOD_IOCTL_SEND_REG_CMD \
+ _IOWR(SMCMOD_IOC_MAGIC, 32, struct smcmod_reg_req)
+#define SMCMOD_IOCTL_SEND_BUF_CMD \
+ _IOWR(SMCMOD_IOC_MAGIC, 33, struct smcmod_buf_req)
+#define SMCMOD_IOCTL_SEND_CIPHER_CMD \
+ _IOWR(SMCMOD_IOC_MAGIC, 34, struct smcmod_cipher_req)
+#define SMCMOD_IOCTL_SEND_MSG_DIGEST_CMD \
+ _IOWR(SMCMOD_IOC_MAGIC, 35, struct smcmod_msg_digest_req)
+#define SMCMOD_IOCTL_GET_VERSION _IOWR(SMCMOD_IOC_MAGIC, 36, uint32_t)
+#define SMCMOD_IOCTL_SEND_DECRYPT_CMD \
+ _IOWR(SMCMOD_IOC_MAGIC, 37, struct smcmod_decrypt_req)
+
+#endif /* __SMCMOD_H_ */
diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 18f5a554134f..d9e2bacde208 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -80,6 +80,7 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask);
extern int register_ipi_completion(struct completion *completion, int cpu);
+extern void smp_send_all_cpu_backtrace(void);
struct smp_operations {
#ifdef CONFIG_SMP
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index ac4bfae26702..6a0826328286 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -7,21 +7,17 @@
#include <linux/prefetch.h>
+extern int msm_krait_need_wfe_fixup;
+
/*
* sev and wfe are ARMv6K extensions. Uniprocessor ARMv6 may not have the K
* extensions, so when running on UP, we have to patch these instructions away.
*/
#ifdef CONFIG_THUMB2_KERNEL
/*
- * For Thumb-2, special care is needed to ensure that the conditional WFE
- * instruction really does assemble to exactly 4 bytes (as required by
- * the SMP_ON_UP fixup code). By itself "wfene" might cause the
- * assembler to insert a extra (16-bit) IT instruction, depending on the
- * presence or absence of neighbouring conditional instructions.
- *
- * To avoid this unpredictableness, an approprite IT is inserted explicitly:
- * the assembler won't change IT instructions which are explicitly present
- * in the input.
+ * Both instructions given to the ALT_SMP macro need to be the same size, to
+ * allow the SMP_ON_UP fixups to function correctly. Hence the explicit encoding
+ * specifications.
*/
#define WFE(cond) __ALT_SMP_ASM( \
"it " cond "\n\t" \
@@ -33,6 +29,33 @@
#define WFE(cond) __ALT_SMP_ASM("wfe" cond, "nop")
#endif
+/*
+ * The fixup involves disabling FIQs during execution of the WFE instruction.
+ * This could potentially lead to deadlock if a thread is trying to acquire a
+ * spinlock which is being released from an FIQ. This should not be a problem
+ * because FIQs are handled by the secure environment and do not directly
+ * manipulate spinlocks.
+ */
+#ifdef CONFIG_MSM_KRAIT_WFE_FIXUP
+#define WFE_SAFE(fixup, tmp) \
+" mrs " tmp ", cpsr\n" \
+" cmp " fixup ", #0\n" \
+" wfeeq\n" \
+" beq 10f\n" \
+" cpsid f\n" \
+" mrc p15, 7, " fixup ", c15, c0, 5\n" \
+" bic " fixup ", " fixup ", #0x10000\n" \
+" mcr p15, 7, " fixup ", c15, c0, 5\n" \
+" isb\n" \
+" wfe\n" \
+" orr " fixup ", " fixup ", #0x10000\n" \
+" mcr p15, 7, " fixup ", c15, c0, 5\n" \
+" isb\n" \
+"10: msr cpsr_cf, " tmp "\n"
+#else
+#define WFE_SAFE(fixup, tmp) " wfe\n"
+#endif
+
#define SEV __ALT_SMP_ASM(WASM(sev), WASM(nop))
static inline void dsb_sev(void)
@@ -57,7 +80,7 @@ static inline void dsb_sev(void)
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
- unsigned long tmp;
+ unsigned long tmp, flags = 0;
u32 newval;
arch_spinlock_t lockval;
@@ -73,7 +96,33 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
: "cc");
while (lockval.tickets.next != lockval.tickets.owner) {
+ if (msm_krait_need_wfe_fixup) {
+ local_save_flags(flags);
+ local_fiq_disable();
+ __asm__ __volatile__(
+ "mrc p15, 7, %0, c15, c0, 5\n"
+ : "=r" (tmp)
+ :
+ : "cc");
+ tmp &= ~(0x10000);
+ __asm__ __volatile__(
+ "mcr p15, 7, %0, c15, c0, 5\n"
+ :
+ : "r" (tmp)
+ : "cc");
+ isb();
+ }
wfe();
+ if (msm_krait_need_wfe_fixup) {
+ tmp |= 0x10000;
+ __asm__ __volatile__(
+ "mcr p15, 7, %0, c15, c0, 5\n"
+ :
+ : "r" (tmp)
+ : "cc");
+ isb();
+ local_irq_restore(flags);
+ }
lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
}
@@ -140,17 +189,19 @@ static inline int arch_spin_is_contended(arch_spinlock_t *lock)
static inline void arch_write_lock(arch_rwlock_t *rw)
{
- unsigned long tmp;
+ unsigned long tmp, fixup = msm_krait_need_wfe_fixup;
prefetchw(&rw->lock);
__asm__ __volatile__(
-"1: ldrex %0, [%1]\n"
+"1: ldrex %0, [%2]\n"
" teq %0, #0\n"
- WFE("ne")
-" strexeq %0, %2, [%1]\n"
+" beq 2f\n"
+ WFE_SAFE("%1", "%0")
+"2:\n"
+" strexeq %0, %3, [%2]\n"
" teq %0, #0\n"
" bne 1b"
- : "=&r" (tmp)
+ : "=&r" (tmp), "+r" (fixup)
: "r" (&rw->lock), "r" (0x80000000)
: "cc");
@@ -211,17 +262,19 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)
*/
static inline void arch_read_lock(arch_rwlock_t *rw)
{
- unsigned long tmp, tmp2;
+ unsigned long tmp, tmp2, fixup = msm_krait_need_wfe_fixup;
prefetchw(&rw->lock);
__asm__ __volatile__(
-"1: ldrex %0, [%2]\n"
+"1: ldrex %0, [%3]\n"
" adds %0, %0, #1\n"
-" strexpl %1, %0, [%2]\n"
- WFE("mi")
+" strexpl %1, %0, [%3]\n"
+" bpl 2f\n"
+ WFE_SAFE("%2", "%0")
+"2:\n"
" rsbpls %0, %1, #0\n"
" bmi 1b"
- : "=&r" (tmp), "=&r" (tmp2)
+ : "=&r" (tmp), "=&r" (tmp2), "+r" (fixup)
: "r" (&rw->lock)
: "cc");
diff --git a/arch/arm/include/asm/system_misc.h b/arch/arm/include/asm/system_misc.h
index a3d61ad984af..062c48452148 100644
--- a/arch/arm/include/asm/system_misc.h
+++ b/arch/arm/include/asm/system_misc.h
@@ -21,6 +21,7 @@ extern void (*arm_pm_idle)(void);
#define UDBG_BUS (1 << 4)
extern unsigned int user_debug;
+extern char* (*arch_read_hardware_id)(void);
#endif /* !__ASSEMBLY__ */
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index def9e570199f..7c51bf6a2cba 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -519,7 +519,11 @@ static inline void __flush_tlb_kernel_page(unsigned long kaddr)
dsb(ishst);
__local_flush_tlb_kernel_page(kaddr);
+#ifdef CONFIG_ARCH_MSM8X60
+ tlb_op(TLB_V7_UIS_PAGE, "c8, c3, 3", kaddr);
+#else
tlb_op(TLB_V7_UIS_PAGE, "c8, c3, 1", kaddr);
+#endif
if (tlb_flag(TLB_BARRIER)) {
dsb(ish);
diff --git a/arch/arm/include/uapi/asm/posix_types.h b/arch/arm/include/uapi/asm/posix_types.h
index d2de9cbbcd9b..1db85c99abdd 100644
--- a/arch/arm/include/uapi/asm/posix_types.h
+++ b/arch/arm/include/uapi/asm/posix_types.h
@@ -22,6 +22,9 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
+typedef unsigned short __kernel_nlink_t;
+#define __kernel_nlink_t __kernel_nlink_t
+
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 38ddd9f83d0e..3e55f2ca818d 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -15,7 +15,7 @@ CFLAGS_REMOVE_return_address.o = -pg
# Object file lists.
-obj-y := elf.o entry-common.o irq.o opcodes.o \
+obj-y := elf.o entry-armv.o entry-common.o irq.o opcodes.o \
process.o ptrace.o return_address.o \
setup.o signal.o sigreturn_codes.o \
stacktrace.o sys_arm.o time.o traps.o
diff --git a/arch/arm/kernel/devtree.c b/arch/arm/kernel/devtree.c
index 11c54de9f8cf..1e93787a4b43 100644
--- a/arch/arm/kernel/devtree.c
+++ b/arch/arm/kernel/devtree.c
@@ -27,6 +27,22 @@
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+#ifndef CONFIG_ARM_LPAE
+ if (base > ((phys_addr_t)~0)) {
+ pr_crit("Ignoring memory at 0x%08llx due to lack of LPAE support\n",
+ base);
+ return;
+ }
+
+ if (size > ((phys_addr_t)~0))
+ size = ((phys_addr_t)~0);
+
+ /* arm_add_memory() already checks for the case of base + size > 4GB */
+#endif
+ arm_add_memory(base, size);
+}
#ifdef CONFIG_SMP
extern struct of_cpu_method __cpu_method_of_table[];
@@ -169,10 +185,14 @@ void __init arm_dt_init_cpu_maps(void)
* a reg property, the DT CPU list can be considered valid and the
* logical map created in smp_setup_processor_id() can be overridden
*/
- for (i = 0; i < cpuidx; i++) {
- set_cpu_possible(i, true);
- cpu_logical_map(i) = tmp_map[i];
- pr_debug("cpu logical map 0x%x\n", cpu_logical_map(i));
+ for (i = 0; i < nr_cpu_ids; i++) {
+ if (i < cpuidx) {
+ set_cpu_possible(i, true);
+ cpu_logical_map(i) = tmp_map[i];
+ pr_debug("cpu logical map 0x%x\n", cpu_logical_map(i));
+ } else {
+ set_cpu_possible(i, false);
+ }
}
}
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 2f5555d307b3..1135c24babac 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -832,6 +832,97 @@ ENDPROC(__switch_to)
.align 5
.globl __kuser_helper_start
__kuser_helper_start:
+#ifdef GENERIC_TIME_VSYSCALL
+/*
+ * Reference declaration:
+ *
+ * extern struct timezone __kernel_helper_gtod_timezone
+ * extern unsigned int __kernel_helper_gtod_seqnum
+ *
+ * Definition and user space usage example:
+ *
+ * #define __kernel_helper_gtod_timezone (*(unsigned int*)0xffff0f20)
+ * #define __kernel_helper_gtod_seqnum (*(unsigned int*)0xffff0f28)
+ *
+ * unsigned int prelock, postlock ;
+ * do {
+ * prelock = __kernel_helper_gtod_seqnum;
+ * memcpy(&tz, (void*)&(__kernel_helper_gtod_timezone),
+ * sizeof(struct timezone)) ;
+ * postlock = __kernel_helper_gtod_seqnum;
+ * } while (prelock != postlock);
+ *
+ * 0xffff0f20-3: tz_minuteswest
+ * 0xffff0f24-7: tz_dsttime
+ * 0xffff0f28-b: sequence #.
+ * 0xffff0f30-3: offset into CONFIG_USER_ACCESSIBLE_TIMER_BASE to get the timer.
+ * 0xffff0f34-7: Feature flag
+ * 0xffff0f38-b: wall-to-mononic: tv_sec
+ * 0xffff0f3c-f: wall-to-mononic: tv_nsec
+ */
+ .globl __kuser_gtod_timezone
+__kuser_gtod_timezone: @0xffff0f20
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ /* This offset is where the flag to enable the
+ * user accessible timers is located.
+ */
+ .word 0
+ .word 0
+ .word 0
+ .align 5
+
+/*
+ * Reference declaration:
+ *
+ * extern struct timeval __kernel_helper_gtod_timeval
+ * extern unsigned int __kernel_helper_gtod_seqnum
+ *
+ * Definition and user space usage example:
+ *
+ * #define __kernel_helper_gtod_timeval (*(unsigned int*)0xffff0f40)
+ * #define __kernel_helper_gtod_seqnum (*(unsigned int*)0xffff0f48)
+ *
+ * unsigned int prelock, postlock ;
+ * struct gtod {
+ * uint64_t cycle_last;
+ * uint64_t mask;
+ * uint32_t mult;
+ * uint32_t shift;
+ * uint32_t tv_sec;
+ * uint32_t tv_nsec;
+ * };
+ * struct gtod gdtod;
+ *
+ * do {
+ * prelock = __kernel_helper_gtod_seqnum;
+ * memcpy(&gdtod, (void*)&(__kernel_helper_gtod_timeval),
+ * sizeof(struct gtod)) ;
+ * postlock = __kernel_helper_gtod_seqnum;
+ * } while (prelock != postlock);
+ *
+ * 0xffff0f40-7: cycle_last
+ * 0xffff0f48-f: mask
+ * 0xffff0f50-3: mult
+ * 0xffff0f54-7: shift
+ * 0xffff0f58-b: tv_sec
+ * 0xffff0f5c-f: tv_nsec
+ */
+ .globl __kuser_gtod_timeval
+__kuser_gtod_timeval: @0xffff0f40
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .word 0
+ .align 5
+#endif
/*
* Due to the length of some sequences, __kuser_cmpxchg64 spans 2 regular
@@ -1032,7 +1123,7 @@ __kuser_helper_end:
* SP points to a minimal amount of processor-private memory, the address
* of which is copied into r0 for the mode specific abort handler.
*/
- .macro vector_stub, name, mode, correction=0
+ .macro vector_stub, name, mode, fixup, correction=0
.align 5
vector_\name:
@@ -1061,6 +1152,18 @@ vector_\name:
and lr, lr, #0x0f
THUMB( adr r0, 1f )
THUMB( ldr lr, [r0, lr, lsl #2] )
+ .if \fixup
+#ifdef CONFIG_MSM_KRAIT_WFE_FIXUP
+ ldr r0, .krait_fixup
+ ldr r0, [r0]
+ cmp r0, #0
+ beq 10f
+ mrc p15, 7, r0, c15, c0, 5
+ orr r0, r0, #0x10000
+ mcr p15, 7, r0, c15, c0, 5
+10: isb
+#endif
+ .endif
mov r0, sp
ARM( ldr lr, [pc, lr, lsl #2] )
movs pc, lr @ branch to handler in SVC mode
@@ -1085,7 +1188,7 @@ vector_rst:
/*
* Interrupt dispatcher
*/
- vector_stub irq, IRQ_MODE, 4
+ vector_stub irq, IRQ_MODE, 1, 4
.long __irq_usr @ 0 (USR_26 / USR_32)
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
@@ -1108,7 +1211,7 @@ vector_rst:
* Data abort dispatcher
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
*/
- vector_stub dabt, ABT_MODE, 8
+ vector_stub dabt, ABT_MODE, 0, 8
.long __dabt_usr @ 0 (USR_26 / USR_32)
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
@@ -1131,7 +1234,7 @@ vector_rst:
* Prefetch abort dispatcher
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
*/
- vector_stub pabt, ABT_MODE, 4
+ vector_stub pabt, ABT_MODE, 0, 4
.long __pabt_usr @ 0 (USR_26 / USR_32)
.long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
@@ -1154,7 +1257,7 @@ vector_rst:
* Undef instr entry dispatcher
* Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
*/
- vector_stub und, UND_MODE
+ vector_stub und, UND_MODE, 0
.long __und_usr @ 0 (USR_26 / USR_32)
.long __und_invalid @ 1 (FIQ_26 / FIQ_32)
@@ -1210,6 +1313,9 @@ vector_addrexcptn:
.long __fiq_svc @ e
.long __fiq_svc @ f
+.krait_fixup:
+ .word msm_krait_need_wfe_fixup
+
.globl vector_fiq_offset
.equ vector_fiq_offset, vector_fiq
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index b37752a96652..00b0d8e8949b 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -39,6 +39,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/seq_file.h>
#include <asm/cacheflush.h>
@@ -147,6 +148,11 @@ void disable_fiq(int fiq)
disable_irq(fiq + fiq_start);
}
+void fiq_set_type(int fiq, unsigned int type)
+{
+ irq_set_irq_type(fiq + FIQ_START, type);
+}
+
EXPORT_SYMBOL(set_fiq_handler);
EXPORT_SYMBOL(__set_fiq_regs); /* defined in fiqasm.S */
EXPORT_SYMBOL(__get_fiq_regs); /* defined in fiqasm.S */
@@ -154,6 +160,7 @@ EXPORT_SYMBOL(claim_fiq);
EXPORT_SYMBOL(release_fiq);
EXPORT_SYMBOL(enable_fiq);
EXPORT_SYMBOL(disable_fiq);
+EXPORT_SYMBOL(fiq_set_type);
void __init init_FIQ(int start)
{
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 664eee8c4a26..1a9d952636ee 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -467,6 +467,17 @@ ENTRY(__turn_mmu_on)
mrc p15, 0, r3, c0, c0, 0 @ read id reg
instr_sync
mov r3, r3
+#ifdef CONFIG_ARCH_MSM_KRAIT
+ movw r3, 0xff0d
+ movt r3, 0xffff
+ and r3, r9, r3
+ movw r4, 0x0400
+ movt r4, 0x511f
+ cmp r3, r4
+ mrceq p15, 7, r3, c15, c0, 2
+ biceq r3, r3, #0x400
+ mcreq p15, 7, r3, c15, c0, 2
+#endif
mov r3, r13
ret r3
__turn_mmu_on_end:
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index b5b452f90f76..6b35b54363e9 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -227,6 +227,17 @@ static int get_num_brps(void)
return core_has_mismatch_brps() ? brps - 1 : brps;
}
+/* Determine if halting mode is enabled */
+static int halting_mode_enabled(void)
+{
+ u32 dscr;
+ ARM_DBG_READ(c0, c1, 0, dscr);
+ WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
+ "halting debug mode enabled. "
+ "Unable to access hardware resources.\n");
+ return !!(dscr & ARM_DSCR_HDBGEN);
+}
+
/*
* In order to access the breakpoint/watchpoint control registers,
* we must be running in debug monitor mode. Unfortunately, we can
@@ -932,6 +943,17 @@ static void reset_ctrl_regs(void *unused)
u32 val;
/*
+ * Bail out without clearing the breakpoint registers if halting
+ * debug mode or monitor debug mode is enabled. Checking for monitor
+ * debug mode here ensures we don't clear the breakpoint registers
+ * across power collapse if save and restore code has already
+ * preserved the debug register values or they weren't lost and
+ * monitor mode was already enabled earlier.
+ */
+ if (halting_mode_enabled() || monitor_mode_enabled())
+ return;
+
+ /*
* v7 debug contains save and restore registers so that debug state
* can be maintained across low-power modes without leaving the debug
* logic powered up. It is IMPLEMENTATION DEFINED whether we can access
diff --git a/arch/arm/kernel/patch.c b/arch/arm/kernel/patch.c
index 07314af47733..7a27c47dad5b 100644
--- a/arch/arm/kernel/patch.c
+++ b/arch/arm/kernel/patch.c
@@ -5,6 +5,7 @@
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
#include <asm/opcodes.h>
+#include <asm/mmu_writeable.h>
#include "patch.h"
@@ -17,6 +18,10 @@ void __kprobes __patch_text(void *addr, unsigned int insn)
{
bool thumb2 = IS_ENABLED(CONFIG_THUMB2_KERNEL);
int size;
+ unsigned long flags;
+
+ mem_text_writeable_spinlock(&flags);
+ mem_text_address_writeable((unsigned long)addr);
if (thumb2 && __opcode_is_thumb16(insn)) {
*(u16 *)addr = __opcode_to_mem_thumb16(insn);
@@ -42,6 +47,9 @@ void __kprobes __patch_text(void *addr, unsigned int insn)
flush_icache_range((uintptr_t)(addr),
(uintptr_t)(addr) + size);
+
+ mem_text_address_restore();
+ mem_text_writeable_spinunlock(&flags);
}
static int __kprobes patch_text_stop_machine(void *data)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index c03106378b49..9ff5825b4e03 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -30,6 +30,7 @@
#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/sort.h>
+#include <linux/dma-mapping.h>
#include <asm/unified.h>
#include <asm/cp15.h>
@@ -77,7 +78,7 @@ extern void paging_init(const struct machine_desc *desc);
extern void early_paging_init(const struct machine_desc *,
struct proc_info_list *);
extern void sanity_check_meminfo(void);
-extern enum reboot_mode reboot_mode;
+//extern enum reboot_mode reboot_mode;
extern void setup_dma_zone(const struct machine_desc *desc);
unsigned int processor_id;
@@ -104,6 +105,14 @@ EXPORT_SYMBOL(elf_hwcap);
unsigned int elf_hwcap2 __read_mostly;
EXPORT_SYMBOL(elf_hwcap2);
+unsigned int boot_reason;
+EXPORT_SYMBOL(boot_reason);
+
+unsigned int cold_boot;
+EXPORT_SYMBOL(cold_boot);
+
+char* (*arch_read_hardware_id)(void);
+EXPORT_SYMBOL(arch_read_hardware_id);
#ifdef MULTI_CPU
struct processor processor __read_mostly;
@@ -890,6 +899,15 @@ void __init hyp_mode_check(void)
#endif
}
+#if 0
+static int __init meminfo_cmp(const void *_a, const void *_b)
+{
+ const struct membank *a = _a, *b = _b;
+ long cmp = bank_pfn_start(a) - bank_pfn_start(b);
+ return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
+}
+#endif
+
void __init setup_arch(char **cmdline_p)
{
const struct machine_desc *mdesc;
@@ -901,8 +919,9 @@ void __init setup_arch(char **cmdline_p)
machine_desc = mdesc;
machine_name = mdesc->name;
- if (mdesc->reboot_mode != REBOOT_HARD)
- reboot_mode = mdesc->reboot_mode;
+// if (mdesc->reboot_mode != REBOOT_HARD)
+// reboot_mode = mdesc->reboot_mode;
+ setup_dma_zone(mdesc);
init_mm.start_code = (unsigned long) _text;
init_mm.end_code = (unsigned long) _etext;
@@ -917,6 +936,10 @@ void __init setup_arch(char **cmdline_p)
early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
setup_dma_zone(mdesc);
+ if (mdesc->init_very_early)
+ mdesc->init_very_early();
+
+// sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL);
sanity_check_meminfo();
arm_memblock_init(mdesc);
@@ -942,6 +965,7 @@ void __init setup_arch(char **cmdline_p)
smp_build_mpidr_hash();
}
#endif
+ arm_dt_init_cpu_maps();
if (!is_smp())
hyp_mode_check();
@@ -1032,7 +1056,7 @@ static int c_show(struct seq_file *m, void *v)
int i, j;
u32 cpuid;
- for_each_online_cpu(i) {
+ for_each_present_cpu(i) {
/*
* glibc reads /proc/cpuinfo to determine the number of
* online processors, looking for lines beginning with
@@ -1077,10 +1101,15 @@ static int c_show(struct seq_file *m, void *v)
seq_printf(m, "CPU revision\t: %d\n\n", cpuid & 15);
}
- seq_printf(m, "Hardware\t: %s\n", machine_name);
+ if (!arch_read_hardware_id)
+ seq_printf(m, "Hardware\t: %s\n", machine_name);
+ else
+ seq_printf(m, "Hardware\t: %s\n", arch_read_hardware_id());
seq_printf(m, "Revision\t: %04x\n", system_rev);
seq_printf(m, "Serial\t\t: %08x%08x\n",
system_serial_high, system_serial_low);
+ seq_printf(m, "Processor\t: %s rev %d (%s)\n",
+ cpu_name, read_cpuid_id() & 15, elf_platform);
return 0;
}
@@ -1106,3 +1135,9 @@ const struct seq_operations cpuinfo_op = {
.stop = c_stop,
.show = c_show
};
+
+void arch_setup_pdev_archdata(struct platform_device *pdev)
+{
+ pdev->archdata.dma_mask = DMA_BIT_MASK(32);
+ pdev->dev.dma_mask = &pdev->archdata.dma_mask;
+}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 13396d3d600e..45f39d0a859f 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -26,6 +26,7 @@
#include <linux/completion.h>
#include <linux/cpufreq.h>
#include <linux/irq_work.h>
+#include <linux/smp.h>
#include <linux/atomic.h>
#include <asm/smp.h>
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 8e95aa47457a..2d2c9ad182c9 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -8,7 +8,10 @@
#include <asm/thread_info.h>
#include <asm/memory.h>
#include <asm/page.h>
-
+#ifdef CONFIG_STRICT_MEMORY_RWX
+#include <asm/pgtable.h>
+#endif
+
#define PROC_INFO \
. = ALIGN(4); \
VMLINUX_SYMBOL(__proc_info_begin) = .; \
@@ -90,6 +93,10 @@ SECTIONS
_text = .;
HEAD_TEXT
}
+#ifdef CONFIG_STRICT_MEMORY_RWX
+ . = ALIGN(1<<SECTION_SHIFT);
+#endif
+
.text : { /* Real text segment */
_stext = .; /* Text and read-only data */
__exception_text_start = .;
@@ -112,6 +119,9 @@ SECTIONS
ARM_CPU_KEEP(PROC_INFO)
}
+#ifdef CONFIG_STRICT_MEMORY_RWX
+ . = ALIGN(1<<SECTION_SHIFT);
+#endif
RO_DATA(PAGE_SIZE)
. = ALIGN(4);
@@ -145,7 +155,11 @@ SECTIONS
_etext = .; /* End of text and rodata section */
#ifndef CONFIG_XIP_KERNEL
+#ifdef CONFIG_STRICT_MEMORY_RWX
+ . = ALIGN(1<<SECTION_SHIFT);
+#else
. = ALIGN(PAGE_SIZE);
+#endif
__init_begin = .;
#endif
/*
@@ -173,6 +187,9 @@ SECTIONS
.init.proc.info : {
ARM_CPU_DISCARD(PROC_INFO)
}
+#ifdef CONFIG_STRICT_MEMORY_RWX
+ . = ALIGN(1<<SECTION_SHIFT);
+#endif
.init.arch.info : {
__arch_info_begin = .;
*(.arch.info.init)
@@ -202,6 +219,7 @@ SECTIONS
INIT_SETUP(16)
INIT_CALLS
CON_INITCALL
+ COMPAT_EXPORTS
SECURITY_INITCALL
INIT_RAM_FS
}
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 9b803a578b4d..dc20ebe76f63 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -1,3 +1,29 @@
- zreladdr-y += 0x10008000
-params_phys-y := 0x10000100
-initrd_phys-y := 0x10800000
+# MSM8974
+ zreladdr-$(CONFIG_ARCH_MSM8974) := 0x00008000
+
+# APQ8084
+ zreladdr-$(CONFIG_ARCH_APQ8084) := 0x00008000
+
+# MDM9630
+ zreladdr-$(CONFIG_ARCH_MDM9630) := 0x00008000
+
+# MSMZIRC
+ zreladdr-$(CONFIG_ARCH_MSMZIRC) := 0x80008000
+
+# MSM8226
+ zreladdr-$(CONFIG_ARCH_MSM8226) := 0x00008000
+
+# FSM9900
+ zreladdr-$(CONFIG_ARCH_FSM9900) := 0x11408000
+
+# MPQ8092
+ zreladdr-$(CONFIG_ARCH_MPQ8092) := 0x00008000
+
+# MSM8916
+ zreladdr-$(CONFIG_ARCH_MSM8916) := 0x80008000
+
+# MSM8610
+ zreladdr-$(CONFIG_ARCH_MSM8610) := 0x00008000
+
+# MSMSAMARIUM
+ zreladdr-$(CONFIG_ARCH_MSMSAMARIUM) := 0x00008000
diff --git a/arch/arm/mach-msm/board-8916.c b/arch/arm/mach-msm/board-8916.c
new file mode 100644
index 000000000000..65d6753d00d7
--- /dev/null
+++ b/arch/arm/mach-msm/board-8916.c
@@ -0,0 +1,128 @@
+/* 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 <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <asm/mach/arch.h>
+#include <soc/qcom/socinfo.h>
+#include <mach/board.h>
+#include <mach/msm_memtypes.h>
+// AGSTUB
+//#include <soc/qcom/rpm-smd.h>
+//#include <soc/qcom/smd.h>
+#include <soc/qcom/smem.h>
+// AGSTUB
+//#include <soc/qcom/spm.h>
+#include <soc/qcom/pm.h>
+#include "board-dt.h"
+#include "platsmp.h"
+
+static void __init msm8916_early_memory(void)
+{
+ of_scan_flat_dt(dt_scan_for_memory_hole, NULL);
+}
+
+static void __init msm8916_dt_reserve(void)
+{
+ of_scan_flat_dt(dt_scan_for_memory_reserve, NULL);
+}
+
+static void __init msm8916_map_io(void)
+{
+ msm_map_msm8916_io();
+}
+
+static struct of_dev_auxdata msm8916_auxdata_lookup[] __initdata = {
+ {}
+};
+
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init msm8916_add_drivers(void)
+{
+// msm_smd_init();
+// AGSTUB
+// msm_rpm_driver_init();
+// msm_spm_device_init();
+ msm_pm_sleep_status_init();
+}
+
+static void __init msm8916_init(void)
+{
+ struct of_dev_auxdata *adata = msm8916_auxdata_lookup;
+
+ /*
+ * populate devices from DT first so smem probe will get called as part
+ * of msm_smem_init. socinfo_init needs smem support so call
+ * msm_smem_init before it.
+ */
+ of_platform_populate(NULL, of_default_bus_match_table, adata, NULL);
+ msm_smem_init();
+
+ if (socinfo_init() < 0)
+ pr_err("%s: socinfo_init() failed\n", __func__);
+
+ msm8916_add_drivers();
+}
+
+static const char *msm8916_dt_match[] __initconst = {
+ "qcom,msm8916",
+ "qcom,apq8016",
+ NULL
+};
+
+static const char *msm8936_dt_match[] __initconst = {
+ "qcom,msm8936",
+ NULL
+};
+
+static const char *msm8939_dt_match[] __initconst = {
+ "qcom,msm8939",
+ NULL
+};
+
+DT_MACHINE_START(MSM8916_DT,
+ "Qualcomm Technologies, Inc. MSM 8916 (Flattened Device Tree)")
+ .map_io = msm8916_map_io,
+ .init_machine = msm8916_init,
+ .dt_compat = msm8916_dt_match,
+ .reserve = msm8916_dt_reserve,
+ .init_very_early = msm8916_early_memory,
+ .smp = &msm8916_smp_ops,
+MACHINE_END
+
+DT_MACHINE_START(MSM8939_DT,
+ "Qualcomm Technologies, Inc. MSM 8939 (Flattened Device Tree)")
+ .map_io = msm8916_map_io,
+ .init_machine = msm8916_init,
+ .dt_compat = msm8939_dt_match,
+ .reserve = msm8916_dt_reserve,
+ .smp = &msm8936_smp_ops,
+MACHINE_END
+
+DT_MACHINE_START(MSM8936_DT,
+ "Qualcomm Technologies, Inc. MSM 8936 (Flattened Device Tree)")
+ .map_io = msm8916_map_io,
+ .init_machine = msm8916_init,
+ .dt_compat = msm8936_dt_match,
+ .reserve = msm8916_dt_reserve,
+ .init_very_early = msm8916_early_memory,
+ .smp = &msm8936_smp_ops,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
new file mode 100644
index 000000000000..4016c4dac4c5
--- /dev/null
+++ b/arch/arm/mach-msm/board-dt.c
@@ -0,0 +1,31 @@
+/* Copyright (c) 2011-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 <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <soc/qcom/scm.h>
+#include <asm/mach/map.h>
+#include <mach/msm_iomap.h>
+
+#include "board-dt.h"
+
+void __init board_dt_populate(struct of_dev_auxdata *adata)
+{
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+ /* Explicitly parent the /soc devices to the root node to preserve
+ * the kernel ABI (sysfs structure, etc) until userspace is updated
+ */
+ of_platform_populate(of_find_node_by_path("/soc"),
+ of_default_bus_match_table, adata, NULL);
+}
diff --git a/arch/arm/mach-msm/board-dt.h b/arch/arm/mach-msm/board-dt.h
new file mode 100644
index 000000000000..33448947015a
--- /dev/null
+++ b/arch/arm/mach-msm/board-dt.h
@@ -0,0 +1,15 @@
+/* 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.
+ */
+
+#include <linux/of_platform.h>
+
+void __init board_dt_populate(struct of_dev_auxdata *adata);
diff --git a/arch/arm/mach-msm/boot_stats.c b/arch/arm/mach-msm/boot_stats.c
new file mode 100644
index 000000000000..4ebf722fd4b6
--- /dev/null
+++ b/arch/arm/mach-msm/boot_stats.c
@@ -0,0 +1,108 @@
+/* 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/smp.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/msm_iomap.h>
+
+struct boot_stats {
+ uint32_t bootloader_start;
+ uint32_t bootloader_end;
+ uint32_t bootloader_display;
+ uint32_t bootloader_load_kernel;
+};
+
+static void __iomem *mpm_counter_base;
+static uint32_t mpm_counter_freq;
+static struct boot_stats __iomem *boot_stats;
+
+static int mpm_parse_dt(void)
+{
+ struct device_node *np;
+ u32 freq;
+
+ np = of_find_compatible_node(NULL, NULL, "qcom,msm-imem-boot_stats");
+ if (!np) {
+ pr_err("can't find qcom,msm-imem node\n");
+ return -ENODEV;
+ }
+ boot_stats = of_iomap(np, 0);
+ if (!boot_stats) {
+ pr_err("boot_stats: Can't map imem\n");
+ return -ENODEV;
+ }
+
+ np = of_find_compatible_node(NULL, NULL, "qcom,mpm2-sleep-counter");
+ if (!np) {
+ pr_err("mpm_counter: can't find DT node\n");
+ return -ENODEV;
+ }
+
+ if (!of_property_read_u32(np, "clock-frequency", &freq))
+ mpm_counter_freq = freq;
+ else
+ return -ENODEV;
+
+ if (of_get_address(np, 0, NULL, NULL)) {
+ mpm_counter_base = of_iomap(np, 0);
+ if (!mpm_counter_base) {
+ pr_err("mpm_counter: cant map counter base\n");
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static void print_boot_stats(void)
+{
+ pr_info("KPI: Bootloader start count = %u\n",
+ readl_relaxed(&boot_stats->bootloader_start));
+ pr_info("KPI: Bootloader end count = %u\n",
+ readl_relaxed(&boot_stats->bootloader_end));
+ pr_info("KPI: Bootloader display count = %u\n",
+ readl_relaxed(&boot_stats->bootloader_display));
+ pr_info("KPI: Bootloader load kernel count = %u\n",
+ readl_relaxed(&boot_stats->bootloader_load_kernel));
+ pr_info("KPI: Kernel MPM timestamp = %u\n",
+ readl_relaxed(mpm_counter_base));
+ pr_info("KPI: Kernel MPM Clock frequency = %u\n",
+ mpm_counter_freq);
+}
+
+int boot_stats_init(void)
+{
+ int ret;
+
+ ret = mpm_parse_dt();
+ if (ret < 0)
+ return -ENODEV;
+
+ print_boot_stats();
+
+ iounmap(boot_stats);
+ iounmap(mpm_counter_base);
+
+ return 0;
+}
+
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
new file mode 100644
index 000000000000..33c51446802f
--- /dev/null
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -0,0 +1,670 @@
+/* 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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/cpu.h>
+#include <linux/seq_file.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <mach/msm-krait-l2-accessors.h>
+#include <mach/msm_iomap.h>
+#include <soc/qcom/socinfo.h>
+#include <asm/cputype.h>
+
+#define CESR_DCTPE BIT(0)
+#define CESR_DCDPE BIT(1)
+#define CESR_ICTPE BIT(2)
+#define CESR_ICDPE BIT(3)
+#define CESR_DCTE (BIT(4) | BIT(5))
+#define CESR_ICTE (BIT(6) | BIT(7))
+#define CESR_TLBMH BIT(16)
+#define CESR_I_MASK 0x000000CC
+
+#define CESR_VALID_MASK 0x000100FF
+
+/* Print a message for everything but TLB MH events */
+#define CESR_PRINT_MASK 0x000000FF
+
+/* Log everything but TLB MH events */
+#define CESR_LOG_EVENT_MASK 0x000000FF
+
+#define L2ESR_IND_ADDR 0x204
+#define L2ESYNR0_IND_ADDR 0x208
+#define L2ESYNR1_IND_ADDR 0x209
+#define L2EAR0_IND_ADDR 0x20C
+#define L2EAR1_IND_ADDR 0x20D
+
+#define L2ESR_MPDCD BIT(0)
+#define L2ESR_MPSLV BIT(1)
+#define L2ESR_TSESB BIT(2)
+#define L2ESR_TSEDB BIT(3)
+#define L2ESR_DSESB BIT(4)
+#define L2ESR_DSEDB BIT(5)
+#define L2ESR_MSE BIT(6)
+#define L2ESR_MPLDREXNOK BIT(8)
+
+#define L2ESR_ACCESS_ERR_MASK 0xFFFC
+
+#define L2ESR_CPU_MASK 0x0F
+#define L2ESR_CPU_SHIFT 16
+
+#ifdef CONFIG_MSM_L1_ERR_PANIC
+#define ERP_L1_ERR(a) panic(a)
+#else
+#define ERP_L1_ERR(a) do { } while (0)
+#endif
+
+#ifdef CONFIG_MSM_L1_RECOV_ERR_PANIC
+#define ERP_L1_RECOV_ERR(a) panic(a)
+#else
+#define ERP_L1_RECOV_ERR(a) do { } while (0)
+#endif
+
+#ifdef CONFIG_MSM_L2_ERP_PORT_PANIC
+#define ERP_PORT_ERR(a) panic(a)
+#else
+#define ERP_PORT_ERR(a) WARN(1, a)
+#endif
+
+#ifdef CONFIG_MSM_L2_ERP_1BIT_PANIC
+#define ERP_1BIT_ERR(a) panic(a)
+#else
+#define ERP_1BIT_ERR(a) do { } while (0)
+#endif
+
+#ifdef CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS
+#define print_access_errors() 1
+#else
+#define print_access_errors() 0
+#endif
+
+#ifdef CONFIG_MSM_L2_ERP_2BIT_PANIC
+#define ERP_2BIT_ERR(a) panic(a)
+#else
+#define ERP_2BIT_ERR(a) do { } while (0)
+#endif
+
+#define MODULE_NAME "msm_cache_erp"
+
+#define ERP_LOG_MAGIC_ADDR 0x6A4
+#define ERP_LOG_MAGIC 0x11C39893
+
+struct msm_l1_err_stats {
+ unsigned int dctpe;
+ unsigned int dcdpe;
+ unsigned int ictpe;
+ unsigned int icdpe;
+ unsigned int dcte;
+ unsigned int icte;
+ unsigned int tlbmh;
+};
+
+struct msm_l2_err_stats {
+ unsigned int mpdcd;
+ unsigned int mpslv;
+ unsigned int tsesb;
+ unsigned int tsedb;
+ unsigned int dsesb;
+ unsigned int dsedb;
+ unsigned int mse;
+ unsigned int mplxrexnok;
+};
+
+struct msm_erp_dump_region {
+ struct resource *res;
+ void __iomem *va;
+};
+
+static DEFINE_PER_CPU(struct msm_l1_err_stats, msm_l1_erp_stats);
+static struct msm_l2_err_stats msm_l2_erp_stats;
+
+static int l1_erp_irq, l2_erp_irq;
+static struct proc_dir_entry *procfs_entry;
+static int num_dump_regions;
+static struct msm_erp_dump_region *dump_regions;
+
+static void __iomem *msm_erp_log_base;
+
+#ifdef CONFIG_MSM_L1_ERR_LOG
+static struct proc_dir_entry *procfs_log_entry;
+#endif
+
+static inline unsigned int read_cesr(void)
+{
+ unsigned int cesr;
+ asm volatile ("mrc p15, 7, %0, c15, c0, 1" : "=r" (cesr));
+ return cesr;
+}
+
+static inline void write_cesr(unsigned int cesr)
+{
+ asm volatile ("mcr p15, 7, %[cesr], c15, c0, 1" : : [cesr]"r" (cesr));
+}
+
+static inline unsigned int read_cesynr(void)
+{
+ unsigned int cesynr;
+ asm volatile ("mrc p15, 7, %0, c15, c0, 3" : "=r" (cesynr));
+ return cesynr;
+}
+
+static int cache_erp_show(struct seq_file *m, void *v)
+{
+ struct msm_l1_err_stats *l1_stats;
+ int cpu;
+
+ for_each_present_cpu(cpu) {
+ l1_stats = &per_cpu(msm_l1_erp_stats, cpu);
+
+ seq_printf(m,
+ "CPU %d:\n"
+ "\tD-cache tag parity errors:\t%u\n"
+ "\tD-cache data parity errors:\t%u\n"
+ "\tI-cache tag parity errors:\t%u\n"
+ "\tI-cache data parity errors:\t%u\n"
+ "\tD-cache timing errors:\t\t%u\n"
+ "\tI-cache timing errors:\t\t%u\n"
+ "\tTLB multi-hit errors:\t\t%u\n\n",
+ cpu,
+ l1_stats->dctpe,
+ l1_stats->dcdpe,
+ l1_stats->ictpe,
+ l1_stats->icdpe,
+ l1_stats->dcte,
+ l1_stats->icte,
+ l1_stats->tlbmh);
+ }
+
+ seq_printf(m,
+ "L2 master port decode errors:\t\t%u\n"
+ "L2 master port slave errors:\t\t%u\n"
+ "L2 tag soft errors, single-bit:\t\t%u\n"
+ "L2 tag soft errors, double-bit:\t\t%u\n"
+ "L2 data soft errors, single-bit:\t%u\n"
+ "L2 data soft errors, double-bit:\t%u\n"
+ "L2 modified soft errors:\t\t%u\n"
+ "L2 master port LDREX NOK errors:\t%u\n",
+ msm_l2_erp_stats.mpdcd,
+ msm_l2_erp_stats.mpslv,
+ msm_l2_erp_stats.tsesb,
+ msm_l2_erp_stats.tsedb,
+ msm_l2_erp_stats.dsesb,
+ msm_l2_erp_stats.dsedb,
+ msm_l2_erp_stats.mse,
+ msm_l2_erp_stats.mplxrexnok);
+
+ return 0;
+}
+
+static int cache_erp_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cache_erp_show, NULL);
+}
+
+static const struct file_operations cache_erp_fops = {
+ .open = cache_erp_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int msm_erp_dump_regions(void)
+{
+ int i = 0;
+ struct msm_erp_dump_region *r;
+
+ for (i = 0; i < num_dump_regions; i++) {
+ r = &dump_regions[i];
+
+ pr_alert("%s %pR:\n", r->res->name, r->res);
+ print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_OFFSET, 32, 4, r->va,
+ resource_size(r->res), 0);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_MSM_L1_ERR_LOG
+static int cache_erp_log_show(struct seq_file *m, void *v)
+{
+ int log_value;
+
+ log_value = __raw_readl(msm_erp_log_base) == ERP_LOG_MAGIC ? 1 : 0;
+
+ seq_printf(m, "%d\n", log_value);
+
+ return 0;
+}
+
+static int cache_erp_log_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, cache_erp_log_show, NULL);
+}
+
+static const struct file_operations cache_erp_log_fops = {
+ .open = cache_erp_log_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void log_cpu_event(void)
+{
+ __raw_writel(ERP_LOG_MAGIC, msm_erp_log_base);
+ mb();
+}
+
+static int procfs_event_log_init(void)
+{
+ procfs_log_entry = proc_create("cpu/msm_erp_log", S_IRUGO, NULL,
+ &cache_erp_log_fops);
+ if (!procfs_log_entry)
+ return -ENODEV;
+ return 0;
+}
+
+#else
+static inline void log_cpu_event(void) { }
+static inline int procfs_event_log_init(void) { return 0; }
+#endif
+
+static irqreturn_t msm_l1_erp_irq(int irq, void *dev_id)
+{
+ struct msm_l1_err_stats *l1_stats = dev_id;
+ unsigned int cesr = read_cesr();
+ unsigned int i_cesynr, d_cesynr;
+ unsigned int cpu = smp_processor_id();
+ int print_regs = cesr & CESR_PRINT_MASK;
+ int log_event = cesr & CESR_LOG_EVENT_MASK;
+
+ if (print_regs) {
+ pr_alert("L1 / TLB Error detected on CPU %d!\n", cpu);
+ pr_alert("\tCESR = 0x%08x\n", cesr);
+ pr_alert("\tMIDR = 0x%08x\n", read_cpuid_id());
+ msm_erp_dump_regions();
+ }
+
+ if (cesr & CESR_DCTPE) {
+ pr_alert("D-cache tag parity error\n");
+ l1_stats->dctpe++;
+ }
+
+ if (cesr & CESR_DCDPE) {
+ pr_alert("D-cache data parity error\n");
+ l1_stats->dcdpe++;
+ }
+
+ if (cesr & CESR_ICTPE) {
+ pr_alert("I-cache tag parity error\n");
+ l1_stats->ictpe++;
+ }
+
+ if (cesr & CESR_ICDPE) {
+ pr_alert("I-cache data parity error\n");
+ l1_stats->icdpe++;
+ }
+
+ if (cesr & CESR_DCTE) {
+ pr_alert("D-cache timing error\n");
+ l1_stats->dcte++;
+ }
+
+ if (cesr & CESR_ICTE) {
+ pr_alert("I-cache timing error\n");
+ l1_stats->icte++;
+ }
+
+ if (cesr & CESR_TLBMH) {
+ asm ("mcr p15, 0, r0, c8, c7, 0");
+ l1_stats->tlbmh++;
+ }
+
+ if (cesr & (CESR_ICTPE | CESR_ICDPE | CESR_ICTE)) {
+ i_cesynr = read_cesynr();
+ pr_alert("I-side CESYNR = 0x%08x\n", i_cesynr);
+ write_cesr(CESR_I_MASK);
+
+ /*
+ * Clear the I-side bits from the captured CESR value so that we
+ * don't accidentally clear any new I-side errors when we do
+ * the CESR write-clear operation.
+ */
+ cesr &= ~CESR_I_MASK;
+ }
+
+ if (cesr & (CESR_DCTPE | CESR_DCDPE | CESR_DCTE)) {
+ d_cesynr = read_cesynr();
+ pr_alert("D-side CESYNR = 0x%08x\n", d_cesynr);
+ }
+
+ if (log_event)
+ log_cpu_event();
+
+ /* Clear the interrupt bits we processed */
+ write_cesr(cesr);
+
+ if (print_regs) {
+ if ((cesr & (~CESR_I_MASK & CESR_VALID_MASK)) ||
+ cpu_is_krait_v1() || cpu_is_krait_v2())
+ ERP_L1_ERR("L1 nonrecoverable cache error detected");
+ else
+ ERP_L1_RECOV_ERR("L1 recoverable error detected\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t msm_l2_erp_irq(int irq, void *dev_id)
+{
+ unsigned int l2esr;
+ unsigned int l2esynr0;
+ unsigned int l2esynr1;
+ unsigned int l2ear0;
+ unsigned int l2ear1;
+ int soft_error = 0;
+ int port_error = 0;
+ int unrecoverable = 0;
+ int print_alert;
+
+ l2esr = get_l2_indirect_reg(L2ESR_IND_ADDR);
+ l2esynr0 = get_l2_indirect_reg(L2ESYNR0_IND_ADDR);
+ l2esynr1 = get_l2_indirect_reg(L2ESYNR1_IND_ADDR);
+ l2ear0 = get_l2_indirect_reg(L2EAR0_IND_ADDR);
+ l2ear1 = get_l2_indirect_reg(L2EAR1_IND_ADDR);
+
+ print_alert = print_access_errors() || (l2esr & L2ESR_ACCESS_ERR_MASK);
+
+ if (print_alert) {
+ pr_alert("L2 Error detected!\n");
+ pr_alert("\tL2ESR = 0x%08x\n", l2esr);
+ pr_alert("\tL2ESYNR0 = 0x%08x\n", l2esynr0);
+ pr_alert("\tL2ESYNR1 = 0x%08x\n", l2esynr1);
+ pr_alert("\tL2EAR0 = 0x%08x\n", l2ear0);
+ pr_alert("\tL2EAR1 = 0x%08x\n", l2ear1);
+ pr_alert("\tCPU bitmap = 0x%x\n", (l2esr >> L2ESR_CPU_SHIFT) &
+ L2ESR_CPU_MASK);
+ }
+
+ if (l2esr & L2ESR_MPDCD) {
+ if (print_alert)
+ pr_alert("L2 master port decode error\n");
+ port_error++;
+ msm_l2_erp_stats.mpdcd++;
+ }
+
+ if (l2esr & L2ESR_MPSLV) {
+ if (print_alert)
+ pr_alert("L2 master port slave error\n");
+ port_error++;
+ msm_l2_erp_stats.mpslv++;
+ }
+
+ if (l2esr & L2ESR_TSESB) {
+ pr_alert("L2 tag soft error, single-bit\n");
+ soft_error++;
+ msm_l2_erp_stats.tsesb++;
+ }
+
+ if (l2esr & L2ESR_TSEDB) {
+ pr_alert("L2 tag soft error, double-bit\n");
+ soft_error++;
+ unrecoverable++;
+ msm_l2_erp_stats.tsedb++;
+ }
+
+ if (l2esr & L2ESR_DSESB) {
+ pr_alert("L2 data soft error, single-bit\n");
+ soft_error++;
+ msm_l2_erp_stats.dsesb++;
+ }
+
+ if (l2esr & L2ESR_DSEDB) {
+ pr_alert("L2 data soft error, double-bit\n");
+ soft_error++;
+ unrecoverable++;
+ msm_l2_erp_stats.dsedb++;
+ }
+
+ if (l2esr & L2ESR_MSE) {
+ pr_alert("L2 modified soft error\n");
+ soft_error++;
+ msm_l2_erp_stats.mse++;
+ }
+
+ if (l2esr & L2ESR_MPLDREXNOK) {
+ pr_alert("L2 master port LDREX received Normal OK response\n");
+ port_error++;
+ msm_l2_erp_stats.mplxrexnok++;
+ }
+
+ if (port_error && print_alert)
+ ERP_PORT_ERR("L2 master port error detected");
+
+ if (soft_error && print_alert)
+ msm_erp_dump_regions();
+
+ if (soft_error && !unrecoverable)
+ ERP_1BIT_ERR("L2 single-bit error detected");
+
+ if (unrecoverable)
+ ERP_2BIT_ERR("L2 double-bit error detected, trouble ahead");
+
+ set_l2_indirect_reg(L2ESR_IND_ADDR, l2esr);
+ return IRQ_HANDLED;
+}
+
+static void enable_erp_irq_callback(void *info)
+{
+ enable_percpu_irq(l1_erp_irq, IRQ_TYPE_LEVEL_HIGH);
+}
+
+static void disable_erp_irq_callback(void *info)
+{
+ disable_percpu_irq(l1_erp_irq);
+}
+
+static int cache_erp_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_STARTING:
+ enable_erp_irq_callback(NULL);
+ break;
+
+ case CPU_DYING:
+ disable_erp_irq_callback(NULL);
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block cache_erp_cpu_notifier = {
+ .notifier_call = cache_erp_cpu_callback,
+};
+
+static int msm_erp_read_dump_regions(struct platform_device *pdev)
+{
+ int i;
+ struct device_node *np = pdev->dev.of_node;
+ struct resource *res;
+
+ num_dump_regions = of_property_count_strings(np, "reg-names");
+
+ if (num_dump_regions <= 0) {
+ num_dump_regions = 0;
+ return 0; /* Not an error - this is an optional property */
+ }
+
+ dump_regions = devm_kzalloc(&pdev->dev,
+ sizeof(*dump_regions) * num_dump_regions,
+ GFP_KERNEL);
+ if (!dump_regions)
+ return -ENOMEM;
+
+ for (i = 0; i < num_dump_regions; i++) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ dump_regions[i].res = res;
+ dump_regions[i].va = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!dump_regions[i].va)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int msm_cache_erp_probe(struct platform_device *pdev)
+{
+ struct resource *r;
+ struct device_node *np = pdev->dev.of_node;
+ struct device_node *imem_node;
+ int ret, cpu;
+
+ imem_node = of_parse_phandle(np, "qcom,msm-imem-phandle", 0);
+ if (!imem_node) {
+ pr_err("Could not get imem handle\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ msm_erp_log_base = of_iomap(imem_node, 0);
+ if (!msm_erp_log_base) {
+ pr_err("Failed to map imem region\n");
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "l1_irq");
+
+ if (!r) {
+ pr_err("Could not get L1 resource\n");
+ ret = -ENODEV;
+ goto fail_imem_map;
+ }
+
+ l1_erp_irq = r->start;
+
+ ret = request_percpu_irq(l1_erp_irq, msm_l1_erp_irq, "MSM_L1",
+ &msm_l1_erp_stats);
+
+ if (ret) {
+ pr_err("Failed to request the L1 cache error interrupt\n");
+ goto fail_imem_map;
+ }
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "l2_irq");
+
+ if (!r) {
+ pr_err("Could not get L2 resource\n");
+ ret = -ENODEV;
+ goto fail_l1;
+ }
+
+ l2_erp_irq = r->start;
+ ret = request_irq(l2_erp_irq, msm_l2_erp_irq, 0, "MSM_L2", NULL);
+
+ if (ret) {
+ pr_err("Failed to request the L2 cache error interrupt\n");
+ goto fail_l1;
+ }
+
+ procfs_entry = proc_create("cpu/msm_cache_erp", S_IRUGO, NULL,
+ &cache_erp_fops);
+
+ if (!procfs_entry) {
+ pr_err("Failed to create procfs node for cache error reporting\n");
+ ret = -ENODEV;
+ goto fail_l2;
+ }
+
+ ret = msm_erp_read_dump_regions(pdev);
+
+ if (ret)
+ goto fail_l2;
+
+ get_online_cpus();
+ register_hotcpu_notifier(&cache_erp_cpu_notifier);
+ for_each_cpu(cpu, cpu_online_mask)
+ smp_call_function_single(cpu, enable_erp_irq_callback, NULL, 1);
+ put_online_cpus();
+
+ ret = procfs_event_log_init();
+ if (ret)
+ pr_err("Failed to create procfs node for ERP log access\n");
+
+ return 0;
+
+fail_l2:
+ free_irq(l2_erp_irq, NULL);
+fail_l1:
+ free_percpu_irq(l1_erp_irq, NULL);
+fail_imem_map:
+ iounmap(msm_erp_log_base);
+fail:
+ return ret;
+}
+
+static int msm_cache_erp_remove(struct platform_device *pdev)
+{
+ int cpu;
+ if (procfs_entry)
+ remove_proc_entry("cpu/msm_cache_erp", NULL);
+
+ get_online_cpus();
+ unregister_hotcpu_notifier(&cache_erp_cpu_notifier);
+ for_each_cpu(cpu, cpu_online_mask)
+ smp_call_function_single(cpu, disable_erp_irq_callback, NULL,
+ 1);
+ put_online_cpus();
+
+ free_percpu_irq(l1_erp_irq, NULL);
+
+ disable_irq(l2_erp_irq);
+ free_irq(l2_erp_irq, NULL);
+ return 0;
+}
+
+static struct of_device_id cache_erp_match_table[] = {
+ { .compatible = "qcom,cache_erp", },
+ {}
+};
+
+static struct platform_driver msm_cache_erp_driver = {
+ .probe = msm_cache_erp_probe,
+ .remove = msm_cache_erp_remove,
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = cache_erp_match_table,
+ },
+};
+
+static int __init msm_cache_erp_init(void)
+{
+ return platform_driver_register(&msm_cache_erp_driver);
+}
+
+static void __exit msm_cache_erp_exit(void)
+{
+ platform_driver_unregister(&msm_cache_erp_driver);
+}
+
+
+module_init(msm_cache_erp_init);
+module_exit(msm_cache_erp_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM cache error reporting driver");
diff --git a/arch/arm/mach-msm/dma.c b/arch/arm/mach-msm/dma.c
index fb9762464718..84246a5b81a6 100644
--- a/arch/arm/mach-msm/dma.c
+++ b/arch/arm/mach-msm/dma.c
@@ -1,6 +1,7 @@
/* linux/arch/arm/mach-msm/dma.c
*
* Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2008-2010, 2012, 2013 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
@@ -19,35 +20,199 @@
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/pm_runtime.h>
#include <mach/dma.h>
-#include <mach/msm_iomap.h>
+
+#define MODULE_NAME "msm_dmov"
#define MSM_DMOV_CHANNEL_COUNT 16
+#define MSM_DMOV_CRCI_COUNT 16
-#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
-#define DMOV_SD1(off, ch) (MSM_DMOV_BASE + 0x0400 + (off) + ((ch) << 2))
-#define DMOV_SD2(off, ch) (MSM_DMOV_BASE + 0x0800 + (off) + ((ch) << 2))
-#define DMOV_SD3(off, ch) (MSM_DMOV_BASE + 0x0C00 + (off) + ((ch) << 2))
+enum {
+ CLK_DIS,
+ CLK_ENABLING,
+ CLK_EN,
+ CLK_TO_BE_DIS,
+ CLK_DISABLING
+};
-#if defined(CONFIG_ARCH_MSM7X30)
-#define DMOV_SD_AARM DMOV_SD2
-#else
-#define DMOV_SD_AARM DMOV_SD3
-#endif
+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 clock_lock;
+ spinlock_t 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;
+};
+
+static void msm_dmov_clock_work(struct work_struct *);
+
+#ifdef CONFIG_ARCH_MSM8X60
+
+#define DMOV_CHANNEL_DEFAULT_CONF { .sd = 1, .block = 0, .priority = 0 }
+#define DMOV_CHANNEL_MODEM_CONF { .sd = 3, .block = 0, .priority = 0 }
+#define DMOV_CHANNEL_CONF(secd, blk, pri) \
+ { .sd = secd, .block = blk, .priority = pri }
+
+static struct msm_dmov_chan_conf adm0_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_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+ DMOV_CHANNEL_DEFAULT_CONF,
+};
+
+static struct msm_dmov_chan_conf adm1_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_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+ DMOV_CHANNEL_MODEM_CONF,
+};
+
+#define DMOV_CRCI_DEFAULT_CONF { .sd = 1, .blk_size = 0 }
+#define DMOV_CRCI_CONF(secd, blk) { .sd = secd, .blk_size = blk }
+
+static struct msm_dmov_crci_conf adm0_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_CONF(1, 4),
+ 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,
+};
-#define DMOV_CMD_PTR(ch) DMOV_SD_AARM(0x000, ch)
-#define DMOV_RSLT(ch) DMOV_SD_AARM(0x040, ch)
-#define DMOV_FLUSH0(ch) DMOV_SD_AARM(0x080, ch)
-#define DMOV_FLUSH1(ch) DMOV_SD_AARM(0x0C0, ch)
-#define DMOV_FLUSH2(ch) DMOV_SD_AARM(0x100, ch)
-#define DMOV_FLUSH3(ch) DMOV_SD_AARM(0x140, ch)
-#define DMOV_FLUSH4(ch) DMOV_SD_AARM(0x180, ch)
-#define DMOV_FLUSH5(ch) DMOV_SD_AARM(0x1C0, ch)
+static struct msm_dmov_crci_conf adm1_crci_conf[] = {
+ DMOV_CRCI_DEFAULT_CONF,
+ DMOV_CRCI_CONF(1, 1),
+ DMOV_CRCI_CONF(1, 1),
+ DMOV_CRCI_DEFAULT_CONF,
+ DMOV_CRCI_CONF(1, 1),
+ DMOV_CRCI_CONF(1, 1),
+ 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(1, 1),
+ DMOV_CRCI_DEFAULT_CONF,
+};
-#define DMOV_STATUS(ch) DMOV_SD_AARM(0x200, ch)
-#define DMOV_ISR DMOV_SD_AARM(0x380, 0)
+static struct msm_dmov_conf dmov_conf[] = {
+ {
+ .crci_conf = adm0_crci_conf,
+ .chan_conf = adm0_chan_conf,
+ .clock_lock = __MUTEX_INITIALIZER(dmov_conf[0].clock_lock),
+ .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
+ .clk_ctl = CLK_DIS,
+ .work = __DELAYED_WORK_INITIALIZER(dmov_conf[0].work,
+ msm_dmov_clock_work, 0),
+ }, {
+ .crci_conf = adm1_crci_conf,
+ .chan_conf = adm1_chan_conf,
+ .clock_lock = __MUTEX_INITIALIZER(dmov_conf[1].clock_lock),
+ .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
+ .clk_ctl = CLK_DIS,
+ .work = __DELAYED_WORK_INITIALIZER(dmov_conf[1].work,
+ msm_dmov_clock_work, 0),
+ }
+};
+#else
+static struct msm_dmov_conf dmov_conf[] = {
+ {
+ .crci_conf = NULL,
+ .chan_conf = NULL,
+ .clock_lock = __MUTEX_INITIALIZER(dmov_conf[0].clock_lock),
+ .lock = __SPIN_LOCK_UNLOCKED(dmov_lock),
+ .clk_ctl = CLK_DIS,
+ .work = __DELAYED_WORK_INITIALIZER(dmov_conf[0].work,
+ msm_dmov_clock_work, 0),
+ }
+};
+#endif
-#define DMOV_CONFIG(ch) DMOV_SD_AARM(0x300, ch)
+#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)
+
+#ifdef CONFIG_MSM_ADM3
+#define DMOV_IRQ_TO_ADM(irq) \
+({ \
+ typeof(irq) _irq = irq; \
+ ((_irq == INT_ADM1_MASTER) || (_irq == INT_ADM1_AARM)); \
+})
+#else
+#define DMOV_IRQ_TO_ADM(irq) 0
+#endif
enum {
MSM_DMOV_PRINT_ERRORS = 1,
@@ -55,11 +220,6 @@ enum {
MSM_DMOV_PRINT_FLOW = 4
};
-static DEFINE_SPINLOCK(msm_dmov_lock);
-static struct clk *msm_dmov_clk;
-static unsigned int channel_active;
-static struct list_head ready_commands[MSM_DMOV_CHANNEL_COUNT];
-static struct list_head active_commands[MSM_DMOV_CHANNEL_COUNT];
unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS;
#define MSM_DMOV_DPRINTF(mask, format, args...) \
@@ -74,51 +234,274 @@ unsigned int msm_dmov_print_mask = MSM_DMOV_PRINT_ERRORS;
#define PRINT_FLOW(format, args...) \
MSM_DMOV_DPRINTF(MSM_DMOV_PRINT_FLOW, format, args);
-void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful)
+static int msm_dmov_clk_on(int adm)
{
- writel((graceful << 31), DMOV_FLUSH0(id));
+ int ret;
+
+ 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;
}
EXPORT_SYMBOL_GPL(msm_dmov_stop_cmd);
-void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd)
+static void msm_dmov_clk_off(int adm)
{
+ 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);
+}
+
+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);
unsigned long irq_flags;
- unsigned int status;
- spin_lock_irqsave(&msm_dmov_lock, irq_flags);
- if (!channel_active)
- clk_enable(msm_dmov_clk);
- dsb();
- status = readl(DMOV_STATUS(id));
- if (list_empty(&ready_commands[id]) &&
- (status & DMOV_STATUS_CMD_PTR_RDY)) {
-#if 0
- if (list_empty(&active_commands[id])) {
- PRINT_FLOW("msm_dmov_enqueue_cmd(%d), enable interrupt\n", id);
- writel(DMOV_CONFIG_IRQ_EN, DMOV_CONFIG(id));
+ mutex_lock(&conf->clock_lock);
+ spin_lock_irqsave(&conf->lock, irq_flags);
+ if (conf->clk_ctl == CLK_TO_BE_DIS) {
+ BUG_ON(conf->channel_active);
+ conf->clk_ctl = CLK_DISABLING;
+ spin_unlock_irqrestore(&conf->lock, irq_flags);
+ msm_dmov_clk_off(adm);
+ spin_lock_irqsave(&conf->lock, irq_flags);
+ if (conf->clk_ctl == CLK_DISABLING)
+ conf->clk_ctl = CLK_DIS;
+ }
+ spin_unlock_irqrestore(&conf->lock, irq_flags);
+ mutex_unlock(&conf->clock_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("start_ready_cmd, %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 = 0;
+
+ mutex_lock(&dmov_conf[adm].clock_lock);
+ /*No spin_lock is required for the condition check below*/
+ BUG_ON(dmov_conf[adm].clk_ctl != CLK_ENABLING);
+ status = msm_dmov_clk_on(adm);
+ if (status != 0) {
+ PRINT_ERROR("ADM: Unexpected clock failure at dma.c:%d/%s()!\n",
+ __LINE__, __func__);
+ goto error;
+ }
+
+ spin_lock_irqsave(&dmov_conf[adm].lock, flags);
+
+ dmov_conf[adm].clk_ctl = CLK_EN;
+
+ for (ch = 0; ch < MSM_DMOV_CHANNEL_COUNT; ch++) {
+ while (!list_empty(&dmov_conf[adm].staged_commands[ch])) {
+ 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]);
}
-#endif
- if (cmd->execute_func)
- cmd->execute_func(cmd);
- PRINT_IO("msm_dmov_enqueue_cmd(%d), start command, status %x\n", id, status);
- list_add_tail(&cmd->list, &active_commands[id]);
- if (!channel_active)
- enable_irq(INT_ADM_AARM);
- channel_active |= 1U << id;
- writel(cmd->cmdptr, DMOV_CMD_PTR(id));
+ if (!list_empty(&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 {
+ if (list_empty(&dmov_conf[adm].
+ active_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);
+ }
+ }
+ }
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, flags);
+error:
+ mutex_unlock(&dmov_conf[adm].clock_lock);
+}
+
+void msm_dmov_enqueue_cmd_ext_atomic(unsigned id, struct msm_dmov_cmd *cmd)
+{
+ unsigned int status;
+ int adm = DMOV_ID_TO_ADM(id);
+ int ch = DMOV_ID_TO_CHAN(id);
+
+ 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);
+ 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));
} else {
- if (!channel_active)
- clk_disable(msm_dmov_clk);
- if (list_empty(&active_commands[id]))
- PRINT_ERROR("msm_dmov_enqueue_cmd(%d), error datamover stalled, status %x\n", id, status);
+ list_add_tail(&cmd->list, &dmov_conf[adm].ready_commands[ch]);
+ 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);
+ }
+}
- PRINT_IO("msm_dmov_enqueue_cmd(%d), enqueue command, status %x\n", id, status);
- list_add_tail(&cmd->list, &ready_commands[id]);
+static void __msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd,
+ int onstack)
+{
+ 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].lock, flags);
+ switch (dmov_conf[adm].clk_ctl) {
+ case CLK_DIS:
+ case CLK_DISABLING:
+ if (onstack)
+ INIT_WORK_ONSTACK(&cmd->work,
+ msm_dmov_enqueue_cmd_ext_work);
+ else
+ INIT_WORK(&cmd->work,
+ msm_dmov_enqueue_cmd_ext_work);
+ list_add_tail(&cmd->list, &dmov_conf[adm].staged_commands[ch]);
+ dmov_conf[adm].clk_ctl = CLK_ENABLING;
+ queue_work(dmov_conf[adm].cmd_wq, &cmd->work);
+ break;
+
+ case CLK_ENABLING:
+ list_add_tail(&cmd->list, &dmov_conf[adm].staged_commands[ch]);
+ break;
+
+ case CLK_EN:
+ msm_dmov_enqueue_cmd_ext_atomic(id, cmd);
+ break;
+
+ case CLK_TO_BE_DIS:
+ cancel_delayed_work(&dmov_conf[adm].work);
+ dmov_conf[adm].clk_ctl = CLK_EN;
+ msm_dmov_enqueue_cmd_ext_atomic(id, cmd);
+ break;
+
+ default:
+ PRINT_ERROR("ADM%d: Invalid CLK State.\n", adm);
+ BUG_ON(dmov_conf[adm].clk_ctl);
}
- spin_unlock_irqrestore(&msm_dmov_lock, irq_flags);
+
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, flags);
}
EXPORT_SYMBOL_GPL(msm_dmov_enqueue_cmd);
+void msm_dmov_enqueue_cmd_ext(unsigned id, struct msm_dmov_cmd *cmd)
+{
+ __msm_dmov_enqueue_cmd_ext(id, cmd, 0);
+}
+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;
+ __msm_dmov_enqueue_cmd_ext(id, cmd, 0);
+}
+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].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;
+ list_for_each_entry(cmd, &dmov_conf[adm].ready_commands[ch], list)
+ cmd->toflush = graceful ? GRACEFUL : NONGRACEFUL;
+ /* spin_unlock_irqrestore has the necessary barrier */
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+}
+EXPORT_SYMBOL(msm_dmov_flush);
+
struct msm_dmov_exec_cmdptr_cmd {
struct msm_dmov_cmd dmov_cmd;
struct completion complete;
@@ -132,7 +515,8 @@ 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);
+ 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));
@@ -148,141 +532,338 @@ int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr)
cmd.dmov_cmd.cmdptr = cmdptr;
cmd.dmov_cmd.complete_func = dmov_exec_cmdptr_complete_func;
- cmd.dmov_cmd.execute_func = NULL;
+ cmd.dmov_cmd.exec_func = NULL;
cmd.id = id;
+ cmd.result = 0;
init_completion(&cmd.complete);
- msm_dmov_enqueue_cmd(id, &cmd.dmov_cmd);
- wait_for_completion(&cmd.complete);
+ __msm_dmov_enqueue_cmd_ext(id, &cmd.dmov_cmd, 1);
+ wait_for_completion_io(&cmd.complete);
if (cmd.result != 0x80000002) {
- PRINT_ERROR("dmov_exec_cmdptr(%d): ERROR, result: %x\n", id, cmd.result);
+ 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]);
+ 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_datamover_irq_handler(int irq, void *dev_id)
+static irqreturn_t msm_dmov_isr(int irq, void *dev_id)
{
- unsigned int int_status, mask, 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);
- spin_lock_irqsave(&msm_dmov_lock, irq_flags);
-
- int_status = readl(DMOV_ISR); /* read and clear interrupt */
+ spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
+ /* 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);
while (int_status) {
mask = int_status & -int_status;
- id = fls(mask) - 1;
- PRINT_FLOW("msm_datamover_irq_handler %08x %08x id %d\n", int_status, mask, id);
+ 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(DMOV_STATUS(id));
+ 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);
+ PRINT_FLOW("msm_datamover_irq_handler id %d, "
+ "result not valid %x\n", id, ch_status);
continue;
}
do {
- ch_result = readl(DMOV_RSLT(id));
- if (list_empty(&active_commands[id])) {
- PRINT_ERROR("msm_datamover_irq_handler id %d, got result "
- "with no active command, status %x, result %x\n",
+ 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(active_commands[id].next, typeof(*cmd), list);
- PRINT_FLOW("msm_datamover_irq_handler id %d, status %x, result %x\n", id, ch_status, ch_result);
+ } 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);
+ 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);
- dsb();
- cmd->complete_func(cmd, ch_result, NULL);
+ cmd->complete_func(cmd, ch_result,
+ NULL);
}
}
if (ch_result & DMOV_RSLT_FLUSH) {
struct msm_dmov_errdata errdata;
- errdata.flush[0] = readl(DMOV_FLUSH0(id));
- errdata.flush[1] = readl(DMOV_FLUSH1(id));
- errdata.flush[2] = readl(DMOV_FLUSH2(id));
- errdata.flush[3] = readl(DMOV_FLUSH3(id));
- errdata.flush[4] = readl(DMOV_FLUSH4(id));
- errdata.flush[5] = readl(DMOV_FLUSH5(id));
- 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]);
+ 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);
- dsb();
- cmd->complete_func(cmd, ch_result, &errdata);
+ cmd->complete_func(cmd, ch_result,
+ &errdata);
}
}
if (ch_result & DMOV_RSLT_ERROR) {
struct msm_dmov_errdata errdata;
- errdata.flush[0] = readl(DMOV_FLUSH0(id));
- errdata.flush[1] = readl(DMOV_FLUSH1(id));
- errdata.flush[2] = readl(DMOV_FLUSH2(id));
- errdata.flush[3] = readl(DMOV_FLUSH3(id));
- errdata.flush[4] = readl(DMOV_FLUSH4(id));
- errdata.flush[5] = readl(DMOV_FLUSH5(id));
+ 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]);
+ 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);
- dsb();
- cmd->complete_func(cmd, ch_result, &errdata);
+ 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(0, DMOV_FLUSH0(id));
+ /* 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));
}
- ch_status = readl(DMOV_STATUS(id));
- PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
- if ((ch_status & DMOV_STATUS_CMD_PTR_RDY) && !list_empty(&ready_commands[id])) {
- cmd = list_entry(ready_commands[id].next, typeof(*cmd), list);
- list_move_tail(&cmd->list, &active_commands[id]);
- if (cmd->execute_func)
- cmd->execute_func(cmd);
- PRINT_FLOW("msm_datamover_irq_handler id %d, start command\n", id);
- writel(cmd->cmdptr, DMOV_CMD_PTR(id));
+ 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) {
+ cmd = start_ready_cmd(ch, adm);
+
+ if (cmd != NULL) {
+ if (cmd->toflush) {
+ int flush = (cmd->toflush ==
+ GRACEFUL) ? 1 << 31 : 0;
+ writel_relaxed(flush,
+ DMOV_REG(DMOV_FLUSH0(ch), adm));
+ }
+ }
}
} while (ch_status & DMOV_STATUS_RSLT_VALID);
- if (list_empty(&active_commands[id]) && list_empty(&ready_commands[id]))
- channel_active &= ~(1U << id);
- PRINT_FLOW("msm_datamover_irq_handler id %d, status %x\n", id, ch_status);
+ 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);
}
- if (!channel_active) {
- disable_irq_nosync(INT_ADM_AARM);
- clk_disable(msm_dmov_clk);
+ 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));
}
- spin_unlock_irqrestore(&msm_dmov_lock, irq_flags);
- return IRQ_HANDLED;
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+ return valid ? IRQ_HANDLED : IRQ_NONE;
}
-static int __init msm_init_datamover(void)
+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;
+ unsigned long irq_flags;
+
+ mutex_lock(&dmov_conf[adm].clock_lock);
+ spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
+ if (dmov_conf[adm].clk_ctl == CLK_TO_BE_DIS) {
+ BUG_ON(dmov_conf[adm].channel_active);
+ dmov_conf[adm].clk_ctl = CLK_DISABLING;
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+ msm_dmov_clk_off(adm);
+ spin_lock_irqsave(&dmov_conf[adm].lock, irq_flags);
+ if (dmov_conf[adm].clk_ctl == CLK_DISABLING)
+ dmov_conf[adm].clk_ctl = CLK_DIS;
+ }
+ spin_unlock_irqrestore(&dmov_conf[adm].lock, irq_flags);
+ mutex_unlock(&dmov_conf[adm].clock_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 const 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 = 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 = 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 = 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)
{
+#ifdef CONFIG_MSM_ADM3
+ int i;
+ 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_SD(7);
+ conf |= DMOV_CONF_SD(chan_conf[i].sd);
+ writel_relaxed(conf | DMOV_CONF_SHADOW_EN,
+ DMOV_REG(DMOV_CONF(i), adm));
+ }
+ }
+ for (i = 0; i < MSM_DMOV_CRCI_COUNT; i++) {
+ struct msm_dmov_crci_conf *crci_conf =
+ dmov_conf[adm].crci_conf;
+
+ writel_relaxed(DMOV_CRCI_CTL_BLK_SZ(crci_conf[i].blk_size),
+ DMOV_REG(DMOV_CRCI_CTL(i), adm));
+ }
+#endif
+}
+
+static int msm_dmov_probe(struct platform_device *pdev)
+{
+ int adm = (pdev->id >= 0) ? pdev->id : 0;
int i;
int ret;
- struct clk *clk;
+ struct msm_dmov_pdata *pdata = pdev->dev.platform_data;
+ struct resource *irqres =
+ platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ struct resource *mres =
+ platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ char wq_name[12];
+
+ if (pdata) {
+ dmov_conf[adm].sd = pdata->sd;
+ dmov_conf[adm].sd_size = pdata->sd_size;
+ }
+ if (!dmov_conf[adm].sd_size)
+ return -ENXIO;
+
+ if (!irqres || !irqres->start)
+ return -ENXIO;
+ dmov_conf[adm].irq = irqres->start;
+
+ if (!mres || !mres->start)
+ return -ENXIO;
+ dmov_conf[adm].base = ioremap_nocache(mres->start, resource_size(mres));
+ if (!dmov_conf[adm].base)
+ return -ENOMEM;
+
+ snprintf(wq_name, sizeof(wq_name), "dmov%d_wq", adm);
+ dmov_conf[adm].cmd_wq = alloc_workqueue(wq_name, WQ_CPU_INTENSIVE, 1);
+ if (!dmov_conf[adm].cmd_wq) {
+ PRINT_ERROR("Couldn't allocate ADM%d workqueue.\n", adm);
+ ret = -ENOMEM;
+ goto out_map;
+ }
+
+ ret = request_irq(dmov_conf[adm].irq, msm_dmov_isr,
+ 0, "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_irq;
+ }
+ ret = msm_dmov_clk_on(adm);
+ if (ret) {
+ PRINT_ERROR("Enabling ADM%d clocks failed\n", adm);
+ goto out_irq;
+ }
+ config_datamover(adm);
for (i = 0; i < MSM_DMOV_CHANNEL_COUNT; i++) {
- INIT_LIST_HEAD(&ready_commands[i]);
- INIT_LIST_HEAD(&active_commands[i]);
- writel(DMOV_CONFIG_IRQ_EN | DMOV_CONFIG_FORCE_TOP_PTR_RSLT | DMOV_CONFIG_FORCE_FLUSH_RSLT, DMOV_CONFIG(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));
}
clk = clk_get(NULL, "adm_clk");
if (IS_ERR(clk))
@@ -290,9 +871,35 @@ static int __init msm_init_datamover(void)
clk_prepare(clk);
msm_dmov_clk = clk;
ret = request_irq(INT_ADM_AARM, msm_datamover_irq_handler, 0, "msmdatamover", NULL);
+ wmb();
+ msm_dmov_clk_off(adm);
+ return ret;
+out_irq:
+ free_irq(dmov_conf[adm].irq, NULL);
+out_wq:
+ destroy_workqueue(dmov_conf[adm].cmd_wq);
+out_map:
+ iounmap(dmov_conf[adm].base);
+ return ret;
+}
+
+static struct platform_driver msm_dmov_driver = {
+ .probe = msm_dmov_probe,
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ .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;
- disable_irq(INT_ADM_AARM);
return 0;
}
module_init(msm_init_datamover);
+arch_initcall(msm_init_datamover);
diff --git a/arch/arm/mach-msm/gpiomux-v2.c b/arch/arm/mach-msm/gpiomux-v2.c
new file mode 100644
index 000000000000..92b914814833
--- /dev/null
+++ b/arch/arm/mach-msm/gpiomux-v2.c
@@ -0,0 +1,32 @@
+/* Copyright (c) 2010-2011, 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 <linux/bitops.h>
+#include <linux/io.h>
+#include <mach/msm_iomap.h>
+#include <mach/gpiomux.h>
+
+#define GPIO_CFG(n) (MSM_TLMM_BASE + 0x1000 + (0x10 * n))
+#define GPIO_IN_OUT(n) (MSM_TLMM_BASE + 0x1004 + (0x10 * n))
+
+void __msm_gpiomux_write(unsigned gpio, struct gpiomux_setting val)
+{
+ uint32_t bits;
+
+ bits = (val.drv << 6) | (val.func << 2) | val.pull;
+ if (val.func == GPIOMUX_FUNC_GPIO) {
+ bits |= val.dir > GPIOMUX_IN ? BIT(9) : 0;
+ __raw_writel(val.dir == GPIOMUX_OUT_HIGH ? BIT(1) : 0,
+ GPIO_IN_OUT(gpio));
+ }
+ __raw_writel(bits, GPIO_CFG(gpio));
+ mb();
+}
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
index 2b8e2d217082..967c577b726e 100644
--- a/arch/arm/mach-msm/gpiomux.c
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010,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
@@ -8,19 +8,31 @@
* 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 <linux/module.h>
+#include <linux/of.h>
+#include <linux/slab.h>
#include <linux/spinlock.h>
+<<<<<<< current
#include "gpiomux.h"
#include "proc_comm.h"
+=======
+#include <linux/io.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+
+struct msm_gpiomux_rec {
+ struct gpiomux_setting *sets[GPIOMUX_NSETTINGS];
+ int ref;
+};
+>>>>>>> patched
static DEFINE_SPINLOCK(gpiomux_lock);
+static struct msm_gpiomux_rec *msm_gpiomux_recs;
+static struct gpiomux_setting *msm_gpiomux_sets;
+static unsigned msm_gpiomux_ngpio;
+<<<<<<< current
static void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
{
unsigned tlmm_config = (val & ~GPIOMUX_CTL_MASK) |
@@ -38,42 +50,80 @@ static void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
int msm_gpiomux_write(unsigned gpio,
gpiomux_config_t active,
gpiomux_config_t suspended)
+=======
+static int msm_gpiomux_store(unsigned gpio, enum msm_gpiomux_setting which,
+ struct gpiomux_setting *setting, struct gpiomux_setting *old_setting)
+>>>>>>> patched
{
- struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ struct msm_gpiomux_rec *rec = msm_gpiomux_recs + gpio;
+ unsigned set_slot = gpio * GPIOMUX_NSETTINGS + which;
unsigned long irq_flags;
- gpiomux_config_t setting;
+ int status = 0;
+
+ if (!msm_gpiomux_recs)
+ return -EFAULT;
- if (gpio >= GPIOMUX_NGPIOS)
+ if (gpio >= msm_gpiomux_ngpio)
return -EINVAL;
spin_lock_irqsave(&gpiomux_lock, irq_flags);
- if (active & GPIOMUX_VALID)
- cfg->active = active;
+ if (old_setting) {
+ if (rec->sets[which] == NULL)
+ status = 1;
+ else
+ *old_setting = *(rec->sets[which]);
+ }
+
+ if (setting) {
+ msm_gpiomux_sets[set_slot] = *setting;
+ rec->sets[which] = &msm_gpiomux_sets[set_slot];
+ } else {
+ rec->sets[which] = NULL;
+ }
+
+ spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
+ return status;
+}
+
+int msm_gpiomux_write(unsigned gpio, enum msm_gpiomux_setting which,
+ struct gpiomux_setting *setting, struct gpiomux_setting *old_setting)
+{
+ int ret;
+ unsigned long irq_flags;
+ struct gpiomux_setting *new_set;
+ struct msm_gpiomux_rec *rec = msm_gpiomux_recs + gpio;
+
+ ret = msm_gpiomux_store(gpio, which, setting, old_setting);
+ if (ret < 0)
+ return ret;
- if (suspended & GPIOMUX_VALID)
- cfg->suspended = suspended;
+ spin_lock_irqsave(&gpiomux_lock, irq_flags);
- setting = cfg->ref ? active : suspended;
- if (setting & GPIOMUX_VALID)
- __msm_gpiomux_write(gpio, setting);
+ new_set = rec->ref ? rec->sets[GPIOMUX_ACTIVE] :
+ rec->sets[GPIOMUX_SUSPENDED];
+ if (new_set)
+ __msm_gpiomux_write(gpio, *new_set);
spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
- return 0;
+ return ret;
}
EXPORT_SYMBOL(msm_gpiomux_write);
int msm_gpiomux_get(unsigned gpio)
{
- struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ struct msm_gpiomux_rec *rec = msm_gpiomux_recs + gpio;
unsigned long irq_flags;
- if (gpio >= GPIOMUX_NGPIOS)
+ if (!msm_gpiomux_recs)
+ return -EFAULT;
+
+ if (gpio >= msm_gpiomux_ngpio)
return -EINVAL;
spin_lock_irqsave(&gpiomux_lock, irq_flags);
- if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID)
- __msm_gpiomux_write(gpio, cfg->active);
+ if (rec->ref++ == 0 && rec->sets[GPIOMUX_ACTIVE])
+ __msm_gpiomux_write(gpio, *rec->sets[GPIOMUX_ACTIVE]);
spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
return 0;
}
@@ -81,31 +131,117 @@ EXPORT_SYMBOL(msm_gpiomux_get);
int msm_gpiomux_put(unsigned gpio)
{
- struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
+ struct msm_gpiomux_rec *rec = msm_gpiomux_recs + gpio;
unsigned long irq_flags;
- if (gpio >= GPIOMUX_NGPIOS)
+ if (!msm_gpiomux_recs)
+ return -EFAULT;
+
+ if (gpio >= msm_gpiomux_ngpio)
return -EINVAL;
spin_lock_irqsave(&gpiomux_lock, irq_flags);
- BUG_ON(cfg->ref == 0);
- if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID)
- __msm_gpiomux_write(gpio, cfg->suspended);
+ BUG_ON(rec->ref == 0);
+ if (--rec->ref == 0 && rec->sets[GPIOMUX_SUSPENDED])
+ __msm_gpiomux_write(gpio, *rec->sets[GPIOMUX_SUSPENDED]);
spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
return 0;
}
EXPORT_SYMBOL(msm_gpiomux_put);
-static int __init gpiomux_init(void)
+int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg)
+{
+ return readl_relaxed(MSM_TLMM_BASE + misc_reg);
+}
+
+void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val)
+{
+ writel_relaxed(val, MSM_TLMM_BASE + misc_reg);
+ /* ensure the write completes before returning */
+ mb();
+}
+
+int msm_gpiomux_init(size_t ngpio)
{
- unsigned n;
+ if (!ngpio)
+ return -EINVAL;
- for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
- msm_gpiomux_configs[n].ref = 0;
- if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
- continue;
- __msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
+ if (msm_gpiomux_recs)
+ return -EPERM;
+
+ msm_gpiomux_recs = kzalloc(sizeof(struct msm_gpiomux_rec) * ngpio,
+ GFP_KERNEL);
+ if (!msm_gpiomux_recs)
+ return -ENOMEM;
+
+ /* There is no need to zero this memory, as clients will be blindly
+ * installing settings on top of it.
+ */
+ msm_gpiomux_sets = kmalloc(sizeof(struct gpiomux_setting) * ngpio *
+ GPIOMUX_NSETTINGS, GFP_KERNEL);
+ if (!msm_gpiomux_sets) {
+ kfree(msm_gpiomux_recs);
+ msm_gpiomux_recs = NULL;
+ return -ENOMEM;
}
+
+ msm_gpiomux_ngpio = ngpio;
+
return 0;
}
-postcore_initcall(gpiomux_init);
+EXPORT_SYMBOL(msm_gpiomux_init);
+
+void msm_gpiomux_install_nowrite(struct msm_gpiomux_config *configs,
+ unsigned nconfigs)
+{
+ unsigned c, s;
+ int rc;
+
+ for (c = 0; c < nconfigs; ++c) {
+ for (s = 0; s < GPIOMUX_NSETTINGS; ++s) {
+ rc = msm_gpiomux_store(configs[c].gpio, s,
+ configs[c].settings[s], NULL);
+ if (rc)
+ pr_err("%s: write failure: %d\n", __func__, rc);
+ }
+ }
+}
+
+void msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs)
+{
+ unsigned c, s;
+ int rc;
+
+ for (c = 0; c < nconfigs; ++c) {
+ for (s = 0; s < GPIOMUX_NSETTINGS; ++s) {
+ rc = msm_gpiomux_write(configs[c].gpio, s,
+ configs[c].settings[s], NULL);
+ if (rc)
+ pr_err("%s: write failure: %d\n", __func__, rc);
+ }
+ }
+}
+EXPORT_SYMBOL(msm_gpiomux_install);
+
+int msm_gpiomux_init_dt(void)
+{
+ int rc;
+ unsigned int ngpio;
+ struct device_node *of_gpio_node;
+
+ of_gpio_node = of_find_compatible_node(NULL, NULL, "qcom,msm-gpio");
+ if (!of_gpio_node) {
+ pr_err("%s: Failed to find qcom,msm-gpio node\n", __func__);
+ return -ENODEV;
+ }
+
+ rc = of_property_read_u32(of_gpio_node, "ngpio", &ngpio);
+ if (rc) {
+ pr_err("%s: Failed to find ngpio property in msm-gpio device node %d\n"
+ , __func__, rc);
+ return rc;
+ }
+
+ return msm_gpiomux_init(ngpio);
+}
+EXPORT_SYMBOL(msm_gpiomux_init_dt);
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
new file mode 100644
index 000000000000..7e6e1c106ab6
--- /dev/null
+++ b/arch/arm/mach-msm/hotplug.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ * Copyright (c) 2011-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 <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+#include <linux/cpu.h>
+#include <linux/notifier.h>
+#include <linux/msm_rtb.h>
+// AGSTUB
+//#include <soc/qcom/spm.h>
+#include <soc/qcom/pm.h>
+
+#include <asm/smp_plat.h>
+#include <asm/vfp.h>
+
+//#include <soc/qcom/jtag.h>
+
+static cpumask_t cpu_dying_mask;
+
+static DEFINE_PER_CPU(unsigned int, warm_boot_flag);
+
+static inline void cpu_enter_lowpower(void)
+{
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+ /* Just enter wfi for now. TODO: Properly shut off the cpu. */
+ for (;;) {
+
+ lpm_cpu_hotplug_enter(cpu);
+ 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
+ */
+ (*spurious)++;
+ }
+}
+
+int msm_cpu_kill(unsigned int cpu)
+{
+ int ret = 0;
+
+ if (cpumask_test_and_clear_cpu(cpu, &cpu_dying_mask))
+ ret = msm_pm_wait_cpu_shutdown(cpu);
+
+ return ret ? 0 : 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void __ref msm_cpu_die(unsigned int cpu)
+{
+ int spurious = 0;
+
+ if (unlikely(cpu != smp_processor_id())) {
+ pr_crit("%s: running on %u, should be %u\n",
+ __func__, smp_processor_id(), cpu);
+ BUG();
+ }
+ /*
+ * we're ready for shutdown now, so do it
+ */
+ cpu_enter_lowpower();
+ platform_do_lowpower(cpu, &spurious);
+
+ pr_debug("CPU%u: %s: normal wakeup\n", cpu, __func__);
+ cpu_leave_lowpower();
+
+ if (spurious)
+ pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
+
+#define CPU_SHIFT 0
+#define CPU_MASK 0xF
+#define CPU_OF(n) (((n) & CPU_MASK) << CPU_SHIFT)
+#define CPUSET_SHIFT 4
+#define CPUSET_MASK 0xFFFF
+#define CPUSET_OF(n) (((n) & CPUSET_MASK) << CPUSET_SHIFT)
+
+static int hotplug_rtb_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ /*
+ * Bits [19:4] of the data are the online mask, lower 4 bits are the
+ * cpu number that is being changed. Additionally, changes to the
+ * online_mask that will be done by the current hotplug will be made
+ * even though they aren't necessarily in the online mask yet.
+ *
+ * XXX: This design is limited to supporting at most 16 cpus
+ */
+ int this_cpumask = CPUSET_OF(1 << (int)hcpu);
+ int cpumask = CPUSET_OF(cpumask_bits(cpu_online_mask)[0]);
+ int cpudata = CPU_OF((int)hcpu) | cpumask;
+
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_STARTING:
+ uncached_logk(LOGK_HOTPLUG, (void *)(cpudata | this_cpumask));
+ break;
+ case CPU_DYING:
+ cpumask_set_cpu((unsigned long)hcpu, &cpu_dying_mask);
+ uncached_logk(LOGK_HOTPLUG, (void *)(cpudata & ~this_cpumask));
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+static struct notifier_block hotplug_rtb_notifier = {
+ .notifier_call = hotplug_rtb_callback,
+};
+
+int msm_platform_secondary_init(unsigned int cpu)
+{
+ int ret;
+ unsigned int *warm_boot = &__get_cpu_var(warm_boot_flag);
+
+ if (!(*warm_boot)) {
+ *warm_boot = 1;
+ return 0;
+ }
+// msm_jtag_restore_state();
+#if defined(CONFIG_VFP) && defined (CONFIG_CPU_PM)
+ //vfp_pm_resume();
+#endif
+ ret = 0; // AGSTUB msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
+
+ return ret;
+}
+
+static int __init init_hotplug(void)
+{
+ return register_hotcpu_notifier(&hotplug_rtb_notifier);
+}
+early_initcall(init_hotplug);
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
new file mode 100644
index 000000000000..7f6376d16e6c
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -0,0 +1,208 @@
+/* arch/arm/mach-msm/include/mach/board.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2008-2014, The Linux Foundation. All rights reserved.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_BOARD_H
+#define __ASM_ARCH_MSM_BOARD_H
+
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/clkdev.h>
+#include <linux/of_platform.h>
+//#include <linux/ssbi.h>
+//#include <linux/msm-bus.h>
+
+
+struct clk_lookup;
+
+struct snd_endpoint {
+ int id;
+ const char *name;
+};
+
+struct msm_snd_endpoints {
+ struct snd_endpoint *endpoints;
+ unsigned num;
+};
+
+struct cad_endpoint {
+ int id;
+ const char *name;
+ uint32_t capability;
+};
+
+struct msm_cad_endpoints {
+ struct cad_endpoint *endpoints;
+ unsigned num;
+};
+
+#define MSM_MAX_DEC_CNT 14
+/* 7k target ADSP information */
+/* Bit 23:0, for codec identification like mp3, wav etc *
+ * Bit 27:24, for mode identification like tunnel, non tunnel*
+ * bit 31:28, for operation support like DM, DMA */
+enum msm_adspdec_concurrency {
+ MSM_ADSP_CODEC_WAV = 0,
+ MSM_ADSP_CODEC_ADPCM = 1,
+ MSM_ADSP_CODEC_MP3 = 2,
+ MSM_ADSP_CODEC_REALAUDIO = 3,
+ MSM_ADSP_CODEC_WMA = 4,
+ MSM_ADSP_CODEC_AAC = 5,
+ MSM_ADSP_CODEC_RESERVED = 6,
+ MSM_ADSP_CODEC_MIDI = 7,
+ MSM_ADSP_CODEC_YADPCM = 8,
+ MSM_ADSP_CODEC_QCELP = 9,
+ MSM_ADSP_CODEC_AMRNB = 10,
+ MSM_ADSP_CODEC_AMRWB = 11,
+ MSM_ADSP_CODEC_EVRC = 12,
+ MSM_ADSP_CODEC_WMAPRO = 13,
+ MSM_ADSP_CODEC_AC3 = 23,
+ MSM_ADSP_MODE_TUNNEL = 24,
+ MSM_ADSP_MODE_NONTUNNEL = 25,
+ MSM_ADSP_MODE_LP = 26,
+ MSM_ADSP_OP_DMA = 28,
+ MSM_ADSP_OP_DM = 29,
+};
+
+struct msm_adspdec_info {
+ const char *module_name;
+ unsigned module_queueid;
+ int module_decid; /* objid */
+ unsigned nr_codec_support;
+};
+
+/* Carries information about number codec
+ * supported if same codec or different codecs
+ */
+struct dec_instance_table {
+ uint8_t max_instances_same_dec;
+ uint8_t max_instances_diff_dec;
+};
+
+struct msm_adspdec_database {
+ unsigned num_dec;
+ unsigned num_concurrency_support;
+ unsigned int *dec_concurrency_table; /* Bit masked entry to *
+ * represents codec, mode etc */
+ struct msm_adspdec_info *dec_info_list;
+ struct dec_instance_table *dec_instance_list;
+};
+
+enum msm_mdp_hw_revision {
+ MDP_REV_20 = 1,
+ MDP_REV_22,
+ MDP_REV_30,
+ MDP_REV_303,
+ MDP_REV_31,
+ MDP_REV_40,
+ MDP_REV_41,
+ MDP_REV_42,
+ MDP_REV_43,
+ MDP_REV_44,
+};
+
+
+#if defined(CONFIG_USB_PEHCI_HCD) || defined(CONFIG_USB_PEHCI_HCD_MODULE)
+struct isp1763_platform_data {
+ unsigned reset_gpio;
+ int (*setup_gpio)(int enable);
+};
+#endif
+/* common init routines for use by arch/arm/mach-msm/board-*.c */
+
+#ifdef CONFIG_OF_DEVICE
+void msm_8974_init(struct of_dev_auxdata **);
+#endif
+void msm_add_devices(void);
+void msm_8974_add_devices(void);
+void msm_8974_add_drivers(void);
+void msm_map_common_io(void);
+void msm_map_qsd8x50_io(void);
+void msm_map_msm8x60_io(void);
+void msm_map_msm8960_io(void);
+void msm_map_msm8930_io(void);
+void msm_map_apq8064_io(void);
+void msm_map_msm7x30_io(void);
+void msm_map_fsm9xxx_io(void);
+void msm_map_fsm9900_io(void);
+void fsm9900_init_gpiomux(void);
+void fsm9900_rf_init_gpiomux(void);
+void msm_map_8974_io(void);
+void msm_map_8084_io(void);
+void msm_map_mdm9630_io(void);
+void msm_map_msmzirc_io(void);
+void msm_map_msmsamarium_io(void);
+void msm_map_msm8625_io(void);
+void msm_map_msm9625_io(void);
+void msm_init_irq(void);
+void msm_8974_init_irq(void);
+void vic_handle_irq(struct pt_regs *regs);
+void msm_8974_reserve(void);
+void msm_8974_very_early(void);
+void msm_8974_init_gpiomux(void);
+void apq8084_init_gpiomux(void);
+void msm9625_init_gpiomux(void);
+void mdm9630_init_gpiomux(void);
+void msmsamarium_init_gpiomux(void);
+void msm_map_mpq8092_io(void);
+void msm_map_msm8916_io(void);
+void mpq8092_init_gpiomux(void);
+void msm_map_msm8226_io(void);
+void msm8226_init_irq(void);
+void msm8226_init_gpiomux(void);
+void msm8610_init_gpiomux(void);
+void msm_map_msm8610_io(void);
+void msm8610_init_irq(void);
+
+/* Dump debug info (states, rate, etc) of clocks */
+#if defined(CONFIG_ARCH_MSM7X27)
+void msm_clk_dump_debug_info(void);
+#else
+static inline void msm_clk_dump_debug_info(void) {}
+#endif
+
+struct mmc_platform_data;
+int msm_add_sdcc(unsigned int controller,
+ struct mmc_platform_data *plat);
+
+void msm_pm_register_irqs(void);
+struct msm_usb_host_platform_data;
+int msm_add_host(unsigned int host,
+ struct msm_usb_host_platform_data *plat);
+#if defined(CONFIG_USB_FUNCTION_MSM_HSUSB) \
+ || defined(CONFIG_USB_MSM_72K) || defined(CONFIG_USB_MSM_72K_MODULE)
+void msm_hsusb_set_vbus_state(int online);
+#else
+static inline void msm_hsusb_set_vbus_state(int online) {}
+#endif
+
+void msm_snddev_init(void);
+void msm_snddev_init_timpani(void);
+void msm_snddev_poweramp_on(void);
+void msm_snddev_poweramp_off(void);
+void msm_snddev_hsed_voltage_on(void);
+void msm_snddev_hsed_voltage_off(void);
+void msm_snddev_tx_route_config(void);
+void msm_snddev_tx_route_deconfig(void);
+
+#if defined(CONFIG_MSM_SMD) && defined(CONFIG_DEBUG_FS)
+int smd_debugfs_init(void);
+#else
+static inline int smd_debugfs_init(void) { return 0; }
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/debug_mm.h b/arch/arm/mach-msm/include/mach/debug_mm.h
new file mode 100644
index 000000000000..6b27dedee35e
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/debug_mm.h
@@ -0,0 +1,33 @@
+/* Copyright (c) 2009, 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 __ARCH_ARM_MACH_MSM_DEBUG_MM_H_
+#define __ARCH_ARM_MACH_MSM_DEBUG_MM_H_
+
+#include <linux/string.h>
+
+/* The below macro removes the directory path name and retains only the
+ * file name to avoid long path names in log messages that comes as
+ * part of __FILE__ to compiler.
+ */
+#define __MM_FILE__ strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/')+1) : \
+ __FILE__
+
+#define MM_DBG(fmt, args...) pr_debug("[%s] " fmt,\
+ __func__, ##args)
+
+#define MM_INFO(fmt, args...) pr_info("[%s:%s] " fmt,\
+ __MM_FILE__, __func__, ##args)
+
+#define MM_ERR(fmt, args...) pr_err("[%s:%s] " fmt,\
+ __MM_FILE__, __func__, ##args)
+#endif /* __ARCH_ARM_MACH_MSM_DEBUG_MM_H_ */
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index a72d48d42342..31dde30d8582 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -1,6 +1,7 @@
/* linux/include/asm-arm/arch-msm/dma.h
*
* Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2008-2013, 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
@@ -14,8 +15,14 @@
*/
#ifndef __ASM_ARCH_MSM_DMA_H
+#define __ASM_ARCH_MSM_DMA_H
#include <linux/list.h>
+#include <mach/msm_iomap.h>
+
+#if defined(CONFIG_ARCH_FSM9XXX)
+#include <mach/dma-fsm9xxx.h>
+#endif
struct msm_dmov_errdata {
uint32_t flush[6];
@@ -27,46 +34,170 @@ struct msm_dmov_cmd {
void (*complete_func)(struct msm_dmov_cmd *cmd,
unsigned int result,
struct msm_dmov_errdata *err);
- void (*execute_func)(struct msm_dmov_cmd *cmd);
- void *data;
+ 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;
};
-#ifndef CONFIG_ARCH_MSM8X60
void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
-void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
+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);
-#else
-static inline
-void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) { }
-static inline
-void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) { }
-static inline
-int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; }
-#endif
+#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_CONFIG_FORCE_TOP_PTR_RSLT (1 << 2)
-#define DMOV_CONFIG_FORCE_FLUSH_RSLT (1 << 1)
-#define DMOV_CONFIG_IRQ_EN (1 << 0)
+#define DMOV_CONF(ch) DMOV_ADDR(0x240, ch)
+#define DMOV_CONF_SD(sd) (((sd & 4) << 11) | ((sd & 3) << 4))
+#define DMOV_CONF_IRQ_EN (1 << 6)
+#define DMOV_CONF_FORCE_RSLT_EN (1 << 7)
+#define DMOV_CONF_SHADOW_EN (1 << 12)
+#define DMOV_CONF_MPU_DISABLE (1 << 11)
+#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_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_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)
+ */
+
+#if defined(CONFIG_ARCH_MSM8X60)
+#define DMOV_GP_CHAN 15
+
+#define DMOV_NAND_CHAN 17
+#define DMOV_NAND_CHAN_MODEM 26
+#define DMOV_NAND_CHAN_Q6 27
+#define DMOV_NAND_CRCI_CMD 15
+#define DMOV_NAND_CRCI_DATA 3
+
+#define DMOV_CE_IN_CHAN 2
+#define DMOV_CE_IN_CRCI 4
+
+#define DMOV_CE_OUT_CHAN 3
+#define DMOV_CE_OUT_CRCI 5
+
+#define DMOV_CE_HASH_CRCI 15
+
+#define DMOV_SDC1_CHAN 18
+#define DMOV_SDC1_CRCI 1
+
+#define DMOV_SDC2_CHAN 19
+#define DMOV_SDC2_CRCI 4
+
+#define DMOV_SDC3_CHAN 20
+#define DMOV_SDC3_CRCI 2
+
+#define DMOV_SDC4_CHAN 21
+#define DMOV_SDC4_CRCI 5
+
+#define DMOV_SDC5_CHAN 21
+#define DMOV_SDC5_CRCI 14
+
+#define DMOV_TSIF_CHAN 4
+#define DMOV_TSIF_CRCI 6
+
+#define DMOV_HSUART1_TX_CHAN 22
+#define DMOV_HSUART1_TX_CRCI 8
+
+#define DMOV_HSUART1_RX_CHAN 23
+#define DMOV_HSUART1_RX_CRCI 9
+
+#define DMOV_HSUART2_TX_CHAN 8
+#define DMOV_HSUART2_TX_CRCI 13
+
+#define DMOV_HSUART2_RX_CHAN 8
+#define DMOV_HSUART2_RX_CRCI 14
+
+#elif defined(CONFIG_ARCH_MSM9615)
+
+#define DMOV_GP_CHAN 4
+
+#define DMOV_CE_IN_CHAN 0
+#define DMOV_CE_IN_CRCI 12
+
+#define DMOV_CE_OUT_CHAN 1
+#define DMOV_CE_OUT_CRCI 13
+
+#define DMOV_NAND_CHAN 3
+#define DMOV_NAND_CRCI_CMD 15
+#define DMOV_NAND_CRCI_DATA 3
+
+#elif defined(CONFIG_ARCH_FSM9XXX)
+/* defined in dma-fsm9xxx.h */
+
+#else
+#define DMOV_GP_CHAN 4
+
+#define DMOV_CE_IN_CHAN 5
+#define DMOV_CE_IN_CRCI 1
+
+#define DMOV_CE_OUT_CHAN 6
+#define DMOV_CE_OUT_CRCI 2
+
+#define DMOV_CE_HASH_CRCI 3
+
#define DMOV_NAND_CHAN 7
#define DMOV_NAND_CRCI_CMD 5
#define DMOV_NAND_CRCI_DATA 4
@@ -77,11 +208,47 @@ int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; }
#define DMOV_SDC2_CHAN 8
#define DMOV_SDC2_CRCI 7
+#define DMOV_SDC3_CHAN 8
+#define DMOV_SDC3_CRCI 12
+
+#define DMOV_SDC4_CHAN 8
+#define DMOV_SDC4_CRCI 13
+
#define DMOV_TSIF_CHAN 10
#define DMOV_TSIF_CRCI 10
#define DMOV_USB_CHAN 11
+#define DMOV_HSUART1_TX_CHAN 4
+#define DMOV_HSUART1_TX_CRCI 8
+
+#define DMOV_HSUART1_RX_CHAN 9
+#define DMOV_HSUART1_RX_CRCI 9
+
+#define DMOV_HSUART2_TX_CHAN 4
+#define DMOV_HSUART2_TX_CRCI 14
+
+#define DMOV_HSUART2_RX_CHAN 11
+#define DMOV_HSUART2_RX_CRCI 15
+#endif
+
+/* 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 4
+#define DMOV8064_TSIF_CRCI 1
+
+/* 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
+
/* no client rate control ifc (eg, ram) */
#define DMOV_NONE_CRCI 0
diff --git a/arch/arm/mach-msm/include/mach/entry-macro.S b/arch/arm/mach-msm/include/mach/entry-macro.S
index f2ae9087f654..5b43f2a6ecb4 100644
--- a/arch/arm/mach-msm/include/mach/entry-macro.S
+++ b/arch/arm/mach-msm/include/mach/entry-macro.S
@@ -1,4 +1,5 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/*
+ * Copyright (c) 2009-2010, 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
@@ -8,12 +9,6 @@
* 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.
- *
*/
#if !defined(CONFIG_ARM_GIC)
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
new file mode 100644
index 000000000000..1cfea4959856
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Author: Mike Lockwood <lockwood@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __ASM_ARCH_MSM_GPIO_H
+#define __ASM_ARCH_MSM_GPIO_H
+
+#define ARCH_NR_GPIOS 1024
+
+#include <linux/interrupt.h>
+#include <asm-generic/gpio.h>
+#include <mach/irqs.h>
+
+#define FIRST_BOARD_GPIO NR_GPIO_IRQS
+
+
+/**
+ * struct msm_gpio - GPIO pin description
+ * @gpio_cfg - configuration bitmap, as per gpio_tlmm_config()
+ * @label - textual label
+ *
+ * Usually, GPIO's are operated by sets.
+ * This struct accumulate all GPIO information in single source
+ * and facilitete group operations provided by msm_gpios_xxx()
+ */
+struct msm_gpio {
+ u32 gpio_cfg;
+ const char *label;
+};
+
+struct msm_gpio_pdata {
+ int ngpio;
+ int direct_connect_irqs;
+};
+
+/**
+ * msm_gpios_request_enable() - request and enable set of GPIOs
+ *
+ * Request and configure set of GPIO's
+ * In case of error, all operations rolled back.
+ * Return error code.
+ *
+ * @table: GPIO table
+ * @size: number of entries in @table
+ */
+int msm_gpios_request_enable(const struct msm_gpio *table, int size);
+
+/**
+ * msm_gpios_disable_free() - disable and free set of GPIOs
+ *
+ * @table: GPIO table
+ * @size: number of entries in @table
+ */
+void msm_gpios_disable_free(const struct msm_gpio *table, int size);
+
+/**
+ * msm_gpios_request() - request set of GPIOs
+ * In case of error, all operations rolled back.
+ * Return error code.
+ *
+ * @table: GPIO table
+ * @size: number of entries in @table
+ */
+int msm_gpios_request(const struct msm_gpio *table, int size);
+
+/**
+ * msm_gpios_free() - free set of GPIOs
+ *
+ * @table: GPIO table
+ * @size: number of entries in @table
+ */
+void msm_gpios_free(const struct msm_gpio *table, int size);
+
+/**
+ * msm_gpios_enable() - enable set of GPIOs
+ * In case of error, all operations rolled back.
+ * Return error code.
+ *
+ * @table: GPIO table
+ * @size: number of entries in @table
+ */
+int msm_gpios_enable(const struct msm_gpio *table, int size);
+
+/**
+ * msm_gpios_disable() - disable set of GPIOs
+ *
+ * @table: GPIO table
+ * @size: number of entries in @table
+ */
+int msm_gpios_disable(const struct msm_gpio *table, int size);
+
+/**
+ * msm_gpios_show_resume_irq() - show the interrupts that could have triggered
+ * resume
+ */
+void msm_gpio_show_resume_irq(void);
+
+/* GPIO TLMM (Top Level Multiplexing) Definitions */
+
+/* GPIO TLMM: Function -- GPIO specific */
+
+/* GPIO TLMM: Direction */
+enum {
+ GPIO_CFG_INPUT,
+ GPIO_CFG_OUTPUT,
+};
+
+/* GPIO TLMM: Pullup/Pulldown */
+enum {
+ GPIO_CFG_NO_PULL,
+ GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_KEEPER,
+ GPIO_CFG_PULL_UP,
+};
+
+/* GPIO TLMM: Drive Strength */
+enum {
+ GPIO_CFG_2MA,
+ GPIO_CFG_4MA,
+ GPIO_CFG_6MA,
+ GPIO_CFG_8MA,
+ GPIO_CFG_10MA,
+ GPIO_CFG_12MA,
+ GPIO_CFG_14MA,
+ GPIO_CFG_16MA,
+};
+
+enum {
+ GPIO_CFG_ENABLE,
+ GPIO_CFG_DISABLE,
+};
+
+#define GPIO_CFG(gpio, func, dir, pull, drvstr) \
+ ((((gpio) & 0x3FF) << 4) | \
+ ((func) & 0xf) | \
+ (((dir) & 0x1) << 14) | \
+ (((pull) & 0x3) << 15) | \
+ (((drvstr) & 0xF) << 17))
+
+/**
+ * extract GPIO pin from bit-field used for gpio_tlmm_config
+ */
+#define GPIO_PIN(gpio_cfg) (((gpio_cfg) >> 4) & 0x3ff)
+#define GPIO_FUNC(gpio_cfg) (((gpio_cfg) >> 0) & 0xf)
+#define GPIO_DIR(gpio_cfg) (((gpio_cfg) >> 14) & 0x1)
+#define GPIO_PULL(gpio_cfg) (((gpio_cfg) >> 15) & 0x3)
+#define GPIO_DRVSTR(gpio_cfg) (((gpio_cfg) >> 17) & 0xf)
+
+int gpio_tlmm_config(unsigned config, unsigned disable);
+
+enum msm_tlmm_hdrive_tgt {
+ TLMM_HDRV_SDC4_CLK = 0,
+ TLMM_HDRV_SDC4_CMD,
+ TLMM_HDRV_SDC4_DATA,
+ TLMM_HDRV_SDC3_CLK,
+ TLMM_HDRV_SDC3_CMD,
+ TLMM_HDRV_SDC3_DATA,
+ TLMM_HDRV_SDC2_CLK,
+ TLMM_HDRV_SDC2_CMD,
+ TLMM_HDRV_SDC2_DATA,
+ TLMM_HDRV_SDC1_CLK,
+ TLMM_HDRV_SDC1_CMD,
+ TLMM_HDRV_SDC1_DATA,
+};
+
+enum msm_tlmm_pull_tgt {
+ TLMM_PULL_SDC4_CLK = 0,
+ TLMM_PULL_SDC4_CMD,
+ TLMM_PULL_SDC4_DATA,
+ TLMM_PULL_SDC3_CLK,
+ TLMM_PULL_SDC3_CMD,
+ TLMM_PULL_SDC3_DATA,
+ TLMM_PULL_SDC2_CLK,
+ TLMM_PULL_SDC2_CMD,
+ TLMM_PULL_SDC2_DATA,
+ TLMM_PULL_SDC1_CLK,
+ TLMM_PULL_SDC1_CMD,
+ TLMM_PULL_SDC1_DATA,
+ TLMM_PULL_SDC1_RCLK,
+};
+
+#if defined(CONFIG_GPIO_MSM_V2) || defined(CONFIG_GPIO_MSM_V3)
+void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt, int drv_str);
+void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull);
+
+/*
+ * A GPIO can be set as a direct-connect IRQ. This can be used to bypass
+ * the normal summary-interrupt mechanism for those GPIO lines deemed to be
+ * higher priority or otherwise worthy of special treatment, but resources
+ * are limited: only a few DC interrupt lines are available.
+ * Care must be taken when usurping a GPIO in this manner, as the summary
+ * interrupt controller has no idea that the GPIO has been taken away from it.
+ * Clients can still register to receive the summary interrupt assigned
+ * to that GPIO, which will uninstall it as a direct connect IRQ with
+ * no warning.
+ *
+ * The irq passed to this function is the DC IRQ number, not the
+ * irq number seen by the scorpion when the interrupt triggers. For example,
+ * if 0 is specified, then when DC IRQ 0 triggers, the scorpion will see
+ * interrupt TLMM_MSM_DIR_CONN_IRQ_0.
+ *
+ * input_polarity parameter specifies when the gpio should raise the direct
+ * interrupt. A value of 0 means that it is active low, anything else means
+ * active high
+ *
+ */
+int msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+ unsigned int input_polarity);
+#else
+static inline void msm_tlmm_set_hdrive(enum msm_tlmm_hdrive_tgt tgt,
+ int drv_str) {}
+static inline void msm_tlmm_set_pull(enum msm_tlmm_pull_tgt tgt, int pull) {}
+static inline int msm_gpio_install_direct_irq(unsigned gpio, unsigned irq,
+ unsigned int input_polarity)
+{
+ return -ENOSYS;
+}
+#endif
+
+#endif /* __ASM_ARCH_MSM_GPIO_H */
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
new file mode 100644
index 000000000000..2278677bac17
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -0,0 +1,216 @@
+/* Copyright (c) 2010-2011,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 __ARCH_ARM_MACH_MSM_GPIOMUX_H
+#define __ARCH_ARM_MACH_MSM_GPIOMUX_H
+
+#include <linux/bitops.h>
+#include <linux/errno.h>
+
+enum msm_gpiomux_setting {
+ GPIOMUX_ACTIVE = 0,
+ GPIOMUX_SUSPENDED,
+ GPIOMUX_NSETTINGS
+};
+
+enum gpiomux_drv {
+ GPIOMUX_DRV_2MA = 0,
+ GPIOMUX_DRV_4MA,
+ GPIOMUX_DRV_6MA,
+ GPIOMUX_DRV_8MA,
+ GPIOMUX_DRV_10MA,
+ GPIOMUX_DRV_12MA,
+ GPIOMUX_DRV_14MA,
+ GPIOMUX_DRV_16MA,
+};
+
+enum gpiomux_func {
+ GPIOMUX_FUNC_GPIO = 0,
+ GPIOMUX_FUNC_1,
+ GPIOMUX_FUNC_2,
+ GPIOMUX_FUNC_3,
+ GPIOMUX_FUNC_4,
+ GPIOMUX_FUNC_5,
+ GPIOMUX_FUNC_6,
+ GPIOMUX_FUNC_7,
+ GPIOMUX_FUNC_8,
+ GPIOMUX_FUNC_9,
+ GPIOMUX_FUNC_A,
+ GPIOMUX_FUNC_B,
+ GPIOMUX_FUNC_C,
+ GPIOMUX_FUNC_D,
+ GPIOMUX_FUNC_E,
+ GPIOMUX_FUNC_F,
+};
+
+enum gpiomux_pull {
+ GPIOMUX_PULL_NONE = 0,
+ GPIOMUX_PULL_DOWN,
+ GPIOMUX_PULL_KEEPER,
+ GPIOMUX_PULL_UP,
+};
+
+/* Direction settings are only meaningful when GPIOMUX_FUNC_GPIO is selected.
+ * This element is ignored for all other FUNC selections, as the output-
+ * enable pin is not under software control in those cases. See the SWI
+ * for your target for more details.
+ */
+enum gpiomux_dir {
+ GPIOMUX_IN = 0,
+ GPIOMUX_OUT_HIGH,
+ GPIOMUX_OUT_LOW,
+};
+
+struct gpiomux_setting {
+ enum gpiomux_func func;
+ enum gpiomux_drv drv;
+ enum gpiomux_pull pull;
+ enum gpiomux_dir dir;
+};
+
+/**
+ * struct msm_gpiomux_config: gpiomux settings for one gpio line.
+ *
+ * A complete gpiomux config is the combination of a drive-strength,
+ * function, pull, and (sometimes) direction. For functions other than GPIO,
+ * the input/output setting is hard-wired according to the function.
+ *
+ * @gpio: The index number of the gpio being described.
+ * @settings: The settings to be installed, specifically:
+ * GPIOMUX_ACTIVE: The setting to be installed when the
+ * line is active, or its reference count is > 0.
+ * GPIOMUX_SUSPENDED: The setting to be installed when
+ * the line is suspended, or its reference count is 0.
+ */
+struct msm_gpiomux_config {
+ unsigned gpio;
+ struct gpiomux_setting *settings[GPIOMUX_NSETTINGS];
+};
+
+/**
+ * struct msm_gpiomux_configs: a collection of gpiomux configs.
+ *
+ * It is so common to manage blocks of gpiomux configs that the data structure
+ * for doing so has been standardized here as a convenience.
+ *
+ * @cfg: A pointer to the first config in an array of configs.
+ * @ncfg: The number of configs in the array.
+ */
+struct msm_gpiomux_configs {
+ struct msm_gpiomux_config *cfg;
+ size_t ncfg;
+};
+
+/* Provide an enum and an API to write to misc TLMM registers */
+enum msm_tlmm_misc_reg {
+ TLMM_ETM_MODE_REG = 0x2014,
+ TLMM_SDC2_HDRV_PULL_CTL = 0x2048,
+ TLMM_SPARE_REG = 0x2024,
+ TLMM_CDC_HDRV_CTL = 0x2054,
+ TLMM_CDC_HDRV_PULL_CTL = 0x2058,
+};
+
+#ifdef CONFIG_MSM_GPIOMUX
+
+/* Before using gpiomux, initialize the subsystem by telling it how many
+ * gpios are going to be managed. Calling any other gpiomux functions before
+ * msm_gpiomux_init is unsupported.
+ */
+int msm_gpiomux_init(size_t ngpio);
+
+/* DT Variant of msm_gpiomux_init. This will look up the number of gpios from
+ * device tree rather than relying on NR_GPIO_IRQS
+ */
+int msm_gpiomux_init_dt(void);
+
+/* Install a block of gpiomux configurations in gpiomux. This is functionally
+ * identical to calling msm_gpiomux_write many times.
+ */
+void msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs);
+
+/* Install a block of gpiomux configurations in gpiomux. Do not however write
+ * to hardware. Just store the settings to be retrieved at a later time
+ */
+void msm_gpiomux_install_nowrite(struct msm_gpiomux_config *configs,
+ unsigned nconfigs);
+
+/* Increment a gpio's reference count, possibly activating the line. */
+int __must_check msm_gpiomux_get(unsigned gpio);
+
+/* Decrement a gpio's reference count, possibly suspending the line. */
+int msm_gpiomux_put(unsigned gpio);
+
+/* Install a new setting in a gpio. To erase a slot, use NULL.
+ * The old setting that was overwritten can be passed back to the caller
+ * old_setting can be NULL if the caller is not interested in the previous
+ * setting
+ * If a previous setting was not available to return (NULL configuration)
+ * - the function returns 1
+ * else function returns 0
+ */
+int msm_gpiomux_write(unsigned gpio, enum msm_gpiomux_setting which,
+ struct gpiomux_setting *setting, struct gpiomux_setting *old_setting);
+
+/* Architecture-internal function for use by the framework only.
+ * This function can assume the following:
+ * - the gpio value has passed a bounds-check
+ * - the gpiomux spinlock has been obtained
+ *
+ * This function is not for public consumption. External users
+ * should use msm_gpiomux_write.
+ */
+void __msm_gpiomux_write(unsigned gpio, struct gpiomux_setting val);
+
+/* Functions that provide an API for drivers to read from and write to
+ * miscellaneous TLMM registers.
+ */
+int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg);
+
+void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);
+
+#else
+static inline int msm_gpiomux_init(size_t ngpio)
+{
+ return -ENOSYS;
+}
+
+static inline void
+msm_gpiomux_install(struct msm_gpiomux_config *configs, unsigned nconfigs) {}
+
+static inline int __must_check msm_gpiomux_get(unsigned gpio)
+{
+ return -ENOSYS;
+}
+
+static inline int msm_gpiomux_put(unsigned gpio)
+{
+ return -ENOSYS;
+}
+
+static inline int msm_gpiomux_write(unsigned gpio,
+ enum msm_gpiomux_setting which, struct gpiomux_setting *setting,
+ struct gpiomux_setting *old_setting)
+{
+ return -ENOSYS;
+}
+
+static inline int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg)
+{
+ return -ENOSYS;
+}
+
+static inline void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg,
+ int val)
+{
+}
+
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/hardware.h b/arch/arm/mach-msm/include/mach/hardware.h
index 2d126091ae41..fbf289e209f8 100644
--- a/arch/arm/mach-msm/include/mach/hardware.h
+++ b/arch/arm/mach-msm/include/mach/hardware.h
@@ -1,6 +1,7 @@
/* arch/arm/mach-msm/include/mach/hardware.h
*
* Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 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
@@ -14,5 +15,8 @@
*/
#ifndef __ASM_ARCH_MSM_HARDWARE_H
+#define __ASM_ARCH_MSM_HARDWARE_H
+
+#define pcibios_assign_all_busses() 1
#endif
diff --git a/arch/arm/mach-msm/include/mach/io.h b/arch/arm/mach-msm/include/mach/io.h
new file mode 100644
index 000000000000..445e17567b10
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/io.h
@@ -0,0 +1,23 @@
+/*
+ * 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 __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/ipc_bridge.h b/arch/arm/mach-msm/include/mach/ipc_bridge.h
new file mode 100644
index 000000000000..a0e12d6f9af5
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/ipc_bridge.h
@@ -0,0 +1,65 @@
+/* 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 __MSM_IPC_BRIDGE_H__
+#define __MSM_IPC_BRIDGE_H__
+
+#include <linux/platform_device.h>
+
+/*
+ * The IPC bridge driver adds a IPC bridge platform device when the
+ * underlying transport is ready. The IPC transport driver acts as a
+ * platform driver for this device. The platform data is populated by
+ * IPC bridge driver to facilitate I/O. The callback functions are
+ * passed in platform data to avoid export functions. This would allow
+ * different bridge drivers to exist in the kernel. The IPC bridge driver
+ * removes the platform device when the underly transport is no longer
+ * available. It typically happens during shutdown and remote processor's
+ * subsystem restart.
+ */
+
+/**
+ * struct ipc_bridge_platform_data - platform device data for IPC
+ * transport driver.
+ * @max_read_size: The maximum possible read size.
+ * @max_write_size: The maximum possible write size.
+ * @open: The open must be called before starting I/O. The IPC bridge
+ * driver use the platform device pointer to identify the
+ * underlying transport channel. The IPC bridge driver may
+ * notify that remote processor that it is ready to receive
+ * data. Returns 0 upon success and appropriate error code
+ * upon failure.
+ * @read: The read is done synchronously and should be called from process
+ * context. Returns the number of bytes read from remote
+ * processor or error code upon failure. The IPC transport
+ * driver may pass the buffer of max_read_size length if the
+ * available data size is not known in advance.
+ * @write: The write is done synchronously and should be called from process
+ * context. The IPC bridge driver uses the same buffer for DMA
+ * to avoid additional memcpy. So it must be physically contiguous.
+ * Returns the number of bytes written or error code upon failure.
+ * @close: The close must be called when the IPC bridge platform device
+ * is removed. The IPC transport driver may call close when
+ * it is no longer required to communicate with remote processor.
+ */
+struct ipc_bridge_platform_data {
+ unsigned int max_read_size;
+ unsigned int max_write_size;
+ int (*open)(struct platform_device *pdev);
+ int (*read)(struct platform_device *pdev, char *buf,
+ unsigned int count);
+ int (*write)(struct platform_device *pdev, char *buf,
+ unsigned int count);
+ void (*close)(struct platform_device *pdev);
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
new file mode 100644
index 000000000000..fd72a23d77ed
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -0,0 +1,57 @@
+/* arch/arm/mach-msm/include/mach/memory.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-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 __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+#include <linux/types.h>
+
+/* physical offset of RAM */
+#define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)
+
+#ifndef __ASSEMBLY__
+int msm_get_memory_type_from_name(const char *memtype_name);
+
+#ifdef CONFIG_CACHE_L2X0
+extern void l2x0_cache_sync(void);
+#define finish_arch_switch(prev) do { l2x0_cache_sync(); } while (0)
+#endif
+
+#define MAX_HOLE_ADDRESS (PHYS_OFFSET + 0x10000000)
+/*
+ * Need a temporary unique variable that no one will ever see to
+ * hold the compat string. Line number gives this easily.
+ * Need another layer of indirection to get __LINE__ to expand
+ * properly as opposed to appending and ending up with
+ * __compat___LINE__
+ */
+#define __CONCAT(a, b) ___CONCAT(a, b)
+#define ___CONCAT(a, b) a ## b
+
+#define EXPORT_COMPAT(com) \
+static char *__CONCAT(__compat_, __LINE__) __used \
+ __attribute((__section__(".exportcompat.init"))) = com
+
+extern char *__compat_exports_start[];
+extern char *__compat_exports_end[];
+
+#endif
+
+#if defined CONFIG_ARCH_MSM_SCORPION || defined CONFIG_ARCH_MSM_KRAIT
+#define arch_has_speculative_dfetch() 1
+#endif
+
+#endif
+
+#define CONSISTENT_DMA_SIZE (SZ_1M * 14)
diff --git a/arch/arm/mach-msm/include/mach/mpp.h b/arch/arm/mach-msm/include/mach/mpp.h
new file mode 100644
index 000000000000..1198fd3c972e
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/mpp.h
@@ -0,0 +1,262 @@
+/* Copyright (c) 2008-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 __ARCH_ARM_MACH_MSM_MPP_H
+#define __ARCH_ARM_MACH_MSM_MPP_H
+
+#define MPPS 22
+
+/* Digital Logical Output Level */
+enum {
+ MPP_DLOGIC_LVL_MSME,
+ MPP_DLOGIC_LVL_MSMP,
+ MPP_DLOGIC_LVL_RUIM,
+ MPP_DLOGIC_LVL_MMC,
+ MPP_DLOGIC_LVL_VDD,
+};
+
+/* Digital Logical Output Control Value */
+enum {
+ MPP_DLOGIC_OUT_CTRL_LOW,
+ MPP_DLOGIC_OUT_CTRL_HIGH,
+ MPP_DLOGIC_OUT_CTRL_MPP, /* MPP Output = MPP Input */
+ MPP_DLOGIC_OUT_CTRL_NOT_MPP, /* MPP Output = Inverted MPP Input */
+};
+
+/* Digital Logical Input Value */
+enum {
+ MPP_DLOGIC_IN_DBUS_NONE,
+ MPP_DLOGIC_IN_DBUS_1,
+ MPP_DLOGIC_IN_DBUS_2,
+ MPP_DLOGIC_IN_DBUS_3,
+};
+
+#define MPP_CFG(level, control) ((((level) & 0x0FFFF) << 16) | \
+ ((control) & 0x0FFFF))
+#define MPP_CFG_INPUT(level, dbus) ((((level) & 0x0FFFF) << 16) | \
+ ((dbus) & 0x0FFFF))
+
+/* Use mpp number starting from 0 */
+int mpp_config_digital_out(unsigned mpp, unsigned config);
+int mpp_config_digital_in(unsigned mpp, unsigned config);
+
+/* PM8058/PM8901 definitions */
+
+/* APIs */
+static inline int pm8058_mpp_config(unsigned mpp, unsigned type,
+ unsigned level, unsigned control)
+{
+ return -EINVAL;
+}
+
+static inline int pm8901_mpp_config(unsigned mpp, unsigned type,
+ unsigned level, unsigned control)
+{
+ return -EINVAL;
+}
+
+/* MPP Type: type */
+#define PM_MPP_TYPE_D_INPUT 0
+#define PM_MPP_TYPE_D_OUTPUT 1
+#define PM_MPP_TYPE_D_BI_DIR 2
+#define PM_MPP_TYPE_A_INPUT 3
+#define PM_MPP_TYPE_A_OUTPUT 4
+#define PM_MPP_TYPE_SINK 5
+#define PM_MPP_TYPE_DTEST_SINK 6
+#define PM_MPP_TYPE_DTEST_OUTPUT 7
+
+
+/* Digital Input/Output: level [8058] */
+#define PM8058_MPP_DIG_LEVEL_VPH 0
+#define PM8058_MPP_DIG_LEVEL_S3 1
+#define PM8058_MPP_DIG_LEVEL_L2 2
+#define PM8058_MPP_DIG_LEVEL_L3 3
+
+/* Digital Input/Output: level [8901] */
+#define PM8901_MPP_DIG_LEVEL_MSMIO 0
+#define PM8901_MPP_DIG_LEVEL_DIG 1
+#define PM8901_MPP_DIG_LEVEL_L5 2
+#define PM8901_MPP_DIG_LEVEL_S4 3
+#define PM8901_MPP_DIG_LEVEL_VPH 4
+
+/* Digital Input: control */
+#define PM_MPP_DIN_TO_INT 0
+#define PM_MPP_DIN_TO_DBUS1 1
+#define PM_MPP_DIN_TO_DBUS2 2
+#define PM_MPP_DIN_TO_DBUS3 3
+
+/* Digital Output: control */
+#define PM_MPP_DOUT_CTL_LOW 0
+#define PM_MPP_DOUT_CTL_HIGH 1
+#define PM_MPP_DOUT_CTL_MPP 2
+#define PM_MPP_DOUT_CTL_INV_MPP 3
+
+/* Bidirectional: control */
+#define PM_MPP_BI_PULLUP_1KOHM 0
+#define PM_MPP_BI_PULLUP_OPEN 1
+#define PM_MPP_BI_PULLUP_10KOHM 2
+#define PM_MPP_BI_PULLUP_30KOHM 3
+
+/* Analog Input: level */
+#define PM_MPP_AIN_AMUX_CH5 0
+#define PM_MPP_AIN_AMUX_CH6 1
+#define PM_MPP_AIN_AMUX_CH7 2
+#define PM_MPP_AIN_AMUX_CH8 3
+#define PM_MPP_AIN_AMUX_CH9 4
+#define PM_MPP_AIN_AMUX_ABUS1 5
+#define PM_MPP_AIN_AMUX_ABUS2 6
+#define PM_MPP_AIN_AMUX_ABUS3 7
+
+/* Analog Output: level */
+#define PM_MPP_AOUT_LVL_1V25 0
+#define PM_MPP_AOUT_LVL_1V25_2 1
+#define PM_MPP_AOUT_LVL_0V625 2
+#define PM_MPP_AOUT_LVL_0V3125 3
+#define PM_MPP_AOUT_LVL_MPP 4
+#define PM_MPP_AOUT_LVL_ABUS1 5
+#define PM_MPP_AOUT_LVL_ABUS2 6
+#define PM_MPP_AOUT_LVL_ABUS3 7
+
+/* Analog Output: control */
+#define PM_MPP_AOUT_CTL_DISABLE 0
+#define PM_MPP_AOUT_CTL_ENABLE 1
+#define PM_MPP_AOUT_CTL_MPP_HIGH_EN 2
+#define PM_MPP_AOUT_CTL_MPP_LOW_EN 3
+
+/* Current Sink: level */
+#define PM_MPP_CS_OUT_5MA 0
+#define PM_MPP_CS_OUT_10MA 1
+#define PM_MPP_CS_OUT_15MA 2
+#define PM_MPP_CS_OUT_20MA 3
+#define PM_MPP_CS_OUT_25MA 4
+#define PM_MPP_CS_OUT_30MA 5
+#define PM_MPP_CS_OUT_35MA 6
+#define PM_MPP_CS_OUT_40MA 7
+
+/* Current Sink: control */
+#define PM_MPP_CS_CTL_DISABLE 0
+#define PM_MPP_CS_CTL_ENABLE 1
+#define PM_MPP_CS_CTL_MPP_HIGH_EN 2
+#define PM_MPP_CS_CTL_MPP_LOW_EN 3
+
+/* DTEST Current Sink: control */
+#define PM_MPP_DTEST_CS_CTL_EN1 0
+#define PM_MPP_DTEST_CS_CTL_EN2 1
+#define PM_MPP_DTEST_CS_CTL_EN3 2
+#define PM_MPP_DTEST_CS_CTL_EN4 3
+
+/* DTEST Digital Output: control */
+#define PM_MPP_DTEST_DBUS1 0
+#define PM_MPP_DTEST_DBUS2 1
+#define PM_MPP_DTEST_DBUS3 2
+#define PM_MPP_DTEST_DBUS4 3
+
+/* Helper APIs */
+static inline int pm8058_mpp_config_digital_in(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8058_mpp_config(mpp, PM_MPP_TYPE_D_INPUT, level, control);
+}
+
+static inline int pm8058_mpp_config_digital_out(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8058_mpp_config(mpp, PM_MPP_TYPE_D_OUTPUT, level, control);
+}
+
+static inline int pm8058_mpp_config_bi_dir(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8058_mpp_config(mpp, PM_MPP_TYPE_D_BI_DIR, level, control);
+}
+
+static inline int pm8058_mpp_config_analog_input(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8058_mpp_config(mpp, PM_MPP_TYPE_A_INPUT, level, control);
+}
+
+static inline int pm8058_mpp_config_analog_output(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8058_mpp_config(mpp, PM_MPP_TYPE_A_OUTPUT, level, control);
+}
+
+static inline int pm8058_mpp_config_current_sink(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8058_mpp_config(mpp, PM_MPP_TYPE_SINK, level, control);
+}
+
+static inline int pm8058_mpp_config_dtest_sink(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8058_mpp_config(mpp, PM_MPP_TYPE_DTEST_SINK, level, control);
+}
+
+static inline int pm8058_mpp_config_dtest_output(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8058_mpp_config(mpp, PM_MPP_TYPE_DTEST_OUTPUT,
+ level, control);
+}
+
+static inline int pm8901_mpp_config_digital_in(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8901_mpp_config(mpp, PM_MPP_TYPE_D_INPUT, level, control);
+}
+
+static inline int pm8901_mpp_config_digital_out(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8901_mpp_config(mpp, PM_MPP_TYPE_D_OUTPUT, level, control);
+}
+
+static inline int pm8901_mpp_config_bi_dir(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8901_mpp_config(mpp, PM_MPP_TYPE_D_BI_DIR, level, control);
+}
+
+static inline int pm8901_mpp_config_analog_input(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8901_mpp_config(mpp, PM_MPP_TYPE_A_INPUT, level, control);
+}
+
+static inline int pm8901_mpp_config_analog_output(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8901_mpp_config(mpp, PM_MPP_TYPE_A_OUTPUT, level, control);
+}
+
+static inline int pm8901_mpp_config_current_sink(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8901_mpp_config(mpp, PM_MPP_TYPE_SINK, level, control);
+}
+
+static inline int pm8901_mpp_config_dtest_sink(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8901_mpp_config(mpp, PM_MPP_TYPE_DTEST_SINK, level, control);
+}
+
+static inline int pm8901_mpp_config_dtest_output(unsigned mpp, unsigned level,
+ unsigned control)
+{
+ return pm8901_mpp_config(mpp, PM_MPP_TYPE_DTEST_OUTPUT,
+ level, control);
+}
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h b/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
new file mode 100644
index 000000000000..5e927cfbc951
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2011-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 __ASM_ARCH_MSM_MSM_KRAIT_L2_ACCESSORS_H
+#define __ASM_ARCH_MSM_MSM_KRAIT_L2_ACCESSORS_H
+
+#define MAX_L2_PERIOD ((1ULL << 32) - 1)
+#define MAX_KRAIT_L2_CTRS 10
+
+#define PMCR_NUM_EV_SHIFT 11
+#define PMCR_NUM_EV_MASK 0x1f
+
+#define L2_EVT_MASK 0xfffff
+
+#define L2_SLAVE_EV_PREFIX 4
+#define L2_TRACECTR_PREFIX 5
+
+#define L2PMCCNTR 0x409
+#define L2PMCCNTCR 0x408
+#define L2PMCCNTSR 0x40A
+#define L2CYCLE_CTR_BIT 31
+#define L2CYCLE_CTR_RAW_CODE 0xfe
+
+#define L2PMOVSR 0x406
+
+#define L2PMCR 0x400
+#define L2PMCR_RESET_ALL 0x6
+#define L2PMCR_GLOBAL_ENABLE 0x1
+#define L2PMCR_GLOBAL_DISABLE 0x0
+
+#define L2PMCNTENSET 0x403
+#define L2PMCNTENCLR 0x402
+
+#define L2PMINTENSET 0x405
+#define L2PMINTENCLR 0x404
+
+#define IA_L2PMXEVCNTCR_BASE 0x420
+#define IA_L2PMXEVTYPER_BASE 0x424
+#define IA_L2PMRESX_BASE 0x410
+#define IA_L2PMXEVFILTER_BASE 0x423
+#define IA_L2PMXEVCNTR_BASE 0x421
+
+/* event format is -e rsRCCG See get_event_desc() */
+
+#define EVENT_PREFIX_MASK 0xf0000
+#define EVENT_REG_MASK 0x0f000
+#define EVENT_GROUPSEL_MASK 0x0000f
+#define EVENT_GROUPCODE_MASK 0x00ff0
+
+#define EVENT_PREFIX_SHIFT 16
+#define EVENT_REG_SHIFT 12
+#define EVENT_GROUPCODE_SHIFT 4
+
+#define RESRX_VALUE_EN 0x80000000
+
+#ifdef CONFIG_ARCH_MSM_KRAIT
+extern void set_l2_indirect_reg(u32 reg_addr, u32 val);
+extern u32 get_l2_indirect_reg(u32 reg_addr);
+#else
+static inline void set_l2_indirect_reg(u32 reg_addr, u32 val) {}
+static inline u32 get_l2_indirect_reg(u32 reg_addr)
+{
+ return 0;
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_cache_dump.h b/arch/arm/mach-msm/include/mach/msm_cache_dump.h
new file mode 100644
index 000000000000..a79bcbd2bc36
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_cache_dump.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2012, 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 _MACH_MSM_CACHE_DUMP_
+#define _MACH_MSM_CACHE_DUMP_
+
+#include <asm-generic/sizes.h>
+
+
+struct l2_cache_line_dump {
+ unsigned int l2dcrtr0_val;
+ unsigned int l2dcrtr1_val;
+ unsigned int cache_line_data[32];
+ unsigned int ddr_data[32];
+} __packed;
+
+struct l2_cache_dump {
+ unsigned int magic_number;
+ unsigned int version;
+ unsigned int tag_size;
+ unsigned int line_size;
+ unsigned int total_lines;
+ struct l2_cache_line_dump cache[8*1024];
+ unsigned int l2esr;
+} __packed;
+
+
+struct l1_cache_dump {
+ unsigned int magic;
+ unsigned int version;
+ unsigned int flags;
+ unsigned int cpu_count;
+ unsigned int i_tag_size;
+ unsigned int i_line_size;
+ unsigned int i_num_sets;
+ unsigned int i_num_ways;
+ unsigned int d_tag_size;
+ unsigned int d_line_size;
+ unsigned int d_num_sets;
+ unsigned int d_num_ways;
+ unsigned int spare[32];
+ unsigned int lines[];
+} __packed;
+
+
+struct msm_cache_dump_platform_data {
+ unsigned int l1_size;
+ unsigned int l2_size;
+};
+
+#define CACHE_BUFFER_DUMP_SIZE (L1_BUFFER_SIZE + L2_BUFFER_SIZE)
+
+#define L1C_SERVICE_ID 3
+#define L1C_BUFFER_SET_COMMAND_ID 4
+#define CACHE_BUFFER_DUMP_COMMAND_ID 5
+#define L1C_BUFFER_GET_SIZE_COMMAND_ID 6
+#define L2C_BUFFER_SET_COMMAND_ID 7
+#define L2C_BUFFER_GET_SIZE_COMMAND_ID 8
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8916.h b/arch/arm/mach-msm/include/mach/msm_iomap-8916.h
new file mode 100644
index 000000000000..b1341bba8383
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8916.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013, 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_IOMAP_8916_H
+#define __ASM_ARCH_MSM_IOMAP_8916_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * io desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+#define MSM8916_APCS_GCC_PHYS 0xB011000
+#define MSM8916_APCS_GCC_SIZE SZ_4K
+
+#ifdef CONFIG_DEBUG_MSM8916_UART
+#define MSM_DEBUG_UART_BASE IOMEM(0xFA0B0000)
+#define MSM_DEBUG_UART_PHYS 0x78B0000
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 0e4f49157684..69f7ec67441d 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2014, The Linux Foundation. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -37,12 +37,12 @@
*
*/
-#if defined(CONFIG_ARCH_MSM7X30)
-#include "msm_iomap-7x30.h"
-#elif defined(CONFIG_ARCH_QSD8X50)
-#include "msm_iomap-8x50.h"
-#else
-#include "msm_iomap-7x00.h"
+#define MSM_DEBUG_UART_SIZE SZ_4K
+
+#if defined(CONFIG_DEBUG_MSM_UART1) || defined(CONFIG_DEBUG_MSM_UART2) \
+ || defined(CONFIG_DEBUG_MSM_UART3)
+#define MSM_DEBUG_UART_BASE 0xFC000000
+#define MSM_DEBUG_UART_PHYS CONFIG_MSM_DEBUG_UART_PHYS
#endif
/* Virtual addresses shared across all MSM targets. */
@@ -50,4 +50,49 @@
#define MSM_GPIO1_BASE IOMEM(0xE0003000)
#define MSM_GPIO2_BASE IOMEM(0xE0004000)
+#define MSM8625_WARM_BOOT_PHYS 0x0FD00000
+
+/* Unified iomap */
+
+#define MSM_TMR_BASE IOMEM(0xFA000000) /* 4K */
+#define MSM_TMR0_BASE IOMEM(0xFA001000) /* 4K */
+#define MSM_TCSR_BASE IOMEM(0xFA004000) /* 4K */
+#define MSM_APCS_GCC_BASE IOMEM(0xFA006000) /* 4K */
+#define MSM_SAW_L2_BASE IOMEM(0xFA007000) /* 4K */
+#define MSM_SAW0_BASE IOMEM(0xFA008000) /* 4K */
+#define MSM_SAW1_BASE IOMEM(0xFA009000) /* 4K */
+
+#define MSM_ACC0_BASE IOMEM(0xFA00B000) /* 4K */
+#define MSM_ACC1_BASE IOMEM(0xFA00C000) /* 4K */
+#define MSM_ACC2_BASE IOMEM(0xFA00D000) /* 4K */
+#define MSM_ACC3_BASE IOMEM(0xFA00E000) /* 4K */
+#define MSM_CLK_CTL_BASE IOMEM(0xFA010000) /* 16K */
+#define MSM_MMSS_CLK_CTL_BASE IOMEM(0xFA014000) /* 4K */
+#define MSM_LPASS_CLK_CTL_BASE IOMEM(0xFA015000) /* 4K */
+#define MSM_HFPLL_BASE IOMEM(0xFA016000) /* 4K */
+#define MSM_TLMM_BASE IOMEM(0xFA017000) /* 16K */
+#define MSM_VIC_BASE IOMEM(0xFA100000) /* 4K */
+#define MSM_CSR_BASE IOMEM(0xFA101000) /* 4K */
+#define MSM_GPIO1_BASE IOMEM(0xFA102000) /* 4K */
+#define MSM_GPIO2_BASE IOMEM(0xFA103000) /* 4K */
+#define MSM_SCU_BASE IOMEM(0xFA104000) /* 4K */
+#define MSM_CFG_CTL_BASE IOMEM(0xFA105000) /* 4K */
+#define MSM_CLK_CTL_SH2_BASE IOMEM(0xFA106000) /* 4K */
+#define MSM_MPM2_PSHOLD_BASE IOMEM(0xFA107000) /* 4k */
+#define MSM_SIC_NON_SECURE_BASE IOMEM(0xFA600000) /* 64K */
+#define MSM_QFPROM_BASE IOMEM(0xFA700000) /* 4K */
+#define MSM_L2CC_BASE IOMEM(0xFA701000) /* 4K */
+#define MSM_APCS_GLB_BASE IOMEM(0xFA702000) /* 4K */
+#define MSM_SAW2_BASE IOMEM(0xFA703000) /* 4k */
+#define MSM_SAW3_BASE IOMEM(0xFA704000) /* 4k */
+#define MSM_HDMI_BASE IOMEM(0xFA800000) /* 4K */
+#define MSM_RPM_BASE IOMEM(0xFA801000) /* 4K */
+#define MSM_RPM_MPM_BASE IOMEM(0xFA802000) /* 4K */
+#define MSM_AD5_BASE IOMEM(0xFA900000) /* 13M (D00000)
+ 0xFB600000 */
+#define MSM_STRONGLY_ORDERED_PAGE 0xFA0F0000
+#define MSM8625_CPU_PHYS 0x0FE00000
+
+#include "msm_iomap-8916.h"
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
new file mode 100644
index 000000000000..457432bd1705
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2010-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.
+*/
+
+/* The MSM Hardware supports multiple flavors of physical memory.
+ * This file captures hardware specific information of these types.
+*/
+
+#ifndef __ASM_ARCH_MSM_MEMTYPES_H
+#define __ASM_ARCH_MSM_MEMTYPES_H
+
+#include <mach/memory.h>
+#include <linux/init.h>
+
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname,
+ int depth, void *data);
+int __init dt_scan_for_memory_hole(unsigned long node, const char *uname,
+ int depth, void *data);
+void adjust_meminfo(unsigned long start, unsigned long size);
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_mpmctr.h b/arch/arm/mach-msm/include/mach/msm_mpmctr.h
new file mode 100644
index 000000000000..d3d853fbd6bd
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_mpmctr.h
@@ -0,0 +1,21 @@
+/*
+ * 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 __MSM_MPMCTR_H__
+#define __MSM_MPMCTR_H__
+
+/*
+ * returns the count value of the mpm timetick.
+ */
+uint32_t msm_mpm_get_count(void);
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_pcie.h b/arch/arm/mach-msm/include/mach/msm_pcie.h
new file mode 100644
index 000000000000..b6933c226d5a
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_pcie.h
@@ -0,0 +1,39 @@
+/* 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 __ASM_ARCH_MSM_PCIE_H
+#define __ASM_ARCH_MSM_PCIE_H
+
+#include <linux/types.h>
+
+enum msm_pcie_pm_opt {
+ MSM_PCIE_SUSPEND,
+ MSM_PCIE_RESUME
+};
+
+/**
+ * msm_pcie_pm_control - control the power state of a PCIe link.
+ * @pm_opt: power management operation
+ * @busnr: bus number of PCIe endpoint
+ * @user: handle of the caller
+ * @data: private data from the caller
+ * @options: options for pm control
+ *
+ * This function gives PCIe endpoint device drivers the control to change
+ * the power state of a PCIe link for their device.
+ *
+ * Return: 0 on success, negative value on error
+ */
+int msm_pcie_pm_control(enum msm_pcie_pm_opt pm_opt, u32 busnr, void *user,
+ void *data, u32 options);
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_serial_hsl_regs.h b/arch/arm/mach-msm/include/mach/msm_serial_hsl_regs.h
new file mode 100644
index 000000000000..774c91dd7c99
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_serial_hsl_regs.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011, 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_SERIAL_HSL_REGS_H
+#define __ASM_ARCH_MSM_SERIAL_HSL_REGS_H
+
+#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS_V14
+#define UARTDM_MR2_OFFSET 0x4
+#define UARTDM_CSR_OFFSET 0xa0
+#define UARTDM_SR_OFFSET 0xa4
+#define UARTDM_CR_OFFSET 0xa8
+#define UARTDM_ISR_OFFSET 0xb4
+#define UARTDM_NCF_TX_OFFSET 0x40
+#define UARTDM_TF_OFFSET 0x100
+#else
+#define UARTDM_MR2_OFFSET 0x4
+#define UARTDM_CSR_OFFSET 0x8
+#define UARTDM_SR_OFFSET 0x8
+#define UARTDM_CR_OFFSET 0x10
+#define UARTDM_ISR_OFFSET 0x14
+#define UARTDM_NCF_TX_OFFSET 0x40
+#define UARTDM_TF_OFFSET 0x70
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_serial_pdata.h b/arch/arm/mach-msm/include/mach/msm_serial_pdata.h
new file mode 100644
index 000000000000..7c1319efcfc6
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_serial_pdata.h
@@ -0,0 +1,28 @@
+/* Copyright (c) 2010, 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 __ASM_ARCH_MSM_SERIAL_H
+#define __ASM_ARCH_MSM_SERIAL_H
+
+#include <linux/serial_core.h>
+
+/* Optional platform device data for msm_serial driver.
+ * Used to configure low power wakeup */
+struct msm_serial_platform_data {
+ int wakeup_irq; /* wakeup irq */
+ /* bool: inject char into rx tty on wakeup */
+ unsigned char inject_rx_on_wakeup;
+ char rx_to_inject;
+ int userid;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_spi.h b/arch/arm/mach-msm/include/mach/msm_spi.h
new file mode 100644
index 000000000000..251edc431394
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_spi.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2008-2009, 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.
+ *
+ */
+/*
+ * SPI driver for Qualcomm Technologies, Inc. MSM platforms.
+ */
+
+/**
+ * msm_spi_platform_data: msm spi-controller's configuration data
+ *
+ * @active_only when set, votes when system active and removes the vote when
+ * system goes idle (optimises for performance). When unset, voting using
+ * runtime pm (optimizes for power).
+ * @master_id master id number of the controller's wrapper (BLSP or GSBI).
+ * When zero, clock path voting is disabled.
+ * @rt when set, spi will pump transaction messages with high (realtime)
+ * priority to reduce the transfer latency on the bus by minimising
+ * the delay between a transfer request.
+ */
+struct msm_spi_platform_data {
+ u32 max_clock_speed;
+ bool active_only;
+ u32 master_id;
+ int (*gpio_config)(void);
+ void (*gpio_release)(void);
+ int (*dma_config)(void);
+ const char *rsl_id;
+ u32 pm_lat;
+ u32 infinite_mode;
+ bool ver_reg_exists;
+ bool use_bam;
+ u32 bam_consumer_pipe_index;
+ u32 bam_producer_pipe_index;
+ bool rt_priority;
+ bool use_pinctrl;
+};
diff --git a/arch/arm/mach-msm/include/mach/msm_tspp.h b/arch/arm/mach-msm/include/mach/msm_tspp.h
new file mode 100644
index 000000000000..c02bb212a9ce
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_tspp.h
@@ -0,0 +1,108 @@
+/* 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.
+ */
+
+#ifndef _MSM_TSPP_H_
+#define _MSM_TSPP_H_
+
+struct msm_tspp_platform_data {
+ int num_gpios;
+ const struct msm_gpio *gpios;
+ const char *tsif_pclk;
+ const char *tsif_ref_clk;
+ int tsif_vreg_present;
+};
+
+struct tspp_data_descriptor {
+ void *virt_base; /* logical address of the actual data */
+ phys_addr_t phys_base; /* physical address of the actual data */
+ u32 size; /* size of buffer in bytes */
+ int id; /* unique identifier */
+ void *user; /* user-defined data */
+};
+
+enum tspp_key_parity {
+ TSPP_KEY_PARITY_EVEN,
+ TSPP_KEY_PARITY_ODD
+};
+
+struct tspp_key {
+ enum tspp_key_parity parity;
+ int lsb;
+ int msb;
+};
+
+enum tspp_source {
+ TSPP_SOURCE_TSIF0,
+ TSPP_SOURCE_TSIF1,
+ TSPP_SOURCE_MEM,
+ TSPP_SOURCE_NONE = -1
+};
+
+enum tspp_mode {
+ TSPP_MODE_DISABLED,
+ TSPP_MODE_PES,
+ TSPP_MODE_RAW,
+ TSPP_MODE_RAW_NO_SUFFIX
+};
+
+enum tspp_tsif_mode {
+ TSPP_TSIF_MODE_LOOPBACK, /* loopback mode */
+ TSPP_TSIF_MODE_1, /* without sync */
+ TSPP_TSIF_MODE_2 /* with sync signal */
+};
+
+struct tspp_filter {
+ int pid;
+ int mask;
+ enum tspp_mode mode;
+ unsigned int priority; /* 0 - 15 */
+ int decrypt;
+ enum tspp_source source;
+};
+
+struct tspp_select_source {
+ enum tspp_source source;
+ enum tspp_tsif_mode mode;
+ int clk_inverse;
+ int data_inverse;
+ int sync_inverse;
+ int enable_inverse;
+};
+
+typedef void (tspp_notifier)(int channel_id, void *user);
+typedef void* (tspp_allocator)(int channel_id, u32 size,
+ phys_addr_t *phys_base, void *user);
+typedef void (tspp_memfree)(int channel_id, u32 size,
+ void *virt_base, phys_addr_t phys_base, void *user);
+
+/* Kernel API functions */
+int tspp_open_stream(u32 dev, u32 channel_id,
+ struct tspp_select_source *source);
+int tspp_close_stream(u32 dev, u32 channel_id);
+int tspp_open_channel(u32 dev, u32 channel_id);
+int tspp_close_channel(u32 dev, u32 channel_id);
+int tspp_get_ref_clk_counter(u32 dev,
+ enum tspp_source source, u32 *tcr_counter);
+int tspp_add_filter(u32 dev, u32 channel_id, struct tspp_filter *filter);
+int tspp_remove_filter(u32 dev, u32 channel_id, struct tspp_filter *filter);
+int tspp_set_key(u32 dev, u32 channel_id, struct tspp_key *key);
+int tspp_register_notification(u32 dev, u32 channel_id, tspp_notifier *notify,
+ void *data, u32 timer_ms);
+int tspp_unregister_notification(u32 dev, u32 channel_id);
+const struct tspp_data_descriptor *tspp_get_buffer(u32 dev, u32 channel_id);
+int tspp_release_buffer(u32 dev, u32 channel_id, u32 descriptor_id);
+int tspp_allocate_buffers(u32 dev, u32 channel_id, u32 count,
+ u32 size, u32 int_freq, tspp_allocator *alloc,
+ tspp_memfree *memfree, void *user);
+
+#endif /* _MSM_TSPP_H_ */
+
diff --git a/arch/arm/mach-msm/include/mach/msm_tspp2.h b/arch/arm/mach-msm/include/mach/msm_tspp2.h
new file mode 100644
index 000000000000..80bf13937fed
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_tspp2.h
@@ -0,0 +1,759 @@
+/* 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 _MSM_TSPP2_H_
+#define _MSM_TSPP2_H_
+
+#include <linux/ion.h>
+#include <linux/msm-sps.h>
+
+#define TSPP2_NUM_DEVICES 1
+#define TSPP2_NUM_TSIF_INPUTS 2
+#define TSPP2_NUM_PIPES 31
+#define TSPP2_NUM_MEM_INPUTS 8
+#define TSPP2_NUM_INDEXING_TABLES 4
+#define TSPP2_NUM_INDEXING_PATTERNS 26
+#define TSPP2_MAX_OPS_PER_FILTER 16
+
+#define TSPP2_INVALID_HANDLE 0
+#define TSPP2_UNIQUE_PID_MASK 0x1FFF
+
+/**
+ * struct msm_tspp2_platform_data - TSPP2 platform data
+ *
+ * @hlos_group: IOMMU HLOS group name.
+ * @cpz_group: IOMMU CPZ group name.
+ * @hlos_partition: IOMMU HLOS partition number.
+ * @cpz_partition: IOMMU CPZ partition number.
+ */
+struct msm_tspp2_platform_data {
+ const char *hlos_group;
+ const char *cpz_group;
+ int hlos_partition;
+ int cpz_partition;
+};
+
+/**
+ * struct tspp2_config - Global configuration
+ *
+ * @min_pcr_interval: Minimum time (in msec) between PCR notifications
+ * on the same PID. Setting to 0 means every PCR
+ * is notified. Default value is 50 msec.
+ * @pcr_on_discontinuity: Flag to indicate whether to notify on PCR when
+ * the discontinuity flag is set in the TS packet,
+ * regardless of min_pcr_interval.
+ * @stc_byte_offset: Offset (in bytes) between the 4 byte timestamp
+ * and the 7 byte STC counter.
+ * Valid values are 0 - 3. A value of 0 means the
+ * 4 LSBytes of the STC are used in the timestamp,
+ * while a value of 3 means the 4 MSBytes are used.
+ */
+struct tspp2_config {
+ u8 min_pcr_interval;
+ int pcr_on_discontinuity;
+ u8 stc_byte_offset;
+};
+
+/**
+ * enum tspp2_src_input - Source input type: TSIF or memory
+ *
+ * @TSPP2_INPUT_TSIF0: Input from TSIF 0.
+ * @TSPP2_INPUT_TSIF1: Input from TSIF 1.
+ * @TSPP2_INPUT_MEMORY: Input from memory.
+ */
+enum tspp2_src_input {
+ TSPP2_INPUT_TSIF0 = 0,
+ TSPP2_INPUT_TSIF1 = 1,
+ TSPP2_INPUT_MEMORY = 2
+};
+
+/**
+ * enum tspp2_tsif_mode - TSIF mode of operation
+ *
+ * @TSPP2_TSIF_MODE_LOOPBACK: Loopback mode, used for debug only.
+ * @TSPP2_TSIF_MODE_1: Mode 1: TSIF works with 3 interface signals.
+ * @TSPP2_TSIF_MODE_2: Mode 2: TSIF works with 4 interface signals.
+ */
+enum tspp2_tsif_mode {
+ TSPP2_TSIF_MODE_LOOPBACK,
+ TSPP2_TSIF_MODE_1,
+ TSPP2_TSIF_MODE_2,
+};
+
+/**
+ * enum tspp2_packet_format - Packet size (in bytes) and timestamp format
+ *
+ * @TSPP2_PACKET_FORMAT_188_RAW: Packet size is 188 Bytes, no timestamp.
+ * @TSPP2_PACKET_FORMAT_192_HEAD: Packet size is 192 Bytes,
+ * 4 Byte timestamp before the data.
+ * @TSPP2_PACKET_FORMAT_192_TAIL: Packet size is 192 Bytes,
+ * 4 Byte timestamp after the data.
+ */
+enum tspp2_packet_format {
+ TSPP2_PACKET_FORMAT_188_RAW,
+ TSPP2_PACKET_FORMAT_192_HEAD,
+ TSPP2_PACKET_FORMAT_192_TAIL
+};
+
+/**
+ * struct tspp2_tsif_src_params - TSIF source configuration parameters
+ *
+ * @tsif_mode: TSIF mode of operation.
+ * @clock_inverse: Invert incoming clock signal.
+ * @data_inverse: Invert incoming data signal.
+ * @sync_inverse: Invert incoming sync signal.
+ * @enable_inverse: Invert incoming enable signal.
+ */
+struct tspp2_tsif_src_params {
+ enum tspp2_tsif_mode tsif_mode;
+ int clock_inverse;
+ int data_inverse;
+ int sync_inverse;
+ int enable_inverse;
+};
+
+/**
+ * struct tspp2_src_cfg - Source configuration
+ *
+ * @input: Source input (TSIF0/1 or memory).
+ * @params: source configuration parameters.
+ */
+struct tspp2_src_cfg {
+ enum tspp2_src_input input;
+ union {
+ struct tspp2_tsif_src_params tsif_params;
+ } params;
+};
+
+/**
+ * enum tspp2_src_parsing_option - Parsing options
+ *
+ * @TSPP2_SRC_PARSING_OPT_CHECK_CONTINUITY: Detect discontinuities in
+ * TS packets.
+ * @TSPP2_SRC_PARSING_OPT_IGNORE_DISCONTINUITY: Ignore discontinuity indicator.
+ * If set, discontinuities are
+ * detected according to the
+ * continuity counter only,
+ * which may result in false
+ * positives.
+ * @TSPP2_SRC_PARSING_OPT_ASSUME_DUPLICATE_PACKETS: Assume TS packets
+ * may be duplicated (i.e., have
+ * the same continuity counter).
+ * If cleared, may result in more
+ * discontinuity statuses. If TSPP2
+ * is configured using PID filter
+ * masks it is recommended to
+ * disable this field. Multi PID
+ * filters may detect false
+ * duplicates which will results in
+ * discarded packets.
+ * @TSPP2_SRC_PARSING_OPT_DISCARD_INVALID_AF_PACKETS: Discard TS packets with
+ * invalid Adaptation Field
+ * control.
+ * @TSPP2_SRC_PARSING_OPT_VERIFY_PES_START: Verify PES start code. If
+ * enabled and the PES doesn’t
+ * start with the start code, the
+ * whole PES is not assembled.
+ */
+enum tspp2_src_parsing_option {
+ TSPP2_SRC_PARSING_OPT_CHECK_CONTINUITY,
+ TSPP2_SRC_PARSING_OPT_IGNORE_DISCONTINUITY,
+ TSPP2_SRC_PARSING_OPT_ASSUME_DUPLICATE_PACKETS,
+ TSPP2_SRC_PARSING_OPT_DISCARD_INVALID_AF_PACKETS,
+ TSPP2_SRC_PARSING_OPT_VERIFY_PES_START
+};
+
+/**
+ * enum tspp2_src_scrambling_ctrl - Scrambling bits control
+ *
+ * @TSPP2_SRC_SCRAMBLING_CTRL_PASSTHROUGH: Packet is clear, pass-through
+ * without decryption.
+ * @TSPP2_SRC_SCRAMBLING_CTRL_DISCARD: Discard packet.
+ * @TSPP2_SRC_SCRAMBLING_CTRL_EVEN: Packet is scrambled with
+ * even Key.
+ * @TSPP2_SRC_SCRAMBLING_CTRL_ODD: Packet is scrambled with
+ * odd key.
+ */
+enum tspp2_src_scrambling_ctrl {
+ TSPP2_SRC_SCRAMBLING_CTRL_PASSTHROUGH,
+ TSPP2_SRC_SCRAMBLING_CTRL_DISCARD,
+ TSPP2_SRC_SCRAMBLING_CTRL_EVEN,
+ TSPP2_SRC_SCRAMBLING_CTRL_ODD
+};
+
+/**
+ * enum tspp2_src_scrambling_monitoring - Scrambling bits monitoring
+ *
+ * @TSPP2_SRC_SCRAMBLING_MONITOR_NONE: No scrambling bits monitoring.
+ * @TSPP2_SRC_SCRAMBLING_MONITOR_PES_ONLY: Monitor only PES heaer
+ * scrambling bit control field.
+ * If no PES header was found,
+ * scrambling bits will be
+ * considered as ‘00’.
+ * @TSPP2_SRC_SCRAMBLING_MONITOR_TS_ONLY: Monitor only TS packet header
+ * scrambling bit control field.
+ * @TSPP2_SRC_SCRAMBLING_MONITOR_PES_AND_TS: Monitor both TS packet and PES
+ * header. Monitor result is the
+ * logical OR of the two.
+ */
+enum tspp2_src_scrambling_monitoring {
+ TSPP2_SRC_SCRAMBLING_MONITOR_NONE,
+ TSPP2_SRC_SCRAMBLING_MONITOR_PES_ONLY,
+ TSPP2_SRC_SCRAMBLING_MONITOR_TS_ONLY,
+ TSPP2_SRC_SCRAMBLING_MONITOR_PES_AND_TS
+};
+
+/**
+ * struct tspp2_src_scrambling_config - Source scrambling bits configuration
+ *
+ * Each TS/PES packet has two bits that
+ * control the scrambling, called
+ * transport_scrambling_control. This
+ * configuration sets the user-defined
+ * meaning of these bits.
+ *
+ * @scrambling_0_ctrl: Scrambling bits control for value '00'.
+ * @scrambling_1_ctrl: Scrambling bits control for value '01'.
+ * @scrambling_2_ctrl: Scrambling bits control for value '10'.
+ * @scrambling_3_ctrl: Scrambling bits control for value '11'.
+ * @scrambling_bits_monitoring: Scrambling bits monitoring configuration
+ * for this source.
+ */
+struct tspp2_src_scrambling_config {
+ enum tspp2_src_scrambling_ctrl scrambling_0_ctrl;
+ enum tspp2_src_scrambling_ctrl scrambling_1_ctrl;
+ enum tspp2_src_scrambling_ctrl scrambling_2_ctrl;
+ enum tspp2_src_scrambling_ctrl scrambling_3_ctrl;
+ enum tspp2_src_scrambling_monitoring scrambling_bits_monitoring;
+};
+
+/**
+ * enum tspp2_src_pipe_mode - pipe mode
+ *
+ * @TSPP2_SRC_PIPE_INPUT: An input (consumer) pipe.
+ * @TSPP2_SRC_PIPE_OUTPUT: An output (producer) pipe.
+ */
+enum tspp2_src_pipe_mode {
+ TSPP2_SRC_PIPE_INPUT,
+ TSPP2_SRC_PIPE_OUTPUT
+};
+
+/**
+ * struct tspp2_pipe_pull_mode_params - Pipe pull mode parameters
+ *
+ * @is_stalling: Whether this pipe is stalling when working in pull mode.
+ * Relevant for the source the pipe is being attached to.
+ * Relevant only for output pipes.
+ * @threshold: The threshold used for flow control (in bytes). The
+ * same threshold must be used for all sources.
+ */
+struct tspp2_pipe_pull_mode_params {
+ int is_stalling;
+ u16 threshold;
+};
+
+/**
+ * struct tspp2_pipe_sps_params - Pipe SPS configuration parameters
+ *
+ * @descriptor_size: Size of each pipe descriptor, in bytes.
+ * @descriptor_flags: Descriptor flags (SPS_IOVEC_FLAG_XXX).
+ * @setting: Pipe settings.
+ * @wakeup_events: Pipe wakeup events.
+ * @callback: A callback function invoked on pipe events.
+ * @user_info: User information reported with each event.
+ */
+struct tspp2_pipe_sps_params {
+ u32 descriptor_size;
+ u32 descriptor_flags;
+ enum sps_option setting;
+ enum sps_option wakeup_events;
+ void (*callback)(struct sps_event_notify *notify);
+ void *user_info;
+};
+
+/**
+ * struct tspp2_pipe_config_params - Pipe configuration parameters
+ *
+ * @ion_client: The ION client used to allocate the buffer.
+ * @buffer_handle: The ION handle representing the buffer.
+ * @buffer_size: The memory buffer size.
+ * @is_secure: Is this a securely allocated and locked buffer or not.
+ * @pipe_mode: Pipe mode (input / output).
+ * @sps_cfg: Pipe SPS configuration.
+ */
+struct tspp2_pipe_config_params {
+ struct ion_client *ion_client;
+ struct ion_handle *buffer_handle;
+ u32 buffer_size;
+ int is_secure;
+ enum tspp2_src_pipe_mode pipe_mode;
+ struct tspp2_pipe_sps_params sps_cfg;
+};
+
+/**
+ * enum tspp2_operation_type - Operation types
+ *
+ * @TSPP2_OP_PES_ANALYSIS: PES analysis operation parses the PES header
+ * and extracts necessary variables from it. Use
+ * this operation before any other PES transmit
+ * operation, otherwise the output buffer will be
+ * empty.
+ * PID filters that includes any PES operation, and
+ * specifically PES analysis, must have a mask that
+ * will match a single PID.
+ * @TSPP2_OP_RAW_TRANSMIT: RAW transmit operation, used to send whole TS
+ * packets to the output pipe. A timestamp can also
+ * be appended.
+ * Use this operation for PIDs that carry section
+ * information, and for recording.
+ * @TSPP2_OP_PES_TRANSMIT: PES transmit operation, used to assemble PES
+ * packets. There are two modes for this operation:
+ * 1. Full PES transmit: the full PES, both header
+ * and payload are written to the output pipe.
+ * 2. Separated PES header and payload: the PES
+ * header is written to one pipe and the payload is
+ * written to a different pipe.
+ * @TSPP2_OP_PCR_EXTRACTION: PCR extraction operation, used to extract TS
+ * packets with PCR. No processing is performed on
+ * the PCR. This operation simply outputs the
+ * packet and the timestamp. It is recommended that
+ * PCR extraction operation will be set before
+ * other operations (PES analysis, cipher) so that
+ * failures in those operation will not affect it.
+ * @TSPP2_OP_CIPHER: Cipher operation, used to encrypt / decrypt TS
+ * packets.
+ * @TSPP2_OP_INDEXING: Indexing operation, used for searching patterns
+ * in the PES payload or for indexing using the
+ * random access indicator.
+ * In order to perform pattern search, a PES
+ * Analysis operation must precede the indexing
+ * operation. For random access indicator indexing
+ * this is not mandatory.
+ * Indexing is performed on video streams.
+ * Use only a single indexing operation per filter.
+ * @TSPP2_OP_COPY_PACKET: Copy packet operation, used to copy the packet
+ * from one sketch buffer to the other.
+ */
+enum tspp2_operation_type {
+ TSPP2_OP_PES_ANALYSIS,
+ TSPP2_OP_RAW_TRANSMIT,
+ TSPP2_OP_PES_TRANSMIT,
+ TSPP2_OP_PCR_EXTRACTION,
+ TSPP2_OP_CIPHER,
+ TSPP2_OP_INDEXING,
+ TSPP2_OP_COPY_PACKET
+};
+
+/**
+ * enum tspp2_operation_buffer - Operation sketch buffer
+ *
+ * @TSPP2_OP_BUFFER_A: Sketch buffer A (initial)
+ * @TSPP2_OP_BUFFER_B: Sketch buffer B
+ */
+enum tspp2_operation_buffer {
+ TSPP2_OP_BUFFER_A,
+ TSPP2_OP_BUFFER_B
+};
+
+/**
+ * enum tspp2_operation_timestamp_mode - RAW transmit operation timestamp mode
+ *
+ * @TSPP2_OP_TIMESTAMP_NONE: Don't add timestamp. Output is 188 byte packets.
+ * @TSPP2_OP_TIMESTAMP_ZERO: Add 4-byte timestamp, value is all zeros.
+ * @TSPP2_OP_TIMESTAMP_STC: Add 4-byte timestamp, value according to STC
+ * generated by TSIF.
+ */
+enum tspp2_operation_timestamp_mode {
+ TSPP2_OP_TIMESTAMP_NONE,
+ TSPP2_OP_TIMESTAMP_ZERO,
+ TSPP2_OP_TIMESTAMP_STC
+};
+
+/**
+ * enum tspp2_operation_cipher_mode - Cipher operation mode
+ *
+ * @TSPP2_OP_CIPHER_DECRYPT: Decrypt packet.
+ * @TSPP2_OP_CIPHER_ENCRYPT: Encrypt packet.
+ */
+enum tspp2_operation_cipher_mode {
+ TSPP2_OP_CIPHER_DECRYPT,
+ TSPP2_OP_CIPHER_ENCRYPT
+};
+
+/**
+ * enum tspp2_operation_cipher_scrambling_mode - Cipher operation scrambling mode
+ *
+ * @TSPP2_OP_CIPHER_AS_IS: Use the original scrambling bits to
+ * decide which key to use (even, odd or
+ * pass-through). If enabled, the operation
+ * will not modify the scrambling bits in
+ * the TS packet header.
+ * @TSPP2_OP_CIPHER_SET_SCRAMBLING_0: Set TS packet scrambling bits to '00'.
+ * @TSPP2_OP_CIPHER_SET_SCRAMBLING_1: Set TS packet scrambling bits to '01'.
+ * @TSPP2_OP_CIPHER_SET_SCRAMBLING_2: Set TS packet scrambling bits to '10'.
+ * @TSPP2_OP_CIPHER_SET_SCRAMBLING_3: Set TS packet scrambling bits to '11'.
+ */
+enum tspp2_operation_cipher_scrambling_mode {
+ TSPP2_OP_CIPHER_AS_IS,
+ TSPP2_OP_CIPHER_SET_SCRAMBLING_0,
+ TSPP2_OP_CIPHER_SET_SCRAMBLING_1,
+ TSPP2_OP_CIPHER_SET_SCRAMBLING_2,
+ TSPP2_OP_CIPHER_SET_SCRAMBLING_3
+};
+
+/**
+ * enum tspp2_op_pes_transmit_mode - PES transmit operation mode
+ *
+ * TSPP2_OP_PES_TRANSMIT_SEPARATED: Separated PES mode.
+ * TSPP2_OP_PES_TRANSMIT_FULL: Full PES mode.
+ */
+enum tspp2_op_pes_transmit_mode {
+ TSPP2_OP_PES_TRANSMIT_SEPARATED,
+ TSPP2_OP_PES_TRANSMIT_FULL
+};
+
+/**
+ * struct tspp2_op_pes_analysis_params - PES analysis operation parameters
+ *
+ * @input: Input buffer for this operation.
+ * @skip_ts_errs: If set, TS packet with an error
+ * indication will not be processed by this
+ * operation. The implication would be that
+ * if a PES started with an erred packet,
+ * the entire PES will be lost. This
+ * parameter affects all PES operations
+ * later in the sequence: PES transmit and
+ * indexing. For indexing, the implications
+ * might be that a pattern will not be
+ * found and the frame will not be indexed.
+ */
+struct tspp2_op_pes_analysis_params {
+ enum tspp2_operation_buffer input;
+ int skip_ts_errs;
+};
+
+/**
+ * struct tspp2_op_raw_transmit_params - Raw transmit operation parameters
+ *
+ * @input: Input buffer for this operation.
+ * @timestamp_mode: Determines timestamp mode.
+ * @timestamp_position: Determines timestamp position, if added.
+ * @support_indexing: If set, then the indexing information
+ * generated by a following indexing
+ * operation refers to the data in the
+ * output pipe used by this RAW operation.
+ * When a filter has multiple RAW
+ * operations, only one of them should set
+ * the support_indexing option.
+ * @skip_ts_errs: If set, TS packet with an error
+ * indication will not be processed by this
+ * operation. The implication depends on
+ * the content which the PID carries.
+ * @output_pipe_handle: Handle of the output pipe.
+ */
+struct tspp2_op_raw_transmit_params {
+ enum tspp2_operation_buffer input;
+ enum tspp2_operation_timestamp_mode timestamp_mode;
+ enum tspp2_packet_format timestamp_position;
+ int support_indexing;
+ int skip_ts_errs;
+ u32 output_pipe_handle;
+};
+
+/**
+ * struct tspp2_op_pes_transmit_params - PES transmit operation parameters
+ *
+ * @input: Input buffer for this operation.
+ * @mode: Seperated / Full PES mode.
+ * @enable_sw_indexing: Enable the PES addressing which is
+ * appended to the PES payload.
+ * @attach_stc_flags: Attach STC and flags to the PES.
+ * Relevant only when mode is full PES.
+ * @disable_tx_on_pes_discontinuity: Disable transmission of PES payload
+ * after a discontinuity. When set, TSPP2
+ * waits until a new PUSI is received and
+ * all the packets until then are
+ * discarded. The current PES will be
+ * closed when the new PUSI arrives.
+ * @output_pipe_handle: Handle of the output pipe in full PES
+ * mode, or the payload output pipe in
+ * separated PES mode.
+ * @header_output_pipe_handle: Handle of the PES header output pipe in
+ * separated PES mode.
+ */
+struct tspp2_op_pes_transmit_params {
+ enum tspp2_operation_buffer input;
+ enum tspp2_op_pes_transmit_mode mode;
+ int enable_sw_indexing;
+ int attach_stc_flags;
+ int disable_tx_on_pes_discontinuity;
+ u32 output_pipe_handle;
+ u32 header_output_pipe_handle;
+};
+
+/**
+ * struct tspp2_op_pcr_extraction_params - PCR extraction operation parameters
+ *
+ * @input: Input buffer for this operation.
+ * @skip_ts_errs: If set, TS packet with an error
+ * indication will not be processed by this
+ * operation. The implication would be that
+ * a PCR packet may be lost.
+ * @extract_pcr: Extract TS packets containing PCR.
+ * @extract_opcr: Extract TS packets containing OPCR.
+ * @extract_splicing_point: Extract TS packets containing a splicing
+ * point indication.
+ * @extract_transport_private_data: Extract TS packets containig private
+ * data.
+ * @extract_af_extension: Extract TS packets with an adaptation
+ * field extension.
+ * @extract_all_af: Extract all TS packets with an adaptaion
+ * field.
+ * @output_pipe_handle: Handle of the output pipe.
+ */
+struct tspp2_op_pcr_extraction_params {
+ enum tspp2_operation_buffer input;
+ int skip_ts_errs;
+ int extract_pcr;
+ int extract_opcr;
+ int extract_splicing_point;
+ int extract_transport_private_data;
+ int extract_af_extension;
+ int extract_all_af;
+ u32 output_pipe_handle;
+};
+
+/**
+ * struct tspp2_op_cipher_params - Cipher operation parameters
+ *
+ * @input: Input buffer for this operation.
+ * @mode: Decrypt / encrypt.
+ * @decrypt_pes_header: Decrypt PES header TS packets (use if
+ * PES header is encrypted).
+ * @skip_ts_errs: If set, TS packet with an error
+ * indication will not be processed by this
+ * operation.
+ * @key_ladder_index: Key ladder index.
+ * @scrambling_mode: Scrambling bits manipulation mode.
+ * @output: Output buffer for this operation.
+ */
+struct tspp2_op_cipher_params {
+ enum tspp2_operation_buffer input;
+ enum tspp2_operation_cipher_mode mode;
+ int decrypt_pes_header;
+ int skip_ts_errs;
+ u32 key_ladder_index;
+ enum tspp2_operation_cipher_scrambling_mode scrambling_mode;
+ enum tspp2_operation_buffer output;
+};
+
+/**
+ * struct tspp2_op_indexing_params - Indexing operation parameters
+ *
+ * @input: Input buffer for this operation.
+ * @random_access_indicator_indexing: If set, do indexing according to the
+ * random access indicator in the TS packet
+ * header. TSPP2 will not look for the
+ * patterns defined in the specified table.
+ * @indexing_table_id: Indexing table ID.
+ * @skip_ts_errs: If set, TS packet with an error
+ * indication will not be processed by this
+ * operation.
+ * @output_pipe_handle: Handle of the output pipe.
+ */
+struct tspp2_op_indexing_params {
+ enum tspp2_operation_buffer input;
+ int random_access_indicator_indexing;
+ u8 indexing_table_id;
+ int skip_ts_errs;
+ u32 output_pipe_handle;
+};
+
+/**
+ * struct tspp2_op_copy_packet_params - Copy packet operation parameters
+ *
+ * @input: Input buffer for this operation.
+ */
+struct tspp2_op_copy_packet_params {
+ enum tspp2_operation_buffer input;
+};
+
+/**
+ * struct tspp2_operation - Operation
+ *
+ * @type: Operation type.
+ * @params: Operation-specific parameters.
+ */
+struct tspp2_operation {
+ enum tspp2_operation_type type;
+ union {
+ struct tspp2_op_pes_analysis_params pes_analysis;
+ struct tspp2_op_raw_transmit_params raw_transmit;
+ struct tspp2_op_pes_transmit_params pes_transmit;
+ struct tspp2_op_pcr_extraction_params pcr_extraction;
+ struct tspp2_op_cipher_params cipher;
+ struct tspp2_op_indexing_params indexing;
+ struct tspp2_op_copy_packet_params copy_packet;
+ } params;
+};
+
+/* TSPP2 device open / close API */
+int tspp2_device_open(u32 dev_id);
+
+int tspp2_device_close(u32 dev_id);
+
+/* Global configuration API */
+int tspp2_config_set(u32 dev_id, const struct tspp2_config *cfg);
+
+int tspp2_config_get(u32 dev_id, struct tspp2_config *cfg);
+
+/* Indexing tables API functions */
+int tspp2_indexing_prefix_set(u32 dev_id,
+ u8 table_id,
+ u32 value,
+ u32 mask);
+
+int tspp2_indexing_patterns_add(u32 dev_id,
+ u8 table_id,
+ const u32 *values,
+ const u32 *masks,
+ u8 patterns_num);
+
+int tspp2_indexing_patterns_clear(u32 dev_id,
+ u8 table_id);
+
+/* Pipe API functions */
+int tspp2_pipe_open(u32 dev_id,
+ const struct tspp2_pipe_config_params *cfg,
+ ion_phys_addr_t *iova,
+ u32 *pipe_handle);
+
+int tspp2_pipe_close(u32 pipe_handle);
+
+/* Source API functions */
+int tspp2_src_open(u32 dev_id,
+ struct tspp2_src_cfg *cfg,
+ u32 *src_handle);
+
+int tspp2_src_close(u32 src_handle);
+
+int tspp2_src_parsing_option_set(u32 src_handle,
+ enum tspp2_src_parsing_option option,
+ int value);
+
+int tspp2_src_parsing_option_get(u32 src_handle,
+ enum tspp2_src_parsing_option option,
+ int *value);
+
+int tspp2_src_sync_byte_config_set(u32 src_handle,
+ int check_sync_byte,
+ u8 sync_byte_value);
+
+int tspp2_src_sync_byte_config_get(u32 src_handle,
+ int *check_sync_byte,
+ u8 *sync_byte_value);
+
+int tspp2_src_scrambling_config_set(u32 src_handle,
+ const struct tspp2_src_scrambling_config *cfg);
+
+int tspp2_src_scrambling_config_get(u32 src_handle,
+ struct tspp2_src_scrambling_config *cfg);
+
+int tspp2_src_packet_format_set(u32 src_handle,
+ enum tspp2_packet_format format);
+
+int tspp2_src_pipe_attach(u32 src_handle,
+ u32 pipe_handle,
+ const struct tspp2_pipe_pull_mode_params *cfg);
+
+int tspp2_src_pipe_detach(u32 src_handle, u32 pipe_handle);
+
+int tspp2_src_enable(u32 src_handle);
+
+int tspp2_src_disable(u32 src_handle);
+
+int tspp2_src_filters_clear(u32 src_handle);
+
+/* Filters and Operations API functions */
+int tspp2_filter_open(u32 src_handle, u16 pid, u16 mask, u32 *filter_handle);
+
+int tspp2_filter_close(u32 filter_handle);
+
+int tspp2_filter_enable(u32 filter_handle);
+
+int tspp2_filter_disable(u32 filter_handle);
+
+int tspp2_filter_operations_set(u32 filter_handle,
+ const struct tspp2_operation *ops,
+ u8 operations_num);
+
+int tspp2_filter_operations_clear(u32 filter_handle);
+
+int tspp2_filter_current_scrambling_bits_get(u32 filter_handle,
+ u8 *scrambling_bits_value);
+
+/* Data-path API functions */
+int tspp2_pipe_descriptor_get(u32 pipe_handle, struct sps_iovec *desc);
+
+int tspp2_pipe_descriptor_put(u32 pipe_handle, u32 addr, u32 size, u32 flags);
+
+int tspp2_pipe_last_address_used_get(u32 pipe_handle, u32 *address);
+
+int tspp2_data_write(u32 src_handle, u32 offset, u32 size);
+
+int tspp2_tsif_data_write(u32 src_handle, u32 *data);
+
+/* Event notification API functions */
+
+/* Global events */
+#define TSPP2_GLOBAL_EVENT_INVALID_AF_CTRL 0x00000001
+#define TSPP2_GLOBAL_EVENT_INVALID_AF_LENGTH 0x00000002
+#define TSPP2_GLOBAL_EVENT_PES_NO_SYNC 0x00000004
+#define TSPP2_GLOBAL_EVENT_TX_FAIL 0x00000008
+/* Source events */
+#define TSPP2_SRC_EVENT_TSIF_LOST_SYNC 0x00000001
+#define TSPP2_SRC_EVENT_TSIF_TIMEOUT 0x00000002
+#define TSPP2_SRC_EVENT_TSIF_OVERFLOW 0x00000004
+#define TSPP2_SRC_EVENT_TSIF_PKT_READ_ERROR 0x00000008
+#define TSPP2_SRC_EVENT_TSIF_PKT_WRITE_ERROR 0x00000010
+#define TSPP2_SRC_EVENT_MEMORY_READ_ERROR 0x00000020
+#define TSPP2_SRC_EVENT_FLOW_CTRL_STALL 0x00000040
+/* Filter events */
+#define TSPP2_FILTER_EVENT_SCRAMBLING_HIGH 0x00000001
+#define TSPP2_FILTER_EVENT_SCRAMBLING_LOW 0x00000002
+
+
+int tspp2_global_event_notification_register(u32 dev_id,
+ u32 global_event_bitmask,
+ void (*callback)(void *cookie, u32 event_bitmask),
+ void *cookie);
+
+int tspp2_src_event_notification_register(u32 src_handle,
+ u32 src_event_bitmask,
+ void (*callback)(void *cookie, u32 event_bitmask),
+ void *cookie);
+
+int tspp2_filter_event_notification_register(u32 filter_handle,
+ u32 filter_event_bitmask,
+ void (*callback)(void *cookie, u32 event_bitmask),
+ void *cookie);
+
+int tspp2_get_reserved_hw_index(u32 src_handle);
+
+int tspp2_get_filter_hw_index(u32 filter_handle);
+
+int tspp2_get_ops_array(u32 filter_handle,
+ struct tspp2_operation ops_array[TSPP2_MAX_OPS_PER_FILTER],
+ u8 *num_of_ops);
+
+#endif /* _MSM_TSPP2_H_ */
+
diff --git a/arch/arm/mach-msm/include/mach/msm_xo.h b/arch/arm/mach-msm/include/mach/msm_xo.h
new file mode 100644
index 000000000000..f9ccfee96370
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_xo.h
@@ -0,0 +1,56 @@
+/* Copyright (c) 2010-2012, 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 __MACH_MSM_XO_H
+#define __MACH_MSM_XO_H
+
+enum msm_xo_ids {
+ MSM_XO_TCXO_D0,
+ MSM_XO_TCXO_D1,
+ MSM_XO_TCXO_A0,
+ MSM_XO_TCXO_A1,
+ MSM_XO_TCXO_A2,
+ MSM_XO_CORE,
+ NUM_MSM_XO_IDS
+};
+
+enum msm_xo_modes {
+ MSM_XO_MODE_OFF,
+ MSM_XO_MODE_PIN_CTRL,
+ MSM_XO_MODE_ON,
+ NUM_MSM_XO_MODES
+};
+
+struct msm_xo_voter;
+
+#ifdef CONFIG_MSM_XO
+struct msm_xo_voter *msm_xo_get(enum msm_xo_ids xo_id, const char *voter);
+void msm_xo_put(struct msm_xo_voter *xo_voter);
+int msm_xo_mode_vote(struct msm_xo_voter *xo_voter, enum msm_xo_modes xo_mode);
+int __init msm_xo_init(void);
+#else
+static inline struct msm_xo_voter *msm_xo_get(enum msm_xo_ids xo_id,
+ const char *voter)
+{
+ return NULL;
+}
+
+static inline void msm_xo_put(struct msm_xo_voter *xo_voter) { }
+
+static inline int msm_xo_mode_vote(struct msm_xo_voter *xo_voter,
+ enum msm_xo_modes xo_mode)
+{
+ return 0;
+}
+static inline int msm_xo_init(void) { return 0; }
+#endif /* CONFIG_MSM_XO */
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/proc_comm.h b/arch/arm/mach-msm/include/mach/proc_comm.h
new file mode 100644
index 000000000000..655692abca3a
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/proc_comm.h
@@ -0,0 +1,181 @@
+/* arch/arm/mach-msm/include/mach/proc_comm.h
+ *
+ * Copyright (c) 2007-2009,2011 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 _ARCH_ARM_MACH_MSM_MSM_PROC_COMM_H_
+#define _ARCH_ARM_MACH_MSM_MSM_PROC_COMM_H_
+
+enum {
+ PCOM_CMD_IDLE = 0x0,
+ PCOM_CMD_DONE,
+ PCOM_RESET_APPS,
+ PCOM_RESET_CHIP,
+ PCOM_CONFIG_NAND_MPU,
+ PCOM_CONFIG_USB_CLKS,
+ PCOM_GET_POWER_ON_STATUS,
+ PCOM_GET_WAKE_UP_STATUS,
+ PCOM_GET_BATT_LEVEL,
+ PCOM_CHG_IS_CHARGING,
+ PCOM_POWER_DOWN,
+ PCOM_USB_PIN_CONFIG,
+ PCOM_USB_PIN_SEL,
+ PCOM_SET_RTC_ALARM,
+ PCOM_NV_READ,
+ PCOM_NV_WRITE,
+ PCOM_GET_UUID_HIGH,
+ PCOM_GET_UUID_LOW,
+ PCOM_GET_HW_ENTROPY,
+ PCOM_RPC_GPIO_TLMM_CONFIG_REMOTE,
+ PCOM_CLKCTL_RPC_ENABLE,
+ PCOM_CLKCTL_RPC_DISABLE,
+ PCOM_CLKCTL_RPC_RESET,
+ PCOM_CLKCTL_RPC_SET_FLAGS,
+ PCOM_CLKCTL_RPC_SET_RATE,
+ PCOM_CLKCTL_RPC_MIN_RATE,
+ PCOM_CLKCTL_RPC_MAX_RATE,
+ PCOM_CLKCTL_RPC_RATE,
+ PCOM_CLKCTL_RPC_PLL_REQUEST,
+ PCOM_CLKCTL_RPC_ENABLED,
+ PCOM_VREG_SWITCH,
+ PCOM_VREG_SET_LEVEL,
+ PCOM_GPIO_TLMM_CONFIG_GROUP,
+ PCOM_GPIO_TLMM_UNCONFIG_GROUP,
+ PCOM_NV_WRITE_BYTES_4_7,
+ PCOM_CONFIG_DISP,
+ PCOM_GET_FTM_BOOT_COUNT,
+ PCOM_RPC_GPIO_TLMM_CONFIG_EX,
+ PCOM_PM_MPP_CONFIG,
+ PCOM_GPIO_IN,
+ PCOM_GPIO_OUT,
+ PCOM_RESET_MODEM,
+ PCOM_RESET_CHIP_IMM,
+ PCOM_PM_VID_EN,
+ PCOM_VREG_PULLDOWN,
+ PCOM_GET_MODEM_VERSION,
+ PCOM_CLK_REGIME_SEC_RESET,
+ PCOM_CLK_REGIME_SEC_RESET_ASSERT,
+ PCOM_CLK_REGIME_SEC_RESET_DEASSERT,
+ PCOM_CLK_REGIME_SEC_PLL_REQUEST_WRP,
+ PCOM_CLK_REGIME_SEC_ENABLE,
+ PCOM_CLK_REGIME_SEC_DISABLE,
+ PCOM_CLK_REGIME_SEC_IS_ON,
+ PCOM_CLK_REGIME_SEC_SEL_CLK_INV,
+ PCOM_CLK_REGIME_SEC_SEL_CLK_SRC,
+ PCOM_CLK_REGIME_SEC_SEL_CLK_DIV,
+ PCOM_CLK_REGIME_SEC_ICODEC_CLK_ENABLE,
+ PCOM_CLK_REGIME_SEC_ICODEC_CLK_DISABLE,
+ PCOM_CLK_REGIME_SEC_SEL_SPEED,
+ PCOM_CLK_REGIME_SEC_CONFIG_GP_CLK_WRP,
+ PCOM_CLK_REGIME_SEC_CONFIG_MDH_CLK_WRP,
+ PCOM_CLK_REGIME_SEC_USB_XTAL_ON,
+ PCOM_CLK_REGIME_SEC_USB_XTAL_OFF,
+ PCOM_CLK_REGIME_SEC_SET_QDSP_DME_MODE,
+ PCOM_CLK_REGIME_SEC_SWITCH_ADSP_CLK,
+ PCOM_CLK_REGIME_SEC_GET_MAX_ADSP_CLK_KHZ,
+ PCOM_CLK_REGIME_SEC_GET_I2C_CLK_KHZ,
+ PCOM_CLK_REGIME_SEC_MSM_GET_CLK_FREQ_KHZ,
+ PCOM_CLK_REGIME_SEC_SEL_VFE_SRC,
+ PCOM_CLK_REGIME_SEC_MSM_SEL_CAMCLK,
+ PCOM_CLK_REGIME_SEC_MSM_SEL_LCDCLK,
+ PCOM_CLK_REGIME_SEC_VFE_RAIL_OFF,
+ PCOM_CLK_REGIME_SEC_VFE_RAIL_ON,
+ PCOM_CLK_REGIME_SEC_GRP_RAIL_OFF,
+ PCOM_CLK_REGIME_SEC_GRP_RAIL_ON,
+ PCOM_CLK_REGIME_SEC_VDC_RAIL_OFF,
+ PCOM_CLK_REGIME_SEC_VDC_RAIL_ON,
+ PCOM_CLK_REGIME_SEC_LCD_CTRL,
+ PCOM_CLK_REGIME_SEC_REGISTER_FOR_CPU_RESOURCE,
+ PCOM_CLK_REGIME_SEC_DEREGISTER_FOR_CPU_RESOURCE,
+ PCOM_CLK_REGIME_SEC_RESOURCE_REQUEST_WRP,
+ PCOM_CLK_REGIME_MSM_SEC_SEL_CLK_OWNER,
+ PCOM_CLK_REGIME_SEC_DEVMAN_REQUEST_WRP,
+ PCOM_GPIO_CONFIG,
+ PCOM_GPIO_CONFIGURE_GROUP,
+ PCOM_GPIO_TLMM_SET_PORT,
+ PCOM_GPIO_TLMM_CONFIG_EX,
+ PCOM_SET_FTM_BOOT_COUNT,
+ PCOM_RESERVED0,
+ PCOM_RESERVED1,
+ PCOM_CUSTOMER_CMD1,
+ PCOM_CUSTOMER_CMD2,
+ PCOM_CUSTOMER_CMD3,
+ PCOM_CLK_REGIME_ENTER_APPSBL_CHG_MODE,
+ PCOM_CLK_REGIME_EXIT_APPSBL_CHG_MODE,
+ PCOM_CLK_REGIME_SEC_RAIL_DISABLE,
+ PCOM_CLK_REGIME_SEC_RAIL_ENABLE,
+ PCOM_CLK_REGIME_SEC_RAIL_CONTROL,
+ PCOM_SET_SW_WATCHDOG_STATE,
+ PCOM_PM_MPP_CONFIG_DIGITAL_INPUT,
+ PCOM_PM_MPP_CONFIG_I_SINK,
+ PCOM_RESERVED_101,
+ PCOM_MSM_HSUSB_PHY_RESET,
+ PCOM_GET_BATT_MV_LEVEL,
+ PCOM_CHG_USB_IS_PC_CONNECTED,
+ PCOM_CHG_USB_IS_CHARGER_CONNECTED,
+ PCOM_CHG_USB_IS_DISCONNECTED,
+ PCOM_CHG_USB_IS_AVAILABLE,
+ PCOM_CLK_REGIME_SEC_MSM_SEL_FREQ,
+ PCOM_CLK_REGIME_SEC_SET_PCLK_AXI_POLICY,
+ PCOM_CLKCTL_RPC_RESET_ASSERT,
+ PCOM_CLKCTL_RPC_RESET_DEASSERT,
+ PCOM_CLKCTL_RPC_RAIL_ON,
+ PCOM_CLKCTL_RPC_RAIL_OFF,
+ PCOM_CLKCTL_RPC_RAIL_ENABLE,
+ PCOM_CLKCTL_RPC_RAIL_DISABLE,
+ PCOM_CLKCTL_RPC_RAIL_CONTROL,
+ PCOM_CLKCTL_RPC_MIN_MSMC1,
+ PCOM_CLKCTL_RPC_SRC_REQUEST,
+ PCOM_NPA_INIT,
+ PCOM_NPA_ISSUE_REQUIRED_REQUEST,
+ PCOM_CLKCTL_RPC_SET_EXT_CONFIG,
+};
+
+enum {
+ PCOM_OEM_FIRST_CMD = 0x10000000,
+ PCOM_OEM_TEST_CMD = PCOM_OEM_FIRST_CMD,
+
+ /* add OEM PROC COMM commands here */
+
+ PCOM_OEM_LAST = PCOM_OEM_TEST_CMD,
+};
+
+enum {
+ PCOM_INVALID_STATUS = 0x0,
+ PCOM_READY,
+ PCOM_CMD_RUNNING,
+ PCOM_CMD_SUCCESS,
+ PCOM_CMD_FAIL,
+ PCOM_CMD_FAIL_FALSE_RETURNED,
+ PCOM_CMD_FAIL_CMD_OUT_OF_BOUNDS_SERVER,
+ PCOM_CMD_FAIL_CMD_OUT_OF_BOUNDS_CLIENT,
+ PCOM_CMD_FAIL_CMD_UNREGISTERED,
+ PCOM_CMD_FAIL_CMD_LOCKED,
+ PCOM_CMD_FAIL_SERVER_NOT_YET_READY,
+ PCOM_CMD_FAIL_BAD_DESTINATION,
+ PCOM_CMD_FAIL_SERVER_RESET,
+ PCOM_CMD_FAIL_SMSM_NOT_INIT,
+ PCOM_CMD_FAIL_PROC_COMM_BUSY,
+ PCOM_CMD_FAIL_PROC_COMM_NOT_INIT,
+};
+
+#ifdef CONFIG_MSM_PROC_COMM
+void msm_proc_comm_reset_modem_now(void);
+int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2);
+#else
+static inline void msm_proc_comm_reset_modem_now(void) { }
+static inline int msm_proc_comm(unsigned cmd, unsigned *data1, unsigned *data2)
+{ return 0; }
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
new file mode 100644
index 000000000000..e31feb041f5d
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -0,0 +1,228 @@
+/* Copyright (c) 2010-2012, 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 __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_H
+#define __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_H
+
+#include <linux/regulator/machine.h>
+
+#define RPM_REGULATOR_DEV_NAME "rpm-regulator"
+
+/**
+ * enum rpm_vreg_version - supported RPM regulator versions
+ */
+enum rpm_vreg_version {
+ RPM_VREG_VERSION_8660,
+ RPM_VREG_VERSION_8960,
+ RPM_VREG_VERSION_9615,
+ RPM_VREG_VERSION_8930,
+ RPM_VREG_VERSION_8930_PM8917,
+ RPM_VREG_VERSION_8960_PM8917,
+ RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8960_PM8917,
+};
+
+#define RPM_VREG_PIN_CTRL_NONE 0x00
+
+/**
+ * enum rpm_vreg_state - enable state for switch or NCP
+ */
+enum rpm_vreg_state {
+ RPM_VREG_STATE_OFF,
+ RPM_VREG_STATE_ON,
+};
+
+/**
+ * enum rpm_vreg_freq - switching frequency for SMPS or NCP
+ */
+enum rpm_vreg_freq {
+ RPM_VREG_FREQ_NONE,
+ RPM_VREG_FREQ_19p20,
+ RPM_VREG_FREQ_9p60,
+ RPM_VREG_FREQ_6p40,
+ RPM_VREG_FREQ_4p80,
+ RPM_VREG_FREQ_3p84,
+ RPM_VREG_FREQ_3p20,
+ RPM_VREG_FREQ_2p74,
+ RPM_VREG_FREQ_2p40,
+ RPM_VREG_FREQ_2p13,
+ RPM_VREG_FREQ_1p92,
+ RPM_VREG_FREQ_1p75,
+ RPM_VREG_FREQ_1p60,
+ RPM_VREG_FREQ_1p48,
+ RPM_VREG_FREQ_1p37,
+ RPM_VREG_FREQ_1p28,
+ RPM_VREG_FREQ_1p20,
+};
+
+/**
+ * enum rpm_vreg_voltage_corner - possible voltage corner values
+ *
+ * These should be used in regulator_set_voltage and rpm_vreg_set_voltage calls
+ * for corner type regulators as if they had units of uV.
+ */
+enum rpm_vreg_voltage_corner {
+ RPM_VREG_CORNER_NONE = 1,
+ RPM_VREG_CORNER_LOW,
+ RPM_VREG_CORNER_NOMINAL,
+ RPM_VREG_CORNER_HIGH,
+};
+
+/**
+ * enum rpm_vreg_voter - RPM regulator voter IDs for private APIs
+ */
+enum rpm_vreg_voter {
+ RPM_VREG_VOTER_REG_FRAMEWORK, /* for internal use only */
+ RPM_VREG_VOTER1, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER2, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER3, /* for use by other drivers */
+ RPM_VREG_VOTER4, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER5, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER6, /* for use by the acpu-clock driver */
+ RPM_VREG_VOTER_COUNT,
+};
+
+/**
+ * struct rpm_regulator_init_data - RPM regulator initialization data
+ * @init_data: regulator constraints
+ * @id: regulator id; from enum rpm_vreg_id
+ * @sleep_selectable: flag which indicates that regulator should be accessable
+ * by external private API
+ * @system_uA: current drawn from regulator not accounted for by any
+ * regulator framework consumer
+ * @enable_time: time in us taken to enable a regulator to the maximum
+ * allowed voltage for the system. This is dependent upon
+ * the load and capacitance for a regulator on the board.
+ * @pull_down_enable: 0 = no pulldown, 1 = pulldown when regulator disabled
+ * @freq: enum value representing the switching frequency of an
+ * SMPS or NCP
+ * @pin_ctrl: pin control inputs to use for the regulator; should be
+ * a combination of RPM_VREG_PIN_CTRL_* values
+ * @pin_fn: action to perform when pin control pin(s) is/are active
+ * @force_mode: used to specify a force mode which overrides the votes
+ * of other RPM masters.
+ * @sleep_set_force_mode: force mode to use in sleep-set requests
+ * @power_mode: mode to use as HPM (typically PWM or hysteretic) when
+ * utilizing Auto mode selection
+ * @default_uV: initial voltage to set the regulator to if enable is
+ * called before set_voltage (e.g. when boot_on or
+ * always_on is set).
+ * @peak_uA: initial peak load requirement sent in RPM request; used
+ * to determine initial mode.
+ * @avg_uA: average load requirement sent in RPM request
+ * @state: initial enable state sent in RPM request for switch or
+ * NCP
+ */
+struct rpm_regulator_init_data {
+ struct regulator_init_data init_data;
+ int id;
+ int sleep_selectable;
+ int system_uA;
+ int enable_time;
+ unsigned pull_down_enable;
+ enum rpm_vreg_freq freq;
+ unsigned pin_ctrl;
+ int pin_fn;
+ int force_mode;
+ int sleep_set_force_mode;
+ int power_mode;
+ int default_uV;
+ unsigned peak_uA;
+ unsigned avg_uA;
+ enum rpm_vreg_state state;
+};
+
+/**
+ * struct rpm_regulator_consumer_mapping - mapping used by private consumers
+ */
+struct rpm_regulator_consumer_mapping {
+ const char *dev_name;
+ const char *supply;
+ int vreg_id;
+ enum rpm_vreg_voter voter;
+ int sleep_also;
+};
+
+/**
+ * struct rpm_regulator_platform_data - RPM regulator platform data
+ */
+struct rpm_regulator_platform_data {
+ struct rpm_regulator_init_data *init_data;
+ int num_regulators;
+ enum rpm_vreg_version version;
+ int vreg_id_vdd_mem;
+ int vreg_id_vdd_dig;
+ bool requires_tcxo_workaround;
+ struct rpm_regulator_consumer_mapping *consumer_map;
+ int consumer_map_len;
+};
+
+#ifdef CONFIG_MSM_RPM_REGULATOR
+/**
+ * rpm_vreg_set_voltage - vote for a min_uV value of specified regualtor
+ * @vreg: ID for regulator
+ * @voter: ID for the voter
+ * @min_uV: minimum acceptable voltage (in uV) that is voted for
+ * @max_uV: maximum acceptable voltage (in uV) that is voted for
+ * @sleep_also: 0 for active set only, non-0 for active set and sleep set
+ *
+ * Returns 0 on success or errno.
+ *
+ * This function is used to vote for the voltage of a regulator without
+ * using the regulator framework. It is needed for consumers which wish to only
+ * vote for active set regulator voltage.
+ *
+ * If sleep_also == 0, then a sleep-set value of 0V will be voted for.
+ *
+ * This function may only be called for regulators which have the sleep flag
+ * specified in their private data.
+ *
+ * Consumers can vote to disable a regulator with this function by passing
+ * min_uV = 0 and max_uV = 0.
+ *
+ * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
+ * as well. For this type of regulator, max_uV > 0 is treated as an enable
+ * request and max_uV == 0 is treated as a disable request.
+ */
+int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
+ int max_uV, int sleep_also);
+
+/**
+ * rpm_vreg_set_frequency - sets the frequency of a switching regulator
+ * @vreg: ID for regulator
+ * @freq: enum corresponding to desired frequency
+ *
+ * Returns 0 on success or errno.
+ */
+int rpm_vreg_set_frequency(int vreg_id, enum rpm_vreg_freq freq);
+
+#else
+
+/*
+ * These stubs exist to allow consumers of these APIs to compile and run
+ * in absence of a real RPM regulator driver. It is assumed that they are
+ * aware of the state of their regulators and have either set them
+ * correctly by some other means or don't care about their state at all.
+ */
+static inline int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter,
+ int min_uV, int max_uV, int sleep_also)
+{
+ return 0;
+}
+
+static inline int rpm_vreg_set_frequency(int vreg_id, enum rpm_vreg_freq freq)
+{
+ return 0;
+}
+
+#endif /* CONFIG_MSM_RPM_REGULATOR */
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
new file mode 100644
index 000000000000..7b7313a3b8c4
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -0,0 +1,1186 @@
+/* Copyright (c) 2010-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 __ARCH_ARM_MACH_MSM_RPM_H
+#define __ARCH_ARM_MACH_MSM_RPM_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/semaphore.h>
+
+#define SEL_MASK_SIZE (5)
+
+enum {
+ MSM_RPM_PAGE_STATUS,
+ MSM_RPM_PAGE_CTRL,
+ MSM_RPM_PAGE_REQ,
+ MSM_RPM_PAGE_ACK,
+ MSM_RPM_PAGE_COUNT
+};
+
+enum {
+ MSM_RPM_CTX_SET_0,
+ MSM_RPM_CTX_SET_SLEEP,
+ MSM_RPM_CTX_SET_COUNT,
+
+ MSM_RPM_CTX_NOTIFICATION = 30,
+ MSM_RPM_CTX_REJECTED = 31,
+};
+
+/* RPM control message RAM enums */
+enum {
+ MSM_RPM_CTRL_VERSION_MAJOR,
+ MSM_RPM_CTRL_VERSION_MINOR,
+ MSM_RPM_CTRL_VERSION_BUILD,
+
+ MSM_RPM_CTRL_REQ_CTX_0,
+ MSM_RPM_CTRL_REQ_SEL_0,
+ MSM_RPM_CTRL_ACK_CTX_0,
+ MSM_RPM_CTRL_ACK_SEL_0,
+
+ MSM_RPM_CTRL_LAST,
+};
+
+enum {
+ MSM_RPM_ID_NOTIFICATION_CONFIGURED_0 = 0,
+ MSM_RPM_ID_NOTIFICATION_CONFIGURED_7 =
+ MSM_RPM_ID_NOTIFICATION_CONFIGURED_0 + 7,
+
+ MSM_RPM_ID_NOTIFICATION_REGISTERED_0,
+ MSM_RPM_ID_NOTIFICATION_REGISTERED_7 =
+ MSM_RPM_ID_NOTIFICATION_REGISTERED_0 + 7,
+
+ MSM_RPM_ID_INVALIDATE_0,
+ MSM_RPM_ID_INVALIDATE_7 =
+ MSM_RPM_ID_INVALIDATE_0 + 7,
+
+ MSM_RPM_ID_TRIGGER_TIMED_TO,
+ MSM_RPM_ID_TRIGGER_TIMED_0,
+ MSM_RPM_ID_TRIGGER_TIMED_SCLK_COUNT,
+
+ MSM_RPM_ID_RPM_CTL,
+
+ /* TRIGGER_CLEAR/SET deprecated in these 24 RESERVED bytes */
+ MSM_RPM_ID_RESERVED_0,
+ MSM_RPM_ID_RESERVED_5 =
+ MSM_RPM_ID_RESERVED_0 + 5,
+
+ MSM_RPM_ID_CXO_CLK,
+ MSM_RPM_ID_PXO_CLK,
+ MSM_RPM_ID_APPS_FABRIC_CLK,
+ MSM_RPM_ID_SYSTEM_FABRIC_CLK,
+ MSM_RPM_ID_MM_FABRIC_CLK,
+ MSM_RPM_ID_DAYTONA_FABRIC_CLK,
+ MSM_RPM_ID_SFPB_CLK,
+ MSM_RPM_ID_CFPB_CLK,
+ MSM_RPM_ID_MMFPB_CLK,
+ MSM_RPM_ID_EBI1_CLK,
+
+ MSM_RPM_ID_APPS_FABRIC_CFG_HALT_0,
+ MSM_RPM_ID_APPS_FABRIC_HALT_0 =
+ MSM_RPM_ID_APPS_FABRIC_CFG_HALT_0,
+ MSM_RPM_ID_APPS_FABRIC_CFG_HALT_1,
+ MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_0,
+ MSM_RPM_ID_APPS_FABRIC_CLOCK_MODE_0 =
+ MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_0,
+ MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_1,
+ MSM_RPM_ID_APPS_FABRIC_CFG_CLKMOD_2,
+ MSM_RPM_ID_APPS_FABRIC_CFG_IOCTL,
+ MSM_RPM_ID_APPS_FABRIC_ARB_0,
+ MSM_RPM_ID_APPS_FABRIC_ARB_11 =
+ MSM_RPM_ID_APPS_FABRIC_ARB_0 + 11,
+
+ MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0,
+ MSM_RPM_ID_SYSTEM_FABRIC_HALT_0 =
+ MSM_RPM_ID_SYS_FABRIC_CFG_HALT_0,
+ MSM_RPM_ID_SYS_FABRIC_CFG_HALT_1,
+ MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_0,
+ MSM_RPM_ID_SYSTEM_FABRIC_CLOCK_MODE_0 =
+ MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_0,
+ MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_1,
+ MSM_RPM_ID_SYS_FABRIC_CFG_CLKMOD_2,
+ MSM_RPM_ID_SYS_FABRIC_CFG_IOCTL,
+ MSM_RPM_ID_SYSTEM_FABRIC_ARB_0,
+ MSM_RPM_ID_SYSTEM_FABRIC_ARB_29 =
+ MSM_RPM_ID_SYSTEM_FABRIC_ARB_0 + 29,
+
+ MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
+ MSM_RPM_ID_MM_FABRIC_HALT_0 =
+ MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_0,
+ MSM_RPM_ID_MMSS_FABRIC_CFG_HALT_1,
+ MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_0,
+ MSM_RPM_ID_MM_FABRIC_CLOCK_MODE_0 =
+ MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_0,
+ MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_1,
+ MSM_RPM_ID_MMSS_FABRIC_CFG_CLKMOD_2,
+ MSM_RPM_ID_MMSS_FABRIC_CFG_IOCTL,
+ MSM_RPM_ID_MM_FABRIC_ARB_0,
+ MSM_RPM_ID_MM_FABRIC_ARB_22 =
+ MSM_RPM_ID_MM_FABRIC_ARB_0 + 22,
+
+ MSM_RPM_ID_PM8921_S1_0,
+ MSM_RPM_ID_PM8921_S1_1,
+ MSM_RPM_ID_PM8921_S2_0,
+ MSM_RPM_ID_PM8921_S2_1,
+ MSM_RPM_ID_PM8921_S3_0,
+ MSM_RPM_ID_PM8921_S3_1,
+ MSM_RPM_ID_PM8921_S4_0,
+ MSM_RPM_ID_PM8921_S4_1,
+ MSM_RPM_ID_PM8921_S5_0,
+ MSM_RPM_ID_PM8921_S5_1,
+ MSM_RPM_ID_PM8921_S6_0,
+ MSM_RPM_ID_PM8921_S6_1,
+ MSM_RPM_ID_PM8921_S7_0,
+ MSM_RPM_ID_PM8921_S7_1,
+ MSM_RPM_ID_PM8921_S8_0,
+ MSM_RPM_ID_PM8921_S8_1,
+ MSM_RPM_ID_PM8921_L1_0,
+ MSM_RPM_ID_PM8921_L1_1,
+ MSM_RPM_ID_PM8921_L2_0,
+ MSM_RPM_ID_PM8921_L2_1,
+ MSM_RPM_ID_PM8921_L3_0,
+ MSM_RPM_ID_PM8921_L3_1,
+ MSM_RPM_ID_PM8921_L4_0,
+ MSM_RPM_ID_PM8921_L4_1,
+ MSM_RPM_ID_PM8921_L5_0,
+ MSM_RPM_ID_PM8921_L5_1,
+ MSM_RPM_ID_PM8921_L6_0,
+ MSM_RPM_ID_PM8921_L6_1,
+ MSM_RPM_ID_PM8921_L7_0,
+ MSM_RPM_ID_PM8921_L7_1,
+ MSM_RPM_ID_PM8921_L8_0,
+ MSM_RPM_ID_PM8921_L8_1,
+ MSM_RPM_ID_PM8921_L9_0,
+ MSM_RPM_ID_PM8921_L9_1,
+ MSM_RPM_ID_PM8921_L10_0,
+ MSM_RPM_ID_PM8921_L10_1,
+ MSM_RPM_ID_PM8921_L11_0,
+ MSM_RPM_ID_PM8921_L11_1,
+ MSM_RPM_ID_PM8921_L12_0,
+ MSM_RPM_ID_PM8921_L12_1,
+ MSM_RPM_ID_PM8921_L13_0,
+ MSM_RPM_ID_PM8921_L13_1,
+ MSM_RPM_ID_PM8921_L14_0,
+ MSM_RPM_ID_PM8921_L14_1,
+ MSM_RPM_ID_PM8921_L15_0,
+ MSM_RPM_ID_PM8921_L15_1,
+ MSM_RPM_ID_PM8921_L16_0,
+ MSM_RPM_ID_PM8921_L16_1,
+ MSM_RPM_ID_PM8921_L17_0,
+ MSM_RPM_ID_PM8921_L17_1,
+ MSM_RPM_ID_PM8921_L18_0,
+ MSM_RPM_ID_PM8921_L18_1,
+ MSM_RPM_ID_PM8921_L19_0,
+ MSM_RPM_ID_PM8921_L19_1,
+ MSM_RPM_ID_PM8921_L20_0,
+ MSM_RPM_ID_PM8921_L20_1,
+ MSM_RPM_ID_PM8921_L21_0,
+ MSM_RPM_ID_PM8921_L21_1,
+ MSM_RPM_ID_PM8921_L22_0,
+ MSM_RPM_ID_PM8921_L22_1,
+ MSM_RPM_ID_PM8921_L23_0,
+ MSM_RPM_ID_PM8921_L23_1,
+ MSM_RPM_ID_PM8921_L24_0,
+ MSM_RPM_ID_PM8921_L24_1,
+ MSM_RPM_ID_PM8921_L25_0,
+ MSM_RPM_ID_PM8921_L25_1,
+ MSM_RPM_ID_PM8921_L26_0,
+ MSM_RPM_ID_PM8921_L26_1,
+ MSM_RPM_ID_PM8921_L27_0,
+ MSM_RPM_ID_PM8921_L27_1,
+ MSM_RPM_ID_PM8921_L28_0,
+ MSM_RPM_ID_PM8921_L28_1,
+ MSM_RPM_ID_PM8921_L29_0,
+ MSM_RPM_ID_PM8921_L29_1,
+ MSM_RPM_ID_PM8921_CLK1_0,
+ MSM_RPM_ID_PM8921_CLK1_1,
+ MSM_RPM_ID_PM8921_CLK2_0,
+ MSM_RPM_ID_PM8921_CLK2_1,
+ MSM_RPM_ID_PM8921_LVS1,
+ MSM_RPM_ID_PM8921_LVS2,
+ MSM_RPM_ID_PM8921_LVS3,
+ MSM_RPM_ID_PM8921_LVS4,
+ MSM_RPM_ID_PM8921_LVS5,
+ MSM_RPM_ID_PM8921_LVS6,
+ MSM_RPM_ID_PM8921_LVS7,
+ MSM_RPM_ID_NCP_0,
+ MSM_RPM_ID_NCP_1,
+ MSM_RPM_ID_CXO_BUFFERS,
+ MSM_RPM_ID_USB_OTG_SWITCH,
+ MSM_RPM_ID_HDMI_SWITCH,
+ MSM_RPM_ID_DDR_DMM_0,
+ MSM_RPM_ID_DDR_DMM_1,
+ MSM_RPM_ID_QDSS_CLK,
+
+ /* 8660 specific ids */
+ MSM_RPM_ID_TRIGGER_SET_FROM,
+ MSM_RPM_ID_TRIGGER_SET_TO,
+ MSM_RPM_ID_TRIGGER_SET_TRIGGER,
+
+ MSM_RPM_ID_TRIGGER_CLEAR_FROM,
+ MSM_RPM_ID_TRIGGER_CLEAR_TO,
+ MSM_RPM_ID_TRIGGER_CLEAR_TRIGGER,
+ MSM_RPM_ID_PLL_4,
+ MSM_RPM_ID_SMI_CLK,
+ MSM_RPM_ID_APPS_L2_CACHE_CTL,
+
+ /* pmic 8901 */
+ MSM_RPM_ID_SMPS0B_0,
+ MSM_RPM_ID_SMPS0B_1,
+ MSM_RPM_ID_SMPS1B_0,
+ MSM_RPM_ID_SMPS1B_1,
+ MSM_RPM_ID_SMPS2B_0,
+ MSM_RPM_ID_SMPS2B_1,
+ MSM_RPM_ID_SMPS3B_0,
+ MSM_RPM_ID_SMPS3B_1,
+ MSM_RPM_ID_SMPS4B_0,
+ MSM_RPM_ID_SMPS4B_1,
+ MSM_RPM_ID_LDO0B_0,
+ MSM_RPM_ID_LDO0B_1,
+ MSM_RPM_ID_LDO1B_0,
+ MSM_RPM_ID_LDO1B_1,
+ MSM_RPM_ID_LDO2B_0,
+ MSM_RPM_ID_LDO2B_1,
+ MSM_RPM_ID_LDO3B_0,
+ MSM_RPM_ID_LDO3B_1,
+ MSM_RPM_ID_LDO4B_0,
+ MSM_RPM_ID_LDO4B_1,
+ MSM_RPM_ID_LDO5B_0,
+ MSM_RPM_ID_LDO5B_1,
+ MSM_RPM_ID_LDO6B_0,
+ MSM_RPM_ID_LDO6B_1,
+ MSM_RPM_ID_LVS0B,
+ MSM_RPM_ID_LVS1B,
+ MSM_RPM_ID_LVS2B,
+ MSM_RPM_ID_LVS3B,
+ MSM_RPM_ID_MVS,
+
+ /* pmic 8058 */
+ MSM_RPM_ID_SMPS0_0,
+ MSM_RPM_ID_SMPS0_1,
+ MSM_RPM_ID_SMPS1_0,
+ MSM_RPM_ID_SMPS1_1,
+ MSM_RPM_ID_SMPS2_0,
+ MSM_RPM_ID_SMPS2_1,
+ MSM_RPM_ID_SMPS3_0,
+ MSM_RPM_ID_SMPS3_1,
+ MSM_RPM_ID_SMPS4_0,
+ MSM_RPM_ID_SMPS4_1,
+ MSM_RPM_ID_LDO0_0,
+ MSM_RPM_ID_LDO0_1,
+ MSM_RPM_ID_LDO1_0,
+ MSM_RPM_ID_LDO1_1,
+ MSM_RPM_ID_LDO2_0,
+ MSM_RPM_ID_LDO2_1,
+ MSM_RPM_ID_LDO3_0,
+ MSM_RPM_ID_LDO3_1,
+ MSM_RPM_ID_LDO4_0,
+ MSM_RPM_ID_LDO4_1,
+ MSM_RPM_ID_LDO5_0,
+ MSM_RPM_ID_LDO5_1,
+ MSM_RPM_ID_LDO6_0,
+ MSM_RPM_ID_LDO6_1,
+ MSM_RPM_ID_LDO7_0,
+ MSM_RPM_ID_LDO7_1,
+ MSM_RPM_ID_LDO8_0,
+ MSM_RPM_ID_LDO8_1,
+ MSM_RPM_ID_LDO9_0,
+ MSM_RPM_ID_LDO9_1,
+ MSM_RPM_ID_LDO10_0,
+ MSM_RPM_ID_LDO10_1,
+ MSM_RPM_ID_LDO11_0,
+ MSM_RPM_ID_LDO11_1,
+ MSM_RPM_ID_LDO12_0,
+ MSM_RPM_ID_LDO12_1,
+ MSM_RPM_ID_LDO13_0,
+ MSM_RPM_ID_LDO13_1,
+ MSM_RPM_ID_LDO14_0,
+ MSM_RPM_ID_LDO14_1,
+ MSM_RPM_ID_LDO15_0,
+ MSM_RPM_ID_LDO15_1,
+ MSM_RPM_ID_LDO16_0,
+ MSM_RPM_ID_LDO16_1,
+ MSM_RPM_ID_LDO17_0,
+ MSM_RPM_ID_LDO17_1,
+ MSM_RPM_ID_LDO18_0,
+ MSM_RPM_ID_LDO18_1,
+ MSM_RPM_ID_LDO19_0,
+ MSM_RPM_ID_LDO19_1,
+ MSM_RPM_ID_LDO20_0,
+ MSM_RPM_ID_LDO20_1,
+ MSM_RPM_ID_LDO21_0,
+ MSM_RPM_ID_LDO21_1,
+ MSM_RPM_ID_LDO22_0,
+ MSM_RPM_ID_LDO22_1,
+ MSM_RPM_ID_LDO23_0,
+ MSM_RPM_ID_LDO23_1,
+ MSM_RPM_ID_LDO24_0,
+ MSM_RPM_ID_LDO24_1,
+ MSM_RPM_ID_LDO25_0,
+ MSM_RPM_ID_LDO25_1,
+ MSM_RPM_ID_LVS0,
+ MSM_RPM_ID_LVS1,
+
+ /* 9615 specific */
+ MSM_RPM_ID_PM8018_S1_0,
+ MSM_RPM_ID_PM8018_S1_1,
+ MSM_RPM_ID_PM8018_S2_0,
+ MSM_RPM_ID_PM8018_S2_1,
+ MSM_RPM_ID_PM8018_S3_0,
+ MSM_RPM_ID_PM8018_S3_1,
+ MSM_RPM_ID_PM8018_S4_0,
+ MSM_RPM_ID_PM8018_S4_1,
+ MSM_RPM_ID_PM8018_S5_0,
+ MSM_RPM_ID_PM8018_S5_1,
+ MSM_RPM_ID_PM8018_L1_0,
+ MSM_RPM_ID_PM8018_L1_1,
+ MSM_RPM_ID_PM8018_L2_0,
+ MSM_RPM_ID_PM8018_L2_1,
+ MSM_RPM_ID_PM8018_L3_0,
+ MSM_RPM_ID_PM8018_L3_1,
+ MSM_RPM_ID_PM8018_L4_0,
+ MSM_RPM_ID_PM8018_L4_1,
+ MSM_RPM_ID_PM8018_L5_0,
+ MSM_RPM_ID_PM8018_L5_1,
+ MSM_RPM_ID_PM8018_L6_0,
+ MSM_RPM_ID_PM8018_L6_1,
+ MSM_RPM_ID_PM8018_L7_0,
+ MSM_RPM_ID_PM8018_L7_1,
+ MSM_RPM_ID_PM8018_L8_0,
+ MSM_RPM_ID_PM8018_L8_1,
+ MSM_RPM_ID_PM8018_L9_0,
+ MSM_RPM_ID_PM8018_L9_1,
+ MSM_RPM_ID_PM8018_L10_0,
+ MSM_RPM_ID_PM8018_L10_1,
+ MSM_RPM_ID_PM8018_L11_0,
+ MSM_RPM_ID_PM8018_L11_1,
+ MSM_RPM_ID_PM8018_L12_0,
+ MSM_RPM_ID_PM8018_L12_1,
+ MSM_RPM_ID_PM8018_L13_0,
+ MSM_RPM_ID_PM8018_L13_1,
+ MSM_RPM_ID_PM8018_L14_0,
+ MSM_RPM_ID_PM8018_L14_1,
+ MSM_RPM_ID_PM8018_LVS1,
+
+ /* 8930 specific */
+ MSM_RPM_ID_PM8038_S1_0,
+ MSM_RPM_ID_PM8038_S1_1,
+ MSM_RPM_ID_PM8038_S2_0,
+ MSM_RPM_ID_PM8038_S2_1,
+ MSM_RPM_ID_PM8038_S3_0,
+ MSM_RPM_ID_PM8038_S3_1,
+ MSM_RPM_ID_PM8038_S4_0,
+ MSM_RPM_ID_PM8038_S4_1,
+ MSM_RPM_ID_PM8038_S5_0,
+ MSM_RPM_ID_PM8038_S5_1,
+ MSM_RPM_ID_PM8038_S6_0,
+ MSM_RPM_ID_PM8038_S6_1,
+ MSM_RPM_ID_PM8038_L1_0,
+ MSM_RPM_ID_PM8038_L1_1,
+ MSM_RPM_ID_PM8038_L2_0,
+ MSM_RPM_ID_PM8038_L2_1,
+ MSM_RPM_ID_PM8038_L3_0,
+ MSM_RPM_ID_PM8038_L3_1,
+ MSM_RPM_ID_PM8038_L4_0,
+ MSM_RPM_ID_PM8038_L4_1,
+ MSM_RPM_ID_PM8038_L5_0,
+ MSM_RPM_ID_PM8038_L5_1,
+ MSM_RPM_ID_PM8038_L6_0,
+ MSM_RPM_ID_PM8038_L6_1,
+ MSM_RPM_ID_PM8038_L7_0,
+ MSM_RPM_ID_PM8038_L7_1,
+ MSM_RPM_ID_PM8038_L8_0,
+ MSM_RPM_ID_PM8038_L8_1,
+ MSM_RPM_ID_PM8038_L9_0,
+ MSM_RPM_ID_PM8038_L9_1,
+ MSM_RPM_ID_PM8038_L10_0,
+ MSM_RPM_ID_PM8038_L10_1,
+ MSM_RPM_ID_PM8038_L11_0,
+ MSM_RPM_ID_PM8038_L11_1,
+ MSM_RPM_ID_PM8038_L12_0,
+ MSM_RPM_ID_PM8038_L12_1,
+ MSM_RPM_ID_PM8038_L13_0,
+ MSM_RPM_ID_PM8038_L13_1,
+ MSM_RPM_ID_PM8038_L14_0,
+ MSM_RPM_ID_PM8038_L14_1,
+ MSM_RPM_ID_PM8038_L15_0,
+ MSM_RPM_ID_PM8038_L15_1,
+ MSM_RPM_ID_PM8038_L16_0,
+ MSM_RPM_ID_PM8038_L16_1,
+ MSM_RPM_ID_PM8038_L17_0,
+ MSM_RPM_ID_PM8038_L17_1,
+ MSM_RPM_ID_PM8038_L18_0,
+ MSM_RPM_ID_PM8038_L18_1,
+ MSM_RPM_ID_PM8038_L19_0,
+ MSM_RPM_ID_PM8038_L19_1,
+ MSM_RPM_ID_PM8038_L20_0,
+ MSM_RPM_ID_PM8038_L20_1,
+ MSM_RPM_ID_PM8038_L21_0,
+ MSM_RPM_ID_PM8038_L21_1,
+ MSM_RPM_ID_PM8038_L22_0,
+ MSM_RPM_ID_PM8038_L22_1,
+ MSM_RPM_ID_PM8038_L23_0,
+ MSM_RPM_ID_PM8038_L23_1,
+ MSM_RPM_ID_PM8038_L24_0,
+ MSM_RPM_ID_PM8038_L24_1,
+ MSM_RPM_ID_PM8038_L25_0,
+ MSM_RPM_ID_PM8038_L25_1,
+ MSM_RPM_ID_PM8038_L26_0,
+ MSM_RPM_ID_PM8038_L26_1,
+ MSM_RPM_ID_PM8038_L27_0,
+ MSM_RPM_ID_PM8038_L27_1,
+ MSM_RPM_ID_PM8038_CLK1_0,
+ MSM_RPM_ID_PM8038_CLK1_1,
+ MSM_RPM_ID_PM8038_CLK2_0,
+ MSM_RPM_ID_PM8038_CLK2_1,
+ MSM_RPM_ID_PM8038_LVS1,
+ MSM_RPM_ID_PM8038_LVS2,
+
+ /* PM8917 specific */
+ MSM_RPM_ID_PM8917_S1_0,
+ MSM_RPM_ID_PM8917_S1_1,
+ MSM_RPM_ID_PM8917_S2_0,
+ MSM_RPM_ID_PM8917_S2_1,
+ MSM_RPM_ID_PM8917_S3_0,
+ MSM_RPM_ID_PM8917_S3_1,
+ MSM_RPM_ID_PM8917_S4_0,
+ MSM_RPM_ID_PM8917_S4_1,
+ MSM_RPM_ID_PM8917_S5_0,
+ MSM_RPM_ID_PM8917_S5_1,
+ MSM_RPM_ID_PM8917_S6_0,
+ MSM_RPM_ID_PM8917_S6_1,
+ MSM_RPM_ID_PM8917_S7_0,
+ MSM_RPM_ID_PM8917_S7_1,
+ MSM_RPM_ID_PM8917_S8_0,
+ MSM_RPM_ID_PM8917_S8_1,
+ MSM_RPM_ID_PM8917_L1_0,
+ MSM_RPM_ID_PM8917_L1_1,
+ MSM_RPM_ID_PM8917_L2_0,
+ MSM_RPM_ID_PM8917_L2_1,
+ MSM_RPM_ID_PM8917_L3_0,
+ MSM_RPM_ID_PM8917_L3_1,
+ MSM_RPM_ID_PM8917_L4_0,
+ MSM_RPM_ID_PM8917_L4_1,
+ MSM_RPM_ID_PM8917_L5_0,
+ MSM_RPM_ID_PM8917_L5_1,
+ MSM_RPM_ID_PM8917_L6_0,
+ MSM_RPM_ID_PM8917_L6_1,
+ MSM_RPM_ID_PM8917_L7_0,
+ MSM_RPM_ID_PM8917_L7_1,
+ MSM_RPM_ID_PM8917_L8_0,
+ MSM_RPM_ID_PM8917_L8_1,
+ MSM_RPM_ID_PM8917_L9_0,
+ MSM_RPM_ID_PM8917_L9_1,
+ MSM_RPM_ID_PM8917_L10_0,
+ MSM_RPM_ID_PM8917_L10_1,
+ MSM_RPM_ID_PM8917_L11_0,
+ MSM_RPM_ID_PM8917_L11_1,
+ MSM_RPM_ID_PM8917_L12_0,
+ MSM_RPM_ID_PM8917_L12_1,
+ MSM_RPM_ID_PM8917_L14_0,
+ MSM_RPM_ID_PM8917_L14_1,
+ MSM_RPM_ID_PM8917_L15_0,
+ MSM_RPM_ID_PM8917_L15_1,
+ MSM_RPM_ID_PM8917_L16_0,
+ MSM_RPM_ID_PM8917_L16_1,
+ MSM_RPM_ID_PM8917_L17_0,
+ MSM_RPM_ID_PM8917_L17_1,
+ MSM_RPM_ID_PM8917_L18_0,
+ MSM_RPM_ID_PM8917_L18_1,
+ MSM_RPM_ID_PM8917_L21_0,
+ MSM_RPM_ID_PM8917_L21_1,
+ MSM_RPM_ID_PM8917_L22_0,
+ MSM_RPM_ID_PM8917_L22_1,
+ MSM_RPM_ID_PM8917_L23_0,
+ MSM_RPM_ID_PM8917_L23_1,
+ MSM_RPM_ID_PM8917_L24_0,
+ MSM_RPM_ID_PM8917_L24_1,
+ MSM_RPM_ID_PM8917_L25_0,
+ MSM_RPM_ID_PM8917_L25_1,
+ MSM_RPM_ID_PM8917_L26_0,
+ MSM_RPM_ID_PM8917_L26_1,
+ MSM_RPM_ID_PM8917_L27_0,
+ MSM_RPM_ID_PM8917_L27_1,
+ MSM_RPM_ID_PM8917_L28_0,
+ MSM_RPM_ID_PM8917_L28_1,
+ MSM_RPM_ID_PM8917_L29_0,
+ MSM_RPM_ID_PM8917_L29_1,
+ MSM_RPM_ID_PM8917_L30_0,
+ MSM_RPM_ID_PM8917_L30_1,
+ MSM_RPM_ID_PM8917_L31_0,
+ MSM_RPM_ID_PM8917_L31_1,
+ MSM_RPM_ID_PM8917_L32_0,
+ MSM_RPM_ID_PM8917_L32_1,
+ MSM_RPM_ID_PM8917_L33_0,
+ MSM_RPM_ID_PM8917_L33_1,
+ MSM_RPM_ID_PM8917_L34_0,
+ MSM_RPM_ID_PM8917_L34_1,
+ MSM_RPM_ID_PM8917_L35_0,
+ MSM_RPM_ID_PM8917_L35_1,
+ MSM_RPM_ID_PM8917_L36_0,
+ MSM_RPM_ID_PM8917_L36_1,
+ MSM_RPM_ID_PM8917_CLK1_0,
+ MSM_RPM_ID_PM8917_CLK1_1,
+ MSM_RPM_ID_PM8917_CLK2_0,
+ MSM_RPM_ID_PM8917_CLK2_1,
+ MSM_RPM_ID_PM8917_LVS1,
+ MSM_RPM_ID_PM8917_LVS3,
+ MSM_RPM_ID_PM8917_LVS4,
+ MSM_RPM_ID_PM8917_LVS5,
+ MSM_RPM_ID_PM8917_LVS6,
+ MSM_RPM_ID_PM8917_LVS7,
+ MSM_RPM_ID_VOLTAGE_CORNER,
+
+ /* 8064 specific */
+ MSM_RPM_ID_PM8821_S1_0,
+ MSM_RPM_ID_PM8821_S1_1,
+ MSM_RPM_ID_PM8821_S2_0,
+ MSM_RPM_ID_PM8821_S2_1,
+ MSM_RPM_ID_PM8821_L1_0,
+ MSM_RPM_ID_PM8821_L1_1,
+ MSM_RPM_ID_VDDMIN_GPIO,
+
+ MSM_RPM_ID_LAST,
+};
+
+enum {
+ MSM_RPM_STATUS_ID_VERSION_MAJOR,
+ MSM_RPM_STATUS_ID_VERSION_MINOR,
+ MSM_RPM_STATUS_ID_VERSION_BUILD,
+ MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_0,
+ MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_1,
+ MSM_RPM_STATUS_ID_SUPPORTED_RESOURCES_2,
+ MSM_RPM_STATUS_ID_RESERVED_SUPPORTED_RESOURCES_0,
+ MSM_RPM_STATUS_ID_SEQUENCE,
+ MSM_RPM_STATUS_ID_RPM_CTL,
+ MSM_RPM_STATUS_ID_CXO_CLK,
+ MSM_RPM_STATUS_ID_PXO_CLK,
+ MSM_RPM_STATUS_ID_APPS_FABRIC_CLK,
+ MSM_RPM_STATUS_ID_SYSTEM_FABRIC_CLK,
+ MSM_RPM_STATUS_ID_MM_FABRIC_CLK,
+ MSM_RPM_STATUS_ID_DAYTONA_FABRIC_CLK,
+ MSM_RPM_STATUS_ID_SFPB_CLK,
+ MSM_RPM_STATUS_ID_CFPB_CLK,
+ MSM_RPM_STATUS_ID_MMFPB_CLK,
+ MSM_RPM_STATUS_ID_EBI1_CLK,
+ MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_HALT,
+ MSM_RPM_STATUS_ID_APPS_FABRIC_HALT =
+ MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_HALT,
+ MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_CLKMOD,
+ MSM_RPM_STATUS_ID_APPS_FABRIC_CLOCK_MODE =
+ MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_CLKMOD,
+ MSM_RPM_STATUS_ID_APPS_FABRIC_CFG_IOCTL,
+ MSM_RPM_STATUS_ID_APPS_FABRIC_ARB,
+ MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_HALT,
+ MSM_RPM_STATUS_ID_SYSTEM_FABRIC_HALT =
+ MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_HALT,
+ MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_CLKMOD,
+ MSM_RPM_STATUS_ID_SYSTEM_FABRIC_CLOCK_MODE =
+ MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_CLKMOD,
+ MSM_RPM_STATUS_ID_SYS_FABRIC_CFG_IOCTL,
+ MSM_RPM_STATUS_ID_SYSTEM_FABRIC_ARB,
+ MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_HALT,
+ MSM_RPM_STATUS_ID_MM_FABRIC_HALT =
+ MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_HALT,
+ MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD,
+ MSM_RPM_STATUS_ID_MM_FABRIC_CLOCK_MODE =
+ MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD,
+ MSM_RPM_STATUS_ID_MMSS_FABRIC_CFG_IOCTL,
+ MSM_RPM_STATUS_ID_MM_FABRIC_ARB,
+ MSM_RPM_STATUS_ID_PM8921_S1_0,
+ MSM_RPM_STATUS_ID_PM8921_S1_1,
+ MSM_RPM_STATUS_ID_PM8921_S2_0,
+ MSM_RPM_STATUS_ID_PM8921_S2_1,
+ MSM_RPM_STATUS_ID_PM8921_S3_0,
+ MSM_RPM_STATUS_ID_PM8921_S3_1,
+ MSM_RPM_STATUS_ID_PM8921_S4_0,
+ MSM_RPM_STATUS_ID_PM8921_S4_1,
+ MSM_RPM_STATUS_ID_PM8921_S5_0,
+ MSM_RPM_STATUS_ID_PM8921_S5_1,
+ MSM_RPM_STATUS_ID_PM8921_S6_0,
+ MSM_RPM_STATUS_ID_PM8921_S6_1,
+ MSM_RPM_STATUS_ID_PM8921_S7_0,
+ MSM_RPM_STATUS_ID_PM8921_S7_1,
+ MSM_RPM_STATUS_ID_PM8921_S8_0,
+ MSM_RPM_STATUS_ID_PM8921_S8_1,
+ MSM_RPM_STATUS_ID_PM8921_L1_0,
+ MSM_RPM_STATUS_ID_PM8921_L1_1,
+ MSM_RPM_STATUS_ID_PM8921_L2_0,
+ MSM_RPM_STATUS_ID_PM8921_L2_1,
+ MSM_RPM_STATUS_ID_PM8921_L3_0,
+ MSM_RPM_STATUS_ID_PM8921_L3_1,
+ MSM_RPM_STATUS_ID_PM8921_L4_0,
+ MSM_RPM_STATUS_ID_PM8921_L4_1,
+ MSM_RPM_STATUS_ID_PM8921_L5_0,
+ MSM_RPM_STATUS_ID_PM8921_L5_1,
+ MSM_RPM_STATUS_ID_PM8921_L6_0,
+ MSM_RPM_STATUS_ID_PM8921_L6_1,
+ MSM_RPM_STATUS_ID_PM8921_L7_0,
+ MSM_RPM_STATUS_ID_PM8921_L7_1,
+ MSM_RPM_STATUS_ID_PM8921_L8_0,
+ MSM_RPM_STATUS_ID_PM8921_L8_1,
+ MSM_RPM_STATUS_ID_PM8921_L9_0,
+ MSM_RPM_STATUS_ID_PM8921_L9_1,
+ MSM_RPM_STATUS_ID_PM8921_L10_0,
+ MSM_RPM_STATUS_ID_PM8921_L10_1,
+ MSM_RPM_STATUS_ID_PM8921_L11_0,
+ MSM_RPM_STATUS_ID_PM8921_L11_1,
+ MSM_RPM_STATUS_ID_PM8921_L12_0,
+ MSM_RPM_STATUS_ID_PM8921_L12_1,
+ MSM_RPM_STATUS_ID_PM8921_L13_0,
+ MSM_RPM_STATUS_ID_PM8921_L13_1,
+ MSM_RPM_STATUS_ID_PM8921_L14_0,
+ MSM_RPM_STATUS_ID_PM8921_L14_1,
+ MSM_RPM_STATUS_ID_PM8921_L15_0,
+ MSM_RPM_STATUS_ID_PM8921_L15_1,
+ MSM_RPM_STATUS_ID_PM8921_L16_0,
+ MSM_RPM_STATUS_ID_PM8921_L16_1,
+ MSM_RPM_STATUS_ID_PM8921_L17_0,
+ MSM_RPM_STATUS_ID_PM8921_L17_1,
+ MSM_RPM_STATUS_ID_PM8921_L18_0,
+ MSM_RPM_STATUS_ID_PM8921_L18_1,
+ MSM_RPM_STATUS_ID_PM8921_L19_0,
+ MSM_RPM_STATUS_ID_PM8921_L19_1,
+ MSM_RPM_STATUS_ID_PM8921_L20_0,
+ MSM_RPM_STATUS_ID_PM8921_L20_1,
+ MSM_RPM_STATUS_ID_PM8921_L21_0,
+ MSM_RPM_STATUS_ID_PM8921_L21_1,
+ MSM_RPM_STATUS_ID_PM8921_L22_0,
+ MSM_RPM_STATUS_ID_PM8921_L22_1,
+ MSM_RPM_STATUS_ID_PM8921_L23_0,
+ MSM_RPM_STATUS_ID_PM8921_L23_1,
+ MSM_RPM_STATUS_ID_PM8921_L24_0,
+ MSM_RPM_STATUS_ID_PM8921_L24_1,
+ MSM_RPM_STATUS_ID_PM8921_L25_0,
+ MSM_RPM_STATUS_ID_PM8921_L25_1,
+ MSM_RPM_STATUS_ID_PM8921_L26_0,
+ MSM_RPM_STATUS_ID_PM8921_L26_1,
+ MSM_RPM_STATUS_ID_PM8921_L27_0,
+ MSM_RPM_STATUS_ID_PM8921_L27_1,
+ MSM_RPM_STATUS_ID_PM8921_L28_0,
+ MSM_RPM_STATUS_ID_PM8921_L28_1,
+ MSM_RPM_STATUS_ID_PM8921_L29_0,
+ MSM_RPM_STATUS_ID_PM8921_L29_1,
+ MSM_RPM_STATUS_ID_PM8921_CLK1_0,
+ MSM_RPM_STATUS_ID_PM8921_CLK1_1,
+ MSM_RPM_STATUS_ID_PM8921_CLK2_0,
+ MSM_RPM_STATUS_ID_PM8921_CLK2_1,
+ MSM_RPM_STATUS_ID_PM8921_LVS1,
+ MSM_RPM_STATUS_ID_PM8921_LVS2,
+ MSM_RPM_STATUS_ID_PM8921_LVS3,
+ MSM_RPM_STATUS_ID_PM8921_LVS4,
+ MSM_RPM_STATUS_ID_PM8921_LVS5,
+ MSM_RPM_STATUS_ID_PM8921_LVS6,
+ MSM_RPM_STATUS_ID_PM8921_LVS7,
+ MSM_RPM_STATUS_ID_NCP_0,
+ MSM_RPM_STATUS_ID_NCP_1,
+ MSM_RPM_STATUS_ID_CXO_BUFFERS,
+ MSM_RPM_STATUS_ID_USB_OTG_SWITCH,
+ MSM_RPM_STATUS_ID_HDMI_SWITCH,
+ MSM_RPM_STATUS_ID_DDR_DMM_0,
+ MSM_RPM_STATUS_ID_DDR_DMM_1,
+ MSM_RPM_STATUS_ID_EBI1_CH0_RANGE,
+ MSM_RPM_STATUS_ID_EBI1_CH1_RANGE,
+ MSM_RPM_STATUS_ID_QDSS_CLK,
+
+ /* 8930 aliases to simplify device mapping */
+ MSM_RPM_STATUS_ID_PM8038_NCP_0 = MSM_RPM_STATUS_ID_NCP_0,
+ MSM_RPM_STATUS_ID_PM8038_NCP_1 = MSM_RPM_STATUS_ID_NCP_1,
+ MSM_RPM_STATUS_ID_PM8038_CXO_BUFFERS
+ = MSM_RPM_STATUS_ID_CXO_BUFFERS,
+ MSM_RPM_STATUS_ID_PM8038_USB_OTG_SWITCH
+ = MSM_RPM_STATUS_ID_USB_OTG_SWITCH,
+ MSM_RPM_STATUS_ID_PM8038_HDMI_SWITCH
+ = MSM_RPM_STATUS_ID_HDMI_SWITCH,
+ MSM_RPM_STATUS_ID_PM8038_QDSS_CLK
+ = MSM_RPM_STATUS_ID_QDSS_CLK,
+
+ MSM_RPM_STATUS_ID_PM8917_NCP_0 = MSM_RPM_STATUS_ID_NCP_0,
+ MSM_RPM_STATUS_ID_PM8917_NCP_1 = MSM_RPM_STATUS_ID_NCP_1,
+ MSM_RPM_STATUS_ID_PM8917_CXO_BUFFERS
+ = MSM_RPM_STATUS_ID_CXO_BUFFERS,
+ MSM_RPM_STATUS_ID_PM8917_USB_OTG_SWITCH
+ = MSM_RPM_STATUS_ID_USB_OTG_SWITCH,
+ MSM_RPM_STATUS_ID_PM8917_HDMI_SWITCH
+ = MSM_RPM_STATUS_ID_HDMI_SWITCH,
+ MSM_RPM_STATUS_ID_PM8917_QDSS_CLK
+ = MSM_RPM_STATUS_ID_QDSS_CLK,
+
+ /* 8660 Specific */
+ MSM_RPM_STATUS_ID_PLL_4,
+ MSM_RPM_STATUS_ID_SMI_CLK,
+ MSM_RPM_STATUS_ID_APPS_L2_CACHE_CTL,
+ MSM_RPM_STATUS_ID_SMPS0B_0,
+ MSM_RPM_STATUS_ID_SMPS0B_1,
+ MSM_RPM_STATUS_ID_SMPS1B_0,
+ MSM_RPM_STATUS_ID_SMPS1B_1,
+ MSM_RPM_STATUS_ID_SMPS2B_0,
+ MSM_RPM_STATUS_ID_SMPS2B_1,
+ MSM_RPM_STATUS_ID_SMPS3B_0,
+ MSM_RPM_STATUS_ID_SMPS3B_1,
+ MSM_RPM_STATUS_ID_SMPS4B_0,
+ MSM_RPM_STATUS_ID_SMPS4B_1,
+ MSM_RPM_STATUS_ID_LDO0B_0,
+ MSM_RPM_STATUS_ID_LDO0B_1,
+ MSM_RPM_STATUS_ID_LDO1B_0,
+ MSM_RPM_STATUS_ID_LDO1B_1,
+ MSM_RPM_STATUS_ID_LDO2B_0,
+ MSM_RPM_STATUS_ID_LDO2B_1,
+ MSM_RPM_STATUS_ID_LDO3B_0,
+ MSM_RPM_STATUS_ID_LDO3B_1,
+ MSM_RPM_STATUS_ID_LDO4B_0,
+ MSM_RPM_STATUS_ID_LDO4B_1,
+ MSM_RPM_STATUS_ID_LDO5B_0,
+ MSM_RPM_STATUS_ID_LDO5B_1,
+ MSM_RPM_STATUS_ID_LDO6B_0,
+ MSM_RPM_STATUS_ID_LDO6B_1,
+ MSM_RPM_STATUS_ID_LVS0B,
+ MSM_RPM_STATUS_ID_LVS1B,
+ MSM_RPM_STATUS_ID_LVS2B,
+ MSM_RPM_STATUS_ID_LVS3B,
+ MSM_RPM_STATUS_ID_MVS,
+ MSM_RPM_STATUS_ID_SMPS0_0,
+ MSM_RPM_STATUS_ID_SMPS0_1,
+ MSM_RPM_STATUS_ID_SMPS1_0,
+ MSM_RPM_STATUS_ID_SMPS1_1,
+ MSM_RPM_STATUS_ID_SMPS2_0,
+ MSM_RPM_STATUS_ID_SMPS2_1,
+ MSM_RPM_STATUS_ID_SMPS3_0,
+ MSM_RPM_STATUS_ID_SMPS3_1,
+ MSM_RPM_STATUS_ID_SMPS4_0,
+ MSM_RPM_STATUS_ID_SMPS4_1,
+ MSM_RPM_STATUS_ID_LDO0_0,
+ MSM_RPM_STATUS_ID_LDO0_1,
+ MSM_RPM_STATUS_ID_LDO1_0,
+ MSM_RPM_STATUS_ID_LDO1_1,
+ MSM_RPM_STATUS_ID_LDO2_0,
+ MSM_RPM_STATUS_ID_LDO2_1,
+ MSM_RPM_STATUS_ID_LDO3_0,
+ MSM_RPM_STATUS_ID_LDO3_1,
+ MSM_RPM_STATUS_ID_LDO4_0,
+ MSM_RPM_STATUS_ID_LDO4_1,
+ MSM_RPM_STATUS_ID_LDO5_0,
+ MSM_RPM_STATUS_ID_LDO5_1,
+ MSM_RPM_STATUS_ID_LDO6_0,
+ MSM_RPM_STATUS_ID_LDO6_1,
+ MSM_RPM_STATUS_ID_LDO7_0,
+ MSM_RPM_STATUS_ID_LDO7_1,
+ MSM_RPM_STATUS_ID_LDO8_0,
+ MSM_RPM_STATUS_ID_LDO8_1,
+ MSM_RPM_STATUS_ID_LDO9_0,
+ MSM_RPM_STATUS_ID_LDO9_1,
+ MSM_RPM_STATUS_ID_LDO10_0,
+ MSM_RPM_STATUS_ID_LDO10_1,
+ MSM_RPM_STATUS_ID_LDO11_0,
+ MSM_RPM_STATUS_ID_LDO11_1,
+ MSM_RPM_STATUS_ID_LDO12_0,
+ MSM_RPM_STATUS_ID_LDO12_1,
+ MSM_RPM_STATUS_ID_LDO13_0,
+ MSM_RPM_STATUS_ID_LDO13_1,
+ MSM_RPM_STATUS_ID_LDO14_0,
+ MSM_RPM_STATUS_ID_LDO14_1,
+ MSM_RPM_STATUS_ID_LDO15_0,
+ MSM_RPM_STATUS_ID_LDO15_1,
+ MSM_RPM_STATUS_ID_LDO16_0,
+ MSM_RPM_STATUS_ID_LDO16_1,
+ MSM_RPM_STATUS_ID_LDO17_0,
+ MSM_RPM_STATUS_ID_LDO17_1,
+ MSM_RPM_STATUS_ID_LDO18_0,
+ MSM_RPM_STATUS_ID_LDO18_1,
+ MSM_RPM_STATUS_ID_LDO19_0,
+ MSM_RPM_STATUS_ID_LDO19_1,
+ MSM_RPM_STATUS_ID_LDO20_0,
+ MSM_RPM_STATUS_ID_LDO20_1,
+ MSM_RPM_STATUS_ID_LDO21_0,
+ MSM_RPM_STATUS_ID_LDO21_1,
+ MSM_RPM_STATUS_ID_LDO22_0,
+ MSM_RPM_STATUS_ID_LDO22_1,
+ MSM_RPM_STATUS_ID_LDO23_0,
+ MSM_RPM_STATUS_ID_LDO23_1,
+ MSM_RPM_STATUS_ID_LDO24_0,
+ MSM_RPM_STATUS_ID_LDO24_1,
+ MSM_RPM_STATUS_ID_LDO25_0,
+ MSM_RPM_STATUS_ID_LDO25_1,
+ MSM_RPM_STATUS_ID_LVS0,
+ MSM_RPM_STATUS_ID_LVS1,
+
+ /* 9615 Specific */
+ MSM_RPM_STATUS_ID_PM8018_S1_0,
+ MSM_RPM_STATUS_ID_PM8018_S1_1,
+ MSM_RPM_STATUS_ID_PM8018_S2_0,
+ MSM_RPM_STATUS_ID_PM8018_S2_1,
+ MSM_RPM_STATUS_ID_PM8018_S3_0,
+ MSM_RPM_STATUS_ID_PM8018_S3_1,
+ MSM_RPM_STATUS_ID_PM8018_S4_0,
+ MSM_RPM_STATUS_ID_PM8018_S4_1,
+ MSM_RPM_STATUS_ID_PM8018_S5_0,
+ MSM_RPM_STATUS_ID_PM8018_S5_1,
+ MSM_RPM_STATUS_ID_PM8018_L1_0,
+ MSM_RPM_STATUS_ID_PM8018_L1_1,
+ MSM_RPM_STATUS_ID_PM8018_L2_0,
+ MSM_RPM_STATUS_ID_PM8018_L2_1,
+ MSM_RPM_STATUS_ID_PM8018_L3_0,
+ MSM_RPM_STATUS_ID_PM8018_L3_1,
+ MSM_RPM_STATUS_ID_PM8018_L4_0,
+ MSM_RPM_STATUS_ID_PM8018_L4_1,
+ MSM_RPM_STATUS_ID_PM8018_L5_0,
+ MSM_RPM_STATUS_ID_PM8018_L5_1,
+ MSM_RPM_STATUS_ID_PM8018_L6_0,
+ MSM_RPM_STATUS_ID_PM8018_L6_1,
+ MSM_RPM_STATUS_ID_PM8018_L7_0,
+ MSM_RPM_STATUS_ID_PM8018_L7_1,
+ MSM_RPM_STATUS_ID_PM8018_L8_0,
+ MSM_RPM_STATUS_ID_PM8018_L8_1,
+ MSM_RPM_STATUS_ID_PM8018_L9_0,
+ MSM_RPM_STATUS_ID_PM8018_L9_1,
+ MSM_RPM_STATUS_ID_PM8018_L10_0,
+ MSM_RPM_STATUS_ID_PM8018_L10_1,
+ MSM_RPM_STATUS_ID_PM8018_L11_0,
+ MSM_RPM_STATUS_ID_PM8018_L11_1,
+ MSM_RPM_STATUS_ID_PM8018_L12_0,
+ MSM_RPM_STATUS_ID_PM8018_L12_1,
+ MSM_RPM_STATUS_ID_PM8018_L13_0,
+ MSM_RPM_STATUS_ID_PM8018_L13_1,
+ MSM_RPM_STATUS_ID_PM8018_L14_0,
+ MSM_RPM_STATUS_ID_PM8018_L14_1,
+ MSM_RPM_STATUS_ID_PM8018_LVS1,
+
+ /* 8930 specific */
+ MSM_RPM_STATUS_ID_PM8038_S1_0,
+ MSM_RPM_STATUS_ID_PM8038_S1_1,
+ MSM_RPM_STATUS_ID_PM8038_S2_0,
+ MSM_RPM_STATUS_ID_PM8038_S2_1,
+ MSM_RPM_STATUS_ID_PM8038_S3_0,
+ MSM_RPM_STATUS_ID_PM8038_S3_1,
+ MSM_RPM_STATUS_ID_PM8038_S4_0,
+ MSM_RPM_STATUS_ID_PM8038_S4_1,
+ MSM_RPM_STATUS_ID_PM8038_S5_0,
+ MSM_RPM_STATUS_ID_PM8038_S5_1,
+ MSM_RPM_STATUS_ID_PM8038_S6_0,
+ MSM_RPM_STATUS_ID_PM8038_S6_1,
+ MSM_RPM_STATUS_ID_PM8038_L1_0,
+ MSM_RPM_STATUS_ID_PM8038_L1_1,
+ MSM_RPM_STATUS_ID_PM8038_L2_0,
+ MSM_RPM_STATUS_ID_PM8038_L2_1,
+ MSM_RPM_STATUS_ID_PM8038_L3_0,
+ MSM_RPM_STATUS_ID_PM8038_L3_1,
+ MSM_RPM_STATUS_ID_PM8038_L4_0,
+ MSM_RPM_STATUS_ID_PM8038_L4_1,
+ MSM_RPM_STATUS_ID_PM8038_L5_0,
+ MSM_RPM_STATUS_ID_PM8038_L5_1,
+ MSM_RPM_STATUS_ID_PM8038_L6_0,
+ MSM_RPM_STATUS_ID_PM8038_L6_1,
+ MSM_RPM_STATUS_ID_PM8038_L7_0,
+ MSM_RPM_STATUS_ID_PM8038_L7_1,
+ MSM_RPM_STATUS_ID_PM8038_L8_0,
+ MSM_RPM_STATUS_ID_PM8038_L8_1,
+ MSM_RPM_STATUS_ID_PM8038_L9_0,
+ MSM_RPM_STATUS_ID_PM8038_L9_1,
+ MSM_RPM_STATUS_ID_PM8038_L10_0,
+ MSM_RPM_STATUS_ID_PM8038_L10_1,
+ MSM_RPM_STATUS_ID_PM8038_L11_0,
+ MSM_RPM_STATUS_ID_PM8038_L11_1,
+ MSM_RPM_STATUS_ID_PM8038_L12_0,
+ MSM_RPM_STATUS_ID_PM8038_L12_1,
+ MSM_RPM_STATUS_ID_PM8038_L13_0,
+ MSM_RPM_STATUS_ID_PM8038_L13_1,
+ MSM_RPM_STATUS_ID_PM8038_L14_0,
+ MSM_RPM_STATUS_ID_PM8038_L14_1,
+ MSM_RPM_STATUS_ID_PM8038_L15_0,
+ MSM_RPM_STATUS_ID_PM8038_L15_1,
+ MSM_RPM_STATUS_ID_PM8038_L16_0,
+ MSM_RPM_STATUS_ID_PM8038_L16_1,
+ MSM_RPM_STATUS_ID_PM8038_L17_0,
+ MSM_RPM_STATUS_ID_PM8038_L17_1,
+ MSM_RPM_STATUS_ID_PM8038_L18_0,
+ MSM_RPM_STATUS_ID_PM8038_L18_1,
+ MSM_RPM_STATUS_ID_PM8038_L19_0,
+ MSM_RPM_STATUS_ID_PM8038_L19_1,
+ MSM_RPM_STATUS_ID_PM8038_L20_0,
+ MSM_RPM_STATUS_ID_PM8038_L20_1,
+ MSM_RPM_STATUS_ID_PM8038_L21_0,
+ MSM_RPM_STATUS_ID_PM8038_L21_1,
+ MSM_RPM_STATUS_ID_PM8038_L22_0,
+ MSM_RPM_STATUS_ID_PM8038_L22_1,
+ MSM_RPM_STATUS_ID_PM8038_L23_0,
+ MSM_RPM_STATUS_ID_PM8038_L23_1,
+ MSM_RPM_STATUS_ID_PM8038_L24_0,
+ MSM_RPM_STATUS_ID_PM8038_L24_1,
+ MSM_RPM_STATUS_ID_PM8038_L25_0,
+ MSM_RPM_STATUS_ID_PM8038_L25_1,
+ MSM_RPM_STATUS_ID_PM8038_L26_0,
+ MSM_RPM_STATUS_ID_PM8038_L26_1,
+ MSM_RPM_STATUS_ID_PM8038_L27_0,
+ MSM_RPM_STATUS_ID_PM8038_L27_1,
+ MSM_RPM_STATUS_ID_PM8038_CLK1_0,
+ MSM_RPM_STATUS_ID_PM8038_CLK1_1,
+ MSM_RPM_STATUS_ID_PM8038_CLK2_0,
+ MSM_RPM_STATUS_ID_PM8038_CLK2_1,
+ MSM_RPM_STATUS_ID_PM8038_LVS1,
+ MSM_RPM_STATUS_ID_PM8038_LVS2,
+
+ /* PMIC 8917 */
+ MSM_RPM_STATUS_ID_PM8917_S1_0,
+ MSM_RPM_STATUS_ID_PM8917_S1_1,
+ MSM_RPM_STATUS_ID_PM8917_S2_0,
+ MSM_RPM_STATUS_ID_PM8917_S2_1,
+ MSM_RPM_STATUS_ID_PM8917_S3_0,
+ MSM_RPM_STATUS_ID_PM8917_S3_1,
+ MSM_RPM_STATUS_ID_PM8917_S4_0,
+ MSM_RPM_STATUS_ID_PM8917_S4_1,
+ MSM_RPM_STATUS_ID_PM8917_S5_0,
+ MSM_RPM_STATUS_ID_PM8917_S5_1,
+ MSM_RPM_STATUS_ID_PM8917_S6_0,
+ MSM_RPM_STATUS_ID_PM8917_S6_1,
+ MSM_RPM_STATUS_ID_PM8917_S7_0,
+ MSM_RPM_STATUS_ID_PM8917_S7_1,
+ MSM_RPM_STATUS_ID_PM8917_S8_0,
+ MSM_RPM_STATUS_ID_PM8917_S8_1,
+ MSM_RPM_STATUS_ID_PM8917_L1_0,
+ MSM_RPM_STATUS_ID_PM8917_L1_1,
+ MSM_RPM_STATUS_ID_PM8917_L2_0,
+ MSM_RPM_STATUS_ID_PM8917_L2_1,
+ MSM_RPM_STATUS_ID_PM8917_L3_0,
+ MSM_RPM_STATUS_ID_PM8917_L3_1,
+ MSM_RPM_STATUS_ID_PM8917_L4_0,
+ MSM_RPM_STATUS_ID_PM8917_L4_1,
+ MSM_RPM_STATUS_ID_PM8917_L5_0,
+ MSM_RPM_STATUS_ID_PM8917_L5_1,
+ MSM_RPM_STATUS_ID_PM8917_L6_0,
+ MSM_RPM_STATUS_ID_PM8917_L6_1,
+ MSM_RPM_STATUS_ID_PM8917_L7_0,
+ MSM_RPM_STATUS_ID_PM8917_L7_1,
+ MSM_RPM_STATUS_ID_PM8917_L8_0,
+ MSM_RPM_STATUS_ID_PM8917_L8_1,
+ MSM_RPM_STATUS_ID_PM8917_L9_0,
+ MSM_RPM_STATUS_ID_PM8917_L9_1,
+ MSM_RPM_STATUS_ID_PM8917_L10_0,
+ MSM_RPM_STATUS_ID_PM8917_L10_1,
+ MSM_RPM_STATUS_ID_PM8917_L11_0,
+ MSM_RPM_STATUS_ID_PM8917_L11_1,
+ MSM_RPM_STATUS_ID_PM8917_L12_0,
+ MSM_RPM_STATUS_ID_PM8917_L12_1,
+ MSM_RPM_STATUS_ID_PM8917_L14_0,
+ MSM_RPM_STATUS_ID_PM8917_L14_1,
+ MSM_RPM_STATUS_ID_PM8917_L15_0,
+ MSM_RPM_STATUS_ID_PM8917_L15_1,
+ MSM_RPM_STATUS_ID_PM8917_L16_0,
+ MSM_RPM_STATUS_ID_PM8917_L16_1,
+ MSM_RPM_STATUS_ID_PM8917_L17_0,
+ MSM_RPM_STATUS_ID_PM8917_L17_1,
+ MSM_RPM_STATUS_ID_PM8917_L18_0,
+ MSM_RPM_STATUS_ID_PM8917_L18_1,
+ MSM_RPM_STATUS_ID_PM8917_L21_0,
+ MSM_RPM_STATUS_ID_PM8917_L21_1,
+ MSM_RPM_STATUS_ID_PM8917_L22_0,
+ MSM_RPM_STATUS_ID_PM8917_L22_1,
+ MSM_RPM_STATUS_ID_PM8917_L23_0,
+ MSM_RPM_STATUS_ID_PM8917_L23_1,
+ MSM_RPM_STATUS_ID_PM8917_L24_0,
+ MSM_RPM_STATUS_ID_PM8917_L24_1,
+ MSM_RPM_STATUS_ID_PM8917_L25_0,
+ MSM_RPM_STATUS_ID_PM8917_L25_1,
+ MSM_RPM_STATUS_ID_PM8917_L26_0,
+ MSM_RPM_STATUS_ID_PM8917_L26_1,
+ MSM_RPM_STATUS_ID_PM8917_L27_0,
+ MSM_RPM_STATUS_ID_PM8917_L27_1,
+ MSM_RPM_STATUS_ID_PM8917_L28_0,
+ MSM_RPM_STATUS_ID_PM8917_L28_1,
+ MSM_RPM_STATUS_ID_PM8917_L29_0,
+ MSM_RPM_STATUS_ID_PM8917_L29_1,
+ MSM_RPM_STATUS_ID_PM8917_L30_0,
+ MSM_RPM_STATUS_ID_PM8917_L30_1,
+ MSM_RPM_STATUS_ID_PM8917_L31_0,
+ MSM_RPM_STATUS_ID_PM8917_L31_1,
+ MSM_RPM_STATUS_ID_PM8917_L32_0,
+ MSM_RPM_STATUS_ID_PM8917_L32_1,
+ MSM_RPM_STATUS_ID_PM8917_L33_0,
+ MSM_RPM_STATUS_ID_PM8917_L33_1,
+ MSM_RPM_STATUS_ID_PM8917_L34_0,
+ MSM_RPM_STATUS_ID_PM8917_L34_1,
+ MSM_RPM_STATUS_ID_PM8917_L35_0,
+ MSM_RPM_STATUS_ID_PM8917_L35_1,
+ MSM_RPM_STATUS_ID_PM8917_L36_0,
+ MSM_RPM_STATUS_ID_PM8917_L36_1,
+ MSM_RPM_STATUS_ID_PM8917_CLK1_0,
+ MSM_RPM_STATUS_ID_PM8917_CLK1_1,
+ MSM_RPM_STATUS_ID_PM8917_CLK2_0,
+ MSM_RPM_STATUS_ID_PM8917_CLK2_1,
+ MSM_RPM_STATUS_ID_PM8917_LVS1,
+ MSM_RPM_STATUS_ID_PM8917_LVS3,
+ MSM_RPM_STATUS_ID_PM8917_LVS4,
+ MSM_RPM_STATUS_ID_PM8917_LVS5,
+ MSM_RPM_STATUS_ID_PM8917_LVS6,
+ MSM_RPM_STATUS_ID_PM8917_LVS7,
+ MSM_RPM_STATUS_ID_VOLTAGE_CORNER,
+ MSM_RPM_STATUS_ID_PM8917_VOLTAGE_CORNER
+ = MSM_RPM_STATUS_ID_VOLTAGE_CORNER,
+ MSM_RPM_STATUS_ID_PM8038_VOLTAGE_CORNER
+ = MSM_RPM_STATUS_ID_VOLTAGE_CORNER,
+
+ /* 8064 specific */
+ MSM_RPM_STATUS_ID_PM8821_S1_0,
+ MSM_RPM_STATUS_ID_PM8821_S1_1,
+ MSM_RPM_STATUS_ID_PM8821_S2_0,
+ MSM_RPM_STATUS_ID_PM8821_S2_1,
+ MSM_RPM_STATUS_ID_PM8821_L1_0,
+ MSM_RPM_STATUS_ID_PM8821_L1_1,
+ MSM_RPM_STATUS_ID_VDDMIN_GPIO,
+
+ MSM_RPM_STATUS_ID_LAST,
+};
+
+static inline uint32_t msm_rpm_get_ctx_mask(unsigned int ctx)
+{
+ return 1UL << ctx;
+}
+
+static inline unsigned int msm_rpm_get_sel_mask_reg(unsigned int sel)
+{
+ return sel / 32;
+}
+
+static inline uint32_t msm_rpm_get_sel_mask(unsigned int sel)
+{
+ return 1UL << (sel % 32);
+}
+
+struct msm_rpm_iv_pair {
+ uint32_t id;
+ uint32_t value;
+};
+
+struct msm_rpm_notification {
+ struct list_head list; /* reserved for RPM use */
+ struct semaphore sem;
+ uint32_t sel_masks[SEL_MASK_SIZE]; /* reserved for RPM use */
+};
+
+struct msm_rpm_map_data {
+ uint32_t id;
+ uint32_t sel;
+ uint32_t count;
+};
+
+#define MSM_RPM_MAP(t, i, s, c) \
+ [MSM_RPM_ID_##i] = \
+ {\
+ .id = MSM_RPM_##t##_ID_##i, \
+ .sel = MSM_RPM_##t##_SEL_##s, \
+ .count = c, \
+ }
+
+#define MSM_RPM_MAP_PMIC(_target, _pmic, _id, _select, _count) \
+ [MSM_RPM_ID_##_id] = \
+ {\
+ .id = MSM_RPM_##_target##_ID_PM##_pmic##_##_id, \
+ .sel = MSM_RPM_##_target##_SEL_##_select, \
+ .count = _count, \
+ }
+
+#define MSM_RPM_STATUS_ID_VALID BIT(31)
+
+#define MSM_RPM_STATUS_ID_MAP(t, i) \
+ [MSM_RPM_STATUS_ID_## i] = (MSM_RPM_##t##_STATUS_ID_##i \
+ | MSM_RPM_STATUS_ID_VALID)
+
+#define MSM_RPM_CTRL_MAP(t, i) \
+ [MSM_RPM_CTRL_##i] = MSM_RPM_##t##_CTRL_##i
+
+
+struct msm_rpm_platform_data {
+ void __iomem *reg_base_addrs[MSM_RPM_PAGE_COUNT];
+ unsigned int irq_ack;
+ unsigned int irq_err;
+ unsigned int irq_wakeup;
+ void *ipc_rpm_reg;
+ unsigned int ipc_rpm_val;
+ struct msm_rpm_map_data target_id[MSM_RPM_ID_LAST];
+ unsigned int target_status[MSM_RPM_STATUS_ID_LAST];
+ unsigned int target_ctrl_id[MSM_RPM_CTRL_LAST];
+ unsigned int sel_invalidate, sel_notification, sel_last;
+ unsigned int ver[3];
+};
+
+extern struct msm_rpm_platform_data msm8660_rpm_data;
+extern struct msm_rpm_platform_data msm8960_rpm_data;
+extern struct msm_rpm_platform_data msm9615_rpm_data;
+extern struct msm_rpm_platform_data msm8930_rpm_data;
+extern struct msm_rpm_platform_data msm8930_rpm_data_pm8917;
+extern struct msm_rpm_platform_data apq8064_rpm_data;
+
+
+static inline int msm_rpm_local_request_is_outstanding(void)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_get_status(struct msm_rpm_iv_pair *status, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_set(int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_set_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_set_nosleep(
+ int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_clear(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_clear_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_clear_nosleep(
+ int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_register_notification(struct msm_rpm_notification *n,
+ struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_unregister_notification(
+ struct msm_rpm_notification *n)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_init(struct msm_rpm_platform_data *data)
+{
+ return -ENODEV;
+}
+
+
+#endif /* __ARCH_ARM_MACH_MSM_RPM_H */
diff --git a/arch/arm/mach-msm/include/mach/scm-io.h b/arch/arm/mach-msm/include/mach/scm-io.h
new file mode 100644
index 000000000000..46e3964c16af
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/scm-io.h
@@ -0,0 +1,22 @@
+/* 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 __MACH_SCM_IO_H
+#define __MACH_SCM_IO_H
+
+#include <linux/types.h>
+
+
+#define secure_readl(c) readl(c)
+#define secure_writel(v, c) writel(v, c)
+
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/sirc.h b/arch/arm/mach-msm/include/mach/sirc.h
index ef55868a5b8a..7b19d159c8bd 100644
--- a/arch/arm/mach-msm/include/mach/sirc.h
+++ b/arch/arm/mach-msm/include/mach/sirc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011, 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
@@ -25,13 +25,12 @@ struct sirc_regs_t {
struct sirc_cascade_regs {
void *int_status;
unsigned int cascade_irq;
+ unsigned int cascade_fiq;
};
void msm_init_sirc(void);
-void msm_sirc_enter_sleep(void);
-void msm_sirc_exit_sleep(void);
-#if defined(CONFIG_ARCH_MSM_SCORPION)
+#if defined(CONFIG_ARCH_MSM_SCORPION) && !defined(CONFIG_MSM_SMP)
#include <mach/msm_iomap.h>
@@ -41,6 +40,10 @@ void msm_sirc_exit_sleep(void);
#define FIRST_SIRC_IRQ (NR_MSM_IRQS + NR_GPIO_IRQS)
+#if defined(CONFIG_ARCH_FSM9XXX)
+#include <mach/sirc-fsm9xxx.h>
+#else /* CONFIG_ARCH_FSM9XXX */
+
#define INT_UART1 (FIRST_SIRC_IRQ + 0)
#define INT_UART2 (FIRST_SIRC_IRQ + 1)
#define INT_UART3 (FIRST_SIRC_IRQ + 2)
@@ -78,8 +81,6 @@ void msm_sirc_exit_sleep(void);
#define SIRC_MASK 0x007FFFFF
#endif
-#define LAST_SIRC_IRQ (FIRST_SIRC_IRQ + NR_SIRC_IRQS - 1)
-
#define SPSS_SIRC_INT_SELECT (MSM_SIRC_BASE + 0x00)
#define SPSS_SIRC_INT_ENABLE (MSM_SIRC_BASE + 0x04)
#define SPSS_SIRC_INT_ENABLE_CLEAR (MSM_SIRC_BASE + 0x08)
@@ -93,6 +94,10 @@ void msm_sirc_exit_sleep(void);
#define SPSS_SIRC_INT_CLEAR (MSM_SIRC_BASE + 0x28)
#define SPSS_SIRC_SOFT_INT (MSM_SIRC_BASE + 0x2C)
-#endif
+#endif /* CONFIG_ARCH_FSM9XXX */
+
+#define LAST_SIRC_IRQ (FIRST_SIRC_IRQ + NR_SIRC_IRQS - 1)
+
+#endif /* CONFIG_ARCH_MSM_SCORPION */
#endif
diff --git a/arch/arm/mach-msm/include/mach/subsystem_restart.h b/arch/arm/mach-msm/include/mach/subsystem_restart.h
new file mode 100644
index 000000000000..1049799ea019
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/subsystem_restart.h
@@ -0,0 +1,17 @@
+/* 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.
+ *
+ */
+/*
+ * This header is deprecated and will be deleted soon. Please include
+ * the header below instead.
+ */
+#include <soc/qcom/subsystem_restart.h>
diff --git a/arch/arm/mach-msm/include/mach/uncompress.h b/arch/arm/mach-msm/include/mach/uncompress.h
new file mode 100644
index 000000000000..14eb271e553f
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/uncompress.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2011-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_UNCOMPRESS_H
+#define __ASM_ARCH_MSM_UNCOMPRESS_H
+
+#include <asm/barrier.h>
+#include <asm/processor.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_serial_hsl_regs.h>
+
+#define UART_CSR (*(volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x08))
+#define UART_TF (*(volatile uint32_t *)(MSM_DEBUG_UART_PHYS + 0x0c))
+
+#define UART_DM_SR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + UARTDM_SR_OFFSET)))
+#define UART_DM_CR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + UARTDM_CR_OFFSET)))
+#define UART_DM_ISR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + UARTDM_ISR_OFFSET)))
+#define UART_DM_NCHAR (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + UARTDM_NCF_TX_OFFSET)))
+#define UART_DM_TF (*((volatile uint32_t *)(MSM_DEBUG_UART_PHYS + UARTDM_TF_OFFSET)))
+
+static void putc(int c)
+{
+#if defined(MSM_DEBUG_UART_PHYS)
+#ifdef CONFIG_MSM_HAS_DEBUG_UART_HS
+ /*
+ * Wait for TX_READY to be set; but skip it if we have a
+ * TX underrun.
+ */
+ if (!(UART_DM_SR & 0x08))
+ while (!(UART_DM_ISR & 0x80))
+ cpu_relax();
+
+ UART_DM_CR = 0x300;
+ UART_DM_NCHAR = 0x1;
+ UART_DM_TF = c;
+#else
+ while (!(UART_CSR & 0x04))
+ cpu_relax();
+ UART_TF = c;
+#endif
+#endif
+}
+
+static inline void flush(void)
+{
+}
+
+static inline void arch_decomp_setup(void)
+{
+}
+
+#endif
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index b042dca1f633..db22ed7c5511 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -86,6 +86,22 @@ void __init msm_map_common_io(void)
}
#endif
+#ifdef CONFIG_ARCH_MSM8916
+static struct map_desc msm8916_io_desc[] __initdata = {
+ MSM_CHIP_DEVICE(APCS_GCC, MSM8916),
+#ifdef CONFIG_DEBUG_MSM8916_UART
+ MSM_DEVICE(DEBUG_UART),
+#endif
+};
+
+void __init msm_map_msm8916_io(void)
+{
+ iotable_init(msm8916_io_desc, ARRAY_SIZE(msm8916_io_desc));
+}
+#endif /* CONFIG_ARCH_MSM8916 */
+
+
+
#ifdef CONFIG_ARCH_QSD8X50
static struct map_desc qsd8x50_io_desc[] __initdata = {
MSM_DEVICE(VIC),
diff --git a/arch/arm/mach-msm/keypad-surf-ffa.c b/arch/arm/mach-msm/keypad-surf-ffa.c
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/arch/arm/mach-msm/keypad-surf-ffa.c
diff --git a/arch/arm/mach-msm/krait-scm.c b/arch/arm/mach-msm/krait-scm.c
new file mode 100644
index 000000000000..d1316632cc24
--- /dev/null
+++ b/arch/arm/mach-msm/krait-scm.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2012, 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 <linux/kernel.h>
+#include <linux/workqueue.h>
+#include <linux/percpu.h>
+#include <linux/cpu.h>
+#include <linux/smp.h>
+#include <linux/sysfs.h>
+#include <soc/qcom/scm.h>
+
+
+#define CPU_CONFIG_CMD 5
+#define CPU_CONFIG_QUERY_CMD 6
+
+static int query_cpu_config(void)
+{
+ struct cpu_config_query_req_resp {
+ u32 id;
+ u32 arg0;
+ u32 arg1;
+ u32 arg2;
+ } request;
+ struct cpu_config_query_resp {
+ u32 ret0;
+ u32 ret1;
+ u32 ret2;
+ u32 ret3;
+ } response = {0};
+ int ret;
+
+ request.id = 1;
+ ret = scm_call(SCM_SVC_BOOT, CPU_CONFIG_QUERY_CMD, &request,
+ sizeof(request), &response, sizeof(response));
+ return ret ? : response.ret0;
+}
+
+static void set_cpu_config(int enable)
+{
+ struct cpu_config_req {
+ u32 id;
+ u32 arg0;
+ u32 arg1;
+ u32 arg2;
+ } request;
+
+ request.id = 1;
+ request.arg0 = enable;
+ scm_call(SCM_SVC_BOOT, CPU_CONFIG_CMD, &request, sizeof(request),
+ NULL, 0);
+}
+
+void enable_cpu_config(struct work_struct *work)
+{
+ set_cpu_config(1);
+}
+
+void disable_cpu_config(struct work_struct *work)
+{
+ set_cpu_config(0);
+}
+
+int cpu_config_on_each_cpu(bool enable)
+{
+ work_func_t func = enable ? enable_cpu_config : disable_cpu_config;
+ return schedule_on_each_cpu(func);
+}
+
+static ssize_t show_cpuctl(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", query_cpu_config());
+}
+
+static ssize_t store_cpuctl(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned val;
+ int ret;
+
+ ret = kstrtouint(buf, 10, &val);
+ if (ret < 0)
+ return ret;
+ ret = cpu_config_on_each_cpu(val);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(cpuctl, 0600, show_cpuctl, store_cpuctl);
+
+static int __init init_scm_cpu(void)
+{
+ return device_create_file(cpu_subsys.dev_root, &dev_attr_cpuctl);
+}
+module_init(init_scm_cpu);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
new file mode 100644
index 000000000000..b2693ff51066
--- /dev/null
+++ b/arch/arm/mach-msm/memory.c
@@ -0,0 +1,223 @@
+/* arch/arm/mach-msm/memory.c
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-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 <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <linux/memblock.h>
+#include <asm/memblock.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/mach/map.h>
+#include <asm/cacheflush.h>
+#include <asm/setup.h>
+#include <mach/msm_memtypes.h>
+#include <mach/memory.h>
+#include <linux/hardirq.h>
+#include <mach/msm_iomap.h>
+#include <soc/qcom/socinfo.h>
+#include <linux/sched.h>
+#include <linux/of_fdt.h>
+
+char *memtype_name[] = {
+ "EBI0",
+ "EBI1"
+};
+
+static int __init check_for_compat(unsigned long node)
+{
+ char **start = __compat_exports_start;
+
+ for ( ; start < __compat_exports_end; start++)
+ if (of_flat_dt_is_compatible(node, *start))
+ return 1;
+
+ return 0;
+}
+
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ unsigned int *memory_remove_prop;
+ unsigned long memory_remove_prop_length;
+ unsigned int *memory_reserve_prop;
+ unsigned long memory_reserve_prop_length;
+ unsigned int memory_size;
+ unsigned int memory_start;
+ unsigned int num_holes = 0;
+ int i;
+ int ret;
+
+ memory_remove_prop = of_get_flat_dt_prop(node,
+ "qcom,memblock-remove",
+ &memory_remove_prop_length);
+
+ memory_reserve_prop = of_get_flat_dt_prop(node,
+ "qcom,memblock-reserve",
+ &memory_reserve_prop_length);
+
+ if (memory_remove_prop || memory_reserve_prop) {
+ if (!check_for_compat(node))
+ goto out;
+ } else {
+ goto out;
+ }
+
+ if (memory_remove_prop) {
+ if (!memory_remove_prop_length || (memory_remove_prop_length %
+ (2 * sizeof(unsigned int)) != 0)) {
+ WARN(1, "Memory remove malformed\n");
+ goto mem_reserve;
+ }
+
+ num_holes = memory_remove_prop_length /
+ (2 * sizeof(unsigned int));
+
+ for (i = 0; i < (num_holes * 2); i += 2) {
+ memory_start = be32_to_cpu(memory_remove_prop[i]);
+ memory_size = be32_to_cpu(memory_remove_prop[i+1]);
+
+ ret = memblock_remove(memory_start, memory_size);
+ if (ret)
+ WARN(1, "Failed to remove memory %x-%x\n",
+ memory_start, memory_start+memory_size);
+ else
+ pr_info("Node %s removed memory %x-%x\n", uname,
+ memory_start, memory_start+memory_size);
+ }
+ }
+
+mem_reserve:
+
+ if (memory_reserve_prop) {
+ if (memory_reserve_prop_length != (2*sizeof(unsigned int))) {
+ WARN(1, "Memory reserve malformed\n");
+ goto out;
+ }
+
+ memory_start = be32_to_cpu(memory_reserve_prop[0]);
+ memory_size = be32_to_cpu(memory_reserve_prop[1]);
+
+ ret = memblock_reserve(memory_start, memory_size);
+ if (ret)
+ WARN(1, "Failed to reserve memory %x-%x\n",
+ memory_start, memory_start+memory_size);
+ else
+ pr_info("Node %s memblock_reserve memory %x-%x\n",
+ uname, memory_start, memory_start+memory_size);
+ }
+
+out:
+ return 0;
+}
+
+/* Function to remove any meminfo blocks which are of size zero */
+static void merge_meminfo(void)
+{
+ int i = 0;
+
+ while (i < meminfo.nr_banks) {
+ struct membank *bank = &meminfo.bank[i];
+
+ if (bank->size == 0) {
+ memmove(bank, bank + 1,
+ (meminfo.nr_banks - i) * sizeof(*bank));
+ meminfo.nr_banks--;
+ continue;
+ }
+ i++;
+ }
+}
+
+/*
+ * Function to scan the device tree and adjust the meminfo table to
+ * reflect the memory holes.
+ */
+int __init dt_scan_for_memory_hole(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ unsigned int *memory_remove_prop;
+ unsigned long memory_remove_prop_length;
+ unsigned long hole_start;
+ unsigned long hole_size;
+ unsigned int num_holes = 0;
+ int i = 0;
+
+ memory_remove_prop = of_get_flat_dt_prop(node,
+ "qcom,memblock-remove",
+ &memory_remove_prop_length);
+
+ if (memory_remove_prop) {
+ if (!check_for_compat(node))
+ goto out;
+ } else {
+ goto out;
+ }
+
+ if (memory_remove_prop) {
+ if (!memory_remove_prop_length || (memory_remove_prop_length %
+ (2 * sizeof(unsigned int)) != 0)) {
+ WARN(1, "Memory remove malformed\n");
+ goto out;
+ }
+
+ num_holes = memory_remove_prop_length /
+ (2 * sizeof(unsigned int));
+
+ for (i = 0; i < (num_holes * 2); i += 2) {
+ hole_start = be32_to_cpu(memory_remove_prop[i]);
+ hole_size = be32_to_cpu(memory_remove_prop[i+1]);
+
+ adjust_meminfo(hole_start, hole_size);
+ }
+ }
+
+out:
+ return 0;
+}
+
+/*
+ * Split the memory bank to reflect the hole, if present,
+ * using the start and end of the memory hole.
+ */
+void adjust_meminfo(unsigned long start, unsigned long size)
+{
+ int i;
+
+ for (i = 0; i < meminfo.nr_banks; i++) {
+ struct membank *bank = &meminfo.bank[i];
+
+ if (((start + size) <= (bank->start + bank->size)) &&
+ (start >= bank->start)) {
+ memmove(bank + 1, bank,
+ (meminfo.nr_banks - i) * sizeof(*bank));
+ meminfo.nr_banks++;
+ i++;
+
+ bank->size = start - bank->start;
+ bank[1].start = (start + size);
+ bank[1].size -= (bank->size + size);
+ bank[1].highmem = 0;
+ merge_meminfo();
+ }
+ }
+}
+
+/* Provide a string that anonymous device tree allocations (those not
+ * directly associated with any driver) can use for their "compatible"
+ * field */
+EXPORT_COMPAT("qcom,msm-contig-mem");
diff --git a/arch/arm/mach-msm/msm-buspm-dev.c b/arch/arm/mach-msm/msm-buspm-dev.c
new file mode 100644
index 000000000000..5862e055cdd8
--- /dev/null
+++ b/arch/arm/mach-msm/msm-buspm-dev.c
@@ -0,0 +1,335 @@
+/* Copyright (c) 2011-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.
+ */
+
+/* #define DEBUG */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/dma-mapping.h>
+#include <soc/qcom/rpm-smd.h>
+#include "msm-buspm-dev.h"
+
+#define MSM_BUSPM_DRV_NAME "msm-buspm-dev"
+
+enum msm_buspm_spdm_res {
+ SPDM_RES_ID = 0,
+ SPDM_RES_TYPE = 0x63707362,
+ SPDM_KEY = 0x00006e65,
+ SPDM_SIZE = 4,
+};
+/*
+ * Allocate kernel buffer.
+ * Currently limited to one buffer per file descriptor. If alloc() is
+ * called twice for the same descriptor, the original buffer is freed.
+ * There is also no locking protection so the same descriptor can not be shared.
+ */
+
+static inline void *msm_buspm_dev_get_vaddr(struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ return (dev) ? dev->vaddr : NULL;
+}
+
+static inline unsigned int msm_buspm_dev_get_buflen(struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ return dev ? dev->buflen : 0;
+}
+
+static inline unsigned long msm_buspm_dev_get_paddr(struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ return (dev) ? dev->paddr : 0L;
+}
+
+static void msm_buspm_dev_free(struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ if (dev && dev->vaddr) {
+ pr_debug("freeing memory at 0x%p\n", dev->vaddr);
+ dma_free_coherent(NULL, dev->buflen, dev->vaddr, dev->paddr);
+ dev->paddr = 0L;
+ dev->vaddr = NULL;
+ }
+}
+
+static int msm_buspm_dev_open(struct inode *inode, struct file *filp)
+{
+ struct msm_buspm_map_dev *dev;
+
+ if (capable(CAP_SYS_ADMIN)) {
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev)
+ filp->private_data = dev;
+ else
+ return -ENOMEM;
+ } else {
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+static int
+msm_buspm_dev_alloc(struct file *filp, struct buspm_alloc_params data)
+{
+ dma_addr_t paddr;
+ void *vaddr;
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ /* If buffer already allocated, then free it */
+ if (dev->vaddr)
+ msm_buspm_dev_free(filp);
+
+ /* Allocate uncached memory */
+ vaddr = dma_alloc_coherent(NULL, data.size, &paddr, GFP_KERNEL);
+
+ if (vaddr == NULL) {
+ pr_err("allocation of 0x%x bytes failed", data.size);
+ return -ENOMEM;
+ }
+
+ dev->vaddr = vaddr;
+ dev->paddr = paddr;
+ dev->buflen = data.size;
+ filp->f_pos = 0;
+ pr_debug("virt addr = 0x%p\n", dev->vaddr);
+ pr_debug("phys addr = 0x%lx\n", dev->paddr);
+
+ return 0;
+}
+
+static int msm_bus_rpm_req(u32 rsc_type, u32 key, u32 hwid,
+ int ctx, u32 val)
+{
+ struct msm_rpm_request *rpm_req;
+ int ret, msg_id;
+
+ rpm_req = msm_rpm_create_request(ctx, rsc_type, SPDM_RES_ID, 1);
+ if (rpm_req == NULL) {
+ pr_err("RPM: Couldn't create RPM Request\n");
+ return -ENXIO;
+ }
+
+ ret = msm_rpm_add_kvp_data(rpm_req, key, (const uint8_t *)&val,
+ (int)(sizeof(uint32_t)));
+ if (ret) {
+ pr_err("RPM: Add KVP failed for RPM Req:%u\n",
+ rsc_type);
+ goto err;
+ }
+
+ pr_debug("Added Key: %d, Val: %u, size: %d\n", key,
+ (uint32_t)val, sizeof(uint32_t));
+ msg_id = msm_rpm_send_request(rpm_req);
+ if (!msg_id) {
+ pr_err("RPM: No message ID for req\n");
+ ret = -ENXIO;
+ goto err;
+ }
+
+ ret = msm_rpm_wait_for_ack(msg_id);
+ if (ret) {
+ pr_err("RPM: Ack failed\n");
+ goto err;
+ }
+
+err:
+ msm_rpm_free_request(rpm_req);
+ return ret;
+}
+
+static int msm_buspm_ioc_cmds(uint32_t arg)
+{
+ switch (arg) {
+ case MSM_BUSPM_SPDM_CLK_DIS:
+ case MSM_BUSPM_SPDM_CLK_EN:
+ return msm_bus_rpm_req(SPDM_RES_TYPE, SPDM_KEY, 0,
+ MSM_RPM_CTX_ACTIVE_SET, arg);
+ default:
+ pr_warn("Unsupported ioctl command: %d\n", arg);
+ return -EINVAL;
+ }
+}
+
+
+
+static long
+msm_buspm_dev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ struct buspm_xfer_req xfer;
+ struct buspm_alloc_params alloc_data;
+ unsigned long paddr;
+ int retval = 0;
+ void *buf = msm_buspm_dev_get_vaddr(filp);
+ unsigned int buflen = msm_buspm_dev_get_buflen(filp);
+ unsigned char *dbgbuf = buf;
+
+ if (_IOC_TYPE(cmd) != MSM_BUSPM_IOC_MAGIC) {
+ pr_err("Wrong IOC_MAGIC.Exiting\n");
+ return -ENOTTY;
+ }
+
+ switch (cmd) {
+ case MSM_BUSPM_IOC_FREE:
+ pr_debug("cmd = 0x%x (FREE)\n", cmd);
+ msm_buspm_dev_free(filp);
+ break;
+
+ case MSM_BUSPM_IOC_ALLOC:
+ pr_debug("cmd = 0x%x (ALLOC)\n", cmd);
+ retval = __get_user(alloc_data.size, (size_t __user *)arg);
+
+ if (retval == 0)
+ retval = msm_buspm_dev_alloc(filp, alloc_data);
+ break;
+
+ case MSM_BUSPM_IOC_RD_PHYS_ADDR:
+ pr_debug("Read Physical Address\n");
+ paddr = msm_buspm_dev_get_paddr(filp);
+ if (paddr == 0L) {
+ retval = -EINVAL;
+ } else {
+ pr_debug("phys addr = 0x%lx\n", paddr);
+ retval = __put_user(paddr,
+ (unsigned long __user *)arg);
+ }
+ break;
+
+ case MSM_BUSPM_IOC_RDBUF:
+ pr_debug("Read Buffer: 0x%x%x%x%x\n",
+ dbgbuf[0], dbgbuf[1], dbgbuf[2], dbgbuf[3]);
+
+ if (!buf) {
+ retval = -EINVAL;
+ break;
+ }
+
+ if (copy_from_user(&xfer, (void __user *)arg, sizeof(xfer))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if ((xfer.size <= buflen) &&
+ (copy_to_user((void __user *)xfer.data, buf,
+ xfer.size))) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
+ case MSM_BUSPM_IOC_WRBUF:
+ pr_debug("Write Buffer\n");
+
+ if (!buf) {
+ retval = -EINVAL;
+ break;
+ }
+
+ if (copy_from_user(&xfer, (void __user *)arg, sizeof(xfer))) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if ((buflen <= xfer.size) &&
+ (copy_from_user(buf, (void __user *)xfer.data,
+ xfer.size))) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
+ case MSM_BUSPM_IOC_CMD:
+ pr_debug("IOCTL command: cmd: %d arg: %lu\n", cmd, arg);
+ retval = msm_buspm_ioc_cmds(arg);
+ break;
+
+ default:
+ pr_debug("Unknown command 0x%x\n", cmd);
+ retval = -EINVAL;
+ break;
+ }
+
+ return retval;
+}
+
+static int msm_buspm_dev_release(struct inode *inode, struct file *filp)
+{
+ struct msm_buspm_map_dev *dev = filp->private_data;
+
+ msm_buspm_dev_free(filp);
+ kfree(dev);
+ filp->private_data = NULL;
+
+ return 0;
+}
+
+static int msm_buspm_dev_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+ pr_debug("vma = 0x%p\n", vma);
+
+ /* Mappings are uncached */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot))
+ return -EFAULT;
+
+ return 0;
+}
+
+static const struct file_operations msm_buspm_dev_fops = {
+ .owner = THIS_MODULE,
+ .mmap = msm_buspm_dev_mmap,
+ .open = msm_buspm_dev_open,
+ .unlocked_ioctl = msm_buspm_dev_ioctl,
+ .llseek = noop_llseek,
+ .release = msm_buspm_dev_release,
+};
+
+struct miscdevice msm_buspm_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = MSM_BUSPM_DRV_NAME,
+ .fops = &msm_buspm_dev_fops,
+};
+
+static int __init msm_buspm_dev_init(void)
+{
+ int ret = 0;
+
+ ret = misc_register(&msm_buspm_misc);
+ if (ret < 0)
+ pr_err("%s: Cannot register misc device\n", __func__);
+
+ return ret;
+}
+
+static void __exit msm_buspm_dev_exit(void)
+{
+ misc_deregister(&msm_buspm_misc);
+}
+module_init(msm_buspm_dev_init);
+module_exit(msm_buspm_dev_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:"MSM_BUSPM_DRV_NAME);
diff --git a/arch/arm/mach-msm/msm-buspm-dev.h b/arch/arm/mach-msm/msm-buspm-dev.h
new file mode 100644
index 000000000000..9c428fb37211
--- /dev/null
+++ b/arch/arm/mach-msm/msm-buspm-dev.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2011,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 __MSM_BUSPM_DEV_H__
+#define __MSM_BUSPM_DEV_H__
+
+#include <linux/ioctl.h>
+
+struct msm_buspm_map_dev {
+ void *vaddr;
+ unsigned long paddr;
+ size_t buflen;
+};
+
+/* Read/write data into kernel buffer */
+struct buspm_xfer_req {
+ unsigned int size; /* Size of this request, in bytes */
+ void *data; /* Data buffer to transfer data to/from */
+};
+
+struct buspm_alloc_params {
+ size_t size;
+};
+
+enum msm_buspm_ioc_cmds {
+ MSM_BUSPM_SPDM_CLK_DIS = 0,
+ MSM_BUSPM_SPDM_CLK_EN,
+};
+
+#define MSM_BUSPM_IOC_MAGIC 'p'
+
+#define MSM_BUSPM_IOC_FREE \
+ _IOW(MSM_BUSPM_IOC_MAGIC, 0, void *)
+
+#define MSM_BUSPM_IOC_ALLOC \
+ _IOW(MSM_BUSPM_IOC_MAGIC, 1, size_t)
+
+#define MSM_BUSPM_IOC_RDBUF \
+ _IOW(MSM_BUSPM_IOC_MAGIC, 2, struct buspm_xfer_req)
+
+#define MSM_BUSPM_IOC_WRBUF \
+ _IOW(MSM_BUSPM_IOC_MAGIC, 3, struct buspm_xfer_req)
+
+#define MSM_BUSPM_IOC_RD_PHYS_ADDR \
+ _IOR(MSM_BUSPM_IOC_MAGIC, 4, unsigned long)
+
+#define MSM_BUSPM_IOC_CMD \
+ _IOR(MSM_BUSPM_IOC_MAGIC, 5, uint32_t)
+#endif
diff --git a/arch/arm/mach-msm/msm-krait-l2-accessors.c b/arch/arm/mach-msm/msm-krait-l2-accessors.c
new file mode 100644
index 000000000000..20a6cde2d320
--- /dev/null
+++ b/arch/arm/mach-msm/msm-krait-l2-accessors.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011-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 <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/msm_rtb.h>
+#include <asm/cputype.h>
+
+DEFINE_RAW_SPINLOCK(l2_access_lock);
+
+void set_l2_indirect_reg(u32 reg_addr, u32 val)
+{
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&l2_access_lock, flags);
+ mb();
+ uncached_logk(LOGK_L2CPWRITE, (void *)reg_addr);
+ asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
+ "isb\n\t"
+ "mcr p15, 3, %[l2cpdr], c15, c0, 7\n\t"
+ "isb\n\t"
+ :
+ : [l2cpselr]"r" (reg_addr), [l2cpdr]"r" (val)
+ );
+ raw_spin_unlock_irqrestore(&l2_access_lock, flags);
+}
+EXPORT_SYMBOL(set_l2_indirect_reg);
+
+u32 get_l2_indirect_reg(u32 reg_addr)
+{
+ u32 val;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&l2_access_lock, flags);
+ uncached_logk(LOGK_L2CPREAD, (void *)reg_addr);
+ asm volatile ("mcr p15, 3, %[l2cpselr], c15, c0, 6\n\t"
+ "isb\n\t"
+ "mrc p15, 3, %[l2cpdr], c15, c0, 7\n\t"
+ : [l2cpdr]"=r" (val)
+ : [l2cpselr]"r" (reg_addr)
+ );
+ raw_spin_unlock_irqrestore(&l2_access_lock, flags);
+
+ return val;
+}
+EXPORT_SYMBOL(get_l2_indirect_reg);
diff --git a/arch/arm/mach-msm/msm_cache_dump.c b/arch/arm/mach-msm/msm_cache_dump.c
new file mode 100644
index 000000000000..8d5dcc5001b7
--- /dev/null
+++ b/arch/arm/mach-msm/msm_cache_dump.c
@@ -0,0 +1,274 @@
+/* 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/notifier.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <soc/qcom/scm.h>
+#include <asm/cacheflush.h>
+#include <mach/msm_cache_dump.h>
+#include <mach/msm_iomap.h>
+#include <soc/qcom/memory_dump.h>
+
+#define L2_DUMP_OFFSET 0x14
+
+static dma_addr_t msm_cache_dump_addr;
+static void *msm_cache_dump_vaddr;
+
+/*
+ * These should not actually be dereferenced. There's no
+ * need for a virtual mapping, but the physical address is
+ * necessary.
+ */
+static struct l1_cache_dump *l1_dump;
+static struct l2_cache_dump *l2_dump;
+
+static int msm_cache_dump_panic(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+#ifdef CONFIG_MSM_CACHE_DUMP_ON_PANIC
+ scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 2);
+ scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 1);
+#endif
+ return 0;
+}
+
+static struct notifier_block msm_cache_dump_blk = {
+ .notifier_call = msm_cache_dump_panic,
+ /*
+ * higher priority to ensure this runs before another panic handler
+ * flushes the caches.
+ */
+ .priority = 1,
+};
+
+static int msm_cache_dump_probe(struct platform_device *pdev)
+{
+ struct msm_cache_dump_platform_data *d = pdev->dev.platform_data;
+ struct msm_client_dump l1_dump_entry, l2_dump_entry;
+ struct msm_dump_entry dump_entry;
+ struct msm_dump_data *l1_inst_data, *l1_data_data, *l2_data;
+ int ret, cpu;
+ struct {
+ unsigned long buf;
+ unsigned long size;
+ } l1_cache_data;
+ u32 l1_size, l2_size;
+ unsigned long total_size;
+ u32 l1_inst_size, l1_data_size;
+ phys_addr_t l1_inst_start, l1_data_start, l2_start;
+
+ if (pdev->dev.of_node) {
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "qcom,l1-dump-size", &l1_size);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "qcom,l2-dump-size", &l2_size);
+ if (ret)
+ return ret;
+ } else {
+ l1_size = d->l1_size;
+ l2_size = d->l2_size;
+ };
+
+ total_size = l1_size + l2_size;
+ msm_cache_dump_vaddr = (void *) dma_alloc_coherent(&pdev->dev,
+ total_size, &msm_cache_dump_addr,
+ GFP_KERNEL);
+
+ if (!msm_cache_dump_vaddr) {
+ pr_err("%s: Could not get memory for cache dumping\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(msm_cache_dump_vaddr, 0xFF, total_size);
+ /* Clean caches before sending buffer to TZ */
+ dmac_clean_range(msm_cache_dump_vaddr,
+ msm_cache_dump_vaddr + total_size);
+
+ l1_cache_data.buf = msm_cache_dump_addr;
+ l1_cache_data.size = l1_size;
+
+ ret = scm_call(L1C_SERVICE_ID, L1C_BUFFER_SET_COMMAND_ID,
+ &l1_cache_data, sizeof(l1_cache_data), NULL, 0);
+
+ if (ret)
+ pr_err("%s: could not register L1 buffer ret = %d.\n",
+ __func__, ret);
+
+ l1_dump = (struct l1_cache_dump *)(uint32_t)msm_cache_dump_addr;
+ l2_dump = (struct l2_cache_dump *)(uint32_t)(msm_cache_dump_addr
+ + l1_size);
+
+#if defined(CONFIG_MSM_CACHE_DUMP_ON_PANIC)
+ l1_cache_data.buf = msm_cache_dump_addr + l1_size;
+ l1_cache_data.size = l2_size;
+
+ ret = scm_call(L1C_SERVICE_ID, L2C_BUFFER_SET_COMMAND_ID,
+ &l1_cache_data, sizeof(l1_cache_data), NULL, 0);
+
+ if (ret)
+ pr_err("%s: could not register L2 buffer ret = %d.\n",
+ __func__, ret);
+#endif
+
+ if (MSM_DUMP_MAJOR(msm_dump_table_version()) == 1) {
+ l1_dump_entry.id = MSM_L1_CACHE;
+ l1_dump_entry.start_addr = msm_cache_dump_addr;
+ l1_dump_entry.end_addr = l1_dump_entry.start_addr + l1_size - 1;
+
+ l2_dump_entry.id = MSM_L2_CACHE;
+ l2_dump_entry.start_addr = msm_cache_dump_addr + l1_size;
+ l2_dump_entry.end_addr = l2_dump_entry.start_addr + l2_size - 1;
+
+ ret = msm_dump_tbl_register(&l1_dump_entry);
+ if (ret)
+ pr_err("Could not register L1 dump area: %d\n", ret);
+
+ ret = msm_dump_tbl_register(&l2_dump_entry);
+ if (ret)
+ pr_err("Could not register L2 dump area: %d\n", ret);
+ } else {
+ l1_inst_data = kzalloc(sizeof(struct msm_dump_data) *
+ num_present_cpus(), GFP_KERNEL);
+ if (!l1_inst_data) {
+ pr_err("l1 inst data structure allocation failed\n");
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ l1_data_data = kzalloc(sizeof(struct msm_dump_data) *
+ num_present_cpus(), GFP_KERNEL);
+ if (!l1_data_data) {
+ pr_err("l1 data data structure allocation failed\n");
+ ret = -ENOMEM;
+ goto err1;
+ }
+
+ l1_inst_start = msm_cache_dump_addr;
+ l1_data_start = msm_cache_dump_addr + (l1_size / 2);
+ l1_inst_size = l1_size / (num_present_cpus() * 2);
+ l1_data_size = l1_inst_size;
+
+ for_each_cpu(cpu, cpu_present_mask) {
+ l1_inst_data[cpu].addr = l1_inst_start +
+ cpu * l1_inst_size;
+ l1_inst_data[cpu].len = l1_inst_size;
+ dump_entry.id = MSM_DUMP_DATA_L1_INST_CACHE + cpu;
+ dump_entry.addr = virt_to_phys(&l1_inst_data[cpu]);
+ ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS,
+ &dump_entry);
+ /*
+ * Don't free the buffers in case of error since
+ * registration may have succeeded for some cpus.
+ */
+ if (ret)
+ pr_err("cpu %d l1 inst dump setup failed\n",
+ cpu);
+
+ l1_data_data[cpu].addr = l1_data_start +
+ cpu * l1_data_size;
+ l1_data_data[cpu].len = l1_data_size;
+ dump_entry.id = MSM_DUMP_DATA_L1_DATA_CACHE + cpu;
+ dump_entry.addr = virt_to_phys(&l1_data_data[cpu]);
+ ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS,
+ &dump_entry);
+ /*
+ * Don't free the buffers in case of error since
+ * registration may have succeeded for some cpus.
+ */
+ if (ret)
+ pr_err("cpu %d l1 data dump setup failed\n",
+ cpu);
+ }
+
+ l2_data = kzalloc(sizeof(struct msm_dump_data) *
+ num_present_cpus(), GFP_KERNEL);
+ if (!l2_data) {
+ pr_err("l2 data structure allocation failed\n");
+ ret = -ENOMEM;
+ goto err2;
+ }
+
+ l2_start = msm_cache_dump_addr + l1_size;
+
+ l2_data->addr = l2_start;
+ l2_data->len = l2_size;
+ dump_entry.id = MSM_DUMP_DATA_L2_CACHE;
+ dump_entry.addr = virt_to_phys(l2_data);
+ ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS,
+ &dump_entry);
+ if (ret)
+ pr_err("l2 dump setup failed\n");
+ }
+
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &msm_cache_dump_blk);
+ return 0;
+err2:
+ kfree(l1_data_data);
+err1:
+ kfree(l1_inst_data);
+err0:
+ dma_free_coherent(&pdev->dev, total_size, msm_cache_dump_vaddr,
+ msm_cache_dump_addr);
+ return ret;
+}
+
+static int msm_cache_dump_remove(struct platform_device *pdev)
+{
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &msm_cache_dump_blk);
+ return 0;
+}
+
+static struct of_device_id cache_dump_match_table[] = {
+ { .compatible = "qcom,cache_dump", },
+ {}
+};
+EXPORT_COMPAT("qcom,cache_dump");
+
+static struct platform_driver msm_cache_dump_driver = {
+ .remove = msm_cache_dump_remove,
+ .driver = {
+ .name = "msm_cache_dump",
+ .owner = THIS_MODULE,
+ .of_match_table = cache_dump_match_table,
+ },
+};
+
+static int __init msm_cache_dump_init(void)
+{
+ return platform_driver_probe(&msm_cache_dump_driver,
+ msm_cache_dump_probe);
+}
+
+static void __exit msm_cache_dump_exit(void)
+{
+ platform_driver_unregister(&msm_cache_dump_driver);
+}
+late_initcall(msm_cache_dump_init);
+module_exit(msm_cache_dump_exit)
diff --git a/arch/arm/mach-msm/msm_mem_hole.c b/arch/arm/mach-msm/msm_mem_hole.c
new file mode 100644
index 000000000000..736219b63ab1
--- /dev/null
+++ b/arch/arm/mach-msm/msm_mem_hole.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2012, 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.
+ */
+
+/**
+ * This module exists for the express purpose of removing memory
+ * via the msm memory-remove mechanism (see
+ * Documentation/devicetree/bindings/arm/msm/memory-reserve.txt). Compiling
+ * this module into a kernel is essentially the means by which any
+ * nodes in the device tree with compatible =
+ * "qcom,msm-mem-hole" will be "activated", thus providing a
+ * convenient mechanism for enabling/disabling memory removal
+ * (qcom,memory-*).
+ */
+
+#include <linux/module.h>
+
+#define MSM_MEM_HOLE_COMPAT_STR "qcom,msm-mem-hole"
+
+EXPORT_COMPAT(MSM_MEM_HOLE_COMPAT_STR);
diff --git a/arch/arm/mach-msm/msm_mpmctr.c b/arch/arm/mach-msm/msm_mpmctr.c
new file mode 100644
index 000000000000..cc0c1c36d7c8
--- /dev/null
+++ b/arch/arm/mach-msm/msm_mpmctr.c
@@ -0,0 +1,99 @@
+/* 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/smp.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/msm_mpmctr.h>
+
+static void __iomem *mpm_timer_base;
+
+uint32_t msm_mpm_get_count(void)
+{
+ uint32_t count;
+ if (!mpm_timer_base)
+ return 0;
+
+ count = __raw_readl_no_log(mpm_timer_base);
+ pr_debug("mpm sclk sync:(%u)", count);
+ return count;
+}
+EXPORT_SYMBOL(msm_mpm_get_count);
+
+static inline void msm_mpmctr_show_count(void)
+{
+ unsigned long long t;
+ unsigned long nsec_rem;
+
+ t = sched_clock();
+
+ nsec_rem = do_div(t, 1000000000)/1000;
+
+ printk(KERN_INFO "mpm_counter: [%5lu.%06lu]:(%u)\n",
+ (unsigned long)t, nsec_rem,
+ msm_mpm_get_count());
+
+}
+
+static struct of_device_id msm_mpmctr_of_match[] = {
+ {.compatible = "qcom,mpm2-sleep-counter"},
+ {}
+};
+
+static struct platform_driver msm_mpmctr_driver = {
+ .driver = {
+ .name = "msm_mpctr",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_mpmctr_of_match,
+ },
+};
+
+static int __init mpmctr_set_register(struct device_node *np)
+{
+ if (of_get_address(np, 0, NULL, NULL)) {
+ mpm_timer_base = of_iomap(np, 0);
+ if (!mpm_timer_base) {
+ pr_err("%s: cannot map timer base\n", __func__);
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+static int __init msm_mpmctr_probe(struct platform_device *pdev)
+{
+ if (!pdev->dev.of_node)
+ return -ENODEV;
+
+ if (mpmctr_set_register(pdev->dev.of_node))
+ return -ENODEV;
+
+ msm_mpmctr_show_count();
+
+ return 0;
+}
+
+static int __init mpmctr_init(void)
+{
+ return platform_driver_probe(&msm_mpmctr_driver, msm_mpmctr_probe);
+}
+
+module_init(mpmctr_init)
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
new file mode 100644
index 000000000000..6818680d6814
--- /dev/null
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -0,0 +1,83 @@
+/* Copyright (c) 2011-2012, 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 __ARCH_ARM_MACH_MSM_MSM_WATCHDOG_H
+#define __ARCH_ARM_MACH_MSM_MSM_WATCHDOG_H
+
+/* The base is just address of the WDT_RST register */
+#define WDT0_OFFSET 0x38
+#define WDT1_OFFSET 0x60
+
+struct msm_watchdog_pdata {
+ /* pet interval period in ms */
+ unsigned int pet_time;
+ /* bark timeout in ms */
+ unsigned int bark_time;
+ bool has_secure;
+ bool needs_expired_enable;
+ bool has_vic;
+ /* You have to be running in secure mode to use FIQ */
+ bool use_kernel_fiq;
+ void __iomem *base;
+};
+
+struct msm_watchdog_dump {
+ uint32_t magic;
+ uint32_t curr_cpsr;
+ uint32_t usr_r0;
+ uint32_t usr_r1;
+ uint32_t usr_r2;
+ uint32_t usr_r3;
+ uint32_t usr_r4;
+ uint32_t usr_r5;
+ uint32_t usr_r6;
+ uint32_t usr_r7;
+ uint32_t usr_r8;
+ uint32_t usr_r9;
+ uint32_t usr_r10;
+ uint32_t usr_r11;
+ uint32_t usr_r12;
+ uint32_t usr_r13;
+ uint32_t usr_r14;
+ uint32_t irq_spsr;
+ uint32_t irq_r13;
+ uint32_t irq_r14;
+ uint32_t svc_spsr;
+ uint32_t svc_r13;
+ uint32_t svc_r14;
+ uint32_t abt_spsr;
+ uint32_t abt_r13;
+ uint32_t abt_r14;
+ uint32_t und_spsr;
+ uint32_t und_r13;
+ uint32_t und_r14;
+ uint32_t fiq_spsr;
+ uint32_t fiq_r8;
+ uint32_t fiq_r9;
+ uint32_t fiq_r10;
+ uint32_t fiq_r11;
+ uint32_t fiq_r12;
+ uint32_t fiq_r13;
+ uint32_t fiq_r14;
+};
+
+void msm_wdog_fiq_setup(void *stack);
+extern unsigned int msm_wdog_fiq_length, msm_wdog_fiq_start;
+extern unsigned int msm7k_fiq_start, msm7k_fiq_length;
+
+#ifdef CONFIG_MSM_WATCHDOG
+void pet_watchdog(void);
+#else
+static inline void pet_watchdog(void) { }
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
new file mode 100644
index 000000000000..8b07d6f6d24c
--- /dev/null
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -0,0 +1,83 @@
+/* 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 <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+
+/*
+ * Subsequent patches should add an entry to end of this string.
+ * Format is incrementing sequence number followed by text of
+ * patch commit title with newline.
+ * Note trailing ';' is on its own line to simplify addition of
+ * future strings.
+ */
+static char *descriptions =
+ " 0 msm: perf: add debug patch logging framework\n"
+ " 1 Perf: port perf-events to 3.10 kernel\n"
+ " 2 Perf: keep events across hotplug\n"
+ " 3 Perf: bring CPU online if needed when disabling irq\n"
+ " 4 Perf: Support sw events across hotplug\n"
+ " 5 msm: perf: initialise krait perf L2 counter enables\n"
+ " 6 msm: perf: clean up duplicate constraint events\n"
+ " 7 Perf: Add L1 counters to tracepoints\n"
+ " 8 Perf: Make per-process counters configurable\n"
+ " 9 msm: perf: Add L2 support for tracecounters\n"
+ "10 ARM: dts: msm: add perf-events support for apq8084\n"
+ "11 ARM: dts: msm: add perf-events support for msmsamarium\n"
+ "12 Perf: Make per-process counters cumulative\n"
+ "13 Perf: Fix PID for tracepoints\n"
+ "14 Perf: preserve registers across hotplug\n"
+ "15 msm: perf: Fix cpu id logic in tracectr notifier\n"
+ "16 msm: perf: tracectr: Initialize cnts after hotplug\n"
+ "17 Perf: Reset pmu after hotplug\n"
+ "18 ARM: dts: msm: add perf-events support for msm8916\n"
+ "19 Perf: Enable pmuv3 on 32 bit kernel\n"
+;
+
+static ssize_t desc_read(struct file *fp, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ return simple_read_from_buffer(buf, count, pos, descriptions,
+ strlen(descriptions));
+}
+
+static const struct file_operations perf_debug_desc_fops = {
+ .read = desc_read,
+};
+
+static int msm_perf_debugfs_init(void)
+{
+ int ret = 0;
+ struct dentry *dir;
+ struct dentry *file;
+
+ dir = debugfs_create_dir("msm-perf-patches", NULL);
+ if (IS_ERR_OR_NULL(dir)) {
+ pr_err("failed to create msm-perf-patches dir in debugfs\n");
+ ret = PTR_ERR(dir);
+ goto init_exit;
+ }
+
+ file = debugfs_create_file("descriptions", 0444, dir, NULL,
+ &perf_debug_desc_fops);
+ if (IS_ERR_OR_NULL(file)) {
+ debugfs_remove(dir);
+ pr_err("failed to create descriptions file for msm-perf-patches\n");
+ ret = PTR_ERR(file);
+ goto init_exit;
+ }
+
+init_exit:
+ return ret;
+}
+late_initcall(msm_perf_debugfs_init);
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
new file mode 100644
index 000000000000..47816c9c04a8
--- /dev/null
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright (c) 2011, 2012 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 <linux/irq.h>
+#include <asm/pmu.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+#include <mach/msm-krait-l2-accessors.h>
+
+/*
+ * The L2 PMU is shared between all CPU's, so protect
+ * its bitmap access.
+ */
+struct pmu_constraints {
+ u64 pmu_bitmap;
+ u8 codes[64];
+ raw_spinlock_t lock;
+} l2_pmu_constraints = {
+ .pmu_bitmap = 0,
+ .codes = {-1},
+ .lock = __RAW_SPIN_LOCK_UNLOCKED(l2_pmu_constraints.lock),
+};
+
+/* NRCCG format for perf RAW codes. */
+PMU_FORMAT_ATTR(l2_prefix, "config:16-19");
+PMU_FORMAT_ATTR(l2_reg, "config:12-15");
+PMU_FORMAT_ATTR(l2_code, "config:4-11");
+PMU_FORMAT_ATTR(l2_grp, "config:0-3");
+
+static struct attribute *msm_l2_ev_formats[] = {
+ &format_attr_l2_prefix.attr,
+ &format_attr_l2_reg.attr,
+ &format_attr_l2_code.attr,
+ &format_attr_l2_grp.attr,
+ NULL,
+};
+
+/*
+ * Format group is essential to access PMU's from userspace
+ * via their .name field.
+ */
+static struct attribute_group msm_l2_pmu_format_group = {
+ .name = "format",
+ .attrs = msm_l2_ev_formats,
+};
+
+static const struct attribute_group *msm_l2_pmu_attr_grps[] = {
+ &msm_l2_pmu_format_group,
+ NULL,
+};
+
+static u32 l2_orig_filter_prefix = 0x000f0030;
+
+/* L2 slave port traffic filtering */
+static u32 l2_slv_filter_prefix = 0x000f0010;
+
+static int total_l2_ctrs;
+static int l2_cycle_ctr_idx;
+
+static u32 pmu_type;
+static u32 from_idle;
+
+static struct arm_pmu krait_l2_pmu;
+static struct arm_pmu *krait_l2_pmu_addr = &krait_l2_pmu;
+
+static struct perf_event *l2_events[MAX_KRAIT_L2_CTRS];
+static unsigned long l2_used_mask[BITS_TO_LONGS(MAX_KRAIT_L2_CTRS)];
+
+static struct pmu_hw_events krait_l2_pmu_hw_events = {
+ .events = l2_events,
+ .used_mask = l2_used_mask,
+ .from_idle = &from_idle,
+ .pmu_lock = __RAW_SPIN_LOCK_UNLOCKED(krait_l2_pmu_hw_events.pmu_lock),
+};
+
+struct event_desc {
+ int event_groupsel;
+ int event_reg;
+ int event_group_code;
+};
+
+static struct pmu_hw_events *krait_l2_get_hw_events(void)
+{
+ return &krait_l2_pmu_hw_events;
+}
+
+void get_event_desc(u64 config, struct event_desc *evdesc)
+{
+ /* L2PMEVCNTRX */
+ evdesc->event_reg = (config & EVENT_REG_MASK) >> EVENT_REG_SHIFT;
+ /* Group code (row ) */
+ evdesc->event_group_code =
+ (config & EVENT_GROUPCODE_MASK) >> EVENT_GROUPCODE_SHIFT;
+ /* Group sel (col) */
+ evdesc->event_groupsel = (config & EVENT_GROUPSEL_MASK);
+
+ pr_debug("%s: reg: %x, group_code: %x, groupsel: %x\n", __func__,
+ evdesc->event_reg, evdesc->event_group_code,
+ evdesc->event_groupsel);
+}
+
+static void set_evcntcr(int ctr)
+{
+ u32 evtcr_reg = (ctr * 16) + IA_L2PMXEVCNTCR_BASE;
+
+ set_l2_indirect_reg(evtcr_reg, 0x0);
+}
+
+static void set_evtyper(int event_groupsel, int event_reg, int ctr)
+{
+ u32 evtype_reg = (ctr * 16) + IA_L2PMXEVTYPER_BASE;
+ u32 evtype_val = event_groupsel + (4 * event_reg);
+
+ set_l2_indirect_reg(evtype_reg, evtype_val);
+}
+
+static void set_evres(int event_groupsel, int event_reg, int event_group_code)
+{
+ u32 group_reg = event_reg + IA_L2PMRESX_BASE;
+ u32 group_val =
+ RESRX_VALUE_EN | (event_group_code << (8 * event_groupsel));
+ u32 resr_val;
+ u32 group_byte = 0xff;
+ u32 group_mask = ~(group_byte << (8 * event_groupsel));
+
+ resr_val = get_l2_indirect_reg(group_reg);
+ resr_val &= group_mask;
+ resr_val |= group_val;
+
+ set_l2_indirect_reg(group_reg, resr_val);
+}
+
+static void set_evfilter_task_mode(int ctr, unsigned int is_slv)
+{
+ u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
+ u32 filter_val = l2_orig_filter_prefix | 1 << smp_processor_id();
+
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
+
+ set_l2_indirect_reg(filter_reg, filter_val);
+}
+
+static void set_evfilter_sys_mode(int ctr, unsigned int is_slv, int cpu,
+ unsigned int is_tracectr)
+{
+ u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
+ u32 filter_val = l2_orig_filter_prefix | 0xf;
+
+ if (is_slv == 1)
+ filter_val = l2_slv_filter_prefix;
+ if (is_tracectr == 1)
+ filter_val = l2_orig_filter_prefix | 1 << cpu;
+
+ set_l2_indirect_reg(filter_reg, filter_val);
+}
+
+static void enable_intenset(u32 idx)
+{
+ if (idx == l2_cycle_ctr_idx)
+ set_l2_indirect_reg(L2PMINTENSET, 1 << L2CYCLE_CTR_BIT);
+ else
+ set_l2_indirect_reg(L2PMINTENSET, 1 << idx);
+}
+
+static void disable_intenclr(u32 idx)
+{
+ if (idx == l2_cycle_ctr_idx)
+ set_l2_indirect_reg(L2PMINTENCLR, 1 << L2CYCLE_CTR_BIT);
+ else
+ set_l2_indirect_reg(L2PMINTENCLR, 1 << idx);
+}
+
+static void enable_counter(u32 idx)
+{
+ if (idx == l2_cycle_ctr_idx)
+ set_l2_indirect_reg(L2PMCNTENSET, 1 << L2CYCLE_CTR_BIT);
+ else
+ set_l2_indirect_reg(L2PMCNTENSET, 1 << idx);
+}
+
+static void disable_counter(u32 idx)
+{
+ if (idx == l2_cycle_ctr_idx)
+ set_l2_indirect_reg(L2PMCNTENCLR, 1 << L2CYCLE_CTR_BIT);
+ else
+ set_l2_indirect_reg(L2PMCNTENCLR, 1 << idx);
+}
+
+static u32 krait_l2_read_counter(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+ u32 val;
+ u32 counter_reg = (idx * 16) + IA_L2PMXEVCNTR_BASE;
+
+ if (idx == l2_cycle_ctr_idx)
+ val = get_l2_indirect_reg(L2PMCCNTR);
+ else
+ val = get_l2_indirect_reg(counter_reg);
+
+ return val;
+}
+
+static void krait_l2_write_counter(struct perf_event *event, u32 val)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+ u32 counter_reg = (idx * 16) + IA_L2PMXEVCNTR_BASE;
+
+ if (idx == l2_cycle_ctr_idx)
+ set_l2_indirect_reg(L2PMCCNTR, val);
+ else
+ set_l2_indirect_reg(counter_reg, val);
+}
+
+static void krait_l2_stop_counter(struct hw_perf_event *hwc, int idx)
+{
+ disable_intenclr(idx);
+ disable_counter(idx);
+
+ pr_debug("%s: event: %ld ctr: %d stopped\n", __func__,
+ hwc->config_base, idx);
+}
+
+static void krait_l2_enable(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+ struct event_desc evdesc;
+ unsigned long iflags;
+ unsigned int is_slv = 0;
+ unsigned int is_tracectr = 0;
+ unsigned int evt_prefix;
+
+ raw_spin_lock_irqsave(&krait_l2_pmu_hw_events.pmu_lock, iflags);
+
+ if (hwc->config_base == L2CYCLE_CTR_RAW_CODE)
+ goto out;
+
+ /* Check if user requested any special origin filtering. */
+ evt_prefix = (hwc->config_base &
+ EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
+
+ if (evt_prefix == L2_SLAVE_EV_PREFIX)
+ is_slv = 1;
+ else if (evt_prefix == L2_TRACECTR_PREFIX)
+ is_tracectr = 1;
+
+ set_evcntcr(idx);
+
+ memset(&evdesc, 0, sizeof(evdesc));
+
+ get_event_desc(hwc->config_base, &evdesc);
+
+ set_evtyper(evdesc.event_groupsel, evdesc.event_reg, idx);
+
+ set_evres(evdesc.event_groupsel, evdesc.event_reg,
+ evdesc.event_group_code);
+
+ if (event->cpu < 0)
+ set_evfilter_task_mode(idx, is_slv);
+ else
+ set_evfilter_sys_mode(idx, is_slv, event->cpu, is_tracectr);
+
+out:
+ enable_intenset(idx);
+ enable_counter(idx);
+
+ raw_spin_unlock_irqrestore(&krait_l2_pmu_hw_events.pmu_lock, iflags);
+
+ pr_debug("%s: ctr: %d group: %ld group_code: %lld started from cpu:%d\n",
+ __func__, idx, hwc->config_base, hwc->config, smp_processor_id());
+}
+
+static void krait_l2_disable(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+ unsigned long iflags;
+
+ raw_spin_lock_irqsave(&krait_l2_pmu_hw_events.pmu_lock, iflags);
+
+ krait_l2_stop_counter(hwc, idx);
+
+ raw_spin_unlock_irqrestore(&krait_l2_pmu_hw_events.pmu_lock, iflags);
+
+ pr_debug("%s: event: %ld deleted\n", __func__, hwc->config_base);
+
+}
+
+static int krait_l2_get_event_idx(struct pmu_hw_events *cpuc,
+ struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int ctr = 0;
+
+ if (hwc->config_base == L2CYCLE_CTR_RAW_CODE) {
+ if (test_and_set_bit(l2_cycle_ctr_idx, cpuc->used_mask))
+ return -EAGAIN;
+
+ return l2_cycle_ctr_idx;
+ }
+
+ for (ctr = 0; ctr < total_l2_ctrs - 1; ctr++) {
+ if (!test_and_set_bit(ctr, cpuc->used_mask))
+ return ctr;
+ }
+
+ return -EAGAIN;
+}
+
+static void krait_l2_start(struct arm_pmu *l2_pmu)
+{
+ isb();
+ set_l2_indirect_reg(L2PMCR, L2PMCR_GLOBAL_ENABLE);
+}
+
+static void krait_l2_stop(struct arm_pmu *l2_pmu)
+{
+ set_l2_indirect_reg(L2PMCR, L2PMCR_GLOBAL_DISABLE);
+ isb();
+}
+
+u32 get_reset_pmovsr(void)
+{
+ int val;
+
+ val = get_l2_indirect_reg(L2PMOVSR);
+ /* reset it */
+ val &= 0xffffffff;
+ set_l2_indirect_reg(L2PMOVSR, val);
+
+ return val;
+}
+
+static irqreturn_t krait_l2_handle_irq(int irq_num, void *dev)
+{
+ unsigned long pmovsr;
+ struct perf_sample_data data;
+ struct pt_regs *regs;
+ struct perf_event *event;
+ struct hw_perf_event *hwc;
+ int bitp;
+ int idx = 0;
+
+ pmovsr = get_reset_pmovsr();
+
+ if (!(pmovsr & 0xffffffff))
+ return IRQ_NONE;
+
+ regs = get_irq_regs();
+
+ while (pmovsr) {
+ bitp = __ffs(pmovsr);
+
+ if (bitp == L2CYCLE_CTR_BIT)
+ idx = l2_cycle_ctr_idx;
+ else
+ idx = bitp;
+
+ event = krait_l2_pmu_hw_events.events[idx];
+
+ if (!event)
+ goto next;
+
+ if (!test_bit(idx, krait_l2_pmu_hw_events.used_mask))
+ goto next;
+
+ hwc = &event->hw;
+ armpmu_event_update(event);
+ perf_sample_data_init(&data, 0, hwc->last_period);
+
+ if (!armpmu_event_set_period(event))
+ goto next;
+
+ if (perf_event_overflow(event, &data, regs))
+ disable_counter(hwc->idx);
+next:
+ pmovsr &= (pmovsr - 1);
+ }
+
+ irq_work_run();
+
+ return IRQ_HANDLED;
+}
+
+static int krait_l2_map_event(struct perf_event *event)
+{
+ if (pmu_type > 0 && pmu_type == event->attr.type)
+ return event->attr.config & L2_EVT_MASK;
+ else
+ return -ENOENT;
+}
+
+static int
+krait_l2_pmu_generic_request_irq(int irq, irq_handler_t *handle_irq, void *dev_id)
+{
+ return request_irq(irq, *handle_irq,
+ IRQF_DISABLED | IRQF_NOBALANCING,
+ "krait-l2-armpmu", &krait_l2_pmu_addr);
+}
+
+static void
+krait_l2_pmu_generic_free_irq(int irq, void *dev_id)
+{
+ if (irq >= 0)
+ free_irq(irq, &krait_l2_pmu_addr);
+}
+
+static int msm_l2_test_set_ev_constraint(struct perf_event *event)
+{
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
+ u8 evt_prefix = (evt_type & EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
+ u8 reg = (evt_type & 0x0F000) >> 12;
+ u8 group = evt_type & 0x0000F;
+ u8 code = (evt_type & 0x00FF0) >> 4;
+ unsigned long flags;
+ u32 err = 0;
+ u64 bitmap_t;
+ u32 shift_idx;
+
+ if (evt_prefix == L2_TRACECTR_PREFIX)
+ return err;
+ /*
+ * Cycle counter collision is detected in
+ * get_event_idx().
+ */
+ if (evt_type == L2CYCLE_CTR_RAW_CODE)
+ return err;
+
+ raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
+
+ shift_idx = ((reg * 4) + group);
+
+ bitmap_t = 1 << shift_idx;
+
+ if (!(l2_pmu_constraints.pmu_bitmap & bitmap_t)) {
+ l2_pmu_constraints.pmu_bitmap |= bitmap_t;
+ l2_pmu_constraints.codes[shift_idx] = code;
+ goto out;
+ } else {
+ /*
+ * If NRCCG's are identical,
+ * its not column exclusion.
+ */
+ if (l2_pmu_constraints.codes[shift_idx] != code)
+ err = -EPERM;
+ else
+ /*
+ * If the event is counted in syswide mode
+ * then we want to count only on one CPU
+ * and set its filter to count from all.
+ * This sets the event OFF on all but one
+ * CPU.
+ */
+ if (!(event->cpu < 0)) {
+ event->state = PERF_EVENT_STATE_OFF;
+ event->attr.constraint_duplicate = 1;
+ }
+ }
+out:
+ raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
+ return err;
+}
+
+static int msm_l2_clear_ev_constraint(struct perf_event *event)
+{
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
+ u8 evt_prefix = (evt_type & EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
+ u8 reg = (evt_type & 0x0F000) >> 12;
+ u8 group = evt_type & 0x0000F;
+ unsigned long flags;
+ u64 bitmap_t;
+ u32 shift_idx;
+
+ if (evt_prefix == L2_TRACECTR_PREFIX)
+ return 1;
+ raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
+
+ shift_idx = ((reg * 4) + group);
+
+ bitmap_t = 1 << shift_idx;
+
+ /* Clear constraint bit. */
+ l2_pmu_constraints.pmu_bitmap &= ~bitmap_t;
+
+ /* Clear code. */
+ l2_pmu_constraints.codes[shift_idx] = -1;
+
+ raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
+ return 1;
+}
+
+int get_num_events(void)
+{
+ int val;
+
+ val = get_l2_indirect_reg(L2PMCR);
+
+ /*
+ * Read bits 15:11 of the L2PMCR and add 1
+ * for the cycle counter.
+ */
+ return ((val >> PMCR_NUM_EV_SHIFT) & PMCR_NUM_EV_MASK) + 1;
+}
+
+static struct arm_pmu krait_l2_pmu = {
+ .name = (char *)"msm-l2",
+ .start = krait_l2_start,
+ .stop = krait_l2_stop,
+ .handle_irq = krait_l2_handle_irq,
+ .request_pmu_irq = krait_l2_pmu_generic_request_irq,
+ .free_pmu_irq = krait_l2_pmu_generic_free_irq,
+ .enable = krait_l2_enable,
+ .disable = krait_l2_disable,
+ .get_event_idx = krait_l2_get_event_idx,
+ .read_counter = krait_l2_read_counter,
+ .write_counter = krait_l2_write_counter,
+ .map_event = krait_l2_map_event,
+ .max_period = MAX_L2_PERIOD,
+ .get_hw_events = krait_l2_get_hw_events,
+ .request_irq = cpu_pmu_request_irq,
+ .free_irq = cpu_pmu_free_irq,
+ .test_set_event_constraints = msm_l2_test_set_ev_constraint,
+ .clear_event_constraints = msm_l2_clear_ev_constraint,
+ .pmu.attr_groups = msm_l2_pmu_attr_grps,
+};
+
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id l2pmu_of_device_ids[] = {
+ {.compatible = "qcom,l2-pmu"},
+ {},
+};
+
+static int krait_l2_pmu_device_probe(struct platform_device *pdev)
+{
+ krait_l2_pmu.plat_device = pdev;
+
+ if (!armpmu_register(&krait_l2_pmu, -1))
+ pmu_type = krait_l2_pmu.pmu.type;
+
+ return 0;
+}
+
+static struct platform_driver krait_l2_pmu_driver = {
+ .driver = {
+ .name = "l2-pmu",
+ .of_match_table = l2pmu_of_device_ids,
+ },
+ .probe = krait_l2_pmu_device_probe,
+};
+
+static int __init register_krait_l2_pmu_driver(void)
+{
+ int i;
+
+ /* Reset all ctrs */
+ set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
+
+ /* Get num of counters in the L2cc PMU. */
+ total_l2_ctrs = get_num_events();
+ krait_l2_pmu.num_events = total_l2_ctrs;
+
+ pr_info("Detected %d counters on the L2CC PMU.\n",
+ total_l2_ctrs);
+
+ /*
+ * The L2 cycle counter index in the used_mask
+ * bit stream is always after the other counters.
+ * Counter indexes begin from 0 to keep it consistent
+ * with the h/w.
+ */
+ l2_cycle_ctr_idx = total_l2_ctrs - 1;
+
+ /* Avoid spurious interrupt if any */
+ get_reset_pmovsr();
+
+ /* Clear counter enables */
+ disable_counter(l2_cycle_ctr_idx);
+ for (i = 0; i < total_l2_ctrs; i++)
+ disable_counter(i);
+
+ return platform_driver_register(&krait_l2_pmu_driver);
+}
+device_initcall(register_krait_l2_pmu_driver);
diff --git a/arch/arm/mach-msm/perf_trace_counters.c b/arch/arm/mach-msm/perf_trace_counters.c
new file mode 100644
index 000000000000..43165c9b9f2f
--- /dev/null
+++ b/arch/arm/mach-msm/perf_trace_counters.c
@@ -0,0 +1,185 @@
+/* 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 <asm/thread_notify.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/cpu.h>
+#define CREATE_TRACE_POINTS
+#include "perf_trace_counters.h"
+
+static unsigned int tp_pid_state;
+
+DEFINE_PER_CPU(u32, previous_ccnt);
+DEFINE_PER_CPU(u32[NUM_L1_CTRS], previous_l1_cnts);
+DEFINE_PER_CPU(u32[NUM_L2_PERCPU], previous_l2_cnts);
+DEFINE_PER_CPU(u32, old_pid);
+DEFINE_PER_CPU(u32, hotplug_flag);
+/* Reset per_cpu variables that store counter values uppn CPU hotplug */
+static int tracectr_cpu_hotplug_notifier(struct notifier_block *self,
+ unsigned long action, void *hcpu)
+{
+ int ret = NOTIFY_OK;
+ int cpu = (int)hcpu;
+
+ if ((action & (~CPU_TASKS_FROZEN)) == CPU_STARTING)
+ per_cpu(hotplug_flag, cpu) = 1;
+
+ return ret;
+}
+
+static struct notifier_block tracectr_cpu_hotplug_notifier_block = {
+ .notifier_call = tracectr_cpu_hotplug_notifier,
+};
+
+static void setup_prev_cnts(u32 cpu)
+{
+ int i;
+ u32 cnten_val;
+
+ /* Read PMCNTENSET */
+ asm volatile("mrc p15, 0, %0, c9, c12, 1" : "=r"(cnten_val));
+ /* Disable all the counters that were enabled */
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(cnten_val));
+ if (cnten_val & CC) {
+ /* Read value */
+ asm volatile("mrc p15, 0, %0, c9, c13, 0"
+ : "=r"(per_cpu(previous_ccnt, cpu)));
+ }
+
+ for (i = 0; i < NUM_L1_CTRS; i++) {
+ if (cnten_val & (1 << i)) {
+ /* Select */
+ asm volatile("mcr p15, 0, %0, c9, c12, 5"
+ : : "r"(i));
+ /* Read value */
+ asm volatile("mrc p15, 0, %0, c9, c13, 2"
+ : "=r"(per_cpu(previous_l1_cnts[i], cpu)));
+ }
+ }
+ /* Enable all the counters that were disabled */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(cnten_val));
+}
+
+static int tracectr_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ struct thread_info *thread = v;
+ int current_pid;
+ u32 cpu = thread->cpu;
+
+ if (cmd != THREAD_NOTIFY_SWITCH)
+ return -EFAULT;
+
+ current_pid = thread->task->pid;
+ if (per_cpu(old_pid, cpu) != -1) {
+ if (per_cpu(hotplug_flag, cpu) == 1) {
+ per_cpu(hotplug_flag, cpu) = 0;
+ setup_prev_cnts(cpu);
+ } else
+ trace_sched_switch_with_ctrs(per_cpu(old_pid, cpu),
+ current_pid);
+ }
+ per_cpu(old_pid, cpu) = current_pid;
+ return NOTIFY_OK;
+}
+
+static struct notifier_block tracectr_notifier_block = {
+ .notifier_call = tracectr_notifier,
+};
+
+static void enable_tp_pid(void)
+{
+ if (tp_pid_state == 0) {
+ tp_pid_state = 1;
+ thread_register_notifier(&tracectr_notifier_block);
+ }
+}
+
+static void disable_tp_pid(void)
+{
+ if (tp_pid_state == 1) {
+ tp_pid_state = 0;
+ thread_unregister_notifier(&tracectr_notifier_block);
+ }
+}
+
+static ssize_t read_enabled_perftp_file_bool(struct file *file,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buf[2];
+ buf[1] = '\n';
+ if (tp_pid_state == 0)
+ buf[0] = '0';
+ else
+ buf[0] = '1';
+ return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+
+static ssize_t write_enabled_perftp_file_bool(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ char buf[32];
+ size_t buf_size;
+
+ buf_size = min(count, (sizeof(buf)-1));
+ if (copy_from_user(buf, user_buf, buf_size))
+ return -EFAULT;
+ switch (buf[0]) {
+ case 'y':
+ case 'Y':
+ case '1':
+ enable_tp_pid();
+ break;
+ case 'n':
+ case 'N':
+ case '0':
+ disable_tp_pid();
+ break;
+ }
+
+ return count;
+}
+
+static const struct file_operations fops_perftp = {
+ .read = read_enabled_perftp_file_bool,
+ .write = write_enabled_perftp_file_bool,
+ .llseek = default_llseek,
+};
+
+int __init init_tracecounters(void)
+{
+ struct dentry *dir;
+ struct dentry *file;
+ unsigned int value = 1;
+ int cpu;
+
+ dir = debugfs_create_dir("perf_debug_tp", NULL);
+ if (!dir)
+ return -ENOMEM;
+ file = debugfs_create_file("enabled", 0660, dir,
+ &value, &fops_perftp);
+ if (!file) {
+ debugfs_remove(dir);
+ return -ENOMEM;
+ }
+ register_cpu_notifier(&tracectr_cpu_hotplug_notifier_block);
+ for_each_possible_cpu(cpu)
+ per_cpu(old_pid, cpu) = -1;
+ return 0;
+}
+
+int __exit exit_tracecounters(void)
+{
+ unregister_cpu_notifier(&tracectr_cpu_hotplug_notifier_block);
+ return 0;
+}
+late_initcall(init_tracecounters);
diff --git a/arch/arm/mach-msm/perf_trace_counters.h b/arch/arm/mach-msm/perf_trace_counters.h
new file mode 100644
index 000000000000..c738bedc97b4
--- /dev/null
+++ b/arch/arm/mach-msm/perf_trace_counters.h
@@ -0,0 +1,161 @@
+/* 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM perf_trace_counters
+
+#if !defined(_PERF_TRACE_COUNTERS_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _PERF_TRACE_COUNTERS_H_
+
+/* Ctr index for PMCNTENSET/CLR */
+#define CC 0x80000000
+#define C0 0x1
+#define C1 0x2
+#define C2 0x4
+#define C3 0x8
+#define C_ALL (CC | C0 | C1 | C2 | C3)
+#define NUM_L1_CTRS 4
+#define NUM_L2_PERCPU 2
+
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/tracepoint.h>
+#include <mach/msm-krait-l2-accessors.h>
+
+DECLARE_PER_CPU(u32, previous_ccnt);
+DECLARE_PER_CPU(u32[NUM_L1_CTRS], previous_l1_cnts);
+DECLARE_PER_CPU(u32[NUM_L2_PERCPU], previous_l2_cnts);
+TRACE_EVENT(sched_switch_with_ctrs,
+
+ TP_PROTO(pid_t prev, pid_t next),
+
+ TP_ARGS(prev, next),
+
+ TP_STRUCT__entry(
+ __field(pid_t, old_pid)
+ __field(pid_t, new_pid)
+ __field(u32, cctr)
+ __field(u32, ctr0)
+ __field(u32, ctr1)
+ __field(u32, ctr2)
+ __field(u32, ctr3)
+ __field(u32, lctr0)
+ __field(u32, lctr1)
+ ),
+
+ TP_fast_assign(
+ u32 cpu = smp_processor_id();
+ u32 idx;
+ u32 i;
+ u32 counter_reg;
+ u32 val;
+ u32 cnten_val;
+ u32 num_l2ctrs;
+ u32 num_cores = nr_cpu_ids;
+ u32 total_ccnt = 0;
+ u32 total_cnt = 0;
+ u32 delta_l1_cnts[NUM_L1_CTRS];
+ u32 delta_l2_cnts[NUM_L2_PERCPU];
+ __entry->old_pid = prev;
+ __entry->new_pid = next;
+
+ val = get_l2_indirect_reg(L2PMCR);
+ num_l2ctrs = ((val >> 11) & 0x1f) + 1;
+
+ /* Read PMCNTENSET */
+ asm volatile("mrc p15, 0, %0, c9, c12, 1"
+ : "=r"(cnten_val));
+ /* Disable all the counters that were enabled */
+ asm volatile("mcr p15, 0, %0, c9, c12, 2"
+ : : "r"(cnten_val));
+ if (cnten_val & CC) {
+ /* Read value */
+ asm volatile("mrc p15, 0, %0, c9, c13, 0"
+ : "=r"(total_ccnt));
+ __entry->cctr = total_ccnt -
+ per_cpu(previous_ccnt, cpu);
+ per_cpu(previous_ccnt, cpu) = total_ccnt;
+ }
+ for (i = 0; i < NUM_L1_CTRS; i++) {
+ if (cnten_val & (1 << i)) {
+ /* Select */
+ asm volatile(
+ "mcr p15, 0, %0, c9, c12, 5"
+ : : "r"(i));
+ /* Read value */
+ asm volatile(
+ "mrc p15, 0, %0, c9, c13, 2"
+ : "=r"(total_cnt));
+
+ delta_l1_cnts[i] = total_cnt -
+ per_cpu(previous_l1_cnts[i], cpu);
+ per_cpu(previous_l1_cnts[i], cpu) =
+ total_cnt;
+ } else
+ delta_l1_cnts[i] = 0;
+ }
+ /* Enable all the counters that were disabled */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1"
+ : : "r"(cnten_val));
+
+ /* L2 counters */
+ /* Assign L2 counters to cores sequentially starting
+ * from zero. A core could have multiple L2 counters
+ * allocated if # L2 counters is more than the # cores
+ */
+ cnten_val = get_l2_indirect_reg(L2PMCNTENSET);
+ for (i = 0; i < NUM_L2_PERCPU; i++) {
+ idx = cpu + (num_cores * i);
+ if (idx < num_l2ctrs &&
+ (cnten_val & (1 << idx))) {
+ /* Disable */
+ set_l2_indirect_reg(L2PMCNTENCLR,
+ (1 << idx));
+ /* L2PMEVCNTR values go from 0x421,
+ * 0x431..
+ * So we multiply idx by 16 to get the
+ * counter reg value
+ */
+ counter_reg = (idx * 16) +
+ IA_L2PMXEVCNTR_BASE;
+ total_cnt =
+ get_l2_indirect_reg(counter_reg);
+ /* Enable */
+ set_l2_indirect_reg(L2PMCNTENSET,
+ (1 << idx));
+ delta_l2_cnts[i] = total_cnt -
+ per_cpu(previous_l2_cnts[i], cpu);
+ per_cpu(previous_l2_cnts[i], cpu) =
+ total_cnt;
+ } else
+ delta_l2_cnts[i] = 0;
+ }
+ __entry->ctr0 = delta_l1_cnts[0];
+ __entry->ctr1 = delta_l1_cnts[1];
+ __entry->ctr2 = delta_l1_cnts[2];
+ __entry->ctr3 = delta_l1_cnts[3];
+ __entry->lctr0 = delta_l2_cnts[0];
+ __entry->lctr1 = delta_l2_cnts[1];
+ ),
+
+ TP_printk("prev_pid=%d, next_pid=%d, CCNTR: %u, CTR0: %u, CTR1: %u, CTR2: %u, CTR3: %u, L2CTR0: %u, L2CTR1: %u",
+ __entry->old_pid, __entry->new_pid,
+ __entry->cctr, __entry->ctr0, __entry->ctr1,
+ __entry->ctr2, __entry->ctr3,
+ __entry->lctr0, __entry->lctr1)
+);
+
+#endif
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../arch/arm/mach-msm
+#define TRACE_INCLUDE_FILE perf_trace_counters
+#include <trace/define_trace.h>
diff --git a/arch/arm/mach-msm/perfmap.c b/arch/arm/mach-msm/perfmap.c
new file mode 100644
index 000000000000..244716a0fc0e
--- /dev/null
+++ b/arch/arm/mach-msm/perfmap.c
@@ -0,0 +1,126 @@
+/* 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.
+ */
+
+/* Character device driver for memory mapped performance counter interface */
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/cpu_pm.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/sched.h>
+#include <linux/cdev.h>
+
+uint32_t perfmap_base;
+uint32_t PERF_BASE_SIZE;
+
+
+static dev_t perfmap_dev;
+static struct cdev perfmap_cdev;
+static struct class *perfmap_devclass;
+
+static struct of_device_id perfmap_of_device_ids[] = {
+ {.compatible = "qcom,perfmap"},
+ {},
+};
+
+static int perfmap_device_probe(struct platform_device *pdev)
+{
+ struct resource *resource;
+
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!resource)
+ return -EINVAL;
+ perfmap_base = resource->start;
+
+ return 0;
+}
+
+static struct platform_driver perfmap_pmu_driver = {
+ .driver = {
+ .name = "perfmap",
+ .of_match_table = perfmap_of_device_ids,
+ },
+ .probe = perfmap_device_probe,
+};
+
+static int perfmap_mmap(struct file *filep, struct vm_area_struct *vma)
+{
+ int ret = 0;
+ unsigned long pfn_num;
+
+ pfn_num = perfmap_base>>PAGE_SHIFT;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ if (remap_pfn_range(vma, vma->vm_start, pfn_num,
+ vma->vm_end-vma->vm_start,
+ vma->vm_page_prot)) {
+ return -EAGAIN;
+ }
+ return ret;
+}
+
+static const struct file_operations perfmap_fops = {
+ .mmap = perfmap_mmap,
+};
+
+static int perfmap_init(void)
+{
+ int result = 0;
+
+ platform_driver_register(&perfmap_pmu_driver);
+ if (alloc_chrdev_region(&perfmap_dev, 0, 1, "perfmap") < 0) {
+ pr_err("perfmap: Error in alloc_chrdev_region\n");
+ goto alloc_err;
+ }
+ perfmap_devclass = class_create(THIS_MODULE, "chardrv");
+ if (IS_ERR(perfmap_devclass)) {
+ pr_err("perfmap: Error in class_create\n");
+ goto class_err;
+ }
+ if (device_create(perfmap_devclass, NULL, perfmap_dev, NULL,
+ "perfmap0") == NULL) {
+ pr_err("perfmap: Error in device_create\n");
+ goto create_err;
+ }
+ cdev_init(&perfmap_cdev, &perfmap_fops);
+ if (cdev_add(&perfmap_cdev, perfmap_dev, 1) == -1) {
+ pr_err("perfmap: Error in cdev_add\n");
+ goto add_err;
+ }
+ return result;
+add_err:
+ device_destroy(perfmap_devclass, perfmap_dev);
+create_err:
+ class_destroy(perfmap_devclass);
+class_err:
+ unregister_chrdev_region(perfmap_dev, 1);
+alloc_err:
+ result = -ENODEV;
+ return result;
+}
+
+static void perfmap_exit(void)
+{
+ cdev_del(&perfmap_cdev);
+ device_destroy(perfmap_devclass, perfmap_dev);
+ class_destroy(perfmap_devclass);
+ unregister_chrdev_region(perfmap_dev, 1);
+ platform_driver_unregister(&perfmap_pmu_driver);
+}
+
+module_init(perfmap_init);
+module_exit(perfmap_exit);
+
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
new file mode 100644
index 000000000000..af66b8e860b4
--- /dev/null
+++ b/arch/arm/mach-msm/platsmp.c
@@ -0,0 +1,539 @@
+/*
+ * Copyright (C) 2002 ARM Ltd.
+ * All Rights Reserved
+ * 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 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/regulator/krait-regulator.h>
+// AGSTUB
+//#include <soc/qcom/spm.h>
+#include <soc/qcom/pm.h>
+#include <soc/qcom/scm-boot.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <asm/mach-types.h>
+#include <asm/smp_plat.h>
+
+#include <soc/qcom/socinfo.h>
+#include <mach/hardware.h>
+#include <mach/msm_iomap.h>
+
+#include "platsmp.h"
+
+#define VDD_SC1_ARRAY_CLAMP_GFS_CTL 0x15A0
+#define SCSS_CPU1CORE_RESET 0xD80
+#define SCSS_DBG_STATUS_CORE_PWRDUP 0xE64
+#define MSM8960_SAW2_BASE_ADDR 0x02089000
+#define MSM8962_SAW2_BASE_ADDR 0xF9089000
+#define APCS_ALIAS0_BASE_ADDR 0xF9088000
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not. This is necessary for the hotplug code to work reliably.
+ */
+void __cpuinit write_pen_release(int val)
+{
+ pen_release = val;
+ smp_wmb();
+ __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+ outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit msm_secondary_init(unsigned int cpu)
+{
+ WARN_ON(msm_platform_secondary_init(cpu));
+
+ /*
+ * let the primary processor know we're out of the
+ * pen, then head off into the C entry point
+ */
+ write_pen_release(-1);
+
+ /*
+ * Synchronise with the boot thread.
+ */
+ spin_lock(&boot_lock);
+ spin_unlock(&boot_lock);
+}
+
+static int __cpuinit release_secondary_sim(unsigned long base, unsigned int cpu)
+{
+ void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+ if (!base_ptr)
+ return -ENODEV;
+
+ writel_relaxed(0x800, base_ptr+0x04);
+ writel_relaxed(0x3FFF, base_ptr+0x14);
+
+ mb();
+ iounmap(base_ptr);
+ return 0;
+}
+
+static int __cpuinit scorpion_release_secondary(void)
+{
+ void *base_ptr = ioremap_nocache(0x00902000, SZ_4K*2);
+ if (!base_ptr)
+ return -EINVAL;
+
+ writel_relaxed(0, base_ptr + VDD_SC1_ARRAY_CLAMP_GFS_CTL);
+ dmb();
+ writel_relaxed(0, base_ptr + SCSS_CPU1CORE_RESET);
+ writel_relaxed(3, base_ptr + SCSS_DBG_STATUS_CORE_PWRDUP);
+ mb();
+ iounmap(base_ptr);
+
+ return 0;
+}
+
+static int __cpuinit msm8960_release_secondary(unsigned long base,
+ unsigned int cpu)
+{
+ void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+ if (!base_ptr)
+ return -ENODEV;
+
+// AGSTUB
+// msm_spm_turn_on_cpu_rail(MSM8960_SAW2_BASE_ADDR, cpu);
+
+ writel_relaxed(0x109, base_ptr+0x04);
+ writel_relaxed(0x101, base_ptr+0x04);
+ mb();
+ ndelay(300);
+
+ writel_relaxed(0x121, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x120, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x100, base_ptr+0x04);
+ mb();
+ udelay(100);
+
+ writel_relaxed(0x180, base_ptr+0x04);
+ mb();
+ iounmap(base_ptr);
+ return 0;
+}
+
+static int __cpuinit msm8974_release_secondary(unsigned long base,
+ unsigned int cpu)
+{
+ void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+
+ if (!base_ptr)
+ return -ENODEV;
+
+ secondary_cpu_hs_init(base_ptr, cpu);
+
+ writel_relaxed(0x021, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x020, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x000, base_ptr+0x04);
+ mb();
+
+ writel_relaxed(0x080, base_ptr+0x04);
+ mb();
+ iounmap(base_ptr);
+ return 0;
+}
+
+static int __cpuinit msm8962_release_secondary(unsigned long base,
+ unsigned int cpu)
+{
+ void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+
+ if (!base_ptr)
+ return -ENODEV;
+
+// AGSTUB
+// msm_spm_turn_on_cpu_rail(MSM8962_SAW2_BASE_ADDR, cpu);
+
+ writel_relaxed(0x021, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x020, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x000, base_ptr+0x04);
+ mb();
+
+ writel_relaxed(0x080, base_ptr+0x04);
+ mb();
+ iounmap(base_ptr);
+ return 0;
+}
+
+static int __cpuinit arm_release_secondary(unsigned long base, unsigned int cpu)
+{
+ void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+ if (!base_ptr)
+ return -ENODEV;
+
+ writel_relaxed(0x00000033, base_ptr+0x04);
+ mb();
+
+ writel_relaxed(0x10000001, base_ptr+0x14);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x00000031, base_ptr+0x04);
+ mb();
+
+ writel_relaxed(0x00000039, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+ writel_relaxed(0x00020038, base_ptr+0x04);
+ mb();
+ udelay(2);
+
+
+ writel_relaxed(0x00020008, base_ptr+0x04);
+ mb();
+
+ writel_relaxed(0x00020088, base_ptr+0x04);
+ mb();
+
+ iounmap(base_ptr);
+ return 0;
+}
+
+static int __cpuinit release_from_pen(unsigned int cpu)
+{
+ unsigned long timeout;
+
+ /* Set preset_lpj to avoid subsequent lpj recalculations */
+ preset_lpj = loops_per_jiffy;
+
+ /*
+ * set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ 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.
+ */
+ write_pen_release(cpu_logical_map(cpu));
+
+ /*
+ * 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;
+}
+
+DEFINE_PER_CPU(int, cold_boot_done);
+
+int __cpuinit scorpion_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+{
+ pr_debug("Starting secondary CPU %d\n", cpu);
+
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ scorpion_release_secondary();
+ per_cpu(cold_boot_done, cpu) = true;
+ }
+ return release_from_pen(cpu);
+}
+
+int __cpuinit msm8960_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ pr_debug("Starting secondary CPU %d\n", cpu);
+
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ msm8960_release_secondary(0x02088000, cpu);
+ per_cpu(cold_boot_done, cpu) = true;
+ }
+ return release_from_pen(cpu);
+}
+
+int __cpuinit msm8974_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ pr_debug("Starting secondary CPU %d\n", cpu);
+
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ if (of_board_is_sim())
+ release_secondary_sim(APCS_ALIAS0_BASE_ADDR, cpu);
+ else if (!of_board_is_rumi())
+ msm8974_release_secondary(APCS_ALIAS0_BASE_ADDR, cpu);
+
+ per_cpu(cold_boot_done, cpu) = true;
+ }
+ return release_from_pen(cpu);
+}
+
+int __cpuinit msm8962_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ pr_debug("Starting secondary CPU %d\n", cpu);
+
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ if (of_board_is_sim())
+ release_secondary_sim(APCS_ALIAS0_BASE_ADDR, cpu);
+ else if (!of_board_is_rumi())
+ msm8962_release_secondary(APCS_ALIAS0_BASE_ADDR, cpu);
+
+ per_cpu(cold_boot_done, cpu) = true;
+ }
+ return release_from_pen(cpu);
+}
+
+static int __cpuinit msm8916_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+{
+ pr_debug("Starting secondary CPU %d\n", cpu);
+
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ if (of_board_is_sim())
+ release_secondary_sim(0xb088000, cpu);
+ else if (!of_board_is_rumi())
+ arm_release_secondary(0xb088000, cpu);
+
+ per_cpu(cold_boot_done, cpu) = true;
+ }
+ return release_from_pen(cpu);
+}
+
+static int __cpuinit msm8936_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+{
+ pr_debug("Starting secondary CPU %d\n", cpu);
+
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ u32 mpidr = cpu_logical_map(cpu);
+ u32 apcs_base = MPIDR_AFFINITY_LEVEL(mpidr, 1) ?
+ 0xb088000 : 0xb188000;
+ if (of_board_is_sim())
+ release_secondary_sim(apcs_base,
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
+ else if (!of_board_is_rumi())
+ arm_release_secondary(apcs_base,
+ MPIDR_AFFINITY_LEVEL(mpidr, 0));
+
+ per_cpu(cold_boot_done, cpu) = true;
+ }
+ return release_from_pen(cpu);
+}
+
+int __cpuinit arm_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ pr_debug("Starting secondary CPU %d\n", cpu);
+
+ if (per_cpu(cold_boot_done, cpu) == false) {
+ if (of_board_is_sim())
+ release_secondary_sim(APCS_ALIAS0_BASE_ADDR, cpu);
+ else if (!of_board_is_rumi())
+ arm_release_secondary(APCS_ALIAS0_BASE_ADDR, cpu);
+
+ per_cpu(cold_boot_done, cpu) = true;
+ }
+ return release_from_pen(cpu);
+}
+
+/*
+ * Initialise the CPU possible map early - this describes the CPUs
+ * which may be present or become present in the system.
+ */
+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 arm_smp_init_cpus(void)
+{
+ unsigned int i, ncores;
+
+ ncores = (__raw_readl(MSM_APCS_GCC_BASE + 0x30)) & 0xF;
+
+ 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 cold_boot_flags[] __initdata = {
+ 0,
+ SCM_FLAG_COLDBOOT_CPU1,
+ SCM_FLAG_COLDBOOT_CPU2,
+ SCM_FLAG_COLDBOOT_CPU3,
+};
+
+static void __init msm_platform_smp_prepare_cpus_mc(unsigned int max_cpus)
+{
+ int cpu, map;
+ u32 aff0_mask = 0;
+ u32 aff1_mask = 0;
+ u32 aff2_mask = 0;
+
+ for_each_present_cpu(cpu) {
+ map = cpu_logical_map(cpu);
+ aff0_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 0));
+ aff1_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 1));
+ aff2_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 2));
+ }
+
+ if (scm_set_boot_addr_mc(virt_to_phys(msm_secondary_startup),
+ aff0_mask, aff1_mask, aff2_mask, SCM_FLAG_COLDBOOT_MC))
+ pr_warn("Failed to set CPU boot address\n");
+}
+
+static void __init msm_platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+ int cpu, map;
+ unsigned int flags = 0;
+
+ if (scm_is_mc_boot_available())
+ return msm_platform_smp_prepare_cpus_mc(max_cpus);
+
+ for_each_present_cpu(cpu) {
+ map = cpu_logical_map(cpu);
+ if (map > ARRAY_SIZE(cold_boot_flags)) {
+ set_cpu_present(cpu, false);
+ __WARN();
+ continue;
+ }
+ flags |= cold_boot_flags[map];
+ }
+
+ if (scm_set_boot_addr(virt_to_phys(msm_secondary_startup), flags))
+ pr_warn("Failed to set CPU boot address\n");
+}
+
+struct smp_operations arm_smp_ops __initdata = {
+ .smp_init_cpus = arm_smp_init_cpus,
+ .smp_prepare_cpus = msm_platform_smp_prepare_cpus,
+ .smp_secondary_init = msm_secondary_init,
+ .smp_boot_secondary = arm_boot_secondary,
+#ifdef CONFIG_HOTPLUG
+ .cpu_die = msm_cpu_die,
+ .cpu_kill = msm_cpu_kill,
+#endif
+};
+
+struct smp_operations msm8916_smp_ops __initdata = {
+ .smp_init_cpus = arm_smp_init_cpus,
+ .smp_prepare_cpus = msm_platform_smp_prepare_cpus,
+ .smp_secondary_init = msm_secondary_init,
+ .smp_boot_secondary = msm8916_boot_secondary,
+#ifdef CONFIG_HOTPLUG
+ .cpu_die = msm_cpu_die,
+ .cpu_kill = msm_cpu_kill,
+#endif
+};
+
+struct smp_operations msm8936_smp_ops __initdata = {
+ .smp_init_cpus = arm_smp_init_cpus,
+ .smp_prepare_cpus = msm_platform_smp_prepare_cpus,
+ .smp_secondary_init = msm_secondary_init,
+ .smp_boot_secondary = msm8936_boot_secondary,
+#ifdef CONFIG_HOTPLUG
+ .cpu_die = msm_cpu_die,
+ .cpu_kill = msm_cpu_kill,
+#endif
+};
+
+struct smp_operations msm8974_smp_ops __initdata = {
+ .smp_init_cpus = msm_smp_init_cpus,
+ .smp_prepare_cpus = msm_platform_smp_prepare_cpus,
+ .smp_secondary_init = msm_secondary_init,
+ .smp_boot_secondary = msm8974_boot_secondary,
+#ifdef CONFIG_HOTPLUG
+ .cpu_die = msm_cpu_die,
+ .cpu_kill = msm_cpu_kill,
+#endif
+};
+
+struct smp_operations msm8962_smp_ops __initdata = {
+ .smp_init_cpus = msm_smp_init_cpus,
+ .smp_prepare_cpus = msm_platform_smp_prepare_cpus,
+ .smp_secondary_init = msm_secondary_init,
+ .smp_boot_secondary = msm8962_boot_secondary,
+#ifdef CONFIG_HOTPLUG
+ .cpu_die = msm_cpu_die,
+ .cpu_kill = msm_cpu_kill,
+#endif
+};
+
+struct smp_operations msm8960_smp_ops __initdata = {
+ .smp_init_cpus = msm_smp_init_cpus,
+ .smp_prepare_cpus = msm_platform_smp_prepare_cpus,
+ .smp_secondary_init = msm_secondary_init,
+ .smp_boot_secondary = msm8960_boot_secondary,
+#ifdef CONFIG_HOTPLUG
+ .cpu_die = msm_cpu_die,
+ .cpu_kill = msm_cpu_kill,
+#endif
+};
+
+struct smp_operations scorpion_smp_ops __initdata = {
+ .smp_init_cpus = msm_smp_init_cpus,
+ .smp_prepare_cpus = msm_platform_smp_prepare_cpus,
+ .smp_secondary_init = msm_secondary_init,
+ .smp_boot_secondary = scorpion_boot_secondary,
+#ifdef CONFIG_HOTPLUG
+ .cpu_die = msm_cpu_die,
+ .cpu_kill = msm_cpu_kill,
+#endif
+};
diff --git a/arch/arm/mach-msm/platsmp.h b/arch/arm/mach-msm/platsmp.h
new file mode 100644
index 000000000000..c321069a5c9c
--- /dev/null
+++ b/arch/arm/mach-msm/platsmp.h
@@ -0,0 +1,26 @@
+/* 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.
+ */
+
+void msm_secondary_startup(void);
+void write_pen_release(int val);
+
+void msm_cpu_die(unsigned int cpu);
+int msm_cpu_kill(unsigned int cpu);
+
+extern struct smp_operations arm_smp_ops;
+extern struct smp_operations msm8960_smp_ops;
+extern struct smp_operations msm8974_smp_ops;
+extern struct smp_operations msm8962_smp_ops;
+extern struct smp_operations msm8625_smp_ops;
+extern struct smp_operations scorpion_smp_ops;
+extern struct smp_operations msm8916_smp_ops;
+extern struct smp_operations msm8936_smp_ops;
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
new file mode 100644
index 000000000000..722a4ff79697
--- /dev/null
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -0,0 +1,263 @@
+/* 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.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H
+#define __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H
+
+#include <mach/rpm.h>
+#include <linux/notifier.h>
+#include <soc/qcom/pm.h>
+#include "test-lpm.h"
+
+enum {
+ MSM_RPMRS_ID_PXO_CLK = 0,
+ MSM_RPMRS_ID_L2_CACHE_CTL = 1,
+ MSM_RPMRS_ID_VDD_DIG_0 = 2,
+ MSM_RPMRS_ID_VDD_DIG_1 = 3,
+ MSM_RPMRS_ID_VDD_MEM_0 = 4,
+ MSM_RPMRS_ID_VDD_MEM_1 = 5,
+ MSM_RPMRS_ID_RPM_CTL = 6,
+ MSM_RPMRS_ID_LAST,
+};
+
+enum {
+ MSM_RPMRS_PXO_OFF = 0,
+ MSM_RPMRS_PXO_ON = 1,
+};
+
+enum {
+ MSM_RPMRS_L2_CACHE_HSFS_OPEN = 0,
+ MSM_RPMRS_L2_CACHE_GDHS = 1,
+ MSM_RPMRS_L2_CACHE_RETENTION = 2,
+ MSM_RPMRS_L2_CACHE_ACTIVE = 3,
+};
+
+enum {
+ MSM_RPMRS_MASK_RPM_CTL_CPU_HALT = 1,
+ MSM_RPMRS_MASK_RPM_CTL_MULTI_TIER = 2,
+};
+
+enum {
+ MSM_RPMRS_VDD_MEM_RET_LOW = 0,
+ MSM_RPMRS_VDD_MEM_RET_HIGH = 1,
+ MSM_RPMRS_VDD_MEM_ACTIVE = 2,
+ MSM_RPMRS_VDD_MEM_MAX = 3,
+ MSM_RPMRS_VDD_MEM_LAST,
+};
+
+enum {
+ MSM_RPMRS_VDD_DIG_RET_LOW = 0,
+ MSM_RPMRS_VDD_DIG_RET_HIGH = 1,
+ MSM_RPMRS_VDD_DIG_ACTIVE = 2,
+ MSM_RPMRS_VDD_DIG_MAX = 3,
+ MSM_RPMRS_VDD_DIG_LAST,
+};
+
+#define MSM_RPMRS_LIMITS(_pxo, _l2, _vdd_upper_b, _vdd) { \
+ MSM_RPMRS_PXO_##_pxo, \
+ MSM_RPMRS_L2_CACHE_##_l2, \
+ MSM_RPMRS_VDD_MEM_##_vdd_upper_b, \
+ MSM_RPMRS_VDD_MEM_##_vdd, \
+ MSM_RPMRS_VDD_DIG_##_vdd_upper_b, \
+ MSM_RPMRS_VDD_DIG_##_vdd, \
+ {0}, {0}, \
+}
+
+struct msm_rpmrs_limits {
+ uint32_t pxo;
+ uint32_t l2_cache;
+ uint32_t vdd_mem_upper_bound;
+ uint32_t vdd_mem;
+ uint32_t vdd_dig_upper_bound;
+ uint32_t vdd_dig;
+
+ uint32_t latency_us[NR_CPUS];
+ uint32_t power[NR_CPUS];
+};
+
+struct msm_rpmrs_level {
+ enum msm_pm_sleep_mode sleep_mode;
+ struct msm_rpmrs_limits rs_limits;
+ bool available;
+ uint32_t latency_us;
+ uint32_t steady_state_power;
+ uint32_t energy_overhead;
+ uint32_t time_overhead_us;
+};
+
+struct msm_rpmrs_platform_data {
+ struct msm_rpmrs_level *levels;
+ unsigned int num_levels;
+ unsigned int vdd_mem_levels[MSM_RPMRS_VDD_MEM_LAST];
+ unsigned int vdd_dig_levels[MSM_RPMRS_VDD_DIG_LAST];
+ unsigned int vdd_mask;
+ unsigned int rpmrs_target_id[MSM_RPMRS_ID_LAST];
+};
+
+enum {
+ MSM_LPM_STATE_ENTER = 0,
+ MSM_LPM_STATE_EXIT = 1,
+};
+
+/**
+ * struct msm_lpm_sleep_data - abstraction to get sleep data
+ * @limits: pointer to the msm_rpmrs_limits structure
+ * @kernel_sleep: kernel sleep time as decided by the power calculation
+ * algorithm
+ *
+ * This structure is an abstraction to get the limits and kernel sleep time
+ * during enter sleep.
+ */
+
+struct msm_lpm_sleep_data {
+ struct msm_rpmrs_limits *limits;
+ uint32_t kernel_sleep;
+};
+
+#define MSM_PM(field) MSM_RPMRS_##field
+
+/**
+ * msm_pm_get_pxo() - get the limits for pxo
+ * @limits: pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource pxo on
+ * 8960
+ */
+
+uint32_t msm_pm_get_pxo(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_l2_cache() - get the limits for l2 cache
+ * @limits: pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource l2 cache
+ * on 8960
+ */
+
+uint32_t msm_pm_get_l2_cache(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_vdd_mem() - get the limits for pxo
+ * @limits: pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource vdd mem
+ * on 8960
+ */
+
+uint32_t msm_pm_get_vdd_mem(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_pm_get_vdd_dig() - get the limits for vdd dig
+ * @limits: pointer to the msm_rpmrs_limits structure
+ *
+ * This function gets the limits to the resource vdd dig
+ * on 8960
+ */
+
+uint32_t msm_pm_get_vdd_dig(struct msm_rpmrs_limits *limits);
+
+/**
+ * msm_lpm_register_notifier() - register for notifications
+ * @cpu: cpu to debug
+ * @level_iter: low power level index to debug
+ * @nb: notifier block to callback on notifications
+ * @is_latency_measure: is it latency measure
+ *
+ * This function sets the permitted level to the index of the
+ * level under test and registers notifier for callback.
+ */
+
+int msm_lpm_register_notifier(int cpu, int level_iter,
+ struct notifier_block *nb, bool is_latency_measure);
+
+/**
+ * msm_lpm_unregister_notifier() - unregister from notifications
+ * @cpu: cpu to debug
+ * @nb: notifier block to callback on notifications
+ *
+ * This function sets the permitted level to a value one more than
+ * available levels count which indicates that all levels are
+ * permitted and it also unregisters notifier for callback.
+ */
+
+int msm_lpm_unregister_notifier(int cpu, struct notifier_block *nb);
+
+
+static inline int msm_rpmrs_set(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_bits_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count, int *mask)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_nosleep(
+ int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear_nosleep(
+ int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline struct msm_rpmrs_limits *msm_rpmrs_lowest_limits(
+ bool from_idle, enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
+ uint32_t sleep_us)
+{
+ return NULL;
+}
+
+static inline int msm_rpmrs_enter_sleep(uint32_t sclk_count,
+ struct msm_rpmrs_limits *limits, bool from_idle, bool notify_rpm)
+{
+ return -ENODEV;
+}
+
+static inline void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+ bool from_idle, bool notify_rpm, bool collapsed)
+{
+ return;
+}
+
+static inline int msm_rpmrs_levels_init(struct msm_rpmrs_platform_data *data)
+{
+ return -ENODEV;
+}
+
+
+#endif /* __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H */
diff --git a/arch/arm/mach-msm/scm-xpu.c b/arch/arm/mach-msm/scm-xpu.c
new file mode 100644
index 000000000000..e05c7b371cdd
--- /dev/null
+++ b/arch/arm/mach-msm/scm-xpu.c
@@ -0,0 +1,44 @@
+/* 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <soc/qcom/scm.h>
+
+
+#define ERR_FATAL_ENABLE 0x0
+#define ERR_FATAL_DISABLE 0x1
+#define ERR_FATAL_READ 0x2
+#define XPU_ERR_FATAL 0xe
+
+static int __init xpu_err_fatal_init(void)
+{
+ int ret, response;
+ struct {
+ unsigned int config;
+ unsigned int spare;
+ } cmd;
+ cmd.config = ERR_FATAL_ENABLE;
+ cmd.spare = 0;
+
+ ret = scm_call(SCM_SVC_MP, XPU_ERR_FATAL, &cmd, sizeof(cmd), &response,
+ sizeof(response));
+
+ if (ret != 0)
+ pr_warn("Failed to set XPU violations as fatal errors: %d\n",
+ ret);
+ else
+ pr_info("Configuring XPU violations to be fatal errors\n");
+
+ return ret;
+}
+early_initcall(xpu_err_fatal_init);
diff --git a/arch/arm/mach-msm/smcmod.c b/arch/arm/mach-msm/smcmod.c
new file mode 100644
index 000000000000..554b9f2880b9
--- /dev/null
+++ b/arch/arm/mach-msm/smcmod.c
@@ -0,0 +1,831 @@
+/* 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.
+ *
+ */
+
+#define KMSG_COMPONENT "SMCMOD"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/msm_ion.h>
+#include <soc/qcom/scm.h>
+#include <soc/qcom/socinfo.h>
+
+#include <asm/smcmod.h>
+
+static DEFINE_MUTEX(ioctl_lock);
+
+#define SMCMOD_SVC_DEFAULT (0)
+#define SMCMOD_SVC_CRYPTO (1)
+#define SMCMOD_CRYPTO_CMD_CIPHER (1)
+#define SMCMOD_CRYPTO_CMD_MSG_DIGEST_FIXED (2)
+#define SMCMOD_CRYPTO_CMD_MSG_DIGEST (3)
+
+/**
+ * struct smcmod_cipher_scm_req - structure for sending the cipher cmd to
+ * scm_call.
+ *
+ * @algorithm - specifies cipher algorithm
+ * @operation - specifies encryption or decryption.
+ * @mode - specifies cipher mode.
+ * @key_phys_addr - physical address for key buffer.
+ * @key_size - key size in bytes.
+ * @plain_text_phys_addr - physical address for plain text buffer.
+ * @plain_text_size - size of plain text in bytes.
+ * @cipher_text_phys_addr - physical address for cipher text buffer.
+ * @cipher_text_size - cipher text size in bytes.
+ * @init_vector_phys_addr - physical address for init vector buffer.
+ * @init_vector_size - size of initialization vector in bytes.
+ */
+struct smcmod_cipher_scm_req {
+ uint32_t algorithm;
+ uint32_t operation;
+ uint32_t mode;
+ uint32_t key_phys_addr;
+ uint32_t key_size;
+ uint32_t plain_text_phys_addr;
+ uint32_t plain_text_size;
+ uint32_t cipher_text_phys_addr;
+ uint32_t cipher_text_size;
+ uint32_t init_vector_phys_addr;
+ uint32_t init_vector_size;
+};
+
+/**
+ * struct smcmod_msg_digest_scm_req - structure for sending message digest
+ * to scm_call.
+ *
+ * @algorithm - specifies the cipher algorithm.
+ * @key_phys_addr - physical address of key buffer.
+ * @key_size - hash key size in bytes.
+ * @input_phys_addr - physical address of input buffer.
+ * @input_size - input data size in bytes.
+ * @output_phys_addr - physical address of output buffer.
+ * @output_size - size of output buffer in bytes.
+ * @verify - indicates whether to verify the hash value.
+ */
+struct smcmod_msg_digest_scm_req {
+ uint32_t algorithm;
+ uint32_t key_phys_addr;
+ uint32_t key_size;
+ uint32_t input_phys_addr;
+ uint32_t input_size;
+ uint32_t output_phys_addr;
+ uint32_t output_size;
+ uint8_t verify;
+} __packed;
+
+static int smcmod_ion_fd_to_phys(int32_t fd, struct ion_client *ion_clientp,
+ struct ion_handle **ion_handlep, uint32_t *phys_addrp, size_t *sizep)
+{
+ int ret = 0;
+
+ /* sanity check args */
+ if ((fd < 0) || IS_ERR_OR_NULL(ion_clientp) ||
+ IS_ERR_OR_NULL(ion_handlep) || IS_ERR_OR_NULL(phys_addrp) ||
+ IS_ERR_OR_NULL(sizep))
+ return -EINVAL;
+
+ /* import the buffer fd */
+ *ion_handlep = ion_import_dma_buf(ion_clientp, fd);
+
+ /* sanity check the handle */
+ if (IS_ERR_OR_NULL(*ion_handlep))
+ return -EINVAL;
+
+ /* get the physical address */
+ ret = ion_phys(ion_clientp, *ion_handlep, (ion_phys_addr_t *)phys_addrp,
+ sizep);
+
+ return ret;
+}
+
+static int smcmod_send_buf_cmd(struct smcmod_buf_req *reqp)
+{
+ int ret = 0;
+ struct ion_client *ion_clientp = NULL;
+ struct ion_handle *ion_cmd_handlep = NULL;
+ struct ion_handle *ion_resp_handlep = NULL;
+ void *cmd_vaddrp = NULL;
+ void *resp_vaddrp = NULL;
+ unsigned long cmd_buf_size = 0;
+ unsigned long resp_buf_size = 0;
+
+ /* sanity check the argument */
+ if (IS_ERR_OR_NULL(reqp))
+ return -EINVAL;
+
+ /* sanity check the fds */
+ if (reqp->ion_cmd_fd < 0)
+ return -EINVAL;
+
+ /* create an ion client */
+ ion_clientp = msm_ion_client_create(UINT_MAX, "smcmod");
+
+ /* check for errors */
+ if (IS_ERR_OR_NULL(ion_clientp))
+ return -EINVAL;
+
+ /* import the command buffer fd */
+ ion_cmd_handlep = ion_import_dma_buf(ion_clientp, reqp->ion_cmd_fd);
+
+ /* sanity check the handle */
+ if (IS_ERR_OR_NULL(ion_cmd_handlep)) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* retrieve the size of the buffer */
+ if (ion_handle_get_size(ion_clientp, ion_cmd_handlep,
+ &cmd_buf_size) < 0) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* ensure that the command buffer size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->cmd_len > cmd_buf_size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* map the area to get a virtual address */
+ cmd_vaddrp = ion_map_kernel(ion_clientp, ion_cmd_handlep);
+
+ /* sanity check the address */
+ if (IS_ERR_OR_NULL(cmd_vaddrp)) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* check if there is a response buffer */
+ if (reqp->ion_resp_fd >= 0) {
+ /* import the handle */
+ ion_resp_handlep =
+ ion_import_dma_buf(ion_clientp, reqp->ion_resp_fd);
+
+ /* sanity check the handle */
+ if (IS_ERR_OR_NULL(ion_resp_handlep)) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* retrieve the size of the buffer */
+ if (ion_handle_get_size(ion_clientp, ion_resp_handlep,
+ &resp_buf_size) < 0) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* ensure that the command buffer size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->resp_len > resp_buf_size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* map the area to get a virtual address */
+ resp_vaddrp = ion_map_kernel(ion_clientp, ion_resp_handlep);
+
+ /* sanity check the address */
+ if (IS_ERR_OR_NULL(resp_vaddrp)) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+ }
+
+ /* No need to flush the cache lines for the command buffer here,
+ * because the buffer will be flushed by scm_call.
+ */
+
+ /* call scm function to switch to secure world */
+ reqp->return_val = scm_call(reqp->service_id, reqp->command_id,
+ cmd_vaddrp, reqp->cmd_len, resp_vaddrp, reqp->resp_len);
+
+ /* The cache lines for the response buffer have already been
+ * invalidated by scm_call before returning.
+ */
+
+buf_cleanup:
+ /* if the client and handle(s) are valid, free them */
+ if (!IS_ERR_OR_NULL(ion_clientp)) {
+ if (!IS_ERR_OR_NULL(ion_cmd_handlep)) {
+ if (!IS_ERR_OR_NULL(cmd_vaddrp))
+ ion_unmap_kernel(ion_clientp, ion_cmd_handlep);
+ ion_free(ion_clientp, ion_cmd_handlep);
+ }
+
+ if (!IS_ERR_OR_NULL(ion_resp_handlep)) {
+ if (!IS_ERR_OR_NULL(resp_vaddrp))
+ ion_unmap_kernel(ion_clientp, ion_resp_handlep);
+ ion_free(ion_clientp, ion_resp_handlep);
+ }
+
+ ion_client_destroy(ion_clientp);
+ }
+
+ return ret;
+}
+
+static int smcmod_send_cipher_cmd(struct smcmod_cipher_req *reqp)
+{
+ int ret = 0;
+ struct smcmod_cipher_scm_req scm_req;
+ struct ion_client *ion_clientp = NULL;
+ struct ion_handle *ion_key_handlep = NULL;
+ struct ion_handle *ion_plain_handlep = NULL;
+ struct ion_handle *ion_cipher_handlep = NULL;
+ struct ion_handle *ion_iv_handlep = NULL;
+ size_t size = 0;
+
+ if (IS_ERR_OR_NULL(reqp))
+ return -EINVAL;
+
+ /* sanity check the fds */
+ if ((reqp->ion_plain_text_fd < 0) ||
+ (reqp->ion_cipher_text_fd < 0) ||
+ (reqp->ion_init_vector_fd < 0))
+ return -EINVAL;
+
+ /* create an ion client */
+ ion_clientp = msm_ion_client_create(UINT_MAX, "smcmod");
+
+ /* check for errors */
+ if (IS_ERR_OR_NULL(ion_clientp))
+ return -EINVAL;
+
+ /* fill in the scm request structure */
+ scm_req.algorithm = reqp->algorithm;
+ scm_req.operation = reqp->operation;
+ scm_req.mode = reqp->mode;
+ scm_req.key_phys_addr = 0;
+ scm_req.key_size = reqp->key_size;
+ scm_req.plain_text_size = reqp->plain_text_size;
+ scm_req.cipher_text_size = reqp->cipher_text_size;
+ scm_req.init_vector_size = reqp->init_vector_size;
+
+ if (!reqp->key_is_null) {
+ /* import the key buffer and get the physical address */
+ ret = smcmod_ion_fd_to_phys(reqp->ion_key_fd, ion_clientp,
+ &ion_key_handlep, &scm_req.key_phys_addr, &size);
+ if (ret < 0)
+ goto buf_cleanup;
+
+ /* ensure that the key size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->key_size > size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+ }
+
+ /* import the plain text buffer and get the physical address */
+ ret = smcmod_ion_fd_to_phys(reqp->ion_plain_text_fd, ion_clientp,
+ &ion_plain_handlep, &scm_req.plain_text_phys_addr, &size);
+
+ if (ret < 0)
+ goto buf_cleanup;
+
+ /* ensure that the plain text size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->plain_text_size > size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* import the cipher text buffer and get the physical address */
+ ret = smcmod_ion_fd_to_phys(reqp->ion_cipher_text_fd, ion_clientp,
+ &ion_cipher_handlep, &scm_req.cipher_text_phys_addr, &size);
+ if (ret < 0)
+ goto buf_cleanup;
+
+ /* ensure that the cipher text size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->cipher_text_size > size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* import the init vector buffer and get the physical address */
+ ret = smcmod_ion_fd_to_phys(reqp->ion_init_vector_fd, ion_clientp,
+ &ion_iv_handlep, &scm_req.init_vector_phys_addr, &size);
+ if (ret < 0)
+ goto buf_cleanup;
+
+ /* ensure that the init vector size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->init_vector_size > size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* Only the scm_req structure will be flushed by scm_call,
+ * so we must flush the cache for the input ion buffers here.
+ */
+ msm_ion_do_cache_op(ion_clientp, ion_key_handlep, NULL,
+ scm_req.key_size, ION_IOC_CLEAN_CACHES);
+ msm_ion_do_cache_op(ion_clientp, ion_iv_handlep, NULL,
+ scm_req.init_vector_size, ION_IOC_CLEAN_CACHES);
+
+ /* For decrypt, cipher text is input, otherwise it's plain text. */
+ if (reqp->operation)
+ msm_ion_do_cache_op(ion_clientp, ion_cipher_handlep, NULL,
+ scm_req.cipher_text_size, ION_IOC_CLEAN_CACHES);
+ else
+ msm_ion_do_cache_op(ion_clientp, ion_plain_handlep, NULL,
+ scm_req.plain_text_size, ION_IOC_CLEAN_CACHES);
+
+ /* call scm function to switch to secure world */
+ reqp->return_val = scm_call(SMCMOD_SVC_CRYPTO,
+ SMCMOD_CRYPTO_CMD_CIPHER, &scm_req,
+ sizeof(scm_req), NULL, 0);
+
+ /* Invalidate the output buffer, since it's not done by scm_call */
+
+ /* for decrypt, plain text is the output, otherwise it's cipher text */
+ if (reqp->operation)
+ msm_ion_do_cache_op(ion_clientp, ion_plain_handlep, NULL,
+ scm_req.plain_text_size, ION_IOC_INV_CACHES);
+ else
+ msm_ion_do_cache_op(ion_clientp, ion_cipher_handlep, NULL,
+ scm_req.cipher_text_size, ION_IOC_INV_CACHES);
+
+buf_cleanup:
+ /* if the client and handles are valid, free them */
+ if (!IS_ERR_OR_NULL(ion_clientp)) {
+ if (!IS_ERR_OR_NULL(ion_key_handlep))
+ ion_free(ion_clientp, ion_key_handlep);
+
+ if (!IS_ERR_OR_NULL(ion_plain_handlep))
+ ion_free(ion_clientp, ion_plain_handlep);
+
+ if (!IS_ERR_OR_NULL(ion_cipher_handlep))
+ ion_free(ion_clientp, ion_cipher_handlep);
+
+ if (!IS_ERR_OR_NULL(ion_iv_handlep))
+ ion_free(ion_clientp, ion_iv_handlep);
+
+ ion_client_destroy(ion_clientp);
+ }
+
+ return ret;
+}
+static int smcmod_send_msg_digest_cmd(struct smcmod_msg_digest_req *reqp)
+{
+ int ret = 0;
+ struct smcmod_msg_digest_scm_req scm_req;
+ struct ion_client *ion_clientp = NULL;
+ struct ion_handle *ion_key_handlep = NULL;
+ struct ion_handle *ion_input_handlep = NULL;
+ struct ion_handle *ion_output_handlep = NULL;
+ size_t size = 0;
+
+ if (IS_ERR_OR_NULL(reqp))
+ return -EINVAL;
+
+ /* sanity check the fds */
+ if ((reqp->ion_input_fd < 0) || (reqp->ion_output_fd < 0))
+ return -EINVAL;
+
+ /* create an ion client */
+ ion_clientp = msm_ion_client_create(UINT_MAX, "smcmod");
+
+ /* check for errors */
+ if (IS_ERR_OR_NULL(ion_clientp))
+ return -EINVAL;
+
+ /* fill in the scm request structure */
+ scm_req.algorithm = reqp->algorithm;
+ scm_req.key_phys_addr = 0;
+ scm_req.key_size = reqp->key_size;
+ scm_req.input_size = reqp->input_size;
+ scm_req.output_size = reqp->output_size;
+ scm_req.verify = 0;
+
+ if (!reqp->key_is_null) {
+ /* import the key buffer and get the physical address */
+ ret = smcmod_ion_fd_to_phys(reqp->ion_key_fd, ion_clientp,
+ &ion_key_handlep, &scm_req.key_phys_addr, &size);
+ if (ret < 0)
+ goto buf_cleanup;
+
+ /* ensure that the key size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->key_size > size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+ }
+
+ /* import the input buffer and get the physical address */
+ ret = smcmod_ion_fd_to_phys(reqp->ion_input_fd, ion_clientp,
+ &ion_input_handlep, &scm_req.input_phys_addr, &size);
+ if (ret < 0)
+ goto buf_cleanup;
+
+ /* ensure that the input size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->input_size > size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* import the output buffer and get the physical address */
+ ret = smcmod_ion_fd_to_phys(reqp->ion_output_fd, ion_clientp,
+ &ion_output_handlep, &scm_req.output_phys_addr, &size);
+ if (ret < 0)
+ goto buf_cleanup;
+
+ /* ensure that the output size is not
+ * greater than the size of the buffer.
+ */
+ if (reqp->output_size > size) {
+ ret = -EINVAL;
+ goto buf_cleanup;
+ }
+
+ /* Only the scm_req structure will be flushed by scm_call,
+ * so we must flush the cache for the input ion buffers here.
+ */
+ msm_ion_do_cache_op(ion_clientp, ion_key_handlep, NULL,
+ scm_req.key_size, ION_IOC_CLEAN_CACHES);
+ msm_ion_do_cache_op(ion_clientp, ion_input_handlep, NULL,
+ scm_req.input_size, ION_IOC_CLEAN_CACHES);
+
+ /* call scm function to switch to secure world */
+ if (reqp->fixed_block)
+ reqp->return_val = scm_call(SMCMOD_SVC_CRYPTO,
+ SMCMOD_CRYPTO_CMD_MSG_DIGEST_FIXED,
+ &scm_req,
+ sizeof(scm_req),
+ NULL, 0);
+ else
+ reqp->return_val = scm_call(SMCMOD_SVC_CRYPTO,
+ SMCMOD_CRYPTO_CMD_MSG_DIGEST,
+ &scm_req,
+ sizeof(scm_req),
+ NULL, 0);
+
+ /* Invalidate the output buffer, since it's not done by scm_call */
+ msm_ion_do_cache_op(ion_clientp, ion_output_handlep, NULL,
+ scm_req.output_size, ION_IOC_INV_CACHES);
+
+buf_cleanup:
+ /* if the client and handles are valid, free them */
+ if (!IS_ERR_OR_NULL(ion_clientp)) {
+ if (!IS_ERR_OR_NULL(ion_key_handlep))
+ ion_free(ion_clientp, ion_key_handlep);
+
+ if (!IS_ERR_OR_NULL(ion_input_handlep))
+ ion_free(ion_clientp, ion_input_handlep);
+
+ if (!IS_ERR_OR_NULL(ion_output_handlep))
+ ion_free(ion_clientp, ion_output_handlep);
+
+ ion_client_destroy(ion_clientp);
+ }
+
+ return ret;
+}
+
+static int smcmod_send_dec_cmd(struct smcmod_decrypt_req *reqp)
+{
+ struct ion_client *ion_clientp;
+ struct ion_handle *ion_handlep = NULL;
+ int ion_fd;
+ int ret;
+ u32 pa;
+ size_t size;
+ struct {
+ u32 args[4];
+ } req;
+ struct {
+ u32 args[3];
+ } rsp;
+
+ ion_clientp = msm_ion_client_create(UINT_MAX, "smcmod");
+ if (IS_ERR_OR_NULL(ion_clientp))
+ return PTR_ERR(ion_clientp);
+
+ switch (reqp->operation) {
+ case SMCMOD_DECRYPT_REQ_OP_METADATA: {
+ ion_fd = reqp->request.metadata.ion_fd;
+ ret = smcmod_ion_fd_to_phys(ion_fd, ion_clientp,
+ &ion_handlep, &pa, &size);
+ if (ret)
+ goto error;
+
+ req.args[0] = reqp->request.metadata.len;
+ req.args[1] = pa;
+ break;
+ }
+ case SMCMOD_DECRYPT_REQ_OP_IMG_FRAG: {
+ ion_fd = reqp->request.img_frag.ion_fd;
+ ret = smcmod_ion_fd_to_phys(ion_fd, ion_clientp,
+ &ion_handlep, &pa, &size);
+ if (ret)
+ goto error;
+
+ req.args[0] = reqp->request.img_frag.ctx_id;
+ req.args[1] = reqp->request.img_frag.last_frag;
+ req.args[2] = reqp->request.img_frag.frag_len;
+ req.args[3] = pa + reqp->request.img_frag.offset;
+ break;
+ }
+ default:
+ ret = -EINVAL;
+ goto error;
+ }
+
+ /*
+ * scm_call does cache maintenance over request and response buffers.
+ * The userspace must flush/invalidate ion input/output buffers itself.
+ */
+
+ ret = scm_call(reqp->service_id, reqp->command_id,
+ &req, sizeof(req), &rsp, sizeof(rsp));
+ if (ret)
+ goto error;
+
+ switch (reqp->operation) {
+ case SMCMOD_DECRYPT_REQ_OP_METADATA:
+ reqp->response.metadata.status = rsp.args[0];
+ reqp->response.metadata.ctx_id = rsp.args[1];
+ reqp->response.metadata.end_offset = rsp.args[2] - pa;
+ break;
+ case SMCMOD_DECRYPT_REQ_OP_IMG_FRAG: {
+ reqp->response.img_frag.status = rsp.args[0];
+ break;
+ }
+ default:
+ break;
+ }
+
+error:
+ if (!IS_ERR_OR_NULL(ion_clientp)) {
+ if (!IS_ERR_OR_NULL(ion_handlep))
+ ion_free(ion_clientp, ion_handlep);
+ ion_client_destroy(ion_clientp);
+ }
+ return ret;
+}
+
+static int smcmod_ioctl_check(unsigned cmd)
+{
+ switch (cmd) {
+ case SMCMOD_IOCTL_SEND_REG_CMD:
+ case SMCMOD_IOCTL_SEND_BUF_CMD:
+ case SMCMOD_IOCTL_SEND_CIPHER_CMD:
+ case SMCMOD_IOCTL_SEND_MSG_DIGEST_CMD:
+ case SMCMOD_IOCTL_GET_VERSION:
+ if (!cpu_is_fsm9xxx())
+ return -EINVAL;
+ break;
+ case SMCMOD_IOCTL_SEND_DECRYPT_CMD:
+ if (!cpu_is_msm8226())
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static long smcmod_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int ret = 0;
+
+ /* sanity check */
+ if (!argp)
+ return -EINVAL;
+
+ /*
+ * The SMC instruction should only be initiated by one process
+ * at a time, hence the critical section here. Note that this
+ * does not prevent user space from modifying the
+ * allocated buffer contents. Extra steps are needed to
+ * prevent that from happening.
+ */
+ mutex_lock(&ioctl_lock);
+
+ ret = smcmod_ioctl_check(cmd);
+ if (ret)
+ goto cleanup;
+
+ switch (cmd) {
+ case SMCMOD_IOCTL_SEND_REG_CMD:
+ {
+ struct smcmod_reg_req req;
+
+ /* copy struct from user */
+ if (copy_from_user((void *)&req, argp, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ /* call the correct scm function to switch to secure
+ * world
+ */
+ if (req.num_args == 1) {
+ req.return_val =
+ scm_call_atomic1(req.service_id,
+ req.command_id, req.args[0]);
+ } else if (req.num_args == 2) {
+ req.return_val =
+ scm_call_atomic2(req.service_id,
+ req.command_id, req.args[0],
+ req.args[1]);
+ } else {
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ /* copy result back to user */
+ if (copy_to_user(argp, (void *)&req, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ }
+ break;
+
+ /* This is an example of how to pass buffers to/from the secure
+ * side using the ion driver.
+ */
+ case SMCMOD_IOCTL_SEND_BUF_CMD:
+ {
+ struct smcmod_buf_req req;
+
+ /* copy struct from user */
+ if (copy_from_user((void *)&req, argp, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ /* send the command */
+ ret = smcmod_send_buf_cmd(&req);
+ if (ret < 0)
+ goto cleanup;
+
+ /* copy result back to user */
+ if (copy_to_user(argp, (void *)&req, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ }
+ break;
+
+ case SMCMOD_IOCTL_SEND_CIPHER_CMD:
+ {
+ struct smcmod_cipher_req req;
+
+ /* copy struct from user */
+ if (copy_from_user((void *)&req, argp, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ ret = smcmod_send_cipher_cmd(&req);
+ if (ret < 0)
+ goto cleanup;
+
+ /* copy result back to user */
+ if (copy_to_user(argp, (void *)&req, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ }
+ break;
+
+ case SMCMOD_IOCTL_SEND_MSG_DIGEST_CMD:
+ {
+ struct smcmod_msg_digest_req req;
+
+ /* copy struct from user */
+ if (copy_from_user((void *)&req, argp, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ ret = smcmod_send_msg_digest_cmd(&req);
+ if (ret < 0)
+ goto cleanup;
+
+ /* copy result back to user */
+ if (copy_to_user(argp, (void *)&req, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ }
+ break;
+
+ case SMCMOD_IOCTL_GET_VERSION:
+ {
+ uint32_t req;
+
+ /* call scm function to switch to secure world */
+ req = scm_get_version();
+
+ /* copy result back to user */
+ if (copy_to_user(argp, (void *)&req, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ }
+ break;
+
+ case SMCMOD_IOCTL_SEND_DECRYPT_CMD:
+ {
+ struct smcmod_decrypt_req req;
+
+ if (copy_from_user((void *)&req, argp, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+
+ ret = smcmod_send_dec_cmd(&req);
+ if (ret < 0)
+ goto cleanup;
+
+ if (copy_to_user(argp, (void *)&req, sizeof(req))) {
+ ret = -EFAULT;
+ goto cleanup;
+ }
+ }
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+cleanup:
+ mutex_unlock(&ioctl_lock);
+ return ret;
+}
+
+static int smcmod_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int smcmod_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static const struct file_operations smcmod_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = smcmod_ioctl,
+ .open = smcmod_open,
+ .release = smcmod_release,
+};
+
+static struct miscdevice smcmod_misc_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = SMCMOD_DEV,
+ .fops = &smcmod_fops
+};
+
+static int __init smcmod_init(void)
+{
+ return misc_register(&smcmod_misc_dev);
+}
+
+static void __exit smcmod_exit(void)
+{
+ misc_deregister(&smcmod_misc_dev);
+}
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. SMC Module");
+MODULE_LICENSE("GPL v2");
+
+module_init(smcmod_init);
+module_exit(smcmod_exit);
diff --git a/arch/arm/mach-msm/test-lpm.c b/arch/arm/mach-msm/test-lpm.c
new file mode 100644
index 000000000000..ac38ff1d0ee0
--- /dev/null
+++ b/arch/arm/mach-msm/test-lpm.c
@@ -0,0 +1,692 @@
+/* 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+
+#if defined(CONFIG_MSM_RPM_SMD)
+#include "lpm_resources.h"
+#endif
+#include "timer.h"
+#include "test-lpm.h"
+
+#define LPM_STATS_RESET "reset"
+#define LPM_TEST_ALL_LEVELS "lpm"
+#define LPM_TEST_LATENCIES "latency"
+#define LPM_TEST_CLEAR "clear"
+#define BUF_SIZE 200
+#define STAT_BUF_EXTRA_SIZE 500
+#define WAIT_FOR_XO 1
+#define COMM_BUF_SIZE 15
+#define INPUT_COUNT_BUF 10
+#define LPM_DEFAULT_CPU 0
+
+#define SNPRINTF(buf, size, format, ...) \
+{ \
+ if (size > 0) { \
+ int ret; \
+ ret = snprintf(buf, size, format, ## __VA_ARGS__); \
+ if (ret > size) { \
+ buf += size; \
+ size = 0; \
+ } else { \
+ buf += ret; \
+ size -= ret; \
+ } \
+ } \
+} \
+
+static DEFINE_MUTEX(lpm_stats_mutex);
+
+struct lpm_level_stat {
+ char level_name[BUF_SIZE];
+ int64_t min_time;
+ int64_t max_time;
+ int64_t avg_time;
+ int64_t exit_early;
+ int64_t count;
+ unsigned long min_threshold;
+ uint32_t kernel_sleep_time;
+ bool entered;
+};
+
+static DEFINE_PER_CPU(struct lpm_level_stat *, lpm_levels);
+
+static struct dentry *lpm_stat;
+static struct dentry *lpm_ext_comm;
+static struct msm_rpmrs_level *lpm_supp_level;
+static int lpm_level_count;
+static int lpm_level_iter;
+static bool msm_lpm_use_qtimer;
+static unsigned long lpm_sleep_time;
+static bool lpm_latency_test;
+
+static unsigned int timer_interval = 5000;
+module_param_named(lpm_timer_interval_msec, timer_interval, uint,
+ S_IRUGO | S_IWUSR | S_IWGRP);
+
+static unsigned int latency_test_interval = 50;
+module_param_named(lpm_latency_timer_interval_usec, latency_test_interval, uint,
+ S_IRUGO | S_IWUSR | S_IWGRP);
+
+static unsigned int cpu_to_debug = LPM_DEFAULT_CPU;
+static int lpm_cpu_update(const char *val, const struct kernel_param *kp)
+{
+ int ret = 0;
+ unsigned int debug_val;
+
+ ret = kstrtouint(val, 10, &debug_val);
+ if ((ret < 0) || (debug_val >= num_possible_cpus()))
+ return -EINVAL;
+ cpu_to_debug = debug_val;
+ return ret;
+}
+
+static struct kernel_param_ops cpu_debug_events = {
+ .set = lpm_cpu_update,
+};
+
+module_param_cb(cpu_to_debug, &cpu_debug_events, &cpu_to_debug,
+ S_IRUGO | S_IWUSR | S_IWGRP);
+
+static void lpm_populate_name(struct lpm_level_stat *stat,
+ struct msm_rpmrs_level *supp)
+{
+ char nm[BUF_SIZE] = {0};
+ char default_buf[20];
+
+ switch (supp->sleep_mode) {
+ case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
+ strlcat(nm, "WFI ", BUF_SIZE);
+ break;
+ case MSM_PM_SLEEP_MODE_RETENTION:
+ strlcat(nm, "Retention ", BUF_SIZE);
+ break;
+ case MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE:
+ strlcat(nm, "Standalone Power collapse ", BUF_SIZE);
+ break;
+ case MSM_PM_SLEEP_MODE_POWER_COLLAPSE:
+ strlcat(nm, "Idle Power collapse ", BUF_SIZE);
+ break;
+ case MSM_PM_MODE_POWER_COLLASE_SUSPEND:
+ strlcat(nm, "Suspend Power collapse", BUF_SIZE);
+ default:
+ strlcat(nm, "Invalid Mode ", BUF_SIZE);
+ break;
+ }
+
+ switch (msm_pm_get_pxo(&(supp->rs_limits))) {
+ case MSM_PM(PXO_OFF):
+ strlcat(nm, "XO: OFF ", BUF_SIZE);
+ break;
+ case MSM_PM(PXO_ON):
+ strlcat(nm, "XO: ON ", BUF_SIZE);
+ break;
+ default:
+ snprintf(default_buf, sizeof(default_buf),
+ "XO : %d ", msm_pm_get_pxo(&(supp->rs_limits)));
+ strlcat(nm, default_buf , BUF_SIZE);
+ break;
+ }
+
+ switch (msm_pm_get_l2_cache(&(supp->rs_limits))) {
+ case MSM_PM(L2_CACHE_HSFS_OPEN):
+ strlcat(nm, "L2: HSFS ", BUF_SIZE);
+ break;
+ case MSM_PM(L2_CACHE_GDHS):
+ strlcat(nm, "L2: GDHS ", BUF_SIZE);
+ break;
+ case MSM_PM(L2_CACHE_RETENTION):
+ strlcat(nm, "L2: Retention ", BUF_SIZE);
+ break;
+ case MSM_PM(L2_CACHE_ACTIVE):
+ strlcat(nm, "L2: Active ", BUF_SIZE);
+ break;
+ default:
+ snprintf(default_buf, sizeof(default_buf),
+ "L2 : %d ", msm_pm_get_l2_cache(&(supp->rs_limits)));
+ strlcat(nm, default_buf , BUF_SIZE);
+ break;
+ }
+
+ snprintf(default_buf, sizeof(default_buf),
+ "Vdd_mem : %d ", msm_pm_get_vdd_mem(&(supp->rs_limits)));
+ strlcat(nm, default_buf , BUF_SIZE);
+
+ snprintf(default_buf, sizeof(default_buf),
+ "Vdd_dig : %d ", msm_pm_get_vdd_dig(&(supp->rs_limits)));
+ strlcat(nm, default_buf , BUF_SIZE);
+
+ strlcpy(stat->level_name, nm, strnlen(nm, BUF_SIZE));
+}
+
+static int64_t msm_lpm_get_time(void)
+{
+ if (msm_lpm_use_qtimer)
+ return ktime_to_ns(ktime_get());
+
+ return msm_timer_get_sclk_time(NULL);
+}
+
+static bool lpm_get_level(void *v, unsigned int *ct)
+{
+ bool ret = false;
+ int it;
+ struct msm_rpmrs_level *level_enter;
+
+ level_enter = container_of(((struct msm_lpm_sleep_data *)v)->limits,
+ struct msm_rpmrs_level, rs_limits);
+ if (level_enter) {
+ for (it = 0; it < lpm_level_count; it++)
+ if (!memcmp(level_enter , lpm_supp_level + it,
+ sizeof(struct msm_rpmrs_level))) {
+ *ct = it;
+ ret = true;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int lpm_callback(struct notifier_block *self, unsigned long cmd,
+ void *sleep_data)
+{
+ static int64_t time;
+ unsigned int ct;
+ struct lpm_level_stat *stats;
+ stats = per_cpu(lpm_levels, cpu_to_debug);
+ /* Update the stats and get the start/stop time */
+ if (cmd == MSM_LPM_STATE_ENTER && !lpm_latency_test) {
+ time = msm_lpm_get_time();
+ stats[lpm_level_iter].entered = true;
+ } else if ((cmd == MSM_LPM_STATE_EXIT) && (time)
+ && (!lpm_latency_test)) {
+ int64_t time1;
+ time1 = msm_lpm_get_time();
+ time = time1 - time;
+
+ if ((time < stats[lpm_level_iter].min_time) ||
+ (!stats[lpm_level_iter].min_time))
+ stats[lpm_level_iter].min_time = time;
+
+ if (time > stats[lpm_level_iter].max_time)
+ stats[lpm_level_iter].max_time = time;
+
+ time1 = stats[lpm_level_iter].avg_time *
+ stats[lpm_level_iter].count + time;
+ do_div(time1, ++(stats[lpm_level_iter].count));
+
+ stats[lpm_level_iter].avg_time = time1;
+ do_div(time, NSEC_PER_USEC);
+ if (time < lpm_supp_level[lpm_level_iter].
+ time_overhead_us)
+ stats[lpm_level_iter].exit_early++;
+ time = 0;
+ } else if (cmd == MSM_LPM_STATE_ENTER && lpm_latency_test) {
+
+ struct msm_lpm_sleep_data *data = sleep_data;
+ if ((lpm_get_level(sleep_data, &ct)) &&
+ (stats[ct].min_threshold == 0) &&
+ data->kernel_sleep <= lpm_sleep_time) {
+
+ stats[ct].min_threshold = lpm_sleep_time;
+ stats[ct].kernel_sleep_time =
+ data->kernel_sleep;
+ }
+ }
+ return 0;
+}
+
+static struct notifier_block lpm_idle_nb = {
+ .notifier_call = lpm_callback,
+};
+
+static void lpm_test_initiate(int lpm_level_test)
+{
+ int test_ret;
+
+ /* This will communicate to 'stat' debugfs to skip latency printing*/
+ lpm_sleep_time = 0;
+ lpm_latency_test = false;
+ /* Unregister any infinitely registered level*/
+ msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+
+ /* Register/Unregister for Notification */
+ while (lpm_level_iter < lpm_level_count) {
+ test_ret = msm_lpm_register_notifier(cpu_to_debug,
+ lpm_level_iter, &lpm_idle_nb, false);
+ if (test_ret < 0) {
+ pr_err("%s: Registering notifier failed\n", __func__);
+ return;
+ }
+ if (!timer_interval)
+ break;
+ msleep(timer_interval);
+ msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+ if (lpm_level_test == lpm_level_count)
+ lpm_level_iter++;
+ else
+ break;
+ }
+}
+
+static void lpm_latency_test_initiate(unsigned long max_time)
+{
+ int test_ret;
+ lpm_latency_test = true;
+ lpm_sleep_time = latency_test_interval;
+
+ msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+ if (max_time > lpm_sleep_time) {
+
+ do {
+ test_ret = msm_lpm_register_notifier(cpu_to_debug,
+ lpm_level_count + 1,
+ &lpm_idle_nb, true);
+ if (test_ret) {
+ pr_err("%s: Registering notifier failed\n",
+ __func__);
+ return;
+ }
+ usleep(lpm_sleep_time);
+ /*Unregister to ensure that we dont update the latency
+ during the timer value transistion*/
+ msm_lpm_unregister_notifier(cpu_to_debug,
+ &lpm_idle_nb);
+ lpm_sleep_time += latency_test_interval;
+ } while (lpm_sleep_time < max_time);
+ } else
+ pr_err("%s: Invalid time interval specified\n", __func__);
+
+ lpm_latency_test = false;
+}
+
+static ssize_t lpm_test_comm_read(struct file *fp, char __user *user_buffer,
+ size_t buffer_length, loff_t *position)
+{
+ int i = 0;
+ int count = buffer_length;
+ int alloc_size = 100 * lpm_level_count;
+ char *temp_buf;
+ char *comm_buf;
+ ssize_t ret;
+
+ comm_buf = kzalloc(alloc_size, GFP_KERNEL);
+ if (!comm_buf) {
+ pr_err("%s:Memory alloc failed\n", __func__);
+ ret = 0;
+ goto com_read_failed;
+ }
+ temp_buf = comm_buf;
+
+ SNPRINTF(temp_buf, count, "Low power modes available:\n");
+
+ for (i = 0; i < lpm_level_count; i++)
+ SNPRINTF(temp_buf, count, "%d. %s\n", i,
+ per_cpu(lpm_levels, cpu_to_debug)[i].level_name);
+
+ SNPRINTF(temp_buf, count, "%d. MSM test all lpm\n", i++);
+ SNPRINTF(temp_buf, count, "%d. MSM determine latency\n", i);
+
+ ret = simple_read_from_buffer(user_buffer, buffer_length - count,
+ position, comm_buf, alloc_size);
+ kfree(comm_buf);
+
+com_read_failed:
+ return ret;
+}
+
+char *trimspaces(char *time_buf)
+{
+ int len;
+ char *tail;
+
+ len = strnlen(time_buf, INPUT_COUNT_BUF);
+ tail = time_buf + len;
+ while (isspace(*time_buf) && (time_buf != tail))
+ time_buf++;
+ if (time_buf == tail) {
+ time_buf = NULL;
+ goto exit_trim_spaces;
+ }
+ len = strnlen(time_buf, INPUT_COUNT_BUF);
+ tail = time_buf + len - 1;
+ while (isspace(*tail) && tail != time_buf) {
+ *tail = '\0';
+ tail--;
+ }
+exit_trim_spaces:
+ return time_buf;
+}
+
+static ssize_t lpm_test_comm_write(struct file *fp, const char __user
+ *user_buffer, size_t count, loff_t *position)
+{
+ ssize_t ret;
+ int str_ret;
+ int lpm_level_test;
+ char *new_ptr;
+ char *comm_buf;
+
+ comm_buf = kzalloc(COMM_BUF_SIZE, GFP_KERNEL);
+ if (!comm_buf) {
+ pr_err("\'%s\': kzalloc failed\n", __func__);
+ return -EINVAL;
+ }
+
+ memset(comm_buf, '\0', COMM_BUF_SIZE);
+
+ ret = simple_write_to_buffer(comm_buf, COMM_BUF_SIZE, position,
+ user_buffer, count);
+ new_ptr = trimspaces(comm_buf);
+ if (!new_ptr) {
+ pr_err("%s: Test case number input invalid\n", __func__);
+ goto write_com_failed;
+ }
+
+ if (!memcmp(comm_buf, LPM_TEST_ALL_LEVELS,
+ sizeof(LPM_TEST_ALL_LEVELS) - 1)) {
+ lpm_level_test = lpm_level_count;
+ lpm_level_iter = 0;
+ lpm_test_initiate(lpm_level_test);
+ goto write_com_success;
+ } else if (!memcmp(comm_buf, LPM_TEST_LATENCIES,
+ sizeof(LPM_TEST_LATENCIES) - 1)) {
+ lpm_level_test = lpm_level_count + 1;
+ lpm_latency_test_initiate(timer_interval * USEC_PER_MSEC);
+ goto write_com_success;
+ } else if (!memcmp(comm_buf, LPM_TEST_CLEAR,
+ sizeof(LPM_TEST_CLEAR) - 1)) {
+ msm_lpm_unregister_notifier(cpu_to_debug, &lpm_idle_nb);
+ goto write_com_success;
+ }
+
+ str_ret = kstrtoint(new_ptr, 10, &lpm_level_test);
+ if ((str_ret) || (lpm_level_test > (lpm_level_count + 1)) ||
+ (lpm_level_test < 0))
+ goto write_com_failed;
+
+ lpm_level_iter = lpm_level_test;
+ lpm_test_initiate(lpm_level_test);
+ goto write_com_success;
+
+write_com_failed:
+ ret = -EINVAL;
+write_com_success:
+ kfree(comm_buf);
+ return ret;
+}
+
+static ssize_t lpm_test_stat_read(struct file *fp, char __user *user_buffer,
+ size_t buffer_length, loff_t *position)
+{
+ int i = 0;
+ int j = 0;
+ int count = buffer_length;
+ char *stat_buf;
+ char *stat_buf_start;
+ size_t stat_buf_size;
+ ssize_t ret;
+ int64_t min_ns;
+ int64_t max_ns;
+ int64_t avg_ns;
+ uint32_t min_ms;
+ uint32_t max_ms;
+ uint32_t avg_ms;
+
+ stat_buf_size = ((sizeof(struct lpm_level_stat) * lpm_level_count) +
+ STAT_BUF_EXTRA_SIZE);
+ stat_buf = kzalloc(stat_buf_size, GFP_KERNEL);
+ if (!stat_buf) {
+ pr_err("\'%s\': kzalloc failed\n", __func__);
+ return -EINVAL;
+ }
+ stat_buf_start = stat_buf;
+ mutex_lock(&lpm_stats_mutex);
+ memset(stat_buf, '\0', stat_buf_size);
+ SNPRINTF(stat_buf, count, "\n\nStats for CPU: %d\nTotal Levels: %d\n",
+ cpu_to_debug, lpm_level_count);
+ if (!lpm_sleep_time) {
+ SNPRINTF(stat_buf, count, "Level(s) failed: ");
+ for (i = 0 ; i < lpm_level_count; i++) {
+ if (per_cpu(lpm_levels, cpu_to_debug)[i].entered)
+ continue;
+ else {
+ SNPRINTF(stat_buf, count,
+ "\n%d. %s", ++j, per_cpu(lpm_levels,
+ cpu_to_debug)[i].level_name);
+ }
+ }
+ SNPRINTF(stat_buf, count, "\n\nSTATS:");
+ for (i = 0; i < lpm_level_count; i++) {
+ min_ns = per_cpu(lpm_levels, cpu_to_debug)[i].min_time;
+ min_ms = do_div(min_ns, NSEC_PER_MSEC);
+ max_ns = per_cpu(lpm_levels, cpu_to_debug)[i].max_time;
+ max_ms = do_div(max_ns, NSEC_PER_MSEC);
+ avg_ns = per_cpu(lpm_levels, cpu_to_debug)[i].avg_time;
+ avg_ms = do_div(avg_ns, NSEC_PER_MSEC);
+ SNPRINTF(stat_buf, count, "\nLEVEL: %s\n"
+ "Entered : %lld\n"
+ "Early wakeup : %lld\n"
+ "Min Time (mSec): %lld.%06u\n"
+ "Max Time (mSec): %lld.%06u\n"
+ "Avg Time (mSec): %lld.%06u\n",
+ per_cpu(lpm_levels, cpu_to_debug)[i].level_name,
+ per_cpu(lpm_levels, cpu_to_debug)[i].count,
+ per_cpu(lpm_levels, cpu_to_debug)[i].exit_early,
+ min_ns, min_ms,
+ max_ns, max_ms,
+ avg_ns, avg_ms);
+ }
+ } else {
+ for (i = 0; i < lpm_level_count; i++) {
+ SNPRINTF(stat_buf, count, "\nLEVEL: %s\n"
+ "Min Timer value (uSec): %lu\n"
+ "Kernel sleep time (uSec): %u\n",
+ per_cpu(lpm_levels, cpu_to_debug)[i].level_name,
+ per_cpu(lpm_levels, cpu_to_debug)[i].
+ min_threshold,
+ per_cpu(lpm_levels,
+ cpu_to_debug)[i].kernel_sleep_time);
+ }
+ }
+
+ ret = simple_read_from_buffer(user_buffer, buffer_length - count,
+ position, stat_buf_start, stat_buf_size);
+
+ mutex_unlock(&lpm_stats_mutex);
+ kfree(stat_buf_start);
+ return ret;
+}
+
+static ssize_t lpm_test_stat_write(struct file *fp, const char __user
+ *user_buffer, size_t count, loff_t *position)
+{
+ char buf[sizeof(LPM_STATS_RESET)];
+ int ret;
+ int i;
+ struct lpm_level_stat *stats;
+
+ if (count > sizeof(LPM_STATS_RESET)) {
+ ret = -EINVAL;
+ goto write_debug_failed;
+ }
+
+ simple_write_to_buffer(buf, sizeof(LPM_STATS_RESET), position,
+ user_buffer, count);
+
+ if (memcmp(buf, LPM_STATS_RESET, sizeof(LPM_STATS_RESET) - 1)) {
+ ret = -EINVAL;
+ goto write_debug_failed;
+ }
+
+ mutex_lock(&lpm_stats_mutex);
+ stats = per_cpu(lpm_levels, cpu_to_debug);
+ for (i = 0 ; i < lpm_level_count; i++) {
+ stats[i].entered = 0;
+ stats[i].min_time = 0;
+ stats[i].max_time = 0;
+ stats[i].avg_time = 0;
+ stats[i].count = 0;
+ stats[i].exit_early = 0;
+ stats[i].min_threshold = 0;
+ stats[i].kernel_sleep_time = 0;
+ }
+ mutex_unlock(&lpm_stats_mutex);
+ return count;
+write_debug_failed:
+ return ret;
+}
+
+static void lpm_init_rpm_levels(int test_lpm_level_count,
+ struct msm_rpmrs_level *test_levels)
+{
+ int i = 0;
+ unsigned int m_cpu = 0;
+ struct lpm_level_stat *stat_levels = NULL;
+
+ if (test_lpm_level_count < 0)
+ return;
+
+ lpm_level_count = test_lpm_level_count;
+
+ lpm_supp_level = test_levels;
+ for_each_possible_cpu(m_cpu) {
+ stat_levels = kzalloc(sizeof(struct lpm_level_stat) *
+ lpm_level_count, GFP_KERNEL);
+ if (!stat_levels) {
+ for (i = m_cpu - 1; i >= 0; i--)
+ kfree(per_cpu(lpm_levels, i));
+ return;
+ }
+
+ for (i = 0; i < lpm_level_count; i++)
+ lpm_populate_name(&stat_levels[i], &lpm_supp_level[i]);
+
+ per_cpu(lpm_levels, m_cpu) = stat_levels;
+ }
+}
+
+static const struct file_operations fops_stat = {
+ .read = lpm_test_stat_read,
+ .write = lpm_test_stat_write,
+};
+
+static const struct file_operations fops_comm = {
+ .read = lpm_test_comm_read,
+ .write = lpm_test_comm_write,
+};
+
+static int lpm_test_init(int test_lpm_level_count,
+ struct msm_rpmrs_level *test_levels)
+{
+ int filevalue;
+ int lpm_comm;
+ int ret = -EINVAL;
+ struct dentry *parent_dir = NULL;
+
+ parent_dir = debugfs_create_dir("msm_lpm_debug", NULL);
+ if (!parent_dir) {
+ pr_err("%s: debugfs directory creation failed\n",
+ __func__);
+ goto init_err;
+ }
+
+ lpm_stat = debugfs_create_file("stat",
+ S_IRUGO | S_IWUSR | S_IWGRP, parent_dir,
+ &filevalue, &fops_stat);
+ if (!lpm_stat) {
+ pr_err("%s: lpm_stats debugfs creation failed\n",
+ __func__);
+ goto init_err;
+ }
+
+ lpm_ext_comm = debugfs_create_file("comm",
+ S_IRUGO | S_IWUSR | S_IWGRP, parent_dir, &lpm_comm,
+ &fops_comm);
+ if (!lpm_ext_comm) {
+ pr_err("%s: lpm_comm debugfs creation failed\n",
+ __func__);
+ debugfs_remove(lpm_stat);
+ goto init_err;
+ }
+
+ /*Query RPM resources and allocate the data sturctures*/
+ lpm_init_rpm_levels(test_lpm_level_count, test_levels);
+ ret = 0;
+
+init_err:
+ return ret;
+}
+
+static int lpm_test_exit(struct platform_device *pdev)
+{
+ unsigned int m_cpu = 0;
+
+ kfree(lpm_supp_level);
+ for_each_possible_cpu(m_cpu)
+ kfree(per_cpu(lpm_levels, m_cpu));
+ debugfs_remove(lpm_stat);
+ debugfs_remove(lpm_ext_comm);
+ return 0;
+}
+
+static int lpm_test_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct lpm_test_platform_data *pdata;
+ struct msm_rpmrs_level *test_levels;
+ int test_lpm_level_count;
+
+ pdata = pdev->dev.platform_data;
+
+ if (!pdata) {
+ dev_err(dev, "no platform data specified\n");
+ return -EINVAL;
+ }
+
+ test_levels = pdata->msm_lpm_test_levels;
+ test_lpm_level_count = pdata->msm_lpm_test_level_count;
+
+ if (pdata->use_qtimer)
+ msm_lpm_use_qtimer = true;
+
+ lpm_test_init(test_lpm_level_count, test_levels);
+
+ return 0;
+}
+
+static struct platform_driver lpm_test_driver = {
+ .probe = lpm_test_probe,
+ .remove = lpm_test_exit,
+ .driver = {
+ .name = "lpm_test",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init lpm_test_platform_driver_init(void)
+{
+ return platform_driver_register(&lpm_test_driver);
+}
+
+late_initcall(lpm_test_platform_driver_init);
diff --git a/arch/arm/mach-msm/test-lpm.h b/arch/arm/mach-msm/test-lpm.h
new file mode 100644
index 000000000000..1486f88c386e
--- /dev/null
+++ b/arch/arm/mach-msm/test-lpm.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2012, 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 __ARCH_ARM_MACH_MSM_TEST_LPM_H
+#define __ARCH_ARM_MACH_MSM_TEST_LPM_H
+
+struct lpm_test_platform_data {
+ struct msm_rpmrs_level *msm_lpm_test_levels;
+ int msm_lpm_test_level_count;
+ bool use_qtimer;
+};
+#endif
diff --git a/arch/arm/mach-msm/test_qmi_client.c b/arch/arm/mach-msm/test_qmi_client.c
new file mode 100644
index 000000000000..8f77005e1e20
--- /dev/null
+++ b/arch/arm/mach-msm/test_qmi_client.c
@@ -0,0 +1,450 @@
+/* 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 <linux/module.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/debugfs.h>
+#include <linux/qmi_encdec.h>
+
+#include <asm/uaccess.h>
+
+#include <soc/qcom/msm_qmi_interface.h>
+
+#include "kernel_test_service_v01.h"
+
+#define TEST_SERVICE_SVC_ID 0x0000000f
+#define TEST_SERVICE_V1 1
+#define TEST_SERVICE_INS_ID 0
+
+static int test_rep_cnt = 10;
+module_param_named(rep_cnt, test_rep_cnt, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int test_data_sz = 50;
+module_param_named(data_sz, test_data_sz, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int test_clnt_debug_mask;
+module_param_named(debug_mask, test_clnt_debug_mask,
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define D(x...) do { \
+ if (test_clnt_debug_mask) \
+ pr_debug(x); \
+} while (0)
+
+/* Variable to initiate the test through debugfs interface */
+static struct dentry *test_dent;
+
+/* Test client port for IPC Router */
+static struct qmi_handle *test_clnt;
+static int test_clnt_reset;
+
+/* Reader thread to receive responses & indications */
+static void test_clnt_recv_msg(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_recv_msg, test_clnt_recv_msg);
+static void test_clnt_svc_arrive(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_svc_arrive, test_clnt_svc_arrive);
+static void test_clnt_svc_exit(struct work_struct *work);
+static DECLARE_DELAYED_WORK(work_svc_exit, test_clnt_svc_exit);
+static struct workqueue_struct *test_clnt_workqueue;
+
+/* Variable to hold the test result */
+static int test_res;
+
+static unsigned int callback_count;
+static void test_async_resp_cb(struct qmi_handle *handle,
+ unsigned int msg_id, void *msg,
+ void *resp_cb_data, int stat)
+{
+ callback_count++;
+ if (stat == 0)
+ D("%s invoked %d time(s): [RESP_LEN] = %d, [RESP_VALID] = %d",
+ __func__, callback_count,
+ ((struct test_data_resp_msg_v01 *)msg)->data_len,
+ ((struct test_data_resp_msg_v01 *)msg)->data_valid);
+ else if (stat < 0)
+ pr_err("%s: Request Failed [MSG_ID]: %d, [ERR_ID]: %d, [Callback_count]: %d",
+ __func__, msg_id, stat, callback_count);
+
+ kfree(msg);
+ kfree(resp_cb_data);
+}
+
+static int test_qmi_ping_pong_send_sync_msg(void)
+{
+ struct test_ping_req_msg_v01 req;
+ struct test_ping_resp_msg_v01 resp;
+ struct msg_desc req_desc, resp_desc;
+ int rc;
+
+ memcpy(req.ping, "ping", sizeof(req.ping));
+ req.client_name_valid = 0;
+
+ req_desc.max_msg_len = TEST_PING_REQ_MAX_MSG_LEN_V01;
+ req_desc.msg_id = TEST_PING_REQ_MSG_ID_V01;
+ req_desc.ei_array = test_ping_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = TEST_PING_REQ_MAX_MSG_LEN_V01;
+ resp_desc.msg_id = TEST_PING_REQ_MSG_ID_V01;
+ resp_desc.ei_array = test_ping_resp_msg_v01_ei;
+
+ rc = qmi_send_req_wait(test_clnt, &req_desc, &req, sizeof(req),
+ &resp_desc, &resp, sizeof(resp), 0);
+ if (rc < 0) {
+ pr_err("%s: send req failed %d\n", __func__, rc);
+ return rc;
+ }
+
+ D("%s: Received %s response\n", __func__, resp.pong);
+ return rc;
+}
+
+static int test_qmi_data_send_sync_msg(unsigned int data_len)
+{
+ struct test_data_req_msg_v01 *req;
+ struct test_data_resp_msg_v01 *resp;
+ struct msg_desc req_desc, resp_desc;
+ int rc, i;
+
+ req = kzalloc(sizeof(struct test_data_req_msg_v01), GFP_KERNEL);
+ if (!req) {
+ pr_err("%s: Data req msg alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ resp = kzalloc(sizeof(struct test_data_resp_msg_v01), GFP_KERNEL);
+ if (!resp) {
+ pr_err("%s: Data resp msg alloc failed\n", __func__);
+ kfree(req);
+ return -ENOMEM;
+ }
+
+ req->data_len = data_len;
+ for (i = 0; i < data_len; i = i + sizeof(int))
+ memcpy(req->data + i, (uint8_t *)&i, sizeof(int));
+ req->client_name_valid = 0;
+
+ req_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+ req_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+ req_desc.ei_array = test_data_req_msg_v01_ei;
+
+ resp_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+ resp_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+ resp_desc.ei_array = test_data_resp_msg_v01_ei;
+
+ rc = qmi_send_req_wait(test_clnt, &req_desc, req, sizeof(*req),
+ &resp_desc, resp, sizeof(*resp), 0);
+ if (rc < 0) {
+ pr_err("%s: send req failed\n", __func__);
+ goto data_send_err;
+ }
+
+ D("%s: data_valid %d\n", __func__, resp->data_valid);
+ D("%s: data_len %d\n", __func__, resp->data_len);
+data_send_err:
+ kfree(resp);
+ kfree(req);
+ return rc;
+}
+
+static int test_qmi_data_send_async_msg(unsigned int data_len)
+{
+ struct test_data_req_msg_v01 *req;
+ struct test_data_resp_msg_v01 *resp;
+ struct msg_desc req_desc, *resp_desc;
+ int rc, i;
+
+ req = kzalloc(sizeof(struct test_data_req_msg_v01), GFP_KERNEL);
+ if (!req) {
+ pr_err("%s: Data req msg alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ resp = kzalloc(sizeof(struct test_data_resp_msg_v01), GFP_KERNEL);
+ if (!resp) {
+ pr_err("%s: Data resp msg alloc failed\n", __func__);
+ kfree(req);
+ return -ENOMEM;
+ }
+
+ resp_desc = kzalloc(sizeof(struct msg_desc), GFP_KERNEL);
+ if (!resp_desc) {
+ pr_err("%s: Resp_desc msg alloc failed\n", __func__);
+ kfree(req);
+ kfree(resp);
+ return -ENOMEM;
+ }
+
+ req->data_len = data_len;
+ for (i = 0; i < data_len; i = i + sizeof(int))
+ memcpy(req->data + i, (uint8_t *)&i, sizeof(int));
+ req->client_name_valid = 0;
+
+ req_desc.max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+ req_desc.msg_id = TEST_DATA_REQ_MSG_ID_V01;
+ req_desc.ei_array = test_data_req_msg_v01_ei;
+
+ resp_desc->max_msg_len = TEST_DATA_REQ_MAX_MSG_LEN_V01;
+ resp_desc->msg_id = TEST_DATA_REQ_MSG_ID_V01;
+ resp_desc->ei_array = test_data_resp_msg_v01_ei;
+
+ rc = qmi_send_req_nowait(test_clnt, &req_desc, req, sizeof(*req),
+ resp_desc, resp, sizeof(*resp),
+ test_async_resp_cb, (void *)resp_desc);
+ if (rc < 0) {
+ pr_err("%s: send req failed\n", __func__);
+ kfree(resp);
+ kfree(resp_desc);
+ }
+ kfree(req);
+ return rc;
+}
+
+static void test_clnt_recv_msg(struct work_struct *work)
+{
+ int rc;
+
+ do {
+ D("%s: Notified about a Receive Event", __func__);
+ } while ((rc = qmi_recv_msg(test_clnt)) == 0);
+
+ if (rc != -ENOMSG)
+ pr_err("%s: Error receiving message\n", __func__);
+}
+
+static void test_clnt_notify(struct qmi_handle *handle,
+ enum qmi_event_type event, void *notify_priv)
+{
+ switch (event) {
+ case QMI_RECV_MSG:
+ queue_delayed_work(test_clnt_workqueue,
+ &work_recv_msg, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static void test_clnt_svc_arrive(struct work_struct *work)
+{
+ int rc;
+
+ D("%s begins\n", __func__);
+
+ /* Create a Local client port for QMI communication */
+ test_clnt = qmi_handle_create(test_clnt_notify, NULL);
+ if (!test_clnt) {
+ pr_err("%s: QMI client handle alloc failed\n", __func__);
+ return;
+ }
+
+ D("%s: Lookup server name\n", __func__);
+ rc = qmi_connect_to_service(test_clnt, TEST_SERVICE_SVC_ID,
+ TEST_SERVICE_V1,
+ TEST_SERVICE_INS_ID);
+ if (rc < 0) {
+ pr_err("%s: Server not found\n", __func__);
+ qmi_handle_destroy(test_clnt);
+ test_clnt = NULL;
+ return;
+ }
+ test_clnt_reset = 0;
+ D("%s complete\n", __func__);
+}
+
+static void test_clnt_svc_exit(struct work_struct *work)
+{
+ D("%s begins\n", __func__);
+
+ qmi_handle_destroy(test_clnt);
+ test_clnt_reset = 1;
+ test_clnt = NULL;
+
+ D("%s complete\n", __func__);
+}
+
+static int test_clnt_svc_event_notify(struct notifier_block *this,
+ unsigned long code,
+ void *_cmd)
+{
+ D("%s: event %ld\n", __func__, code);
+ switch (code) {
+ case QMI_SERVER_ARRIVE:
+ queue_delayed_work(test_clnt_workqueue,
+ &work_svc_arrive, 0);
+ break;
+ case QMI_SERVER_EXIT:
+ queue_delayed_work(test_clnt_workqueue,
+ &work_svc_exit, 0);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int test_qmi_open(struct inode *ip, struct file *fp)
+{
+ if (!test_clnt) {
+ pr_err("%s Test client is not initialized\n", __func__);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static ssize_t test_qmi_read(struct file *fp, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ char _buf[16];
+ snprintf(_buf, sizeof(_buf), "%d\n", test_res);
+ test_res = 0;
+ return simple_read_from_buffer(buf, count, pos,
+ _buf, strnlen(_buf, 16));
+}
+
+static int test_qmi_release(struct inode *ip, struct file *fp)
+{
+ return 0;
+}
+
+static ssize_t test_qmi_write(struct file *fp, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ unsigned char cmd[64];
+ int len;
+ int i;
+
+ if (count < 1)
+ return 0;
+
+ len = min(count, (sizeof(cmd) - 1));
+
+ if (copy_from_user(cmd, buf, len))
+ return -EFAULT;
+
+ cmd[len] = 0;
+ if (cmd[len-1] == '\n') {
+ cmd[len-1] = 0;
+ len--;
+ }
+
+ if (!strncmp(cmd, "ping_pong", sizeof(cmd))) {
+ for (i = 0; i < test_rep_cnt; i++) {
+ test_res = test_qmi_ping_pong_send_sync_msg();
+ if (test_res == -ENETRESET || test_clnt_reset) {
+ do {
+ msleep(50);
+ } while (test_clnt_reset);
+ }
+ }
+ } else if (!strncmp(cmd, "data", sizeof(cmd))) {
+ for (i = 0; i < test_rep_cnt; i++) {
+ test_res = test_qmi_data_send_sync_msg(test_data_sz);
+ if (test_res == -ENETRESET || test_clnt_reset) {
+ do {
+ msleep(50);
+ } while (test_clnt_reset);
+ }
+ }
+ } else if (!strncmp(cmd, "data_async", sizeof(cmd))) {
+ int i;
+ callback_count = 0;
+ for (i = 0; i < test_rep_cnt; i++) {
+ test_res = test_qmi_data_send_async_msg(test_data_sz);
+ if (test_res == -ENETRESET || test_clnt_reset) {
+ --i;
+ do {
+ msleep(50);
+ } while (test_clnt_reset);
+ } else if (test_res < 0) {
+ --i;
+ pr_err("%s: Error sending txn, aborting now",
+ __func__);
+ break;
+ }
+ }
+ while (callback_count < i) {
+ if (test_clnt_reset) {
+ pr_err("%s: Service Exited", __func__);
+ break;
+ }
+ msleep(50);
+ }
+ D("%s complete\n", __func__);
+ callback_count = 0;
+ } else {
+ test_res = -EINVAL;
+ }
+ return count;
+}
+
+static struct notifier_block test_clnt_nb = {
+ .notifier_call = test_clnt_svc_event_notify,
+};
+
+static const struct file_operations debug_ops = {
+ .owner = THIS_MODULE,
+ .open = test_qmi_open,
+ .read = test_qmi_read,
+ .write = test_qmi_write,
+ .release = test_qmi_release,
+};
+
+static int __init test_qmi_init(void)
+{
+ int rc;
+
+ test_clnt_workqueue = create_singlethread_workqueue("test_clnt");
+ if (!test_clnt_workqueue)
+ return -EFAULT;
+
+ rc = qmi_svc_event_notifier_register(TEST_SERVICE_SVC_ID,
+ TEST_SERVICE_V1, TEST_SERVICE_INS_ID,
+ &test_clnt_nb);
+ if (rc < 0) {
+ pr_err("%s: notifier register failed\n", __func__);
+ destroy_workqueue(test_clnt_workqueue);
+ return rc;
+ }
+
+ test_dent = debugfs_create_file("test_qmi_client", 0444, 0,
+ NULL, &debug_ops);
+ if (IS_ERR(test_dent)) {
+ pr_err("%s: unable to create debugfs %ld\n",
+ __func__, IS_ERR(test_dent));
+ test_dent = NULL;
+ qmi_svc_event_notifier_unregister(TEST_SERVICE_SVC_ID,
+ TEST_SERVICE_V1, TEST_SERVICE_INS_ID,
+ &test_clnt_nb);
+ destroy_workqueue(test_clnt_workqueue);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static void __exit test_qmi_exit(void)
+{
+ qmi_svc_event_notifier_unregister(TEST_SERVICE_SVC_ID,
+ TEST_SERVICE_V1,
+ TEST_SERVICE_INS_ID, &test_clnt_nb);
+ destroy_workqueue(test_clnt_workqueue);
+ debugfs_remove(test_dent);
+}
+
+module_init(test_qmi_init);
+module_exit(test_qmi_exit);
+
+MODULE_DESCRIPTION("TEST QMI Client Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/timer.h b/arch/arm/mach-msm/timer.h
new file mode 100644
index 000000000000..ad67981c9067
--- /dev/null
+++ b/arch/arm/mach-msm/timer.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2008-2009, 2011-2012 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 _ARCH_ARM_MACH_MSM_TIMER_H_
+#define _ARCH_ARM_MACH_MSM_TIMER_H_
+
+void msm_timer_init(void);
+uint32_t msm_timer_get_sclk_ticks(void);
+int msm_timer_init_time_sync(void (*timeout)(void));
+#ifndef CONFIG_ARM_ARCH_TIMER
+void __iomem *msm_timer_get_timer0_base(void);
+int64_t msm_timer_enter_idle(void);
+void msm_timer_exit_idle(int low_power);
+int64_t msm_timer_get_sclk_time(int64_t *period);
+#else
+static inline int64_t msm_timer_enter_idle(void) { return 0; }
+static inline void msm_timer_exit_idle(int low_power) { return; }
+static inline int64_t msm_timer_get_sclk_time(int64_t *period) { return 0; }
+static inline void __iomem *msm_timer_get_timer0_base(void) { return NULL; }
+#endif
+#endif
diff --git a/arch/arm/mach-msm/tz_log.c b/arch/arm/mach-msm/tz_log.c
new file mode 100644
index 000000000000..4b0dfe34fe52
--- /dev/null
+++ b/arch/arm/mach-msm/tz_log.c
@@ -0,0 +1,785 @@
+/* Copyright (c) 2011-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 <linux/debugfs.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/msm_ion.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <soc/qcom/scm.h>
+#include <soc/qcom/qseecomi.h>
+
+#define DEBUG_MAX_RW_BUF 4096
+
+/* QSEE_LOG_BUF_SIZE = 32K */
+#define QSEE_LOG_BUF_SIZE 0x8000
+
+
+/* TZ Diagnostic Area legacy version number */
+#define TZBSP_DIAG_MAJOR_VERSION_LEGACY 2
+/*
+ * Preprocessor Definitions and Constants
+ */
+#define TZBSP_CPU_COUNT 0x02
+/*
+ * Number of VMID Tables
+ */
+#define TZBSP_DIAG_NUM_OF_VMID 16
+/*
+ * VMID Description length
+ */
+#define TZBSP_DIAG_VMID_DESC_LEN 7
+/*
+ * Number of Interrupts
+ */
+#define TZBSP_DIAG_INT_NUM 32
+/*
+ * Length of descriptive name associated with Interrupt
+ */
+#define TZBSP_MAX_INT_DESC 16
+/*
+ * VMID Table
+ */
+struct tzdbg_vmid_t {
+ uint8_t vmid; /* Virtual Machine Identifier */
+ uint8_t desc[TZBSP_DIAG_VMID_DESC_LEN]; /* ASCII Text */
+};
+/*
+ * Boot Info Table
+ */
+struct tzdbg_boot_info_t {
+ uint32_t wb_entry_cnt; /* Warmboot entry CPU Counter */
+ uint32_t wb_exit_cnt; /* Warmboot exit CPU Counter */
+ uint32_t pc_entry_cnt; /* Power Collapse entry CPU Counter */
+ uint32_t pc_exit_cnt; /* Power Collapse exit CPU counter */
+ uint32_t warm_jmp_addr; /* Last Warmboot Jump Address */
+ uint32_t spare; /* Reserved for future use. */
+};
+/*
+ * Reset Info Table
+ */
+struct tzdbg_reset_info_t {
+ uint32_t reset_type; /* Reset Reason */
+ uint32_t reset_cnt; /* Number of resets occured/CPU */
+};
+/*
+ * Interrupt Info Table
+ */
+struct tzdbg_int_t {
+ /*
+ * Type of Interrupt/exception
+ */
+ uint16_t int_info;
+ /*
+ * Availability of the slot
+ */
+ uint8_t avail;
+ /*
+ * Reserved for future use
+ */
+ uint8_t spare;
+ /*
+ * Interrupt # for IRQ and FIQ
+ */
+ uint32_t int_num;
+ /*
+ * ASCII text describing type of interrupt e.g:
+ * Secure Timer, EBI XPU. This string is always null terminated,
+ * supporting at most TZBSP_MAX_INT_DESC characters.
+ * Any additional characters are truncated.
+ */
+ uint8_t int_desc[TZBSP_MAX_INT_DESC];
+ uint64_t int_count[TZBSP_CPU_COUNT]; /* # of times seen per CPU */
+};
+
+/*
+ * Log ring buffer position
+ */
+struct tzdbg_log_pos_t {
+ uint16_t wrap;
+ uint16_t offset;
+};
+
+ /*
+ * Log ring buffer
+ */
+struct tzdbg_log_t {
+ struct tzdbg_log_pos_t log_pos;
+ /* open ended array to the end of the 4K IMEM buffer */
+ uint8_t log_buf[];
+};
+
+/*
+ * Diagnostic Table
+ */
+struct tzdbg_t {
+ uint32_t magic_num;
+ uint32_t version;
+ /*
+ * Number of CPU's
+ */
+ uint32_t cpu_count;
+ /*
+ * Offset of VMID Table
+ */
+ uint32_t vmid_info_off;
+ /*
+ * Offset of Boot Table
+ */
+ uint32_t boot_info_off;
+ /*
+ * Offset of Reset info Table
+ */
+ uint32_t reset_info_off;
+ /*
+ * Offset of Interrupt info Table
+ */
+ uint32_t int_info_off;
+ /*
+ * Ring Buffer Offset
+ */
+ uint32_t ring_off;
+ /*
+ * Ring Buffer Length
+ */
+ uint32_t ring_len;
+ /*
+ * VMID to EE Mapping
+ */
+ struct tzdbg_vmid_t vmid_info[TZBSP_DIAG_NUM_OF_VMID];
+ /*
+ * Boot Info
+ */
+ struct tzdbg_boot_info_t boot_info[TZBSP_CPU_COUNT];
+ /*
+ * Reset Info
+ */
+ struct tzdbg_reset_info_t reset_info[TZBSP_CPU_COUNT];
+ uint32_t num_interrupts;
+ struct tzdbg_int_t int_info[TZBSP_DIAG_INT_NUM];
+ /*
+ * We need at least 2K for the ring buffer
+ */
+ struct tzdbg_log_t ring_buffer; /* TZ Ring Buffer */
+};
+
+/*
+ * Enumeration order for VMID's
+ */
+enum tzdbg_stats_type {
+ TZDBG_BOOT = 0,
+ TZDBG_RESET,
+ TZDBG_INTERRUPT,
+ TZDBG_VMID,
+ TZDBG_GENERAL,
+ TZDBG_LOG,
+ TZDBG_QSEE_LOG,
+ TZDBG_STATS_MAX
+};
+
+struct tzdbg_stat {
+ char *name;
+ char *data;
+};
+
+struct tzdbg {
+ void __iomem *virt_iobase;
+ struct tzdbg_t *diag_buf;
+ char *disp_buf;
+ int debug_tz[TZDBG_STATS_MAX];
+ struct tzdbg_stat stat[TZDBG_STATS_MAX];
+};
+
+static struct tzdbg tzdbg = {
+
+ .stat[TZDBG_BOOT].name = "boot",
+ .stat[TZDBG_RESET].name = "reset",
+ .stat[TZDBG_INTERRUPT].name = "interrupt",
+ .stat[TZDBG_VMID].name = "vmid",
+ .stat[TZDBG_GENERAL].name = "general",
+ .stat[TZDBG_LOG].name = "log",
+ .stat[TZDBG_QSEE_LOG].name = "qsee_log",
+};
+
+static struct tzdbg_log_t *g_qsee_log;
+
+/*
+ * Debugfs data structure and functions
+ */
+
+static int _disp_tz_general_stats(void)
+{
+ int len = 0;
+
+ len += snprintf(tzdbg.disp_buf + len, DEBUG_MAX_RW_BUF - 1,
+ " Version : 0x%x\n"
+ " Magic Number : 0x%x\n"
+ " Number of CPU : %d\n",
+ tzdbg.diag_buf->version,
+ tzdbg.diag_buf->magic_num,
+ tzdbg.diag_buf->cpu_count);
+ tzdbg.stat[TZDBG_GENERAL].data = tzdbg.disp_buf;
+ return len;
+}
+
+static int _disp_tz_vmid_stats(void)
+{
+ int i, num_vmid;
+ int len = 0;
+ struct tzdbg_vmid_t *ptr;
+
+ ptr = (struct tzdbg_vmid_t *)((unsigned char *)tzdbg.diag_buf +
+ tzdbg.diag_buf->vmid_info_off);
+ num_vmid = ((tzdbg.diag_buf->boot_info_off -
+ tzdbg.diag_buf->vmid_info_off)/
+ (sizeof(struct tzdbg_vmid_t)));
+
+ for (i = 0; i < num_vmid; i++) {
+ if (ptr->vmid < 0xFF) {
+ len += snprintf(tzdbg.disp_buf + len,
+ (DEBUG_MAX_RW_BUF - 1) - len,
+ " 0x%x %s\n",
+ (uint32_t)ptr->vmid, (uint8_t *)ptr->desc);
+ }
+ if (len > (DEBUG_MAX_RW_BUF - 1)) {
+ pr_warn("%s: Cannot fit all info into the buffer\n",
+ __func__);
+ break;
+ }
+ ptr++;
+ }
+
+ tzdbg.stat[TZDBG_VMID].data = tzdbg.disp_buf;
+ return len;
+}
+
+static int _disp_tz_boot_stats(void)
+{
+ int i;
+ int len = 0;
+ struct tzdbg_boot_info_t *ptr;
+
+ ptr = (struct tzdbg_boot_info_t *)((unsigned char *)tzdbg.diag_buf +
+ tzdbg.diag_buf->boot_info_off);
+
+ for (i = 0; i < tzdbg.diag_buf->cpu_count; i++) {
+ len += snprintf(tzdbg.disp_buf + len,
+ (DEBUG_MAX_RW_BUF - 1) - len,
+ " CPU #: %d\n"
+ " Warmboot jump address : 0x%x\n"
+ " Warmboot entry CPU counter: 0x%x\n"
+ " Warmboot exit CPU counter : 0x%x\n"
+ " Power Collapse entry CPU counter: 0x%x\n"
+ " Power Collapse exit CPU counter : 0x%x\n",
+ i, ptr->warm_jmp_addr, ptr->wb_entry_cnt,
+ ptr->wb_exit_cnt, ptr->pc_entry_cnt,
+ ptr->pc_exit_cnt);
+
+ if (len > (DEBUG_MAX_RW_BUF - 1)) {
+ pr_warn("%s: Cannot fit all info into the buffer\n",
+ __func__);
+ break;
+ }
+ ptr++;
+ }
+ tzdbg.stat[TZDBG_BOOT].data = tzdbg.disp_buf;
+ return len;
+}
+
+static int _disp_tz_reset_stats(void)
+{
+ int i;
+ int len = 0;
+ struct tzdbg_reset_info_t *ptr;
+
+ ptr = (struct tzdbg_reset_info_t *)((unsigned char *)tzdbg.diag_buf +
+ tzdbg.diag_buf->reset_info_off);
+
+ for (i = 0; i < tzdbg.diag_buf->cpu_count; i++) {
+ len += snprintf(tzdbg.disp_buf + len,
+ (DEBUG_MAX_RW_BUF - 1) - len,
+ " CPU #: %d\n"
+ " Reset Type (reason) : 0x%x\n"
+ " Reset counter : 0x%x\n",
+ i, ptr->reset_type, ptr->reset_cnt);
+
+ if (len > (DEBUG_MAX_RW_BUF - 1)) {
+ pr_warn("%s: Cannot fit all info into the buffer\n",
+ __func__);
+ break;
+ }
+
+ ptr++;
+ }
+ tzdbg.stat[TZDBG_RESET].data = tzdbg.disp_buf;
+ return len;
+}
+
+static int _disp_tz_interrupt_stats(void)
+{
+ int i, j, int_info_size;
+ int len = 0;
+ int *num_int;
+ unsigned char *ptr;
+ struct tzdbg_int_t *tzdbg_ptr;
+
+ num_int = (uint32_t *)((unsigned char *)tzdbg.diag_buf +
+ (tzdbg.diag_buf->int_info_off - sizeof(uint32_t)));
+ ptr = ((unsigned char *)tzdbg.diag_buf +
+ tzdbg.diag_buf->int_info_off);
+ int_info_size = ((tzdbg.diag_buf->ring_off -
+ tzdbg.diag_buf->int_info_off)/(*num_int));
+
+ for (i = 0; i < (*num_int); i++) {
+ tzdbg_ptr = (struct tzdbg_int_t *)ptr;
+ len += snprintf(tzdbg.disp_buf + len,
+ (DEBUG_MAX_RW_BUF - 1) - len,
+ " Interrupt Number : 0x%x\n"
+ " Type of Interrupt : 0x%x\n"
+ " Description of interrupt : %s\n",
+ tzdbg_ptr->int_num,
+ (uint32_t)tzdbg_ptr->int_info,
+ (uint8_t *)tzdbg_ptr->int_desc);
+ for (j = 0; j < tzdbg.diag_buf->cpu_count; j++) {
+ len += snprintf(tzdbg.disp_buf + len,
+ (DEBUG_MAX_RW_BUF - 1) - len,
+ " int_count on CPU # %d : %u\n",
+ (uint32_t)j,
+ (uint32_t)tzdbg_ptr->int_count[j]);
+ }
+ len += snprintf(tzdbg.disp_buf + len, DEBUG_MAX_RW_BUF - 1,
+ "\n");
+
+ if (len > (DEBUG_MAX_RW_BUF - 1)) {
+ pr_warn("%s: Cannot fit all info into the buffer\n",
+ __func__);
+ break;
+ }
+
+ ptr += int_info_size;
+ }
+ tzdbg.stat[TZDBG_INTERRUPT].data = tzdbg.disp_buf;
+ return len;
+}
+
+static int _disp_tz_log_stats_legacy(void)
+{
+ int len = 0;
+ unsigned char *ptr;
+
+ ptr = (unsigned char *)tzdbg.diag_buf +
+ tzdbg.diag_buf->ring_off;
+ len += snprintf(tzdbg.disp_buf, (DEBUG_MAX_RW_BUF - 1) - len,
+ "%s\n", ptr);
+
+ tzdbg.stat[TZDBG_LOG].data = tzdbg.disp_buf;
+ return len;
+}
+
+static int _disp_log_stats(struct tzdbg_log_t *log,
+ struct tzdbg_log_pos_t *log_start, uint32_t log_len,
+ size_t count, uint32_t buf_idx)
+{
+ uint32_t wrap_start;
+ uint32_t wrap_end;
+ uint32_t wrap_cnt;
+ int max_len;
+ int len = 0;
+ int i = 0;
+
+ wrap_start = log_start->wrap;
+ wrap_end = log->log_pos.wrap;
+
+ /* Calculate difference in # of buffer wrap-arounds */
+ if (wrap_end >= wrap_start) {
+ wrap_cnt = wrap_end - wrap_start;
+ } else {
+ /* wrap counter has wrapped around, invalidate start position */
+ wrap_cnt = 2;
+ }
+
+ if (wrap_cnt > 1) {
+ /* end position has wrapped around more than once, */
+ /* current start no longer valid */
+ log_start->wrap = log->log_pos.wrap - 1;
+ log_start->offset = (log->log_pos.offset + 1) % log_len;
+ } else if ((wrap_cnt == 1) &&
+ (log->log_pos.offset > log_start->offset)) {
+ /* end position has overwritten start */
+ log_start->offset = (log->log_pos.offset + 1) % log_len;
+ }
+
+ while (log_start->offset == log->log_pos.offset) {
+ /*
+ * No data in ring buffer,
+ * so we'll hang around until something happens
+ */
+ unsigned long t = msleep_interruptible(50);
+ if (t != 0) {
+ /* Some event woke us up, so let's quit */
+ return 0;
+ }
+
+ if (buf_idx == TZDBG_LOG)
+ memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase,
+ DEBUG_MAX_RW_BUF);
+
+ }
+
+ max_len = (count > DEBUG_MAX_RW_BUF) ? DEBUG_MAX_RW_BUF : count;
+
+ /*
+ * Read from ring buff while there is data and space in return buff
+ */
+ while ((log_start->offset != log->log_pos.offset) && (len < max_len)) {
+ tzdbg.disp_buf[i++] = log->log_buf[log_start->offset];
+ log_start->offset = (log_start->offset + 1) % log_len;
+ if (0 == log_start->offset)
+ ++log_start->wrap;
+ ++len;
+ }
+
+ /*
+ * return buffer to caller
+ */
+ tzdbg.stat[buf_idx].data = tzdbg.disp_buf;
+ return len;
+}
+
+static int _disp_tz_log_stats(size_t count)
+{
+ static struct tzdbg_log_pos_t log_start = {0};
+ struct tzdbg_log_t *log_ptr;
+ log_ptr = (struct tzdbg_log_t *)((unsigned char *)tzdbg.diag_buf +
+ tzdbg.diag_buf->ring_off -
+ offsetof(struct tzdbg_log_t, log_buf));
+
+ return _disp_log_stats(log_ptr, &log_start,
+ tzdbg.diag_buf->ring_len, count, TZDBG_LOG);
+}
+
+static int _disp_qsee_log_stats(size_t count)
+{
+ static struct tzdbg_log_pos_t log_start = {0};
+
+ return _disp_log_stats(g_qsee_log, &log_start,
+ QSEE_LOG_BUF_SIZE - sizeof(struct tzdbg_log_pos_t),
+ count, TZDBG_QSEE_LOG);
+}
+
+static ssize_t tzdbgfs_read(struct file *file, char __user *buf,
+ size_t count, loff_t *offp)
+{
+ int len = 0;
+ int *tz_id = file->private_data;
+
+ memcpy_fromio((void *)tzdbg.diag_buf, tzdbg.virt_iobase,
+ DEBUG_MAX_RW_BUF);
+ switch (*tz_id) {
+ case TZDBG_BOOT:
+ len = _disp_tz_boot_stats();
+ break;
+ case TZDBG_RESET:
+ len = _disp_tz_reset_stats();
+ break;
+ case TZDBG_INTERRUPT:
+ len = _disp_tz_interrupt_stats();
+ break;
+ case TZDBG_GENERAL:
+ len = _disp_tz_general_stats();
+ break;
+ case TZDBG_VMID:
+ len = _disp_tz_vmid_stats();
+ break;
+ case TZDBG_LOG:
+ if (TZBSP_DIAG_MAJOR_VERSION_LEGACY <
+ (tzdbg.diag_buf->version >> 16)) {
+ len = _disp_tz_log_stats(count);
+ *offp = 0;
+ } else {
+ len = _disp_tz_log_stats_legacy();
+ }
+ break;
+ case TZDBG_QSEE_LOG:
+ len = _disp_qsee_log_stats(count);
+ *offp = 0;
+ break;
+ default:
+ break;
+ }
+
+ if (len > count)
+ len = count;
+
+ return simple_read_from_buffer(buf, len, offp,
+ tzdbg.stat[(*tz_id)].data, len);
+}
+
+static int tzdbgfs_open(struct inode *inode, struct file *pfile)
+{
+ pfile->private_data = inode->i_private;
+ return 0;
+}
+
+const struct file_operations tzdbg_fops = {
+ .owner = THIS_MODULE,
+ .read = tzdbgfs_read,
+ .open = tzdbgfs_open,
+};
+
+static struct ion_client *g_ion_clnt;
+static struct ion_handle *g_ihandle;
+
+/*
+ * Allocates log buffer from ION, registers the buffer at TZ
+ */
+static void tzdbg_register_qsee_log_buf(void)
+{
+ /* register log buffer scm request */
+ struct qseecom_reg_log_buf_ireq req;
+
+ /* scm response */
+ struct qseecom_command_scm_resp resp = {};
+ ion_phys_addr_t pa = 0;
+ uint32_t len;
+ int ret = 0;
+
+ /* Create ION msm client */
+ g_ion_clnt = msm_ion_client_create(ION_HEAP_CARVEOUT_MASK, "qsee_log");
+ if (g_ion_clnt == NULL) {
+ pr_err("%s: Ion client cannot be created\n", __func__);
+ return;
+ }
+
+ g_ihandle = ion_alloc(g_ion_clnt, QSEE_LOG_BUF_SIZE,
+ 4096, ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+ if (IS_ERR_OR_NULL(g_ihandle)) {
+ pr_err("%s: Ion client could not retrieve the handle\n",
+ __func__);
+ goto err1;
+ }
+
+ ret = ion_phys(g_ion_clnt, g_ihandle, &pa, &len);
+ if (ret) {
+ pr_err("%s: Ion conversion to physical address failed\n",
+ __func__);
+ goto err2;
+ }
+
+ req.qsee_cmd_id = QSEOS_REGISTER_LOG_BUF_COMMAND;
+ req.phy_addr = pa;
+ req.len = len;
+
+ /* SCM_CALL to register the log buffer */
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, &req, sizeof(req),
+ &resp, sizeof(resp));
+ if (ret) {
+ pr_err("%s: scm_call to register log buffer failed\n",
+ __func__);
+ goto err2;
+ }
+
+ if (resp.result != QSEOS_RESULT_SUCCESS) {
+ pr_err(
+ "%s: scm_call to register log buf failed, resp result =%d\n",
+ __func__, resp.result);
+ goto err2;
+ }
+
+ g_qsee_log =
+ (struct tzdbg_log_t *)ion_map_kernel(g_ion_clnt, g_ihandle);
+ g_qsee_log->log_pos.wrap = g_qsee_log->log_pos.offset = 0;
+ return;
+
+err2:
+ ion_free(g_ion_clnt, g_ihandle);
+ g_ihandle = NULL;
+err1:
+ ion_client_destroy(g_ion_clnt);
+ g_ion_clnt = NULL;
+}
+
+static int tzdbgfs_init(struct platform_device *pdev)
+{
+ int rc = 0;
+ int i;
+ struct dentry *dent_dir;
+ struct dentry *dent;
+
+ dent_dir = debugfs_create_dir("tzdbg", NULL);
+ if (dent_dir == NULL) {
+ dev_err(&pdev->dev, "tzdbg debugfs_create_dir failed\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < TZDBG_STATS_MAX; i++) {
+ tzdbg.debug_tz[i] = i;
+ dent = debugfs_create_file(tzdbg.stat[i].name,
+ S_IRUGO, dent_dir,
+ &tzdbg.debug_tz[i], &tzdbg_fops);
+ if (dent == NULL) {
+ dev_err(&pdev->dev, "TZ debugfs_create_file failed\n");
+ rc = -ENOMEM;
+ goto err;
+ }
+ }
+ tzdbg.disp_buf = kzalloc(DEBUG_MAX_RW_BUF, GFP_KERNEL);
+ if (tzdbg.disp_buf == NULL) {
+ pr_err("%s: Can't Allocate memory for tzdbg.disp_buf\n",
+ __func__);
+
+ goto err;
+ }
+ platform_set_drvdata(pdev, dent_dir);
+ return 0;
+err:
+ debugfs_remove_recursive(dent_dir);
+
+ return rc;
+}
+
+static void tzdbgfs_exit(struct platform_device *pdev)
+{
+ struct dentry *dent_dir;
+
+ kzfree(tzdbg.disp_buf);
+ dent_dir = platform_get_drvdata(pdev);
+ debugfs_remove_recursive(dent_dir);
+ if (g_ion_clnt != NULL) {
+ if (!IS_ERR_OR_NULL(g_ihandle)) {
+ ion_unmap_kernel(g_ion_clnt, g_ihandle);
+ ion_free(g_ion_clnt, g_ihandle);
+ }
+ ion_client_destroy(g_ion_clnt);
+}
+}
+
+/*
+ * Driver functions
+ */
+static int tz_log_probe(struct platform_device *pdev)
+{
+ struct resource *resource;
+ void __iomem *virt_iobase;
+ phys_addr_t tzdiag_phy_iobase;
+ uint32_t *ptr = NULL;
+
+ /*
+ * Get address that stores the physical location of 4KB
+ * diagnostic data
+ */
+ resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!resource) {
+ dev_err(&pdev->dev,
+ "%s: ERROR Missing MEM resource\n", __func__);
+ return -ENXIO;
+ };
+ /*
+ * Map address that stores the physical location of 4KB
+ * diagnostic data
+ */
+ virt_iobase = devm_ioremap_nocache(&pdev->dev, resource->start,
+ resource->end - resource->start + 1);
+ if (!virt_iobase) {
+ dev_err(&pdev->dev,
+ "%s: ERROR could not ioremap: start=%pr, len=%u\n",
+ __func__, &resource->start,
+ (unsigned int)(resource->end - resource->start + 1));
+ return -ENXIO;
+ }
+ /*
+ * Retrieve the address of 4KB diagnostic data
+ */
+ tzdiag_phy_iobase = readl_relaxed(virt_iobase);
+
+ /*
+ * Map the 4KB diagnostic information area
+ */
+ tzdbg.virt_iobase = devm_ioremap_nocache(&pdev->dev,
+ tzdiag_phy_iobase, DEBUG_MAX_RW_BUF);
+
+ if (!tzdbg.virt_iobase) {
+ dev_err(&pdev->dev,
+ "%s: ERROR could not ioremap: start=%pr, len=%u\n",
+ __func__, &tzdiag_phy_iobase,
+ DEBUG_MAX_RW_BUF);
+ return -ENXIO;
+ }
+
+ ptr = kzalloc(DEBUG_MAX_RW_BUF, GFP_KERNEL);
+ if (ptr == NULL) {
+ pr_err("%s: Can't Allocate memory: ptr\n",
+ __func__);
+ return -ENXIO;
+ }
+
+ tzdbg.diag_buf = (struct tzdbg_t *)ptr;
+
+ if (tzdbgfs_init(pdev))
+ goto err;
+
+ tzdbg_register_qsee_log_buf();
+ return 0;
+err:
+ kfree(tzdbg.diag_buf);
+ return -ENXIO;
+}
+
+
+static int tz_log_remove(struct platform_device *pdev)
+{
+ kzfree(tzdbg.diag_buf);
+ tzdbgfs_exit(pdev);
+
+ return 0;
+}
+
+static struct of_device_id tzlog_match[] = {
+ { .compatible = "qcom,tz-log",
+ },
+ {}
+};
+
+static struct platform_driver tz_log_driver = {
+ .probe = tz_log_probe,
+ .remove = tz_log_remove,
+ .driver = {
+ .name = "tz_log",
+ .owner = THIS_MODULE,
+ .of_match_table = tzlog_match,
+ },
+};
+
+static int __init tz_log_init(void)
+{
+ return platform_driver_register(&tz_log_driver);
+}
+
+static void __exit tz_log_exit(void)
+{
+ platform_driver_unregister(&tz_log_driver);
+}
+
+module_init(tz_log_init);
+module_exit(tz_log_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TZ Log driver");
+MODULE_VERSION("1.1");
+MODULE_ALIAS("platform:tz_log");
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index ee5697ba05bc..dce1a43b9c3b 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -23,6 +23,37 @@ config ARCH_MSM8974
bool "Enable support for MSM8974"
select HAVE_ARM_ARCH_TIMER
+config ARCH_MSM8916
+ bool "MSM8916"
+ select ARCH_MSM_CORTEXMP
+ select HAVE_GENERIC_HARDIRQS
+ select USE_GENERIC_CPU_HELPERS
+ select ARM_GIC
+ select MULTI_IRQ_HANDLER
+ select CPU_V7
+ select HAVE_ARM_ARCH_TIMER
+ select MAY_HAVE_SPARSE_IRQ
+ select SPARSE_IRQ
+ select PINCTRL
+ select PINCTRL_MSM_TLMM_V4
+ select USE_PINCTRL_IRQ
+ select MSM_PM if PM
+ select MSM_RPM_SMD
+ select MEMORY_HOLE_CARVEOUT
+ select DONT_MAP_HOLE_AFTER_MEMBANK0
+ select QMI_ENCDEC
+ select MSM_IRQ
+ select MSM_CORTEX_A53
+ select CPU_FREQ_MSM
+ select CPU_FREQ
+ select PM_DEVFREQ
+ select MSM_DEVFREQ_CPUBW
+ select MSM_RPM_SMD
+ select ARM_HAS_SG_CHAIN
+ select ARCH_WANT_KMAP_ATOMIC_FLUSH
+ select SOC_BUS
+
+
config QCOM_SCM
bool
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 7eb94e6fc376..c59ae579a30f 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -695,6 +695,21 @@ config SWP_EMULATE
If unsure, say Y.
+config FORCE_INSTRUCTION_ALIGNMENT
+ bool "Force instructions address alignment"
+ depends on CPU_V7 && ALIGNMENT_TRAP
+ help
+ Branching to an address in ARM state which is not word aligned,
+ where this is defined to be UNPREDICTABLE, can cause one of the
+ following two behaviours: 1. The unaligned location is forced to
+ be aligned. 2. Using the unaligned address generates a Prefetch
+ Abort on the first instruction using the unaligned PC value.
+
+ To be consistant for the user space binaries, the unaligned location
+ is forced aligned with this config.
+
+ If unsure, say Y.
+
config CPU_BIG_ENDIAN
bool "Build big-endian kernel"
depends on ARCH_SUPPORTS_BIG_ENDIAN
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 83792f4324ea..ab8da50a417e 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -747,6 +747,36 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
return NULL;
}
+#ifdef CONFIG_FORCE_INSTRUCTION_ALIGNMENT
+static int
+do_ialignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+ /*
+ * Branching to an address in ARM state which is not word aligned,
+ * where this is defined to be UNPREDICTABLE,
+ * can cause one of the following two behaviours:
+ * 1. The unaligned location is forced to be aligned.
+ * 2. Using the unaligned address generates a Prefetch Abort on
+ * the first instruction using the unaligned PC value.
+ */
+ int isize = 4;
+
+ if (user_mode(regs) && !thumb_mode(regs)) {
+ ai_sys += 1;
+
+ /*
+ * Force align the instruction in software to be following
+ * a single behaviour for the unpredicatable cases.
+ */
+ instruction_pointer(regs) &= ~(isize + (-1UL));
+ return 0;
+ }
+
+ ai_skipped += 1;
+ return 1;
+}
+#endif
+
static int
do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
{
@@ -990,6 +1020,11 @@ static int __init alignment_init(void)
hook_fault_code(FAULT_CODE_ALIGNMENT, do_alignment, SIGBUS, BUS_ADRALN,
"alignment exception");
+#ifdef CONFIG_FORCE_INSTRUCTION_ALIGNMENT
+ hook_ifault_code(FAULT_CODE_ALIGNMENT, do_ialignment, SIGBUS,
+ BUS_ADRALN, "alignment exception");
+#endif
+
/*
* ARMv6K and ARMv7 use fault status 3 (0b00011) as Access Flag section
* fault, not as alignment error.
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index b966656d2c2d..5154280c1ad7 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -371,7 +371,6 @@ v7_dma_inv_range:
dsb st
ret lr
ENDPROC(v7_dma_inv_range)
-
/*
* v7_dma_clean_range(start,end)
* - start - virtual start address of region
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 9481f85c56e6..b68992f71f1d 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -46,6 +46,9 @@ unsigned long __init __clear_cr(unsigned long mask)
#endif
static phys_addr_t phys_initrd_start __initdata = 0;
+int msm_krait_need_wfe_fixup;
+EXPORT_SYMBOL(msm_krait_need_wfe_fixup);
+
static unsigned long phys_initrd_size __initdata = 0;
static int __init early_initrd(char *p)
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index a10297da122b..8c7bf7936ef5 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -467,6 +467,7 @@ msm7x27_surf MACH_MSM7X27_SURF MSM7X27_SURF 2705
msm7x27_ffa MACH_MSM7X27_FFA MSM7X27_FFA 2706
msm7x30_ffa MACH_MSM7X30_FFA MSM7X30_FFA 2707
qsd8x50_surf MACH_QSD8X50_SURF QSD8X50_SURF 2708
+qsd8x50_ffa MACH_QSD8X50_FFA QSD8X50_FFA 2710
mx53_evk MACH_MX53_EVK MX53_EVK 2716
igep0030 MACH_IGEP0030 IGEP0030 2717
sbc3530 MACH_SBC3530 SBC3530 2722
@@ -479,6 +480,8 @@ wbd222 MACH_WBD222 WBD222 2753
msm8x60_surf MACH_MSM8X60_SURF MSM8X60_SURF 2755
msm8x60_sim MACH_MSM8X60_SIM MSM8X60_SIM 2756
tcc8000_sdk MACH_TCC8000_SDK TCC8000_SDK 2758
+msm8x55_surf MACH_MSM8X55_SURF MSM8X55_SURF 2768
+msm8x55_ffa MACH_MSM8X55_FFA MSM8X55_FFA 2769
cns3420vb MACH_CNS3420VB CNS3420VB 2776
omap4_panda MACH_OMAP4_PANDA OMAP4_PANDA 2791
ti8168evm MACH_TI8168EVM TI8168EVM 2800
@@ -491,6 +494,8 @@ smdkc210 MACH_SMDKC210 SMDKC210 2838
t5325 MACH_T5325 T5325 2846
income MACH_INCOME INCOME 2849
goni MACH_GONI GONI 2862
+msm8x55_svlte_ffa MACH_MSM8X55_SVLTE_FFA MSM8X55_SVLTE_FFA 2863
+msm8x55_svlte_surf MACH_MSM8X55_SVLTE_SURF MSM8X55_SVLTE_SURF 2864
bv07 MACH_BV07 BV07 2882
openrd_ultimate MACH_OPENRD_ULTIMATE OPENRD_ULTIMATE 2884
devixp MACH_DEVIXP DEVIXP 2885
@@ -515,14 +520,19 @@ mx53_smd MACH_MX53_SMD MX53_SMD 3011
msm8x60_rumi3 MACH_MSM8X60_RUMI3 MSM8X60_RUMI3 3016
msm8x60_ffa MACH_MSM8X60_FFA MSM8X60_FFA 3017
cm_a510 MACH_CM_A510 CM_A510 3020
+fsm9xxx_surf MACH_FSM9XXX_SURF FSM9XXX_SURF 3028
+fsm9xxx_ffa MACH_FSM9XXX_FFA FSM9XXX_FFA 3029
tx28 MACH_TX28 TX28 3043
pcontrol_g20 MACH_PCONTROL_G20 PCONTROL_G20 3062
vpr200 MACH_VPR200 VPR200 3087
torbreck MACH_TORBRECK TORBRECK 3090
prima2_evb MACH_PRIMA2_EVB PRIMA2_EVB 3103
+msm8x60_fluid MACH_MSM8X60_FLUID MSM8X60_FLUID 3124
paz00 MACH_PAZ00 PAZ00 3128
acmenetusfoxg20 MACH_ACMENETUSFOXG20 ACMENETUSFOXG20 3129
+msm8x60_fusion MACH_MSM8X60_FUSION MSM8X60_FUSION 3181
ag5evm MACH_AG5EVM AG5EVM 3189
+msm8x60_fusn_ffa MACH_MSM8X60_FUSN_FFA MSM8X60_FUSN_FFA 3199
ics_if_voip MACH_ICS_IF_VOIP ICS_IF_VOIP 3206
wlf_cragg_6410 MACH_WLF_CRAGG_6410 WLF_CRAGG_6410 3207
trimslice MACH_TRIMSLICE TRIMSLICE 3209
@@ -540,17 +550,28 @@ armlex4210 MACH_ARMLEX4210 ARMLEX4210 3361
snowball MACH_SNOWBALL SNOWBALL 3363
xilinx_ep107 MACH_XILINX_EP107 XILINX_EP107 3378
nuri MACH_NURI NURI 3379
+msm8960_cdp MACH_MSM8960_CDP MSM8960_CDP 3396
+msm8960_mtp MACH_MSM8960_MTP MSM8960_MTP 3397
+msm8960_fluid MACH_MSM8960_FLUID MSM8960_FLUID 3398
+msm8960_apq MACH_MSM8960_APQ MSM8960_APQ 3399
origen MACH_ORIGEN ORIGEN 3455
nspire MACH_NSPIRE NSPIRE 3503
nokia_rm696 MACH_NOKIA_RM696 NOKIA_RM696 3522
mikrap_x168 MACH_MIKRAP_X168 MIKRAP_X168 3543
deto_macarm9 MACH_DETO_MACARM9 DETO_MACARM9 3568
+msm8x60_dragon MACH_MSM8X60_DRAGON MSM8X60_DRAGON 3586
m28evk MACH_M28EVK M28EVK 3613
kota2 MACH_KOTA2 KOTA2 3616
bonito MACH_BONITO BONITO 3623
omap3_egf MACH_OMAP3_EGF OMAP3_EGF 3637
smdk4212 MACH_SMDK4212 SMDK4212 3638
apx4devkit MACH_APX4DEVKIT APX4DEVKIT 3712
+msm9615_cdp MACH_MSM9615_CDP MSM9615_CDP 3675
+msm9615_mtp MACH_MSM9615_MTP MSM9615_MTP 3681
+msm8930_cdp MACH_MSM8930_CDP MSM8930_CDP 3727
+msm8930_mtp MACH_MSM8930_MTP MSM8930_MTP 3728
+msm8930_fluid MACH_MSM8930_FLUID MSM8930_FLUID 3729
+msm7627a_qrd1 MACH_MSM7627A_QRD1 MSM7627A_QRD1 3756
smdk4412 MACH_SMDK4412 SMDK4412 3765
marzen MACH_MARZEN MARZEN 3790
krome MACH_KROME KROME 3797
@@ -1007,3 +1028,19 @@ eco5_bx2 MACH_ECO5_BX2 ECO5_BX2 4572
eukrea_cpuimx28sd MACH_EUKREA_CPUIMX28SD EUKREA_CPUIMX28SD 4573
domotab MACH_DOMOTAB DOMOTAB 4574
pfla03 MACH_PFLA03 PFLA03 4575
+msm8625_rumi3 MACH_MSM8625_RUMI3 MSM8625_RUMI3 3871
+msm7627a_evb MACH_MSM7627A_EVB MSM7627A_EVB 3934
+apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
+apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
+apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
+mpq8064_cdp MACH_MPQ8064_CDP MPQ8064_CDP 3993
+mpq8064_hrd MACH_MPQ8064_HRD MPQ8064_HRD 3994
+mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995
+fsm8064_ep MACH_FSM8064_EP FSM8064_EP 3996
+msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
+msm8625_surf MACH_MSM8625_SURF MSM8625_SURF 4037
+msm8625_evb MACH_MSM8625_EVB MSM8625_EVB 4042
+msm8625_qrd7 MACH_MSM8625_QRD7 MSM8625_QRD7 4095
+msm8625_ffa MACH_MSM8625_FFA MSM8625_FFA 4166
+msm8625_evt MACH_MSM8625_EVT MSM8625_EVT 4193
+qrd_skud_prime MACH_QRD_SKUD_PRIME QRD_SKUD_PRIME 4393
diff --git a/drivers/Makefile b/drivers/Makefile
index ebee55537a05..fd1e9d72f81e 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -7,6 +7,9 @@
obj-y += irqchip/
obj-y += bus/
+obj-y += soc/
+
+
obj-$(CONFIG_GENERIC_PHY) += phy/
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 6922cd6850a2..508151a19485 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -6,7 +6,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \
attribute_container.o transport_class.o \
topology.o container.o
obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
-obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
+obj-$(CONFIG_DMA_CMA) += dma-contiguous.o dma-removed.o
obj-y += power/
obj-$(CONFIG_HAS_DMA) += dma-mapping.o
obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 950fff9ce453..5d3c70d31aa1 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -9,6 +9,9 @@
* 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.
+ *
+ * The Linux Foundation chooses to take subject only to the GPLv2 license
+ * terms, and distributes only under these terms.
*/
#define pr_fmt(fmt) "cma: " fmt
@@ -24,9 +27,70 @@
#include <linux/memblock.h>
#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/page-isolation.h>
#include <linux/sizes.h>
#include <linux/dma-contiguous.h>
#include <linux/cma.h>
+#include <linux/dma-removed.h>
+#include <trace/events/kmem.h>
+
+struct cma {
+ unsigned long base_pfn;
+ unsigned long count;
+ unsigned long *bitmap;
+ bool in_system;
+ struct mutex lock;
+};
+
+static DEFINE_MUTEX(cma_mutex);
+
+struct cma *dma_contiguous_def_area;
+phys_addr_t dma_contiguous_def_base;
+
+static struct cma_area {
+ phys_addr_t base;
+ unsigned long size;
+ struct cma *cma;
+ const char *name;
+ bool to_system;
+} cma_areas[MAX_CMA_AREAS];
+static unsigned cma_area_count;
+
+
+static struct cma_map {
+ phys_addr_t base;
+ struct device *dev;
+} cma_maps[MAX_CMA_AREAS] __initdata;
+static unsigned cma_map_count __initdata;
+
+static struct cma *cma_get_area(phys_addr_t base)
+{
+ int i;
+ for (i = 0; i < cma_area_count; i++)
+ if (cma_areas[i].base == base)
+ return cma_areas[i].cma;
+ return NULL;
+}
+
+static struct cma *cma_get_area_by_name(const char *name)
+{
+ int i;
+ if (!name)
+ return NULL;
+
+ for (i = 0; i < cma_area_count; i++)
+ if (cma_areas[i].name && strcmp(cma_areas[i].name, name) == 0)
+ return cma_areas[i].cma;
+ return NULL;
+}
+
+
+>>>>>>> patched
#ifdef CONFIG_CMA_SIZE_MBYTES
#define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
@@ -34,8 +98,16 @@
#define CMA_SIZE_MBYTES 0
#endif
+<<<<<<< current
struct cma *dma_contiguous_default_area;
+=======
+#ifdef CONFIG_CMA_RESERVE_DEFAULT_AREA
+#define CMA_RESERVE_AREA 1
+#else
+#define CMA_RESERVE_AREA 0
+#endif
+>>>>>>> patched
/*
* Default global CMA area size can be defined in kernel's .config.
* This is useful mainly for distro maintainers to create a kernel
@@ -95,6 +167,7 @@ static inline __maybe_unused phys_addr_t cma_early_percent_memory(void)
#endif
+<<<<<<< current
/**
* dma_contiguous_reserve() - reserve area(s) for contiguous memory handling
* @limit: End address of the reserved memory (optional, 0 for any).
@@ -146,6 +219,181 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
* dma_contiguous_reserve_area() - reserve custom contiguous area
* @size: Size of the reserved area (in bytes),
* @base: Base address of the reserved area optional, use 0 for any
+=======
+static __init int cma_activate_area(unsigned long base_pfn, unsigned long count)
+{
+ unsigned long pfn = base_pfn;
+ unsigned i = count >> pageblock_order;
+ struct zone *zone;
+
+ WARN_ON_ONCE(!pfn_valid(pfn));
+ zone = page_zone(pfn_to_page(pfn));
+
+ do {
+ unsigned j;
+ base_pfn = pfn;
+ for (j = pageblock_nr_pages; j; --j, pfn++) {
+ WARN_ON_ONCE(!pfn_valid(pfn));
+ if (page_zone(pfn_to_page(pfn)) != zone)
+ return -EINVAL;
+ }
+ init_cma_reserved_pageblock(pfn_to_page(base_pfn));
+ } while (--i);
+ return 0;
+}
+
+static __init struct cma *cma_create_area(unsigned long base_pfn,
+ unsigned long count, bool system)
+{
+ int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
+ struct cma *cma;
+ int ret = -ENOMEM;
+
+ pr_debug("%s(base %08lx, count %lx)\n", __func__, base_pfn, count);
+
+ cma = kmalloc(sizeof *cma, GFP_KERNEL);
+ if (!cma)
+ return ERR_PTR(-ENOMEM);
+
+ cma->base_pfn = base_pfn;
+ cma->count = count;
+ cma->in_system = system;
+ cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+
+ if (!cma->bitmap)
+ goto no_mem;
+
+ if (cma->in_system) {
+ ret = cma_activate_area(base_pfn, count);
+ if (ret)
+ goto error;
+ }
+ mutex_init(&cma->lock);
+
+ pr_debug("%s: returned %p\n", __func__, (void *)cma);
+ return cma;
+
+error:
+ kfree(cma->bitmap);
+no_mem:
+ kfree(cma);
+ return ERR_PTR(ret);
+}
+
+/*****************************************************************************/
+
+#ifdef CONFIG_OF
+int __init cma_fdt_scan(unsigned long node, const char *uname,
+ int depth, void *data)
+{
+ phys_addr_t base, size;
+ unsigned long len;
+ __be32 *prop;
+ char *name;
+ bool in_system;
+ bool remove;
+ unsigned long size_cells = dt_root_size_cells;
+ unsigned long addr_cells = dt_root_addr_cells;
+ phys_addr_t limit = MEMBLOCK_ALLOC_ANYWHERE;
+ char *status;
+
+ if (!of_get_flat_dt_prop(node, "linux,reserve-contiguous-region", NULL))
+ return 0;
+
+ status = of_get_flat_dt_prop(node, "status", NULL);
+ /*
+ * Yes, we actually want strncmp here to check for a prefix
+ * ok vs. okay
+ */
+ if (status && (strncmp(status, "ok", 2) != 0))
+ return 0;
+
+ prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
+ if (prop)
+ size_cells = be32_to_cpup(prop);
+
+ prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
+ if (prop)
+ addr_cells = be32_to_cpup(prop);
+
+ prop = of_get_flat_dt_prop(node, "reg", &len);
+ if (!prop || depth != 2)
+ return 0;
+
+ base = dt_mem_next_cell(addr_cells, &prop);
+ size = dt_mem_next_cell(size_cells, &prop);
+
+ name = of_get_flat_dt_prop(node, "label", NULL);
+ in_system =
+ of_get_flat_dt_prop(node, "linux,reserve-region", NULL) ? 0 : 1;
+
+ prop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
+ if (prop)
+ limit = be32_to_cpu(prop[0]);
+
+ remove =
+ of_get_flat_dt_prop(node, "linux,remove-completely", NULL) ? 1 : 0;
+
+ pr_info("Found %s, memory base %pa, size %ld MiB, limit %pa\n", uname,
+ &base, (unsigned long)size / SZ_1M, &limit);
+ dma_contiguous_reserve_area(size, &base, limit, name,
+ in_system, remove);
+
+ return 0;
+}
+#endif
+
+/**
+ * dma_contiguous_reserve() - reserve area for contiguous memory handling
+ * @limit: End address of the reserved memory (optional, 0 for any).
+ *
+ * This function reserves memory from early allocator. It should be
+ * called by arch specific code once the early allocator (memblock or bootmem)
+ * has been activated and all other subsystems have already allocated/reserved
+ * memory. It reserves contiguous areas for global, device independent
+ * allocations and (optionally) all areas defined in device tree structures.
+ */
+void __init dma_contiguous_reserve(phys_addr_t limit)
+{
+ phys_addr_t sel_size = 0;
+
+ pr_debug("%s(limit %pa)\n", __func__, &limit);
+
+ if (size_cmdline != -1) {
+ sel_size = size_cmdline;
+ } else {
+#ifdef CONFIG_CMA_SIZE_SEL_MBYTES
+ sel_size = size_bytes;
+#elif defined(CONFIG_CMA_SIZE_SEL_PERCENTAGE)
+ sel_size = cma_early_percent_memory();
+#elif defined(CONFIG_CMA_SIZE_SEL_MIN)
+ sel_size = min(size_bytes, cma_early_percent_memory());
+#elif defined(CONFIG_CMA_SIZE_SEL_MAX)
+ sel_size = max(size_bytes, cma_early_percent_memory());
+#endif
+ }
+
+ if (sel_size) {
+ phys_addr_t base = 0;
+ pr_debug("%s: reserving %ld MiB for global area\n", __func__,
+ (unsigned long)sel_size / SZ_1M);
+
+ if (dma_contiguous_reserve_area(sel_size, &base, limit, NULL,
+ CMA_RESERVE_AREA ? 0 : 1, false) == 0)
+ dma_contiguous_def_base = base;
+ }
+#ifdef CONFIG_OF
+ of_scan_flat_dt(cma_fdt_scan, NULL);
+#endif
+};
+
+/**
+ * dma_contiguous_reserve_area() - reserve custom contiguous area
+ * @size: Size of the reserved area (in bytes),
+ * @base: Pointer to the base address of the reserved area, also used to return
+ * base address of the actually reserved area, optional, use pointer to
+ * 0 for any
+>>>>>>> patched
* @limit: End address of the reserved memory (optional, 0 for any).
* @res_cma: Pointer to store the created cma region.
* @fixed: hint about where to place the reserved area
@@ -156,6 +404,7 @@ void __init dma_contiguous_reserve(phys_addr_t limit)
* memory. This function allows to create custom reserved areas for specific
* devices.
*
+<<<<<<< current
* If @fixed is true, reserve contiguous area at exactly @base. If false,
* reserve in range from @base to @limit.
*/
@@ -174,6 +423,200 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
cma_get_size(*res_cma));
return 0;
+=======
+ * This function reserves memory from early allocator. It should be
+ * called by arch specific code once the early allocator (memblock or bootmem)
+ * has been activated and all other subsystems have already allocated/reserved
+ * memory. This function allows to create custom reserved areas for specific
+ * devices.
+ */
+int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t *res_base,
+ phys_addr_t limit, const char *name,
+ bool to_system, bool remove)
+{
+ phys_addr_t base = *res_base;
+ phys_addr_t alignment = PAGE_SIZE;
+ int ret = 0;
+
+ pr_debug("%s(size %lx, base %pa, limit %pa)\n", __func__,
+ (unsigned long)size, &base,
+ &limit);
+
+ /* Sanity checks */
+ if (cma_area_count == ARRAY_SIZE(cma_areas)) {
+ pr_err("Not enough slots for CMA reserved regions!\n");
+ return -ENOSPC;
+ }
+
+ if (!size)
+ return -EINVAL;
+
+ /* Sanitise input arguments */
+ if (!remove)
+ alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
+ base = ALIGN(base, alignment);
+ size = ALIGN(size, alignment);
+ limit &= ~(alignment - 1);
+
+ /* Reserve memory */
+ if (base) {
+ if (memblock_is_region_reserved(base, size) ||
+ memblock_reserve(base, size) < 0) {
+ ret = -EBUSY;
+ goto err;
+ }
+ } else {
+ /*
+ * Use __memblock_alloc_base() since
+ * memblock_alloc_base() panic()s.
+ */
+ phys_addr_t addr = __memblock_alloc_base(size, alignment, limit);
+ if (!addr) {
+ ret = -ENOMEM;
+ goto err;
+ } else {
+ base = addr;
+ }
+ }
+
+ if (remove) {
+ if (!to_system) {
+ memblock_free(base, size);
+ memblock_remove(base, size);
+ } else {
+ WARN(1, "Removing is incompatible with staying in the system\n");
+ }
+ }
+
+ /*
+ * Each reserved area must be initialised later, when more kernel
+ * subsystems (like slab allocator) are available.
+ */
+ cma_areas[cma_area_count].base = base;
+ cma_areas[cma_area_count].size = size;
+ cma_areas[cma_area_count].name = name;
+ cma_areas[cma_area_count].to_system = to_system;
+ cma_area_count++;
+ *res_base = base;
+
+ pr_info("CMA: reserved %ld MiB at %pa\n", (unsigned long)size / SZ_1M,
+ &base);
+
+ /* Architecture specific contiguous memory fixup. */
+ if (!remove)
+ dma_contiguous_early_fixup(base, size);
+ return 0;
+err:
+ pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M);
+ return ret;
+}
+
+/**
+ * dma_contiguous_add_device() - add device to custom contiguous reserved area
+ * @dev: Pointer to device structure.
+ * @base: Pointer to the base address of the reserved area returned by
+ * dma_contiguous_reserve_area() function, also used to return
+ *
+ * This function assigns the given device to the contiguous memory area
+ * reserved earlier by dma_contiguous_reserve_area() function.
+ */
+int __init dma_contiguous_add_device(struct device *dev, phys_addr_t base)
+{
+ if (cma_map_count == ARRAY_SIZE(cma_maps)) {
+ pr_err("Not enough slots for CMA reserved regions!\n");
+ return -ENOSPC;
+ }
+ cma_maps[cma_map_count].dev = dev;
+ cma_maps[cma_map_count].base = base;
+ cma_map_count++;
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static void cma_assign_device_from_dt(struct device *dev)
+{
+ struct device_node *node;
+ struct cma *cma;
+ const char *name;
+ u32 value;
+
+ node = of_parse_phandle(dev->of_node, "linux,contiguous-region", 0);
+ if (!node)
+ return;
+ if (of_property_read_u32(node, "reg", &value) && !value)
+ return;
+
+ if (of_property_read_string(node, "label", &name))
+ return;
+
+ cma = cma_get_area_by_name(name);
+ if (!cma)
+ return;
+
+ dev_set_cma_area(dev, cma);
+
+ if (of_property_read_bool(node, "linux,remove-completely"))
+ set_dma_ops(dev, &removed_dma_ops);
+
+ pr_info("Assigned CMA region at %lx to %s device\n", (unsigned long)value, dev_name(dev));
+}
+
+static int cma_device_init_notifier_call(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct device *dev = data;
+ if (event == BUS_NOTIFY_ADD_DEVICE && dev->of_node)
+ cma_assign_device_from_dt(dev);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block cma_dev_init_nb = {
+ .notifier_call = cma_device_init_notifier_call,
+};
+#endif
+
+static int __init cma_init_reserved_areas(void)
+{
+ struct cma *cma;
+ int i;
+
+ for (i = 0; i < cma_area_count; i++) {
+ phys_addr_t base = PFN_DOWN(cma_areas[i].base);
+ unsigned int count = cma_areas[i].size >> PAGE_SHIFT;
+ bool system = cma_areas[i].to_system;
+
+ cma = cma_create_area(base, count, system);
+ if (!IS_ERR(cma))
+ cma_areas[i].cma = cma;
+ }
+
+ dma_contiguous_def_area = cma_get_area(dma_contiguous_def_base);
+
+ for (i = 0; i < cma_map_count; i++) {
+ cma = cma_get_area(cma_maps[i].base);
+ dev_set_cma_area(cma_maps[i].dev, cma);
+ }
+
+#ifdef CONFIG_OF
+ bus_register_notifier(&platform_bus_type, &cma_dev_init_nb);
+#endif
+ return 0;
+}
+core_initcall(cma_init_reserved_areas);
+
+phys_addr_t cma_get_base(struct device *dev)
+{
+ struct cma *cma = dev_get_cma_area(dev);
+
+ return cma->base_pfn << PAGE_SHIFT;
+}
+
+static void clear_cma_bitmap(struct cma *cma, unsigned long pfn, int count)
+{
+ mutex_lock(&cma->lock);
+ bitmap_clear(cma->bitmap, pfn - cma->base_pfn, count);
+ mutex_unlock(&cma->lock);
+>>>>>>> patched
}
/**
@@ -187,13 +630,77 @@ int __init dma_contiguous_reserve_area(phys_addr_t size, phys_addr_t base,
* global one. Requires architecture specific dev_get_cma_area() helper
* function.
*/
-struct page *dma_alloc_from_contiguous(struct device *dev, int count,
+unsigned long dma_alloc_from_contiguous(struct device *dev, int count,
unsigned int align)
{
+<<<<<<< current
if (align > CONFIG_CMA_ALIGNMENT)
align = CONFIG_CMA_ALIGNMENT;
return cma_alloc(dev_get_cma_area(dev), count, align);
+=======
+ unsigned long mask, pfn = 0, pageno, start = 0;
+ struct cma *cma = dev_get_cma_area(dev);
+ int ret = 0;
+ int tries = 0;
+
+ if (!cma || !cma->count)
+ return 0;
+
+ if (align > CONFIG_CMA_ALIGNMENT)
+ align = CONFIG_CMA_ALIGNMENT;
+
+ pr_debug("%s(cma %p, count %d, align %d)\n", __func__, (void *)cma,
+ count, align);
+
+ if (!count)
+ return 0;
+
+ mask = (1 << align) - 1;
+
+
+ for (;;) {
+ mutex_lock(&cma->lock);
+ pageno = bitmap_find_next_zero_area(cma->bitmap, cma->count,
+ start, count, mask);
+ if (pageno >= cma->count) {
+ pfn = 0;
+ mutex_unlock(&cma->lock);
+ break;
+ }
+ bitmap_set(cma->bitmap, pageno, count);
+ /*
+ * It's safe to drop the lock here. We've marked this region for
+ * our exclusive use. If the migration fails we will take the
+ * lock again and unmark it.
+ */
+ mutex_unlock(&cma->lock);
+
+ pfn = cma->base_pfn + pageno;
+ if (cma->in_system) {
+ mutex_lock(&cma_mutex);
+ ret = alloc_contig_range(pfn, pfn + count, MIGRATE_CMA);
+ mutex_unlock(&cma_mutex);
+ }
+ if (ret == 0) {
+ break;
+ } else if (ret != -EBUSY) {
+ pfn = 0;
+ clear_cma_bitmap(cma, pfn, count);
+ break;
+ }
+ clear_cma_bitmap(cma, pfn, count);
+ tries++;
+
+ pr_debug("%s(): memory range at %p is busy, retrying\n",
+ __func__, pfn_to_page(pfn));
+ /* try again with a bit different memory target */
+ start = pageno + mask + 1;
+ }
+
+ pr_debug("%s(): returned %lx\n", __func__, pfn);
+ return pfn;
+>>>>>>> patched
}
/**
@@ -206,9 +713,10 @@ struct page *dma_alloc_from_contiguous(struct device *dev, int count,
* It returns false when provided pages do not belong to contiguous area and
* true otherwise.
*/
-bool dma_release_from_contiguous(struct device *dev, struct page *pages,
+bool dma_release_from_contiguous(struct device *dev, unsigned long pfn,
int count)
{
+<<<<<<< current
return cma_release(dev_get_cma_area(dev), pages, count);
}
@@ -228,6 +736,14 @@ static int rmem_cma_device_init(struct reserved_mem *rmem, struct device *dev)
dev_set_cma_area(dev, rmem->priv);
return 0;
}
+=======
+ struct cma *cma = dev_get_cma_area(dev);
+
+ if (!cma || !pfn)
+ return false;
+
+ pr_debug("%s(pfn %lx)\n", __func__, pfn);
+>>>>>>> patched
static void rmem_cma_device_release(struct reserved_mem *rmem,
struct device *dev)
@@ -248,9 +764,15 @@ static int __init rmem_cma_setup(struct reserved_mem *rmem)
struct cma *cma;
int err;
+<<<<<<< current
if (!of_get_flat_dt_prop(node, "reusable", NULL) ||
of_get_flat_dt_prop(node, "no-map", NULL))
return -EINVAL;
+=======
+ if (cma->in_system)
+ free_contig_range(pfn, count);
+ clear_cma_bitmap(cma, pfn, count);
+>>>>>>> patched
if ((rmem->base & mask) || (rmem->size & mask)) {
pr_err("Reserved memory: incorrect alignment of CMA region\n");
diff --git a/drivers/base/dma-removed.c b/drivers/base/dma-removed.c
new file mode 100644
index 000000000000..45c0bf0c05e5
--- /dev/null
+++ b/drivers/base/dma-removed.c
@@ -0,0 +1,162 @@
+/*
+ *
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2000-2004 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/gfp.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-contiguous.h>
+#include <linux/highmem.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+#include <linux/iommu.h>
+#include <linux/io.h>
+#include <linux/vmalloc.h>
+#include <linux/sizes.h>
+
+#define NO_KERNEL_MAPPING_DUMMY 0x2222
+
+void *removed_alloc(struct device *dev, size_t size, dma_addr_t *handle,
+ gfp_t gfp, struct dma_attrs *attrs)
+{
+ bool no_kernel_mapping = dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING,
+ attrs);
+ bool skip_zeroing = dma_get_attr(DMA_ATTR_SKIP_ZEROING, attrs);
+ unsigned long pfn;
+ unsigned long order = get_order(size);
+ void *addr = NULL;
+
+ size = PAGE_ALIGN(size);
+
+ if (!(gfp & __GFP_WAIT))
+ return NULL;
+
+ pfn = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT, order);
+
+ if (pfn) {
+ if (no_kernel_mapping && skip_zeroing) {
+ *handle = __pfn_to_phys(pfn);
+ return (void *)NO_KERNEL_MAPPING_DUMMY;
+ }
+
+ addr = ioremap(__pfn_to_phys(pfn), size);
+ if (WARN_ON(!addr)) {
+ dma_release_from_contiguous(dev, pfn, order);
+ } else {
+ if (!skip_zeroing)
+ memset(addr, 0, size);
+ if (no_kernel_mapping) {
+ iounmap(addr);
+ addr = (void *)NO_KERNEL_MAPPING_DUMMY;
+ }
+ *handle = __pfn_to_phys(pfn);
+ }
+ }
+
+ return addr;
+}
+
+
+int removed_mmap(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
+ struct dma_attrs *attrs)
+{
+ return -ENXIO;
+}
+
+void removed_free(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle, struct dma_attrs *attrs)
+{
+ bool no_kernel_mapping = dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING,
+ attrs);
+
+ if (!no_kernel_mapping)
+ iounmap(cpu_addr);
+ dma_release_from_contiguous(dev, __phys_to_pfn(handle),
+ size >> PAGE_SHIFT);
+}
+
+static dma_addr_t removed_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ return ~(dma_addr_t)0;
+}
+
+static void removed_unmap_page(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ return;
+}
+
+static int removed_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ return 0;
+}
+
+static void removed_unmap_sg(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ return;
+}
+
+static void removed_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ return;
+}
+
+void removed_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ return;
+}
+
+void removed_sync_sg_for_cpu(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ return;
+}
+
+void removed_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ return;
+}
+
+struct dma_map_ops removed_dma_ops = {
+ .alloc = removed_alloc,
+ .free = removed_free,
+ .mmap = removed_mmap,
+ .map_page = removed_map_page,
+ .unmap_page = removed_unmap_page,
+ .map_sg = removed_map_sg,
+ .unmap_sg = removed_unmap_sg,
+ .sync_single_for_cpu = removed_sync_single_for_cpu,
+ .sync_single_for_device = removed_sync_single_for_device,
+ .sync_sg_for_cpu = removed_sync_sg_for_cpu,
+ .sync_sg_for_device = removed_sync_sg_for_device,
+};
+EXPORT_SYMBOL(removed_dma_ops);
+
+
diff --git a/drivers/clocksource/qcom-timer.c b/drivers/clocksource/qcom-timer.c
index 098c542e5c53..86e70efc9bb7 100644
--- a/drivers/clocksource/qcom-timer.c
+++ b/drivers/clocksource/qcom-timer.c
@@ -1,5 +1,4 @@
/*
- *
* Copyright (C) 2007 Google, Inc.
* Copyright (c) 2009-2012,2014, The Linux Foundation. All rights reserved.
*
@@ -14,36 +13,196 @@
*
*/
+#include <linux/module.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/cpu.h>
#include <linux/init.h>
+#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/sched_clock.h>
#include <asm/delay.h>
+#include <linux/percpu.h>
+#include <linux/mm.h>
+#include <linux/sched_clock.h>
+
+#include <asm/localtimer.h>
+#include <asm/mach/time.h>
+#include <asm/smp_plat.h>
+#include <asm/user_accessible_timer.h>
+#include <mach/msm_iomap.h>
+#include <mach/irqs.h>
+#include <soc/qcom/socinfo.h>
+
+#include <soc/qcom/smem.h>
+#if defined(CONFIG_MSM_SMD)
+#include <soc/qcom/smsm.h>
+#endif
+#include "timer.h"
+
+enum {
+ MSM_TIMER_DEBUG_SYNC = 1U << 0,
+};
+static int msm_timer_debug_mask;
+module_param_named(debug_mask, msm_timer_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#ifdef CONFIG_MSM7X00A_USE_GP_TIMER
+ #define DG_TIMER_RATING 100
+#else
+ #define DG_TIMER_RATING 300
+#endif
+
+#ifndef MSM_TMR0_BASE
+#define MSM_TMR0_BASE MSM_TMR_BASE
+#endif
+
+#define MSM_DGT_SHIFT (5)
+
+#define TIMER_MATCH_VAL 0x0000
+#define TIMER_COUNT_VAL 0x0004
+#define TIMER_ENABLE 0x0008
+#define TIMER_CLEAR 0x000C
+#define DGT_CLK_CTL 0x0034
+enum {
+ DGT_CLK_CTL_DIV_1 = 0,
+ DGT_CLK_CTL_DIV_2 = 1,
+ DGT_CLK_CTL_DIV_3 = 2,
+ DGT_CLK_CTL_DIV_4 = 3,
+};
+#define TIMER_STATUS 0x0088
+#define TIMER_ENABLE_EN 1
+#define TIMER_ENABLE_CLR_ON_MATCH_EN 2
+
+#define LOCAL_TIMER 0
+#define GLOBAL_TIMER 1
-#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)
+/*
+ * global_timer_offset is added to the regbase of a timer to force the memory
+ * access to come from the CPU0 region.
+ */
+static int global_timer_offset;
+static int msm_global_timer;
+
+#define NR_TIMERS ARRAY_SIZE(msm_clocks)
-#define GPT_HZ 32768
+unsigned int gpt_hz = 32768;
+unsigned int sclk_hz = 32768;
-#define MSM_DGT_SHIFT 5
+static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt);
+static irqreturn_t msm_timer_interrupt(int irq, void *dev_id);
+static cycle_t msm_gpt_read(struct clocksource *cs);
+static cycle_t msm_dgt_read(struct clocksource *cs);
+static void msm_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt);
+static int msm_timer_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt);
+
+enum {
+ MSM_CLOCK_FLAGS_UNSTABLE_COUNT = 1U << 0,
+ MSM_CLOCK_FLAGS_ODD_MATCH_WRITE = 1U << 1,
+ MSM_CLOCK_FLAGS_DELAYED_WRITE_POST = 1U << 2,
+};
+
+struct msm_clock {
+ struct clock_event_device clockevent;
+ struct clocksource clocksource;
+ unsigned int irq;
+ void __iomem *regbase;
+ uint32_t freq;
+ uint32_t shift;
+ uint32_t flags;
+ uint32_t write_delay;
+ uint32_t rollover_offset;
+ uint32_t index;
+ void __iomem *global_counter;
+ void __iomem *local_counter;
+ uint32_t status_mask;
+ union {
+ struct clock_event_device *evt;
+ struct clock_event_device __percpu **percpu_evt;
+ };
+};
-static void __iomem *event_base;
-static void __iomem *sts_base;
+enum {
+ MSM_CLOCK_GPT,
+ MSM_CLOCK_DGT,
+};
+
+struct msm_clock_percpu_data {
+ uint32_t last_set;
+ uint32_t sleep_offset;
+ uint32_t alarm_vtime;
+ uint32_t alarm;
+ uint32_t non_sleep_offset;
+ uint32_t in_sync;
+ cycle_t stopped_tick;
+ int stopped;
+ uint32_t last_sync_gpt;
+ u64 last_sync_jiffies;
+};
+
+struct msm_timer_sync_data_t {
+ struct msm_clock *clock;
+ uint32_t timeout;
+ int exit_sleep;
+};
+
+static struct msm_clock msm_clocks[] = {
+ [MSM_CLOCK_GPT] = {
+ .clockevent = {
+ .name = "gp_timer",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .rating = 200,
+ .set_next_event = msm_timer_set_next_event,
+ .set_mode = msm_timer_set_mode,
+ },
+ .clocksource = {
+ .name = "gp_timer",
+ .rating = 200,
+ .read = msm_gpt_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ },
+ .irq = INT_GP_TIMER_EXP,
+ .regbase = MSM_TMR_BASE + 0x4,
+ .freq = 32768,
+ .index = MSM_CLOCK_GPT,
+ .write_delay = 9,
+ },
+ [MSM_CLOCK_DGT] = {
+ .clockevent = {
+ .name = "dg_timer",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 32,
+ .rating = DG_TIMER_RATING,
+ .set_next_event = msm_timer_set_next_event,
+ .set_mode = msm_timer_set_mode,
+ },
+ .clocksource = {
+ .name = "dg_timer",
+ .rating = DG_TIMER_RATING,
+ .read = msm_dgt_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ },
+ .irq = INT_DEBUG_TIMER_EXP,
+ .regbase = MSM_TMR_BASE + 0x24,
+ .index = MSM_CLOCK_DGT,
+ .write_delay = 9,
+ }
+};
+
+static DEFINE_PER_CPU(struct msm_clock_percpu_data[NR_TIMERS],
+ msm_clocks_percpu);
+
+static DEFINE_PER_CPU(struct msm_clock *, msm_active_clock);
static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
{
@@ -58,45 +217,182 @@ static irqreturn_t msm_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
+static uint32_t msm_read_timer_count(struct msm_clock *clock, int global)
+{
+ uint32_t t1, t2, t3;
+ int loop_count = 0;
+ void __iomem *addr = clock->regbase + TIMER_COUNT_VAL +
+ global*global_timer_offset;
+
+ if (!(clock->flags & MSM_CLOCK_FLAGS_UNSTABLE_COUNT))
+ return __raw_readl_no_log(addr);
+
+ t1 = __raw_readl_no_log(addr);
+ t2 = __raw_readl_no_log(addr);
+ if ((t2-t1) <= 1)
+ return t2;
+ while (1) {
+ t1 = __raw_readl_no_log(addr);
+ t2 = __raw_readl_no_log(addr);
+ t3 = __raw_readl_no_log(addr);
+ cpu_relax();
+ if ((t3-t2) <= 1)
+ return t3;
+ if ((t2-t1) <= 1)
+ return t2;
+ if ((t2 >= t1) && (t3 >= t2))
+ return t2;
+ if (++loop_count == 5) {
+ pr_err("msm_read_timer_count timer %s did not "
+ "stabilize: %u -> %u -> %u\n",
+ clock->clockevent.name, t1, t2, t3);
+ return t3;
+ }
+ }
+}
+
+static cycle_t msm_gpt_read(struct clocksource *cs)
+{
+ struct msm_clock *clock = &msm_clocks[MSM_CLOCK_GPT];
+ struct msm_clock_percpu_data *clock_state =
+ &per_cpu(msm_clocks_percpu, 0)[MSM_CLOCK_GPT];
+
+ if (clock_state->stopped)
+ return clock_state->stopped_tick;
+
+ return msm_read_timer_count(clock, GLOBAL_TIMER) +
+ clock_state->sleep_offset;
+}
+
+static cycle_t msm_dgt_read(struct clocksource *cs)
+{
+ struct msm_clock *clock = &msm_clocks[MSM_CLOCK_DGT];
+ struct msm_clock_percpu_data *clock_state =
+ &per_cpu(msm_clocks_percpu, 0)[MSM_CLOCK_DGT];
+
+ if (clock_state->stopped)
+ return clock_state->stopped_tick >> clock->shift;
+
+ return (msm_read_timer_count(clock, GLOBAL_TIMER) +
+ clock_state->sleep_offset) >> clock->shift;
+}
+
+static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt)
+{
+ int i;
+
+ if (!is_smp())
+ return container_of(evt, struct msm_clock, clockevent);
+
+ for (i = 0; i < NR_TIMERS; i++)
+ if (evt == &(msm_clocks[i].clockevent))
+ return &msm_clocks[i];
+ return &msm_clocks[msm_global_timer];
+}
+
static int msm_timer_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
- u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
+ int i;
+ struct msm_clock *clock;
+ struct msm_clock_percpu_data *clock_state;
+ uint32_t now;
+ uint32_t alarm;
+ int late;
- ctrl &= ~TIMER_ENABLE_EN;
- writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+ clock = clockevent_to_clock(evt);
+ clock_state = &__get_cpu_var(msm_clocks_percpu)[clock->index];
+ now = msm_read_timer_count(clock, LOCAL_TIMER);
+ alarm = now + (cycles << clock->shift);
+ if (clock->flags & MSM_CLOCK_FLAGS_ODD_MATCH_WRITE)
+ while (now == clock_state->last_set)
+ now = msm_read_timer_count(clock, LOCAL_TIMER);
- writel_relaxed(ctrl, event_base + TIMER_CLEAR);
- writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
+ clock_state->alarm = alarm;
+ __raw_writel(alarm, clock->regbase + TIMER_MATCH_VAL);
- if (sts_base)
- while (readl_relaxed(sts_base) & TIMER_STS_GPT0_CLR_PEND)
- cpu_relax();
+ if (clock->flags & MSM_CLOCK_FLAGS_DELAYED_WRITE_POST) {
+ /* read the counter four extra times to make sure write posts
+ before reading the time */
+ for (i = 0; i < 4; i++)
+ __raw_readl_no_log(clock->regbase + TIMER_COUNT_VAL);
+ }
+ now = msm_read_timer_count(clock, LOCAL_TIMER);
+ clock_state->last_set = now;
+ clock_state->alarm_vtime = alarm + clock_state->sleep_offset;
+ late = now - alarm;
+ if (late >= (int)(-clock->write_delay << clock->shift) &&
+ late < clock->freq*5)
+ return -ETIME;
- 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)
+ struct clock_event_device *evt)
{
- u32 ctrl;
+ struct msm_clock *clock;
+ struct msm_clock **cur_clock;
+ struct msm_clock_percpu_data *clock_state, *gpt_state;
+ unsigned long irq_flags;
+ struct irq_chip *chip;
- ctrl = readl_relaxed(event_base + TIMER_ENABLE);
- ctrl &= ~(TIMER_ENABLE_EN | TIMER_ENABLE_CLR_ON_MATCH_EN);
+ clock = clockevent_to_clock(evt);
+ clock_state = &__get_cpu_var(msm_clocks_percpu)[clock->index];
+ gpt_state = &__get_cpu_var(msm_clocks_percpu)[MSM_CLOCK_GPT];
+
+ local_irq_save(irq_flags);
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 */
+ clock_state->stopped = 0;
+ clock_state->sleep_offset =
+ -msm_read_timer_count(clock, LOCAL_TIMER) +
+ clock_state->stopped_tick;
+ get_cpu_var(msm_active_clock) = clock;
+ put_cpu_var(msm_active_clock);
+ __raw_writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE);
+ chip = irq_get_chip(clock->irq);
+ if (chip && chip->irq_unmask)
+ chip->irq_unmask(irq_get_irq_data(clock->irq));
+ if (clock != &msm_clocks[MSM_CLOCK_GPT])
+ __raw_writel(TIMER_ENABLE_EN,
+ msm_clocks[MSM_CLOCK_GPT].regbase +
+ TIMER_ENABLE);
break;
case CLOCK_EVT_MODE_UNUSED:
case CLOCK_EVT_MODE_SHUTDOWN:
+ cur_clock = &get_cpu_var(msm_active_clock);
+ if (*cur_clock == clock)
+ *cur_clock = NULL;
+ put_cpu_var(msm_active_clock);
+ clock_state->in_sync = 0;
+ clock_state->stopped = 1;
+ clock_state->stopped_tick =
+ msm_read_timer_count(clock, LOCAL_TIMER) +
+ clock_state->sleep_offset;
+ __raw_writel(0, clock->regbase + TIMER_MATCH_VAL);
+ chip = irq_get_chip(clock->irq);
+ if (chip && chip->irq_mask)
+ chip->irq_mask(irq_get_irq_data(clock->irq));
+
+ if (!is_smp() || clock != &msm_clocks[MSM_CLOCK_DGT]
+ || smp_processor_id())
+ __raw_writel(0, clock->regbase + TIMER_ENABLE);
+
+ if (msm_global_timer == MSM_CLOCK_DGT &&
+ clock != &msm_clocks[MSM_CLOCK_GPT]) {
+ gpt_state->in_sync = 0;
+ __raw_writel(0, msm_clocks[MSM_CLOCK_GPT].regbase +
+ TIMER_ENABLE);
+ }
break;
}
- writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+ wmb();
+ local_irq_restore(irq_flags);
}
static struct clock_event_device __percpu *msm_evt;
@@ -104,8 +400,10 @@ static struct clock_event_device __percpu *msm_evt;
static void __iomem *source_base;
static notrace cycle_t msm_read_timer_count(struct clocksource *cs)
+
+void __iomem *msm_timer_get_timer0_base(void)
{
- return readl_relaxed(source_base + TIMER_COUNT_VAL);
+ return MSM_TMR_BASE + global_timer_offset;
}
static struct clocksource msm_clocksource = {
@@ -147,12 +445,77 @@ static int msm_local_timer_setup(struct clock_event_device *evt)
return 0;
}
-static void msm_local_timer_stop(struct clock_event_device *evt)
+#define MPM_SCLK_COUNT_VAL 0x0024
+
+#ifdef CONFIG_PM
+/*
+ * Retrieve the cycle count from sclk and optionally synchronize local clock
+ * with the sclk value.
+ *
+ * time_start and time_expired are callbacks that must be specified. The
+ * protocol uses them to detect timeout. The update callback is optional.
+ * If not NULL, update will be called so that it can update local clock.
+ *
+ * The function does not use the argument data directly; it passes data to
+ * the callbacks.
+ *
+ * Return value:
+ * 0: the operation failed
+ * >0: the slow clock value after time-sync
+ */
+static void (*msm_timer_sync_timeout)(void);
+#if defined(CONFIG_MSM_DIRECT_SCLK_ACCESS)
+uint32_t msm_timer_get_sclk_ticks(void)
{
- evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
- disable_percpu_irq(evt->irq);
+ uint32_t t1, t2;
+ int loop_count = 10;
+ int loop_zero_count = 3;
+ int tmp = USEC_PER_SEC;
+ do_div(tmp, sclk_hz);
+ tmp /= (loop_zero_count-1);
+
+ while (loop_zero_count--) {
+ t1 = __raw_readl_no_log(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
+ do {
+ udelay(1);
+ t2 = t1;
+ t1 = __raw_readl_no_log(
+ MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
+ } while ((t2 != t1) && --loop_count);
+
+ if (!loop_count) {
+ printk(KERN_EMERG "SCLK did not stabilize\n");
+ return 0;
+ }
+
+ if (t1)
+ break;
+
+ udelay(tmp);
+ }
+
+ if (!loop_zero_count) {
+ printk(KERN_EMERG "SCLK reads zero\n");
+ return 0;
+ }
+
+ return t1;
}
+static uint32_t msm_timer_do_sync_to_sclk(
+ void (*time_start)(struct msm_timer_sync_data_t *data),
+ bool (*time_expired)(struct msm_timer_sync_data_t *data),
+ void (*update)(struct msm_timer_sync_data_t *, uint32_t, uint32_t),
+ struct msm_timer_sync_data_t *data)
+{
+ unsigned t1 = msm_timer_get_sclk_ticks();
+
+ if (t1 && update != NULL)
+ update(data, t1, sclk_hz);
+ return t1;
+}
+#else
+
static int msm_timer_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
@@ -230,8 +593,97 @@ err:
sched_clock_register(msm_sched_clock_read, sched_bits, dgt_hz);
msm_delay_timer.freq = dgt_hz;
register_current_timer_delay(&msm_delay_timer);
+
+}
+
+/* Time Master State Bits */
+#define MASTER_BITS_PER_CPU 1
+#define MASTER_TIME_PENDING \
+ (0x01UL << (MASTER_BITS_PER_CPU * SMSM_APPS_STATE))
+
+/* Time Slave State Bits */
+#define SLAVE_TIME_REQUEST 0x0400
+#define SLAVE_TIME_POLL 0x0800
+#define SLAVE_TIME_INIT 0x1000
+
+static uint32_t msm_timer_do_sync_to_sclk(
+ void (*time_start)(struct msm_timer_sync_data_t *data),
+ bool (*time_expired)(struct msm_timer_sync_data_t *data),
+ void (*update)(struct msm_timer_sync_data_t *, uint32_t, uint32_t),
+ struct msm_timer_sync_data_t *data)
+{
+ uint32_t *smem_clock;
+ uint32_t smem_clock_val;
+ uint32_t state;
+
+ smem_clock = smem_find(SMEM_SMEM_SLOW_CLOCK_VALUE,
+ sizeof(uint32_t), 0, SMEM_ANY_HOST_FLAG);
+ if (smem_clock == NULL) {
+ printk(KERN_ERR "no smem clock\n");
+ return 0;
+ }
+
+ state = smsm_get_state(SMSM_MODEM_STATE);
+ if ((state & SMSM_INIT) == 0) {
+ printk(KERN_ERR "smsm not initialized\n");
+ return 0;
+ }
+
+ time_start(data);
+ while ((state = smsm_get_state(SMSM_TIME_MASTER_DEM)) &
+ MASTER_TIME_PENDING) {
+ if (time_expired(data)) {
+ printk(KERN_EMERG "get_smem_clock: timeout 1 still "
+ "invalid state %x\n", state);
+ msm_timer_sync_timeout();
+ }
+ }
+
+ smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_POLL | SLAVE_TIME_INIT,
+ SLAVE_TIME_REQUEST);
+
+ time_start(data);
+ while (!((state = smsm_get_state(SMSM_TIME_MASTER_DEM)) &
+ MASTER_TIME_PENDING)) {
+ if (time_expired(data)) {
+ printk(KERN_EMERG "get_smem_clock: timeout 2 still "
+ "invalid state %x\n", state);
+ msm_timer_sync_timeout();
+ }
+ }
+
+ smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_REQUEST, SLAVE_TIME_POLL);
+
+ time_start(data);
+ do {
+ smem_clock_val = *smem_clock;
+ } while (smem_clock_val == 0 && !time_expired(data));
+
+ state = smsm_get_state(SMSM_TIME_MASTER_DEM);
+
+ if (smem_clock_val) {
+ if (update != NULL)
+ update(data, smem_clock_val, sclk_hz);
+
+ if (msm_timer_debug_mask & MSM_TIMER_DEBUG_SYNC)
+ printk(KERN_INFO
+ "get_smem_clock: state %x clock %u\n",
+ state, smem_clock_val);
+ } else {
+ printk(KERN_EMERG
+ "get_smem_clock: timeout state %x clock %u\n",
+ state, smem_clock_val);
+ msm_timer_sync_timeout();
+ }
+
+ smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_REQUEST | SLAVE_TIME_POLL,
+ SLAVE_TIME_INIT);
+ return smem_clock_val;
+>>>>>>> patched:arch/arm/mach-msm/timer.c
}
+#endif /* CONFIG_MSM_DIRECT_SCLK_ACCESS */
+<<<<<<< current:drivers/clocksource/qcom-timer.c
#ifdef CONFIG_ARCH_QCOM
static void __init msm_dt_timer_init(struct device_node *np)
{
@@ -246,65 +698,394 @@ static void __init msm_dt_timer_init(struct device_node *np)
if (!base) {
pr_err("Failed to map event base\n");
return;
+=======
+/*
+ * Callback function that initializes the timeout value.
+ */
+static void msm_timer_sync_to_sclk_time_start(
+ struct msm_timer_sync_data_t *data)
+{
+ /* approx 2 seconds */
+ uint32_t delta = data->clock->freq << data->clock->shift << 1;
+ data->timeout = msm_read_timer_count(data->clock, LOCAL_TIMER) + delta;
+}
+
+/*
+ * Callback function that checks the timeout.
+ */
+static bool msm_timer_sync_to_sclk_time_expired(
+ struct msm_timer_sync_data_t *data)
+{
+ uint32_t delta = msm_read_timer_count(data->clock, LOCAL_TIMER) -
+ data->timeout;
+ return ((int32_t) delta) > 0;
+}
+
+/*
+ * Callback function that updates local clock from the specified source clock
+ * value and frequency.
+ */
+static void msm_timer_sync_update(struct msm_timer_sync_data_t *data,
+ uint32_t src_clk_val, uint32_t src_clk_freq)
+{
+ struct msm_clock *dst_clk = data->clock;
+ struct msm_clock_percpu_data *dst_clk_state =
+ &__get_cpu_var(msm_clocks_percpu)[dst_clk->index];
+ uint32_t dst_clk_val = msm_read_timer_count(dst_clk, LOCAL_TIMER);
+ uint32_t new_offset;
+
+ if ((dst_clk->freq << dst_clk->shift) == src_clk_freq) {
+ new_offset = src_clk_val - dst_clk_val;
+ } else {
+ uint64_t temp;
+
+ /* separate multiplication and division steps to reduce
+ rounding error */
+ temp = src_clk_val;
+ temp *= dst_clk->freq << dst_clk->shift;
+ do_div(temp, src_clk_freq);
+
+ new_offset = (uint32_t)(temp) - dst_clk_val;
}
- /* 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;
+ if (dst_clk_state->sleep_offset + dst_clk_state->non_sleep_offset !=
+ new_offset) {
+ if (data->exit_sleep)
+ dst_clk_state->sleep_offset =
+ new_offset - dst_clk_state->non_sleep_offset;
+ else
+ dst_clk_state->non_sleep_offset =
+ new_offset - dst_clk_state->sleep_offset;
+
+ if (msm_timer_debug_mask & MSM_TIMER_DEBUG_SYNC)
+ printk(KERN_INFO "sync clock %s: "
+ "src %u, new offset %u + %u\n",
+ dst_clk->clocksource.name, src_clk_val,
+ dst_clk_state->sleep_offset,
+ dst_clk_state->non_sleep_offset);
+>>>>>>> patched:arch/arm/mach-msm/timer.c
}
+}
- /* We use CPU0's DGT for the clocksource */
- if (of_property_read_u32(np, "cpu-offset", &percpu_offset))
- percpu_offset = 0;
+/*
+ * Synchronize GPT clock with sclk.
+ */
+static void msm_timer_sync_gpt_to_sclk(int exit_sleep)
+{
+ struct msm_clock *gpt_clk = &msm_clocks[MSM_CLOCK_GPT];
+ struct msm_clock_percpu_data *gpt_clk_state =
+ &__get_cpu_var(msm_clocks_percpu)[MSM_CLOCK_GPT];
+ struct msm_timer_sync_data_t data;
+ uint32_t ret;
- if (of_address_to_resource(np, 0, &res)) {
- pr_err("Failed to parse DGT resource\n");
+ if (gpt_clk_state->in_sync)
return;
- }
- cpu0_base = ioremap(res.start + percpu_offset, resource_size(&res));
- if (!cpu0_base) {
- pr_err("Failed to map source base\n");
+ data.clock = gpt_clk;
+ data.timeout = 0;
+ data.exit_sleep = exit_sleep;
+
+ ret = msm_timer_do_sync_to_sclk(
+ msm_timer_sync_to_sclk_time_start,
+ msm_timer_sync_to_sclk_time_expired,
+ msm_timer_sync_update,
+ &data);
+
+ if (ret)
+ gpt_clk_state->in_sync = 1;
+}
+
+/*
+ * Synchronize clock with GPT clock.
+ */
+static void msm_timer_sync_to_gpt(struct msm_clock *clock, int exit_sleep)
+{
+ struct msm_clock *gpt_clk = &msm_clocks[MSM_CLOCK_GPT];
+ struct msm_clock_percpu_data *gpt_clk_state =
+ &__get_cpu_var(msm_clocks_percpu)[MSM_CLOCK_GPT];
+ struct msm_clock_percpu_data *clock_state =
+ &__get_cpu_var(msm_clocks_percpu)[clock->index];
+ struct msm_timer_sync_data_t data;
+ uint32_t gpt_clk_val;
+ u64 gpt_period = (1ULL << 32) * HZ;
+ u64 now = get_jiffies_64();
+
+ do_div(gpt_period, gpt_hz);
+
+ BUG_ON(clock == gpt_clk);
+
+ if (clock_state->in_sync &&
+ (now - clock_state->last_sync_jiffies < (gpt_period >> 1)))
return;
+
+ gpt_clk_val = msm_read_timer_count(gpt_clk, LOCAL_TIMER)
+ + gpt_clk_state->sleep_offset + gpt_clk_state->non_sleep_offset;
+
+ if (exit_sleep && gpt_clk_val < clock_state->last_sync_gpt)
+ clock_state->non_sleep_offset -= clock->rollover_offset;
+
+ data.clock = clock;
+ data.timeout = 0;
+ data.exit_sleep = exit_sleep;
+
+ msm_timer_sync_update(&data, gpt_clk_val, gpt_hz);
+
+ clock_state->in_sync = 1;
+ clock_state->last_sync_gpt = gpt_clk_val;
+ clock_state->last_sync_jiffies = now;
+}
+
+static void msm_timer_reactivate_alarm(struct msm_clock *clock)
+{
+ struct msm_clock_percpu_data *clock_state =
+ &__get_cpu_var(msm_clocks_percpu)[clock->index];
+ long alarm_delta = clock_state->alarm_vtime -
+ clock_state->sleep_offset -
+ msm_read_timer_count(clock, LOCAL_TIMER);
+ alarm_delta >>= clock->shift;
+ if (alarm_delta < (long)clock->write_delay + 4)
+ alarm_delta = clock->write_delay + 4;
+ while (msm_timer_set_next_event(alarm_delta, &clock->clockevent))
+ ;
+}
+
+int64_t msm_timer_enter_idle(void)
+{
+ struct msm_clock *gpt_clk = &msm_clocks[MSM_CLOCK_GPT];
+ struct msm_clock *clock = __get_cpu_var(msm_active_clock);
+ struct msm_clock_percpu_data *clock_state =
+ &__get_cpu_var(msm_clocks_percpu)[clock->index];
+ uint32_t alarm;
+ uint32_t count;
+ int32_t delta;
+
+ BUG_ON(clock != &msm_clocks[MSM_CLOCK_GPT] &&
+ clock != &msm_clocks[MSM_CLOCK_DGT]);
+
+ msm_timer_sync_gpt_to_sclk(0);
+ if (clock != gpt_clk)
+ msm_timer_sync_to_gpt(clock, 0);
+
+ count = msm_read_timer_count(clock, LOCAL_TIMER);
+ if (clock_state->stopped++ == 0)
+ clock_state->stopped_tick = count + clock_state->sleep_offset;
+ alarm = clock_state->alarm;
+ delta = alarm - count;
+ if (delta <= -(int32_t)((clock->freq << clock->shift) >> 10)) {
+ /* timer should have triggered 1ms ago */
+ printk(KERN_ERR "msm_timer_enter_idle: timer late %d, "
+ "reprogram it\n", delta);
+ msm_timer_reactivate_alarm(clock);
}
+ if (delta <= 0)
+ return 0;
+ return clocksource_cyc2ns((alarm - count) >> clock->shift,
+ clock->clocksource.mult,
+ clock->clocksource.shift);
+}
- if (of_property_read_u32(np, "clock-frequency", &freq)) {
- pr_err("Unknown frequency\n");
- return;
+void msm_timer_exit_idle(int low_power)
+{
+ struct msm_clock *gpt_clk = &msm_clocks[MSM_CLOCK_GPT];
+ struct msm_clock *clock = __get_cpu_var(msm_active_clock);
+ struct msm_clock_percpu_data *gpt_clk_state =
+ &__get_cpu_var(msm_clocks_percpu)[MSM_CLOCK_GPT];
+ struct msm_clock_percpu_data *clock_state =
+ &__get_cpu_var(msm_clocks_percpu)[clock->index];
+ uint32_t enabled;
+
+ BUG_ON(clock != &msm_clocks[MSM_CLOCK_GPT] &&
+ clock != &msm_clocks[MSM_CLOCK_DGT]);
+
+ if (!low_power)
+ goto exit_idle_exit;
+
+ enabled = __raw_readl(gpt_clk->regbase + TIMER_ENABLE) &
+ TIMER_ENABLE_EN;
+ if (!enabled)
+ __raw_writel(TIMER_ENABLE_EN, gpt_clk->regbase + TIMER_ENABLE);
+
+#if defined(CONFIG_ARCH_MSM_SCORPION) || defined(CONFIG_ARCH_MSM_KRAIT)
+ gpt_clk_state->in_sync = 0;
+#else
+ gpt_clk_state->in_sync = gpt_clk_state->in_sync && enabled;
+#endif
+ /* Make sure timer is actually enabled before we sync it */
+ wmb();
+ msm_timer_sync_gpt_to_sclk(1);
+
+ if (clock == gpt_clk)
+ goto exit_idle_alarm;
+
+ enabled = __raw_readl(clock->regbase + TIMER_ENABLE) & TIMER_ENABLE_EN;
+ if (!enabled)
+ __raw_writel(TIMER_ENABLE_EN, clock->regbase + TIMER_ENABLE);
+
+#if defined(CONFIG_ARCH_MSM_SCORPION) || defined(CONFIG_ARCH_MSM_KRAIT)
+ clock_state->in_sync = 0;
+#else
+ clock_state->in_sync = clock_state->in_sync && enabled;
+#endif
+ /* Make sure timer is actually enabled before we sync it */
+ wmb();
+ msm_timer_sync_to_gpt(clock, 1);
+
+exit_idle_alarm:
+ msm_timer_reactivate_alarm(clock);
+
+exit_idle_exit:
+ clock_state->stopped--;
+}
+
+/*
+ * Callback function that initializes the timeout value.
+ */
+static void msm_timer_get_sclk_time_start(
+ struct msm_timer_sync_data_t *data)
+{
+ data->timeout = 200000;
+}
+
+/*
+ * Callback function that checks the timeout.
+ */
+static bool msm_timer_get_sclk_time_expired(
+ struct msm_timer_sync_data_t *data)
+{
+ udelay(10);
+ return --data->timeout <= 0;
+}
+
+/*
+ * Retrieve the cycle count from the sclk and convert it into
+ * nanoseconds.
+ *
+ * On exit, if period is not NULL, it contains the period of the
+ * sclk in nanoseconds, i.e. how long the cycle count wraps around.
+ *
+ * Return value:
+ * 0: the operation failed; period is not set either
+ * >0: time in nanoseconds
+ */
+int64_t msm_timer_get_sclk_time(int64_t *period)
+{
+ struct msm_timer_sync_data_t data;
+ uint32_t clock_value;
+ int64_t tmp;
+
+ memset(&data, 0, sizeof(data));
+ clock_value = msm_timer_do_sync_to_sclk(
+ msm_timer_get_sclk_time_start,
+ msm_timer_get_sclk_time_expired,
+ NULL,
+ &data);
+
+ if (!clock_value)
+ return 0;
+
+ if (period) {
+ tmp = 1LL << 32;
+ tmp *= NSEC_PER_SEC;
+ do_div(tmp, sclk_hz);
+ *period = tmp;
+ }
+
+ tmp = (int64_t)clock_value;
+ tmp *= NSEC_PER_SEC;
+ do_div(tmp, sclk_hz);
+ return tmp;
+}
+
+int __init msm_timer_init_time_sync(void (*timeout)(void))
+{
+#if !defined(CONFIG_MSM_DIRECT_SCLK_ACCESS)
+ int ret = smsm_change_intr_mask(SMSM_TIME_MASTER_DEM, 0xFFFFFFFF, 0);
+
+ if (ret) {
+ printk(KERN_ERR "%s: failed to clear interrupt mask, %d\n",
+ __func__, ret);
+ return ret;
}
- 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);
+ smsm_change_state(SMSM_APPS_DEM,
+ SLAVE_TIME_REQUEST | SLAVE_TIME_POLL, SLAVE_TIME_INIT);
+#endif
- msm_timer_init(freq, 32, irq, !!percpu_offset);
+ BUG_ON(timeout == NULL);
+ msm_timer_sync_timeout = timeout;
+
+ return 0;
}
+<<<<<<< current:drivers/clocksource/qcom-timer.c
CLOCKSOURCE_OF_DECLARE(kpss_timer, "qcom,kpss-timer", msm_dt_timer_init);
CLOCKSOURCE_OF_DECLARE(scss_timer, "qcom,scss-timer", msm_dt_timer_init);
#else
+=======
-static int __init msm_timer_map(phys_addr_t addr, u32 event, u32 source,
- u32 sts)
+#endif
+>>>>>>> patched:arch/arm/mach-msm/timer.c
+
+static u32 notrace msm_read_sched_clock(void)
{
- void __iomem *base;
+ struct msm_clock *clock = &msm_clocks[msm_global_timer];
+ struct clocksource *cs = &clock->clocksource;
+ return cs->read(NULL);
+}
- base = ioremap(addr, SZ_256);
- if (!base) {
- pr_err("Failed to map timer base\n");
- return -ENOMEM;
+static struct delay_timer msm_delay_timer;
+
+static unsigned long msm_read_current_timer(void)
+{
+ struct msm_clock *dgt = &msm_clocks[MSM_CLOCK_DGT];
+ return msm_read_timer_count(dgt, GLOBAL_TIMER);
+}
+
+static void __init msm_sched_clock_init(void)
+{
+ struct msm_clock *clock = &msm_clocks[msm_global_timer];
+
+ setup_sched_clock(msm_read_sched_clock, 32 - clock->shift, clock->freq);
+}
+
+#ifdef CONFIG_LOCAL_TIMERS
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+ static DEFINE_PER_CPU(bool, first_boot) = true;
+ struct msm_clock *clock = &msm_clocks[msm_global_timer];
+
+ /* Use existing clock_event for cpu 0 */
+ if (!smp_processor_id())
+ return 0;
+
+ if (cpu_is_msm8x60() || soc_class_is_msm8960() ||
+ soc_class_is_apq8064() || soc_class_is_msm8930())
+ __raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+
+ if (__get_cpu_var(first_boot)) {
+ __raw_writel(0, clock->regbase + TIMER_ENABLE);
+ __raw_writel(0, clock->regbase + TIMER_CLEAR);
+ __raw_writel(~0, clock->regbase + TIMER_MATCH_VAL);
+ __get_cpu_var(first_boot) = false;
+ if (clock->status_mask)
+ while (__raw_readl(MSM_TMR_BASE + TIMER_STATUS) &
+ clock->status_mask)
+ ;
}
- event_base = base + event;
- source_base = base + source;
- if (sts)
- sts_base = base + sts;
+ evt->irq = clock->irq;
+ evt->name = "local_timer";
+ evt->features = CLOCK_EVT_FEAT_ONESHOT;
+ evt->rating = clock->clockevent.rating;
+ evt->set_mode = msm_timer_set_mode;
+ evt->set_next_event = msm_timer_set_next_event;
+
+ *__this_cpu_ptr(clock->percpu_evt) = evt;
+ clockevents_config_and_register(evt, gpt_hz, 4, 0xf0000000);
+ enable_percpu_irq(evt->irq, IRQ_TYPE_EDGE_RISING);
return 0;
}
+<<<<<<< current:drivers/clocksource/qcom-timer.c
static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
{
/*
@@ -315,29 +1096,204 @@ static notrace cycle_t msm_read_timer_count_shift(struct clocksource *cs)
}
void __init msm7x01_timer_init(void)
+=======
+void local_timer_stop(struct clock_event_device *evt)
+>>>>>>> patched:arch/arm/mach-msm/timer.c
{
- 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);
+ evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+ disable_percpu_irq(evt->irq);
}
-void __init msm7x30_timer_init(void)
+static struct local_timer_ops msm_lt_ops = {
+ local_timer_setup,
+ local_timer_stop,
+};
+#endif /* CONFIG_LOCAL_TIMERS */
+
+#ifdef CONFIG_ARCH_MSM8625
+static void fixup_msm8625_timer(void)
{
- if (msm_timer_map(0xc0100000, 0x4, 0x24, 0x80))
- return;
- msm_timer_init(24576000 / 4, 32, 1, false);
+ struct msm_clock *dgt = &msm_clocks[MSM_CLOCK_DGT];
+ struct msm_clock *gpt = &msm_clocks[MSM_CLOCK_GPT];
+ dgt->irq = MSM8625_INT_DEBUG_TIMER_EXP;
+ gpt->irq = MSM8625_INT_GP_TIMER_EXP;
+ global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
}
+#else
+static inline void fixup_msm8625_timer(void) { };
+#endif
-void __init qsd8x50_timer_init(void)
+void __init msm_timer_init(void)
{
- if (msm_timer_map(0xAC100000, 0x0, 0x10, 0x34))
- return;
- msm_timer_init(19200000 / 4, 32, 7, false);
+ int i;
+ int res;
+ struct irq_chip *chip;
+ struct msm_clock *dgt = &msm_clocks[MSM_CLOCK_DGT];
+ struct msm_clock *gpt = &msm_clocks[MSM_CLOCK_GPT];
+
+ if (cpu_is_msm7x01() || cpu_is_msm7x25() || cpu_is_msm7x27() ||
+ cpu_is_msm7x25a() || cpu_is_msm7x27a() || cpu_is_msm7x25aa() ||
+ cpu_is_msm7x27aa() || cpu_is_msm8625() || cpu_is_msm7x25ab() ||
+ cpu_is_msm8625q()) {
+ dgt->shift = MSM_DGT_SHIFT;
+ dgt->freq = 19200000 >> MSM_DGT_SHIFT;
+ dgt->clockevent.shift = 32 + MSM_DGT_SHIFT;
+ dgt->clocksource.mask = CLOCKSOURCE_MASK(32 - MSM_DGT_SHIFT);
+ gpt->regbase = MSM_TMR_BASE;
+ dgt->regbase = MSM_TMR_BASE + 0x10;
+ gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT
+ | MSM_CLOCK_FLAGS_ODD_MATCH_WRITE
+ | MSM_CLOCK_FLAGS_DELAYED_WRITE_POST;
+ if (cpu_is_msm8625() || cpu_is_msm8625q())
+ fixup_msm8625_timer();
+ } else if (cpu_is_qsd8x50()) {
+ dgt->freq = 4800000;
+ gpt->regbase = MSM_TMR_BASE;
+ dgt->regbase = MSM_TMR_BASE + 0x10;
+ } else if (cpu_is_fsm9xxx())
+ dgt->freq = 4800000;
+ else if (cpu_is_msm7x30() || cpu_is_msm8x55()) {
+ gpt->status_mask = BIT(10);
+ dgt->status_mask = BIT(2);
+ dgt->freq = 6144000;
+ } else if (cpu_is_msm8x60()) {
+ global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
+ gpt->status_mask = BIT(10);
+ dgt->status_mask = BIT(2);
+ dgt->freq = 6750000;
+ __raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+ } else if (cpu_is_msm9615()) {
+ dgt->freq = 6750000;
+ __raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+ gpt->status_mask = BIT(10);
+ dgt->status_mask = BIT(2);
+ gpt->freq = 32765;
+ gpt_hz = 32765;
+ sclk_hz = 32765;
+ gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ } else if (soc_class_is_msm8960() || soc_class_is_apq8064() ||
+ soc_class_is_msm8930()) {
+ global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
+ dgt->freq = 6750000;
+ __raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
+ gpt->status_mask = BIT(10);
+ dgt->status_mask = BIT(2);
+ if (!soc_class_is_apq8064()) {
+ gpt->freq = 32765;
+ gpt_hz = 32765;
+ sclk_hz = 32765;
+ }
+ if (!soc_class_is_msm8930() && !cpu_is_msm8960ab()) {
+ gpt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
+ }
+ } else {
+ WARN(1, "Timer running on unknown hardware. Configure this! "
+ "Assuming default configuration.\n");
+ dgt->freq = 6750000;
+ }
+
+ if (msm_clocks[MSM_CLOCK_GPT].clocksource.rating > DG_TIMER_RATING)
+ msm_global_timer = MSM_CLOCK_GPT;
+ else
+ msm_global_timer = MSM_CLOCK_DGT;
+
+ for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) {
+ struct msm_clock *clock = &msm_clocks[i];
+ struct clock_event_device *ce = &clock->clockevent;
+ struct clocksource *cs = &clock->clocksource;
+ __raw_writel(0, clock->regbase + TIMER_ENABLE);
+ __raw_writel(0, clock->regbase + TIMER_CLEAR);
+ __raw_writel(~0, clock->regbase + TIMER_MATCH_VAL);
+
+ if ((clock->freq << clock->shift) == gpt_hz) {
+ clock->rollover_offset = 0;
+ } else {
+ uint64_t temp;
+
+ temp = clock->freq << clock->shift;
+ temp <<= 32;
+ do_div(temp, gpt_hz);
+
+ clock->rollover_offset = (uint32_t) temp;
+ }
+
+ ce->mult = div_sc(clock->freq, NSEC_PER_SEC, ce->shift);
+ /* allow at least 10 seconds to notice that the timer wrapped */
+ ce->max_delta_ns =
+ clockevent_delta2ns(0xf0000000 >> clock->shift, ce);
+ /* ticks gets rounded down by one */
+ ce->min_delta_ns =
+ clockevent_delta2ns(clock->write_delay + 4, ce);
+ ce->cpumask = cpumask_of(0);
+
+ res = clocksource_register_hz(cs, clock->freq);
+ if (res)
+ printk(KERN_ERR "msm_timer_init: clocksource_register "
+ "failed for %s\n", cs->name);
+
+ ce->irq = clock->irq;
+ if (cpu_is_msm8x60() || cpu_is_msm9615() || cpu_is_msm8625() ||
+ cpu_is_msm8625q() || soc_class_is_msm8960() ||
+ soc_class_is_apq8064() || soc_class_is_msm8930()) {
+ clock->percpu_evt = alloc_percpu(struct clock_event_device *);
+ if (!clock->percpu_evt) {
+ pr_err("msm_timer_init: memory allocation "
+ "failed for %s\n", ce->name);
+ continue;
+ }
+
+ *__this_cpu_ptr(clock->percpu_evt) = ce;
+ res = request_percpu_irq(ce->irq, msm_timer_interrupt,
+ ce->name, clock->percpu_evt);
+ if (!res)
+ enable_percpu_irq(ce->irq,
+ IRQ_TYPE_EDGE_RISING);
+ } else {
+ clock->evt = ce;
+ res = request_irq(ce->irq, msm_timer_interrupt,
+ IRQF_TIMER | IRQF_NOBALANCING | IRQF_TRIGGER_RISING,
+ ce->name, &clock->evt);
+ }
+
+ if (res)
+ pr_err("msm_timer_init: request_irq failed for %s\n",
+ ce->name);
+
+ chip = irq_get_chip(clock->irq);
+ if (chip && chip->irq_mask)
+ chip->irq_mask(irq_get_irq_data(clock->irq));
+
+ if (clock->status_mask)
+ while (__raw_readl(MSM_TMR_BASE + TIMER_STATUS) &
+ clock->status_mask)
+ ;
+
+ clockevents_register_device(ce);
+ }
+ msm_sched_clock_init();
+
+ if (use_user_accessible_timers()) {
+ if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064()) {
+ struct msm_clock *gtclock = &msm_clocks[MSM_CLOCK_GPT];
+ void __iomem *addr = gtclock->regbase +
+ TIMER_COUNT_VAL + global_timer_offset;
+ setup_user_timer_offset(virt_to_phys(addr)&0xfff);
+ set_user_accessible_timer_flag(true);
+ }
+ }
+
+ if (is_smp()) {
+ __raw_writel(1,
+ msm_clocks[MSM_CLOCK_DGT].regbase + TIMER_ENABLE);
+ msm_delay_timer.freq = dgt->freq;
+ msm_delay_timer.read_current_timer = &msm_read_current_timer;
+ register_current_timer_delay(&msm_delay_timer);
+ }
+
+#ifdef CONFIG_LOCAL_TIMERS
+ local_timer_register(&msm_lt_ops);
+#endif
}
#endif
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 438901257ac1..cb69e7cbf5d5 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1 +1,55 @@
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
+# When adding new entries keep the list in alphabetical order
+CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+
+obj-$(CONFIG_MSM_RUN_QUEUE_STATS) += msm_rq_stats.o
+#obj-$(CONFIG_DEBUG_FS) += nohlt.o
+obj-$(CONFIG_ARM64) += idle-v8.o cpu_ops.o
+obj-$(CONFIG_CPU_V7) += idle-v7.o
+obj-$(CONFIG_MAXIMUM_CURRENT_THROTTLING) += mct.o
+obj-$(CONFIG_MSM_BAM_DMUX) += bam_dmux.o
+obj-$(CONFIG_MSM_EVENT_TIMER) += event_timer.o
+obj-$(CONFIG_MSM_IPC_ROUTER_HSIC_XPRT) += ipc_router_hsic_xprt.o
+obj-$(CONFIG_MSM_IPC_ROUTER_SMD_XPRT) += ipc_router_smd_xprt.o
+obj-$(CONFIG_MSM_MEMORY_DUMP) += memory_dump.o
+obj-$(CONFIG_MSM_MEMORY_DUMP_V2) += memory_dump_v2.o
+obj-$(CONFIG_MSM_MPM_OF) += mpm-of.o
+obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o
+ifdef CONFIG_DEBUG_FS
+obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd-debug.o
+endif
+obj-$(CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG) += rpm_rbcpr_stats_v2.o
+obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o rpm_master_stat.o
+obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
+obj-$(CONFIG_MSM_JTAG) += jtag-fuse.o jtag.o
+obj-$(CONFIG_MSM_JTAG_MM) += jtag-fuse.o jtag-mm.o
+obj-$(CONFIG_MSM_JTAGV8) += jtag-fuse.o jtagv8.o jtagv8-mm.o
+obj-$(CONFIG_MSM_QMI_INTERFACE) += qmi_interface.o
+
+obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
+
+obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o smd_private.o smd_init_dt.o smsm_debug.o
+obj-$(CONFIG_MSM_SMEM) += smem.o smem_debug.o
+obj-$(CONFIG_MSM_SMEM_LOGGING) += smem_log.o
+obj-$(CONFIG_MSM_COMMON_LOG) += common_log.o
+obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o
+obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_spinlock_test.o
+obj-$(CONFIG_MSM_WATCHDOG_V2) += watchdog_v2.o
+#obj-$(CONFIG_MEM_SHARE_QMI_SERVICE) += memshare/
+obj-$(CONFIG_MSM_SPM_V2) += spm-v2.o spm_devices.o
+obj-y += socinfo.o
+
+obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
+obj-$(CONFIG_MSM_PIL_SSR_GENERIC) += subsys-pil-tz.o
+obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-msa.o pil-q6v5-mss.o
+obj-$(CONFIG_MSM_PIL_FEMTO) += pil-q6v5.o pil-msa.o pil-femto-modem.o
+
+obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o ocmem_rdm.o ocmem_core.o
+
+ifdef CONFIG_MSM_SUBSYSTEM_RESTART
+ obj-y += subsystem_notif.o
+ obj-y += subsystem_restart.o
+ obj-y += ramdump.o
+endif
+obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
diff --git a/drivers/soc/qcom/idle-v7.S b/drivers/soc/qcom/idle-v7.S
new file mode 100644
index 000000000000..575f5a933582
--- /dev/null
+++ b/drivers/soc/qcom/idle-v7.S
@@ -0,0 +1,64 @@
+/*
+ * Idle processing for ARMv7-based Qualcomm SoCs.
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2009, 2011-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 <linux/linkage.h>
+#include <linux/threads.h>
+#include <asm/assembler.h>
+
+ .arm
+ENTRY(msm_pm_boot_entry)
+THUMB( adr r9, BSYM(2f) ) /* Kernel is always entered in ARM. */
+THUMB( bx r9 ) /* If this is a Thumb-2 kernel, */
+THUMB( .thumb ) /* switch to Thumb now. */
+THUMB(2: )
+ mrc p15, 0, r0, c0, c0, 5 /* MPIDR */
+ bic r0, #0xff000000 /* what CPU am I */
+
+ adr r3, 3f
+ ldr r1, [r3]
+ sub r3, r1, r3
+ ldr r1, =msm_pc_debug_counters_phys /*phys addr for IMEM reg */
+ sub r1, r1, r3 /* translate virt to phys */
+ ldr r1,[r1]
+
+ cmp r1, #0
+ beq skip_pc_debug3
+ add r1, r1, r0, LSL #4 /* debug location for this CPU */
+ add r1, #4 /* warmboot entry counter*/
+ ldr r2, [r1]
+ add r2, #1
+ str r2, [r1]
+
+skip_pc_debug3:
+ ldr r1, =msm_pm_boot_vector
+ sub r1, r1, r3 /* translate virt to phys */
+
+ add r1, r1, r0, LSL #2 /* locate boot vector for our cpu */
+ ldr pc, [r1] /* jump */
+ENDPROC(msm_pm_boot_entry)
+
+3: .long .
+
+ .data
+
+ .globl msm_pm_boot_vector
+msm_pm_boot_vector:
+ .space 4 * NR_CPUS
+
+ .globl msm_pc_debug_counters_phys
+msm_pc_debug_counters_phys:
+ .long 0x0
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
new file mode 100644
index 000000000000..d482225183b2
--- /dev/null
+++ b/drivers/soc/qcom/socinfo.c
@@ -0,0 +1,1355 @@
+/* Copyright (c) 2009-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.
+ *
+ */
+/*
+ * SOC Info Routines
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sys_soc.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include <asm/system_misc.h>
+
+#include <soc/qcom/socinfo.h>
+#include <soc/qcom/smem.h>
+#include <soc/qcom/boot_stats.h>
+
+#define BUILD_ID_LENGTH 32
+#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
+#define SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE 128
+#define SMEM_IMAGE_VERSION_SIZE 4096
+#define SMEM_IMAGE_VERSION_NAME_SIZE 75
+#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20
+#define SMEM_IMAGE_VERSION_VARIANT_OFFSET 75
+#define SMEM_IMAGE_VERSION_OEM_SIZE 32
+#define SMEM_IMAGE_VERSION_OEM_OFFSET 96
+#define SMEM_IMAGE_VERSION_PARTITION_APPS 10
+
+enum {
+ HW_PLATFORM_UNKNOWN = 0,
+ HW_PLATFORM_SURF = 1,
+ HW_PLATFORM_FFA = 2,
+ HW_PLATFORM_FLUID = 3,
+ HW_PLATFORM_SVLTE_FFA = 4,
+ HW_PLATFORM_SVLTE_SURF = 5,
+ HW_PLATFORM_MTP = 8,
+ HW_PLATFORM_LIQUID = 9,
+ /* Dragonboard platform id is assigned as 10 in CDT */
+ HW_PLATFORM_DRAGON = 10,
+ HW_PLATFORM_QRD = 11,
+ HW_PLATFORM_HRD = 13,
+ HW_PLATFORM_DTV = 14,
+ HW_PLATFORM_STP = 23,
+ HW_PLATFORM_SBC = 24,
+ HW_PLATFORM_INVALID
+};
+
+const char *hw_platform[] = {
+ [HW_PLATFORM_UNKNOWN] = "Unknown",
+ [HW_PLATFORM_SURF] = "Surf",
+ [HW_PLATFORM_FFA] = "FFA",
+ [HW_PLATFORM_FLUID] = "Fluid",
+ [HW_PLATFORM_SVLTE_FFA] = "SVLTE_FFA",
+ [HW_PLATFORM_SVLTE_SURF] = "SLVTE_SURF",
+ [HW_PLATFORM_MTP] = "MTP",
+ [HW_PLATFORM_LIQUID] = "Liquid",
+ [HW_PLATFORM_DRAGON] = "Dragon",
+ [HW_PLATFORM_QRD] = "QRD",
+ [HW_PLATFORM_HRD] = "HRD",
+ [HW_PLATFORM_DTV] = "DTV",
+ [HW_PLATFORM_STP] = "STP",
+ [HW_PLATFORM_SBC] = "SBC",
+};
+
+enum {
+ ACCESSORY_CHIP_UNKNOWN = 0,
+ ACCESSORY_CHIP_CHARM = 58,
+};
+
+enum {
+ PLATFORM_SUBTYPE_QRD = 0x0,
+ PLATFORM_SUBTYPE_SKUAA = 0x1,
+ PLATFORM_SUBTYPE_SKUF = 0x2,
+ PLATFORM_SUBTYPE_SKUAB = 0x3,
+ PLATFORM_SUBTYPE_SKUG = 0x5,
+ PLATFORM_SUBTYPE_QRD_INVALID,
+};
+
+const char *qrd_hw_platform_subtype[] = {
+ [PLATFORM_SUBTYPE_QRD] = "QRD",
+ [PLATFORM_SUBTYPE_SKUAA] = "SKUAA",
+ [PLATFORM_SUBTYPE_SKUF] = "SKUF",
+ [PLATFORM_SUBTYPE_SKUAB] = "SKUAB",
+ [PLATFORM_SUBTYPE_SKUG] = "SKUG",
+ [PLATFORM_SUBTYPE_QRD_INVALID] = "INVALID",
+};
+
+enum {
+ PLATFORM_SUBTYPE_UNKNOWN = 0x0,
+ PLATFORM_SUBTYPE_CHARM = 0x1,
+ PLATFORM_SUBTYPE_STRANGE = 0x2,
+ PLATFORM_SUBTYPE_STRANGE_2A = 0x3,
+ PLATFORM_SUBTYPE_INVALID,
+};
+
+const char *hw_platform_subtype[] = {
+ [PLATFORM_SUBTYPE_UNKNOWN] = "Unknown",
+ [PLATFORM_SUBTYPE_CHARM] = "charm",
+ [PLATFORM_SUBTYPE_STRANGE] = "strange",
+ [PLATFORM_SUBTYPE_STRANGE_2A] = "strange_2a,"
+};
+
+/* Used to parse shared memory. Must match the modem. */
+struct socinfo_v1 {
+ uint32_t format;
+ uint32_t id;
+ uint32_t version;
+ char build_id[BUILD_ID_LENGTH];
+};
+
+struct socinfo_v2 {
+ struct socinfo_v1 v1;
+
+ /* only valid when format==2 */
+ uint32_t raw_id;
+ uint32_t raw_version;
+};
+
+struct socinfo_v3 {
+ struct socinfo_v2 v2;
+
+ /* only valid when format==3 */
+ uint32_t hw_platform;
+};
+
+struct socinfo_v4 {
+ struct socinfo_v3 v3;
+
+ /* only valid when format==4 */
+ uint32_t platform_version;
+};
+
+struct socinfo_v5 {
+ struct socinfo_v4 v4;
+
+ /* only valid when format==5 */
+ uint32_t accessory_chip;
+};
+
+struct socinfo_v6 {
+ struct socinfo_v5 v5;
+
+ /* only valid when format==6 */
+ uint32_t hw_platform_subtype;
+};
+
+struct socinfo_v7 {
+ struct socinfo_v6 v6;
+
+ /* only valid when format==7 */
+ uint32_t pmic_model;
+ uint32_t pmic_die_revision;
+};
+
+struct socinfo_v8 {
+ struct socinfo_v7 v7;
+
+ /* only valid when format==8*/
+ uint32_t pmic_model_1;
+ uint32_t pmic_die_revision_1;
+ uint32_t pmic_model_2;
+ uint32_t pmic_die_revision_2;
+};
+
+struct socinfo_v9 {
+ struct socinfo_v8 v8;
+
+ /* only valid when format==9*/
+ uint32_t foundry_id;
+};
+
+static union {
+ struct socinfo_v1 v1;
+ struct socinfo_v2 v2;
+ struct socinfo_v3 v3;
+ struct socinfo_v4 v4;
+ struct socinfo_v5 v5;
+ struct socinfo_v6 v6;
+ struct socinfo_v7 v7;
+ struct socinfo_v8 v8;
+ struct socinfo_v9 v9;
+} *socinfo;
+
+static struct msm_soc_info cpu_of_id[] = {
+
+ /* 7x01 IDs */
+ [0] = {MSM_CPU_UNKNOWN, "Unknown CPU"},
+ [1] = {MSM_CPU_7X01, "MSM7X01"},
+ [16] = {MSM_CPU_7X01, "MSM7X01"},
+ [17] = {MSM_CPU_7X01, "MSM7X01"},
+ [18] = {MSM_CPU_7X01, "MSM7X01"},
+ [19] = {MSM_CPU_7X01, "MSM7X01"},
+ [23] = {MSM_CPU_7X01, "MSM7X01"},
+ [25] = {MSM_CPU_7X01, "MSM7X01"},
+ [26] = {MSM_CPU_7X01, "MSM7X01"},
+ [32] = {MSM_CPU_7X01, "MSM7X01"},
+ [33] = {MSM_CPU_7X01, "MSM7X01"},
+ [34] = {MSM_CPU_7X01, "MSM7X01"},
+ [35] = {MSM_CPU_7X01, "MSM7X01"},
+
+ /* 7x25 IDs */
+ [20] = {MSM_CPU_7X25, "MSM7X25"},
+ [21] = {MSM_CPU_7X25, "MSM7X25"},
+ [24] = {MSM_CPU_7X25, "MSM7X25"},
+ [27] = {MSM_CPU_7X25, "MSM7X25"},
+ [39] = {MSM_CPU_7X25, "MSM7X25"},
+ [40] = {MSM_CPU_7X25, "MSM7X25"},
+ [41] = {MSM_CPU_7X25, "MSM7X25"},
+ [42] = {MSM_CPU_7X25, "MSM7X25"},
+ [62] = {MSM_CPU_7X25, "MSM7X25"},
+ [63] = {MSM_CPU_7X25, "MSM7X25"},
+ [66] = {MSM_CPU_7X25, "MSM7X25"},
+
+
+ /* 7x27 IDs */
+ [43] = {MSM_CPU_7X27, "MSM7X27"},
+ [44] = {MSM_CPU_7X27, "MSM7X27"},
+ [61] = {MSM_CPU_7X27, "MSM7X27"},
+ [67] = {MSM_CPU_7X27, "MSM7X27"},
+ [68] = {MSM_CPU_7X27, "MSM7X27"},
+ [69] = {MSM_CPU_7X27, "MSM7X27"},
+
+
+ /* 8x50 IDs */
+ [30] = {MSM_CPU_8X50, "MSM8X50"},
+ [36] = {MSM_CPU_8X50, "MSM8X50"},
+ [37] = {MSM_CPU_8X50, "MSM8X50"},
+ [38] = {MSM_CPU_8X50, "MSM8X50"},
+
+ /* 7x30 IDs */
+ [59] = {MSM_CPU_7X30, "MSM7X30"},
+ [60] = {MSM_CPU_7X30, "MSM7X30"},
+
+ /* 8x55 IDs */
+ [74] = {MSM_CPU_8X55, "MSM8X55"},
+ [75] = {MSM_CPU_8X55, "MSM8X55"},
+ [85] = {MSM_CPU_8X55, "MSM8X55"},
+
+ /* 8x60 IDs */
+ [70] = {MSM_CPU_8X60, "MSM8X60"},
+ [71] = {MSM_CPU_8X60, "MSM8X60"},
+ [86] = {MSM_CPU_8X60, "MSM8X60"},
+
+ /* 8960 IDs */
+ [87] = {MSM_CPU_8960, "MSM8960"},
+
+ /* 7x25A IDs */
+ [88] = {MSM_CPU_7X25A, "MSM7X25A"},
+ [89] = {MSM_CPU_7X25A, "MSM7X25A"},
+ [96] = {MSM_CPU_7X25A, "MSM7X25A"},
+
+ /* 7x27A IDs */
+ [90] = {MSM_CPU_7X27A, "MSM7X27A"},
+ [91] = {MSM_CPU_7X27A, "MSM7X27A"},
+ [92] = {MSM_CPU_7X27A, "MSM7X27A"},
+ [97] = {MSM_CPU_7X27A, "MSM7X27A"},
+
+ /* FSM9xxx ID */
+ [94] = {FSM_CPU_9XXX, "FSM9XXX"},
+ [95] = {FSM_CPU_9XXX, "FSM9XXX"},
+
+ /* 7x25AA ID */
+ [98] = {MSM_CPU_7X25AA, "MSM7X25AA"},
+ [99] = {MSM_CPU_7X25AA, "MSM7X25AA"},
+ [100] = {MSM_CPU_7X25AA, "MSM7X25AA"},
+
+ /* 7x27AA ID */
+ [101] = {MSM_CPU_7X27AA, "MSM7X27AA"},
+ [102] = {MSM_CPU_7X27AA, "MSM7X27AA"},
+ [103] = {MSM_CPU_7X27AA, "MSM7X27AA"},
+ [136] = {MSM_CPU_7X27AA, "MSM7X27AA"},
+
+ /* 9x15 ID */
+ [104] = {MSM_CPU_9615, "MSM9615"},
+ [105] = {MSM_CPU_9615, "MSM9615"},
+ [106] = {MSM_CPU_9615, "MSM9615"},
+ [107] = {MSM_CPU_9615, "MSM9615"},
+ [171] = {MSM_CPU_9615, "MSM9615"},
+
+ /* 8064 IDs */
+ [109] = {MSM_CPU_8064, "APQ8064"},
+
+ /* 8930 IDs */
+ [116] = {MSM_CPU_8930, "MSM8930"},
+ [117] = {MSM_CPU_8930, "MSM8930"},
+ [118] = {MSM_CPU_8930, "MSM8930"},
+ [119] = {MSM_CPU_8930, "MSM8930"},
+ [179] = {MSM_CPU_8930, "MSM8930"},
+
+ /* 8627 IDs */
+ [120] = {MSM_CPU_8627, "MSM8627"},
+ [121] = {MSM_CPU_8627, "MSM8627"},
+
+ /* 8660A ID */
+ [122] = {MSM_CPU_8960, "MSM8960"},
+
+ /* 8260A ID */
+ [123] = {MSM_CPU_8960, "MSM8960"},
+
+ /* 8060A ID */
+ [124] = {MSM_CPU_8960, "MSM8960"},
+
+ /* 8974 IDs */
+ [126] = {MSM_CPU_8974, "MSM8974"},
+ [184] = {MSM_CPU_8974, "MSM8974"},
+ [185] = {MSM_CPU_8974, "MSM8974"},
+ [186] = {MSM_CPU_8974, "MSM8974"},
+
+ /* 8974AA IDs */
+ [208] = {MSM_CPU_8974PRO_AA, "MSM8974PRO-AA"},
+ [211] = {MSM_CPU_8974PRO_AA, "MSM8974PRO-AA"},
+ [214] = {MSM_CPU_8974PRO_AA, "MSM8974PRO-AA"},
+ [217] = {MSM_CPU_8974PRO_AA, "MSM8974PRO-AA"},
+
+ /* 8974AB IDs */
+ [209] = {MSM_CPU_8974PRO_AB, "MSM8974PRO-AB"},
+ [212] = {MSM_CPU_8974PRO_AB, "MSM8974PRO-AB"},
+ [215] = {MSM_CPU_8974PRO_AB, "MSM8974PRO-AB"},
+ [218] = {MSM_CPU_8974PRO_AB, "MSM8974PRO-AB"},
+
+ /* 8974AC IDs */
+ [194] = {MSM_CPU_8974PRO_AC, "MSM8974PRO-AC"},
+ [210] = {MSM_CPU_8974PRO_AC, "MSM8974PRO-AC"},
+ [213] = {MSM_CPU_8974PRO_AC, "MSM8974PRO-AC"},
+ [216] = {MSM_CPU_8974PRO_AC, "MSM8974PRO-AC"},
+
+ /* 8625 IDs */
+ [127] = {MSM_CPU_8625, "MSM8625"},
+ [128] = {MSM_CPU_8625, "MSM8625"},
+ [129] = {MSM_CPU_8625, "MSM8625"},
+ [137] = {MSM_CPU_8625, "MSM8625"},
+ [167] = {MSM_CPU_8625, "MSM8625"},
+
+ /* 8064 MPQ ID */
+ [130] = {MSM_CPU_8064, "APQ8064"},
+
+ /* 7x25AB IDs */
+ [131] = {MSM_CPU_7X25AB, "MSM7X25AB"},
+ [132] = {MSM_CPU_7X25AB, "MSM7X25AB"},
+ [133] = {MSM_CPU_7X25AB, "MSM7X25AB"},
+ [135] = {MSM_CPU_7X25AB, "MSM7X25AB"},
+
+ /* 9625 IDs */
+ [134] = {MSM_CPU_9625, "MSM9625"},
+ [148] = {MSM_CPU_9625, "MSM9625"},
+ [149] = {MSM_CPU_9625, "MSM9625"},
+ [150] = {MSM_CPU_9625, "MSM9625"},
+ [151] = {MSM_CPU_9625, "MSM9625"},
+ [152] = {MSM_CPU_9625, "MSM9625"},
+ [173] = {MSM_CPU_9625, "MSM9625"},
+ [174] = {MSM_CPU_9625, "MSM9625"},
+ [175] = {MSM_CPU_9625, "MSM9625"},
+
+ /* 8960AB IDs */
+ [138] = {MSM_CPU_8960AB, "MSM8960AB"},
+ [139] = {MSM_CPU_8960AB, "MSM8960AB"},
+ [140] = {MSM_CPU_8960AB, "MSM8960AB"},
+ [141] = {MSM_CPU_8960AB, "MSM8960AB"},
+
+ /* 8930AA IDs */
+ [142] = {MSM_CPU_8930AA, "MSM8930AA"},
+ [143] = {MSM_CPU_8930AA, "MSM8930AA"},
+ [144] = {MSM_CPU_8930AA, "MSM8930AA"},
+ [160] = {MSM_CPU_8930AA, "MSM8930AA"},
+ [180] = {MSM_CPU_8930AA, "MSM8930AA"},
+
+ /* 8226 IDs */
+ [145] = {MSM_CPU_8226, "MSM8626"},
+ [158] = {MSM_CPU_8226, "MSM8226"},
+ [159] = {MSM_CPU_8226, "MSM8526"},
+ [198] = {MSM_CPU_8226, "MSM8126"},
+ [199] = {MSM_CPU_8226, "APQ8026"},
+ [200] = {MSM_CPU_8226, "MSM8926"},
+ [205] = {MSM_CPU_8226, "MSM8326"},
+ [219] = {MSM_CPU_8226, "APQ8028"},
+ [220] = {MSM_CPU_8226, "MSM8128"},
+ [221] = {MSM_CPU_8226, "MSM8228"},
+ [222] = {MSM_CPU_8226, "MSM8528"},
+ [223] = {MSM_CPU_8226, "MSM8628"},
+ [224] = {MSM_CPU_8226, "MSM8928"},
+
+ /* 8092 IDs */
+ [146] = {MSM_CPU_8092, "MPQ8092"},
+
+ /* 8610 IDs */
+ [147] = {MSM_CPU_8610, "MSM8610"},
+ [161] = {MSM_CPU_8610, "MSM8110"},
+ [162] = {MSM_CPU_8610, "MSM8210"},
+ [163] = {MSM_CPU_8610, "MSM8810"},
+ [164] = {MSM_CPU_8610, "MSM8212"},
+ [165] = {MSM_CPU_8610, "MSM8612"},
+ [166] = {MSM_CPU_8610, "MSM8112"},
+ [225] = {MSM_CPU_8610, "MSM8510"},
+ [226] = {MSM_CPU_8610, "MSM8512"},
+
+ /* 8064AB IDs */
+ [153] = {MSM_CPU_8064AB, "APQ8064AB"},
+
+ /* 8930AB IDs */
+ [154] = {MSM_CPU_8930AB, "MSM8930AB"},
+ [155] = {MSM_CPU_8930AB, "MSM8930AB"},
+ [156] = {MSM_CPU_8930AB, "MSM8930AB"},
+ [157] = {MSM_CPU_8930AB, "MSM8930AB"},
+ [181] = {MSM_CPU_8930AB, "MSM8930AB"},
+
+ /* 8625Q IDs */
+ [168] = {MSM_CPU_8625Q, "MSM8225Q"},
+ [169] = {MSM_CPU_8625Q, "MSM8625Q"},
+ [170] = {MSM_CPU_8625Q, "MSM8125Q"},
+
+ /* 8064AA IDs */
+ [172] = {MSM_CPU_8064AA, "APQ8064AA"},
+
+ /* 8084 IDs */
+ [178] = {MSM_CPU_8084, "APQ8084"},
+
+ /* 9630 IDs */
+ [187] = {MSM_CPU_9630, "MDM9630"},
+ [227] = {MSM_CPU_9630, "MDM9630"},
+ [228] = {MSM_CPU_9630, "MDM9630"},
+ [229] = {MSM_CPU_9630, "MDM9630"},
+ [230] = {MSM_CPU_9630, "MDM9630"},
+ [231] = {MSM_CPU_9630, "MDM9630"},
+
+ /* FSM9900 ID */
+ [188] = {FSM_CPU_9900, "FSM9900"},
+ [189] = {FSM_CPU_9900, "FSM9900"},
+ [190] = {FSM_CPU_9900, "FSM9900"},
+ [191] = {FSM_CPU_9900, "FSM9900"},
+ [192] = {FSM_CPU_9900, "FSM9900"},
+ [193] = {FSM_CPU_9900, "FSM9900"},
+
+ /* 8916 IDs */
+ [206] = {MSM_CPU_8916, "MSM8916"},
+ [247] = {MSM_CPU_8916, "APQ8016"},
+ [248] = {MSM_CPU_8916, "MSM8216"},
+ [249] = {MSM_CPU_8916, "MSM8116"},
+ [250] = {MSM_CPU_8916, "MSM8616"},
+
+ /* 8936 IDs */
+ [233] = {MSM_CPU_8936, "MSM8936"},
+
+ /* 8939 IDs */
+ [239] = {MSM_CPU_8939, "MSM8939"},
+
+ /* ZIRC IDs */
+ [234] = {MSM_CPU_ZIRC, "MSMZIRC"},
+ [235] = {MSM_CPU_ZIRC, "MSMZIRC"},
+ [236] = {MSM_CPU_ZIRC, "MSMZIRC"},
+ [237] = {MSM_CPU_ZIRC, "MSMZIRC"},
+ [238] = {MSM_CPU_ZIRC, "MSMZIRC"},
+
+ /* Uninitialized IDs are not known to run Linux.
+ MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
+ considered as unknown CPU. */
+};
+
+static enum msm_cpu cur_cpu;
+static int current_image;
+
+static struct socinfo_v1 dummy_socinfo = {
+ .format = 1,
+ .version = 1,
+};
+
+uint32_t socinfo_get_id(void)
+{
+ return (socinfo) ? socinfo->v1.id : 0;
+}
+EXPORT_SYMBOL_GPL(socinfo_get_id);
+
+uint32_t socinfo_get_version(void)
+{
+ return (socinfo) ? socinfo->v1.version : 0;
+}
+
+char *socinfo_get_build_id(void)
+{
+ return (socinfo) ? socinfo->v1.build_id : NULL;
+}
+
+static char *msm_read_hardware_id(void)
+{
+ static char msm_soc_str[256] = "Qualcomm Technologies, Inc ";
+ static bool string_generated;
+ int ret = 0;
+
+ if (string_generated)
+ return msm_soc_str;
+ if (!socinfo)
+ goto err_path;
+ if (!cpu_of_id[socinfo->v1.id].soc_id_string)
+ goto err_path;
+
+ ret = strlcat(msm_soc_str, cpu_of_id[socinfo->v1.id].soc_id_string,
+ sizeof(msm_soc_str));
+ if (ret > sizeof(msm_soc_str))
+ goto err_path;
+
+ string_generated = true;
+ return msm_soc_str;
+err_path:
+ return "UNKNOWN SOC TYPE";
+}
+
+uint32_t socinfo_get_raw_id(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 2 ? socinfo->v2.raw_id : 0)
+ : 0;
+}
+
+uint32_t socinfo_get_raw_version(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 2 ? socinfo->v2.raw_version : 0)
+ : 0;
+}
+
+uint32_t socinfo_get_platform_type(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 3 ? socinfo->v3.hw_platform : 0)
+ : 0;
+}
+
+
+uint32_t socinfo_get_platform_version(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 4 ? socinfo->v4.platform_version : 0)
+ : 0;
+}
+
+/* This information is directly encoded by the machine id */
+/* Thus no external callers rely on this information at the moment */
+static uint32_t socinfo_get_accessory_chip(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 5 ? socinfo->v5.accessory_chip : 0)
+ : 0;
+}
+
+uint32_t socinfo_get_platform_subtype(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 6 ? socinfo->v6.hw_platform_subtype : 0)
+ : 0;
+}
+
+static uint32_t socinfo_get_foundry_id(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 9 ? socinfo->v9.foundry_id : 0)
+ : 0;
+}
+
+enum pmic_model socinfo_get_pmic_model(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 7 ? socinfo->v7.pmic_model
+ : PMIC_MODEL_UNKNOWN)
+ : PMIC_MODEL_UNKNOWN;
+}
+
+uint32_t socinfo_get_pmic_die_revision(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 7 ? socinfo->v7.pmic_die_revision : 0)
+ : 0;
+}
+
+static char *socinfo_get_image_version_base_address(void)
+{
+ return smem_find(SMEM_IMAGE_VERSION_TABLE,
+ SMEM_IMAGE_VERSION_SIZE, 0, SMEM_ANY_HOST_FLAG);
+}
+
+static uint32_t socinfo_get_format(void)
+{
+ return socinfo ? socinfo->v1.format : 0;
+}
+
+enum msm_cpu socinfo_get_msm_cpu(void)
+{
+ return cur_cpu;
+}
+EXPORT_SYMBOL_GPL(socinfo_get_msm_cpu);
+
+static ssize_t
+msm_get_vendor(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "Qualcomm\n");
+}
+
+static ssize_t
+msm_get_raw_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_raw_id());
+}
+
+static ssize_t
+msm_get_raw_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_raw_version());
+}
+
+static ssize_t
+msm_get_build_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+ socinfo_get_build_id());
+}
+
+static ssize_t
+msm_get_hw_platform(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ uint32_t hw_type;
+ hw_type = socinfo_get_platform_type();
+
+ return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+ hw_platform[hw_type]);
+}
+
+static ssize_t
+msm_get_platform_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_platform_version());
+}
+
+static ssize_t
+msm_get_accessory_chip(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_accessory_chip());
+}
+
+static ssize_t
+msm_get_platform_subtype(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ uint32_t hw_subtype;
+ hw_subtype = socinfo_get_platform_subtype();
+ if (HW_PLATFORM_QRD == socinfo_get_platform_type()) {
+ if (hw_subtype >= PLATFORM_SUBTYPE_QRD_INVALID) {
+ pr_err("%s: Invalid hardware platform sub type for qrd found\n",
+ __func__);
+ hw_subtype = PLATFORM_SUBTYPE_QRD_INVALID;
+ }
+ return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+ qrd_hw_platform_subtype[hw_subtype]);
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%-.32s\n",
+ hw_platform_subtype[hw_subtype]);
+}
+
+static ssize_t
+msm_get_platform_subtype_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ uint32_t hw_subtype;
+ hw_subtype = socinfo_get_platform_subtype();
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ hw_subtype);
+}
+
+static ssize_t
+msm_get_foundry_id(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_foundry_id());
+}
+
+static ssize_t
+msm_get_pmic_model(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_pmic_model());
+}
+
+static ssize_t
+msm_get_pmic_die_revision(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_pmic_die_revision());
+}
+
+static ssize_t
+msm_get_image_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ char *string_address;
+
+ string_address = socinfo_get_image_version_base_address();
+ if (IS_ERR_OR_NULL(string_address)) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "Unknown");
+ }
+ string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s\n",
+ string_address);
+}
+
+static ssize_t
+msm_set_image_version(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *store_address;
+
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (IS_ERR_OR_NULL(store_address)) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ snprintf(store_address, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s", buf);
+ return count;
+}
+
+static ssize_t
+msm_get_image_variant(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ char *string_address;
+
+ string_address = socinfo_get_image_version_base_address();
+ if (IS_ERR_OR_NULL(string_address)) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE,
+ "Unknown");
+ }
+ string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ string_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET;
+ return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s\n",
+ string_address);
+}
+
+static ssize_t
+msm_set_image_variant(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *store_address;
+
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (IS_ERR_OR_NULL(store_address)) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ store_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET;
+ snprintf(store_address, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s", buf);
+ return count;
+}
+
+static ssize_t
+msm_get_image_crm_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ char *string_address;
+
+ string_address = socinfo_get_image_version_base_address();
+ if (IS_ERR_OR_NULL(string_address)) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "Unknown");
+ }
+ string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ string_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
+ return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s\n",
+ string_address);
+}
+
+static ssize_t
+msm_set_image_crm_version(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *store_address;
+
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (IS_ERR_OR_NULL(store_address)) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ store_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
+ snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s", buf);
+ return count;
+}
+
+static ssize_t
+msm_get_image_number(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ current_image);
+}
+
+static ssize_t
+msm_select_image(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, digit;
+
+ ret = kstrtoint(buf, 10, &digit);
+ if (ret)
+ return ret;
+ if (0 <= digit && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT)
+ current_image = digit;
+ else
+ current_image = 0;
+ return count;
+}
+
+
+static struct device_attribute msm_soc_attr_raw_version =
+ __ATTR(raw_version, S_IRUGO, msm_get_raw_version, NULL);
+
+static struct device_attribute msm_soc_attr_raw_id =
+ __ATTR(raw_id, S_IRUGO, msm_get_raw_id, NULL);
+
+static struct device_attribute msm_soc_attr_vendor =
+ __ATTR(vendor, S_IRUGO, msm_get_vendor, NULL);
+
+static struct device_attribute msm_soc_attr_build_id =
+ __ATTR(build_id, S_IRUGO, msm_get_build_id, NULL);
+
+static struct device_attribute msm_soc_attr_hw_platform =
+ __ATTR(hw_platform, S_IRUGO, msm_get_hw_platform, NULL);
+
+
+static struct device_attribute msm_soc_attr_platform_version =
+ __ATTR(platform_version, S_IRUGO,
+ msm_get_platform_version, NULL);
+
+static struct device_attribute msm_soc_attr_accessory_chip =
+ __ATTR(accessory_chip, S_IRUGO,
+ msm_get_accessory_chip, NULL);
+
+static struct device_attribute msm_soc_attr_platform_subtype =
+ __ATTR(platform_subtype, S_IRUGO,
+ msm_get_platform_subtype, NULL);
+
+/* Platform Subtype String is being deprecated. Use Platform
+ * Subtype ID instead.
+ */
+static struct device_attribute msm_soc_attr_platform_subtype_id =
+ __ATTR(platform_subtype_id, S_IRUGO,
+ msm_get_platform_subtype_id, NULL);
+
+static struct device_attribute msm_soc_attr_foundry_id =
+ __ATTR(foundry_id, S_IRUGO,
+ msm_get_foundry_id, NULL);
+
+static struct device_attribute msm_soc_attr_pmic_model =
+ __ATTR(pmic_model, S_IRUGO,
+ msm_get_pmic_model, NULL);
+
+static struct device_attribute msm_soc_attr_pmic_die_revision =
+ __ATTR(pmic_die_revision, S_IRUGO,
+ msm_get_pmic_die_revision, NULL);
+
+static struct device_attribute image_version =
+ __ATTR(image_version, S_IRUGO | S_IWUSR,
+ msm_get_image_version, msm_set_image_version);
+
+static struct device_attribute image_variant =
+ __ATTR(image_variant, S_IRUGO | S_IWUSR,
+ msm_get_image_variant, msm_set_image_variant);
+
+static struct device_attribute image_crm_version =
+ __ATTR(image_crm_version, S_IRUGO | S_IWUSR,
+ msm_get_image_crm_version, msm_set_image_crm_version);
+
+static struct device_attribute select_image =
+ __ATTR(select_image, S_IRUGO | S_IWUSR,
+ msm_get_image_number, msm_select_image);
+
+static void * __init setup_dummy_socinfo(void)
+{
+ if (early_machine_is_mpq8092()) {
+ dummy_socinfo.id = 146;
+ strlcpy(dummy_socinfo.build_id, "mpq8092 - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_apq8084()) {
+ dummy_socinfo.id = 178;
+ strlcpy(dummy_socinfo.build_id, "apq8084 - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_mdm9630()) {
+ dummy_socinfo.id = 187;
+ strlcpy(dummy_socinfo.build_id, "mdm9630 - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_msmsamarium()) {
+ dummy_socinfo.id = 195;
+ strlcpy(dummy_socinfo.build_id, "msmsamarium - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_msm8916()) {
+ dummy_socinfo.id = 206;
+ strlcpy(dummy_socinfo.build_id, "msm8916 - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_msm8939()) {
+ dummy_socinfo.id = 239;
+ strlcpy(dummy_socinfo.build_id, "msm8939 - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_msm8936()) {
+ dummy_socinfo.id = 233;
+ strlcpy(dummy_socinfo.build_id, "msm8936 - ",
+ sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_msmzirc()) {
+ dummy_socinfo.id = 238;
+ strlcpy(dummy_socinfo.build_id, "msmzirc - ",
+ sizeof(dummy_socinfo.build_id));
+ }
+
+ strlcat(dummy_socinfo.build_id, "Dummy socinfo",
+ sizeof(dummy_socinfo.build_id));
+ return (void *) &dummy_socinfo;
+}
+
+static void __init populate_soc_sysfs_files(struct device *msm_soc_device)
+{
+ uint32_t legacy_format = socinfo_get_format();
+
+ device_create_file(msm_soc_device, &msm_soc_attr_vendor);
+ device_create_file(msm_soc_device, &image_version);
+ device_create_file(msm_soc_device, &image_variant);
+ device_create_file(msm_soc_device, &image_crm_version);
+ device_create_file(msm_soc_device, &select_image);
+
+ switch (legacy_format) {
+ case 9:
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_foundry_id);
+ case 8:
+ case 7:
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_pmic_model);
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_pmic_die_revision);
+ case 6:
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_platform_subtype);
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_platform_subtype_id);
+ case 5:
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_accessory_chip);
+ case 4:
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_platform_version);
+ case 3:
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_hw_platform);
+ case 2:
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_raw_id);
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_raw_version);
+ case 1:
+ device_create_file(msm_soc_device,
+ &msm_soc_attr_build_id);
+ break;
+ default:
+ pr_err("%s:Unknown socinfo format:%u\n", __func__,
+ legacy_format);
+ break;
+ }
+
+ return;
+}
+
+static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr)
+{
+ uint32_t soc_version = socinfo_get_version();
+
+ soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", socinfo_get_id());
+ soc_dev_attr->machine = "Snapdragon";
+ soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u.%u",
+ SOCINFO_VERSION_MAJOR(soc_version),
+ SOCINFO_VERSION_MINOR(soc_version));
+ return;
+
+}
+
+static int __init socinfo_init_sysfs(void)
+{
+ struct device *msm_soc_device;
+ struct soc_device *soc_dev;
+ struct soc_device_attribute *soc_dev_attr;
+
+ if (!socinfo) {
+ pr_err("%s: No socinfo found!\n", __func__);
+ return -ENODEV;
+ }
+
+ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ if (!soc_dev_attr) {
+ pr_err("%s: Soc Device alloc failed!\n", __func__);
+ return -ENOMEM;
+ }
+
+ soc_info_populate(soc_dev_attr);
+ soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR_OR_NULL(soc_dev)) {
+ kfree(soc_dev_attr);
+ pr_err("%s: Soc device register failed\n", __func__);
+ return -EIO;
+ }
+
+ msm_soc_device = soc_device_to_device(soc_dev);
+ populate_soc_sysfs_files(msm_soc_device);
+ return 0;
+}
+
+late_initcall(socinfo_init_sysfs);
+
+static void socinfo_print(void)
+{
+ switch (socinfo->v1.format) {
+ case 1:
+ pr_info("%s: v%u, id=%u, ver=%u.%u\n",
+ __func__, socinfo->v1.format, socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version));
+ break;
+ case 2:
+ pr_info("%s: v%u, id=%u, ver=%u.%u, "
+ "raw_id=%u, raw_ver=%u\n",
+ __func__, socinfo->v1.format, socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version),
+ socinfo->v2.raw_id, socinfo->v2.raw_version);
+ break;
+ case 3:
+ pr_info("%s: v%u, id=%u, ver=%u.%u, "
+ "raw_id=%u, raw_ver=%u, hw_plat=%u\n",
+ __func__, socinfo->v1.format, socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version),
+ socinfo->v2.raw_id, socinfo->v2.raw_version,
+ socinfo->v3.hw_platform);
+ break;
+ case 4:
+ pr_info("%s: v%u, id=%u, ver=%u.%u, "
+ "raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n",
+ __func__, socinfo->v1.format, socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version),
+ socinfo->v2.raw_id, socinfo->v2.raw_version,
+ socinfo->v3.hw_platform, socinfo->v4.platform_version);
+ break;
+ case 5:
+ pr_info("%s: v%u, id=%u, ver=%u.%u, "
+ "raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n"
+ " accessory_chip=%u\n", __func__, socinfo->v1.format,
+ socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version),
+ socinfo->v2.raw_id, socinfo->v2.raw_version,
+ socinfo->v3.hw_platform, socinfo->v4.platform_version,
+ socinfo->v5.accessory_chip);
+ break;
+ case 6:
+ pr_info("%s: v%u, id=%u, ver=%u.%u, "
+ "raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n"
+ " accessory_chip=%u hw_plat_subtype=%u\n", __func__,
+ socinfo->v1.format,
+ socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version),
+ socinfo->v2.raw_id, socinfo->v2.raw_version,
+ socinfo->v3.hw_platform, socinfo->v4.platform_version,
+ socinfo->v5.accessory_chip,
+ socinfo->v6.hw_platform_subtype);
+ break;
+ case 8:
+ case 7:
+ pr_info("%s: v%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u\n",
+ __func__,
+ socinfo->v1.format,
+ socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version),
+ socinfo->v2.raw_id, socinfo->v2.raw_version,
+ socinfo->v3.hw_platform, socinfo->v4.platform_version,
+ socinfo->v5.accessory_chip,
+ socinfo->v6.hw_platform_subtype,
+ socinfo->v7.pmic_model,
+ socinfo->v7.pmic_die_revision);
+ break;
+ case 9:
+ pr_info("%s: v%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u foundry_id=%u\n",
+ __func__,
+ socinfo->v1.format,
+ socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version),
+ socinfo->v2.raw_id, socinfo->v2.raw_version,
+ socinfo->v3.hw_platform, socinfo->v4.platform_version,
+ socinfo->v5.accessory_chip,
+ socinfo->v6.hw_platform_subtype,
+ socinfo->v7.pmic_model,
+ socinfo->v7.pmic_die_revision,
+ socinfo->v9.foundry_id);
+ break;
+
+ default:
+ pr_err("%s: Unknown format found\n", __func__);
+ break;
+ }
+}
+
+int __init socinfo_init(void)
+{
+ static bool socinfo_init_done;
+
+ if (socinfo_init_done)
+ return 0;
+
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v9),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo))
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v8),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo))
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v7),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo))
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v6),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo))
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v5),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo))
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v4),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo))
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v3),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo))
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v2),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo))
+ socinfo = smem_find(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v1),
+ 0,
+ SMEM_ANY_HOST_FLAG);
+
+ if (IS_ERR_OR_NULL(socinfo)) {
+ pr_warn("%s: Can't find SMEM_HW_SW_BUILD_ID; falling back on dummy values.\n",
+ __func__);
+ socinfo = setup_dummy_socinfo();
+ }
+
+ WARN(!socinfo_get_id(), "Unknown SOC ID!\n");
+
+ if (socinfo_get_id() >= ARRAY_SIZE(cpu_of_id))
+ BUG_ON("New IDs added! ID => CPU mapping needs an update.\n");
+ else
+ cur_cpu = cpu_of_id[socinfo->v1.id].generic_soc_type;
+
+ boot_stats_init();
+ socinfo_print();
+ arch_read_hardware_id = msm_read_hardware_id;
+ socinfo_init_done = true;
+
+ return 0;
+}
+subsys_initcall(socinfo_init);
+
+const int get_core_count(void)
+{
+ if (!(read_cpuid_mpidr() & BIT(31)))
+ return 1;
+
+ if (read_cpuid_mpidr() & BIT(30))
+ return 1;
+
+ /* 1 + the PART[1:0] field of MIDR */
+ return ((read_cpuid_id() >> 4) & 3) + 1;
+}
+
+const int read_msm_cpu_type(void)
+{
+ if (socinfo_get_msm_cpu() != MSM_CPU_UNKNOWN)
+ return socinfo_get_msm_cpu();
+
+ switch (read_cpuid_id()) {
+ case 0x510F02D0:
+ case 0x510F02D2:
+ case 0x510F02D4:
+ return MSM_CPU_8X60;
+
+ case 0x510F04D0:
+ case 0x510F04D1:
+ case 0x510F04D2:
+ case 0x511F04D0:
+ case 0x512F04D0:
+ return MSM_CPU_8960;
+
+ case 0x51404D11: /* We can't get here unless we are in bringup */
+ return MSM_CPU_8930;
+
+ case 0x510F06F0:
+ return MSM_CPU_8064;
+
+ case 0x511F06F1:
+ case 0x511F06F2:
+ case 0x512F06F0:
+ return MSM_CPU_8974;
+
+ default:
+ return MSM_CPU_UNKNOWN;
+ };
+}
+
+const int cpu_is_krait(void)
+{
+ return ((read_cpuid_id() & 0xFF00FC00) == 0x51000400);
+}
+
+const int cpu_is_krait_v1(void)
+{
+ switch (read_cpuid_id()) {
+ case 0x510F04D0:
+ case 0x510F04D1:
+ case 0x510F04D2:
+ return 1;
+
+ default:
+ return 0;
+ };
+}
+
+const int cpu_is_krait_v2(void)
+{
+ switch (read_cpuid_id()) {
+ case 0x511F04D0:
+ case 0x511F04D1:
+ case 0x511F04D2:
+ case 0x511F04D3:
+ case 0x511F04D4:
+
+ case 0x510F06F0:
+ case 0x510F06F1:
+ case 0x510F06F2:
+ return 1;
+
+ default:
+ return 0;
+ };
+}
+
+const int cpu_is_krait_v3(void)
+{
+ switch (read_cpuid_id()) {
+ case 0x512F04D0:
+ case 0x511F06F0:
+ case 0x511F06F1:
+ case 0x511F06F2:
+ case 0x510F05D0:
+ case 0x510F07F0:
+ return 1;
+
+ default:
+ return 0;
+ };
+}
diff --git a/include/asm-generic/dma-contiguous.h b/include/asm-generic/dma-contiguous.h
index 292c571750f0..f7aae4d28bf6 100644
--- a/include/asm-generic/dma-contiguous.h
+++ b/include/asm-generic/dma-contiguous.h
@@ -1,9 +1,25 @@
#ifndef _ASM_GENERIC_DMA_CONTIGUOUS_H
#define _ASM_GENERIC_DMA_CONTIGUOUS_H
+#include <linux/device.h>
+#include <linux/dma-contiguous.h>
+
#include <linux/types.h>
static inline void
dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { }
+static inline struct cma *dev_get_cma_area(struct device *dev)
+{
+ if (dev && dev->cma_area)
+ return dev->cma_area;
+ return dma_contiguous_def_area;
+}
+
+static inline void dev_set_cma_area(struct device *dev, struct cma *cma)
+{
+ if (dev)
+ dev->cma_area = cma;
+}
+
#endif
diff --git a/include/asm-generic/percpu-defs.h b/include/asm-generic/percpu-defs.h
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/include/asm-generic/percpu-defs.h
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index aa70cbda327c..a0a37cfc16ea 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -165,9 +165,18 @@
#define IRQCHIP_OF_MATCH_TABLE() OF_TABLE(CONFIG_IRQCHIP, irqchip)
#define CLK_OF_TABLES() OF_TABLE(CONFIG_COMMON_CLK, clk)
#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
-#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
+/* #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method) */
#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
+#ifdef CONFIG_OF
+#define CPU_METHOD_OF_TABLES() . = ALIGN(8); \
+ VMLINUX_SYMBOL(__cpu_method_of_table) = .; \
+ *(__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) = .; \
@@ -496,6 +505,7 @@
MEM_DISCARD(init.rodata) \
CLK_OF_TABLES() \
RESERVEDMEM_OF_TABLES() \
+ CPU_METHOD_OF_TABLES() \
CLKSRC_OF_TABLES() \
CPU_METHOD_OF_TABLES() \
KERNEL_DTB() \
@@ -653,6 +663,11 @@
*(.security_initcall.init) \
VMLINUX_SYMBOL(__security_initcall_end) = .;
+#define COMPAT_EXPORTS \
+ VMLINUX_SYMBOL(__compat_exports_start) = .; \
+ *(.exportcompat.init) \
+ VMLINUX_SYMBOL(__compat_exports_end) = .;
+
#ifdef CONFIG_BLK_DEV_INITRD
#define INIT_RAM_FS \
. = ALIGN(4); \
diff --git a/include/dt-bindings/clock/msm-clocks-8916.h b/include/dt-bindings/clock/msm-clocks-8916.h
new file mode 100644
index 000000000000..c609f3e2969e
--- /dev/null
+++ b/include/dt-bindings/clock/msm-clocks-8916.h
@@ -0,0 +1,222 @@
+/* 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 __MSM_CLOCKS_8916_H
+#define __MSM_CLOCKS_8916_H
+
+/* GPLLs */
+#define clk_gpll0_clk_src 0x5933b69f
+#define clk_gpll0_ao_clk_src 0x6b2fb034
+#define clk_gpll1_clk_src 0x916f8847
+#define clk_gpll2_clk_src 0x7c34503b
+
+/* SR2PLL */
+#define clk_a53sspll 0xf761da94
+
+/* SRCs */
+#define clk_apss_ahb_clk_src 0x36f8495f
+#define clk_blsp1_qup1_i2c_apps_clk_src 0x17f78f5e
+#define clk_blsp1_qup1_spi_apps_clk_src 0xf534c4fa
+#define clk_blsp1_qup2_i2c_apps_clk_src 0x8de71c79
+#define clk_blsp1_qup2_spi_apps_clk_src 0x33cf809a
+#define clk_blsp1_qup3_i2c_apps_clk_src 0xf161b902
+#define clk_blsp1_qup3_spi_apps_clk_src 0x5e95683f
+#define clk_blsp1_qup4_i2c_apps_clk_src 0xb2ecce68
+#define clk_blsp1_qup4_spi_apps_clk_src 0xddb5bbdb
+#define clk_blsp1_qup5_i2c_apps_clk_src 0x71ea7804
+#define clk_blsp1_qup5_spi_apps_clk_src 0x9752f35f
+#define clk_blsp1_qup6_i2c_apps_clk_src 0x28806803
+#define clk_blsp1_qup6_spi_apps_clk_src 0x44a1edc4
+#define clk_blsp1_uart1_apps_clk_src 0xf8146114
+#define clk_blsp1_uart2_apps_clk_src 0xfc9c2f73
+#define clk_byte0_clk_src 0x75cc885b
+#define clk_cci_clk_src 0x822f3d97
+#define clk_cpp_clk_src 0x8382f56d
+#define clk_camss_ahb_clk_src 0xa68afe9c
+#define clk_camss_gp0_clk_src 0x43b063e9
+#define clk_camss_gp1_clk_src 0xa3315f1b
+#define clk_crypto_clk_src 0x37a21414
+#define clk_csi0_clk_src 0x227e65bc
+#define clk_csi1_clk_src 0x6a2a6c36
+#define clk_csi0phytimer_clk_src 0xc8a309be
+#define clk_csi1phytimer_clk_src 0x7c0fe23a
+#define clk_esc0_clk_src 0xb41d7c38
+#define clk_gfx3d_clk_src 0x917f76ef
+#define clk_gp1_clk_src 0xad85b97a
+#define clk_gp2_clk_src 0xfb1f0065
+#define clk_gp3_clk_src 0x63b693d6
+#define clk_jpeg0_clk_src 0x9a0a0ac3
+#define clk_mdp_clk_src 0x6dc1f8f1
+#define clk_mclk0_clk_src 0x266b3853
+#define clk_mclk1_clk_src 0xa73cad0c
+#define clk_pclk0_clk_src 0xccac1f35
+#define clk_pdm2_clk_src 0x31e494fd
+#define clk_sdcc1_apps_clk_src 0xd4975db2
+#define clk_sdcc2_apps_clk_src 0xfc46c821
+#define clk_usb_hs_system_clk_src 0x28385546
+#define clk_vsync_clk_src 0xecb43940
+#define clk_vfe0_clk_src 0xa0c2bd8f
+#define clk_vcodec0_clk_src 0xbc193019
+
+/* BRANCHEs*/
+#define clk_gcc_blsp1_ahb_clk 0x8caa5b4f
+#define clk_gcc_boot_rom_ahb_clk 0xde2adeb1
+#define clk_gcc_crypto_ahb_clk 0x94de4919
+#define clk_gcc_crypto_axi_clk 0xd4415c9b
+#define clk_gcc_crypto_clk 0x00d390d2
+#define clk_gcc_prng_ahb_clk 0x397e7eaa
+#define clk_gcc_apss_tcu_clk 0xaf56a329
+#define clk_gcc_gfx_tbu_clk 0x18bb9a90
+#define clk_gcc_gtcu_ahb_clk 0xb432168e
+#define clk_gcc_jpeg_tbu_clk 0xcf8fd944
+#define clk_gcc_mdp_tbu_clk 0x82287f76
+#define clk_gcc_smmu_cfg_clk 0x75eaefa5
+#define clk_gcc_venus_tbu_clk 0x7e0b97ce
+#define clk_gcc_vfe_tbu_clk 0x061f2f95
+#define clk_gcc_blsp1_qup1_i2c_apps_clk 0xc303fae9
+#define clk_gcc_blsp1_qup1_spi_apps_clk 0x759a76b0
+#define clk_gcc_blsp1_qup2_i2c_apps_clk 0x1076f220
+#define clk_gcc_blsp1_qup2_spi_apps_clk 0x3e77d48f
+#define clk_gcc_blsp1_qup3_i2c_apps_clk 0x9e25ac82
+#define clk_gcc_blsp1_qup3_spi_apps_clk 0xfb978880
+#define clk_gcc_blsp1_qup4_i2c_apps_clk 0xd7f40f6f
+#define clk_gcc_blsp1_qup4_spi_apps_clk 0x80f8722f
+#define clk_gcc_blsp1_qup5_i2c_apps_clk 0xacae5604
+#define clk_gcc_blsp1_qup5_spi_apps_clk 0xbf3e15d7
+#define clk_gcc_blsp1_qup6_i2c_apps_clk 0x5c6ad820
+#define clk_gcc_blsp1_qup6_spi_apps_clk 0x780d9f85
+#define clk_gcc_blsp1_uart1_apps_clk 0xc7c62f90
+#define clk_gcc_blsp1_uart2_apps_clk 0xf8a61c96
+#define clk_gcc_camss_cci_ahb_clk 0xa81c11ba
+#define clk_gcc_camss_cci_clk 0xb7dd8824
+#define clk_gcc_camss_csi0_ahb_clk 0x175d672a
+#define clk_gcc_camss_csi0_clk 0x6b01b3e1
+#define clk_gcc_camss_csi0phy_clk 0x06a41ff7
+#define clk_gcc_camss_csi0pix_clk 0x61a8a930
+#define clk_gcc_camss_csi0rdi_clk 0x7053c7ae
+#define clk_gcc_camss_csi1_ahb_clk 0x2c2dc261
+#define clk_gcc_camss_csi1_clk 0x1aba4a8c
+#define clk_gcc_camss_csi1phy_clk 0x0fd1d1fa
+#define clk_gcc_camss_csi1pix_clk 0x87fc98d8
+#define clk_gcc_camss_csi1rdi_clk 0x6ac996fe
+#define clk_gcc_camss_csi_vfe0_clk 0xcc73453c
+#define clk_gcc_camss_gp0_clk 0xd2bc3892
+#define clk_gcc_camss_gp1_clk 0xe4c013e1
+#define clk_gcc_camss_ispif_ahb_clk 0x3c0a858f
+#define clk_gcc_camss_jpeg0_clk 0x1ed3f032
+#define clk_gcc_camss_jpeg_ahb_clk 0x3bfa7603
+#define clk_gcc_camss_jpeg_axi_clk 0x3e278896
+#define clk_gcc_camss_mclk0_clk 0x80902deb
+#define clk_gcc_camss_mclk1_clk 0x5002d85f
+#define clk_gcc_camss_micro_ahb_clk 0xfbbee8cf
+#define clk_gcc_camss_csi0phytimer_clk 0xf8897589
+#define clk_gcc_camss_csi1phytimer_clk 0x4d26438f
+#define clk_gcc_camss_ahb_clk 0x9894b414
+#define clk_gcc_camss_top_ahb_clk 0x4e814a78
+#define clk_gcc_camss_cpp_ahb_clk 0x4ac95e14
+#define clk_gcc_camss_cpp_clk 0x7118a0de
+#define clk_gcc_camss_vfe0_clk 0xaaa3cd97
+#define clk_gcc_camss_vfe_ahb_clk 0x4050f47a
+#define clk_gcc_camss_vfe_axi_clk 0x77fe2384
+#define clk_gcc_oxili_gmem_clk 0x5620913a
+#define clk_gcc_gp1_clk 0x057f7b69
+#define clk_gcc_gp2_clk 0x9bf83ffd
+#define clk_gcc_gp3_clk 0xec6539ee
+#define clk_gcc_mdss_ahb_clk 0xbfb92ed3
+#define clk_gcc_mdss_axi_clk 0x668f51de
+#define clk_gcc_mdss_byte0_clk 0x35da7862
+#define clk_gcc_mdss_esc0_clk 0xaec5cb25
+#define clk_gcc_mdss_mdp_clk 0x22f3521f
+#define clk_gcc_mdss_pclk0_clk 0xcc5c5c77
+#define clk_gcc_mdss_vsync_clk 0x32a09f1f
+#define clk_gcc_mss_cfg_ahb_clk 0x111cde81
+#define clk_gcc_mss_q6_bimc_axi_clk 0x67544d62
+#define clk_gcc_oxili_ahb_clk 0xd15c8a00
+#define clk_gcc_oxili_gfx3d_clk 0x49a51fd9
+#define clk_gcc_pdm2_clk 0x99d55711
+#define clk_gcc_pdm_ahb_clk 0x365664f6
+#define clk_gcc_sdcc1_ahb_clk 0x691e0caa
+#define clk_gcc_sdcc1_apps_clk 0x9ad6fb96
+#define clk_gcc_sdcc2_ahb_clk 0x23d5727f
+#define clk_gcc_sdcc2_apps_clk 0x861b20ac
+#define clk_gcc_usb2a_phy_sleep_clk 0x6caa736f
+#define clk_gcc_usb_hs_ahb_clk 0x72ce8032
+#define clk_gcc_usb_hs_system_clk 0xa11972e5
+#define clk_gcc_venus0_ahb_clk 0x08d778c6
+#define clk_gcc_venus0_axi_clk 0xcdf4c8f6
+#define clk_gcc_venus0_vcodec0_clk 0xf76a02bb
+#define clk_gcc_gfx_tcu_clk 0x59505e55
+#define clk_gcc_gtcu_ahb_bridge_clk 0x19d2c5fe
+#define clk_gcc_bimc_gpu_clk 0x19922503
+#define clk_gcc_bimc_gfx_clk 0x3edd69ad
+
+#define clk_pixel_clk_src 0x8b6f83d8
+#define clk_byte_clk_src 0x3a911c53
+
+/* RPM */
+#define clk_pcnoc_clk 0xc1296d0f
+#define clk_pcnoc_a_clk 0x9bcffee4
+#define clk_pcnoc_msmbus_clk 0x2b53b688
+#define clk_pcnoc_msmbus_a_clk 0x9753a54f
+#define clk_pcnoc_keepalive_a_clk 0x9464f720
+#define clk_pcnoc_sps_clk 0x23d3f584
+#define clk_pcnoc_usb_a_clk 0x11d6a74e
+#define clk_snoc_clk 0x2c341aa0
+#define clk_snoc_a_clk 0x8fcef2af
+#define clk_snoc_msmbus_clk 0xe6900bb6
+#define clk_snoc_msmbus_a_clk 0x5d4683bd
+#define clk_snoc_mmnoc_axi_clk 0xfedd4bd5
+#define clk_snoc_mmnoc_ahb_clk 0xd2149dbb
+#define clk_snoc_usb_a_clk 0x34b7821b
+#define clk_bimc_clk 0x4b80bf00
+#define clk_bimc_a_clk 0x4b25668a
+#define clk_bimc_acpu_a_clk 0x4446311b
+#define clk_bimc_msmbus_clk 0xd212feea
+#define clk_bimc_msmbus_a_clk 0x71d1a499
+#define clk_bimc_usb_a_clk 0xea410834
+#define clk_qdss_clk 0x1492202a
+#define clk_qdss_a_clk 0xdd121669
+#define clk_xo_clk_src 0x23f5649f
+#define clk_xo_a_clk_src 0x2fdd2c7c
+#define clk_xo_otg_clk 0x79bca5cc
+#define clk_xo_a2 0xeba5a83d
+#define clk_xo_dwc3_clk 0xfad488ce
+#define clk_xo_ehci_host_clk 0xc7c340b1
+#define clk_xo_lpm_clk 0x2be48257
+#define clk_xo_pil_mss_clk 0xe97a8354
+#define clk_xo_pil_pronto_clk 0x89dae6d0
+#define clk_xo_wlan_clk 0x0116b76f
+
+#define clk_bb_clk1 0xf5304268
+#define clk_bb_clk1_pin 0x6dd0a779
+#define clk_bb_clk2 0xfe15cb87
+#define clk_bb_clk2_pin 0x498938e5
+#define clk_rf_clk1 0xaabeea5a
+#define clk_rf_clk1_pin 0x8f463562
+#define clk_rf_clk2 0x24a30992
+#define clk_rf_clk2_pin 0xa7c5602a
+
+/* DEBUG */
+#define clk_gcc_debug_mux 0x8121ac15
+#define clk_rpm_debug_mux 0x25cd1f3a
+#define clk_wcnss_m_clk 0x709f430b
+#define clk_apss_debug_pri_mux 0xc691ff55
+#define clk_apss_debug_sec_mux 0xc0b680f9
+#define clk_apss_debug_ter_mux 0x32041c48
+#define clk_apc0_m_clk 0xce1e9473
+#define clk_apc1_m_clk 0x990fbaf7
+#define clk_apc2_m_clk 0x252cd4ae
+#define clk_apc3_m_clk 0x78c64486
+#define clk_l2_m_clk 0x4bedf4d0
+
+
+#endif
diff --git a/include/linux/dma-attrs.h b/include/linux/dma-attrs.h
index c8e1831d7572..eb1b9d727f39 100644
--- a/include/linux/dma-attrs.h
+++ b/include/linux/dma-attrs.h
@@ -18,6 +18,8 @@ enum dma_attr {
DMA_ATTR_NO_KERNEL_MAPPING,
DMA_ATTR_SKIP_CPU_SYNC,
DMA_ATTR_FORCE_CONTIGUOUS,
+ DMA_ATTR_STRONGLY_ORDERED,
+ DMA_ATTR_SKIP_ZEROING,
DMA_ATTR_MAX,
};
diff --git a/include/linux/dma-removed.h b/include/linux/dma-removed.h
new file mode 100644
index 000000000000..3a0f1a4b45e7
--- /dev/null
+++ b/include/linux/dma-removed.h
@@ -0,0 +1,16 @@
+/*
+ * 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 <linux/dma-mapping.h>
+
+extern struct dma_map_ops removed_dma_ops;
diff --git a/include/linux/msm_rtb.h b/include/linux/msm_rtb.h
new file mode 100644
index 000000000000..f8033c02feb2
--- /dev/null
+++ b/include/linux/msm_rtb.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+#ifndef __MSM_RTB_H__
+#define __MSM_RTB_H__
+
+/*
+ * These numbers are used from the kernel command line and sysfs
+ * to control filtering. Remove items from here with extreme caution.
+ */
+enum logk_event_type {
+ LOGK_NONE = 0,
+ LOGK_READL = 1,
+ LOGK_WRITEL = 2,
+ LOGK_LOGBUF = 3,
+ LOGK_HOTPLUG = 4,
+ LOGK_CTXID = 5,
+ LOGK_TIMESTAMP = 6,
+ LOGK_L2CPREAD = 7,
+ LOGK_L2CPWRITE = 8,
+};
+
+#define LOGTYPE_NOPC 0x80
+
+struct msm_rtb_platform_data {
+ unsigned int size;
+};
+
+#if defined(CONFIG_MSM_RTB)
+/*
+ * returns 1 if data was logged, 0 otherwise
+ */
+int uncached_logk_pc(enum logk_event_type log_type, void *caller,
+ void *data);
+
+/*
+ * returns 1 if data was logged, 0 otherwise
+ */
+int uncached_logk(enum logk_event_type log_type, void *data);
+
+#define ETB_WAYPOINT do { \
+ BRANCH_TO_NEXT_ISTR; \
+ nop(); \
+ BRANCH_TO_NEXT_ISTR; \
+ nop(); \
+ } while (0)
+
+#define BRANCH_TO_NEXT_ISTR asm volatile("b .+4\n" : : : "memory")
+/*
+ * both the mb and the isb are needed to ensure enough waypoints for
+ * etb tracing
+ */
+#define LOG_BARRIER do { \
+ mb(); \
+ isb();\
+ } while (0)
+#else
+
+static inline int uncached_logk_pc(enum logk_event_type log_type,
+ void *caller,
+ void *data) { return 0; }
+
+static inline int uncached_logk(enum logk_event_type log_type,
+ void *data) { return 0; }
+
+#define ETB_WAYPOINT
+#define BRANCH_TO_NEXT_ISTR
+/*
+ * Due to a GCC bug, we need to have a nop here in order to prevent an extra
+ * read from being generated after the write.
+ */
+#define LOG_BARRIER nop()
+#endif
+#endif
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index 420032d41d27..f3a800001028 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -53,6 +53,19 @@
__attribute__((section(".discard"), unused))
/*
+ * Macro which verifies @ptr is a percpu pointer without evaluating
+ * @ptr. This is to be used in percpu accessors to verify that the
+ * input parameter is a percpu pointer.
+ *
+ * + 0 is required in order to convert the pointer type from a
+ * potential array type to a pointer to a single item of the array.
+ */
+#define __verify_pcpu_ptr(ptr) do { \
+ const void __percpu *__vpp_verify = (typeof((ptr) + 0))NULL; \
+ (void)__vpp_verify; \
+} while (0)
+
+/*
* s390 and alpha modules require percpu variables to be defined as
* weak to force the compiler to generate GOT based external
* references for them. This is necessary because percpu sections
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 67fc8fcdc4b0..c9c38aa25ac5 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -34,7 +34,6 @@ extern int reboot_default;
extern int reboot_cpu;
extern int reboot_force;
-
extern int register_reboot_notifier(struct notifier_block *);
extern int unregister_reboot_notifier(struct notifier_block *);
diff --git a/include/linux/regulator/krait-regulator.h b/include/linux/regulator/krait-regulator.h
new file mode 100644
index 000000000000..10d7e2675f8f
--- /dev/null
+++ b/include/linux/regulator/krait-regulator.h
@@ -0,0 +1,39 @@
+/* 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 __KRAIT_REGULATOR_H__
+#define __KRAIT_REGULATOR_H__
+
+#define KRAIT_REGULATOR_DRIVER_NAME "krait-power-regulator"
+#define KRAIT_PDN_DRIVER_NAME "krait-pdn"
+
+/**
+ * krait_power_init - driver initialization function
+ *
+ * This function registers the krait-power-regulator platform driver. This
+ * should be called from appropriate initialization code. Returns 0 on
+ * success and error on failure.
+ */
+
+#ifdef CONFIG_KRAIT_REGULATOR
+int __init krait_power_init(void);
+void secondary_cpu_hs_init(void *base_ptr, int cpu);
+#else
+static inline int __init krait_power_init(void)
+{
+ return -ENOSYS;
+}
+
+static inline void secondary_cpu_hs_init(void *base_ptr, int cpu) {}
+#endif
+
+#endif
diff --git a/include/linux/sched_clock.h b/include/linux/sched_clock.h
index efa931c5cef1..e10601e855c8 100644
--- a/include/linux/sched_clock.h
+++ b/include/linux/sched_clock.h
@@ -16,5 +16,10 @@ static inline void sched_clock_postinit(void) { }
extern void sched_clock_register(u64 (*read)(void), int bits,
unsigned long rate);
+extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
+extern void sched_clock_register(u64 (*read)(void), int bits,
+ unsigned long rate);
+
+extern unsigned long long (*sched_clock_func)(void);
#endif
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 93dff5fff524..6aaaddafd7a8 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -111,6 +111,27 @@ void generic_smp_call_function_single_interrupt(void);
generic_smp_call_function_single_interrupt
/*
+ * Call a function on all processors
+ */
+int on_each_cpu(smp_call_func_t func, void *info, int wait);
+
+/*
+ * Call a function on processors specified by mask, which might include
+ * the local one.
+ */
+void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func,
+ void *info, bool wait);
+
+/*
+ * Call a function on each processor for which the supplied function
+ * cond_func returns a positive value. This may include the local
+ * processor.
+ */
+void on_each_cpu_cond(bool (*cond_func)(int cpu, void *info),
+ smp_call_func_t func, void *info, bool wait,
+ gfp_t gfp_flags);
+
+/*
* Mark the boot cpu "online" so that it can call console drivers in
* printk() and can access its per-cpu storage.
*/
diff --git a/include/soc/qcom/boot_stats.h b/include/soc/qcom/boot_stats.h
new file mode 100644
index 000000000000..b607dc3fa5b8
--- /dev/null
+++ b/include/soc/qcom/boot_stats.h
@@ -0,0 +1,17 @@
+/* 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.
+ */
+
+#ifdef CONFIG_MSM_BOOT_STATS
+int boot_stats_init(void);
+#else
+static inline int boot_stats_init(void) { return 0; }
+#endif
diff --git a/include/soc/qcom/pm.h b/include/soc/qcom/pm.h
new file mode 100644
index 000000000000..47de77c385fd
--- /dev/null
+++ b/include/soc/qcom/pm.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
+ * Author: San Mehat <san@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_PM_H
+#define __ARCH_ARM_MACH_MSM_PM_H
+
+#include <linux/types.h>
+#include <linux/cpuidle.h>
+#include <asm/smp_plat.h>
+
+#if !defined(CONFIG_SMP)
+#define msm_secondary_startup NULL
+#elif defined(CONFIG_CPU_V7)
+extern void msm_secondary_startup(void);
+#else
+#define msm_secondary_startup secondary_holding_pen
+#endif
+
+enum msm_pm_sleep_mode {
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
+ MSM_PM_SLEEP_MODE_RETENTION,
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE,
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE,
+ MSM_PM_SLEEP_MODE_POWER_COLLAPSE_SUSPEND,
+ MSM_PM_SLEEP_MODE_NR,
+ MSM_PM_SLEEP_MODE_NOT_SELECTED,
+};
+
+enum msm_pm_l2_scm_flag {
+ MSM_SCM_L2_ON = 0,
+ MSM_SCM_L2_OFF = 1,
+ MSM_SCM_L2_RET = 2,
+ MSM_SCM_L2_GDHS = 3,
+};
+
+#define MSM_PM_MODE(cpu, mode_nr) ((cpu) * MSM_PM_SLEEP_MODE_NR + (mode_nr))
+
+struct msm_pm_time_params {
+ uint32_t latency_us;
+ uint32_t sleep_us;
+ uint32_t next_event_us;
+ uint32_t modified_time_us;
+};
+
+struct msm_pm_sleep_status_data {
+ void *base_addr;
+ uint32_t cpu_offset;
+ uint32_t mask;
+};
+
+int msm_pm_mode_sysfs_add(const char *);
+
+/**
+ * msm_pm_sleep_mode_allow() - API to determine if sleep mode is allowed.
+ * @cpu: CPU on which to check for the sleep mode.
+ * @mode: Sleep Mode to check for.
+ * @idle: Idle or Suspend Sleep Mode.
+ *
+ * Helper function to determine if a Idle or Suspend
+ * Sleep mode is allowed for a specific CPU.
+ *
+ * Return: 1 for allowed; 0 if not allowed.
+ */
+int msm_pm_sleep_mode_allow(unsigned int, unsigned int, bool);
+
+/**
+ * msm_pm_sleep_mode_supported() - API to determine if sleep mode is
+ * supported.
+ * @cpu: CPU on which to check for the sleep mode.
+ * @mode: Sleep Mode to check for.
+ * @idle: Idle or Suspend Sleep Mode.
+ *
+ * Helper function to determine if a Idle or Suspend
+ * Sleep mode is allowed and enabled for a specific CPU.
+ *
+ * Return: 1 for supported; 0 if not supported.
+ */
+int msm_pm_sleep_mode_supported(unsigned int, unsigned int, bool);
+
+struct msm_pm_cpr_ops {
+ void (*cpr_suspend)(void);
+ void (*cpr_resume)(void);
+};
+
+void __init msm_pm_set_tz_retention_flag(unsigned int flag);
+void msm_pm_enable_retention(bool enable);
+bool msm_pm_retention_enabled(void);
+void msm_cpu_pm_enter_sleep(enum msm_pm_sleep_mode mode, bool from_idle);
+
+#ifdef CONFIG_MSM_PM
+void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
+int msm_pm_wait_cpu_shutdown(unsigned int cpu);
+int __init msm_pm_sleep_status_init(void);
+void msm_pm_set_l2_flush_flag(enum msm_pm_l2_scm_flag flag);
+void lpm_cpu_hotplug_enter(unsigned int cpu);
+s32 msm_cpuidle_get_deep_idle_latency(void);
+int msm_pm_collapse(unsigned long unused);
+#else
+static inline void msm_pm_set_rpm_wakeup_irq(unsigned int irq) {}
+static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; }
+static inline int msm_pm_sleep_status_init(void) { return 0; };
+static inline void msm_pm_set_l2_flush_flag(unsigned int flag) { }
+static inline void lpm_cpu_hotplug_enter(unsigned int cpu) {};
+static inline s32 msm_cpuidle_get_deep_idle_latency(void) { return 0; }
+#define msm_pm_collapse NULL
+#endif
+
+#ifdef CONFIG_HOTPLUG_CPU
+int msm_platform_secondary_init(unsigned int cpu);
+#else
+static inline int msm_platform_secondary_init(unsigned int cpu) { return 0; }
+#endif
+
+enum msm_pm_time_stats_id {
+ MSM_PM_STAT_REQUESTED_IDLE = 0,
+ MSM_PM_STAT_IDLE_SPIN,
+ MSM_PM_STAT_IDLE_WFI,
+ MSM_PM_STAT_RETENTION,
+ MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE,
+ MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE,
+ MSM_PM_STAT_IDLE_POWER_COLLAPSE,
+ MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE,
+ MSM_PM_STAT_SUSPEND,
+ MSM_PM_STAT_FAILED_SUSPEND,
+ MSM_PM_STAT_NOT_IDLE,
+ MSM_PM_STAT_COUNT
+};
+
+#ifdef CONFIG_MSM_IDLE_STATS
+void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats, int size);
+void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t);
+void msm_pm_l2_add_stat(uint32_t id, int64_t t);
+#else
+static inline void msm_pm_add_stats(enum msm_pm_time_stats_id *enable_stats,
+ int size) {}
+static inline void msm_pm_add_stat(enum msm_pm_time_stats_id id, int64_t t) {}
+static inline void msm_pm_l2_add_stat(uint32_t id, int64_t t) {}
+#endif
+
+void msm_pm_set_cpr_ops(struct msm_pm_cpr_ops *ops);
+extern unsigned long msm_pc_debug_counters_phys;
+#endif /* __ARCH_ARM_MACH_MSM_PM_H */
diff --git a/include/soc/qcom/scm-boot.h b/include/soc/qcom/scm-boot.h
new file mode 100644
index 000000000000..ef108ee7cc8f
--- /dev/null
+++ b/include/soc/qcom/scm-boot.h
@@ -0,0 +1,65 @@
+/* Copyright (c) 2010, 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.
+ */
+#ifndef __MACH_SCM_BOOT_H
+#define __MACH_SCM_BOOT_H
+
+#define SCM_BOOT_ADDR 0x1
+#define SCM_FLAG_COLDBOOT_CPU1 0x01
+#define SCM_FLAG_COLDBOOT_CPU2 0x08
+#define SCM_FLAG_COLDBOOT_CPU3 0x20
+#define SCM_FLAG_WARMBOOT_CPU1 0x02
+#define SCM_FLAG_WARMBOOT_CPU0 0x04
+#define SCM_FLAG_WARMBOOT_CPU2 0x10
+#define SCM_FLAG_WARMBOOT_CPU3 0x40
+
+/* Multicluster Variants */
+#define SCM_BOOT_ADDR_MC 0x11
+#define SCM_FLAG_COLDBOOT_MC 0x02
+#define SCM_FLAG_WARMBOOT_MC 0x04
+
+#ifdef CONFIG_ARM64
+#define SCM_FLAG_HLOS 0x01
+#else
+#define SCM_FLAG_HLOS 0x0
+#endif
+
+#ifdef CONFIG_MSM_SCM
+int scm_set_boot_addr(phys_addr_t addr, unsigned int flags);
+int scm_set_boot_addr_mc(phys_addr_t addr, u32 aff0,
+ u32 aff1, u32 aff2, u32 flags);
+int scm_set_warm_boot_addr_mc_for_all(phys_addr_t addr);
+int scm_is_mc_boot_available(void);
+#else
+static inline int scm_set_boot_addr(phys_addr_t addr, unsigned int flags)
+{
+ WARN_ONCE(1, "CONFIG_MSM_SCM disabled, SCM call will fail silently\n");
+ return 0;
+}
+int scm_set_boot_addr_mc(phys_addr_t addr, u32 aff0,
+ u32 aff1, u32 aff2, u32 flags)
+{
+ WARN_ONCE(1, "CONFIG_MSM_SCM disabled, SCM call will fail silently\n");
+ return 0;
+}
+int scm_set_warm_boot_addr_mc_for_all(phys_addr_t addr)
+{
+ WARN_ONCE(1, "CONFIG_MSM_SCM disabled, SCM call will fail silently\n");
+ return 0;
+}
+static inline int scm_is_mc_boot_available(void)
+{
+ WARN_ONCE(1, "CONFIG_MSM_SCM disabled, SCM call will fail silently\n");
+ return 0;
+}
+#endif
+
+#endif
diff --git a/include/soc/qcom/scm.h b/include/soc/qcom/scm.h
new file mode 100644
index 000000000000..b05a7cb61d05
--- /dev/null
+++ b/include/soc/qcom/scm.h
@@ -0,0 +1,124 @@
+/* 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.
+ */
+#ifndef __MACH_SCM_H
+#define __MACH_SCM_H
+
+#define SCM_SVC_BOOT 0x1
+#define SCM_SVC_PIL 0x2
+#define SCM_SVC_UTIL 0x3
+#define SCM_SVC_TZ 0x4
+#define SCM_SVC_IO 0x5
+#define SCM_SVC_INFO 0x6
+#define SCM_SVC_SSD 0x7
+#define SCM_SVC_FUSE 0x8
+#define SCM_SVC_PWR 0x9
+#define SCM_SVC_MP 0xC
+#define SCM_SVC_DCVS 0xD
+#define SCM_SVC_ES 0x10
+#define SCM_SVC_HDCP 0x11
+#define SCM_SVC_TZSCHEDULER 0xFC
+
+#define SCM_FUSE_READ 0x7
+#define SCM_CMD_HDCP 0x01
+
+/* SCM Features */
+#define SCM_SVC_SEC_CAMERA 0xD
+
+#define DEFINE_SCM_BUFFER(__n) \
+static char __n[PAGE_SIZE] __aligned(PAGE_SIZE);
+
+#define SCM_BUFFER_SIZE(__buf) sizeof(__buf)
+
+#define SCM_BUFFER_PHYS(__buf) virt_to_phys(__buf)
+
+#ifdef CONFIG_MSM_SCM
+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);
+
+extern int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf,
+ size_t cmd_len, void *resp_buf, size_t resp_len,
+ void *scm_buf, size_t scm_buf_size);
+
+
+extern s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1);
+extern s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2);
+extern s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3);
+extern s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3,
+ u32 arg4, u32 *ret1, u32 *ret2);
+
+#define SCM_VERSION(major, minor) (((major) << 16) | ((minor) & 0xFF))
+
+extern u32 scm_get_version(void);
+extern int scm_is_call_available(u32 svc_id, u32 cmd_id);
+extern int scm_get_feat_version(u32 feat);
+
+#define SCM_HDCP_MAX_REG 5
+
+struct scm_hdcp_req {
+ u32 addr;
+ u32 val;
+};
+
+#else
+
+static inline int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf,
+ size_t cmd_len, void *resp_buf, size_t resp_len)
+{
+ return 0;
+}
+
+static inline int scm_call_noalloc(u32 svc_id, u32 cmd_id,
+ const void *cmd_buf, size_t cmd_len, void *resp_buf,
+ size_t resp_len, void *scm_buf, size_t scm_buf_size)
+{
+ return 0;
+}
+
+static inline s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
+{
+ return 0;
+}
+
+static inline s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)
+{
+ return 0;
+}
+
+static inline s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2,
+ u32 arg3)
+{
+ return 0;
+}
+
+static inline s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2,
+ u32 arg3, u32 arg4, u32 *ret1, u32 *ret2)
+{
+ return 0;
+}
+
+static inline u32 scm_get_version(void)
+{
+ return 0;
+}
+
+static inline int scm_is_call_available(u32 svc_id, u32 cmd_id)
+{
+ return 0;
+}
+
+static inline int scm_get_feat_version(u32 feat)
+{
+ return 0;
+}
+
+#endif
+#endif
diff --git a/include/soc/qcom/smem.h b/include/soc/qcom/smem.h
new file mode 100644
index 000000000000..c734dee2d9d0
--- /dev/null
+++ b/include/soc/qcom/smem.h
@@ -0,0 +1,241 @@
+/* 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 _ARCH_ARM_MACH_MSM_SMEM_H_
+#define _ARCH_ARM_MACH_MSM_SMEM_H_
+
+#include <linux/types.h>
+
+enum {
+ SMEM_APPS,
+ SMEM_MODEM,
+ SMEM_Q6,
+ SMEM_DSPS,
+ SMEM_WCNSS,
+ SMEM_MODEM_Q6_FW,
+ SMEM_RPM,
+ NUM_SMEM_SUBSYSTEMS,
+};
+
+/*
+ * Flag options for the XXX_to_proc() API
+ *
+ * SMEM_ITEM_CACHED_FLAG - Indicates this operation should use cachable smem
+ *
+ * SMEM_ANY_HOST_FLAG - Indicates this operation should not apply to smem items
+ * which are limited to a specific host pairing. Will
+ * cause this operation to ignore the to_proc parameter.
+ */
+#define SMEM_ITEM_CACHED_FLAG 1
+#define SMEM_ANY_HOST_FLAG 2
+
+#define SMEM_NUM_SMD_STREAM_CHANNELS 64
+
+/**
+ * OVERFLOW_ADD_UNSIGNED() - check for unsigned overflow
+ *
+ * @type: type to check for overflow
+ * @a: left value to use
+ * @b: right value to use
+ * @returns: true if a + b will result in overflow; false otherwise
+ */
+#define OVERFLOW_ADD_UNSIGNED(type, a, b) \
+ (((type)~0 - (a)) < (b) ? true : false)
+
+enum {
+ /* fixed items */
+ SMEM_PROC_COMM = 0,
+ SMEM_HEAP_INFO,
+ SMEM_ALLOCATION_TABLE,
+ SMEM_VERSION_INFO,
+ SMEM_HW_RESET_DETECT,
+ SMEM_AARM_WARM_BOOT,
+ SMEM_DIAG_ERR_MESSAGE,
+ SMEM_SPINLOCK_ARRAY,
+ SMEM_MEMORY_BARRIER_LOCATION,
+ SMEM_FIXED_ITEM_LAST = SMEM_MEMORY_BARRIER_LOCATION,
+
+ /* dynamic items */
+ SMEM_AARM_PARTITION_TABLE,
+ SMEM_AARM_BAD_BLOCK_TABLE,
+ SMEM_RESERVE_BAD_BLOCKS,
+ SMEM_WM_UUID,
+ SMEM_CHANNEL_ALLOC_TBL,
+ SMEM_SMD_BASE_ID,
+ SMEM_SMEM_LOG_IDX = SMEM_SMD_BASE_ID + SMEM_NUM_SMD_STREAM_CHANNELS,
+ SMEM_SMEM_LOG_EVENTS,
+ SMEM_SMEM_STATIC_LOG_IDX,
+ SMEM_SMEM_STATIC_LOG_EVENTS,
+ SMEM_SMEM_SLOW_CLOCK_SYNC,
+ SMEM_SMEM_SLOW_CLOCK_VALUE,
+ SMEM_BIO_LED_BUF,
+ SMEM_SMSM_SHARED_STATE,
+ SMEM_SMSM_INT_INFO,
+ SMEM_SMSM_SLEEP_DELAY,
+ SMEM_SMSM_LIMIT_SLEEP,
+ SMEM_SLEEP_POWER_COLLAPSE_DISABLED,
+ SMEM_KEYPAD_KEYS_PRESSED,
+ SMEM_KEYPAD_STATE_UPDATED,
+ SMEM_KEYPAD_STATE_IDX,
+ SMEM_GPIO_INT,
+ SMEM_MDDI_LCD_IDX,
+ SMEM_MDDI_HOST_DRIVER_STATE,
+ SMEM_MDDI_LCD_DISP_STATE,
+ SMEM_LCD_CUR_PANEL,
+ SMEM_MARM_BOOT_SEGMENT_INFO,
+ SMEM_AARM_BOOT_SEGMENT_INFO,
+ SMEM_SLEEP_STATIC,
+ SMEM_SCORPION_FREQUENCY,
+ SMEM_SMD_PROFILES,
+ SMEM_TSSC_BUSY,
+ SMEM_HS_SUSPEND_FILTER_INFO,
+ SMEM_BATT_INFO,
+ SMEM_APPS_BOOT_MODE,
+ SMEM_VERSION_FIRST,
+ SMEM_VERSION_SMD = SMEM_VERSION_FIRST,
+ SMEM_VERSION_LAST = SMEM_VERSION_FIRST + 24,
+ SMEM_OSS_RRCASN1_BUF1,
+ SMEM_OSS_RRCASN1_BUF2,
+ SMEM_ID_VENDOR0,
+ SMEM_ID_VENDOR1,
+ SMEM_ID_VENDOR2,
+ SMEM_HW_SW_BUILD_ID,
+ SMEM_SMD_BASE_ID_2,
+ SMEM_SMD_FIFO_BASE_ID_2 = SMEM_SMD_BASE_ID_2 +
+ SMEM_NUM_SMD_STREAM_CHANNELS,
+ SMEM_CHANNEL_ALLOC_TBL_2 = SMEM_SMD_FIFO_BASE_ID_2 +
+ SMEM_NUM_SMD_STREAM_CHANNELS,
+ SMEM_I2C_MUTEX = SMEM_CHANNEL_ALLOC_TBL_2 +
+ SMEM_NUM_SMD_STREAM_CHANNELS,
+ SMEM_SCLK_CONVERSION,
+ SMEM_SMD_SMSM_INTR_MUX,
+ SMEM_SMSM_CPU_INTR_MASK,
+ SMEM_APPS_DEM_SLAVE_DATA,
+ SMEM_QDSP6_DEM_SLAVE_DATA,
+ SMEM_CLKREGIM_BSP,
+ SMEM_CLKREGIM_SOURCES,
+ SMEM_SMD_FIFO_BASE_ID,
+ SMEM_USABLE_RAM_PARTITION_TABLE = SMEM_SMD_FIFO_BASE_ID +
+ SMEM_NUM_SMD_STREAM_CHANNELS,
+ SMEM_POWER_ON_STATUS_INFO,
+ SMEM_DAL_AREA,
+ SMEM_SMEM_LOG_POWER_IDX,
+ SMEM_SMEM_LOG_POWER_WRAP,
+ SMEM_SMEM_LOG_POWER_EVENTS,
+ SMEM_ERR_CRASH_LOG,
+ SMEM_ERR_F3_TRACE_LOG,
+ SMEM_SMD_BRIDGE_ALLOC_TABLE,
+ SMEM_SMDLITE_TABLE,
+ SMEM_SD_IMG_UPGRADE_STATUS,
+ SMEM_SEFS_INFO,
+ SMEM_RESET_LOG,
+ SMEM_RESET_LOG_SYMBOLS,
+ SMEM_MODEM_SW_BUILD_ID,
+ SMEM_SMEM_LOG_MPROC_WRAP,
+ SMEM_BOOT_INFO_FOR_APPS,
+ SMEM_SMSM_SIZE_INFO,
+ SMEM_SMD_LOOPBACK_REGISTER,
+ SMEM_SSR_REASON_MSS0,
+ SMEM_SSR_REASON_WCNSS0,
+ SMEM_SSR_REASON_LPASS0,
+ SMEM_SSR_REASON_DSPS0,
+ SMEM_SSR_REASON_VCODEC0,
+ SMEM_SMP2P_APPS_BASE = 427,
+ SMEM_SMP2P_MODEM_BASE = SMEM_SMP2P_APPS_BASE + 8, /* 435 */
+ SMEM_SMP2P_AUDIO_BASE = SMEM_SMP2P_MODEM_BASE + 8, /* 443 */
+ SMEM_SMP2P_WIRLESS_BASE = SMEM_SMP2P_AUDIO_BASE + 8, /* 451 */
+ SMEM_SMP2P_POWER_BASE = SMEM_SMP2P_WIRLESS_BASE + 8, /* 459 */
+ SMEM_FLASH_DEVICE_INFO = SMEM_SMP2P_POWER_BASE + 8, /* 467 */
+ SMEM_BAM_PIPE_MEMORY, /* 468 */
+ SMEM_IMAGE_VERSION_TABLE, /* 469 */
+ SMEM_LC_DEBUGGER, /* 470 */
+ SMEM_FLASH_NAND_DEV_INFO, /* 471 */
+ SMEM_A2_BAM_DESCRIPTOR_FIFO, /* 472 */
+ SMEM_CPR_CONFIG, /* 473 */
+ SMEM_CLOCK_INFO, /* 474 */
+ SMEM_IPC_FIFO, /* 475 */
+ SMEM_NUM_ITEMS,
+};
+
+#ifdef CONFIG_MSM_SMEM
+void *smem_alloc(unsigned id, unsigned size_in, unsigned to_proc,
+ unsigned flags);
+void *smem_find(unsigned id, unsigned size_in, unsigned to_proc,
+ unsigned flags);
+void *smem_get_entry(unsigned id, unsigned *size, unsigned to_proc,
+ unsigned flags);
+
+/**
+ * smem_get_entry_no_rlock - Get existing item without using remote spinlock
+ *
+ * @id: ID of SMEM item
+ * @size_out: Pointer to size variable for storing the result
+ * @to_proc: SMEM host that shares the item with apps
+ * @flags: Item attribute flags
+ * @returns: Pointer to SMEM item or NULL if it doesn't exist
+ *
+ * This function does not lock the remote spinlock and should only be used in
+ * failure-recover cases such as retrieving the subsystem failure reason during
+ * subsystem restart.
+ */
+void *smem_get_entry_no_rlock(unsigned id, unsigned *size_out, unsigned to_proc,
+ unsigned flags);
+
+/**
+ * smem_virt_to_phys() - Convert SMEM address to physical address.
+ *
+ * @smem_address: Virtual address returned by smem_alloc()
+ * @returns: Physical address (or NULL if there is a failure)
+ *
+ * This function should only be used if an SMEM item needs to be handed
+ * off to a DMA engine.
+ */
+phys_addr_t smem_virt_to_phys(void *smem_address);
+
+/**
+ * SMEM initialization function that registers for a SMEM platform driver.
+ *
+ * @returns: success on successful driver registration.
+ */
+int __init msm_smem_init(void);
+
+#else
+static inline void *smem_alloc(unsigned id, unsigned size_in, unsigned to_proc,
+ unsigned flags)
+{
+ return NULL;
+}
+static inline void *smem_find(unsigned id, unsigned size_in,
+ unsigned to_proc, unsigned flags)
+{
+ return NULL;
+}
+static inline void *smem_get_entry(unsigned id, unsigned *size,
+ unsigned to_proc, unsigned flags)
+{
+ return NULL;
+}
+static inline void *smem_get_entry_no_rlock(unsigned id, unsigned *size_out,
+ unsigned to_proc, unsigned flags)
+{
+ return NULL;
+}
+static inline phys_addr_t smem_virt_to_phys(void *smem_address)
+{
+ return (phys_addr_t) NULL;
+}
+static inline int __init msm_smem_init(void)
+{
+ return 0;
+}
+#endif /* CONFIG_MSM_SMEM */
+#endif /* _ARCH_ARM_MACH_MSM_SMEM_H_ */
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
new file mode 100644
index 000000000000..9f18fd90a94b
--- /dev/null
+++ b/include/soc/qcom/socinfo.h
@@ -0,0 +1,604 @@
+/* Copyright (c) 2009-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 _ARCH_ARM_MACH_MSM_SOCINFO_H_
+#define _ARCH_ARM_MACH_MSM_SOCINFO_H_
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/of_fdt.h>
+#include <linux/of.h>
+
+#include <asm/cputype.h>
+/*
+ * SOC version type with major number in the upper 16 bits and minor
+ * number in the lower 16 bits. For example:
+ * 1.0 -> 0x00010000
+ * 2.3 -> 0x00020003
+ */
+#define SOCINFO_VERSION_MAJOR(ver) ((ver & 0xffff0000) >> 16)
+#define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
+
+#ifdef CONFIG_OF
+#define of_board_is_cdp() of_machine_is_compatible("qcom,cdp")
+#define of_board_is_sim() of_machine_is_compatible("qcom,sim")
+#define of_board_is_rumi() of_machine_is_compatible("qcom,rumi")
+#define of_board_is_fluid() of_machine_is_compatible("qcom,fluid")
+#define of_board_is_liquid() of_machine_is_compatible("qcom,liquid")
+#define of_board_is_dragonboard() \
+ of_machine_is_compatible("qcom,dragonboard")
+#define of_board_is_cdp() of_machine_is_compatible("qcom,cdp")
+#define of_board_is_mtp() of_machine_is_compatible("qcom,mtp")
+#define of_board_is_qrd() of_machine_is_compatible("qcom,qrd")
+#define of_board_is_xpm() of_machine_is_compatible("qcom,xpm")
+#define of_board_is_skuf() of_machine_is_compatible("qcom,skuf")
+#define of_board_is_sbc() of_machine_is_compatible("qcom,sbc")
+
+#define machine_is_msm8974() of_machine_is_compatible("qcom,msm8974")
+#define machine_is_msm9625() of_machine_is_compatible("qcom,msm9625")
+#define machine_is_msm8610() of_machine_is_compatible("qcom,msm8610")
+#define machine_is_msm8226() of_machine_is_compatible("qcom,msm8226")
+#define machine_is_apq8074() of_machine_is_compatible("qcom,apq8074")
+#define machine_is_msm8926() of_machine_is_compatible("qcom,msm8926")
+
+#define early_machine_is_msm8610() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8610")
+#define early_machine_is_mpq8092() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
+#define early_machine_is_msm8916() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8916")
+#define early_machine_is_msm8936() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8936")
+#define early_machine_is_msm8939() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8939")
+#define early_machine_is_apq8084() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,apq8084")
+#define early_machine_is_mdm9630() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mdm9630")
+#define early_machine_is_msmzirc() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzirc")
+#define early_machine_is_fsm9900() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,fsm9900")
+#define early_machine_is_msmsamarium() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmsamarium")
+#else
+#define of_board_is_sim() 0
+#define of_board_is_rumi() 0
+#define of_board_is_fluid() 0
+#define of_board_is_liquid() 0
+#define of_board_is_dragonboard() 0
+#define of_board_is_cdp() 0
+#define of_board_is_mtp() 0
+#define of_board_is_qrd() 0
+#define of_board_is_xpm() 0
+#define of_board_is_skuf() 0
+#define of_board_is_sbc() 0
+
+#define machine_is_msm8974() 0
+#define machine_is_msm9625() 0
+#define machine_is_msm8610() 0
+#define machine_is_msm8226() 0
+#define machine_is_apq8074() 0
+#define machine_is_msm8926() 0
+
+#define early_machine_is_msm8610() 0
+#define early_machine_is_mpq8092() 0
+#define early_machine_is_msm8916() 0
+#define early_machine_is_msm8936() 0
+#define early_machine_is_msm8939() 0
+#define early_machine_is_apq8084() 0
+#define early_machine_is_mdm9630() 0
+#define early_machine_is_fsm9900() 0
+#define early_machine_is_msmsamarium() 0
+#endif
+
+#define PLATFORM_SUBTYPE_MDM 1
+#define PLATFORM_SUBTYPE_INTERPOSERV3 2
+#define PLATFORM_SUBTYPE_SGLTE 6
+
+enum msm_cpu {
+ MSM_CPU_UNKNOWN = 0,
+ MSM_CPU_7X01,
+ MSM_CPU_7X25,
+ MSM_CPU_7X27,
+ MSM_CPU_8X50,
+ MSM_CPU_8X50A,
+ MSM_CPU_7X30,
+ MSM_CPU_8X55,
+ MSM_CPU_8X60,
+ MSM_CPU_8960,
+ MSM_CPU_8960AB,
+ MSM_CPU_7X27A,
+ FSM_CPU_9XXX,
+ MSM_CPU_7X25A,
+ MSM_CPU_7X25AA,
+ MSM_CPU_7X25AB,
+ MSM_CPU_8064,
+ MSM_CPU_8064AB,
+ MSM_CPU_8064AA,
+ MSM_CPU_8930,
+ MSM_CPU_8930AA,
+ MSM_CPU_8930AB,
+ MSM_CPU_7X27AA,
+ MSM_CPU_9615,
+ MSM_CPU_8974,
+ MSM_CPU_8974PRO_AA,
+ MSM_CPU_8974PRO_AB,
+ MSM_CPU_8974PRO_AC,
+ MSM_CPU_8627,
+ MSM_CPU_8625,
+ MSM_CPU_9625,
+ MSM_CPU_8092,
+ MSM_CPU_8916,
+ MSM_CPU_8936,
+ MSM_CPU_8939,
+ MSM_CPU_8226,
+ MSM_CPU_8610,
+ MSM_CPU_8625Q,
+ MSM_CPU_8084,
+ MSM_CPU_9630,
+ FSM_CPU_9900,
+ MSM_CPU_ZIRC,
+};
+
+struct msm_soc_info {
+ enum msm_cpu generic_soc_type;
+ char *soc_id_string;
+};
+
+enum pmic_model {
+ PMIC_MODEL_PM8058 = 13,
+ PMIC_MODEL_PM8028 = 14,
+ PMIC_MODEL_PM8901 = 15,
+ PMIC_MODEL_PM8027 = 16,
+ PMIC_MODEL_ISL_9519 = 17,
+ PMIC_MODEL_PM8921 = 18,
+ PMIC_MODEL_PM8018 = 19,
+ PMIC_MODEL_PM8015 = 20,
+ PMIC_MODEL_PM8014 = 21,
+ PMIC_MODEL_PM8821 = 22,
+ PMIC_MODEL_PM8038 = 23,
+ PMIC_MODEL_PM8922 = 24,
+ PMIC_MODEL_PM8917 = 25,
+ PMIC_MODEL_UNKNOWN = 0xFFFFFFFF
+};
+
+enum msm_cpu socinfo_get_msm_cpu(void);
+uint32_t socinfo_get_id(void);
+uint32_t socinfo_get_version(void);
+uint32_t socinfo_get_raw_id(void);
+char *socinfo_get_build_id(void);
+uint32_t socinfo_get_platform_type(void);
+uint32_t socinfo_get_platform_subtype(void);
+uint32_t socinfo_get_platform_version(void);
+enum pmic_model socinfo_get_pmic_model(void);
+uint32_t socinfo_get_pmic_die_revision(void);
+int __init socinfo_init(void) __must_check;
+const int read_msm_cpu_type(void);
+const int get_core_count(void);
+const int cpu_is_krait(void);
+const int cpu_is_krait_v1(void);
+const int cpu_is_krait_v2(void);
+const int cpu_is_krait_v3(void);
+
+static inline int cpu_is_msm7x01(void)
+{
+#ifdef CONFIG_ARCH_MSM7X01A
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X01;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm7x25(void)
+{
+#ifdef CONFIG_ARCH_MSM7X25
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X25;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm7x27(void)
+{
+#if defined(CONFIG_ARCH_MSM7X27) && !defined(CONFIG_ARCH_MSM7X27A)
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X27;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm7x27a(void)
+{
+#ifdef CONFIG_ARCH_MSM7X27A
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X27A;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm7x27aa(void)
+{
+#ifdef CONFIG_ARCH_MSM7X27A
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X27AA;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm7x25a(void)
+{
+#ifdef CONFIG_ARCH_MSM7X27A
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X25A;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm7x25aa(void)
+{
+#ifdef CONFIG_ARCH_MSM7X27A
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X25AA;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm7x25ab(void)
+{
+#ifdef CONFIG_ARCH_MSM7X27A
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X25AB;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm7x30(void)
+{
+#ifdef CONFIG_ARCH_MSM7X30
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_7X30;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_qsd8x50(void)
+{
+#ifdef CONFIG_ARCH_QSD8X50
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8X50;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8x55(void)
+{
+#ifdef CONFIG_ARCH_MSM7X30
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8X55;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8x60(void)
+{
+#ifdef CONFIG_ARCH_MSM8X60
+ return read_msm_cpu_type() == MSM_CPU_8X60;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8960(void)
+{
+ return 0;
+}
+
+static inline int cpu_is_msm8960ab(void)
+{
+ return 0;
+}
+
+static inline int cpu_is_apq8064(void)
+{
+#ifdef CONFIG_ARCH_APQ8064
+ return read_msm_cpu_type() == MSM_CPU_8064;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_apq8064ab(void)
+{
+#ifdef CONFIG_ARCH_APQ8064
+ return read_msm_cpu_type() == MSM_CPU_8064AB;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_apq8064aa(void)
+{
+#ifdef CONFIG_ARCH_APQ8064
+ return read_msm_cpu_type() == MSM_CPU_8064AA;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8930(void)
+{
+#ifdef CONFIG_ARCH_MSM8930
+ return read_msm_cpu_type() == MSM_CPU_8930;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8930aa(void)
+{
+#ifdef CONFIG_ARCH_MSM8930
+ return read_msm_cpu_type() == MSM_CPU_8930AA;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8930ab(void)
+{
+#ifdef CONFIG_ARCH_MSM8930
+ return read_msm_cpu_type() == MSM_CPU_8930AB;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8627(void)
+{
+/* 8930 and 8627 will share the same CONFIG_ARCH type unless otherwise needed */
+#ifdef CONFIG_ARCH_MSM8930
+ return read_msm_cpu_type() == MSM_CPU_8627;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_fsm9xxx(void)
+{
+#ifdef CONFIG_ARCH_FSM9XXX
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == FSM_CPU_9XXX;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm9615(void)
+{
+#ifdef CONFIG_ARCH_MSM9615
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_9615;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8625(void)
+{
+#ifdef CONFIG_ARCH_MSM8625
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8625;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8974(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8974;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8974pro_aa(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8974PRO_AA;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8974pro_ab(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8974PRO_AB;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8974pro_ac(void)
+{
+#ifdef CONFIG_ARCH_MSM8974
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8974PRO_AC;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_mpq8092(void)
+{
+#ifdef CONFIG_ARCH_MPQ8092
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8092;
+#else
+ return 0;
+#endif
+
+}
+
+static inline int cpu_is_msm8916(void)
+{
+#ifdef CONFIG_ARCH_MSM8916
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8916;
+#else
+ return 0;
+#endif
+
+}
+
+static inline int cpu_is_msm8936(void)
+{
+#ifdef CONFIG_ARCH_MSM8916
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8936;
+#else
+ return 0;
+#endif
+
+}
+
+static inline int cpu_is_msm8939(void)
+{
+#ifdef CONFIG_ARCH_MSM8916
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8939;
+#else
+ return 0;
+#endif
+
+}
+
+static inline int cpu_is_msm8226(void)
+{
+#ifdef CONFIG_ARCH_MSM8226
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8226;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8610(void)
+{
+#ifdef CONFIG_ARCH_MSM8610
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8610;
+#else
+ return 0;
+#endif
+}
+
+static inline int cpu_is_msm8625q(void)
+{
+#ifdef CONFIG_ARCH_MSM8625
+ enum msm_cpu cpu = socinfo_get_msm_cpu();
+
+ BUG_ON(cpu == MSM_CPU_UNKNOWN);
+ return cpu == MSM_CPU_8625Q;
+#else
+ return 0;
+#endif
+}
+
+static inline int soc_class_is_msm8960(void)
+{
+ return cpu_is_msm8960() || cpu_is_msm8960ab();
+}
+
+static inline int soc_class_is_apq8064(void)
+{
+ return cpu_is_apq8064() || cpu_is_apq8064ab() || cpu_is_apq8064aa();
+}
+
+static inline int soc_class_is_msm8930(void)
+{
+ return cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8930ab() ||
+ cpu_is_msm8627();
+}
+
+static inline int soc_class_is_msm8974(void)
+{
+ return cpu_is_msm8974() || cpu_is_msm8974pro_aa() ||
+ cpu_is_msm8974pro_ab() || cpu_is_msm8974pro_ac();
+}
+
+#endif
diff --git a/init/Kconfig b/init/Kconfig
index 2081a4d3d917..7bc67dab58f1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1345,6 +1345,12 @@ config HAVE_PCSPKR_PLATFORM
config BPF
bool
+config PANIC_TIMEOUT
+ int "Default panic timeout"
+ default 0
+ help
+ Set default panic timeout.
+
menuconfig EXPERT
bool "Configure standard kernel features (expert users)"
# Unhide debug options, to make the on-by-default options visible
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 54be19a0fa51..5f7772fcc953 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -295,6 +295,12 @@ _dtbinst_pre_:
%.dtb_dtbinst_: $(obj)/%.dtb _dtbinst_pre_
$(call cmd,dtb_install,$(INSTALL_DTBS_PATH))
+# cat
+# ---------------------------------------------------------------------------
+# Concatentate multiple files together
+quiet_cmd_cat = CAT $@
+cmd_cat = (cat $(filter-out FORCE,$^) > $@) || (rm -f $@; false)
+
# Bzip2
# ---------------------------------------------------------------------------