diff --git a/AndroidKernel.mk b/AndroidKernel.mk
new file mode 100644
index 00000000000..dcb81d72d65
--- /dev/null
+++ b/AndroidKernel.mk
@@ -0,0 +1,64 @@
+#Android makefile to build kernel as a part of Android Build
+
+ifeq ($(TARGET_PREBUILT_KERNEL),)
+
+KERNEL_OUT := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ
+KERNEL_CONFIG := $(KERNEL_OUT)/.config
+TARGET_PREBUILT_INT_KERNEL := $(KERNEL_OUT)/arch/arm/boot/zImage
+KERNEL_HEADERS_INSTALL := $(KERNEL_OUT)/usr
+KERNEL_MODULES_INSTALL := system
+KERNEL_MODULES_OUT := $(TARGET_OUT)/lib/modules
+
+ifeq ($(TARGET_USES_UNCOMPRESSED_KERNEL),true)
+$(info Using uncompressed kernel)
+TARGET_PREBUILT_KERNEL := $(KERNEL_OUT)/piggy
+else
+TARGET_PREBUILT_KERNEL := $(TARGET_PREBUILT_INT_KERNEL)
+endif
+
+define mv-modules
+mdpath=`find $(KERNEL_MODULES_OUT) -type f -name modules.dep`;\
+if [ "$$mdpath" != "" ];then\
+mpath=`dirname $$mdpath`;\
+ko=`find $$mpath/kernel -type f -name *.ko`;\
+for i in $$ko; do mv $$i $(KERNEL_MODULES_OUT)/; done;\
+fi
+endef
+
+define clean-module-folder
+mdpath=`find $(KERNEL_MODULES_OUT) -type f -name modules.dep`;\
+if [ "$$mdpath" != "" ];then\
+mpath=`dirname $$mdpath`; rm -rf $$mpath;\
+fi
+endef
+
+$(KERNEL_OUT):
+ mkdir -p $(KERNEL_OUT)
+
+$(KERNEL_CONFIG): $(KERNEL_OUT)
+ $(MAKE) -C kernel O=../$(KERNEL_OUT) ARCH=arm CROSS_COMPILE=arm-eabi- $(KERNEL_DEFCONFIG)
+
+$(KERNEL_OUT)/piggy : $(TARGET_PREBUILT_INT_KERNEL)
+ $(hide) gunzip -c $(KERNEL_OUT)/arch/arm/boot/compressed/piggy.gzip > $(KERNEL_OUT)/piggy
+
+$(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_OUT) $(KERNEL_CONFIG) $(KERNEL_HEADERS_INSTALL)
+ $(MAKE) -C kernel O=../$(KERNEL_OUT) ARCH=arm CROSS_COMPILE=arm-eabi-
+ $(MAKE) -C kernel O=../$(KERNEL_OUT) ARCH=arm CROSS_COMPILE=arm-eabi- modules
+ $(MAKE) -C kernel O=../$(KERNEL_OUT) INSTALL_MOD_PATH=../../$(KERNEL_MODULES_INSTALL) ARCH=arm CROSS_COMPILE=arm-eabi- modules_install
+ $(mv-modules)
+ $(clean-module-folder)
+
+$(KERNEL_HEADERS_INSTALL): $(KERNEL_OUT) $(KERNEL_CONFIG)
+ $(MAKE) -C kernel O=../$(KERNEL_OUT) ARCH=arm CROSS_COMPILE=arm-eabi- headers_install
+
+kerneltags: $(KERNEL_OUT) $(KERNEL_CONFIG)
+ $(MAKE) -C kernel O=../$(KERNEL_OUT) ARCH=arm CROSS_COMPILE=arm-eabi- tags
+
+kernelconfig: $(KERNEL_OUT) $(KERNEL_CONFIG)
+ env KCONFIG_NOTIMESTAMP=true \
+ $(MAKE) -C kernel O=../$(KERNEL_OUT) ARCH=arm CROSS_COMPILE=arm-eabi- menuconfig
+ env KCONFIG_NOTIMESTAMP=true \
+ $(MAKE) -C kernel O=../$(KERNEL_OUT) ARCH=arm CROSS_COMPILE=arm-eabi- savedefconfig
+ cp $(KERNEL_OUT)/defconfig kernel/arch/arm/configs/$(KERNEL_DEFCONFIG)
+
+endif
diff --git a/Documentation/DocBook/debugobjects.tmpl b/Documentation/DocBook/debugobjects.tmpl
index 08ff908aa7a..24979f691e3 100644
--- a/Documentation/DocBook/debugobjects.tmpl
+++ b/Documentation/DocBook/debugobjects.tmpl
@@ -96,6 +96,7 @@
debug_object_deactivate
debug_object_destroy
debug_object_free
+ debug_object_assert_init
Each of these functions takes the address of the real object and
a pointer to the object type specific debug description
@@ -273,6 +274,26 @@
debug checks.
+
+
+ debug_object_assert_init
+
+ This function is called to assert that an object has been
+ initialized.
+
+
+ When the real object is not tracked by debugobjects, it calls
+ fixup_assert_init of the object type description structure
+ provided by the caller, with the hardcoded object state
+ ODEBUG_NOT_AVAILABLE. The fixup function can correct the problem
+ by calling debug_object_init and other specific initializing
+ functions.
+
+
+ When the real object is already tracked by debugobjects it is
+ ignored.
+
+
Fixup functions
@@ -381,6 +402,35 @@
statistics.
+
+ fixup_assert_init
+
+ This function is called from the debug code whenever a problem
+ in debug_object_assert_init is detected.
+
+
+ Called from debug_object_assert_init() with a hardcoded state
+ ODEBUG_STATE_NOTAVAILABLE when the object is not found in the
+ debug bucket.
+
+
+ The function returns 1 when the fixup was successful,
+ otherwise 0. The return value is used to update the
+ statistics.
+
+
+ Note, this function should make sure debug_object_init() is
+ called before returning.
+
+
+ The handling of statically initialized objects is a special
+ case. The fixup function should check if this is a legitimate
+ case of a statically initialized object or not. In this case only
+ debug_object_init() should be called to make the object known to
+ the tracker. Then the function should return 0 because this is not
+ a real fixup.
+
+
Known Bugs And Assumptions
diff --git a/Documentation/arm/msm/boot.txt b/Documentation/arm/msm/boot.txt
new file mode 100644
index 00000000000..1a41cd53202
--- /dev/null
+++ b/Documentation/arm/msm/boot.txt
@@ -0,0 +1,23 @@
+Introduction
+=============
+The power management integrated circuit (PMIC) records the reason the
+Application processor was powered on in Shared Memory.
+The hardware and software used is the shared memory interface. This document
+is not for the purpose of describing this interface, but to identify the
+possible values for this data item.
+
+Description
+===========
+Shared memory item (SMEM_POWER_ON_STATUS_INFO) is read to get access to
+this data. The table below identifies the possible values stored.
+
+power_on_status values set by the PMIC for power on event:
+----------------------------------------------------------
+0x01 -- keyboard power on
+0x02 -- RTC alarm
+0x04 -- cable power on
+0x08 -- SMPL
+0x10 -- Watch Dog timeout
+0x20 -- USB charger
+0x40 -- Wall charger
+0xFF -- error reading power_on_status value
diff --git a/Documentation/arm/msm/emulate_domain_manager.txt b/Documentation/arm/msm/emulate_domain_manager.txt
new file mode 100644
index 00000000000..b0d007ed4c8
--- /dev/null
+++ b/Documentation/arm/msm/emulate_domain_manager.txt
@@ -0,0 +1,254 @@
+Introduction
+============
+
+8x50 chipset requires the ability to disable HW domain manager function.
+
+The ARM MMU architecture has a feature known as domain manager mode.
+Briefly each page table, section, or supersection is assigned a domain.
+Each domain can be globally configured to NoAccess, Client, or Manager
+mode. These global configurations allow the access permissions of the
+entire domain to be changed simultaneously.
+
+The domain manger emulation is required to fix a HW problem on the 8x50
+chipset. The problem is simple to repair except when domain manager mode
+is enabled. The emulation allows the problem to be completely resolved.
+
+
+Hardware description
+====================
+
+When domain manager mode is enabled on a specific domain, the MMU
+hardware ignores the access permission bits and the execute never bit. All
+accesses, to memory in the domain, are granted full read, write,
+execute permissions.
+
+The mode of each domain is controlled by a field in the cp15 dacr register.
+Each domain can be globally configured to NoAccess, Client, or Manager mode.
+
+See: ARMv7 Architecture Reference Manual
+
+
+Software description
+====================
+
+In order to disable domain manager mode the equivalent HW functionality must
+be emulated in SW. Any attempts to enable domain manager mode, must be
+intercepted.
+
+Because domain manager mode is not enabled, permissions for the
+associated domain will remain restricted. Permission faults will be generated.
+The permission faults will be intercepted. The faulted pages/sections will
+be modified to grant full access and execute permissions.
+
+The modified page tables must be restored when exiting domain manager mode.
+
+
+Design
+======
+
+Design Goals:
+
+Disable Domain Manager Mode
+Exact SW emulation of Domain Manager Mode
+Minimal Kernel changes
+Minimal Security Risk
+
+Design Decisions:
+
+Detect kernel page table modifications on restore
+Direct ARMv7 HW MMU table manipulation
+Restore emulation modified MMU entries on context switch
+No need to restore MMU entries for MMU entry copy operations
+Invalidate TLB entries on modification
+Store Domain Manager bits in memory
+8 entry MMU entry cache
+Use spin_lock_irqsave to protect domain manipulation
+Assume no split MMU table
+
+Design Discussion:
+
+Detect kernel page table modifications on restore -
+When restoring original page/section permission faults, the submitted design
+verifies the MMU entry has not been modified. The kernel modifies MMU
+entries for the following purposes : create a memory mapping, release a
+memory mapping, add permissions during a permission fault, and map a page
+during a translation fault. The submitted design works with the listed
+scenarios. The translation fault and permission faults simply do not happen on
+relevant entries (valid entries with full access permissions). The alternative
+would be to hook every MMU table modification. The alternative greatly
+increases complexity and code maintenance issues.
+
+Direct ARMv7 HW MMU table manipulation -
+The natural choice would be to use the kernel provided mechanism to manipulate
+MMU page table entries. The ARM MMU interface is described in pgtable.h.
+This interface is complicated by the Linux implementation. The level 1 pgd
+entries are treated and manipulated as entry pairs. The level 2 entries are
+shadowed and cloned. The compromise was chosen to actually use the ARMv7 HW
+registers to walk and modify the MMU table entries. The choice limits the
+usage of this implementation to ARMv7 and similar ARM MMU architectures. Since
+this implementation is targeted at fixing an issue in 8x50 ARMv7, the choice is
+logical. The HW manipulation is in distinct low level functions. These could
+easily be replaced or generalized to support other architectures as necessary.
+
+Restore emulation modified MMU entries on context switch -
+This additional hook was added to minimize performance impact. By guaranteeing
+the ASID will not change during the emulation, the emulation may invalidate each
+entry by MVA & ASID. Only the affected page table entries will be removed from
+the TLB cache. The performance cost of the invalidate on context switch is near
+zero. Typically on context switch the domain mode would also change, forcing a
+complete restore of all modified MMU entries. The alternative would be to
+invalidate the entire TLB every time a table entry is restored.
+
+No need to restore MMU entries for copy operations -
+Operations which copy MMU entries are relatively rare in the kernel. Because
+we modify the level 2 pte entries directly in hardware, the Linux shadow copies
+are left untouched. The kernel treats the shadow copies as the primary pte
+entry. Any pte copy operations would be unaffected by the HW modification.
+On translation section fault, pgd entries are copied from the kernel master
+page table to the current thread page table. Since we restore MMU entries on
+context switch, we guarantee the master table will not contain modifications,
+while faulting on a process local entry. Other read, modify write operations
+occur during permission fault handling. Since we open permission on modified
+entries, these do not need to be restored, because we guarantee these
+permission fault operations will not happen.
+
+Invalidate TLB entries on modification -
+No real choice here. This is more of a design requirement. On permission
+fault, the MMU entry with restricted permissions will be in the TLB. To open
+access permissions, the TLB entry must be invalidated. Otherwise the access
+will permission fault again. Upon restoring original MMU entries, the TLB
+must be invalidated to restrict memory access.
+
+Store Domain Manager bits in memory -
+There was only one alternative here. 2.6.29 kernel only uses 3 of 16
+possible domains. Additional bits in dacr could be used to store the
+manager bits. This would allow faster access to the manager bits.
+Overall this would reduce any performance impact. The performance
+needs did not seem to justify the added weirdness.
+
+8 entry MMU entry cache-
+The size of the modified MMU entry cache is somewhat arbitrary. The thought
+process is that typically, a thread is using two pointers to perform a copy
+operation. In this case only 2 entries would be required. One could imagine
+a more complicated operation, a masked copy for instance, which would require
+more pointers. 8 pointer seemed to be large enough to minimize risk of
+permission fault thrashing. The disadvantage of a larger cache would simply
+be a longer list of entries to restore.
+
+Use spin_lock_irqsave to protect domain manipulation -
+The obvious choice.
+
+Assume no split MMU table -
+This same assumption is documented in cpu_v7_switch_mm.
+
+
+Power Management
+================
+
+Not affected.
+
+
+SMP/multi-core
+==============
+
+SMP/multicore not supported. This is intended as a 8x50 workaround.
+
+
+Security
+========
+
+MMU page/section permissions must be manipulated correctly to emulate domain
+manager mode. If page permission are left in full access mode, any process
+can read associated memory.
+
+
+Performance
+===========
+
+Performance should be impacted only minimally. When emulating domain manager
+mode, there is overhead added to MMU table/context switches, set_domain()
+calls, data aborts, and prefetch aborts.
+
+Normally the kernel operates with domain != DOMAIN_MANAGER. In this case the
+overhead is minimal. An additional check is required to see if domain manager
+mode is on. This minimal code is added to each of emulation entry points :
+set, data abort, prefetch abort, and MMU table/context switch.
+
+Initial accesses to a MMU protected page/section will generate a permission
+fault. The page will be manipulated to grant full access permissions and
+the access will be retried. This will typically require 2-3 page table
+walks.
+
+On a context switch, all modified MMU entries will be restored. On thread
+resume, additional accesses will be treated as initial accesses.
+
+
+Interface
+=========
+
+The emulation does not have clients. It is hooked to the kernel through a
+small list of functions.
+
+void emulate_domain_manager_set(u32 domain);
+int emulate_domain_manager_data_abort(u32 dfsr, u32 dfar);
+int emulate_domain_manager_prefetch_abort(u32 ifsr, u32 ifar);
+void emulate_domain_manager_switch_mm(
+ unsigned long pgd_phys,
+ struct mm_struct *mm,
+ void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *));
+
+emulate_domain_manager_set() is the set_domain handler. This replaces the
+direct manipulation of CP15 dacr with a function call. This allows emulation
+to prevent setting dacr manager bits. It also allows emulation to restore
+page/section permissions when domain manger is disabled.
+
+emulate_domain_manager_data_abort() handles data aborts caused by domain
+not being set in HW, and handles section/page manipulation.
+
+emulate_domain_manager_prefetch_abort() is the similar prefetch abort handler.
+
+emulate_domain_manager_switch_mm() handles MMU table and context switches.
+This notifies the emulation that the MMU context is changing. Allowing the
+emulation to restore page table entry permission before switching contexts.
+
+
+Config options
+==============
+
+This option is enable/disable by the EMULATE_DOMAIN_MANAGER_V7 option.
+
+
+Dependencies
+============
+
+Implementation is for ARMv7, MMU, and !SMP. Targets solving issue for 8x50
+chipset.
+
+
+User space utilities
+====================
+
+None
+
+
+Other
+=====
+
+Code is implemented in kernel/arch/arm/mm.
+
+
+arch/arm/mm/emulate_domain_manager.c contains comments. No additional public
+documentation available or planned.
+
+
+Known issues
+============
+
+No intent to support SMP or non ARMv7 architectures
+
+
+To do
+=====
+
+None
+
diff --git a/Documentation/arm/msm/gpiomux.txt b/Documentation/arm/msm/gpiomux.txt
index 67a81620adf..aaf0793be07 100644
--- a/Documentation/arm/msm/gpiomux.txt
+++ b/Documentation/arm/msm/gpiomux.txt
@@ -2,112 +2,79 @@ This document provides an overview of the msm_gpiomux interface, which
is used to provide gpio pin multiplexing and configuration on mach-msm
targets.
-History
-=======
-
-The first-generation API for gpio configuration & multiplexing on msm
-is the function gpio_tlmm_config(). This function has a few notable
-shortcomings, which led to its deprecation and replacement by gpiomux:
-
-The 'disable' parameter: Setting the second parameter to
-gpio_tlmm_config to GPIO_CFG_DISABLE tells the peripheral
-processor in charge of the subsystem to perform a look-up into a
-low-power table and apply the low-power/sleep setting for the pin.
-As the msm family evolved this became problematic. Not all pins
-have sleep settings, not all peripheral processors will accept requests
-to apply said sleep settings, and not all msm targets have their gpio
-subsystems managed by a peripheral processor. In order to get consistent
-behavior on all targets, drivers are forced to ignore this parameter,
-rendering it useless.
-
-The 'direction' flag: for all mux-settings other than raw-gpio (0),
-the output-enable bit of a gpio is hard-wired to a known
-input (usually VDD or ground). For those settings, the direction flag
-is meaningless at best, and deceptive at worst. In addition, using the
-direction flag to change output-enable (OE) directly can cause trouble in
-gpiolib, which has no visibility into gpio direction changes made
-in this way. Direction control in gpio mode should be made through gpiolib.
-
-Key Features of gpiomux
-=======================
-
-- A consistent interface across all generations of msm. Drivers can expect
-the same results on every target.
-- gpiomux plays nicely with gpiolib. Functions that should belong to gpiolib
-are left to gpiolib and not duplicated here. gpiomux is written with the
-intent that gpio_chips will call gpiomux reference-counting methods
-from their request() and free() hooks, providing full integration.
-- Tabular configuration. Instead of having to call gpio_tlmm_config
-hundreds of times, gpio configuration is placed in a single table.
-- Per-gpio sleep. Each gpio is individually reference counted, allowing only
-those lines which are in use to be put in high-power states.
-- 0 means 'do nothing': all flags are designed so that the default memset-zero
-equates to a sensible default of 'no configuration', preventing users
-from having to provide hundreds of 'no-op' configs for unused or
-unwanted lines.
-
Usage
=====
-To use gpiomux, provide configuration information for relevant gpio lines
-in the msm_gpiomux_configs table. Since a 0 equates to "unconfigured",
-only those lines to be managed by gpiomux need to be specified. Here
-is a completely fictional example:
-
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
- [12] = {
- .active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1,
- .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
- },
- [34] = {
- .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+To use gpiomux, do the following before the msmgpio gpiochips probe:
+
+- Call msm_gpiomux_init to allocate needed resources.
+- Install one or more sets of gpiomux configuration data via
+ msm_gpiomux_install and/or msm_gpiomux_write.
+
+Failing to finish these steps before the probe of msmgpio can result in calls
+from msmgpio to gpiomux to try and activate lines which have not yet
+been configured.
+
+A basic gpiomux setting is described by a gpiomux_setting structure.
+A gpiomux configuration is a group of those settings (one for each power
+state of the board) paired with a specific gpio, like so:
+
+struct msm_gpiomux_config gpio123_config __initdata = {
+ .gpio = 123,
+ .settings = {
+ [GPIOMUX_ACTIVE] = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_HIGH,
+ },
+ [GPIOMUX_SUSPENDED] = {
+ .func = GPIOMUX_FUNC_3,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ },
},
};
-To indicate that a gpio is in use, call msm_gpiomux_get() to increase
-its reference count. To decrease the reference count, call msm_gpiomux_put().
-
The effect of this configuration is as follows:
-When the system boots, gpios 12 and 34 will be initialized with their
-'suspended' configurations. All other gpios, which were left unconfigured,
-will not be touched.
-
-When msm_gpiomux_get() is called on gpio 12 to raise its reference count
-above 0, its active configuration will be applied. Since no other gpio
-line has a valid active configuration, msm_gpiomux_get() will have no
-effect on any other line.
-
-When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference
-count to 0, their suspended configurations will be applied.
-Since no other gpio line has a valid suspended configuration, no other
-gpio line will be effected by msm_gpiomux_put(). Since gpio 34 has no valid
-active configuration, this is effectively a no-op for gpio 34 as well,
-with one small caveat, see the section "About Output-Enable Settings".
-
-All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but
-they address some important issues. As unused entries (all those
-except 12 and 34) are zero-filled, gpiomux needs a way to distinguish
-the used fields from the unused. In addition, the all-zero pattern
-is a valid configuration! Therefore, gpiomux defines an additional bit
-which is used to indicate when a field is used. This has the pleasant
-side-effect of allowing calls to msm_gpiomux_write to use '0' to indicate
-that a value should not be changed:
-
- msm_gpiomux_write(0, GPIOMUX_VALID, 0);
-
-replaces the active configuration of gpio 0 with an all-zero configuration,
-but leaves the suspended configuration as it was.
+- When the system boots, gpio 123 will be put into the SUSPENDED setting.
+- When the reference count for gpio 123 rises above 0, the ACTIVE setting
+ will be applied.
+- When the reference count falls back to 0, the SUSPENDED setting will be
+ reapplied.
+
+The reference count rises when msm_gpiomux_get() is called and falls
+when msm_gpiomux_put() is called. msmgpio has hooks to these functions
+in its gpiolib implementation. This means that when you call gpio_request()
+on an msmgpio, msm_gpiomux_get() is automatically called on your behalf.
+Similarly, when you call gpio_free(), msm_gpiomux_put() is called for you.
+This allows generic drivers to obtain low-level management of msmgpio lines
+without having to be aware of the gpiomux layer.
+
+Note that the .dir field is ignored if .func != GPIOMUX_FUNC_GPIO, since
+software control of gpios is allowed only in GPIO mode. By selecting any
+other .func, you assign the gpio to another piece of hardware and lose
+control of it from gpiolib. You can still reserve such gpios with gpio_request
+to prevent other modules from using them while they're in such a state,
+but other gpiolib functions will not behave as you expect if .func != GPIO.
+
+If a configuration is omitted, nothing will happen at the relevant transitions.
+This allows for the creation of 'static configurations' which do not
+change as the line is requested and freed.
Static Configurations
=====================
To install a static configuration, which is applied at boot and does
not change after that, install a configuration with a suspended component
-but no active component, as in the previous example:
+but no active component:
- [34] = {
- .suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
+ .gpio = ...,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = {
+ ...
+ },
},
The suspended setting is applied during boot, and the lack of any valid
@@ -153,24 +120,3 @@ This provides important functionality:
This mechanism allows for "auto-request" of gpiomux lines via gpiolib
when it is suitable. Drivers wishing more exact control are, of course,
free to also use msm_gpiomux_set and msm_gpiomux_get.
-
-About Output-Enable Settings
-============================
-
-Some msm targets do not have the ability to query the current gpio
-configuration setting. This means that changes made to the output-enable
-(OE) bit by gpiolib cannot be consistently detected and preserved by gpiomux.
-Therefore, when gpiomux applies a configuration setting, any direction
-settings which may have been applied by gpiolib are lost and the default
-input settings are re-applied.
-
-For this reason, drivers should not assume that gpio direction settings
-continue to hold if they free and then re-request a gpio. This seems like
-common sense - after all, anybody could have obtained the line in the
-meantime - but it needs saying.
-
-This also means that calls to msm_gpiomux_write will reset the OE bit,
-which means that if the gpio line is held by a client of gpiolib and
-msm_gpiomux_write is called, the direction setting has been lost and
-gpiolib's internal state has been broken.
-Release gpio lines before reconfiguring them.
diff --git a/Documentation/arm/msm/kgsl-sysfs.txt b/Documentation/arm/msm/kgsl-sysfs.txt
new file mode 100644
index 00000000000..c572312c437
--- /dev/null
+++ b/Documentation/arm/msm/kgsl-sysfs.txt
@@ -0,0 +1,98 @@
+This document lists details for the device specific sysfs attributes
+created by the KGSL GPU driver.
+
+- /sys/devices/platform/kgsl/vmalloc
+ The total amount of vmalloc()ed memory currently allocated by the driver
+ (in bytes)
+
+- /sys/devices/platform/kgsl/vmalloc_max
+ The maximum amount of vmalloc()ed memory allocated at any one
+ time by the driver since the system was booted (in bytes)
+
+- /sys/devices/platform/kgsl/coherent
+ The total amount of coherent DMA memory currently allocated by the driver
+ (in bytes)
+
+- /sys/devices/platform/kgsl/coherent_max
+ The maximum amount of coherent DMA memory allocated at any one
+ time by the driver since the system was booted (in bytes)
+
+
+- /sys/devices/platform/kgsl/histogram
+ A histogram of the sizes of vmalloc allocations by the driver
+ since the system was booted. The allocations are grouped by the order
+ of the allocation size in pages. For example, order 0 are 1 page
+ allocations, order 1 are 2 page allocations, order 2 are 4 page allocations,
+ and so forth, up to order 16 (32768) pages.
+
+- /sys/devices/platform/kgsl/proc
+ This directory contains individual entries for each active rendering
+ process. Rendering instances are created for each unique process that
+ opens the GPU devices, and are named for the id of the creating process.
+ In the driver, memory allocations are owned by the process that allocates
+ them, and outstanding memory is garbage collected when the process closes
+ the device.
+
+ - /sys/devices/platform/kgsl/proc/NN/vmalloc
+ The total amount of vmalloc memory currently allocated by the process
+ (in bytes)
+
+ - /sys/devices/platform/kgsl/proc/NN/vmalloc_max
+ The maximum amount of vmalloc memory allocated at any one
+ time by the process since it was created (in bytes)
+
+ - /sys/devices/platform/kgsl/proc/NN/exmem
+ The total amount of external memory devices currently mapped by the process
+ (in bytes). This includes PMEM, ASHMEM and external memory pointers from
+ userspace.
+
+ - /sys/devices/platform/kgsl/proc/NN/exmem_max
+ The maximum amount of external memory devices allocated at any one
+ time by the process since it was created (in bytes). This includes PMEM,
+ ASHMEM and external memory pointers from userspace.
+
+ - /sys/devices/platform/kgsl/proc/NN/flushes
+ The total number of cache flushes performed by this process since it
+ was created.
+
+- /sys/devices/platform/kgsl/pagetables
+ This directory contains individual entries for each active pagetable.
+ There will always be a global pagetable with ID 0. If per-process
+ pagetables are not enabled, pagetable ID 0 will also be the default
+ pagetable for all processes. If per-process pagetables are enabled,
+ there will be an entry for each pagetable, named after the ID of the
+ process that created it.
+
+ - /sys/devices/platform/kgsl/pagetables/NN/entries
+ The number of concurrent entries mapped in the GPU MMU.
+
+ - /sys/devices/platform/kgsl/pagetables/NN/mapped
+ The number of bytes currently mapped in the GPU MMU.
+
+ - /sys/devices/platform/kgsl/pagetables/NN/va_range
+ The virtual address size of the MMU pagetable (in bytes).
+
+ - /sys/devices/platform/kgsl/pagetables/NN/max_mapped
+ The maximum number of bytes concurrently mapped in the GPU MMU since
+ the pagetable was created.
+
+ - /sys/devices/platform/kgsl/pagetables/NN/max_entries
+ The maximum number of entries concurrently mapped in the GPU MMU since
+ the pagetable was created.
+
+- /sys/devices/platform/kgsl/msm_kgsl/
+ Each individual GPU device (2D or 3D) will have its own device node in
+ this directory. All platforms will have kgsl-3d0 (3D device), some
+ devices may have 1 2D device (kgsl-2d0) and others might add a second 2D
+ device (kgsl-2d1).
+
+ - /sys/devices/platform/kgsl/msm_kgsl/kgsl-XXX/pwrnap
+ Controls the system ability to nap (lightly sleep between frames). 1
+ indicates napping is enabled, 0 indicates it is disabled. Write a 1 or
+ a 0 to the file to control napping.
+
+ - /sys/devices/platform/kgsl/msm_kgsl/kgsl-XXX/gpuclk
+ Shows the last active requested speed of the GPU clock in HZ, does not
+ actually measure the current clock rate. Write a clock speed to the file
+ corresponding to a supported platform power level to change to that power
+ level. The bandwidth vote will also be adjusted.
diff --git a/Documentation/arm/msm/msm_rng-driver.txt b/Documentation/arm/msm/msm_rng-driver.txt
new file mode 100644
index 00000000000..3e7d1e9f460
--- /dev/null
+++ b/Documentation/arm/msm/msm_rng-driver.txt
@@ -0,0 +1,75 @@
+Introduction:
+=============
+
+The msm_rng device driver handles random number generation
+using hardware present in MSM chipsets.
+
+Hardware description:
+=====================
+
+The supported hardware is a macro block within a system-on-a-chip (SoC).
+The hardware is pseudo random number generator (PRNG) with four oscillators
+setup with a linear feedback shift register (LFSR).
+The hardware must be initially configured once for normal operation and
+a 32bit FIFO is read to obtain hardware generated pseudo random numbers.
+Currently the driver configures the hardware registers during initialization
+and the future plan is to have the boot loader configure these registers and
+write lock them so only host OS can read them and the driver writes will be
+ignored.
+
+Software description
+====================
+
+The driver is based on the platform_driver model. It registers an entry,
+exit and probe functions. Once the probe function is called, the driver
+registers a callback function with the hwrng (Hardware Random Number Generator)
+subsystem that is called when the hardware device (i.e. /dev/hw_random) is
+requesting random data from this device.
+Once the callback is issued from the hwrng subsystem, the driver checks to
+make sure the hardware has random data available and determines the maximum
+data it can return and returns that much data back.
+
+Power Management
+================
+
+Initially, no services are provided in the area of power management.
+
+SMP/multi-core
+==============
+
+The locking mechanism for the hwrng operations is taken care of by the hwrng
+framework. There are no SMP situations within the driver that need addressing.
+
+Driver parameters
+=================
+
+This driver is built and statically linked into the kernel; therefore,
+there are no module parameters supported by this driver.
+
+There are no kernel command line parameters supported by this driver.
+
+Config options
+==============
+
+This driver is enabled by the kernel config option CONFIG_HW_RANDOM_MSM.
+The option CONFIG_HW_RANDOM_MSM depends on HW_RANDOM && ARCH_MSM.
+
+Dependencies:
+=============
+
+This driver depends on the HW_RANDOM subsystem to register with and get
+callbacks to request random data.
+
+User space utilities:
+=====================
+
+The driver alone does not feed random numbers into kernel but just provides a
+method to get random numbers to a known device (i.e. /dev/hw_random). A user-
+space utility is required to monitor the /dev/random device entropy pool and
+feed it from the /dev/hw_random device. This application also must perform some
+sort of sanity checking on the returned data to make sure the data is not all
+the same.
+
+There is currently a GPL v2 tool called rng-tools that has a daemon called,
+"rngd" that performs this functionality. There is also a test tool in this
+package that tests the whole random subsystem.
diff --git a/Documentation/arm/msm/pil.txt b/Documentation/arm/msm/pil.txt
new file mode 100644
index 00000000000..5b0b527a6aa
--- /dev/null
+++ b/Documentation/arm/msm/pil.txt
@@ -0,0 +1,267 @@
+Introduction
+============
+
+The PIL (Peripheral Image Loader) driver loads peripheral images into memory
+and interfaces with the Peripheral Authentication Service (PAS) to
+authenticate and reset peripherals embedded in the SoC.
+
+The PAS could either be running under secure mode in the application
+processor (secure boot support) or be running as a non-secure kernel driver
+(non-secure boot support).
+
+The PIL driver also does housekeeping to handle cases where more than one
+client driver is using the same peripheral.
+
+Some examples of peripherals are modem, DSP and sensors.
+
+Hardware description
+====================
+
+The memory used by the peripherals for code and data storage will be
+accessible as normal memory to the application processor.
+
+The non-secure code (Linux kernel) will have read/write permissions to the
+peripheral memory by default.
+
+The PAS will have access to a MPU (memory protection unit) that can lock away
+the pages of memory from the Linux kernel. It will also have access to
+registers that can reset each peripheral.
+
+Software description
+====================
+
+The PAS provides the following three APIs:
+
+* Init image - Takes as input the peripheral id and firmware metadata and
+ returns a status indicating the authenticity of the firmware metadata. The
+ firmware metadata consists of a standard ELF32 header followed by a program
+ header table and an optional blob of data used to authenticate the metadata
+ and the rest of the firmware.
+
+* Verify segment - Takes as input the firmware segment id and the length of
+ the segment. Authenticates whatever amount (specified by the "length"
+ parameter) of the firmware segment that has been loaded and removes
+ non-secure mode read/write permissions for the pages belonging to the
+ firmware segment. Allows multiple calls for the same firmware segment to
+ allow partial loading and authentication.
+
+* Auth and Reset - Verifies all the necessary firmware segments have been
+ loaded and authenticated and then resets the peripheral.
+
+The user space is expected to provide the firmware metadata and firmware
+segments as separate files on persistent storage. See "Interface" section for
+further details.
+
+The PIL driver will use the request_firmware API provided by the Linux kernel
+to read the firmware and firmware metadata from persistent storage.
+
+When a client driver requests for a peripheral to be enabled, the PIL driver
+increments the reference count for that peripheral, loads the firmware
+metadata and calls the PAS Init Image API that initializes the authentication
+state machine using the firmware metadata.
+
+If the initialization succeeds, the PIL driver loads the appropriate firmware
+segments into their respective memory locations and call the PAS Verify
+segment API on each of the loaded segments to authenticate and lock it.
+
+After all the firmware segments have been successfully loaded and
+authenticated, the PAS Auth and Reset API is called to reset the peripheral
+and initiate its boot sequence.
+
+A peripheral enable request to the PIL driver will block until it succeeds
+(or fails) to initiate the peripheral boot sequence but will NOT block until
+the peripheral is ready. It is not possible to block until a peripheral is
+ready since the semantics of "ready" is subjective to the caller.
+
+The PIL driver will maintain a reference count for each of the peripherals.
+So, if a peripheral is already under use and another client driver requests
+for the peripheral to be enabled, the PIL driver will immediately return a
+value to indicate success.
+
+When all the client drivers of a particular peripheral no longer need the
+peripheral and the reference count reaches zero, the PIL driver can cleanly
+shut down the peripheral. Since a lot of drivers in their current state can't
+handle a peripheral restart, the PIL driver will never let the reference
+count go back to zero.
+
+All information about a peripheral, like firmware filenames, peripheral ID
+passed to PAS, etc, will be hard coded in the PIL driver.
+
+All the PIL APIs will execute in the context of the caller. This includes
+calls from the PIL driver to the PAS driver. The PAS driver might decide to
+switch into secure mode from a separate workqueue or in the same context as
+the caller, but that shouldn't have any implications for the PIL API callers
+since all the PIL APIs are blocking calls.
+
+Dependencies:
+-------------
+* Firmware class (CONFIG_FW_LOADER) for using the request_firmware API to
+ load firmware from persistent storage.
+* PAS to authenticate firmware and bring a peripheral out of reset.
+
+Error cases:
+------------
+The PIL driver could fail to enable a peripheral for several reasons like not
+having enough memory to load firmware and metadata, being unable to
+communicate with the PAS, the PAS returning with an error, etc. For all
+possible error cases, the PIL driver does not perform any retries and returns
+an appropriate error code. The client drivers should always check for success
+before trying to access the peripheral.
+
+Design
+======
+
+Design goals:
+-------------
+* The PIL driver must be agnostic to the actual format and method used to
+ authenticate the firmware.
+* Allow for future expansion to support demand loading of parts of firmware
+ for each peripheral.
+* Move most of the work into the preprocessing/building stage of the firmware.
+* Provide an API to the client drivers that absolves them from having to know
+ the structure or names of the firmware in persistent storage.
+* Handle multiple client drivers wanting to enable the same peripheral.
+
+
+Design reasons:
+---------------
+The user space is expected to provide the firmware metadata and segments as
+separate files for the following reasons:
+* Don't need to load the whole ELF file if the authentication info is
+ invalid.
+* Works better during low memory conditions since the amount of memory used
+ at any given instant when loading one segment at a time is smaller than
+ loading the whole ELF file.
+* Since an ELF segment in memory can be much bigger than on file, having a
+ flat binary would waste a lot of space due to zero-fills.
+* Allows for future enhancements to the loading procedure.
+
+Design tradeoffs:
+-----------------
+* With appropriate changes to the request_firmware API, the firmware blobs
+ could be directly loaded into the right memory location. But due to the
+ additional work and community approval that would be needed for modifying
+ the request_firmware API, we load the firmware blobs into kernel memory and
+ then copy them into the appropriate locations.
+
+Alternate designs:
+------------------
+One of the alternate designs that were considered required the firmware to be
+a flat binary. Although this design would simplify the PIL driver, it would
+result in the waste of a lot of persistent storage space (due to large
+zero-fills), prevent demand loading of segments in the future and use a lot
+more memory while loading the firmware.
+
+Software layering:
+------------------
+The peripheral authentication, reset and shutdown implementation is factored
+away into a Peripheral Authentication Service driver to allow the PIL driver
+to be agnostic of secure vs. non-secure boot and the mechanisms needed for
+communicating with any code that might be running in secure mode.
+
+Power Management
+================
+
+Some of the peripherals might support being turned off when not in use.
+Support for this might be disabled in the initial implementation of the PIL
+driver since many of the existing drivers can not handle peripheral restart.
+
+SMP/multi-core
+==============
+
+Will use mutexes to protected data that might be shared (reference count,
+etc).
+
+Security
+========
+
+The PIL driver must validate the physical memory addresses specified in the
+ELF and program header table before loading firmware segments to make sure
+it's not overwriting any memory used by the kernel and possibly PMEM regions
+(if it can be done without being an ugly hack). The PIL driver might need to
+maintain a white list or black list of physical memory address ranges to
+perform the address validation.
+
+Performance
+===========
+
+As mentioned in the design section, the loading of firmware segments is not
+optimal and has room for improvement.
+
+Interface
+=========
+
+In kernel APIs:
+void * pil_get(char *peripheral_name)
+ - Enables (if not already enabled) a peripheral and returns a handle
+ that can be used to disable the peripheral at a later time. If
+ peripheral can't be enabled successfully, then returns an error
+ (use IS_ERR) indicating the reason.
+
+void pil_put(void *peripheral_handle)
+ - Inform PIL that this client no longer needs the peripheral to be
+ active. Does not necessarily mean that the peripheral would be
+ disabled or powered off.
+
+
+User space APIs:
+All firmware must be located in the path that is expected by the hotplug (or
+compatible) daemon. A hotplug (or compatible) daemon should be running and be
+able to handle events from the kernel requesting for a firmware file.
+
+The basename of the firmware files will depend on the peripheral. For a given
+peripheral, the metadata filename should end with a ".mdt" and the firmware
+segment files should end with ".bXX" where XX denotes the index of the
+firmware segment starting from 0.
+
+Android hotplug compatible daemon expects the firmware files to be under
+/etc/firmware.
+
+Driver parameters
+=================
+
+No module or kernel command line parameters supported.
+
+Config options
+==============
+
+This driver is enabled using the MSM_PIL kernel config option and will
+depend on the CONFIG_FW_LOADER being available.
+
+Dependencies
+============
+
+Depends on firmware class module for the request_firmware API.
+
+Interacts with the PAS to authenticate the firmware and to initiate the boot
+sequence of a peripheral.
+
+Doesn't communicate with other processors since the secure code, if any, will
+be running on the application processor cores.
+
+User space utilities
+====================
+
+None.
+
+Other
+=====
+
+The firmware_class driver might be changed in the future to directly load the
+firmware into memory locations provided by the caller of request_firmware().
+
+Known issues
+============
+
+Since support for cleanly shutting down peripherals is yet to be added, the
+reference count of peripherals will never be allowed to go to zero once it
+becomes non-zero.
+
+To do
+=====
+
+* Add support for turning off peripherals when they are not in use.
+* Modify request_firmware() to directly copy firmware blobs into the
+ appropriate memory locations.
+* Add support for demand loading of firmware segments.
+* Add support for forced peripheral restarts.
diff --git a/Documentation/arm/msm/rpm.txt b/Documentation/arm/msm/rpm.txt
new file mode 100644
index 00000000000..9c9511fb030
--- /dev/null
+++ b/Documentation/arm/msm/rpm.txt
@@ -0,0 +1,157 @@
+Introduction
+============
+
+Resource Power Manager (RPM)
+
+RPM is a dedicated hardware engine for managing shared SoC resources,
+which includes buses, clocks, power rails, etc. The goal of RPM is
+to achieve the maximum power savings while satisfying the SoC's
+operational and performance requirements. RPM accepts resource
+requests from multiple RPM masters. It arbitrates and aggregates the
+requests, and configures the shared resources. The RPM masters are
+the application processor, the modem processor, as well as some
+hardware accelerators.
+
+The RPM driver provides an API for interacting with RPM. Kernel code
+calls the RPM driver to request RPM-managed, shared resources.
+Kernel code can also register with the driver for RPM notifications,
+which are sent when the status of shared resources change.
+
+Hardware description
+====================
+
+RPM exposes a separate region of registers to each of the RPM masters.
+In general, each register represents some shared resource(s). At a
+very basic level, a master requests resources by writing to the
+registers, then generating an interrupt to RPM. RPM processes the
+request, writes acknowledgement to the registers, then generates an
+interrupt to the master.
+
+In addition to the master-specific regions, RPM also exposes a shared
+region that contains the current status of the shared resources. Only
+RPM can write to the status region, but every master can read from it.
+
+RPM contains internal logics that aggregate and arbitrate among
+requests from the various RPM masters. It interfaces with the PMIC,
+the bus arbitration block, and the clock controller block in order to
+configure the shared resources.
+
+Software description
+====================
+
+The RPM driver encapsulates the low level RPM interactions, which
+rely on reading/writing registers and generating/processing
+interrupts, and provides a higher level synchronuous set/clear/get
+interface. Most functions take an array of id-value pairs.
+The ids identify the RPM registers which would correspond to some
+RPM resources, the values specify the new resource values.
+
+The RPM driver synchronizes accesses to RPM. It protects against
+simultaneous accesses from multiple tasks, on SMP cores, in task
+contexts, and in atomic contexts.
+
+Design
+======
+
+Design goals:
+- Encapsulate low level RPM interactions.
+- Provide a synchronuous set/clear/get interface.
+- Synchronize simultaneous software accesses to RPM.
+
+Power Management
+================
+
+RPM is part of the power management architecture for MSM 8660. RPM
+manages shared system resources to lower system power.
+
+SMP/multi-core
+==============
+
+The RPM driver uses mutex to synchronize client accesses among tasks.
+It uses spinlocks to synchronize accesses from atomic contexts and
+SMP cores.
+
+Security
+========
+
+None.
+
+Performance
+===========
+
+None.
+
+Interface
+=========
+
+msm_rpm_get_status():
+The function reads the shared status region and returns the current
+resource values, which are the arbitrated/aggregated results across
+all RPM masters.
+
+msm_rpm_set():
+The function makes a resource request to RPM.
+
+msm_rpm_set_noirq():
+The function is similar to msm_rpm_set() except that it must be
+called with interrupts masked. If possible, use msm_rpm_set()
+instead, to maximize CPU throughput.
+
+msm_rpm_clear():
+The function makes a resource request to RPM to clear resource values.
+Once the values are cleared, the resources revert back to their default
+values for this RPM master. RPM internally uses the default values as
+the requests from this RPM master when arbitrating and aggregating with
+requests from other RPM masters.
+
+msm_rpm_clear_noirq():
+The function is similar to msm_rpm_clear() except that it must be
+called with interrupts masked. If possible, use msm_rpm_clear()
+instead, to maximize CPU throughput.
+
+msm_rpm_register_notification():
+The function registers for RPM notification. When the specified
+resources change their status on RPM, RPM sends out notifications
+and the driver will "up" the semaphore in struct
+msm_rpm_notification.
+
+msm_rpm_unregister_notification():
+The function unregisters a notification.
+
+msm_rpm_init():
+The function initializes the RPM driver with platform specific data.
+
+Driver parameters
+=================
+
+None.
+
+Config options
+==============
+
+MSM_RPM
+
+Dependencies
+============
+
+None.
+
+User space utilities
+====================
+
+None.
+
+Other
+=====
+
+None.
+
+Known issues
+============
+
+None.
+
+To do
+=====
+
+None.
diff --git a/Documentation/arm/msm/tsif.txt b/Documentation/arm/msm/tsif.txt
new file mode 100644
index 00000000000..9f6827c38b5
--- /dev/null
+++ b/Documentation/arm/msm/tsif.txt
@@ -0,0 +1,231 @@
+TSIF driver serves piece of hardware found in Qualcomm MSM's.
+It deals with Digital Mobile Broadcast.
+
+If you are dealing with Qualcomm MSM that have relevant piece of hardware,
+read on.
+
+There are various Digital Mobile Broadcast (DMB) systems developed to receive
+audio and/or television broadcast programs by Mobile Station Modem (MSM).
+(in simplified words - cellular phone)
+
+All of these systems have similar architecture. They use radio link which
+is different from primary handset link and hence use the additional antenna.
+RF signal from the broadcast tuner goes to de-modulator.
+Regardless of actual tuner and de-modulator, all systems present
+ITU-T H.222.0 (also known as MPEG2) Transport Stream (HTS)
+to the Mobile Station Modem (MSM).
+
+TSIF stands for Transport Stream Interface;
+this is hardware block in MSM that receives HTS signal from the de-modulator.
+
+TSIF use serial interface with de-modulator;
+it buffers data received in internal registers.
+TSIF support data copying from its internal registers to the RAM
+with the Data Mover (DM).
+
+TSIF driver prevent MSM from sleeping while TSIF hardware is active.
+To achieve this, driver holds wake lock.
+
+For access to TSIF data, TSIF driver provides kernel API
+that may be used by another kernel module. As example for API usage,
+simple TSIF chardev adapter provided. It provides character device
+/dev/tsif0. This device may be opened by single process at a time.
+When read, it provides TS stream.
+
+Quick start:
+
+### copy modules to the target
+adb push msm_tsif.ko /data/local/tmp/
+adb push tsif_chrdev.ko /data/local/tmp/
+### Load modules on the target:
+adb shell mount -t debugfs debugfs /sys/kernel/debug
+adb shell insmod /data/local/tmp/msm_tsif.ko
+adb shell insmod /data/local/tmp/tsif_chrdev.ko
+### Run capture:
+adb shell cat /dev/tsif0 > /data/local/tmp/tsif.dump
+
+
+# tests:
+adb shell mount -t debugfs debugfs /sys/kernel/debug
+adb shell rmmod tsif_chrdev
+adb shell rmmod msm_tsif
+adb shell insmod /data/local/tmp/msm_tsif.ko
+adb shell insmod /data/local/tmp/tsif_chrdev.ko
+adb shell 'echo 60 > /sys/devices/platform/msm_tsif.0/time_limit'
+adb shell 'echo "16 * 8" > /sys/devices/platform/msm_tsif.0/buf_config'
+
+# separate xterm:
+watch adb shell cat /sys/devices/platform/msm_tsif.0/stats
+# separate xterm:
+watch adb shell cat /sys/kernel/debug/msm_tsif.0/dma
+# separate xterm:
+adb shell dd if=/dev/tsif0 of=/dev/null
+
+Mode of operation
+
+TSIF hardware have 2 modes of operation: mode1 and mode 2.
+They differ in serial interface signals. Mode used should match demodulator
+chip interface.
+
+In addition to these 2 modes of operation, TSIF driver have pseudo-mode 3
+that means "debug mode" where all operation controlled through debug interfaces.
+Client configure TSIF mode of operation using tsif_set_mode().
+Alternatively, mode of operation may be configured using device attribute file:
+echo 1 > /sys/devices/platform/msm_tsif.0/mode
+
+Time limit
+
+TSIF driver maintains time limit value. Its value corresponds
+to the TSIF_TIME_LIMIT register in TSIF hardware.
+Value in ticks of tsif_ref_clk. If time between the end of previous
+packet and end of current one exceeds this value, timeout status reported
+for the current TSIF packet.
+Client configure TSIF time limit using tsif_set_time_limit().
+Alternatively, time limit may be configured using device attribute file:
+echo 100 > /sys/devices/platform/msm_tsif.0/time_limit
+
+TSIF packet format
+
+TSIF driver uses 192 byte packets; where first 188 packets is HTS packet;
+last 4 bytes consists of :
+3 bytes TTS in bytes 188..190; and status byte ib byte 191.
+
+Status byte contains the following fields:
+Bit Name Comment
+0 Valid Always set to 1 to indicate valid HTS packet and status.
+ If set to 0, this packet is not valid and should be ignored
+1 First packet When set, indicates 1-st packet of a new stream or
+ 1-st valid packet after one or more packets were lost.
+2 Overflow When set, indicates overflow condition in TSIF hardware;
+ one or more packets were lost. Current packet is valid.
+3 Error Indicates the tsif_error signal status
+4 Null Indicates the tsif_null signal status
+5 Reserved Don't care
+6 Timeout Indicates the 1-st packet after timeout.
+ First packet flag will also be set.
+
+Debug facilities
+
+TSIF driver provides extensive debugging facilities to assist debug both
+TSIF input and TSIF client interfaces. 2 mechanisms used:
+
+Device attribute, accessible through usual /sys hierarchy under
+/sys/devices/platform/msm_tsif.0, provides status and statistics information.
+
+Debugfs exposes more hardware and software details. In order to use debugfs,
+one need to mount it:
+
+adb shell mount -t debugfs debugfs /sys/kernel/debug
+
+When debugfs mounted, TSIF entries may be found under
+/sys/kernel/debug/msm_tsif.0
+
+Register access
+
+All TSIF hardware registers accessible through debugfs.
+$ adb shell ls -l /sys/kernel/debug/msm_tsif.0
+-r--r--r-- root root 0 1980-01-07 16:15 dma
+--w------- root root 0 1980-01-07 16:15 action
+-r--r--r-- root root 0 1980-01-07 16:15 gpios
+-r-------- root root 0 1980-01-07 16:15 data_port
+-r--r--r-- root root 0 1980-01-07 16:15 test_current
+-rw-r--r-- root root 0 1980-01-07 16:15 test_export
+--w------- root root 0 1980-01-07 16:15 test_reset
+-rw-r--r-- root root 0 1980-01-07 16:15 test_mode
+-rw-r--r-- root root 0 1980-01-07 16:15 test_ctl
+-rw-r--r-- root root 0 1980-01-07 16:15 lpbk_data
+-rw-r--r-- root root 0 1980-01-07 16:15 lpbk_flags
+-rw-r--r-- root root 0 1980-01-07 16:15 clk_ref
+-rw-r--r-- root root 0 1980-01-07 16:15 time_limit
+-rw-r--r-- root root 0 1980-01-07 16:15 sts_ctl
+
+TSIF clocks are off when TSIF is not running.
+To control TSIF through low level register access, it should be set to the
+mode 3 ("debug"); in addition, TSIF start/stop actions may be executed using
+debugfs action file:
+
+adb shell 'echo open > /sys/kernel/debug/msm_tsif.0/action'
+
+Possible actions are "open" and "close".
+
+DMA activity
+
+DMA activity may be queried using debugfs dma file:
+
+$ adb shell cat /sys/kernel/debug/msm_tsif.0/dma
+ri 16 | wi 24 | dmwi 40 | [ 24]{ 32} [ 32]{ 40}
+
+This file provides ri/wi/dmwi indexes
+(dmwi is for Data Mover write index - index for first location where
+next DMA may be scheduled);
+and 2 Data Mover transfer tasks, each in [wi] {next_wi} format.
+Here, wi is index DMA is scheduled for; next_wi is where driver's
+wi will be set after DMA completion.
+
+Driver status
+
+Driver status available through stats device attribute:
+
+$ adb shell cat /sys/devices/platform/msm_tsif.0/stats
+Device msm_tsif.0
+Mode = 1
+Time limit = 60
+State running
+Client = bf036f68
+Pkt/Buf = 64
+Pkt/chunk = 8
+--statistics--
+Rx chunks = 3288898
+Overflow = 4606
+Lost sync = 0
+Timeout = 1
+DMA error = 0
+Soft drop = 0
+IFI = 48
+--debug--
+GLBL_CLK_ENA = 0x637dfe23
+ROW_RESET = 0x000008c1
+CLK_HALT_STATEB = 0xde6d80ff
+TV_NS_REG = 0xf8e00b44
+TSIF_NS_REG = 0x00000b40
+
+GPIO
+
+Current GPIO values may be read using debugfs gpio file:
+$ adb shell cat /sys/kernel/debug/msm_tsif.0/gpios
+ tsif_clk: 0
+ tsif_en: 0
+ tsif_data: 0
+ tsif_sync: 0
+
+In normal regime, signals changed too fast for this facility to provide
+change by change log; it should be seen as random time capture.
+When debugging TSIF input connectivity, it may be helpful to run
+
+watch -d adb shell cat /sys/kernel/debug/msm_tsif.0/gpios
+
+to see if input ever changes. If nothing changes at all; it is indication
+for mis-configured input.
+
+Another tip: in case of wire connection between components, one may connect
+TSIF input pin to logical 1 instead of actual signal source,
+to verify this is the pin required.
+
+Inter frame interval
+
+To estimate incoming bit rate, TSIF driver measure average time interval
+between packets. Interval measured in tsif_ref_clk ticks. Actually, TSIF
+gets TTS from 1-st and last packets in chunk and use this time to calculate
+inter frame interval.
+Inter frame interval available as part of device statistics.
+
+Tip: to measure tsif_ref_clk frequency, this approach may be used:
+
+adb shell cat /sys/kernel/debug/msm_tsif.0/clk_ref; sleep 10; adb shell cat /sys/kernel/debug/msm_tsif.0/clk_ref
+0x8db70ec8
+0x8dc6974b
+
+Then, calculate (0x8dc6974b - 0x8db70ec8)/10 that is 101798.7 Hz
+
+
+
diff --git a/Documentation/crypto/msm/qce.txt b/Documentation/crypto/msm/qce.txt
new file mode 100644
index 00000000000..18435d170e1
--- /dev/null
+++ b/Documentation/crypto/msm/qce.txt
@@ -0,0 +1,228 @@
+Introduction:
+=============
+
+The Qualcomm crypto engine (qce) driver is a module that
+provides common services for accessing the Qualcomm crypto device.
+Currently, the two main clients of qce are
+-qcrypto driver (module provided for accessing CE HW by kernel space apps)
+-qcedev driver (module provided for accessing CE HW by user space apps)
+
+
+The crypto engine (qce) driver is a client to the DMA driver for the Qualcomm
+DMA device - Application Data Mover (ADM). ADM is used to provide the DMA
+transfer capability between Qualcomm crypto device hardware and DDR memory
+for crypto operations.
+
+ Figure 1.
+ ---------
+
+ Linux kernel
+ (ex:IPSec)<--*Qualcomm crypto driver----+
+ (qcrypto) |
+ (for kernel space app) |
+ |
+ +-->|
+ |
+ | *qce <----> Qualcomm
+ | driver ADM driver <---> ADM HW
+ +-->| | |
+ | | |
+ | | |
+ | | |
+ Linux kernel | | |
+ misc device <--- *QCEDEV Driver-------+ | |
+ interface (qcedev) (Reg interface) (DMA interface)
+ (for user space app) \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ Qualcomm crypto CE3 HW
+
+
+ The entities marked with (*) in the Figure 1, are the software components of
+ the Linux Qualcomm crypto modules.
+
+===============
+IMPORTANT NOTE:
+===============
+(1) The CE hardware can be accessed either from user space OR kernel space,
+ at one time. Both user space and kernel space clients cannot access the
+ qce driver (and the CE hardware) at the same time.
+ - If your device has user space apps that needs to access the crypto
+ hardware, make sure to have the qcrypto module disabled/unloaded.
+ This will result in the kernel space apps to use the registered
+ software implementation of the crypto algorithms.
+ - If your device has kernel space apps that needs to access the
+ crypto hardware, make sure to have qcedev module disabled/unloaded
+ and implement your user space application to use the software
+ implemenation (ex: openssl/crypto) of the crypto algorithms.
+
+(2) If your device has Playready(Windows Media DRM) application enabled and
+ uses the qcedev module to access the crypto hardware accelarator,
+ please be informed that for performance reasons, the CE hardware will need
+ to be dedicated to playready application. Any other user space application
+ should be implemented to use the software implemenation (ex: openssl/crypto)
+ of the crypto algorithms.
+
+
+Hardware description:
+=====================
+
+Qualcomm Crypto HW device family provides a series of algorithms implemented
+in the device hardware.
+
+Crypto 2 hardware provides hashing - SHA-1, SHA-256, ciphering - DES, 3DES, AES
+algorithms, and concurrent operations of hashing, and ciphering.
+
+In addition to those functions provided by Crypto 2 HW, Crypto 3 HW provides
+fast AES algorithms.
+
+In addition to those functions provided by Crypto 3 HW, Crypto 3E provides
+HMAC-SHA1 hashing algorithm, and Over The Air (OTA) f8/f9 algorithms as
+defined by the 3GPP forum.
+
+
+Software description
+====================
+
+The crypto device is defined as a platform device. The driver is
+independent of the platform. The driver supports multiple instances of
+crypto HW.
+All the platform specific parameters are defined in the board init
+file, eg. arch/arm/mach-msm/board-msm7x30.c for MSM7x30.
+
+The qce driver provide the common services of HW crypto
+access to the two drivers as listed above (qcedev, qcrypto. It sets up
+the crypto HW device for the operation, then it requests ADM driver for
+the DMA of the crypto operation.
+
+Two ADM channels and two command lists (one command list for each
+channel) are involved in an operation.
+
+The setting up of the command lists and the procedure of the operation
+of the crypto device are described in the following sections.
+
+The command list for the first DMA channel is set up as follows:
+
+ 1st command of the list is for the DMA transfer from DDR memory to the
+ crypto device to input data to crypto device. The dst crci of the command
+ is set for crci-in for this crypto device.
+
+ 2nd command is for the DMA tansfer is from crypto device to DDR memory for
+ the authentication result. The src crci is set as crci-hash-done of the
+ crypto device. If authentication is not required in the operation,
+ the 2nd command is not used.
+
+The command list for the second DMA channel is set up as follows:
+
+ One command to DMA data from crypto device to DDR memory for encryption or
+ decryption output from crypto device.
+
+To accomplish ciphering and authentication concurrent operations, the driver
+performs the following steps:
+ (a). set up HW crypto device
+ (b). hit the crypto go register.
+ (c). issue the DMA command of first channel to the ADM driver,
+ (d). issue the DMA command of 2nd channel to the ADM driver.
+
+SHA1/SHA256 is an authentication/integrity hash algorithm. To accomplish
+hash operation (or any authentication only algorithm), 2nd DMA channel is
+not required. Only steps (a) to (c) are performed.
+
+At the completion of the DMA operation (for (c) and (d)) ADM driver
+invokes the callback registered to the DMA driver. This signifies the end of
+the DMA operation(s). The driver reads the status and other information from
+the CE hardware register and then invokes the callback to the qce driver client.
+This signal the completion and the results of the DMA along with the status of
+the CE hardware to the qce driver client. This completes a crypto operation.
+
+In the qce driver initialization, memory for the two command lists, descriptor
+lists for each crypto device are allocated out of coherent memory, using Linux
+DMA API. The driver pre-configures most of the two ADM command lists
+in the initialization. During each crypto operation, minimal set up is required.
+src_dscr or/and dst_dscr descriptor list of the ADM command are populated
+from the information obtained from the corresponding data structure. eg: for
+AEAD request, the following data structure provides the information:
+
+ struct aead_request *req
+ ......
+ req->assoc
+ req->src
+ req->dst
+
+The DMA address of a scatter list will be retrieved and set up in the
+descriptor list of an ADM command.
+
+Power Management
+================
+ none
+
+
+Interface:
+==========
+
+The interface is defined in kernel/drivers/crypto/msm/inc/qce.h
+
+The clients qcrypto, qcedev drivers are the clients using
+the interfaces.
+
+The following services are provided by the qce driver -
+
+ qce_open(), qce_close(), qce_ablk_cipher_req(),
+ qce_hw_support(), qce_process_sha_req()
+
+ qce_open() is the first request from the client, ex. Qualcomm crypto
+ driver (qcedev, qcrypto), to open a crypto engine. It is normally
+ called at the probe function of the client for a device. During the
+ probe,
+ - ADM command list structure will be set up
+ - Crypto device will be initialized.
+ - Resource associated with the crypto engine is retrieved by doing
+ platform_get_resource() or platform_get_resource_byname().
+
+ The resources for a device are
+ - crci-in, crci-out, crci-hash-done
+ - two DMA channel IDs, one for encryption and decryption input, one for
+ output.
+ - base address of the HW crypto device.
+
+ qce_close() is the last request from the client. Normally, it is
+ called from the remove function of the client.
+
+ qce_hw_support() allows the client to query what is supported
+ by the crypto engine hardware.
+
+ qce_ablk_cipher_req() provides ciphering service to the client.
+ qce_process_sha_req() provide hashing service to the client.
+ qce_aead_req() provide aead service to the client.
+
+Module parameters:
+==================
+
+The following module parameters are defined in the board init file.
+-CE hardware nase register address
+-Data mover channel used for transfer to/from CE hardware
+These parameters differ in each platform.
+
+
+Dependencies:
+=============
+
+Existing DMA driver.
+The transfers are DMA'ed between the crypto hardware and DDR memory via the
+data mover, ADM. The data transfers are set up to use the existing dma driver.
+
+User space utilities:
+=====================
+ n/a
+
+Known issues:
+=============
+ n/a
+
+To do:
+======
+ n/a
diff --git a/Documentation/crypto/msm/qce40.txt b/Documentation/crypto/msm/qce40.txt
new file mode 100644
index 00000000000..e99f7d7ef6c
--- /dev/null
+++ b/Documentation/crypto/msm/qce40.txt
@@ -0,0 +1,241 @@
+Introduction:
+=============
+
+The Qualcomm crypto engine (qce40) driver is a module that
+provides common services for accessing the Qualcomm crypto device.
+Currently, the two main clients of qce40 are
+-qcrypto driver (module provided for accessing CE HW by kernel space apps)
+-qcedev driver (module provided for accessing CE HW by user space apps)
+This module provides the same interface to the clients as does qce.c and is
+based off qce.c. Following are the updates from qce.c
+- Add support for AES XTS mode
+- Add support for CMAC mode
+- Add support for AES CCM mode
+- Add support for SHA1/SHA256 HMAC
+- Read HASH/MAC information directly from CE hardware registers instead of
+ using datamover.
+
+The crypto engine (qce40) module is a client to the DMA driver for the Qualcomm
+DMA device - Application Data Mover (ADM). ADM is used to provide the DMA
+transfer capability between Qualcomm crypto device hardware and DDR memory
+for crypto operations.
+
+ Figure 1.
+ ---------
+
+ Linux kernel
+ (ex:IPSec)<--*Qualcomm crypto driver----+
+ (qcrypto) |
+ (for kernel space app) |
+ |
+ +-->|
+ |
+ | *qce40 <----> Qualcomm
+ | driver ADM driver <---> ADM HW
+ +-->| | |
+ | | |
+ | | |
+ | | |
+ Linux kernel | | |
+ misc device <--- *QCEDEV Driver-------+ | |
+ interface (qcedev) (Reg interface) (DMA interface)
+ (for user space app) \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ \ /
+ Qualcomm crypto CE3 HW
+
+
+ The entities marked with (*) in the Figure 1, are the software components of
+ the Linux Qualcomm crypto modules.
+
+===============
+IMPORTANT NOTE:
+===============
+(1) The CE hardware can be accessed either from user space OR kernel space,
+ at one time. Both user space and kernel space clients cannot access the
+ qce driver (and the CE hardware) at the same time.
+ - If your device has user space apps that needs to access the crypto
+ hardware, make sure to have the qcrypto module disabled/unloaded.
+ This will result in the kernel space apps to use the registered
+ software implementation of the crypto algorithms.
+ - If your device has kernel space apps that needs to access the
+ crypto hardware, make sure to have qcedev module disabled/unloaded
+ and implement your user space application to use the software
+ implemenation (ex: openssl/crypto) of the crypto algorithms.
+
+(2) If your device has Playready(Windows Media DRM) application enabled and
+ uses the qcedev module to access the crypto hardware accelarator,
+ please be informed that for performance reasons, the CE hardware will need
+ to be dedicated to playready application. Any other user space application
+ should be implemented to use the software implemenation (ex: openssl/crypto)
+ of the crypto algorithms.
+
+
+Hardware description:
+=====================
+
+Qualcomm Crypto HW device family provides a series of algorithms implemented
+in the device hardware.
+
+Crypto 2 hardware provides hashing - SHA-1, SHA-256, ciphering - DES, 3DES, AES
+algorithms, and concurrent operations of hashing and ciphering.
+
+In addition to those functions provided by Crypto 2 HW, Crypto 3 HW provides
+fast AES algorithms.
+
+In addition to those functions provided by Crypto 3 HW, Crypto 3E provides
+HMAC-SHA1 hashing algorithm, and Over The Air (OTA) f8/f9 algorithms as
+defined by the 3GPP forum.
+
+
+Software description
+====================
+
+The crypto device is defined as a platform device. The driver is
+independent of the platform. The driver supports multiple instances of
+crypto HW.
+All the platform specific parameters are defined in the board init
+file, eg. arch/arm/mach-msm/board-msm8960.c for MSM8960.
+
+The qce40 driver provide the common services of HW crypto
+access to the two drivers as listed above (qcedev, qcrypto. It sets up
+the crypto HW device for the operation, then it requests ADM driver for
+the DMA of the crypto operation.
+
+Two ADM channels and two command lists (one command list for each
+channel) are involved in an operation.
+
+The setting up of the command lists and the procedure of the operation
+of the crypto device are described in the following sections.
+
+The command lists contains a single command. For the first DMA channel it
+is set up as follows:
+
+ The command is for the DMA transfer from DDR memory to the
+ crypto device to input data to crypto device. The dst crci of the command
+ is set for crci-in for this crypto device.
+
+The command list for the second DMA channel is set up as follows:
+
+ One command to DMA data from crypto device to DDR memory for encryption or
+ decryption output from crypto device.
+
+To accomplish ciphering and authentication concurrent operations, the driver
+performs the following steps:
+ (a). set up HW crypto device
+ (b). hit the crypto go register.
+ (c). issue the DMA command of first channel to the ADM driver,
+ (d). issue the DMA command of 2nd channel to the ADM driver.
+
+SHA1/SHA256 is an authentication/integrity hash algorithm. To accomplish
+hash operation (or any authentication only algorithm), 2nd DMA channel is
+not required. Only steps (a) to (c) are performed.
+
+At the completion of the DMA operation (for (c) and (d)) ADM driver
+invokes the callback registered to the DMA driver. This signifies the end of
+the DMA operation(s). The driver reads the status and other information from
+the CE hardware register. For HASH functions (SHA1/SHA256, HMAC, CMAC and
+CCM) were the MAC/HASH information is read off hardware registers.
+
+[ NOTE: This is different from what is done in the qce module that support
+CE3.x hardware. In CE4.0 there is not CRCI_HASH and hence we cannot rely
+on the data mover to populate the HMAC/SHA information. This information
+is acquired fromte h ahrdware by reading directly from some registers that
+hold this information ]
+
+The driver than nvokes the callback to the qce driver client.
+This signal the completion and the results of the DMA along with the status of
+the CE hardware to the qce40 driver client. This completes a crypto operation.
+
+In the qce40 driver initialization, memory for the two command lists, descriptor
+lists for each crypto device are allocated out of coherent memory, using Linux
+DMA API. The driver pre-configures most of the two ADM command lists
+in the initialization. During each crypto operation, minimal set up is required.
+src_dscr or/and dst_dscr descriptor list of the ADM command are populated
+from the information obtained from the corresponding data structure. eg: for
+AEAD request, the following data structure provides the information:
+
+ struct aead_request *req
+ ......
+ req->assoc
+ req->src
+ req->dst
+
+The DMA address of a scatter list will be retrieved and set up in the
+descriptor list of an ADM command.
+
+Power Management
+================
+ none
+
+
+Interface:
+==========
+
+The interface is defined in kernel/drivers/crypto/msm/inc/qce.h
+
+The clients qcrypto, qcedev drivers are the clients using
+the interfaces.
+
+The following services are provided by the qce driver -
+
+ qce_open(), qce_close(), qce_ablk_cipher_req(),
+ qce_hw_support(), qce_process_sha_req()
+
+ qce_open() is the first request from the client, ex. Qualcomm crypto
+ driver (qcedev, qcrypto), to open a crypto engine. It is normally
+ called at the probe function of the client for a device. During the
+ probe,
+ - ADM command list structure will be set up
+ - Crypto device will be initialized.
+ - Resource associated with the crypto engine is retrieved by doing
+ platform_get_resource() or platform_get_resource_byname().
+
+ The resources for a device are
+ - crci-in, crci-out, crci-hash-done
+ - two DMA channel IDs, one for encryption and decryption input, one for
+ output.
+ - base address of the HW crypto device.
+
+ qce_close() is the last request from the client. Normally, it is
+ called from the remove function of the client.
+
+ qce_hw_support() allows the client to query what is supported
+ by the crypto engine hardware.
+
+ qce_ablk_cipher_req() provides ciphering service to the client.
+ qce_process_sha_req() provides hashing service to the client.
+ qce_aead_req() provides aead service to the client.
+
+
+Module parameters:
+==================
+
+The following module parameters are defined in the board init file.
+-CE hardware base register address
+-Data mover channel used for transfer to/from CE hardware
+These parameters differ in each platform.
+
+
+Dependencies:
+=============
+
+Existing DMA driver.
+The transfers are DMA'ed between the crypto hardware and DDR memory via the
+data mover, ADM. The data transfers are set up to use the existing dma driver.
+
+User space utilities:
+=====================
+ n/a
+
+Known issues:
+=============
+ n/a
+
+To do:
+======
+ n/a
diff --git a/Documentation/crypto/msm/qcedev.txt b/Documentation/crypto/msm/qcedev.txt
new file mode 100644
index 00000000000..fde69bbed7c
--- /dev/null
+++ b/Documentation/crypto/msm/qcedev.txt
@@ -0,0 +1,232 @@
+Introduction:
+=============
+
+This driver provides IOCTLS for user space application to access crypto
+engine hardware for the qcedev crypto services. The driver supports the
+following crypto algorithms
+- AES-128, AES-256 (ECB, CBC and CTR mode)
+- AES-192, (ECB, CBC and CTR mode)
+ (support exists on platform supporting CE 3.x hardware)
+- SHA1/SHA256
+- AES-128, AES-256 (XTS), AES CMAC, SHA1/SHA256 HMAC
+ (support exists on platform supporting CE 4.x hardware)
+
+Hardware description:
+=====================
+Crypto 3E provides cipher and hash algorithms as defined in the
+3GPP forum specifications.
+
+
+Software description
+====================
+
+The driver is a Linux platform device driver. For an msm target,
+there can be multiple crypto devices assigned for QCEDEV.
+
+The driver is a misc device driver as well.
+The following operations are registered in the driver,
+-qcedev_ioctl()
+-qcedev_open()
+-qcedev_release()
+
+The following IOCTLS are available to the user space application(s)-
+
+ Cipher IOCTLs:
+ --------------
+ QCEDEV_IOCTL_ENC_REQ is for encrypting data.
+ QCEDEV_IOCTL_DEC_REQ is for decrypting data.
+
+ Hashing/HMAC IOCTLs
+ -------------------
+
+ QCEDEV_IOCTL_SHA_INIT_REQ is for initializing a hash/hmac request.
+ QCEDEV_IOCTL_SHA_UPDATE_REQ is for updating hash/hmac.
+ QCEDEV_IOCTL_SHA_FINAL_REQ is for ending the hash/mac request.
+ QCEDEV_IOCTL_GET_SHA_REQ is for retrieving the hash/hmac for data
+ packet of known size.
+ QCEDEV_IOCTL_GET_CMAC_REQ is for retrieving the MAC (using AES CMAC
+ algorithm) for data packet of known size.
+
+The requests are synchronous. The driver will put the process to
+sleep, waiting for the completion of the requests using wait_for_completion().
+
+Since the requests are coming out of user space application, before giving
+the requests to the low level qce driver, the ioctl requests and the
+associated input/output buffer will have to be safe checked, and copied
+to/from kernel space.
+
+The extra copying of requests/buffer can affect the performance. The issue
+with copying the data buffer is resolved by having the client use PMEM
+allocated buffers.
+
+NOTE: Using memory allocated via PMEM is supported only for in place
+ operations where source and destination buffers point to the same
+ location. Support for different source and destination buffers
+ is not supported currently.
+ Furthermore, when using PMEM, and in AES CTR mode, when issuing an
+ encryption or decryption request, a non-zero byteoffset is not
+ supported.
+
+The design of the driver is to allow multiple open, and multiple requests
+to be issued from application(s). Therefore, the driver will internally queue
+the requests, and serialize the requests to the low level qce (or qce40) driver.
+
+On an IOCTL request from an application, if there is no outstanding
+request, a the driver will issue a "qce" request, otherwise,
+the request is queued in the driver queue. The process is suspended
+waiting for completion.
+
+On completion of a request by the low level qce driver, the internal
+tasklet (done_tasklet) is scheduled. The sole purpose of done_tasklet is
+to call the completion of the current active request (complete()), and
+issue more requests to the qce, if any.
+When the process wakes up from wait_for_completion(), it will collect the
+return code, and return the ioctl.
+
+A spin lock is used to protect the critical section of internal queue to
+be accessed from multiple tasks, SMP, and completion callback
+from qce.
+
+The driver maintains a set of statistics using debug fs. The files are
+in /debug/qcedev/stats1, /debug/qcedev/stats2, /debug/qcedev/stats3;
+one for each instance of device. Reading the file associated with
+a device will retrieve the driver statistics for that device.
+Any write to the file will clear the statistics.
+
+
+Power Management
+================
+n/a
+
+
+Interface:
+==========
+
+Linux user space applications will need to open a handle
+(file desrciptor) to the qcedev device. This is achieved by doing
+the following to retrieve a file desrciptor to the device.
+
+ fd = open("/dev/qce", O_RDWR);
+ ..
+ ioctl(fd, ...);
+
+Once a valid fd is retrieved, user can call the following ioctls with
+the fd as the first parameter and a pointer to an appropriate data
+structure, qcedev_cipher_op_req or qcedev_sha_op_req (depending on
+cipher/hash functionality) as the second parameter.
+
+The following IOCTLS are available to the user space application(s)-
+
+ Cipher IOCTLs:
+ --------------
+ QCEDEV_IOCTL_ENC_REQ is for encrypting data.
+ QCEDEV_IOCTL_DEC_REQ is for decrypting data.
+
+ The caller of the IOCTL passes a pointer to the structure shown
+ below, as the second parameter.
+
+ struct qcedev_cipher_op_req {
+ int use_pmem;
+ union{
+ struct qcedev_pmem_info pmem;
+ struct qcedev_vbuf_info vbuf;
+ };
+ uint32_t entries;
+ uint32_t data_len;
+ uint8_t in_place_op;
+ uint8_t enckey[QCEDEV_MAX_KEY_SIZE];
+ uint32_t encklen;
+ uint8_t iv[QCEDEV_MAX_IV_SIZE];
+ uint32_t ivlen;
+ uint32_t byteoffset;
+ enum qcedev_cipher_alg_enum alg;
+ enum qcedev_cipher_mode_enum mode;
+ enum qcedev_oper_enum op;
+ };
+
+ Hashing/HMAC IOCTLs
+ -------------------
+
+ QCEDEV_IOCTL_SHA_INIT_REQ is for initializing a hash/hmac request.
+ QCEDEV_IOCTL_SHA_UPDATE_REQ is for updating hash/hmac.
+ QCEDEV_IOCTL_SHA_FINAL_REQ is for ending the hash/mac request.
+ QCEDEV_IOCTL_GET_SHA_REQ is for retrieving the hash/hmac for data
+ packet of known size.
+ QCEDEV_IOCTL_GET_CMAC_REQ is for retrieving the MAC (using AES CMAC
+ algorithm) for data packet of known size.
+
+ The caller of the IOCTL passes a pointer to the structure shown
+ below, as the second parameter.
+
+ struct qcedev_sha_op_req {
+ struct buf_info data[QCEDEV_MAX_BUFFERS];
+ uint32_t entries;
+ uint32_t data_len;
+ uint8_t digest[QCEDEV_MAX_SHA_DIGEST];
+ uint32_t diglen;
+ uint8_t *authkey;
+ uint32_t authklen;
+ enum qcedev_sha_alg_enum alg;
+ struct qcedev_sha_ctxt ctxt;
+ };
+
+The IOCTLs and associated request data structures are defined in
+ kernel/drivers/crypto/msm/inc/qcedev.h..
+
+
+Module parameters:
+==================
+
+The following module parameters are defined in the board init file.
+-CE hardware nase register address
+-Data mover channel used for transfer to/from CE hardware
+These parameters differ in each platform.
+
+
+
+Dependencies:
+=============
+qce driver. Please see Documentation/arm/msm/qce.txt.
+
+
+User space utilities:
+=====================
+
+none
+
+Known issues:
+=============
+
+none.
+
+
+To do:
+======
+ Enhance Cipher functionality:
+ (1) Add support for handling > 32KB for ciphering functionality when
+ - operation is not an "in place" operation (source != destination).
+ (when using PMEM allocated memory)
+
+Limitations:
+============
+ (1) In case of cipher functionality, Driver does not support
+ a combination of different memory sources for source/destination.
+ In other words, memory pointed to by src and dst,
+ must BOTH (src/dst) be "pmem" or BOTH(src/dst) be "vbuf".
+
+ (2) In case of hash functionality, driver does not support handling data
+ buffers allocated via PMEM.
+
+ (3) Do not load this driver if your device already has kernel space apps
+ that need to access the crypto hardware.
+ Make sure to have qcedev module disabled/unloaded and implement your user
+ space application to use the software implemenation (ex: openssl/crypto)
+ of the crypto algorithms.
+ (NOTE: Please refer to details on the limitations listed in qce.txt)
+
+ (4) If your device has Playready (Windows Media DRM) application enabled
+ and uses the qcedev module to access the crypto hardware accelarator,
+ please be informed that for performance reasons, the CE hardware will
+ need to be dedicated to playready application. Any other user space
+ application should be implemented to use the software implemenation
+ (ex: openssl/crypto) of the crypto algorithms.
diff --git a/Documentation/crypto/msm/qcrypto.txt b/Documentation/crypto/msm/qcrypto.txt
new file mode 100644
index 00000000000..81aa1941e15
--- /dev/null
+++ b/Documentation/crypto/msm/qcrypto.txt
@@ -0,0 +1,144 @@
+Introduction:
+=============
+
+Qualcomm Crypto (qcrypto) driver is a Linux crypto driver which interfaces
+with the Linux kernel crypto API layer to provide the HW crypto functions.
+This driver is accessed by kernel space apps via the kernel crypto API layer.
+At present there is no means for user space apps to access this module.
+
+Hardware description:
+=====================
+
+Qualcomm Crypto HW device family provides a series of algorithms implemented
+in the device.
+
+Crypto 2 hardware provides hashing - SHA-1, SHA-256, ciphering - DES, 3DES, AES
+algorithms, and concurrent operations of hashing, and ciphering.
+
+In addition to those functions provided by Crypto 2 HW, Crypto 3 provides fast
+AES algorithms.
+
+In addition to those functions provided by Crypto 3 HW, Crypto 3E provides
+HMAC-SHA1 hashing algorithm.
+
+In addition to those functions provided by Crypto 3 HW, Crypto 4.0 provides
+HMAC-SHA1/SHA256, AES CBC-MAC hashing algorithm and AES XTS/CCM cipher
+algorithms.
+
+
+Software description
+====================
+
+The module init function (_qcrypto_init()), does a platform_register(),
+to register the driver. As the result, the driver probe function,
+_qcrypto_probe(), will be invoked for each registered device.
+
+In the probe function, driver opens the low level CE (qce_open), and
+registers the supported algorithms to the kernel crypto API layer.
+Currently, qcrypto supports the following algorithms.
+
+ ablkcipher -
+ cbc(aes),ecb(aes),ctr(aes)
+ ahash -
+ sha1, sha256
+ aead -
+ authenc(hmac(sha1),cbc(aes))
+
+ The hmac(sha1), hmac(sha256, authenc(hmac(sha1),cbc(aes)), ccm(aes)
+ and xts(aes) algorithms are registered for some platforms that
+ support these in the CE hardware
+
+The HW device can support various algorithms. However, the most important
+algorithms to gain the performance using a HW crypto accelerator are
+AEAD, and ABLKCIPHER.
+
+AEAD stands for "authentication encryption with association data".
+ABLKCIPHER stands of "asynchronous block cipher".
+
+The AEAD structure is described in the following header file
+ LINUX/opensource/kernel/include/crypto/aead.h
+
+The design of the driver is to allow multiple requests
+issued from kernel client SW (eg IPSec).
+Therefore, the driver will have to internally queue the requests, and
+serialize the requests to the low level qce driver.
+
+When a request is received from the client, if there is no outstanding
+request, a qce (or qce40) request is issued, otherwise, the request is
+queued in the driver queue.
+
+On completion of a request, the qce (or qce40) invokes the registered
+callback from the qcrypto. The internal tasklet (done_tasklet) is scheduled
+in this callback function. The sole purpose of done_tasklet is
+to call the completion of the current active request, and
+issue more requests to the qce (or qce40), if any exists.
+
+A spin lock is used to protect the critical section of internal queue to
+be accessed from multiple tasks, SMP, and completion callback
+from qce.
+
+The driver maintains a set of statistics using debug fs. The files are
+in /debug/qcrypto/stats1, /debug/qcrypto/stats2, /debug/qcrypto/stats3;
+one for each instance of device. Reading the file associated with
+a device will retrieve the driver statistics for that device.
+Any write to the file will clear the statistics.
+
+Test vectors for authenc(hmac(sha1),cbc(aes)) algorithm are
+developed offline, and imported to crypto/testmgr.c, and crypto/testmgr.h.
+
+
+Power Management
+================
+ none
+
+
+Interface:
+==========
+The kernel interface is defined in
+ LINUX/opensource/kernel/include/linux/crypto.h.
+
+
+Module parameters:
+==================
+
+All the platform specific parameters are defined in the board init
+file, eg. arch/arm/mach-msm/board-mssm7x30.c for msm7x30.
+
+Dependencies:
+=============
+qce driver.
+
+
+User space utilities:
+=====================
+ n/a
+
+Known issues:
+=============
+ n/a
+
+To do:
+======
+ Add Hashing algorithms.
+
+
+Limitations:
+===============
+(1) Each packet transfer size (for cipher and hash) is limited to maximum of
+ 32KB. This is a limitation in the crypto engine hardware. Client will
+ have to break packets larger than 32KB into multiple requests of smaller
+ size data packets.
+
+(2) Do not load this driver if your device has user space apps that needs to
+ access the crypto hardware. Please make sure to have the qcrypto module
+ disabled/unloaded.
+ Not having the driver loaded, will result in the kernel space apps to use
+ the registered software implementation of the crypto algorithms.
+
+(3) If your device has Playready application enabled and uses the qcedev module
+ to access the crypto hardware accelarator, please be informed that for
+ performance reasons, the CE hardware will need to be dedicated to playready
+ application. Any other user space or kernel application should be implemented
+ to use the software implemenation of the crypto algorithms.
+
+ (NOTE: Please refer to details on the limitations listed in qce/40.txt)
diff --git a/Documentation/csdio.txt b/Documentation/csdio.txt
new file mode 100644
index 00000000000..22d5e35bc0f
--- /dev/null
+++ b/Documentation/csdio.txt
@@ -0,0 +1,189 @@
+Introduction
+============
+The Char SDIO Device Driver is an interface which exposes an SDIO
+card/function from kernel space as a char device in user space.
+
+The driver doesn't interact with any HW directly. It relies on SDIO
+card/function interface provided as a part of Linux kernel.
+
+Hardware description
+====================
+Each SDIO device/card contains an SDIO client HW block.
+The host interacts with the device by sending byte sequences called
+command (CMD). Some commands can be followed by data blocks. The
+device sends back a byte sequence called response (R) and a data
+block if required. CMD3, CMD5 and CMD7 are used to initialize the
+device. CMD52 and CMD53 are used to access the device. Command
+format and properties are defined by SDIO Specification document
+published by SD Association:
+ http://www.sdcard.org/developers/tech/sdio/.
+
+CMD52 and CMD53 can access up to 8 address spaces called Functions.
+Function 0 contains system information predefined by SD/SDIO
+standard and Functions 1-7 are defined by the SDIO device
+manufacturer.
+
+An SDIO device/card can send an interrupt to SDIO host. This
+interrupt is intercepted and handled by SDIO host.
+
+Software description
+====================
+Linux provides a framework for handling SDIO devices. It implements
+kind of plug-and-play model in which the Linux SDIO Host Driver is
+responsible for initializing an SDIO device upon insertion. It also
+reads device/card identification information and enumerates functions
+provided by the device and then looks up in the list of
+preregistered user SDIO drivers for a suitable one.
+
+During its lifecycle the user SDIO driver interacts with the Linux
+SDIO Host Driver in order to send/receive information to/from SDIO
+device/card. The user SDIO driver doesn't work with CMD52/CMD53
+directly. Instead it uses an abstraction provided by the Linux SDIO
+Host Driver.
+
+The Linux SDIO Host Driver is also in charge of handling SDIO
+interrupts. User SDIO driver can register its own callback in SDIO
+Host Driver and get a notification about interrupt event.
+
+The Char SDIO Device Driver follows the design guidelines mentioned
+above. It provides the following functionality:
+
+ - Register itself in the user SDIO drivers list;
+ - Handle Probe event upon insertion of supported card/device;
+ - Creates and maintains a char device driver for each SDIO Function
+ found in the card/device;
+ - Translates read/write/ioctl calls to appropriate SDIO call
+ sequences;
+
+In order to handle general SDIO configuration functionality and
+Function 0 the Char SDIO Device Driver provides additional
+simplified char device driver.
+
+The Manufacturer and Device IDs of handled SDIO device should be
+provided as parameters for kernel module or as configuration
+parameters in case of statically linked driver.
+
+Design
+======
+The main goal of the Char SDIO Device Driver is to expose an SDIO
+card/device from kernel space to user space as a char device driver.
+The driver should be generic and simple as far as possible.
+
+The biggest design tradeoff is maintaining a balance between the
+system call overhead required to initiate an SDIO transaction from
+user space and overall SDIO communication performance. But luckily,
+because of nature of SDIO protocol, this overhead is negligible
+comparing to time required to execute SDIO transaction itself. So,
+each CMD52 (read or write) consists from single ioctl system call.
+And each CMD53 invokes single ioctl system call followed by read or
+write system call.
+
+The Char SDIO Device Driver registers its own class of the devices
+called 'csdio'. This class will serve as a common roof for all SDIO
+devices served by different instances of the Char SDIO Device Driver.
+Additional benefit from maintaining its own class is the driver
+ability to overwrite default permissions of the dev nodes created by
+the driver.
+
+Power Management
+================
+None
+
+SMP/multi-core
+==============
+The driver does not anticipate any issues related to multi-core
+since it is expected to run on one core only.
+
+Security
+========
+None
+
+Performance
+===========
+None
+
+Interface
+=========
+The Char SDIO Device Driver has two char device interfaces:
+ - Control Interface;
+ - Function Interface.
+
+Char SDIO Device Driver Control Interface consists of:
+ - open() - device node is /dev/csdio0;
+ - close()
+ - ioctl() - the following options are available:
+ - CSDIO_IOC_ENABLE_HIGHSPEED_MODE;
+ - CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS;
+ - CSDIO_IOC_ENABLE_ISR;
+ - CSDIO_IOC_DISABLE_ISR.
+
+Char SDIO Device Driver Function Interface consists of:
+ - open() - device node is /dev/csdiofX, where X is Function Id;
+ - close()
+ - read() - send CMD53 read;
+ - write() - send CMD53 write;
+ - ioctl() - the following options are available:
+ - CSDIO_IOC_SET_OP_CODE - 0 fixed adrress, 1 autoincrement.
+ - CSDIO_IOC_FUNCTION_SET_BLOCK_SIZE;
+ - CSDIO_IOC_SET_BLOCK_MODE - 0 byte mode, 1 block mode;
+ - CSDIO_IOC_CMD52 - execute CMD52, receives the
+ following structure as a parameter:
+ struct csdio_cmd52_ctrl_t {
+ uint32_t m_write; // 0 - read, 1 -write
+ uint32_t m_address;
+ uint32_t m_data; // data to write or read data
+ uint32_t m_ret; // command execution status
+ }__attribute__ ((packed));
+ - CSDIO_IOC_CMD53 - setup CMD53 data transfer, receives the
+ following structure as a parameter:
+ struct csdio_cmd53_ctrl_t {
+ uint32_t m_block_mode;
+ uint32_t m_op_code;
+ uint32_t m_address;
+ }__attribute__ ((packed));
+ - CSDIO_IOC_CONNECT_ISR;
+ - CSDIO_IOC_DISCONNECT_ISR;
+ - CSDIO_IOC_GET_VDD;
+ - CSDIO_IOC_SET_VDD.
+
+Additionally, user space application can use fcntl system call with
+parameters F_SETOWN and F_SETFL in order to set an asynchronous
+callback for SDIO interrupt.
+
+Driver parameters
+=================
+If the driver is compiled as a kernel module, the following
+parameters can be used in order to provide Manufacturer and Device IDs
+upon module download:
+ - csdio_vendor_id;
+ - csdio_device_id.
+If the driver is intended to work with specific SDIO host the
+host_name parameter should be added followed by the name of the MMC
+host platform device.
+
+Config options
+==============
+These are the kernel configuration options:
+ - CONFIG_CSDIO_VENDOR_ID;
+ - CONFIG_CSDIO_DEVICE_ID.
+
+Dependencies
+============
+The Char SDIO Device Driver depends on Linux SDIO Host Driver.
+
+User space utilities
+====================
+None
+
+Other
+=====
+None
+
+Known issues
+============
+None
+
+To do
+=====
+Provide mechanism to support a number of SDIO devices simultaneously
+connected to different SDIO hosts.
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index aa47be71df4..729e1466d77 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2349,6 +2349,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
1: Fast pin select (default)
2: ATC IRMode
+ snddev_icodec.msm_codec_i2s_slave_mode= [ARM-MSM]
+ 1, codec is I2S master
+ 0, MSM is I2S master (default)
+
softlockup_panic=
[KNL] Should the soft-lockup detector generate panics.
Format:
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index bfe924217f2..d6114ed8aea 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -1043,9 +1043,15 @@ conf/all/forwarding - BOOLEAN
This referred to as global forwarding.
-proxy_ndp - BOOLEAN
+proxy_ndp - INTEGER
Do proxy ndp.
+ Possible values are:
+ 0 Proxy NDP is disabled
+ 1 Proxy NDP is enabled
+ 2 NDP packets are sent to userspace, where a userspace proxy
+ can be implemented
+
conf/interface/*:
Change special settings per interface.
diff --git a/Documentation/networking/qfec.txt b/Documentation/networking/qfec.txt
new file mode 100644
index 00000000000..182043f6b51
--- /dev/null
+++ b/Documentation/networking/qfec.txt
@@ -0,0 +1,309 @@
+Driver name: Qualcomm FSM9xxx Ethernet Driver
+
+Supported hardware: FSM9xxx Ethernet Controller
+
+Maintainer(s):
+Author(s):
+
+
+Introduction:
+=============
+
+The FSM9xxx Ethernet controller is register based with separate TX and RX DMA
+engines supporting scatter/gather and support 1EEE-1588 timestamping.
+MII, RevMII and RgMII interfaces are support. RgMII support 1G.
+
+The driver supports gather but not scatter, uses the controller DMA engines,
+and timestamping.
+
+
+Hardware description:
+=====================
+
+The Ethernet Controller is a memory mapped register device with two
+internal DMA engines for TX and RX path processing using separate
+buffer-descriptors (BD) allocated from non-cached main memory for the TX
+and RX paths. These BDs support scatter-gather but are only used to
+transfer single max sized Ethernet frames. The BDs are sequentially
+accessed as a ring, with an end-of-ring bit set in the last BD. Ownership
+bits control access by hardware and software to individual BDs.
+
+An additional 4 words of space can be configured and is allocated between
+each BD to store additional information about the sk_buff associated with it.
+The driver software uses 2 ring structures and local functions to manage
+them to keep in sync with the hardware the BDs . The number of BDs is
+determined from the space allocated for them (PAGE_SIZE). The ratio of RX
+to TX BD is set by a #define.
+
+Interrupts are used to service and replenish pre-allocated sk_buff for each
+RX BD. TX frames are allocated to a TX BD and transmitted frames are
+freed within the xmit() invoked to send the frame. No TX interrupts are
+processed since sk_buffs are freed in the xmit().
+
+Three PHY interfaces are supported: MII, RevMII and RgMII. The selected
+interface is determined from the resource structure (to be completed) and
+programmed into a register prior to resetting the Ethernet controller.
+
+Separate PLLs are managed to provide MAC/PHY clocks in RevMii and RgMii
+modes, and a 25mHz clock timestamping.
+
+
+
+Software description
+====================
+
+Structures
+
+struct qfec_buf_desc {
+ uint32_t status;
+ uint32_t ctl;
+ void *p_buf;
+ void *next;
+};
+
+struct buf_desc {
+ struct qfec_buf_desc desc; /* must be first */
+
+ struct sk_buff *skb;
+ void *buf_virt_addr;
+ void *buf_phys_addr;
+ uint32_t last_bd_flag;
+};
+
+struct ring {
+ int head;
+ int tail;
+ int n_free;
+ int len;
+};
+
+struct qfec_priv {
+ struct net_device *net_dev;
+ struct net_device_stats stats; /* req statistics */
+
+ struct device dev;
+
+ spinlock_t hw_lock;
+
+ unsigned int state; /* driver state */
+
+ void *bd_base; /* addr buf-desc */
+ dma_addr_t tbd_dma; /* dma/phy-addr buf-desc */
+ dma_addr_t rbd_dma; /* dma/phy-addr buf-desc */
+
+ struct resource *mac_res;
+ void *mac_base; /* mac (virt) base address */
+
+ struct resource *clk_res;
+ void *clk_base; /* clk (virt) base address */
+
+ unsigned int n_tbd; /* # of TX buf-desc */
+ struct ring ring_tbd; /* TX ring */
+ struct buf_desc *p_tbd; /* # TX buf-desc */
+
+ unsigned int n_rbd; /* # of RX buf-desc */
+ struct ring ring_rbd; /* RX ring */
+ struct buf_desc *p_rbd; /* # RX buf-desc */
+
+ unsigned long cntr[cntr_last]; /* activity counters */
+
+ struct mii_if_info mii;
+
+ int mdio_clk; /* phy mdio clock rate */
+ int phy_id; /* default PHY addr (0) */
+ struct timer_list phy_tmr; /* monitor PHY state */
+};
+
+
+
+Initialization is divided between probe() and open() such that the
+net_device is allocated, the address space is mapped for register access,
+and procfs files created in probe(). BD memory is allocated and
+initialized along with interrupts and timers in open(). BD is not
+de-allocated in close() allowing it to be debugged after the interface is
+ifconfig down'd. This approach is intended to aid with debugging by
+allowing configuring the interface down and up may clear some early usage
+problems
+
+Phy link state changes are monitored using a timer using some existing
+functions from the mii library, but also with local functions intended to
+support RGMII in the future.
+
+A variety of information is accessible through procFs. Counters are used
+to track various driver events, these include abnormal and error
+interrupts. Hardware counters of various frame statistics (e.g. types and
+sizes of TX and RX frames) are available. Hardware registers and up to the
+50 TX and RX BDs can be can be displayed. A table of procfs filenames and
+functions are used to create and delete the procfs entries as needed.
+
+Probe()
+
+Allocate and initialize the net_device structure with resource information
+specifying the Ethernet controller, clock control and MAC address memory
+regions. Set netdev_ops to a statically defined sub-structure supporting
+the device.
+
+Open()
+
+Use qfec_mem_alloc() to allocate space for the buffer-descriptors (BD).
+TX BDs are initialized by clearing the ownership bit of each. Each RX BD
+is initialized using qfec_rbd_init(). Qfec_rbd_init() pre-allocates an
+sk_buff, saving the addresses of both the sk_buff and its data buffer in the
+additional BD space, setting the BD buf pointer to the physical address of
+the sk_buff data, and finally setting the ownership bit.
+
+Once the BDs are initialized, interface selected register is set to the
+appropriate PHY interface configuration, and the Ethernet controller is
+reset and its registers initialized, including the starting addresses of
+the TX and RX BDs.
+
+The PHY monitor state is initialized and the timer initialized and started.
+
+Finally, the interrupt for the Ethernet controller is initialized.
+
+ Note - Interrupts from both from the external PHY and internal RevMii
+ PHY, are available, but neither is used in preference to the
+ timer.
+
+
+Interrupt Processing
+
+Besides recognizing abnormal error interrupts, RX, TX and GMAC interrupts
+are recognized, although TX and GMAC interrupts are ignored but cleared and
+counted. (The gmac interrupt can be ignored but must be disabled).
+
+RX interrupts invoke a handler to process the received frame, send it
+to the stack and re-allocate a replacement sk_bufff for the buffer-
+descriptor.
+
+
+Receive Processing
+
+The RX buffer descriptors are initialized by _open() using qfec_rbd_init()
+which pre-allocated an sk_buff, saving its address and the physical address
+of its data in the additional BD space, as well as writing the physical
+address to the BD pbuf entry read by HW. The size of the buffer and
+other control information are written to the BD, as well as setting the
+ownership bit.
+
+A received frame generates an interrupt invoking qfec_rx_int(). It
+repeatedly checks the ownership the next available BD, and passing the
+sk_buff containing the received frame to the stack via netif_rx().
+
+Once all received frames are processed, it repeatedly calls qfec_rbd_init()
+to allocate a new sk_buff with each available BD.
+
+
+Transmit Processing
+
+Frames are transmitted through the start_xmit callback function.
+qfec_tx_replenish() is immediately called to free sk_buffs from BD
+that have been transmitted, before checking is a BD is available.
+The sk_buff address is stored in the additional BD space and the
+physical address of its data is store in the pbuf BD entry used
+by the HW. The TX poll-demand register is accessed, causing the
+HW to recheck the current BD and process it.
+
+While the TX interrupt could be processed to free sk_buffs as BD
+are processed, they are ignored since the sk_buffs will be freed
+with each call to _xmit().
+
+procfs
+
+debug files are available to display the controller registers,
+frame counters from the controller, driver activity counters, and
+the first 50 entries of the RX and TX buffer descriptors.
+
+
+Callbacks
+
+In addition to the functions described above, the following functions
+are used to support their correspondingly named device operations:
+
+ qfec_stop
+ qfec_do_ioctl
+ qfec_tx_timeout
+ qfec_set_mac_address
+ qfec_get_stats
+ qfec_set_config
+
+ eth_change_mtu
+ eth_validate_addr
+
+
+Power Management
+================
+None
+
+
+Interface:
+==========
+
+- Module-init/exit
+- standard network interface functions
+
+
+Module parameters:
+==================
+
+static struct resource qfec_resources [] = {
+ [0] = {
+ .start = QFEC_MAC_BASE,
+ .end = QFEC_MAC_BASE + QFEC_MAC_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = QFEC_MAC_IRQ,
+ .end = QFEC_MAC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ .start = QFEC_CLK_BASE,
+ .end = QFEC_CLK_BASE + QFEC_CLK_SIZE,
+ .flags = IORESOURCE_IO,
+ },
+ [3] = {
+ .start = QFEC_MAC_FUSE_BASE,
+ .end = QFEC_MAC_FUSE_BASE + QFEC_MAC_FUSE_SIZE,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct platform_device qfec_device = {
+ .name = "qfec",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(qfec_resources),
+ .resource = qfec_resources,
+};
+
+
+Resource entries exist for three address regions and one interrupt. The
+interrupt is identified as IORESOURCE_IRQ, the controller registers as
+OPRESOURCE_MEM, the clock control registers as IORESOURCE_IO, and the
+MAC address fuses as IORESOURCE_DMA.
+
+
+Dependencies:
+=============
+None
+
+
+User space utilities:
+=====================
+
+See procfs descriptions
+
+
+Known issues:
+=============
+
+- replace procfs w/ debugfs
+
+
+To do:
+======
+
+- specify interface (MII/RevMII/RgMii) in resource structure
+- RevMii support untested
+- RgMii (10/100/1000)
+- generic timestamp support
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 5e7cb39ad19..6d7ca5695b0 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -21,6 +21,7 @@ show up in /proc/sys/kernel:
- acct
- bootloader_type [ X86 only ]
- bootloader_version [ X86 only ]
+- boot_reason [ ARM only ]
- callhome [ S390 only ]
- auto_msgmni
- core_pattern
@@ -126,6 +127,19 @@ Documentation/x86/boot.txt for additional information.
==============================================================
+boot_reason:
+
+ARM -- reason for device boot
+
+A single bit will be set in the unsigned integer value to identify the
+reason the device was booted / powered on. The value will be zero if this
+feature is not supported on the ARM device being booted.
+
+See the power-on-status field definitions in
+Documentation/arm/msm/boot.txt for Qualcomm's family of devices.
+
+==============================================================
+
callhome:
Controls the kernel's callhome behavior in case of a kernel panic.
diff --git a/Documentation/tzcom.txt b/Documentation/tzcom.txt
new file mode 100644
index 00000000000..7472deeede6
--- /dev/null
+++ b/Documentation/tzcom.txt
@@ -0,0 +1,181 @@
+Introduction
+============
+
+The tzcom (TrustZone Communicator) device driver provides IOCTLs for userspace
+to communicate with TrustZone Operating Environment (TZBSP) using Secure
+Channel Manager (SCM) interface. It also provides a way for TZBSP to utilize
+services in HLOS.
+
+Hardware description
+====================
+
+The hardware interaction is specified in Secure Channel Manager for TZBSP design
+document. This driver exercises the SCM interface (scm_call).
+
+Software description
+====================
+
+This driver is a character device driver and following operations are registered:
+- tzcom_open()
+- tzcom_release()
+- tzcom_ioctl()
+
+
+This driver provides following IOCTL methods:
+ TZCOM_IOCTL_REGISTER_SERVICE_REQ - to register HLOS service
+ TZCOM_IOCTL_UNREGISTER_SERVICE_REQ - to unregister HLOS service
+ TZCOM_IOCTL_SEND_CMD_REQ - send a command to a service
+ TZCOM_IOCTL_READ_NEXT_CMD_REQ - wait for a cmd from TZBSP to use HLOS service
+ TZCOM_IOCTL_CONTINUE_CMD_REQ - continue the last incomplete cmd on TZBSP
+
+TZCOM_IOCTL_REGISTER_SERVICE_REQ sequence diagram:
+
+ +--------------+ +---------------+
+ | USERSPACE | | TZCOM |
+ +------+-------+ +-------+-------+
+ | REGISTER_SERVICE |
+ |----------------->| ___
+ | |,-' ``.
+ | + verify &`.
+ | | add |
+ | | service |
+ | | to a list|
+ | registered |<-.._,,,,/
+ |<-----------------|
+ | |
+
+TZCOM_IOCTL_READ_NEXT_CMD_REQ, TZCOM_IOCTL_SEND_CMD_REQ and
+TZCOM_IOCTL_CONTINUE_CMD_REQ sequence:
+
+ +--------------+ +---------------+ +-------------+ +----------------+
+ | USERSPACE | | TZCOM | | SCM | | TZBSP |
+ +---+--+-------+ +-------+-------+ +------+------+ +-------+--------+
+ | | READ_NEXT_CMD | | |
+ +--|----------------->| | |
+ | | |.--------. | |
+ | | || BLOCKED| | |
+ | | |`--------' | |
+ | | | | |
+ | | | | |
+ | | SEND_CMD | | |
+ | +----------------->| | |
+ | | | scm_call | |
+ | | +---------------->| SEND_CMD |
+ | | | +---------------->|
+ | | | | cmd incomplete |
+ | | | scm_call returns|<----------------+
+ | | |<----------------+ |
+ | | | | |
+ | | |,-'''-. | |
+ | | + READ `. | |
+ | | | NEXT | | |
+ | | | CMD / | |
+ | | READ_NEXT_CMD ret|<.____,' | |
+ |<-|------------------+ | |
+ ,---. | | | | |
+ / \ | | | | |
+/perform\| | | | |
+ received) | | | |
+\command/| | | | |
+ \ / | | | | |
+ `---' | | | | |
+ | | | | |
+ | | CONTINUE_CMD | | |
+ +--|----------------->| | |
+ | | returns | _,... | |
+ | | immediately |' `. | |
+ | | | fill in`. | |
+ | | | incomplete | |
+ | | | cmd ; | |
+ | |<-...---' | |
+ | | scm_call | |
+ | +---------------->| SEND_CMD |
+ | | +---------------->|
+ | | | cmd complete |
+ | | scm_call returns|<----------------+
+ |SEND_CMD return |<----------------+ |
+ |<-----------------+ | |
+ | | | |
+
+
+
+There are three shared buffers between TZCOM driver and TZBSP.
+1) For command and response buffers for SEND_CMD requests
+2) For commands originated from TZBSP and their corresponding responses
+3) For debug service
+
+When calling IOCTL_SEND_CMD_REQ from userspace, command request and response
+buffers are initialized and provided in the IOCTL arguments. Where request and
+response buffers will be passed as an arguments to the smc_call method.
+
+The requests are synchronous. The driver will put the process to sleep,
+waiting for the completion of the requests using wait_for_completion().
+
+This driver uses kmalloc for shared buffer pools which get initialized at driver
+initialization. There are three buffers each 20 KB. If any of the buffers fail
+to initialize then driver will fail to load. Assumption is the allocated
+memory for buffers is contiguous.
+
+
+Design
+======
+
+The goal of this driver is to provide a communication API for the userspace
+application to execute services in TrustZone as well as TrustZone operating
+environment to access services in HLOS.
+
+Currently TZ->HLOS communication happens from a blocking call to READ_NEXT_CMD
+that is initiated from the userspace and on receiving a command request from TZ
+service, command is placed on a queue to unblock READ_NEXT_CMD call. This could
+have been solved by using a callback, but the practice of invoking callbacks in
+userspace from kernel is discouraged.
+
+Power Management
+================
+
+n/a
+
+SMP/multi-core
+==============
+
+TZCOM allows multiple services being registered from HLOS and multiple processes
+or threads can call IOCTL_READ_NEXT_MSG. These services will block until new
+data arrives on the shared buffer (buffer #2 as mentioned in Software
+Description). This is achieved using wait queues.
+
+Security
+========
+
+Please refer to Security Channel Manager design document.
+
+Performance
+===========
+
+Every scm_call is a context switch between non-trusted and trusted operating
+environment. There are no performance related matrix for scm_call available as
+of now.
+
+Interface
+=========
+
+This driver will have a /dev/tzcom node and following IOCTL calls can be made.
+
+Userspace API (ioctl calls):
+ TZCOM_IOCTL_REGISTER_SERVICE_REQ - to register HLOS service
+ TZCOM_IOCTL_UNREGISTER_SERVICE_REQ - to unregister HLOS service
+ TZCOM_IOCTL_SEND_CMD_REQ - send a command to a service
+ TZCOM_IOCTL_READ_NEXT_CMD_REQ - wait for a cmd from TZBSP to use HLOS service
+ TZCOM_IOCTL_CONTINUE_CMD_REQ - continue the last incomplete cmd on TZBSP
+
+
+Dependencies
+============
+
+This driver interacts with Trustzone operating environment, thus depends on
+the TZBSP supported architecture.
+
+
+To do
+=====
+
+TBD
diff --git a/Documentation/usb/ehset_compliance.txt b/Documentation/usb/ehset_compliance.txt
new file mode 100644
index 00000000000..3f00cf0ea9e
--- /dev/null
+++ b/Documentation/usb/ehset_compliance.txt
@@ -0,0 +1,69 @@
+Introduction
+============
+
+A USB high speed host must pass electrical compliance tests defined
+by the USB-IF. These compliance tests require the host controller to
+support various test modes defined by the USB 2.0 specification.
+
+USB-IF defines a standard method to initiate the test modes on an
+embedded host controller by using a test fixture. During enumeration
+by the USB host, this test fixture provides a Vendor-Id/Product-Id
+(or VID/PID) pair which is used by the host to initiate a particular
+test mode as each VID/PID pair corresponds to a unique test mode.
+
+Hardware description
+====================
+
+The driver doesn't require any new hardware and is like any other
+USB host class driver. It gets notified when a Test Fixture device is
+connected to the host.
+
+The test modes that can be initiated are specific to the high speed
+hosts controllers only.
+
+Software description
+====================
+
+This EHSET (or Embedded High Speed Electrical Test) driver registers
+itself with USB core as the preferred driver for the Test Fixture
+device. During registration it provides the list of the various
+VID/PID pairs which the Test Fixture may present during enumeration.
+The VID is always 0x1A0A, and the PIDs presented by the Test Fixture
+correspond to the following test modes:
+
+__________________________________________________
+ PID Test Mode
+--------------------------------------------------
+ 0x0101 TEST_SE0_NAK
+ 0x0102 TEST_J
+ 0x0103 TEST_K
+ 0x0104 TEST_PACKET
+ 0x0106 HS_HOST_PORT_SUSPEND_RESUME
+ 0x0107 SINGLE_STEP_GET_DEV_DESC
+ 0x0108 SINGLE_STEP_SET_FEATURE
+--------------------------------------------------
+
+The control flow is as follows:
+
+1. USB core notifies the ehset driver when a device (Test Fixture) is
+attached to the host having the VID/PID pair as one of the specified
+above.
+
+2. EHSET driver checks the PID which the Test Fixture presented during
+enumeration and then initiates the corresponding test mode.
+
+
+Dependencies
+============
+
+The driver depends on the USB EHCI Host support.
+
+Other
+=====
+
+The driver's code shall be added as a new file in the
+/kernel/drivers/usb/misc directory.
+
+Embedded High-speed Electrical Test Procedure document is available
+at:
+http://www.usb.org/developers/onthego/EHSET_v1.01.pdf
diff --git a/Documentation/usb/gadget_rmnet.txt b/Documentation/usb/gadget_rmnet.txt
new file mode 100644
index 00000000000..2bf05a1b131
--- /dev/null
+++ b/Documentation/usb/gadget_rmnet.txt
@@ -0,0 +1,222 @@
+Introduction
+============
+
+QUALCOMM MSM Interface (QMI) defines the interface between MSM and
+attached Terminal Equipment (TE). RmNet interface is a new logical
+device in QMI framework for data services. RmNet in accordance with
+QMI architecture defines channels for control and data transfers and
+for example it uses Data I/O channel for IP data transfer and control
+I/O channel for QMI messaging (functionality similar to AT commands).
+RmNet may be used in place of legacy USB modem interface.
+
+Tethered networking is one of the function from MSM which can also be
+supported using QMI protocol. There are other standard protocols exists
+such as CDC-ECM and Windows proprietary RNDIS. On the host-side system,
+the gadget rmnet device looks like a ethernet adapter.
+
+Hardware description
+====================
+
+QMI is a messaging protocol to expose various functionalities of MSM
+and one of the functionality to be tethered networking which is being
+exposed over QMI using RmNet protocol. This usb gadget has one bulk-in,
+one bulk-out and one interrupt-in endpoint.
+
+Design:
+=======
+RmNet function driver design follows two approaches:
+
+Approach 1:
+-----------
+Single function driver is used to communicate with
+Modem(both for data and control). Most of the initial
+MSM targets are following this approach.
+
+The main disadvantage with this approach is there are
+multiple RmNet drivers for any change in DATA and Control
+Layer. There is no re-use in the code.
+
+Approach 2:
+-----------
+RmNet driver is divided into 3 components
+
+1. USB:
+This component has the functionality to deal with composite layer.
+Allocates Interfaces, Endpoints, listens to connect/disconnect
+interrupts and gives connect/disconnect notifications to DATA and
+CONTROL modules.
+
+2. Data:
+This component talks to modem to transfer IP data. Usually DATA
+and CONTROL go over same channel. However, to achieve higher
+data rates new transport channel for DATA may be used.
+
+3. Control:
+This component talks to modem to transfer rmnet control data.
+
+Software description
+====================
+The RmNet suports following data and control transports:
+as follows:
+ 1. SMD Interface
+ 2. SDIO Interface
+ 3. BAM Interface
+ 4. SMD Control Interface
+
+SMD interface uses the Shared memory for the RmNet driver to communicate
+with the MSM modem processor.
+SDIO interface acts as a link for communication of RmNet driver with the
+MDM modem processor.
+
+USB INTERACTION:
+----------------
+
+The RmNet function driver binds with the USB using the struct usb_function.
+The function is added using the usb_function_add().
+Control Transfers: The RmNet handles two Class-specific control
+transfers: SEND_ENCAPSULATED_COMMAND and GET_ENCAPSULATED_RESPONSE.
+The asynchronous protocol QMI which consists of the QMI requests/responses
+is used for handling the transfers between the RmNet and the Host where the
+host sends a new QMI request before receiving the response for the current
+QMI request.
+
+Control & Data flow:
+1. Host issues a SEND_ENCAPSULATED command to send a QMI request.
+SMD: If the SMD control channel has enough room to accomodate a QMI request,
+it is written into the SMD buffer. Otherwise, append/add that request to
+qmi_request queue. A tasklet is scheduled to drain all QMI requests in
+qmi_request queue.
+SDIO: Add each request in the qmi_request queue and is processed until
+the queue is empty.
+
+2. Append/Add QMI response from modem to qmi_response queue.
+A notification on an interrupt end point is used to communicate the QMI
+response to host.
+
+3. Host issues a GET_ENCAPSULATED command to retrieve the QMI response.
+The response from qmi_response queue will be sent to the host.
+
+4. After the connection is fully established data can be sent to
+bulk-out endpoint and data can be received from bulk-in endpoint.
+
+5. Host can send QMI requests even after the connection is established.
+
+RmNet gadget driver is completely unaware of QMI/IP protocol. It just
+acts as a bridge between the modem and the PC.
+
+All the request/response queues in the driver can be accessed either
+from tasklet/workqueue or from interrupt context (either usb or smd/sdio
+interrupt handler). Hence a spinlock is used to protect all data/control req
+lists.
+
+
+SMD Interface:
+--------------
+
+1. Each QMI request/response can at most be 2048 bytes. Eight 2KB buffers
+are allocated using kmalloc for storing maximum of 8 requests/responses.
+
+2. Four 2KB buffers are allocated using kmalloc for data transfers on
+each bulk endpoint.
+
+Data structures:
+struct qmi_buf - Buffer to handle QMI requests & responses
+struct rmnet_smd_info - Control & Data SMD channel private data
+struct rmnet_dev - Endpoint and driver specific data
+
+Workqueues:
+rmnet_connect_work - Called on device connection.
+ Opens SMD channels; enables endpoints
+rmnet_disconnect_work - Called on device disconnection.
+ Closes SMD channels.
+
+Tasklets:
+rmnet_control_rx_tlet
+rmnet_control_tx_tlet - Control transfer data reception and transmission
+ handler
+
+rmnet_data_rx_tlet
+rmnet_data_tx_tlet - Data transfer data reception and transmission handler
+
+
+SMD control interface
+----------------------
+This function driver implements exchnage of control informtion with
+modem over SMD. Uses smd_read/write commands to read or write rmnet
+ctrl packets. Exposes a call back function to usb component to write
+control packet and at the same time call a call back usb component
+callback to send data to usb host.
+
+Data structures and Interfaces are very similar to control interfaces
+explained in "SMD Interface"
+
+BAM MUX interface
+------------------
+BAM Mux interface is very similar to SDIO MUX interface. However there
+are differences in the way BAM and SDIO operate but all of the details
+are masked by MUX Driver.
+
+Refer to the SDIO interfaces for more information on data structures
+
+SDIO Interface:
+---------------
+
+1. Each QMI request/response buffer is allocated depending on the size
+of data to be transmitted for the request/response.
+
+2. A 2KB network buffer is allocated for data transfer on bulk-out
+endpoint. The SDIO allocates the required buffer for data transfers
+on an bulk-in endpoint.
+
+Data structures:
+struct rmnet_sdio_qmi_buf - Buffer to handle QMI requests/responses.
+struct rmnet_dev - Endpoint and driver specific data
+
+Workqueues:
+rmnet_connect_work - Device connection handler. Opens SDIO
+ channels; enables and allocate buffer for
+ endpoints
+rmnet_disconnect_work - Device disconnection handler. Closes
+ SDIO channels; Frees allocated buffers.
+rmnet_control_rx_work - Control data reception handler.
+rmnet_data_rx_work - Network data reception handler.
+
+
+Two SMD/SDIO channels (control and data) are used as communication channels
+between Modem and Apps processor. The driver opens the SMD/SDIO channels
+on USB device connection. Data is either read from/written to the channels
+as one complete packet.
+
+SMD/SDIO provides a notification whenever the Modem processor completes
+read/write of a packet. Based on these SMD/SDIO notifications all the
+pending read/write requests will be handled. Tasklets(SMD)/Workqueues(SDIO)
+are used to get the requests done.
+
+There is another variant of rmnet driver called rmnet_smd_sdio which is used
+on some boards. This driver allows the transport (SMD/SDIO) to be chosen
+at runtime. This is required because either MDM processor or MODEM processor
+is only active at a time for data transfers. As SMD and SDIO interfaces
+are different, different endpoint completion handlers are used. This driver
+leverage the existing rmnet over smd and rmnet over sdio drivers. The control
+messages (QMI) always routed over SDIO. After the control messages exchange,
+user space will come to know about the available data transport (SMD/SDIO).
+User space notify the same to driver and the corresponding transport is
+activated. It is assumed that transport will not change while a USB cable
+is connected.
+
+Rmnet over SMD and rmnet over SDIO doesn't expose any of its interfaces to
+either kernelspace or userspace. But rmnet over smd/sdio expose a sysfs
+interface for userspace to notify the available transport to driver.
+
+The sysfs file can be found at
+/sys/class/usb_composite/rmnet_smd_sdio/transport
+
+The below command activates the SMD transport
+echo 0 > /sys/class/usb_composite/rmnet_smd_sdio/transport
+
+The below command activates the SDIO transport
+echo 1 > /sys/class/usb_composite/rmnet_smd_sdio/transport
+
+-EINVAL is returned if a write is attempted to transport when a USB cable
+is not connected.
+
diff --git a/Documentation/usb/gadget_sdio.txt b/Documentation/usb/gadget_sdio.txt
new file mode 100644
index 00000000000..d0f1d639e9a
--- /dev/null
+++ b/Documentation/usb/gadget_sdio.txt
@@ -0,0 +1,32 @@
+Introduction
+============
+
+Gadget serial driver is divided into two parts.
+1. f_serial.c : Interacts with USB Gadget Layer
+2. u_serial.c : Interacts with TTY Layer
+
+Gadget sdio driver adds capability to interact with SDIO Layer in
+case modem device is inter-connected with sdio interface.
+
+S/W Description
+===============
+Gadget SDIO driver is a simple bridge driver between usb serial
+gadget and sdio abstraction layer. It registers with sdio
+abstraction layer with read/write call backs and provides
+USB connect/disconnect call backs usb gadget serial driver.
+
+
+S/W Control Flow:
+=================
+Driver maintains two sdio channels, one for data and one for control.
+Data pipe is dedicated sdio channel where as control is a muxed channel.
+Incase of sdio control pipe, driver registers for control information
+chagnes from modem side. Whenever new information is available, it
+would queue a interrupt endpoint w/ new info. Laptop can also send the
+DTR and RTS information as part of SET Encapsulated command.
+
+Data pipe of sdio channel also has notification mechanism to indicate
+the READ/WRITE availability. When READ is available on SDIO pipe,
+driver would read the data and hands it over to USB In ept and when
+it receives the data from USB driver would queue the same to SDIO
+channel(if write buffers are available).
diff --git a/Documentation/usb/gadget_smd.txt b/Documentation/usb/gadget_smd.txt
new file mode 100644
index 00000000000..18b93d8ff31
--- /dev/null
+++ b/Documentation/usb/gadget_smd.txt
@@ -0,0 +1,27 @@
+Introduction
+============
+
+Gadget serial driver is divided into two parts.
+1. f_serial.c : Interacts with USB Gadget Layer
+2. u_serial.c : Interacts with TTY Layer
+
+Gadget smd driver adds capability to interact with smd layer in
+case modem device is inter-connected with smd interface.
+
+S/W Description
+===============
+Gadget smd driver is a simple bridge driver between usb serial
+gadget and smd abstraction layer. It registers with smd
+abstraction layer with notification call back and provides
+USB connect/disconnect call backs usb gadget serial driver.
+
+
+S/W Control Flow:
+=================
+USB SMD driver registers w/ SMD driver and provides notification
+call back. SMD Driver calls this call back whenever DATA is available
+to read, buffer is available to write or modem control signals changed.
+Upon receiving notification from SMD driver, USB driver appropriately
+schedules read/write works. In case of control singals, USB driver
+notifies gadget component with changed control information.
+
diff --git a/Documentation/usb/msm_otg.txt b/Documentation/usb/msm_otg.txt
new file mode 100644
index 00000000000..29b6f1a635c
--- /dev/null
+++ b/Documentation/usb/msm_otg.txt
@@ -0,0 +1,382 @@
+Introduction
+============
+This driver implements Session Request Protocol (SRP) and Host negotiation
+Protocol (HNP) described in On-The-Go (OTG) Supplement to the USB 2.0
+Specification. It also provides support for Accessory Charger Adapter (ACA)
+defined in the Battery Charging Specification 1.1.
+
+These protocols provide a means for USB host devices to intelligently manage
+power on VBUS and USB peripheral devices to become the host when paired with
+another OTG device.
+
+Hardware description
+====================
+USB hardware found in Qualcomm chipsets like MSM7x27, MSM7x30, QSD8x50 and
+MSM8660 is compliant to USB 2.0 high speed On-The-Go protocol.
+The transceiver, aka PHY is integrated on the chip and ULPI interface is used for
+communication.
+
+USB hardware interfaces to the system memory via AHB BUS. DMA engine is included
+to move all of the data to be transferred over the USB between USB core and
+system memory. Device controller can support 16 endpoints of all types
+(control/bulk/interrupt /isochronous) defined in USB 2.0 specification. The
+host controller is compliant to EHCI specification. Directly connected USB 1.1
+Full/Low speed devices are supported without a companion controller by having
+inbuilt Transaction Translator (TT).
+
+USB_HS_CLK, USB_HS_PCLK and USB_HS_CCLK are required for USB operation.
+Phy feeds 60MHZ HS_CLK to link when ULPI interface is used. This clock needs to
+be turned on only while resetting the link. HS_PCLK (Pbus clock) is required to
+move data to/from hardware FIFO. This clock may not be required on targets like
+MSM8660 where USB is part of smart peripheral subsystem. AXI bus frequency needs
+to be kept at maximum value while USB data transfers are happening. HS_CCLK
+(core clock) is introduced in MSM7x30 to get rid of dependency on AXI bus
+frequency.
+
+The same irq line is shared across OTG, Device controller and Host controller
+drivers. Phy is integrated on the chip and no gpios are required to connect link
+and PHY.
+
+Phy can monitor VBUS and ID lines while operating in low power mode (LPM). But
+leaving comparators ON in LPM increases power consumption. Hence VBUS line is
+routed to PMIC hardware which can generate interrupt (when accessed by Apps
+processor) or send RPC callback. This is also useful when an External LDO to
+power up 3.3V of PHY is not installed. An internal LDO is turned upon
+receiving notification from PMIC. Id line is not routed to PMIC. Hence OTG mode
+can not be supported with this configuration and External LDO must be present.
+
+Hardware can generate interrupt when voltage on VBUS line is reached
+above/below A-VBUS Valid and B-Session Valid threshold values defined in OTG
+specification. Interrupt is generated when Id line is grounded i.e Micro-A
+cable is connected.
+
+The following hardware features help in meeting the SRP and HNP protocol
+timings.
+
+Hardware Assist Data-pulse (HADP):
+---------------------------------
+When software programs HADP, Hardware start a data pulse of approximately 7ms
+in duration and then automatically ceases the data pulsing. This automation
+relieves software from controlling the data-pulse duration. This assist will
+ensure data pulsing meets the OTG requirement of > 5ms and < 10ms.
+
+Hardware Assist Auto-Reset (HAAR):
+---------------------------------
+When software programs HAAR, Hardware will automatically start a reset after
+a connect event. This shortcuts the normal process where software is notified
+of the connect event and starts the reset. Software will still receive
+notification of the connect event but should not write the reset bit when the
+HAAR is set. Software will be notified again after the reset is complete via
+the enable change bit in the PORTSC register which cause a port change
+interrupt.
+
+Hardware Assist B-Disconnect to A-Connect (HABA):
+------------------------------------------------
+During Host negotiation Protocol(HNP), A-Device must enable pull-up on D+ as
+soon as possible after detecting disconnect from B-device.
+
+When Software programs HABA, the Host Controller port is in suspend mode, and
+the B-device disconnects, then this hardware assist begins.
+1. Reset the OTG core
+2. Write the OTG core into device mode.
+3. Write the device run bit to a '1' and enable necessary interrupts including:
+ * USB Reset Enable (URE) : enables interrupt on usb bus reset to device
+ * Sleep Enable (SLE) : enables interrupt on device suspend
+ * Port Change Detect Enable (PCE) : enables interrupt on device connect
+
+When software has enabled this hardware assist, it must not interfere during the
+transition and should not write any register in the core until it gets an
+interrupt from the device controller signifying that a reset interrupt has
+occurred or at least first verify that the core has entered device mode.
+
+The following hardware feature helps in supporting Accessory Charger Adapter:
+
+PHY Support for ID_A/B/C:
+------------------------
+Accessory Charger Adapter has three ports to attach an OTG, charger and A or
+B-device. So, based on what all device are attached to the ACA, it outputs a
+state on the ID pin (i.e GROUND, ID_A, ID_B, ID_C, FLOAT).
+USB PHY has support for these ID states. Once software enables this support,
+PHY sets corresponding bit in its INTS register based on any changes in the
+ID state.
+
+Software description
+====================
+
+This driver provides OTG functionality when Device controller driver (DCD) and
+Host controller driver (HCD) are enabled. It is enabled even when one of the DCD
+or HCD is enabled to use PHY initialization, clock management, register memory
+mapping, low power mode (LPM) functionalities.
+
+Session Request Protocol (SRP): A-device may turn off power on VBUS upon user
+request or A_WAIT_BCON timeout. SRP detection interrupt is enabled and
+hardware is put into LPM. If Data pulse is detected, A-device starts a new
+session by applying power on VBUS. Hardware Auto Assist Data pulse feature is
+used to program Data pulse
+When acting as a B-device, if SRP initial conditions (SE0 condition for
+TB_SE0_SRP min and previous session was ended before TB_SSEND_SRP) are met, SRP
+is initiated upon user request. Hardware Auto Assist Data pulse feature is
+used to program Data pulse. If remote device does not turn on VBUS before
+TB_SRP_FAIL, an error is reported to user space.
+
+Host Negotiation Protocol (HNP): A-device periodically polls B-device to check
+host request status. When B-device returns true, A-device shall enable HNP and
+suspend the bus with in THOST_REQ_SUSP. HNP polling is implemented in USB core
+software. HCD registers a start_hnp callback method with EHCI framework. This
+method is called after suspending the port if HNP is enabled. HCD notifies OTG
+that B-device is suspended. A_AIDL_BDIS timer is kicked and waits for B-device
+disconnection. If B-device does not signal disconnect within TA_AIDL_BDIS
+timeout, session is closed by powering down VBUS. Otherwise A-device stops HCD
+and starts DCD to enable pull-up. A-device again resumes host role if it had
+observed bus idle for TA_BIDL_ADIS time.
+B-device signals host_request true upon user request. DCD notifies OTG that
+HNP is enabled and bus is idle. OTG driver disable pull-up by stopping DCD and
+kick B_ASE0_BRST timer. If A-device does not signal connect with in
+TB_ASE0_BRST, B-device resumes in peripheral role. Otherwise B-device assert
+the bus reset and enumerate the A-device.
+
+MSM chipsets which have 45nm integrated PHY supports Attach Detection Protocol.
+(A protocol which enables an OTG device to detect when a remote device has been
+attached or detached without supplying VBUS). ADP support needs to be
+implemented to efficiently supply/request power on VBUS. Leakage currents (i.e
+VBUS applied but no peripheral is connected) are very less on MSM hardware. So
+VBUS can be applied when Id becomes false. ADP may be never implemented in
+this driver due to this reason.
+
+The state machine is implemented as described in the OTG specification.
+A few exceptions are mentioned below:
+
+1. Host session request i.e a_bus_request input variable is automatically
+asserted when Id becomes false and SRP is detected.
+It is de-asserted When HCD suspends the bus and asserted again in case of
+remote device remote wakeup.
+2. Output variables like drv_vbus, loc_conn, loc_sof, adp_prb are not
+maintained in the state machine as they serve no purpose.
+3. Bus power down request i.e a_bus_drop is cleared when Micro-A cable is
+connected so that non OTG device can be detected when Micro-A cable is
+connected next time.
+4. Input variables that determine SRP initial condition status b_se0_srp and
+b_ssend_srp are not maintained in state machine processing. When a session is
+ended i.e VBUS falls below B-Session Valid threshold, time stamp is taken and
+is compared against the current time at the time of SRP initiation.
+
+
+Controller gives interrupt for every 1 msec if 1MSIE (1 Msec interrupt enable)
+is set. Timers used in OTG state machine can be implementing using 1MSEC
+timer as a source. But hrtimer on MSM hardware can give at least 1/32KHZ
+precision. So hrtimer framework is used to implement OTG timers. No two OTG
+timers run in parallel. Hence one hrtimer is used for all OTG timers.
+
+OTG state machine processing can not be done in atomic context. Hence a worker
+thread is created for processing the state machine events. A separate worker
+thread is created instead of using default worker thread to meet OTG
+specification timings.
+
+OTG supplement Revision 2.0 has made HNP timings less stringent compared to
+Revision 1.3. TA_BDIS_ACON (The time with in A-Device should enable pull-up
+upon B-device signals disconnect) has been changed to 150 msec from 3 msec.
+DCD can be easily activated within 150 msec. Hence HABA is not used.
+TB_ACON_BSE0 (The time with in B-device should reset the A-device) has been
+changed to 150 msec from 1 sec. Host software would easily meet this timing
+given that de-bounce delays and root hub port power stabilization delays are
+not required during HNP.
+
+Accessory Charger Adapter (ACA): To support ACA there must be support in the
+USB hardware (Controller and PHY) for the ID_A/B/C states. It should be able
+to interrupt software for any ID state changes. On receiving this interrupt,
+interrupt handler checks the current ID state and invokes OTG state machine
+for further handling. Even if the USB Controller doesn't support these ID_A/B/C
+states, driver can still detect the ID state transitions by depending on USB
+PHY if the PHY supports these ID states. For this scenario, driver relies
+on polling of PHY register to determine the ID state changes as long as an
+ACA is attached to the system. This polling is implemented by using a timer
+running at a frequency of 1 sec. This timer checks for the current ID state
+and on detecting any change it invokes OTG state machine for further handling.
+
+Following are the actions performed by the driver as per the ID state:
+* ID_FLOAT: Configure device to act as peripheral and allow charging if VBUS
+ is present, else move it to LPM (low power mode).
+* ID_GROUND: Configure device to act as host and supply VBUS.
+* ID_A: Configure device to act as host and don't supply VBUS. In this state
+ the device can charge as well.
+* ID_B: Keep the device in IDLE state and allow charging.
+* ID_C: Configure device to act as peripheral and allow charging.
+
+Design
+======
+
+The following goals are kept in mind while designing OTG state machine.
+
+1. Avoid User intervention when operating as a standard Host or standard
+peripheral
+2. Support host only and peripheral only modes
+3. Put Hardware in LPM when ever possible
+4. Pass OTG compliance tests
+5. Report notification/error messages to user space
+6. With ACA, allow charging in Host mode as well
+7. Disable LPM as long as ID state polling is happening
+
+Power Management
+================
+
+System suspend is negated by acquiring wakelock while processing OTG state
+machine, or while polling for the PHY ID state in case of ACA.
+Wakelock is released:
+1. After activating the DCD/HCD. It is the responsibility of DCD/HCD to
+acquire wakelock if required.
+2. After putting hardware in LPM.
+3. No state machine events and timers are pending. This would cover scenarios
+mentioned in (1) and (2).
+4. After driver stops polling for ID state in case of ACA.
+
+Wake lock is re-acquired when state machine work is scheduled, which can
+happen from interrupt (exiting LPM), sysfs entries (initiate SRP, clear
+error, bus drop, etc), or from ID state polling routine.
+
+OTG driver provides set_suspend method for DCD/HCD to put hardware in LPM. DCD
+can use this method upon bus suspend. HCD can use this method upon suspending
+the root hub.
+
+LPM entering procedure:
+1. Clear PHY interrupt latch registers.
+2. Enable PHY comparators to detect Id, B-Session Valid interrupts while hardware
+is in LPM.
+3. Turn off PLL block on the PHY to achieve maximum power savings.
+4. Put PHY in suspend mode by setting PHCD bit in PORTSC register.
+5. Enable asynchronous interrupt so that PHY can generate interrupt when
+clocks are disabled.
+6. Disable all USB clocks.
+
+LPM exit procedure:
+1. Enable USB clocks.
+2. Disable asynchronous interrupt.
+3. Put PHY out of suspend mode. This is not required when LPM is exited due to
+hardware activity i.e asynchronous interrupt.
+
+SMP/multi-core
+==============
+
+OTG state machine inputs like bus request, bus drop, srp_detect etc accessed
+from interrupt context, and multiple process contexts. Hence atomic bit ops are
+used. ulpi_read and ulpi_write functions can now be accessed from multiple
+context, hence, these are protected using a spin_lock.
+
+Interface
+=========
+This driver provides the following methods to DCD and HCD.
+
+set_peripheral: DCD use this methods to register/unregister USB gadget.
+
+set_host: HCD use this method to register/unregister USB bus. Unlike gadget
+framework, there are no standard methods to start/stop HCD. Hence start_host
+method is introduced and must be initialized by HCD prior to registration.
+
+set_clk: HCD and DCD use this method to turn on/off USB_HS_CLK clk which is
+required only while resetting the controller.
+
+start_srp: DCD use this method to initiate Session Request Protocol (SRP).
+SRP may be initiated when function drivers use remote wakeup facility, when
+B-Device wishes to become host. OTG driver programs Data-Pulsing if initial
+condition of SRP are met. Otherwise proper error code is returned.
+
+set_suspend: DCD call this method when controller generates suspend
+interrupt or generates reset/port change interrupt before HNP and during HNP.
+If device is in B_PERIPHERAL state, HNP is initiated if host had enabled it.
+If device is in A_PERIPHERAL state, A_BIDL_ADIS timer is kicked in case of
+suspend interrupt. If this timer expires, A-device take back it's host role
+and continue previous session. This timer is deleted in case of
+reset/port change interrupts.
+HCD call this method after suspending the root hub. Hardware is put into LPM.
+
+start_hnp: A-device needs to enable pull-up on D+ within TA_BIDL_ADIS after
+suspending the bus i.e putting port in suspend state. EHCI stack can use this
+method to notify OTG right after suspending the OTG port. OTG driver schedule
+a work to stop host and enable pull-up on D+.
+
+send_event: USB core, DCD and HCD can use otg_send_event() API to send OTG
+notification/error messages to user space. send_event method defined in
+otg_transceiver is invoked by otg_send_event() API. An uevent is sent
+with SUBSYSTEM=platform, MODULE=msm_otg and EVENT=, where event could
+be one of the following events.
+
+OTG_EVENT_DEV_CONN_TMOUT: Device connection timeout or device not responding.
+OTG_EVENT_NO_RESP_FOR_HNP_ENABLE: Device is not responding to B_HNP_ENABLE
+ feature request.
+OTG_EVENT_HUB_NOT_SUPPORTED: Host does not support HUB class peripherals.
+OTG_EVENT_DEV_NOT_SUPPORTED: Host does not support the attached peripheral.
+OTG_EVENT_HNP_FAILED: HNP failed due to not meeting protocol timings.
+OTG_EVENT_NO_RESP_FOR_SRP: No Response for B-device SRP request.
+
+set_power: DCD can use otg_set_power() API to specify about the current that
+can be withdrawn from the VBUS for charging. Based on the current OTG state
+and whether ACA is attached or not, OTG driver makes a decision about the
+charging current and calls the charging APIs.
+
+The following sysfs nodes are provided at /sys/devices/platform/msm_otg
+
+pwr_down: This node can be used to control A-device session. a_bus_drop and
+a_bus_req state machine input variables are altered to start/stop session.
+Write to this node is invalid when device operating as a B-device.
+
+start_srp: This node can be used for requesting session. If all initial
+conditions of SRP are met, SRP is initiated. Write to this node is invalid
+when device operating as an A-device.
+
+clr_err: This node can be used to clear over-current condition. Write to this
+node is invalid when operating as an B-device. Error condition is
+automatically cleared when Id becomes false.
+
+The following sysfs nodes are provided at /sys/devices/platform/msm_hsusb/otg
+
+host_request: This node can be used for requesting host role. A-device shall
+select a_hnp_support feature prior to configuration and poll B-device for host
+request. When '1' is written to this node, host request is asserted. This node
+can also be used for taking host role when A-device operating as a peripheral.
+
+hnp_avail: User space can check this node before requesting the host role.
+Gadget controller driver asserts its internal variable hnp_avail when HNP
+polling request is send by the Host.
+
+Dependencies
+============
+
+If USB clocks are controlled by modem processor, proc_comm interface is used
+to turn on/off clocks.
+
+If VBUS power is controlled by modem processor, RPC interface is used to turn
+on/off VBUS power.
+
+Config options
+==============
+
+CONFIG_USB_MSM_ACA: Enable support for Accessory Charger Adapter (ACA)
+CONFIG_ENABLE_MSM_OTG_A_WAIT_BCON_TIMEOUT: Enable A_WAIT_BCON timeout. VBUS
+will be turned off and SRP detection is enabled upon this timeout. If this
+config is not selected, VBUS will not be turned off when Mini/Micro-A cable
+is connected. But hardware is put into LPM.
+
+Other
+=====
+On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification
+(Revision 2.0) found at http://www.usb.org/developers/onthego
+
+Known issues
+============
+Phy instability issues are observed when vbus_valid interrupt is enabled.
+Hence a_vbus_vld state machine variable is explicitly asserted after
+a_wait_vrise timer expiration.
+
+Spurious interrupt is seen when trying to put PHY in Low Power Mode with
+ID_A/B/C interrupts enabled in the PHY. As a result of which PHY doesn't stay
+in LPM. Hence, ID_A/B/C interrupts are disabled before entering LPM, and
+enabled while returning.
+
+To do
+=====
+
+Verify SRP detection on all targets.
+
+Phy instability issues are observed when A-Vbus Valid interrupt is enabled.
+But without this interrupt over current condition can not be determined. Root
+cause analysis for PHY instability issue and alternative methods like PMIC
+interrupt are being pursued.
diff --git a/Makefile b/Makefile
index f124b185b8e..800a54bc85a 100644
--- a/Makefile
+++ b/Makefile
@@ -330,7 +330,7 @@ include $(srctree)/scripts/Kbuild.include
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
-CC = $(CROSS_COMPILE)gcc
+REAL_CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
@@ -345,6 +345,10 @@ KALLSYMS = scripts/kallsyms
PERL = perl
CHECK = sparse
+# Use the wrapper for the compiler. This wrapper scans for new
+# warnings and causes the build to stop upon encountering them.
+CC = $(srctree)/scripts/gcc-wrapper.py $(REAL_CC)
+
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
-Wbitwise -Wno-return-void $(CF)
CFLAGS_MODULE =
diff --git a/arch/Kconfig b/arch/Kconfig
index 26b0e2397a5..6ea895daaa5 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -148,6 +148,13 @@ config HAVE_HW_BREAKPOINT
bool
depends on PERF_EVENTS
+config HAVE_HW_BRKPT_RESERVED_RW_ACCESS
+ bool
+ depends on HAVE_HW_BREAKPOINT
+ help
+ Some of the hardware might not have r/w access beyond a certain number
+ of breakpoint register access.
+
config HAVE_MIXED_BREAKPOINTS_REGS
bool
depends on HAVE_HW_BREAKPOINT
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 81f0b93a0cb..f150c181fe9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -62,7 +62,7 @@ config GENERIC_CLOCKEVENTS
config GENERIC_CLOCKEVENTS_BROADCAST
bool
depends on GENERIC_CLOCKEVENTS
- default y if SMP
+ default y if SMP && !LOCAL_TIMERS
config KTIME_SCALAR
bool
@@ -627,6 +627,10 @@ config ARCH_MSM
select GENERIC_CLOCKEVENTS
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
+ select ARCH_HAS_CPUFREQ
+ select GENERIC_GPIO
+ select GENERIC_TIME
+ select GENERIC_ALLOCATOR
help
Support for Qualcomm MSM/QSD based systems. This runs on the
apps processor of the MSM/QSD and depends on a shared memory
@@ -1033,6 +1037,19 @@ config ARM_TIMER_SP804
source arch/arm/mm/Kconfig
+config DONT_RESERVE_FROM_MOVABLE_ZONE
+ def_bool y
+ depends on MEMORY_HOTPLUG
+
+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
@@ -1234,6 +1251,29 @@ config ARM_ERRATA_754327
This workaround defines cpu_relax() as smp_mb(), preventing correctly
written polling loops from denying visibility of updates to memory.
+config PL310_ERRATA_727915
+ bool "Background Clean & Invalidate by Way operation can cause data corruption"
+ depends on CACHE_L2X0
+ help
+ PL310 implements the Clean & Invalidate by Way L2 cache maintenance
+ operation (offset 0x7FC). This operation runs in background so that
+ PL310 can handle normal accesses while it is in progress. Under very
+ rare circumstances, due to this erratum, write data can be lost when
+ PL310 treats a cacheable write transaction during a Clean &
+ Invalidate by Way operation.
+
+config KSAPI
+ tristate "KSAPI support (EXPERIMENTAL)"
+ depends on ARCH_MSM_SCORPION || ARCH_MSM_KRAIT
+ default n
+ help
+ KSAPI: Performance monitoring tool for linux.
+ KSAPI records performance statistics for Snapdragon linux platform.
+ It uses the /proc FS as a means to exchange configuration data and
+ counter statistics. It can monitor the counter statistics for
+ Scorpion processor supported hardware performance counters on a per
+ thread basis or AXI counters on an overall system basis.
+
endmenu
source "arch/arm/common/Kconfig"
@@ -1311,9 +1351,9 @@ config SMP
depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
- ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
+ MSM_SMP || ARCH_SHMOBILE
select USE_GENERIC_SMP_HELPERS
- select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
+ select HAVE_ARM_SCU if !MSM_SMP
help
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
@@ -1395,9 +1435,11 @@ config HOTPLUG_CPU
config LOCAL_TIMERS
bool "Use local timer interrupts"
- depends on SMP
+ depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
+ REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || ARCH_U8500 || \
+ MSM_SMP)
default y
- select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
+ select HAVE_ARM_TWD if (!MSM_SMP && !EXYNOS4_MCT)
help
Enable support for local timers on SMP platforms, rather then the
legacy IPI broadcast method. Local timers allows the system
@@ -1537,8 +1579,26 @@ config HW_PERF_EVENTS
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
+config VMALLOC_RESERVE
+ hex "Reserved vmalloc space"
+ default 0x08000000
+ depends on MMU
+ help
+ Reserved vmalloc space if not specified on the kernel commandline.
+
source "mm/Kconfig"
+config ARCH_MEMORY_PROBE
+ def_bool n
+ depends on MEMORY_HOTPLUG
+
+config ARCH_MEMORY_REMOVE
+ def_bool n
+ depends on MEMORY_HOTPLUG
+
+config DONT_RESERVE_FROM_MOVABLE_ZONE
+ def_bool n
+
config FORCE_MAX_ZONEORDER
int "Maximum zone order" if ARCH_SHMOBILE
range 11 64 if ARCH_SHMOBILE
@@ -1680,6 +1740,17 @@ config ARM_FLUSH_CONSOLE_ON_RESTART
released if it failed to be acquired, which will cause all the
pending messages to be flushed.
+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/system/cpaccess/cpaccess0.
+
+ If unsure, say N.
+
endmenu
menu "Boot options"
@@ -1940,6 +2011,14 @@ source "drivers/cpuidle/Kconfig"
endmenu
+config CPU_FREQ_MSM
+ bool
+ depends on CPU_FREQ && ARCH_MSM
+ default y
+ help
+ This enables the CPUFreq driver for Qualcomm CPUs.
+ If in doubt, say Y.
+
menu "Floating point emulation"
comment "At least one emulation must be selected"
@@ -2029,7 +2108,7 @@ menu "Power management options"
source "kernel/power/Kconfig"
config ARCH_SUSPEND_POSSIBLE
- depends on !ARCH_S5P64X0 && !ARCH_S5PC100
+ depends on !ARCH_S5P64X0 && !ARCH_S5PC100 && !ARCH_FSM9XXX
depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
def_bool y
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index f5b2b390c8f..96981603367 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -255,6 +255,7 @@ core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y += $(machdirs) $(platdirs)
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
+core-y += arch/arm/perfmon/
libs-y := arch/arm/lib/ $(libs-y)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index e58603b0006..25914b0aca6 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -27,6 +27,14 @@
.macro writeb, ch, rb
mcr p14, 0, \ch, c0, c5, 0
.endm
+#elif defined(CONFIG_CPU_V7)
+ .macro loadsp, rb, tmp
+ .endm
+ .macro writeb, ch, rb
+wait: mrc p14, 0, pc, c0, c1, 0
+ bcs wait
+ mcr p14, 0, \ch, c0, c5, 0
+ .endm
#elif defined(CONFIG_CPU_XSCALE)
.macro loadsp, rb, tmp
.endm
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index cf82a884a5c..66ed0c384b2 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,5 +1,6 @@
config ARM_GIC
bool
+ select MSM_SHOW_RESUME_IRQ
config ARM_VIC
bool
diff --git a/arch/arm/common/cpaccess.c b/arch/arm/common/cpaccess.c
new file mode 100644
index 00000000000..241e3395392
--- /dev/null
+++ b/arch/arm/common/cpaccess.c
@@ -0,0 +1,253 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*
+ * CP parameters
+ */
+struct cp_params {
+ unsigned long cp;
+ unsigned long op1;
+ unsigned long op2;
+ unsigned long crn;
+ unsigned long crm;
+ unsigned long write_value;
+ char rw;
+};
+
+static struct semaphore cp_sem;
+static int cpu;
+
+static DEFINE_PER_CPU(struct cp_params, cp_param)
+ = { 15, 0, 0, 0, 0, 0, 'r' };
+
+static struct sysdev_class cpaccess_sysclass = {
+ .name = "cpaccess",
+};
+
+/*
+ * get_asm_value - Dummy fuction
+ * @write_val: Write value incase of a CP register write operation.
+ *
+ * This function is just a placeholder. The first 2 instructions
+ * will be inserted to perform MRC/MCR instruction and a return.
+ * See do_cpregister_rw function. Value passed to function is
+ * accessed from r0 register.
+ */
+static noinline unsigned long cpaccess_dummy(unsigned long write_val)
+{
+ asm("mrc p15, 0, r0, c0, c0, 0\n\t");
+ asm("bx lr\n\t");
+ return 0xBEEF;
+} __attribute__((aligned(32)))
+
+/*
+ * get_asm_value - Read/Write CP registers
+ * @ret: Pointer to return value in case of CP register
+ * read op.
+ *
+ */
+static void get_asm_value(void *ret)
+{
+ *(unsigned long *)ret =
+ cpaccess_dummy(per_cpu(cp_param.write_value, cpu));
+}
+
+/*
+ * dp_cpregister_rw - Read/Write CP registers
+ * @write: 1 for Write and 0 for Read operation
+ *
+ * Returns value read from CP register
+ */
+static unsigned long do_cpregister_rw(int write)
+{
+ unsigned long opcode, ret, *p_opcode;
+
+ /*
+ * Mask the crn, crm, op1, op2 and cp values so they do not
+ * interfer with other fields of the op code.
+ */
+ per_cpu(cp_param.cp, cpu) &= 0xF;
+ per_cpu(cp_param.crn, cpu) &= 0xF;
+ per_cpu(cp_param.crm, cpu) &= 0xF;
+ per_cpu(cp_param.op1, cpu) &= 0x7;
+ per_cpu(cp_param.op2, cpu) &= 0x7;
+
+ /*
+ * Base MRC opcode for MIDR is EE100010,
+ * MCR is 0xEE000010
+ */
+ opcode = (write == 1 ? 0xEE000010 : 0xEE100010);
+ opcode |= (per_cpu(cp_param.crn, cpu)<<16) |
+ (per_cpu(cp_param.crm, cpu)<<0) |
+ (per_cpu(cp_param.op1, cpu)<<21) |
+ (per_cpu(cp_param.op2, cpu)<<5) |
+ (per_cpu(cp_param.cp, cpu) << 8);
+
+ /*
+ * Grab address of the Dummy function, insert MRC/MCR
+ * instruction and a return instruction ("bx lr"). Do
+ * a D cache clean and I cache invalidate after inserting
+ * new code.
+ */
+ p_opcode = (unsigned long *)&cpaccess_dummy;
+ *p_opcode++ = opcode;
+ *p_opcode-- = 0xE12FFF1E;
+ __cpuc_coherent_kern_range((unsigned long)p_opcode,
+ ((unsigned long)p_opcode + (sizeof(long) * 2)));
+
+#ifdef CONFIG_SMP
+ /*
+ * Use smp_call_function_single to do CPU core specific
+ * get_asm_value function call.
+ */
+ if (smp_call_function_single(cpu, get_asm_value, &ret, 1))
+ printk(KERN_ERR "Error cpaccess smp call single\n");
+#else
+ get_asm_value(&ret);
+#endif
+
+ return ret;
+}
+
+/*
+ * cp_register_write_sysfs - sysfs interface for writing to
+ * CP register
+ * @dev: sys device
+ * @attr: device attribute
+ * @buf: write value
+ * @cnt: not used
+ *
+ */
+static ssize_t cp_register_write_sysfs(struct sys_device *dev,
+ struct sysdev_attribute *attr, const char *buf, size_t cnt)
+{
+ unsigned long op1, op2, crn, crm, cp = 15, write_value, ret;
+ char rw;
+ if (down_timeout(&cp_sem, 6000))
+ return -ERESTARTSYS;
+
+ sscanf(buf, "%lu:%lu:%lu:%lu:%lu:%c:%lx:%d", &cp, &op1, &crn,
+ &crm, &op2, &rw, &write_value, &cpu);
+ per_cpu(cp_param.cp, cpu) = cp;
+ per_cpu(cp_param.op1, cpu) = op1;
+ per_cpu(cp_param.crn, cpu) = crn;
+ per_cpu(cp_param.crm, cpu) = crm;
+ per_cpu(cp_param.op2, cpu) = op2;
+ per_cpu(cp_param.rw, cpu) = rw;
+ per_cpu(cp_param.write_value, cpu) = write_value;
+
+ if (per_cpu(cp_param.rw, cpu) == 'w') {
+ do_cpregister_rw(1);
+ ret = cnt;
+ }
+
+ if ((per_cpu(cp_param.rw, cpu) != 'w') &&
+ (per_cpu(cp_param.rw, cpu) != 'r')) {
+ ret = -1;
+ printk(KERN_INFO "Wrong Entry for 'r' or 'w'. \
+ Use cp:op1:crn:crm:op2:r/w:write_value.\n");
+ }
+
+ return cnt;
+}
+
+/*
+ * cp_register_read_sysfs - sysfs interface for reading CP registers
+ * @dev: sys device
+ * @attr: device attribute
+ * @buf: write value
+ *
+ * Code to read in the CPxx crn, crm, op1, op2 variables, or into
+ * the base MRC opcode, store to executable memory, clean/invalidate
+ * caches and then execute the new instruction and provide the
+ * result to the caller.
+ */
+static ssize_t cp_register_read_sysfs(struct sys_device *dev,
+ struct sysdev_attribute *attr, char *buf)
+{
+ int ret;
+ ret = sprintf(buf, "%lx\n", do_cpregister_rw(0));
+
+ if (cp_sem.count <= 0)
+ up(&cp_sem);
+
+ return ret;
+}
+
+/*
+ * Setup sysfs files
+ */
+SYSDEV_ATTR(cp_rw, 0644, cp_register_read_sysfs,
+ cp_register_write_sysfs);
+
+static struct sys_device device_cpaccess = {
+ .id = 0,
+ .cls = &cpaccess_sysclass,
+};
+
+/*
+ * init_cpaccess_sysfs - initialize sys devices
+ */
+static int __init init_cpaccess_sysfs(void)
+{
+ int error = sysdev_class_register(&cpaccess_sysclass);
+
+ if (!error)
+ error = sysdev_register(&device_cpaccess);
+ else
+ printk(KERN_ERR "Error initializing cpaccess \
+ interface\n");
+
+ if (!error)
+ error = sysdev_create_file(&device_cpaccess,
+ &attr_cp_rw);
+ else {
+ printk(KERN_ERR "Error initializing cpaccess \
+ interface\n");
+ sysdev_unregister(&device_cpaccess);
+ sysdev_class_unregister(&cpaccess_sysclass);
+ }
+
+ sema_init(&cp_sem, 1);
+
+ return error;
+}
+
+static void __exit exit_cpaccess_sysfs(void)
+{
+ sysdev_remove_file(&device_cpaccess, &attr_cp_rw);
+ sysdev_unregister(&device_cpaccess);
+ sysdev_class_unregister(&cpaccess_sysclass);
+}
+
+module_init(init_cpaccess_sysfs);
+module_exit(exit_cpaccess_sysfs);
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 4ddd0a6ac7f..8996f06a76a 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -28,10 +28,12 @@
#include
#include
#include
+#include
#include
#include
#include
+#include
static DEFINE_SPINLOCK(irq_controller_lock);
@@ -42,6 +44,11 @@ struct gic_chip_data {
unsigned int irq_offset;
void __iomem *dist_base;
void __iomem *cpu_base;
+ unsigned int max_irq;
+#ifdef CONFIG_PM
+ unsigned int wakeup_irqs[32];
+ unsigned int enabled_irqs[32];
+#endif
};
/*
@@ -55,6 +62,7 @@ struct irq_chip gic_arch_extn = {
.irq_retrigger = NULL,
.irq_set_type = NULL,
.irq_set_wake = NULL,
+ .irq_disable = NULL,
};
#ifndef MAX_GIC_NR
@@ -93,6 +101,7 @@ static void gic_mask_irq(struct irq_data *d)
if (gic_arch_extn.irq_mask)
gic_arch_extn.irq_mask(d);
spin_unlock(&irq_controller_lock);
+
}
static void gic_unmask_irq(struct irq_data *d)
@@ -106,6 +115,104 @@ static void gic_unmask_irq(struct irq_data *d)
spin_unlock(&irq_controller_lock);
}
+static void gic_disable_irq(struct irq_data *d)
+{
+ if (gic_arch_extn.irq_disable)
+ gic_arch_extn.irq_disable(d);
+}
+
+#ifdef CONFIG_PM
+static int gic_suspend_one(struct gic_chip_data *gic)
+{
+ unsigned int i;
+ void __iomem *base = gic->dist_base;
+
+ for (i = 0; i * 32 < gic->max_irq; i++) {
+ gic->enabled_irqs[i]
+ = readl_relaxed(base + GIC_DIST_ENABLE_SET + i * 4);
+ /* disable all of them */
+ writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4);
+ /* enable the wakeup set */
+ writel_relaxed(gic->wakeup_irqs[i],
+ base + GIC_DIST_ENABLE_SET + i * 4);
+ }
+ mb();
+ return 0;
+}
+
+static int gic_suspend(void)
+{
+ int i;
+ for (i = 0; i < MAX_GIC_NR; i++)
+ gic_suspend_one(&gic_data[i]);
+ return 0;
+}
+
+extern int msm_show_resume_irq_mask;
+
+static void gic_show_resume_irq(struct gic_chip_data *gic)
+{
+ unsigned int i;
+ u32 enabled;
+ unsigned long pending[32];
+ void __iomem *base = gic->dist_base;
+
+ if (!msm_show_resume_irq_mask)
+ return;
+
+ spin_lock(&irq_controller_lock);
+ for (i = 0; i * 32 < gic->max_irq; i++) {
+ enabled = readl_relaxed(base + GIC_DIST_ENABLE_CLEAR + i * 4);
+ pending[i] = readl_relaxed(base + GIC_DIST_PENDING_SET + i * 4);
+ pending[i] &= enabled;
+ }
+ spin_unlock(&irq_controller_lock);
+
+ for (i = find_first_bit(pending, gic->max_irq);
+ i < gic->max_irq;
+ i = find_next_bit(pending, gic->max_irq, i+1)) {
+ pr_warning("%s: %d triggered", __func__,
+ i + gic->irq_offset);
+ }
+}
+
+static void gic_resume_one(struct gic_chip_data *gic)
+{
+ unsigned int i;
+ void __iomem *base = gic->dist_base;
+
+ gic_show_resume_irq(gic);
+ for (i = 0; i * 32 < gic->max_irq; i++) {
+ /* disable all of them */
+ writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4);
+ /* enable the enabled set */
+ writel_relaxed(gic->enabled_irqs[i],
+ base + GIC_DIST_ENABLE_SET + i * 4);
+ }
+ mb();
+}
+
+static void gic_resume(void)
+{
+ int i;
+ for (i = 0; i < MAX_GIC_NR; i++)
+ gic_resume_one(&gic_data[i]);
+}
+
+static struct syscore_ops gic_syscore_ops = {
+ .suspend = gic_suspend,
+ .resume = gic_resume,
+};
+
+static int __init gic_init_sys(void)
+{
+ register_syscore_ops(&gic_syscore_ops);
+ return 0;
+}
+arch_initcall(gic_init_sys);
+
+#endif
+
static void gic_eoi_irq(struct irq_data *d)
{
if (gic_arch_extn.irq_eoi) {
@@ -202,6 +309,20 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
static int gic_set_wake(struct irq_data *d, unsigned int on)
{
int ret = -ENXIO;
+ unsigned int reg_offset, bit_offset;
+ unsigned int gicirq = gic_irq(d);
+ struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
+
+ /* per-cpu interrupts cannot be wakeup interrupts */
+ WARN_ON(gicirq < 32);
+
+ reg_offset = gicirq / 32;
+ bit_offset = gicirq % 32;
+
+ if (on)
+ gic_data->wakeup_irqs[reg_offset] |= 1 << bit_offset;
+ else
+ gic_data->wakeup_irqs[reg_offset] &= ~(1 << bit_offset);
if (gic_arch_extn.irq_set_wake)
ret = gic_arch_extn.irq_set_wake(d, on);
@@ -250,6 +371,7 @@ static struct irq_chip gic_chip = {
#ifdef CONFIG_SMP
.irq_set_affinity = gic_set_affinity,
#endif
+ .irq_disable = gic_disable_irq,
.irq_set_wake = gic_set_wake,
};
@@ -324,7 +446,10 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
+ gic->max_irq = gic_irqs;
+
writel_relaxed(1, base + GIC_DIST_CTRL);
+ mb();
}
static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
@@ -348,6 +473,7 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL);
+ mb();
}
void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
@@ -399,5 +525,47 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
/* this always happens on GIC0 */
writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
+ mb();
}
#endif
+
+/* before calling this function the interrupts should be disabled
+ * and the irq must be disabled at gic to avoid spurious interrupts */
+bool gic_is_spi_pending(unsigned int irq)
+{
+ struct irq_data *d = irq_get_irq_data(irq);
+ struct gic_chip_data *gic_data = &gic_data[0];
+ u32 mask, val;
+
+ WARN_ON(!irqs_disabled());
+ spin_lock(&irq_controller_lock);
+ mask = 1 << (gic_irq(d) % 32);
+ val = readl(gic_dist_base(d) +
+ GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
+ /* warn if the interrupt is enabled */
+ WARN_ON(val & mask);
+ val = readl(gic_dist_base(d) +
+ GIC_DIST_PENDING_SET + (gic_irq(d) / 32) * 4);
+ spin_unlock(&irq_controller_lock);
+ return (bool) (val & mask);
+}
+
+/* before calling this function the interrupts should be disabled
+ * and the irq must be disabled at gic to avoid spurious interrupts */
+void gic_clear_spi_pending(unsigned int irq)
+{
+ struct gic_chip_data *gic_data = &gic_data[0];
+ struct irq_data *d = irq_get_irq_data(irq);
+
+ u32 mask, val;
+ WARN_ON(!irqs_disabled());
+ spin_lock(&irq_controller_lock);
+ mask = 1 << (gic_irq(d) % 32);
+ val = readl(gic_dist_base(d) +
+ GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
+ /* warn if the interrupt is enabled */
+ WARN_ON(val & mask);
+ writel(mask, gic_dist_base(d) +
+ GIC_DIST_PENDING_CLEAR + (gic_irq(d) / 32) * 4);
+ spin_unlock(&irq_controller_lock);
+}
diff --git a/arch/arm/configs/apq8064_defconfig b/arch/arm/configs/apq8064_defconfig
new file mode 100644
index 00000000000..e69865366dd
--- /dev/null
+++ b/arch/arm/configs/apq8064_defconfig
@@ -0,0 +1,134 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=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_FAIR_GROUP_SCHED is not set
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_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_EMBEDDED=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_APQ8064=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_CPU_HAS_L2_PMU=y
+# CONFIG_MSM_JTAG_V7 is not set
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+# CONFIG_MSM_DALRPC is not set
+# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_DIRECT_SCLK_ACCESS=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_SMP_ON_UP is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_SERIAL_MSM=y
+# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_HW_RANDOM=y
+CONFIG_DCC_TTY=y
+CONFIG_GPIOLIB=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_MSM_PMIC is not set
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_MSM_SSBI=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_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_KEYS=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/msm7627-perf_defconfig b/arch/arm/configs/msm7627-perf_defconfig
new file mode 100644
index 00000000000..63bbd30d1fe
--- /dev/null
+++ b/arch/arm/configs/msm7627-perf_defconfig
@@ -0,0 +1,298 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-perf"
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM7X27=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_MSM7X00A_USE_DG_TIMER=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_ONCRPCROUTER=y
+CONFIG_MSM_RMT_STORAGE_CLIENT=y
+# CONFIG_MSM_HW3D is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_VFP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_CLS_U32=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_IBS=y
+CONFIG_BT_MSM_SLEEP=y
+CONFIG_MSM_BT_POWER=y
+# CONFIG_WIRELESS_EXT_SYSFS is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_PM is not set
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=8
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBRA_SDIOIF=m
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MSM_LEGACY=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_HS=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_MSM=y
+# CONFIG_HWMON is not set
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_MSM_KGSL=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
+CONFIG_FB_MSM_MDP30=y
+CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_MSM_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MSM_72K=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MSM_72K=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+CONFIG_MMC_MSM_SDC1_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC2_DUMMY52_REQUIRED=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DEBUG=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=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_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7627_defconfig b/arch/arm/configs/msm7627_defconfig
new file mode 100644
index 00000000000..0f9f76f01fb
--- /dev/null
+++ b/arch/arm/configs/msm7627_defconfig
@@ -0,0 +1,299 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=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_BLK_DEV_INITRD=y
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM7X27=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_MSM7X00A_USE_DG_TIMER=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_ONCRPCROUTER=y
+CONFIG_MSM_RMT_STORAGE_CLIENT=y
+# CONFIG_MSM_HW3D is not set
+CONFIG_STRICT_MEMORY_RWX=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT_DETAILS=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_VFP=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_CLS_U32=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_IBS=y
+CONFIG_BT_MSM_SLEEP=y
+CONFIG_MSM_BT_POWER=y
+# CONFIG_WIRELESS_EXT_SYSFS is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_PM is not set
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=8
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBRA_SDIOIF=m
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MSM_LEGACY=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_KEYCHORD=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_HS=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_DCC_TTY=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_MSM=y
+# CONFIG_HWMON is not set
+CONFIG_MSM_KGSL=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
+CONFIG_FB_MSM_MDP30=y
+CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_MSM_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MSM_72K=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MSM_72K=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+CONFIG_MMC_MSM_SDC1_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC2_DUMMY52_REQUIRED=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DEBUG=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=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_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_LATENCYTOP=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
new file mode 100644
index 00000000000..cef8e5422d6
--- /dev/null
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -0,0 +1,315 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="$(KERNEL_LOCAL_VERSION)-perf"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM7X27=y
+CONFIG_MSM_SOC_REV_A=y
+# CONFIG_MACH_MSM7X27_SURF is not set
+# CONFIG_MACH_MSM7X27_FFA is not set
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_MSM7X00A_USE_DG_TIMER=y
+# CONFIG_MSM_JTAG_V7 is not set
+# CONFIG_MSM_FIQ_SUPPORT is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+# CONFIG_MSM_SMD_DEBUG is not set
+# CONFIG_MSM_RESET_MODEM is not set
+# CONFIG_MSM_SMD_NMEA is not set
+# CONFIG_MSM_SMD_QMI is not set
+CONFIG_MSM_ONCRPCROUTER=y
+# CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
+CONFIG_MSM_RMT_STORAGE_CLIENT=y
+# CONFIG_MSM_HW3D is not set
+CONFIG_MSM7X27A_AUDIO=y
+CONFIG_MSM_DMA_TEST=y
+CONFIG_BT_MSM_PINTEST=y
+CONFIG_MSM_RPC_VIBRATOR=y
+CONFIG_PM8XXX_RPC_VIBRATOR=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_CP_ACCESS is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
+CONFIG_BT_MSM_SLEEP=y
+CONFIG_RFKILL=y
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_BLK_DEV is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBRA_SDIOIF=m
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_HS=y
+# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
+CONFIG_DIAG_CHAR=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MSM is not set
+CONFIG_I2C_QUP=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_SX150X=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_MSM=y
+# CONFIG_HWMON is not set
+CONFIG_MARIMBA_CORE=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MT9T013 is not set
+# CONFIG_MT9D112 is not set
+CONFIG_WEBCAM_OV9726=y
+# CONFIG_MT9P012 is not set
+# CONFIG_MT9P012_KM is not set
+CONFIG_MT9E013=y
+# CONFIG_S5K3E2FX is not set
+CONFIG_S5K4E1=y
+CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_IMX072=y
+CONFIG_RADIO_TAVARUA=y
+CONFIG_MSM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
+CONFIG_FB_MSM_MDP30=y
+CONFIG_FB_MSM_MDP303=y
+CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT_PANEL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MSM_72K=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MSM_72K=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_RMNET_SMD_CTL_CHANNEL="DATA40_CNTL"
+CONFIG_RMNET_SMD_DATA_CHANNEL="DATA40"
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+CONFIG_MMC_MSM_CARD_HW_DETECTION=y
+CONFIG_MMC_MSM_SDC2_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC3_SUPPORT=y
+CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
+CONFIG_LEDS_MSM_PDM=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=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_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_FTRACE is not set
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
new file mode 100644
index 00000000000..d2dde46652d
--- /dev/null
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -0,0 +1,308 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="$(KERNEL_LOCAL_VERSION)"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM7X27=y
+CONFIG_MSM_SOC_REV_A=y
+# CONFIG_MACH_MSM7X27_SURF is not set
+# CONFIG_MACH_MSM7X27_FFA is not set
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_MSM7X00A_USE_DG_TIMER=y
+# CONFIG_MSM_JTAG_V7 is not set
+# CONFIG_MSM_FIQ_SUPPORT is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+# CONFIG_MSM_SMD_DEBUG is not set
+# CONFIG_MSM_RESET_MODEM is not set
+# CONFIG_MSM_SMD_NMEA is not set
+# CONFIG_MSM_SMD_QMI is not set
+CONFIG_MSM_ONCRPCROUTER=y
+# CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
+CONFIG_MSM_RMT_STORAGE_CLIENT=y
+# CONFIG_MSM_HW3D is not set
+CONFIG_MSM7X27A_AUDIO=y
+CONFIG_MSM_DMA_TEST=y
+CONFIG_BT_MSM_PINTEST=y
+CONFIG_MSM_RPC_VIBRATOR=y
+CONFIG_PM8XXX_RPC_VIBRATOR=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_CP_ACCESS is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
+CONFIG_BT_MSM_SLEEP=y
+CONFIG_RFKILL=y
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_BLK_DEV is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBRA_SDIOIF=m
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_HS=y
+# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_DCC_TTY=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MSM is not set
+CONFIG_I2C_QUP=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_SX150X=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_MSM=y
+# CONFIG_HWMON is not set
+CONFIG_MARIMBA_CORE=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MT9T013 is not set
+# CONFIG_MT9D112 is not set
+CONFIG_WEBCAM_OV9726=y
+# CONFIG_MT9P012 is not set
+# CONFIG_MT9P012_KM is not set
+CONFIG_MT9E013=y
+# CONFIG_S5K3E2FX is not set
+CONFIG_S5K4E1=y
+CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_IMX072=y
+CONFIG_RADIO_TAVARUA=y
+CONFIG_MSM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
+CONFIG_FB_MSM_MDP30=y
+CONFIG_FB_MSM_MDP303=y
+CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT_PANEL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MSM_72K=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+CONFIG_MMC_MSM_CARD_HW_DETECTION=y
+CONFIG_MMC_MSM_SDC2_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC3_SUPPORT=y
+CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
+CONFIG_LEDS_MSM_PDM=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=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_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_LATENCYTOP=y
+# CONFIG_FTRACE is not set
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
new file mode 100644
index 00000000000..a1cd480c48b
--- /dev/null
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -0,0 +1,369 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-perf"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM7X30=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+# CONFIG_MSM_JTAG_V7 is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG3=y
+CONFIG_MSM_SDIO_DMUX=y
+CONFIG_MSM_SDIO_CMUX=y
+CONFIG_MSM_SDIO_CTL=y
+CONFIG_MSM_ONCRPCROUTER=y
+CONFIG_MSM_RPC_WATCHDOG=y
+CONFIG_MSM_RMT_STORAGE_CLIENT=y
+# CONFIG_MSM_HW3D is not set
+# CONFIG_QSD_AUDIO is not set
+CONFIG_MSM_MEMORY_LOW_POWER_MODE=y
+CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
+CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
+CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
+CONFIG_MSM_STANDALONE_POWER_COLLAPSE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M ip=dhcp"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
+# CONFIG_WIRELESS_EXT_SYSFS is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_PM is not set
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=8
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_MISC_DEVICES=y
+CONFIG_HAPTIC_ISA1200=y
+CONFIG_PMIC8058_UPL=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBRA_SDIOIF=m
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_MSM_RMNET_SDIO=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MSM=y
+CONFIG_TOUCHSCREEN_TSC2007=y
+CONFIG_TOUCHSCREEN_CY8C_TS=y
+CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+CONFIG_BOSCH_BMA150=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_DIAG_CHAR=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
+CONFIG_I2C_SSBI=y
+CONFIG_SPI=y
+CONFIG_SPI_QSD=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_MSM=y
+CONFIG_SENSORS_MSM_ADC=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_MSM_POPMEM=y
+CONFIG_MARIMBA_CORE=y
+CONFIG_MARIMBA_CODEC=y
+CONFIG_TIMPANI_CODEC=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_WEBCAM_OV9726=y
+CONFIG_MT9E013=y
+CONFIG_MSM_GEMINI=y
+CONFIG_RADIO_TAVARUA=y
+CONFIG_MSM_KGSL=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_LOGO=y
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
+CONFIG_FB_MSM_MDP40=y
+CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
+CONFIG_FB_MSM_HDMI_ADV7520_PANEL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_MSM7KV2_SOC=y
+CONFIG_SND_MVS_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MSM_72K=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MSM_72K=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_RMNET_SMD_CTL_CHANNEL="DATA40_CNTL"
+CONFIG_RMNET_SMD_DATA_CHANNEL="DATA40"
+CONFIG_RMNET_SDIO_SMD_DATA_CHANNEL=""
+CONFIG_USB_MSM_ACA=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+CONFIG_MMC_MSM_CARD_HW_DETECTION=y
+# CONFIG_MMC_MSM_SDC1_SUPPORT is not set
+CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
+CONFIG_MMC_MSM_SDC2_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC3_SUPPORT=y
+CONFIG_MMC_MSM_SDC3_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC4_SUPPORT=y
+# CONFIG_LEDS_MSM_PMIC is not set
+CONFIG_LEDS_PMIC8058=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DEBUG=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=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_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=m
+CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
new file mode 100644
index 00000000000..54f1a44e24c
--- /dev/null
+++ b/arch/arm/configs/msm7630_defconfig
@@ -0,0 +1,358 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=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_BLK_DEV_INITRD=y
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM7X30=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG3=y
+CONFIG_MSM_SDIO_DMUX=y
+CONFIG_MSM_SDIO_CMUX=y
+CONFIG_MSM_SDIO_CTL=y
+CONFIG_MSM_ONCRPCROUTER=y
+CONFIG_MSM_RPC_WATCHDOG=y
+CONFIG_MSM_RMT_STORAGE_CLIENT=y
+# CONFIG_MSM_HW3D is not set
+# CONFIG_QSD_AUDIO is not set
+CONFIG_MSM_MEMORY_LOW_POWER_MODE=y
+CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION=y
+CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN=y
+CONFIG_MSM_IDLE_WAIT_ON_MODEM=2000
+CONFIG_STRICT_MEMORY_RWX=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="init=/sbin/init root=/dev/ram rw initrd=0x11000000,16M console=ttyDCC0 mem=88M ip=dhcp"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
+# CONFIG_WIRELESS_EXT_SYSFS is not set
+CONFIG_RFKILL=y
+# CONFIG_RFKILL_PM is not set
+CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=8
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_MISC_DEVICES=y
+CONFIG_HAPTIC_ISA1200=y
+CONFIG_PMIC8058_UPL=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBRA_SDIOIF=m
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_MSM_RMNET_SDIO=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MSM=y
+CONFIG_TOUCHSCREEN_TSC2007=y
+CONFIG_TOUCHSCREEN_CY8C_TS=y
+CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=y
+CONFIG_BOSCH_BMA150=y
+# CONFIG_SERIO is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_HS=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_DCC_TTY=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
+CONFIG_I2C_SSBI=y
+CONFIG_SPI=y
+CONFIG_SPI_QSD=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_BATTERY_MSM=y
+CONFIG_SENSORS_MSM_ADC=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_MSM_POPMEM=y
+CONFIG_MARIMBA_CORE=y
+CONFIG_MARIMBA_CODEC=y
+CONFIG_TIMPANI_CODEC=y
+CONFIG_MSM_KGSL=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_LOGO=y
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
+CONFIG_FB_MSM_MDP40=y
+CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM=y
+CONFIG_FB_MSM_HDMI_ADV7520_PANEL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_MSM7KV2_SOC=y
+CONFIG_SND_MVS_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MSM_72K=y
+CONFIG_USB_MSM_ACA=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+CONFIG_MMC_MSM_CARD_HW_DETECTION=y
+# CONFIG_MMC_MSM_SDC1_SUPPORT is not set
+CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
+CONFIG_MMC_MSM_SDC2_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC3_SUPPORT=y
+CONFIG_MMC_MSM_SDC3_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC4_SUPPORT=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DEBUG=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=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_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_YAFFS_FS=y
+CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_PROVE_LOCKING=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=m
+CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
new file mode 100644
index 00000000000..3423b729ba9
--- /dev/null
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -0,0 +1,427 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-perf"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=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_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM8X60=y
+CONFIG_MACH_MSM8X60_RUMI3=y
+CONFIG_MACH_MSM8X60_SIM=y
+CONFIG_MACH_MSM8X60_SURF=y
+CONFIG_MACH_MSM8X60_FFA=y
+CONFIG_MACH_MSM8X60_FLUID=y
+CONFIG_MACH_MSM8X60_FUSION=y
+CONFIG_MACH_MSM8X60_FUSN_FFA=y
+CONFIG_MSM7X00A_USE_DG_TIMER=y
+CONFIG_MSM7X00A_SLEEP_MODE_POWER_COLLAPSE=y
+CONFIG_MSM7X00A_IDLE_SLEEP_WAIT_FOR_INTERRUPT=y
+# CONFIG_MSM_JTAG_V7 is not set
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SDIO_DMUX=y
+# CONFIG_MSM_RESET_MODEM is not set
+# CONFIG_MSM_SMD_NMEA is not set
+CONFIG_MSM_SDIO_TTY=y
+# CONFIG_MSM_SMD_QMI is not set
+CONFIG_MSM_SDIO_CMUX=y
+CONFIG_MSM_DSPS=y
+CONFIG_MSM_SDIO_CTL=y
+CONFIG_MSM_ONCRPCROUTER=y
+# CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
+# CONFIG_MSM_RPCSERVER_WATCHDOG is not set
+# CONFIG_MSM_RPCSERVER_HANDSET is not set
+CONFIG_MSM_RMT_STORAGE_CLIENT=y
+CONFIG_MSM_SDIO_SMEM=y
+# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_SECURE_PIL=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_RPM_LOG=y
+CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_WATCHDOG=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ETM=y
+CONFIG_MSM_SLEEP_STATS=y
+CONFIG_MSM_GSBI9_UART=y
+CONFIG_STRICT_MEMORY_RWX=y
+CONFIG_KSAPI=m
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_CP_ACCESS=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
+# CONFIG_WIRELESS_EXT_SYSFS is not set
+CONFIG_RFKILL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_MISC_DEVICES=y
+CONFIG_UID_STAT=y
+CONFIG_TSIF=m
+CONFIG_TSIF_CHRDEV=m
+CONFIG_HAPTIC_ISA1200=y
+CONFIG_PMIC8058_VIBRATOR=y
+CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8058_XOADC=y
+CONFIG_PMIC8058_MISC=y
+CONFIG_TZCOM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBRA_SDIOIF=m
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_MSM_RMNET_SDIO=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_INPUT_KEYRESET=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_MATRIX=y
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
+CONFIG_TOUCHSCREEN_CY8C_TS=y
+CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_PMIC8058_PWRKEY=y
+CONFIG_PMIC8058_OTHC=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MSM is not set
+CONFIG_I2C_QUP=y
+CONFIG_I2C_SSBI=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_SX150X=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_BATTERY_MSM is not set
+CONFIG_BATTERY_MSM8X60=y
+CONFIG_PM8058_CHARGER=y
+CONFIG_ISL9519_CHARGER=y
+CONFIG_SMB137B_CHARGER=y
+CONFIG_BATTERY_BQ27520=y
+CONFIG_BATTERY_BQ27541=y
+CONFIG_SENSORS_MSM_ADC=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_PM8901=y
+CONFIG_THERMAL_PM8058=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MARIMBA_CORE=y
+CONFIG_TIMPANI_CODEC=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_WEBCAM_OV9726=y
+CONFIG_MT9E013=y
+CONFIG_MSM_GEMINI=y
+CONFIG_RADIO_TAVARUA=y
+CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
+CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
+CONFIG_FB_MSM_MDP40=y
+CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_OVERLAY_WRITEBACK=y
+CONFIG_FB_MSM_LCDC_PANEL_AUTO_DETECT=y
+CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_HID_APPLE=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MSM_72K=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MSM_72K=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_RMNET_SMD_CTL_CHANNEL="DATA40_CNTL"
+CONFIG_RMNET_SMD_DATA_CHANNEL="DATA40"
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+CONFIG_MMC_MSM_CARD_HW_DETECTION=y
+CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
+CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
+CONFIG_MMC_MSM_SDC2_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC3_SUPPORT=y
+CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
+CONFIG_MMC_MSM_SDC4_SUPPORT=y
+CONFIG_MMC_MSM_SDC4_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC5_SUPPORT=y
+CONFIG_MMC_MSM_SDC5_DUMMY52_REQUIRED=y
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_MSM_PMIC is not set
+CONFIG_LEDS_PMIC8058=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_SLEEP=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_PM8058=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=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_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_CIFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_STACKTRACE is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
new file mode 100644
index 00000000000..7b334617ac8
--- /dev/null
+++ b/arch/arm/configs/msm8660_defconfig
@@ -0,0 +1,425 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=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_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_ASHMEM=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_DEFAULT_DEADLINE=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM8X60=y
+CONFIG_MACH_MSM8X60_RUMI3=y
+CONFIG_MACH_MSM8X60_SIM=y
+CONFIG_MACH_MSM8X60_SURF=y
+CONFIG_MACH_MSM8X60_FFA=y
+CONFIG_MACH_MSM8X60_FLUID=y
+CONFIG_MSM7X00A_USE_DG_TIMER=y
+CONFIG_MSM7X00A_SLEEP_MODE_POWER_COLLAPSE=y
+CONFIG_MSM7X00A_IDLE_SLEEP_WAIT_FOR_INTERRUPT=y
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+# CONFIG_MSM_RESET_MODEM is not set
+# CONFIG_MSM_SMD_NMEA is not set
+# CONFIG_MSM_SMD_QMI is not set
+CONFIG_MSM_DSPS=y
+CONFIG_MSM_ONCRPCROUTER=y
+# CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
+# CONFIG_MSM_RPCSERVER_WATCHDOG is not set
+# CONFIG_MSM_RPCSERVER_HANDSET is not set
+CONFIG_MSM_RMT_STORAGE_CLIENT=y
+# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_SECURE_PIL=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_RPM_LOG=y
+CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_WATCHDOG=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ETM=y
+CONFIG_MSM_SLEEP_STATS=y
+CONFIG_MSM_GSBI9_UART=y
+CONFIG_STRICT_MEMORY_RWX=y
+CONFIG_KSAPI=m
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0x10000000
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_SFQ=y
+CONFIG_NET_SCH_TBF=y
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_BASIC=y
+CONFIG_NET_CLS_TCINDEX=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_IBS=y
+# CONFIG_WIRELESS_EXT_SYSFS is not set
+CONFIG_RFKILL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_MISC_DEVICES=y
+CONFIG_KERNEL_DEBUGGER_CORE=y
+CONFIG_UID_STAT=y
+CONFIG_TSIF=m
+CONFIG_TSIF_CHRDEV=m
+CONFIG_HAPTIC_ISA1200=y
+CONFIG_PMIC8058_VIBRATOR=y
+CONFIG_PMIC8058_UPL=y
+CONFIG_PMIC8058_XOADC=y
+CONFIG_PMIC8058_MISC=y
+CONFIG_TZCOM=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_LIBRA_SDIOIF=m
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_INPUT_KEYRESET=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_MATRIX=y
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
+CONFIG_TOUCHSCREEN_CY8C_TS=y
+CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_PMIC8058_PWRKEY=y
+CONFIG_PMIC8058_OTHC=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
+CONFIG_DCC_TTY=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MSM is not set
+CONFIG_I2C_QUP=y
+CONFIG_I2C_SSBI=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_SX150X=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_BATTERY_MSM is not set
+CONFIG_BATTERY_MSM8X60=y
+CONFIG_PM8058_CHARGER=y
+CONFIG_ISL9519_CHARGER=y
+CONFIG_SMB137B_CHARGER=y
+CONFIG_BATTERY_BQ27520=y
+CONFIG_BATTERY_BQ27541=y
+CONFIG_SENSORS_MSM_ADC=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_PM8901=y
+CONFIG_THERMAL_PM8058=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MARIMBA_CORE=y
+CONFIG_TIMPANI_CODEC=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_WEBCAM_OV9726=y
+CONFIG_MT9E013=y
+CONFIG_MSM_GEMINI=y
+CONFIG_RADIO_TAVARUA=y
+CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
+CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES=y
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_TRIPLE_BUFFER=y
+CONFIG_FB_MSM_MDP40=y
+CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_OVERLAY_WRITEBACK=y
+CONFIG_FB_MSM_LCDC_PANEL_AUTO_DETECT=y
+CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_MSM_8x60_VOIP=y
+CONFIG_HID_APPLE=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MSM_72K=y
+CONFIG_USB_MSM_ACA=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_EMBEDDED_SDIO=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SDIO_SUPPORT=y
+CONFIG_MMC_MSM_CARD_HW_DETECTION=y
+CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
+CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
+CONFIG_MMC_MSM_SDC2_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC3_SUPPORT=y
+CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
+CONFIG_MMC_MSM_SDC4_SUPPORT=y
+CONFIG_MMC_MSM_SDC4_DUMMY52_REQUIRED=y
+CONFIG_MMC_MSM_SDC5_SUPPORT=y
+CONFIG_MMC_MSM_SDC5_DUMMY52_REQUIRED=y
+CONFIG_LEDS_GPIO=y
+# CONFIG_LEDS_MSM_PMIC is not set
+CONFIG_LEDS_PMIC8058=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_SLEEP=y
+CONFIG_SWITCH=y
+CONFIG_SWITCH_GPIO=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_PM8058=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=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_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_CIFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_PROVE_LOCKING=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_SG=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=m
+CONFIG_CRYPTO_DEV_QCEDEV=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
new file mode 100644
index 00000000000..73d9f9d1ca5
--- /dev/null
+++ b/arch/arm/configs/msm8960_defconfig
@@ -0,0 +1,365 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=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_FAIR_GROUP_SCHED is not set
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ASHMEM=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_ARCH_MSM=y
+CONFIG_ARCH_MSM8960=y
+CONFIG_MACH_MSM8960_SIM=y
+CONFIG_MACH_MSM8960_RUMI3=y
+CONFIG_MACH_MSM8960_CDP=y
+CONFIG_MACH_MSM8960_MTP=y
+CONFIG_MACH_MSM8960_FLUID=y
+# CONFIG_MSM_STACKED_MEMORY is not set
+CONFIG_KERNEL_PMEM_EBI_REGION=y
+# CONFIG_MSM_JTAG_V7 is not set
+# CONFIG_MSM_FIQ_SUPPORT is not set
+# CONFIG_MSM_PROC_COMM is not set
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_DSPS=y
+CONFIG_MSM_IPC_ROUTER=y
+# CONFIG_MSM_HW3D is not set
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_MODEM_8960=y
+CONFIG_MSM_WATCHDOG=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_SMP_ON_UP is not set
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_WAKELOCK=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_OWNER=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+CONFIG_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_BT=y
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=y
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=y
+CONFIG_BT_HCISMD=m
+CONFIG_RFKILL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_MISC_DEVICES=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
+CONFIG_KS8851=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_WCNSS_WLAN=m
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_MODE_SLIP6=y
+# CONFIG_MSM_RMNET is not set
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVBUG=m
+CONFIG_KEYBOARD_PMIC8XXX=y
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_CYTTSP_I2C=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_PMIC8XXX_PWRKEY=y
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_HS=y
+# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
+CONFIG_SERIAL_MSM_HSL=y
+CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
+CONFIG_HW_RANDOM=y
+CONFIG_DCC_TTY=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MSM is not set
+CONFIG_I2C_QUP=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SLIMBUS=y
+CONFIG_SLIMBUS_MSM_CTRL=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_SX150X=y
+CONFIG_POWER_SUPPLY=y
+# CONFIG_BATTERY_MSM is not set
+CONFIG_PM8921_CHARGER=y
+CONFIG_PM8921_BMS=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_PM8XXX=y
+CONFIG_MFD_PM8921_CORE=y
+CONFIG_MFD_PM8921_ADC=y
+CONFIG_MFD_PM8XXX_BATT_ALARM=y
+CONFIG_WCD9310_CODEC=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_MSM_CAMERA_V4L2=y
+CONFIG_MSM_GEMINI=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=m
+CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+# CONFIG_FB_MSM_BACKLIGHT is not set
+CONFIG_FB_MSM_MDP40=y
+CONFIG_FB_MSM_OVERLAY=y
+CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT_PANEL=y
+CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_QDSP6=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_CI13XXX_MSM=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_ANDROID_RMNET_CTRL_SMD=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_CARD_HW_DETECTION=y
+CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y
+# CONFIG_MMC_MSM_SDC2_SUPPORT is not set
+CONFIG_MMC_MSM_SDC3_SUPPORT=y
+CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_LEDS_PM8XXX=y
+# CONFIG_LEDS_MSM_PMIC is not set
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+# CONFIG_RTC_DRV_MSM is not set
+CONFIG_RTC_DRV_PM8XXX=y
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOGGER=y
+CONFIG_ANDROID_RAM_CONSOLE=y
+CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_MSM_SSBI=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_BAMDMA=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_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_CIFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_USER=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEV_QCRYPTO=m
+CONFIG_CRYPTO_DEV_QCE=m
+CONFIG_CRYPTO_DEV_QCEDEV=m
+CONFIG_CRC_CCITT=y
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 1252a2675ca..584fe0b6fcd 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -87,6 +87,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.
@@ -107,6 +122,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 *);
};
@@ -133,6 +150,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
@@ -153,6 +172,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
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index cd4458f6417..cb47d28cbe1 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -8,6 +8,7 @@
#define CPUID_CACHETYPE 1
#define CPUID_TCM 2
#define CPUID_TLBTYPE 3
+#define CPUID_MPIDR 5
#define CPUID_EXT_PFR0 "c1, 0"
#define CPUID_EXT_PFR1 "c1, 1"
@@ -70,6 +71,11 @@ static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void)
return read_cpuid(CPUID_TCM);
}
+static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
+{
+ return read_cpuid(CPUID_MPIDR);
+}
+
/*
* Intel's XScale3 core supports some v6 features (supersections, L2)
* but advertises itself as v5 as it does not support the v6 ISA. For
diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h
index b2deda18154..5c6b9a3c5df 100644
--- a/arch/arm/include/asm/delay.h
+++ b/arch/arm/include/asm/delay.h
@@ -8,7 +8,7 @@
#include /* HZ */
-extern void __delay(int loops);
+extern void __delay(unsigned long loops);
/*
* This function intentionally does not exist; if you see references to
@@ -40,5 +40,8 @@ extern void __const_udelay(unsigned long);
__const_udelay((n) * ((2199023U*HZ)>>11))) : \
__udelay(n))
+extern void set_delay_fn(void (*fn)(unsigned long));
+extern void read_current_timer_delay_loop(unsigned long loops);
+
#endif /* defined(_ARM_DELAY_H) */
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 4fff837363e..6f48921b08d 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -172,6 +172,46 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size,
{
}
+
+/*
+ * 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
+ if (arch_is_coherent())
+ 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
+ if (arch_is_coherent())
+ dmb();
+ else
+ barrier();
+#endif
+}
+
/**
* dma_alloc_coherent - allocate consistent memory for DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -385,6 +425,58 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
return addr;
}
+/**
+ * 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));
+
+ if (!arch_is_coherent())
+ ___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() && !arch_is_coherent()
+ && dir != DMA_TO_DEVICE)
+ /*
+ * Treat DMA_BIDIRECTIONAL and DMA_FROM_DEVICE
+ * identically: invalidate
+ */
+ ___dma_single_cpu_to_dev(virtual_addr,
+ size, DMA_FROM_DEVICE);
+}
+
/**
* dma_map_page - map a portion of a page for streaming DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff --git a/arch/arm/include/asm/domain.h b/arch/arm/include/asm/domain.h
index af18ceaacf5..0854849e4d9 100644
--- a/arch/arm/include/asm/domain.h
+++ b/arch/arm/include/asm/domain.h
@@ -2,6 +2,7 @@
* arch/arm/include/asm/domain.h
*
* Copyright (C) 1999 Russell King.
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -27,8 +28,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
@@ -56,6 +62,17 @@
#ifndef __ASSEMBLY__
#ifdef CONFIG_CPU_USE_DOMAINS
+#ifdef CONFIG_EMULATE_DOMAIN_MANAGER_V7
+void emulate_domain_manager_set(u32 domain);
+int emulate_domain_manager_data_abort(u32 dfsr, u32 dfar);
+int emulate_domain_manager_prefetch_abort(u32 ifsr, u32 ifar);
+void emulate_domain_manager_switch_mm(
+ unsigned long pgd_phys,
+ struct mm_struct *mm,
+ void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *));
+
+#define set_domain(x) emulate_domain_manager_set(x)
+#else
#define set_domain(x) \
do { \
__asm__ __volatile__( \
@@ -63,6 +80,7 @@
: : "r" (x)); \
isb(); \
} while (0)
+#endif
#define modify_domain(dom,type) \
do { \
diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index 16bd4803158..1fc2f49a954 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -59,6 +59,7 @@
/* Registers shifts and masks */
#define L2X0_CACHE_ID_PART_MASK (0xf << 6)
#define L2X0_CACHE_ID_PART_L210 (1 << 6)
+#define L2X0_CACHE_ID_PART_L220 (2 << 6)
#define L2X0_CACHE_ID_PART_L310 (3 << 6)
#define L2X0_AUX_CTRL_MASK 0xc0000fff
@@ -71,9 +72,13 @@
#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28
#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29
#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30
+#define L2X0_AUX_CTRL_EVNT_MON_BUS_EN_SHIFT 20
#ifndef __ASSEMBLY__
extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
+extern void l2x0_suspend(void);
+extern void l2x0_resume(int collapsed);
+extern void l2x0_cache_sync(void);
#endif
#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 0691f9dcc50..27adea340a5 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -41,6 +41,8 @@ void gic_secondary_init(unsigned int);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
void gic_enable_ppi(unsigned int);
+bool gic_is_spi_pending(unsigned int irq);
+void gic_clear_spi_pending(unsigned int irq);
#endif
#endif
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index d66605dea55..761c29e01ee 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -248,6 +248,8 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
#define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
+#define ioremap_strongly_ordered(cookie, size) __arch_ioremap(cookie, size, \
+ MT_DEVICE_STRONGLY_ORDERED)
#define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
#define iounmap __arch_iounmap
diff --git a/arch/arm/include/asm/mach/flash.h b/arch/arm/include/asm/mach/flash.h
index 4ca69fe2c85..36938ea24a3 100644
--- a/arch/arm/include/asm/mach/flash.h
+++ b/arch/arm/include/asm/mach/flash.h
@@ -17,6 +17,7 @@ struct mtd_info;
* 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
@@ -28,6 +29,7 @@ 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);
diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h
index d2fedb5aeb1..02fa7534bcb 100644
--- a/arch/arm/include/asm/mach/map.h
+++ b/arch/arm/include/asm/mach/map.h
@@ -29,6 +29,10 @@ struct map_desc {
#define MT_MEMORY_NONCACHED 11
#define MT_MEMORY_DTCM 12
#define MT_MEMORY_ITCM 13
+#define MT_DEVICE_STRONGLY_ORDERED 14
+#define MT_MEMORY_R 15
+#define MT_MEMORY_RW 16
+#define MT_MEMORY_RX 17
#ifdef CONFIG_MMU
extern void iotable_init(struct map_desc *, int);
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index bca864ac945..d439160a51c 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -7,6 +7,12 @@
#include
#include
#include
+#include
+
+#define SDC_DAT1_DISABLE 0
+#define SDC_DAT1_ENABLE 1
+#define SDC_DAT1_ENWAKE 2
+#define SDC_DAT1_DISWAKE 3
struct embedded_sdio_data {
struct sdio_cis cis;
@@ -15,6 +21,91 @@ struct embedded_sdio_data {
int num_funcs;
};
+/* This structure keeps information per regulator */
+struct msm_mmc_reg_data {
+ /* voltage regulator handle */
+ struct regulator *reg;
+ /* regulator name */
+ const char *name;
+ /* voltage level to be set */
+ unsigned int level;
+ /* Load values for low power and high power mode */
+ unsigned int lpm_uA;
+ unsigned int hpm_uA;
+ /*
+ * is set voltage supported for this regulator?
+ * false => set voltage is not supported
+ * true => set voltage is supported
+ */
+ bool set_voltage_sup;
+ /* is this regulator enabled? */
+ bool is_enabled;
+ /* is this regulator needs to be always on? */
+ bool always_on;
+ /* is low power mode setting required for this regulator? */
+ bool lpm_sup;
+};
+
+/*
+ * This structure keeps information for all the
+ * regulators required for a SDCC slot.
+ */
+struct msm_mmc_slot_reg_data {
+ struct msm_mmc_reg_data *vdd_data; /* keeps VDD/VCC regulator info */
+ struct msm_mmc_reg_data *vccq_data; /* keeps VCCQ regulator info */
+ struct msm_mmc_reg_data *vddp_data; /* keeps VDD Pad regulator info */
+};
+
+struct msm_mmc_gpio {
+ u32 no;
+ const char *name;
+ bool is_always_on;
+ bool is_enabled;
+};
+
+struct msm_mmc_gpio_data {
+ struct msm_mmc_gpio *gpio;
+ u8 size;
+};
+
+struct msm_mmc_pad_pull {
+ enum msm_tlmm_pull_tgt no;
+ u32 val;
+};
+
+struct msm_mmc_pad_pull_data {
+ struct msm_mmc_pad_pull *on;
+ struct msm_mmc_pad_pull *off;
+ u8 size;
+};
+
+struct msm_mmc_pad_drv {
+ enum msm_tlmm_hdrive_tgt no;
+ u32 val;
+};
+
+struct msm_mmc_pad_drv_data {
+ struct msm_mmc_pad_drv *on;
+ struct msm_mmc_pad_drv *off;
+ u8 size;
+};
+
+struct msm_mmc_pad_data {
+ struct msm_mmc_pad_pull_data *pull;
+ struct msm_mmc_pad_drv_data *drv;
+};
+
+struct msm_mmc_pin_data {
+ /*
+ * = 1 if controller pins are using gpios
+ * = 0 if controller has dedicated MSM pads
+ */
+ u8 is_gpio;
+ u8 cfg_sts;
+ struct msm_mmc_gpio_data *gpio_data;
+ struct msm_mmc_pad_data *pad_data;
+};
+
struct mmc_platform_data {
unsigned int ocr_mask; /* available voltages */
int built_in; /* built-in device flag */
@@ -23,6 +114,35 @@ struct mmc_platform_data {
unsigned int (*status)(struct device *);
struct embedded_sdio_data *embedded_sdio;
int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
+ /*
+ * XPC controls the maximum current in the
+ * default speed mode of SDXC card.
+ */
+ unsigned int xpc_cap;
+ /* Supported UHS-I Modes */
+ unsigned int uhs_caps;
+ void (*sdio_lpm_gpio_setup)(struct device *, unsigned int);
+ unsigned int status_irq;
+ unsigned int status_gpio;
+ unsigned int sdiowakeup_irq;
+ unsigned long irq_flags;
+ unsigned long mmc_bus_width;
+ int (*wpswitch) (struct device *);
+ int dummy52_required;
+ unsigned int msmsdcc_fmin;
+ unsigned int msmsdcc_fmid;
+ unsigned int msmsdcc_fmax;
+ bool nonremovable;
+ bool pclk_src_dfab;
+ int (*cfg_mpm_sdiowakeup)(struct device *, unsigned);
+ bool sdcc_v4_sup;
+ unsigned int wpswitch_gpio;
+ unsigned char wpswitch_polarity;
+ struct msm_mmc_slot_reg_data *vreg_data;
+ int is_sdio_al_client;
+ unsigned int *sup_clk_table;
+ unsigned char sup_clk_cnt;
+ struct msm_mmc_pin_data *pin_data;
};
#endif
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index af44a8fb348..9ecd2dc0b73 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -299,6 +299,13 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#define arch_is_coherent() 0
#endif
+/*
+ * Set if the architecture speculatively fetches data into cache.
+ */
+#ifndef arch_has_speculative_dfetch
+#define arch_has_speculative_dfetch() 0
+#endif
+
#endif
#include
diff --git a/arch/arm/include/asm/mutex.h b/arch/arm/include/asm/mutex.h
index 93226cf23ae..fd3f17ef94a 100644
--- a/arch/arm/include/asm/mutex.h
+++ b/arch/arm/include/asm/mutex.h
@@ -41,6 +41,8 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
__res |= __ex_flag;
if (unlikely(__res != 0))
fail_fn(count);
+ else
+ smp_rmb();
}
static inline int
@@ -61,6 +63,9 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
__res |= __ex_flag;
if (unlikely(__res != 0))
__res = fail_fn(count);
+ else
+ smp_rmb();
+
return __res;
}
@@ -74,6 +79,7 @@ __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
{
int __ex_flag, __res, __orig;
+ smp_wmb();
__asm__ (
"ldrex %0, [%3] \n\t"
@@ -119,6 +125,8 @@ __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
: "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag)
: "r" (&count->counter)
: "cc", "memory" );
+ if (__orig)
+ smp_rmb();
return __orig;
}
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index ac75d084888..ac118163c51 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -201,6 +201,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
#endif /* !__ASSEMBLY__ */
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index c4aa4e8c6af..0e1fd190105 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -24,6 +24,9 @@ enum arm_perf_pmu_ids {
ARM_PERF_PMU_ID_V6MP,
ARM_PERF_PMU_ID_CA8,
ARM_PERF_PMU_ID_CA9,
+ ARM_PERF_PMU_ID_SCORPION,
+ ARM_PERF_PMU_ID_SCORPIONMP,
+ ARM_PERF_PMU_ID_KRAIT,
ARM_NUM_PMU_IDS,
};
diff --git a/arch/arm/include/asm/perftypes.h b/arch/arm/include/asm/perftypes.h
new file mode 100644
index 00000000000..8d21dcd121c
--- /dev/null
+++ b/arch/arm/include/asm/perftypes.h
@@ -0,0 +1,33 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+** perftypes.h
+** DESCRIPTION
+** ksapi.ko function hooks header file
+*/
+
+#ifndef __PERFTYPES_H__
+#define __PERFTYPES_H__
+
+typedef void (*VPVF)(void);
+typedef void (*VPULF)(unsigned long);
+typedef void (*VPULULF)(unsigned long, unsigned long);
+
+extern VPVF pp_interrupt_out_ptr;
+extern VPVF pp_interrupt_in_ptr;
+extern VPULF pp_process_remove_ptr;
+extern void perf_mon_interrupt_in(void);
+extern void perf_mon_interrupt_out(void);
+
+#endif
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 5750704e027..cbb2f45f84d 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -22,7 +22,9 @@
#include
#include
+#include
#include
+#include
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
@@ -232,16 +234,30 @@ extern pgprot_t pgprot_kernel;
#define pgprot_writecombine(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
+#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__ */
@@ -469,8 +485,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
+#ifndef HAS_ARCH_IO_REMAP_PFN_RANGE
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
- remap_pfn_range(vma, from, pfn, size, prot)
+ remap_pfn_range(vma,from,pfn,size,prot)
+#else
+extern int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot);
+#define io_remap_pfn_range(vma,from,pfn,size,prot) \
+ arch_io_remap_pfn_range(vma,from,pfn,size,prot)
+#endif
+
#define pgtable_cache_init() do { } while (0)
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index 7544ce6b481..48d148dc7da 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -16,6 +16,7 @@
enum arm_pmu_type {
ARM_PMU_DEVICE_CPU = 0,
+ ARM_PMU_DEVICE_L2 = 1,
ARM_NUM_PMU_DEVICES,
};
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index b2d9df5667a..12bc94d26f1 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -29,6 +29,8 @@
#define STACK_TOP_MAX TASK_SIZE
#endif
+extern unsigned int boot_reason;
+
struct debug_info {
#ifdef CONFIG_HAVE_HW_BREAKPOINT
struct perf_event *hbp[ARM_MAX_HBP_SLOTS];
diff --git a/arch/arm/include/asm/remote_spinlock.h b/arch/arm/include/asm/remote_spinlock.h
new file mode 100644
index 00000000000..702b6696131
--- /dev/null
+++ b/arch/arm/include/asm/remote_spinlock.h
@@ -0,0 +1,18 @@
+/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef __ASM_REMOTE_SPINLOCK_H
+#define __ASM_REMOTE_SPINLOCK_H
+
+#include
+
+#endif /* __ASM_REMOTE_SPINLOCK_H */
diff --git a/arch/arm/include/asm/setup.h b/arch/arm/include/asm/setup.h
index ee2ad8ae07a..950665dfcc6 100644
--- a/arch/arm/include/asm/setup.h
+++ b/arch/arm/include/asm/setup.h
@@ -37,6 +37,15 @@ struct tag_core {
/* it is allowed to have multiple ATAG_MEM nodes */
#define ATAG_MEM 0x54410002
+/* it is allowed to have multiple ATAG_MEM_RESERVED nodes */
+/* these indicate places where hotpluggable memory is present */
+/* which are not active during boot */
+#define ATAG_MEM_RESERVED 0x5441000A
+/* it is allowed to have multiple ATAG_MEM_LOW_POWER nodes */
+/* these indicate memory which can be put in a low power state */
+#define ATAG_MEM_LOW_POWER 0x5441000B
+/* these indicate memory which can be reclaimed from OSBL memory after bootup */
+#define ATAG_MEM_OSBL 0x5441000C
struct tag_mem32 {
__u32 size;
@@ -221,6 +230,18 @@ extern int arm_add_memory(phys_addr_t start, unsigned long size);
extern void early_print(const char *str, ...);
extern void dump_machine_table(void);
+/*
+ * Early command line parameters.
+ */
+struct early_params {
+ const char *arg;
+ void (*fn)(char **p);
+};
+
+#define __early_param(name,fn) \
+static struct early_params __early_##fn __used \
+__attribute__((__section__(".early_param.init"))) = { name, fn }
+
#endif /* __KERNEL__ */
#endif
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index 832888d0c20..d3808b5eeed 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -69,6 +69,8 @@
#define __exception_irq_entry __exception
#endif
+void cpu_idle_wait(void);
+
struct thread_info;
struct task_struct;
@@ -141,7 +143,7 @@ extern unsigned int user_debug;
#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
: : "r" (0) : "memory")
#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
- : : "r" (0) : "memory")
+ : : "r" (0) : "memory")
#elif defined(CONFIG_CPU_FA526)
#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
: : "r" (0) : "memory")
diff --git a/arch/arm/include/asm/tlbflush.h b/arch/arm/include/asm/tlbflush.h
index d2005de383b..ab2a488ae77 100644
--- a/arch/arm/include/asm/tlbflush.h
+++ b/arch/arm/include/asm/tlbflush.h
@@ -433,7 +433,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
if (tlb_flag(TLB_V6_I_PAGE))
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
if (tlb_flag(TLB_V7_UIS_PAGE))
-#ifdef CONFIG_ARM_ERRATA_720789
+#if defined(CONFIG_ARM_ERRATA_720789) || defined(CONFIG_ARCH_MSM8X60)
asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (uaddr & PAGE_MASK) : "cc");
#else
asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
@@ -480,7 +480,11 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
if (tlb_flag(TLB_V6_I_PAGE))
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
if (tlb_flag(TLB_V7_UIS_PAGE))
+#ifdef CONFIG_ARCH_MSM8X60
+ asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (kaddr) : "cc");
+#else
asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
+#endif
if (tlb_flag(TLB_BTB)) {
/* flush the branch target cache */
diff --git a/arch/arm/include/asm/vfp.h b/arch/arm/include/asm/vfp.h
index f4ab34fd4f7..cb3ea0845ff 100644
--- a/arch/arm/include/asm/vfp.h
+++ b/arch/arm/include/asm/vfp.h
@@ -21,7 +21,7 @@
#define FPSID_FORMAT_MASK (0x3 << FPSID_FORMAT_BIT)
#define FPSID_NODOUBLE (1<<20)
#define FPSID_ARCH_BIT (16)
-#define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT)
+#define FPSID_ARCH_MASK (0x7F << FPSID_ARCH_BIT)
#define FPSID_PART_BIT (8)
#define FPSID_PART_MASK (0xFF << FPSID_PART_BIT)
#define FPSID_VARIANT_BIT (4)
@@ -82,3 +82,8 @@
#define VFPOPDESC_UNUSED_BIT (24)
#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT)
#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK))
+
+#ifndef __ASSEMBLY__
+int vfp_flush_context(void);
+void vfp_reinit(void);
+#endif
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index acca35aebe2..263eaaf3f26 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -52,10 +52,6 @@ extern void fpundefinstr(void);
EXPORT_SYMBOL(__backtrace);
- /* platform dependent support */
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__const_udelay);
-
/* networking */
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_from_user);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 2cd00764016..af0a86c2688 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -734,7 +734,14 @@ ENTRY(__switch_to)
ldr r7, [r7, #TSK_STACK_CANARY]
#endif
#ifdef CONFIG_CPU_USE_DOMAINS
+#ifdef CONFIG_EMULATE_DOMAIN_MANAGER_V7
+ stmdb r13!, {r0-r3, lr}
+ mov r0, r6
+ bl emulate_domain_manager_set
+ ldmia r13!, {r0-r3, lr}
+#else
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
+#endif
#endif
mov r5, r0
add r4, r2, #TI_CPU_SAVE
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 278c1b0ebb2..f379b0411fc 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -362,10 +362,17 @@ __enable_mmu:
#ifdef CONFIG_CPU_ICACHE_DISABLE
bic r0, r0, #CR_I
#endif
- mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
+#ifdef CONFIG_EMULATE_DOMAIN_MANAGER_V7
+ mov r5, #(domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \
+ domain_val(DOMAIN_KERNEL, DOMAIN_CLIENT) | \
+ domain_val(DOMAIN_TABLE, DOMAIN_CLIENT) | \
+ domain_val(DOMAIN_IO, DOMAIN_CLIENT))
+#else
+ mov r5, #(domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
- domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
+ domain_val(DOMAIN_TABLE, DOMAIN_CLIENT) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
+#endif
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
b __turn_mmu_on
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 87acc25d7a3..951eb8d334d 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -833,6 +833,18 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
return ret;
}
+static void reset_brps_reserved_reg(int n)
+{
+ int i;
+
+ /* we must also reset any reserved registers. */
+ for (i = 0; i < n; ++i) {
+ write_wb_reg(ARM_BASE_BCR + i, 0UL);
+ write_wb_reg(ARM_BASE_BVR + i, 0UL);
+ }
+
+}
+
/*
* One-time initialisation.
*/
@@ -880,11 +892,11 @@ static void reset_ctrl_regs(void *info)
if (enable_monitor_mode())
return;
- /* We must also reset any reserved registers. */
- for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
- write_wb_reg(ARM_BASE_BCR + i, 0UL);
- write_wb_reg(ARM_BASE_BVR + i, 0UL);
- }
+#ifdef CONFIG_HAVE_HW_BRKPT_RESERVED_RW_ACCESS
+ reset_brps_reserved_reg(core_num_brps);
+#else
+ reset_brps_reserved_reg(core_num_brps + core_num_reserved_brps);
+#endif
for (i = 0; i < core_num_wrps; ++i) {
write_wb_reg(ARM_BASE_WCR + i, 0UL);
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 83bbad03fcc..40603864994 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -42,6 +42,8 @@
#include
#include
+#include
+
/*
* No architecture-specific irq_finish function defined in arm/arch/irqs.h.
*/
@@ -76,6 +78,7 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
+ perf_mon_interrupt_in();
irq_enter();
/*
@@ -95,6 +98,7 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
irq_exit();
set_irq_regs(old_regs);
+ perf_mon_interrupt_out();
}
void set_irq_flags(unsigned int irq, unsigned int iflags)
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index e59bbd496c3..601ef744500 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -86,6 +86,7 @@ void machine_kexec(struct kimage *image)
unsigned long reboot_code_buffer_phys;
void *reboot_code_buffer;
+ arch_kexec();
page_list = image->head & PAGE_MASK;
@@ -120,5 +121,5 @@ void machine_kexec(struct kimage *image)
cpu_proc_fin();
outer_inv_all();
flush_cache_all();
- cpu_reset(reboot_code_buffer_phys);
+ __virt_to_phys(cpu_reset)(reboot_code_buffer_phys);
}
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 2b5b1421596..c9982829f21 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -19,6 +19,7 @@
#include
#include
#include
+#include
#include
#include
@@ -71,6 +72,10 @@ struct arm_pmu {
enum arm_perf_pmu_ids id;
const char *name;
irqreturn_t (*handle_irq)(int irq_num, void *dev);
+#ifdef CONFIG_SMP
+ void (*secondary_enable)(unsigned int irq);
+ void (*secondary_disable)(unsigned int irq);
+#endif
void (*enable)(struct hw_perf_event *evt, int idx);
void (*disable)(struct hw_perf_event *evt, int idx);
int (*get_event_idx)(struct cpu_hw_events *cpuc,
@@ -426,6 +431,10 @@ armpmu_reserve_hardware(void)
pr_warning("unable to request IRQ%d for ARM perf "
"counters\n", irq);
break;
+#ifdef CONFIG_SMP
+ } else if (armpmu->secondary_enable) {
+ armpmu->secondary_enable(irq);
+#endif
}
}
@@ -449,8 +458,13 @@ armpmu_release_hardware(void)
for (i = pmu_device->num_resources - 1; i >= 0; --i) {
irq = platform_get_irq(pmu_device, i);
- if (irq >= 0)
+ if (irq >= 0) {
free_irq(irq, NULL);
+#ifdef CONFIG_SMP
+ if (armpmu->secondary_disable)
+ armpmu->secondary_disable(irq);
+#endif
+ }
}
armpmu->stop();
@@ -624,6 +638,10 @@ static struct pmu pmu = {
#include "perf_event_xscale.c"
#include "perf_event_v6.c"
#include "perf_event_v7.c"
+#include "perf_event_msm.c"
+#include "perf_event_msm_l2.c"
+#include "perf_event_msm_krait.c"
+#include "perf_event_msm_krait_l2.c"
/*
* Ensure the PMU has sane values out of reset.
@@ -674,6 +692,22 @@ init_hw_perf_events(void)
armpmu = xscale2pmu_init();
break;
}
+ /* Qualcomm CPUs */
+ } else if (0x51 == implementor) {
+ switch (part_number) {
+ case 0x00F0: /* 8x50 & 7x30*/
+ armpmu = armv7_scorpion_pmu_init();
+ break;
+ case 0x02D0: /* 8x60 */
+ armpmu = armv7_scorpionmp_pmu_init();
+ scorpionmp_l2_pmu_init();
+ break;
+ case 0x0490: /* 8960 sim */
+ case 0x04D0: /* 8960 */
+ armpmu = armv7_krait_pmu_init();
+ krait_l2_pmu_init();
+ break;
+ }
}
if (armpmu) {
diff --git a/arch/arm/kernel/perf_event_msm.c b/arch/arm/kernel/perf_event_msm.c
new file mode 100644
index 00000000000..ae8bfcbf7f0
--- /dev/null
+++ b/arch/arm/kernel/perf_event_msm.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include "../vfp/vfpinstr.h"
+
+#ifdef CONFIG_CPU_V7
+enum scorpion_perf_common {
+ SCORPION_EVT_START_IDX = 0x4c,
+ SCORPION_ICACHE_EXPL_INV = 0x4c,
+ SCORPION_ICACHE_MISS = 0x4d,
+ SCORPION_ICACHE_ACCESS = 0x4e,
+ SCORPION_ICACHE_CACHEREQ_L2 = 0x4f,
+ SCORPION_ICACHE_NOCACHE_L2 = 0x50,
+ SCORPION_HIQUP_NOPED = 0x51,
+ SCORPION_DATA_ABORT = 0x52,
+ SCORPION_IRQ = 0x53,
+ SCORPION_FIQ = 0x54,
+ SCORPION_ALL_EXCPT = 0x55,
+ SCORPION_UNDEF = 0x56,
+ SCORPION_SVC = 0x57,
+ SCORPION_SMC = 0x58,
+ SCORPION_PREFETCH_ABORT = 0x59,
+ SCORPION_INDEX_CHECK = 0x5a,
+ SCORPION_NULL_CHECK = 0x5b,
+ SCORPION_ICIMVAU_IMPL_ICIALLU = 0x5c,
+ SCORPION_NONICIALLU_BTAC_INV = 0x5d,
+ SCORPION_IMPL_ICIALLU = 0x5e,
+ SCORPION_EXPL_ICIALLU = 0x5f,
+ SCORPION_SPIPE_ONLY_CYCLES = 0x60,
+ SCORPION_XPIPE_ONLY_CYCLES = 0x61,
+ SCORPION_DUAL_CYCLES = 0x62,
+ SCORPION_DISPATCH_ANY_CYCLES = 0x63,
+ SCORPION_FIFO_FULLBLK_CMT = 0x64,
+ SCORPION_FAIL_COND_INST = 0x65,
+ SCORPION_PASS_COND_INST = 0x66,
+ SCORPION_ALLOW_VU_CLK = 0x67,
+ SCORPION_VU_IDLE = 0x68,
+ SCORPION_ALLOW_L2_CLK = 0x69,
+ SCORPION_L2_IDLE = 0x6a,
+ SCORPION_DTLB_IMPL_INV_SCTLR_DACR = 0x6b,
+ SCORPION_DTLB_EXPL_INV = 0x6c,
+ SCORPION_DTLB_MISS = 0x6d,
+ SCORPION_DTLB_ACCESS = 0x6e,
+ SCORPION_ITLB_MISS = 0x6f,
+ SCORPION_ITLB_IMPL_INV = 0x70,
+ SCORPION_ITLB_EXPL_INV = 0x71,
+ SCORPION_UTLB_D_MISS = 0x72,
+ SCORPION_UTLB_D_ACCESS = 0x73,
+ SCORPION_UTLB_I_MISS = 0x74,
+ SCORPION_UTLB_I_ACCESS = 0x75,
+ SCORPION_UTLB_INV_ASID = 0x76,
+ SCORPION_UTLB_INV_MVA = 0x77,
+ SCORPION_UTLB_INV_ALL = 0x78,
+ SCORPION_S2_HOLD_RDQ_UNAVAIL = 0x79,
+ SCORPION_S2_HOLD = 0x7a,
+ SCORPION_S2_HOLD_DEV_OP = 0x7b,
+ SCORPION_S2_HOLD_ORDER = 0x7c,
+ SCORPION_S2_HOLD_BARRIER = 0x7d,
+ SCORPION_VIU_DUAL_CYCLE = 0x7e,
+ SCORPION_VIU_SINGLE_CYCLE = 0x7f,
+ SCORPION_VX_PIPE_WAR_STALL_CYCLES = 0x80,
+ SCORPION_VX_PIPE_WAW_STALL_CYCLES = 0x81,
+ SCORPION_VX_PIPE_RAW_STALL_CYCLES = 0x82,
+ SCORPION_VX_PIPE_LOAD_USE_STALL = 0x83,
+ SCORPION_VS_PIPE_WAR_STALL_CYCLES = 0x84,
+ SCORPION_VS_PIPE_WAW_STALL_CYCLES = 0x85,
+ SCORPION_VS_PIPE_RAW_STALL_CYCLES = 0x86,
+ SCORPION_EXCEPTIONS_INV_OPERATION = 0x87,
+ SCORPION_EXCEPTIONS_DIV_BY_ZERO = 0x88,
+ SCORPION_COND_INST_FAIL_VX_PIPE = 0x89,
+ SCORPION_COND_INST_FAIL_VS_PIPE = 0x8a,
+ SCORPION_EXCEPTIONS_OVERFLOW = 0x8b,
+ SCORPION_EXCEPTIONS_UNDERFLOW = 0x8c,
+ SCORPION_EXCEPTIONS_DENORM = 0x8d,
+};
+
+enum scorpion_perf_smp {
+ SCORPIONMP_NUM_BARRIERS = 0x8e,
+ SCORPIONMP_BARRIER_CYCLES = 0x8f,
+};
+
+enum scorpion_perf_up {
+ SCORPION_BANK_AB_HIT = 0x8e,
+ SCORPION_BANK_AB_ACCESS = 0x8f,
+ SCORPION_BANK_CD_HIT = 0x90,
+ SCORPION_BANK_CD_ACCESS = 0x91,
+ SCORPION_BANK_AB_DSIDE_HIT = 0x92,
+ SCORPION_BANK_AB_DSIDE_ACCESS = 0x93,
+ SCORPION_BANK_CD_DSIDE_HIT = 0x94,
+ SCORPION_BANK_CD_DSIDE_ACCESS = 0x95,
+ SCORPION_BANK_AB_ISIDE_HIT = 0x96,
+ SCORPION_BANK_AB_ISIDE_ACCESS = 0x97,
+ SCORPION_BANK_CD_ISIDE_HIT = 0x98,
+ SCORPION_BANK_CD_ISIDE_ACCESS = 0x99,
+ SCORPION_ISIDE_RD_WAIT = 0x9a,
+ SCORPION_DSIDE_RD_WAIT = 0x9b,
+ SCORPION_BANK_BYPASS_WRITE = 0x9c,
+ SCORPION_BANK_AB_NON_CASTOUT = 0x9d,
+ SCORPION_BANK_AB_L2_CASTOUT = 0x9e,
+ SCORPION_BANK_CD_NON_CASTOUT = 0x9f,
+ SCORPION_BANK_CD_L2_CASTOUT = 0xa0,
+};
+
+static const unsigned armv7_scorpion_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned armv7_scorpion_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ [C(L1D)] = {
+ /*
+ * The performance counters don't differentiate between read
+ * and write accesses/misses so this isn't strictly correct,
+ * but it's the best we can do. Writes and reads get
+ * combined.
+ */
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_DCACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_DCACHE_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_DCACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_DCACHE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = SCORPION_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = SCORPION_ICACHE_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = SCORPION_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = SCORPION_ICACHE_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(DTLB)] = {
+ /*
+ * Only ITLB misses and DTLB refills are supported.
+ * If users want the DTLB refills misses a raw counter
+ * must be used.
+ */
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = SCORPION_DTLB_ACCESS,
+ [C(RESULT_MISS)] = SCORPION_DTLB_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = SCORPION_DTLB_ACCESS,
+ [C(RESULT_MISS)] = SCORPION_DTLB_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = SCORPION_ITLB_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = SCORPION_ITLB_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+};
+
+struct scorpion_evt {
+ /*
+ * The scorpion_evt_type field corresponds to the actual Scorpion
+ * event codes. These map many-to-one to the armv7 defined codes
+ */
+ u32 scorpion_evt_type;
+
+ /*
+ * The group_setval field corresponds to the value that the group
+ * register needs to be set to. This value is deduced from the row
+ * and column that the event belongs to in the event table
+ */
+ u32 group_setval;
+
+ /*
+ * The groupcode corresponds to the group that the event belongs to.
+ * Scorpion has 5 groups of events LPM0, LPM1, LPM2, L2LPM and VLPM
+ * going from 0 to 4 in terms of the codes used
+ */
+ u8 groupcode;
+
+ /*
+ * The armv7_evt_type field corresponds to the armv7 defined event
+ * code that the Scorpion events map to
+ */
+ u32 armv7_evt_type;
+};
+
+static const struct scorpion_evt scorpion_event[] = {
+ {SCORPION_ICACHE_EXPL_INV, 0x80000500, 0, 0x4d},
+ {SCORPION_ICACHE_MISS, 0x80050000, 0, 0x4e},
+ {SCORPION_ICACHE_ACCESS, 0x85000000, 0, 0x4f},
+ {SCORPION_ICACHE_CACHEREQ_L2, 0x86000000, 0, 0x4f},
+ {SCORPION_ICACHE_NOCACHE_L2, 0x87000000, 0, 0x4f},
+ {SCORPION_HIQUP_NOPED, 0x80080000, 0, 0x4e},
+ {SCORPION_DATA_ABORT, 0x8000000a, 0, 0x4c},
+ {SCORPION_IRQ, 0x80000a00, 0, 0x4d},
+ {SCORPION_FIQ, 0x800a0000, 0, 0x4e},
+ {SCORPION_ALL_EXCPT, 0x8a000000, 0, 0x4f},
+ {SCORPION_UNDEF, 0x8000000b, 0, 0x4c},
+ {SCORPION_SVC, 0x80000b00, 0, 0x4d},
+ {SCORPION_SMC, 0x800b0000, 0, 0x4e},
+ {SCORPION_PREFETCH_ABORT, 0x8b000000, 0, 0x4f},
+ {SCORPION_INDEX_CHECK, 0x8000000c, 0, 0x4c},
+ {SCORPION_NULL_CHECK, 0x80000c00, 0, 0x4d},
+ {SCORPION_ICIMVAU_IMPL_ICIALLU, 0x8000000d, 0, 0x4c},
+ {SCORPION_NONICIALLU_BTAC_INV, 0x80000d00, 0, 0x4d},
+ {SCORPION_IMPL_ICIALLU, 0x800d0000, 0, 0x4e},
+ {SCORPION_EXPL_ICIALLU, 0x8d000000, 0, 0x4f},
+
+ {SCORPION_SPIPE_ONLY_CYCLES, 0x80000600, 1, 0x51},
+ {SCORPION_XPIPE_ONLY_CYCLES, 0x80060000, 1, 0x52},
+ {SCORPION_DUAL_CYCLES, 0x86000000, 1, 0x53},
+ {SCORPION_DISPATCH_ANY_CYCLES, 0x89000000, 1, 0x53},
+ {SCORPION_FIFO_FULLBLK_CMT, 0x8000000d, 1, 0x50},
+ {SCORPION_FAIL_COND_INST, 0x800d0000, 1, 0x52},
+ {SCORPION_PASS_COND_INST, 0x8d000000, 1, 0x53},
+ {SCORPION_ALLOW_VU_CLK, 0x8000000e, 1, 0x50},
+ {SCORPION_VU_IDLE, 0x80000e00, 1, 0x51},
+ {SCORPION_ALLOW_L2_CLK, 0x800e0000, 1, 0x52},
+ {SCORPION_L2_IDLE, 0x8e000000, 1, 0x53},
+
+ {SCORPION_DTLB_IMPL_INV_SCTLR_DACR, 0x80000001, 2, 0x54},
+ {SCORPION_DTLB_EXPL_INV, 0x80000100, 2, 0x55},
+ {SCORPION_DTLB_MISS, 0x80010000, 2, 0x56},
+ {SCORPION_DTLB_ACCESS, 0x81000000, 2, 0x57},
+ {SCORPION_ITLB_MISS, 0x80000200, 2, 0x55},
+ {SCORPION_ITLB_IMPL_INV, 0x80020000, 2, 0x56},
+ {SCORPION_ITLB_EXPL_INV, 0x82000000, 2, 0x57},
+ {SCORPION_UTLB_D_MISS, 0x80000003, 2, 0x54},
+ {SCORPION_UTLB_D_ACCESS, 0x80000300, 2, 0x55},
+ {SCORPION_UTLB_I_MISS, 0x80030000, 2, 0x56},
+ {SCORPION_UTLB_I_ACCESS, 0x83000000, 2, 0x57},
+ {SCORPION_UTLB_INV_ASID, 0x80000400, 2, 0x55},
+ {SCORPION_UTLB_INV_MVA, 0x80040000, 2, 0x56},
+ {SCORPION_UTLB_INV_ALL, 0x84000000, 2, 0x57},
+ {SCORPION_S2_HOLD_RDQ_UNAVAIL, 0x80000800, 2, 0x55},
+ {SCORPION_S2_HOLD, 0x88000000, 2, 0x57},
+ {SCORPION_S2_HOLD_DEV_OP, 0x80000900, 2, 0x55},
+ {SCORPION_S2_HOLD_ORDER, 0x80090000, 2, 0x56},
+ {SCORPION_S2_HOLD_BARRIER, 0x89000000, 2, 0x57},
+
+ {SCORPION_VIU_DUAL_CYCLE, 0x80000001, 4, 0x5c},
+ {SCORPION_VIU_SINGLE_CYCLE, 0x80000100, 4, 0x5d},
+ {SCORPION_VX_PIPE_WAR_STALL_CYCLES, 0x80000005, 4, 0x5c},
+ {SCORPION_VX_PIPE_WAW_STALL_CYCLES, 0x80000500, 4, 0x5d},
+ {SCORPION_VX_PIPE_RAW_STALL_CYCLES, 0x80050000, 4, 0x5e},
+ {SCORPION_VX_PIPE_LOAD_USE_STALL, 0x80000007, 4, 0x5c},
+ {SCORPION_VS_PIPE_WAR_STALL_CYCLES, 0x80000008, 4, 0x5c},
+ {SCORPION_VS_PIPE_WAW_STALL_CYCLES, 0x80000800, 4, 0x5d},
+ {SCORPION_VS_PIPE_RAW_STALL_CYCLES, 0x80080000, 4, 0x5e},
+ {SCORPION_EXCEPTIONS_INV_OPERATION, 0x8000000b, 4, 0x5c},
+ {SCORPION_EXCEPTIONS_DIV_BY_ZERO, 0x80000b00, 4, 0x5d},
+ {SCORPION_COND_INST_FAIL_VX_PIPE, 0x800b0000, 4, 0x5e},
+ {SCORPION_COND_INST_FAIL_VS_PIPE, 0x8b000000, 4, 0x5f},
+ {SCORPION_EXCEPTIONS_OVERFLOW, 0x8000000c, 4, 0x5c},
+ {SCORPION_EXCEPTIONS_UNDERFLOW, 0x80000c00, 4, 0x5d},
+ {SCORPION_EXCEPTIONS_DENORM, 0x8c000000, 4, 0x5f},
+
+#ifdef CONFIG_MSM_SMP
+ {SCORPIONMP_NUM_BARRIERS, 0x80000e00, 3, 0x59},
+ {SCORPIONMP_BARRIER_CYCLES, 0x800e0000, 3, 0x5a},
+#else
+ {SCORPION_BANK_AB_HIT, 0x80000001, 3, 0x58},
+ {SCORPION_BANK_AB_ACCESS, 0x80000100, 3, 0x59},
+ {SCORPION_BANK_CD_HIT, 0x80010000, 3, 0x5a},
+ {SCORPION_BANK_CD_ACCESS, 0x81000000, 3, 0x5b},
+ {SCORPION_BANK_AB_DSIDE_HIT, 0x80000002, 3, 0x58},
+ {SCORPION_BANK_AB_DSIDE_ACCESS, 0x80000200, 3, 0x59},
+ {SCORPION_BANK_CD_DSIDE_HIT, 0x80020000, 3, 0x5a},
+ {SCORPION_BANK_CD_DSIDE_ACCESS, 0x82000000, 3, 0x5b},
+ {SCORPION_BANK_AB_ISIDE_HIT, 0x80000003, 3, 0x58},
+ {SCORPION_BANK_AB_ISIDE_ACCESS, 0x80000300, 3, 0x59},
+ {SCORPION_BANK_CD_ISIDE_HIT, 0x80030000, 3, 0x5a},
+ {SCORPION_BANK_CD_ISIDE_ACCESS, 0x83000000, 3, 0x5b},
+ {SCORPION_ISIDE_RD_WAIT, 0x80000009, 3, 0x58},
+ {SCORPION_DSIDE_RD_WAIT, 0x80090000, 3, 0x5a},
+ {SCORPION_BANK_BYPASS_WRITE, 0x8000000a, 3, 0x58},
+ {SCORPION_BANK_AB_NON_CASTOUT, 0x8000000c, 3, 0x58},
+ {SCORPION_BANK_AB_L2_CASTOUT, 0x80000c00, 3, 0x59},
+ {SCORPION_BANK_CD_NON_CASTOUT, 0x800c0000, 3, 0x5a},
+ {SCORPION_BANK_CD_L2_CASTOUT, 0x8c000000, 3, 0x5b},
+#endif
+};
+
+static unsigned int get_scorpion_evtinfo(unsigned int scorpion_evt_type,
+ struct scorpion_evt *evtinfo)
+{
+ u32 idx;
+
+ if (scorpion_evt_type < SCORPION_EVT_START_IDX || scorpion_evt_type >=
+ (ARRAY_SIZE(scorpion_event) + SCORPION_EVT_START_IDX))
+ return -EINVAL;
+ idx = scorpion_evt_type - SCORPION_EVT_START_IDX;
+ if (scorpion_event[idx].scorpion_evt_type == scorpion_evt_type) {
+ evtinfo->group_setval = scorpion_event[idx].group_setval;
+ evtinfo->groupcode = scorpion_event[idx].groupcode;
+ evtinfo->armv7_evt_type = scorpion_event[idx].armv7_evt_type;
+ return scorpion_event[idx].armv7_evt_type;
+ }
+ return -EINVAL;
+}
+
+static u32 scorpion_read_lpm0(void)
+{
+ u32 val;
+
+ asm volatile("mrc p15, 0, %0, c15, c0, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_lpm0(u32 val)
+{
+ asm volatile("mcr p15, 0, %0, c15, c0, 0" : : "r" (val));
+}
+
+static u32 scorpion_read_lpm1(void)
+{
+ u32 val;
+
+ asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_lpm1(u32 val)
+{
+ asm volatile("mcr p15, 1, %0, c15, c0, 0" : : "r" (val));
+}
+
+static u32 scorpion_read_lpm2(void)
+{
+ u32 val;
+
+ asm volatile("mrc p15, 2, %0, c15, c0, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_lpm2(u32 val)
+{
+ asm volatile("mcr p15, 2, %0, c15, c0, 0" : : "r" (val));
+}
+
+static u32 scorpion_read_l2lpm(void)
+{
+ u32 val;
+
+ asm volatile("mrc p15, 3, %0, c15, c2, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_l2lpm(u32 val)
+{
+ asm volatile("mcr p15, 3, %0, c15, c2, 0" : : "r" (val));
+}
+
+static u32 scorpion_read_vlpm(void)
+{
+ u32 val;
+
+ asm volatile("mrc p10, 7, %0, c11, c0, 0" : "=r" (val));
+ return val;
+}
+
+static void scorpion_write_vlpm(u32 val)
+{
+ asm volatile("mcr p10, 7, %0, c11, c0, 0" : : "r" (val));
+}
+
+/*
+ * The Scorpion processor supports performance monitoring for Venum unit.
+ * In order to access the performance monitor registers corresponding to
+ * VFP, CPACR and FPEXC registers need to be set up beforehand.
+ * Also, they need to be recovered once the access is done.
+ * This is the reason for having pre and post functions
+ */
+
+static DEFINE_PER_CPU(u32, venum_orig_val);
+static DEFINE_PER_CPU(u32, fp_orig_val);
+
+static void scorpion_pre_vlpm(void)
+{
+ u32 venum_new_val;
+ u32 fp_new_val;
+
+ /* CPACR Enable CP10 access*/
+ venum_orig_val = get_copro_access();
+ venum_new_val = venum_orig_val | CPACC_SVC(10);
+ set_copro_access(venum_new_val);
+ /* Enable FPEXC */
+ fp_orig_val = fmrx(FPEXC);
+ fp_new_val = fp_orig_val | FPEXC_EN;
+ fmxr(FPEXC, fp_new_val);
+}
+
+static void scorpion_post_vlpm(void)
+{
+ /* Restore FPEXC*/
+ fmxr(FPEXC, fp_orig_val);
+ isb();
+ /* Restore CPACR*/
+ set_copro_access(venum_orig_val);
+}
+
+struct scorpion_access_funcs {
+ u32 (*read) (void);
+ void (*write) (u32);
+ void (*pre) (void);
+ void (*post) (void);
+};
+
+/*
+ * The scorpion_functions array is used to set up the event register codes
+ * based on the group to which an event belongs to.
+ * Having the following array modularizes the code for doing that.
+ */
+struct scorpion_access_funcs scorpion_functions[] = {
+ {scorpion_read_lpm0, scorpion_write_lpm0, NULL, NULL},
+ {scorpion_read_lpm1, scorpion_write_lpm1, NULL, NULL},
+ {scorpion_read_lpm2, scorpion_write_lpm2, NULL, NULL},
+ {scorpion_read_l2lpm, scorpion_write_l2lpm, NULL, NULL},
+ {scorpion_read_vlpm, scorpion_write_vlpm, scorpion_pre_vlpm,
+ scorpion_post_vlpm},
+};
+
+static inline u32 scorpion_get_columnmask(u32 evt_code)
+{
+ const u32 columnmasks[] = {0xffffff00, 0xffff00ff, 0xff00ffff,
+ 0x80ffffff};
+
+ return columnmasks[evt_code & 0x3];
+}
+
+static void scorpion_evt_setup(u32 gr, u32 setval, u32 evt_code)
+{
+ u32 val;
+
+ if (scorpion_functions[gr].pre)
+ scorpion_functions[gr].pre();
+ val = scorpion_get_columnmask(evt_code) & scorpion_functions[gr].read();
+ val = val | setval;
+ scorpion_functions[gr].write(val);
+ if (scorpion_functions[gr].post)
+ scorpion_functions[gr].post();
+}
+
+static void scorpion_clear_pmuregs(void)
+{
+ unsigned long flags;
+
+ scorpion_write_lpm0(0);
+ scorpion_write_lpm1(0);
+ scorpion_write_lpm2(0);
+ scorpion_write_l2lpm(0);
+ raw_spin_lock_irqsave(&pmu_lock, flags);
+ scorpion_pre_vlpm();
+ scorpion_write_vlpm(0);
+ scorpion_post_vlpm();
+ raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void scorpion_clearpmu(u32 grp, u32 val, u32 evt_code)
+{
+ u32 orig_pmuval, new_pmuval;
+
+ if (scorpion_functions[grp].pre)
+ scorpion_functions[grp].pre();
+ orig_pmuval = scorpion_functions[grp].read();
+ val = val & ~scorpion_get_columnmask(evt_code);
+ new_pmuval = orig_pmuval & ~val;
+ scorpion_functions[grp].write(new_pmuval);
+ if (scorpion_functions[grp].post)
+ scorpion_functions[grp].post();
+}
+
+static void scorpion_pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+ unsigned long flags;
+ u32 val = 0;
+ u32 gr;
+ unsigned long event;
+ struct scorpion_evt evtinfo;
+
+ /* Disable counter and interrupt */
+ raw_spin_lock_irqsave(&pmu_lock, flags);
+
+ /* Disable counter */
+ armv7_pmnc_disable_counter(idx);
+
+ /*
+ * Clear lpm code (if destined for PMNx counters)
+ * We don't need to set the event if it's a cycle count
+ */
+ if (idx != ARMV7_CYCLE_COUNTER) {
+ val = hwc->config_base;
+ val &= ARMV7_EVTSEL_MASK;
+ if (val > 0x40) {
+ event = get_scorpion_evtinfo(val, &evtinfo);
+ if (event == -EINVAL)
+ goto scorpion_dis_out;
+ val = evtinfo.group_setval;
+ gr = evtinfo.groupcode;
+ scorpion_clearpmu(gr, val, evtinfo.armv7_evt_type);
+ }
+ }
+ /* Disable interrupt for this counter */
+ armv7_pmnc_disable_intens(idx);
+
+scorpion_dis_out:
+ raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void scorpion_pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+ unsigned long flags;
+ u32 val = 0;
+ u32 gr;
+ unsigned long event;
+ struct scorpion_evt evtinfo;
+
+ /*
+ * Enable counter and interrupt, and set the counter to count
+ * the event that we're interested in.
+ */
+ raw_spin_lock_irqsave(&pmu_lock, flags);
+
+ /* Disable counter */
+ armv7_pmnc_disable_counter(idx);
+
+ /*
+ * Set event (if destined for PMNx counters)
+ * We don't need to set the event if it's a cycle count
+ */
+ if (idx != ARMV7_CYCLE_COUNTER) {
+ val = hwc->config_base;
+ val &= ARMV7_EVTSEL_MASK;
+ if (val < 0x40) {
+ armv7_pmnc_write_evtsel(idx, hwc->config_base);
+ } else {
+ event = get_scorpion_evtinfo(val, &evtinfo);
+
+ if (event == -EINVAL)
+ goto scorpion_out;
+ /*
+ * Set event (if destined for PMNx counters)
+ * We don't need to set the event if it's a cycle count
+ */
+ armv7_pmnc_write_evtsel(idx, event);
+ val = 0x0;
+ asm volatile("mcr p15, 0, %0, c9, c15, 0" : :
+ "r" (val));
+ val = evtinfo.group_setval;
+ gr = evtinfo.groupcode;
+ scorpion_evt_setup(gr, val, evtinfo.armv7_evt_type);
+ }
+ }
+
+ /* Enable interrupt for this counter */
+ armv7_pmnc_enable_intens(idx);
+
+ /* Enable counter */
+ armv7_pmnc_enable_counter(idx);
+
+scorpion_out:
+ raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+#ifdef CONFIG_SMP
+static void scorpion_secondary_enable_callback(void *info)
+{
+ int irq = *(unsigned int *)info;
+
+ if (irq_get_chip(irq)->irq_unmask)
+ irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
+}
+static void scorpion_secondary_disable_callback(void *info)
+{
+ int irq = *(unsigned int *)info;
+
+ if (irq_get_chip(irq)->irq_mask)
+ irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
+}
+
+static void scorpion_secondary_enable(unsigned int irq)
+{
+ smp_call_function(scorpion_secondary_enable_callback, &irq, 1);
+}
+
+static void scorpion_secondary_disable(unsigned int irq)
+{
+ smp_call_function(scorpion_secondary_disable_callback, &irq, 1);
+}
+#endif
+
+static struct arm_pmu scorpion_pmu = {
+ .handle_irq = armv7pmu_handle_irq,
+#ifdef CONFIG_SMP
+ .secondary_enable = scorpion_secondary_enable,
+ .secondary_disable = scorpion_secondary_disable,
+#endif
+ .enable = scorpion_pmu_enable_event,
+ .disable = scorpion_pmu_disable_event,
+ .read_counter = armv7pmu_read_counter,
+ .write_counter = armv7pmu_write_counter,
+ .raw_event_mask = 0xFF,
+ .get_event_idx = armv7pmu_get_event_idx,
+ .start = armv7pmu_start,
+ .stop = armv7pmu_stop,
+ .max_period = (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init armv7_scorpion_pmu_init(void)
+{
+ scorpion_pmu.id = ARM_PERF_PMU_ID_SCORPION;
+ scorpion_pmu.name = "ARMv7 Scorpion";
+ scorpion_pmu.cache_map = &armv7_scorpion_perf_cache_map;
+ scorpion_pmu.event_map = &armv7_scorpion_perf_map;
+ scorpion_pmu.num_events = armv7_read_num_pmnc_events();
+ scorpion_clear_pmuregs();
+ return &scorpion_pmu;
+}
+
+static const struct arm_pmu *__init armv7_scorpionmp_pmu_init(void)
+{
+ scorpion_pmu.id = ARM_PERF_PMU_ID_SCORPIONMP;
+ scorpion_pmu.name = "ARMv7 Scorpion-MP";
+ scorpion_pmu.cache_map = &armv7_scorpion_perf_cache_map;
+ scorpion_pmu.event_map = &armv7_scorpion_perf_map;
+ scorpion_pmu.num_events = armv7_read_num_pmnc_events();
+ scorpion_clear_pmuregs();
+ return &scorpion_pmu;
+}
+#else
+static const struct arm_pmu *__init armv7_scorpion_pmu_init(void)
+{
+ return NULL;
+}
+static const struct arm_pmu *__init armv7_scorpionmp_pmu_init(void)
+{
+ return NULL;
+}
+#endif /* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
new file mode 100644
index 00000000000..cb94d646aa2
--- /dev/null
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+
+#ifdef CONFIG_CPU_V7
+#define KRAIT_EVT_PREFIX 1
+#define KRAIT_MAX_L1_REG 2
+/*
+ event encoding: prccg
+ p = prefix (1 for Krait L1)
+ r = register
+ cc = code
+ g = group
+*/
+#define KRAIT_L1_ICACHE_MISS 0x10010
+#define KRAIT_L1_ICACHE_ACCESS 0x10011
+#define KRAIT_DTLB_ACCESS 0x121B2
+#define KRAIT_ITLB_ACCESS 0x121C0
+
+u32 evt_type_base[] = {0x4c, 0x50, 0x54};
+
+static const unsigned armv7_krait_perf_map[PERF_COUNT_HW_MAX] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = ARMV7_PERFCTR_CPU_CYCLES,
+ [PERF_COUNT_HW_INSTRUCTIONS] = ARMV7_PERFCTR_INSTR_EXECUTED,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_CACHE_MISSES] = HW_OP_UNSUPPORTED,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV7_PERFCTR_PC_WRITE,
+ [PERF_COUNT_HW_BRANCH_MISSES] = ARMV7_PERFCTR_PC_BRANCH_MIS_PRED,
+ [PERF_COUNT_HW_BUS_CYCLES] = ARMV7_PERFCTR_CLOCK_CYCLES,
+};
+
+static const unsigned armv7_krait_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ [C(L1D)] = {
+ /*
+ * The performance counters don't differentiate between read
+ * and write accesses/misses so this isn't strictly correct,
+ * but it's the best we can do. Writes and reads get
+ * combined.
+ */
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_DCACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_DCACHE_REFILL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = ARMV7_PERFCTR_DCACHE_ACCESS,
+ [C(RESULT_MISS)] = ARMV7_PERFCTR_DCACHE_REFILL,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = KRAIT_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = KRAIT_L1_ICACHE_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = KRAIT_L1_ICACHE_ACCESS,
+ [C(RESULT_MISS)] = KRAIT_L1_ICACHE_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = KRAIT_DTLB_ACCESS,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = KRAIT_DTLB_ACCESS,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = KRAIT_ITLB_ACCESS,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = KRAIT_ITLB_ACCESS,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ [C(RESULT_MISS)]
+ = ARMV7_PERFCTR_PC_BRANCH_MIS_USED,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = CACHE_OP_UNSUPPORTED,
+ [C(RESULT_MISS)] = CACHE_OP_UNSUPPORTED,
+ },
+ },
+};
+
+struct krait_evt {
+ /*
+ * The group_setval field corresponds to the value that the group
+ * register needs to be set to. This value is calculated from the row
+ * and column that the event belongs to in the event table
+ */
+ u32 group_setval;
+
+ /*
+ * The groupcode corresponds to the group that the event belongs to.
+ * Krait has 3 groups of events PMRESR0, 1, 2
+ * going from 0 to 2 in terms of the codes used
+ */
+ u8 groupcode;
+
+ /*
+ * The armv7_evt_type field corresponds to the armv7 defined event
+ * code that the Krait events map to
+ */
+ u32 armv7_evt_type;
+};
+
+static unsigned int get_krait_evtinfo(unsigned int krait_evt_type,
+ struct krait_evt *evtinfo)
+{
+ u8 prefix;
+ u8 reg;
+ u8 code;
+ u8 group;
+
+ prefix = (krait_evt_type & 0xF0000) >> 16;
+ reg = (krait_evt_type & 0x0F000) >> 12;
+ code = (krait_evt_type & 0x00FF0) >> 4;
+ group = krait_evt_type & 0x0000F;
+
+ if ((prefix != KRAIT_EVT_PREFIX) || (group > 3) ||
+ (reg > KRAIT_MAX_L1_REG))
+ return -EINVAL;
+
+ evtinfo->group_setval = 0x80000000 | (code << (group * 8));
+ evtinfo->groupcode = reg;
+ evtinfo->armv7_evt_type = evt_type_base[reg] | group;
+
+ return evtinfo->armv7_evt_type;
+}
+
+static u32 krait_read_pmresr0(void)
+{
+ u32 val;
+
+ asm volatile("mrc p15, 1, %0, c9, c15, 0" : "=r" (val));
+ return val;
+}
+
+static void krait_write_pmresr0(u32 val)
+{
+ asm volatile("mcr p15, 1, %0, c9, c15, 0" : : "r" (val));
+}
+
+static u32 krait_read_pmresr1(void)
+{
+ u32 val;
+
+ asm volatile("mrc p15, 1, %0, c9, c15, 1" : "=r" (val));
+ return val;
+}
+
+static void krait_write_pmresr1(u32 val)
+{
+ asm volatile("mcr p15, 1, %0, c9, c15, 1" : : "r" (val));
+}
+
+static u32 krait_read_pmresr2(void)
+{
+ u32 val;
+
+ asm volatile("mrc p15, 1, %0, c9, c15, 2" : "=r" (val));
+ return val;
+}
+
+static void krait_write_pmresr2(u32 val)
+{
+ asm volatile("mcr p15, 1, %0, c9, c15, 2" : : "r" (val));
+}
+
+struct krait_access_funcs {
+ u32 (*read) (void);
+ void (*write) (u32);
+};
+
+/*
+ * The krait_functions array is used to set up the event register codes
+ * based on the group to which an event belongs.
+ * Having the following array modularizes the code for doing that.
+ */
+struct krait_access_funcs krait_functions[] = {
+ {krait_read_pmresr0, krait_write_pmresr0},
+ {krait_read_pmresr1, krait_write_pmresr1},
+ {krait_read_pmresr2, krait_write_pmresr2},
+};
+
+static inline u32 krait_get_columnmask(u32 evt_code)
+{
+ const u32 columnmasks[] = {0xffffff00, 0xffff00ff, 0xff00ffff,
+ 0x80ffffff};
+
+ return columnmasks[evt_code & 0x3];
+}
+
+static void krait_evt_setup(u32 gr, u32 setval, u32 evt_code)
+{
+ u32 val;
+
+ val = krait_get_columnmask(evt_code) & krait_functions[gr].read();
+ val = val | setval;
+ krait_functions[gr].write(val);
+}
+
+static void krait_clear_pmuregs(void)
+{
+ krait_write_pmresr0(0);
+ krait_write_pmresr1(0);
+ krait_write_pmresr2(0);
+}
+
+static void krait_clearpmu(u32 grp, u32 val, u32 evt_code)
+{
+ u32 new_pmuval;
+
+ new_pmuval = krait_functions[grp].read() &
+ krait_get_columnmask(evt_code);
+ krait_functions[grp].write(new_pmuval);
+}
+
+static void krait_pmu_disable_event(struct hw_perf_event *hwc, int idx)
+{
+ unsigned long flags;
+ u32 val = 0;
+ u32 gr;
+ unsigned long event;
+ struct krait_evt evtinfo;
+
+ /* Disable counter and interrupt */
+ raw_spin_lock_irqsave(&pmu_lock, flags);
+
+ /* Disable counter */
+ armv7_pmnc_disable_counter(idx);
+
+ /*
+ * Clear pmresr code (if destined for PMNx counters)
+ * We don't need to set the event if it's a cycle count
+ */
+ if (idx != ARMV7_CYCLE_COUNTER) {
+ val = hwc->config_base;
+ if (val > 0x40) {
+ event = get_krait_evtinfo(val, &evtinfo);
+ if (event == -EINVAL)
+ goto krait_dis_out;
+ val = evtinfo.group_setval;
+ gr = evtinfo.groupcode;
+ krait_clearpmu(gr, val, evtinfo.armv7_evt_type);
+ }
+ }
+ /* Disable interrupt for this counter */
+ armv7_pmnc_disable_intens(idx);
+
+krait_dis_out:
+ raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static void krait_pmu_enable_event(struct hw_perf_event *hwc, int idx)
+{
+ unsigned long flags;
+ u32 val = 0;
+ u32 gr;
+ unsigned long event;
+ struct krait_evt evtinfo;
+
+ /*
+ * Enable counter and interrupt, and set the counter to count
+ * the event that we're interested in.
+ */
+ raw_spin_lock_irqsave(&pmu_lock, flags);
+
+ /* Disable counter */
+ armv7_pmnc_disable_counter(idx);
+
+ /*
+ * Set event (if destined for PMNx counters)
+ * We don't need to set the event if it's a cycle count
+ */
+ if (idx != ARMV7_CYCLE_COUNTER) {
+ val = hwc->config_base;
+ if (val < 0x40) {
+ armv7_pmnc_write_evtsel(idx, hwc->config_base);
+ } else {
+ event = get_krait_evtinfo(val, &evtinfo);
+
+ if (event == -EINVAL)
+ goto krait_out;
+ /*
+ * Set event (if destined for PMNx counters)
+ * We don't need to set the event if it's a cycle count
+ */
+ armv7_pmnc_write_evtsel(idx, event);
+ val = 0x0;
+ asm volatile("mcr p15, 0, %0, c9, c15, 0" : :
+ "r" (val));
+ val = evtinfo.group_setval;
+ gr = evtinfo.groupcode;
+ krait_evt_setup(gr, val, evtinfo.armv7_evt_type);
+ }
+ }
+
+ /* Enable interrupt for this counter */
+ armv7_pmnc_enable_intens(idx);
+
+ /* Enable counter */
+ armv7_pmnc_enable_counter(idx);
+
+krait_out:
+ raw_spin_unlock_irqrestore(&pmu_lock, flags);
+}
+
+static struct arm_pmu krait_pmu = {
+ .handle_irq = armv7pmu_handle_irq,
+#ifdef CONFIG_ARCH_MSM_SMP
+ .secondary_enable = scorpion_secondary_enable,
+ .secondary_disable = scorpion_secondary_disable,
+#endif
+ .enable = krait_pmu_enable_event,
+ .disable = krait_pmu_disable_event,
+ .read_counter = armv7pmu_read_counter,
+ .write_counter = armv7pmu_write_counter,
+ .raw_event_mask = 0xFFFFF,
+ .get_event_idx = armv7pmu_get_event_idx,
+ .start = armv7pmu_start,
+ .stop = armv7pmu_stop,
+ .max_period = (1LLU << 32) - 1,
+};
+
+static const struct arm_pmu *__init armv7_krait_pmu_init(void)
+{
+ krait_pmu.id = ARM_PERF_PMU_ID_KRAIT;
+ krait_pmu.name = "ARMv7 Krait";
+ krait_pmu.cache_map = &armv7_krait_perf_cache_map;
+ krait_pmu.event_map = &armv7_krait_perf_map;
+ krait_pmu.num_events = armv7_read_num_pmnc_events();
+ krait_clear_pmuregs();
+ return &krait_pmu;
+}
+
+#else
+static const struct arm_pmu *__init armv7_krait_pmu_init(void)
+{
+ return NULL;
+}
+#endif /* CONFIG_CPU_V7 */
diff --git a/arch/arm/kernel/perf_event_msm_krait_l2.c b/arch/arm/kernel/perf_event_msm_krait_l2.c
new file mode 100644
index 00000000000..7cb4ee78f4b
--- /dev/null
+++ b/arch/arm/kernel/perf_event_msm_krait_l2.c
@@ -0,0 +1,656 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifdef CONFIG_CPU_HAS_L2_PMU
+
+#include
+
+#include
+
+#define MAX_L2_PERIOD ((1ULL << 32) - 1)
+#define MAX_KRAIT_L2_CTRS 5
+
+#define L2PMCCNTR 0x409
+#define L2PMCCNTCR 0x408
+#define L2PMCCNTSR 0x40A
+#define L2CYCLE_CTR_BIT 31
+#define L2CYCLE_CTR_EVENT_IDX 4
+#define L2CYCLE_CTR_RAW_CODE 0xff
+
+#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_REG_MASK 0xf000
+#define EVENT_GROUPSEL_MASK 0x000f
+#define EVENT_GROUPCODE_MASK 0x0ff0
+#define EVENT_REG_SHIFT 12
+#define EVENT_GROUPCODE_SHIFT 4
+
+#define RESRX_VALUE_EN 0x80000000
+
+static struct platform_device *l2_pmu_device;
+
+struct hw_krait_l2_pmu {
+ struct perf_event *events[MAX_KRAIT_L2_CTRS];
+ unsigned long active_mask[BITS_TO_LONGS(MAX_KRAIT_L2_CTRS)];
+ raw_spinlock_t lock;
+};
+
+struct hw_krait_l2_pmu hw_krait_l2_pmu;
+
+struct event_desc {
+ int event_groupsel;
+ int event_reg;
+ int event_group_code;
+};
+
+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(int ctr)
+{
+ u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
+ u32 filter_val = 0x000f0030 | 1 << smp_processor_id();
+
+ set_l2_indirect_reg(filter_reg, filter_val);
+}
+
+static void enable_intenset(u32 idx)
+{
+ if (idx == L2CYCLE_CTR_EVENT_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 == L2CYCLE_CTR_EVENT_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 == L2CYCLE_CTR_EVENT_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 == L2CYCLE_CTR_EVENT_IDX)
+ set_l2_indirect_reg(L2PMCNTENCLR, 1 << L2CYCLE_CTR_BIT);
+ else
+ set_l2_indirect_reg(L2PMCNTENCLR, 1 << idx);
+}
+
+static u64 read_counter(u32 idx)
+{
+ u32 val;
+ u32 counter_reg = (idx * 16) + IA_L2PMXEVCNTR_BASE;
+
+ if (idx == L2CYCLE_CTR_EVENT_IDX)
+ val = get_l2_indirect_reg(L2PMCCNTR);
+ else
+ val = get_l2_indirect_reg(counter_reg);
+
+ return val;
+}
+
+static void write_counter(u32 idx, u32 val)
+{
+ u32 counter_reg = (idx * 16) + IA_L2PMXEVCNTR_BASE;
+
+ if (idx == L2CYCLE_CTR_EVENT_IDX)
+ set_l2_indirect_reg(L2PMCCNTR, val);
+ else
+ set_l2_indirect_reg(counter_reg, val);
+}
+
+static int
+pmu_event_set_period(struct perf_event *event,
+ struct hw_perf_event *hwc, int idx)
+{
+ s64 left = local64_read(&hwc->period_left);
+ s64 period = hwc->sample_period;
+ int ret = 0;
+
+ if (unlikely(left <= -period)) {
+ left = period;
+ local64_set(&hwc->period_left, left);
+ hwc->last_period = period;
+ ret = 1;
+ }
+
+ if (unlikely(left <= 0)) {
+ left += period;
+ local64_set(&hwc->period_left, left);
+ hwc->last_period = period;
+ ret = 1;
+ }
+
+ if (left > (s64) MAX_L2_PERIOD)
+ left = MAX_L2_PERIOD;
+
+ local64_set(&hwc->prev_count, (u64)-left);
+
+ write_counter(idx, (u64) (-left) & 0xffffffff);
+
+ perf_event_update_userpage(event);
+
+ return ret;
+}
+
+static u64
+pmu_event_update(struct perf_event *event, struct hw_perf_event *hwc, int idx,
+ int overflow)
+{
+ u64 prev_raw_count, new_raw_count;
+ u64 delta;
+
+again:
+ prev_raw_count = local64_read(&hwc->prev_count);
+ new_raw_count = read_counter(idx);
+
+ if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+ new_raw_count) != prev_raw_count)
+ goto again;
+
+ new_raw_count &= MAX_L2_PERIOD;
+ prev_raw_count &= MAX_L2_PERIOD;
+
+ if (overflow)
+ delta = MAX_L2_PERIOD - prev_raw_count + new_raw_count;
+ else
+ delta = new_raw_count - prev_raw_count;
+
+ local64_add(delta, &event->count);
+ local64_sub(delta, &hwc->period_left);
+
+ pr_debug("%s: new: %lld, prev: %lld, event: %ld count: %lld\n",
+ __func__, new_raw_count, prev_raw_count,
+ hwc->config_base, local64_read(&event->count));
+
+ return new_raw_count;
+}
+
+static void krait_l2_read(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ pmu_event_update(event, hwc, hwc->idx, 0);
+}
+
+static void krait_l2_stop_counter(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+
+ if (!(hwc->state & PERF_HES_STOPPED)) {
+ disable_intenclr(idx);
+ disable_counter(idx);
+
+ pmu_event_update(event, hwc, idx, 0);
+ hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+ }
+
+ pr_debug("%s: event: %ld ctr: %d stopped\n", __func__, hwc->config_base,
+ idx);
+}
+
+static void krait_l2_start_counter(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+ struct event_desc evdesc;
+
+ if (flags & PERF_EF_RELOAD)
+ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+ hwc->state = 0;
+
+ pmu_event_set_period(event, hwc, idx);
+
+ if (hwc->config_base == L2CYCLE_CTR_RAW_CODE)
+ goto out;
+
+ 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);
+
+ set_evfilter(idx);
+
+out:
+ enable_intenset(idx);
+ enable_counter(idx);
+
+ 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_del_event(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+ unsigned long iflags;
+
+ raw_spin_lock_irqsave(&hw_krait_l2_pmu.lock, iflags);
+
+ clear_bit(idx, (long unsigned int *)(&hw_krait_l2_pmu.active_mask));
+
+ krait_l2_stop_counter(event, PERF_EF_UPDATE);
+ hw_krait_l2_pmu.events[idx] = NULL;
+ hwc->idx = -1;
+
+ raw_spin_unlock_irqrestore(&hw_krait_l2_pmu.lock, iflags);
+
+ pr_debug("%s: event: %ld deleted\n", __func__, hwc->config_base);
+
+ perf_event_update_userpage(event);
+}
+
+static int krait_l2_add_event(struct perf_event *event, int flags)
+{
+ int ctr = 0;
+ struct hw_perf_event *hwc = &event->hw;
+ unsigned long iflags;
+ int err = 0;
+
+ perf_pmu_disable(event->pmu);
+
+ raw_spin_lock_irqsave(&hw_krait_l2_pmu.lock, iflags);
+
+ /* Cycle counter has a resrvd index */
+ if (hwc->config_base == L2CYCLE_CTR_RAW_CODE) {
+ if (hw_krait_l2_pmu.events[L2CYCLE_CTR_EVENT_IDX]) {
+ pr_err("%s: Stale cycle ctr event ptr !\n", __func__);
+ err = -EINVAL;
+ goto out;
+ }
+ hwc->idx = L2CYCLE_CTR_EVENT_IDX;
+ hw_krait_l2_pmu.events[L2CYCLE_CTR_EVENT_IDX] = event;
+ set_bit(L2CYCLE_CTR_EVENT_IDX,
+ (long unsigned int *)&hw_krait_l2_pmu.active_mask);
+ goto skip_ctr_loop;
+ }
+
+ for (ctr = 0; ctr < MAX_KRAIT_L2_CTRS - 1; ctr++) {
+ if (!hw_krait_l2_pmu.events[ctr]) {
+ hwc->idx = ctr;
+ hw_krait_l2_pmu.events[ctr] = event;
+ set_bit(ctr,
+ (long unsigned int *)
+ &hw_krait_l2_pmu.active_mask);
+ break;
+ }
+ }
+
+ if (hwc->idx < 0) {
+ err = -ENOSPC;
+ pr_err("%s: No space for event: %llx!!\n", __func__,
+ event->attr.config);
+ goto out;
+ }
+
+skip_ctr_loop:
+
+ disable_counter(hwc->idx);
+
+ hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+
+ if (flags & PERF_EF_START)
+ krait_l2_start_counter(event, PERF_EF_RELOAD);
+
+ perf_event_update_userpage(event);
+
+ pr_debug("%s: event: %ld, ctr: %d added from cpu:%d\n",
+ __func__, hwc->config_base, hwc->idx, smp_processor_id());
+out:
+ raw_spin_unlock_irqrestore(&hw_krait_l2_pmu.lock, iflags);
+
+ /* Resume the PMU even if this event could not be added */
+ perf_pmu_enable(event->pmu);
+
+ return err;
+}
+
+static void krait_l2_pmu_enable(struct pmu *pmu)
+{
+ isb();
+ set_l2_indirect_reg(L2PMCR, L2PMCR_GLOBAL_ENABLE);
+}
+
+static void krait_l2_pmu_disable(struct pmu *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();
+
+ perf_sample_data_init(&data, 0);
+
+ raw_spin_lock(&hw_krait_l2_pmu.lock);
+
+ while (pmovsr) {
+ bitp = __ffs(pmovsr);
+
+ if (bitp == L2CYCLE_CTR_BIT)
+ idx = L2CYCLE_CTR_EVENT_IDX;
+ else
+ idx = bitp;
+
+ event = hw_krait_l2_pmu.events[idx];
+
+ if (!event)
+ goto next;
+
+ if (!test_bit(idx, hw_krait_l2_pmu.active_mask))
+ goto next;
+
+ hwc = &event->hw;
+ pmu_event_update(event, hwc, idx, 1);
+ data.period = event->hw.last_period;
+
+ if (!pmu_event_set_period(event, hwc, idx))
+ goto next;
+
+ if (perf_event_overflow(event, 0, &data, regs))
+ disable_counter(hwc->idx);
+next:
+ pmovsr &= (pmovsr - 1);
+ }
+
+ raw_spin_unlock(&hw_krait_l2_pmu.lock);
+
+ irq_work_run();
+
+ return IRQ_HANDLED;
+}
+
+static atomic_t active_l2_events = ATOMIC_INIT(0);
+static DEFINE_MUTEX(krait_pmu_reserve_mutex);
+
+static int pmu_reserve_hardware(void)
+{
+ int i, err = -ENODEV, irq;
+
+ l2_pmu_device = reserve_pmu(ARM_PMU_DEVICE_L2);
+
+ if (IS_ERR(l2_pmu_device)) {
+ pr_warning("unable to reserve pmu\n");
+ return PTR_ERR(l2_pmu_device);
+ }
+
+ if (l2_pmu_device->num_resources < 1) {
+ pr_err("no irqs for PMUs defined\n");
+ return -ENODEV;
+ }
+
+ if (strncmp(l2_pmu_device->name, "l2-arm-pmu", 6)) {
+ pr_err("Incorrect pdev reserved !\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < l2_pmu_device->num_resources; ++i) {
+ irq = platform_get_irq(l2_pmu_device, i);
+ if (irq < 0)
+ continue;
+
+ err = request_irq(irq, krait_l2_handle_irq,
+ IRQF_DISABLED | IRQF_NOBALANCING,
+ "krait-l2-pmu", NULL);
+ if (err) {
+ pr_warning("unable to request IRQ%d for Krait L2 perf "
+ "counters\n", irq);
+ break;
+ }
+
+ irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
+ }
+
+ if (err) {
+ for (i = i - 1; i >= 0; --i) {
+ irq = platform_get_irq(l2_pmu_device, i);
+ if (irq >= 0)
+ free_irq(irq, NULL);
+ }
+ release_pmu(l2_pmu_device);
+ l2_pmu_device = NULL;
+ }
+
+ return err;
+}
+
+static void pmu_release_hardware(void)
+{
+ int i, irq;
+
+ for (i = l2_pmu_device->num_resources - 1; i >= 0; --i) {
+ irq = platform_get_irq(l2_pmu_device, i);
+ if (irq >= 0)
+ free_irq(irq, NULL);
+ }
+
+ krait_l2_pmu_disable(NULL);
+
+ release_pmu(l2_pmu_device);
+ l2_pmu_device = NULL;
+}
+
+static void pmu_perf_event_destroy(struct perf_event *event)
+{
+ if (atomic_dec_and_mutex_lock
+ (&active_l2_events, &krait_pmu_reserve_mutex)) {
+ pmu_release_hardware();
+ mutex_unlock(&krait_pmu_reserve_mutex);
+ }
+}
+
+static int krait_l2_event_init(struct perf_event *event)
+{
+ int err = 0;
+ struct hw_perf_event *hwc = &event->hw;
+ int status = 0;
+
+ switch (event->attr.type) {
+ case PERF_TYPE_SHARED:
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ hwc->idx = -1;
+
+ event->destroy = pmu_perf_event_destroy;
+
+ if (!atomic_inc_not_zero(&active_l2_events)) {
+ /* 0 active events */
+ mutex_lock(&krait_pmu_reserve_mutex);
+ err = pmu_reserve_hardware();
+ mutex_unlock(&krait_pmu_reserve_mutex);
+ if (!err)
+ atomic_inc(&active_l2_events);
+ else
+ return err;
+ } else {
+ if (atomic_read(&active_l2_events) > (MAX_KRAIT_L2_CTRS - 1)) {
+ pr_err("%s: No space left on PMU for event: %llx\n",
+ __func__, event->attr.config);
+ atomic_dec(&active_l2_events);
+ return -ENOSPC;
+ }
+ }
+
+ hwc->config_base = event->attr.config;
+ hwc->config = 0;
+ hwc->event_base = 0;
+
+ /* Only one CPU can control the cycle counter */
+ if (hwc->config_base == L2CYCLE_CTR_RAW_CODE) {
+ /* Check if its already running */
+ status = get_l2_indirect_reg(L2PMCCNTSR);
+ if (status == 0x2) {
+ err = -ENOSPC;
+ goto out;
+ }
+ }
+
+ if (!hwc->sample_period) {
+ hwc->sample_period = MAX_L2_PERIOD;
+ hwc->last_period = hwc->sample_period;
+ local64_set(&hwc->period_left, hwc->sample_period);
+ }
+
+ pr_debug("%s: event: %lld init'd\n", __func__, event->attr.config);
+
+out:
+ if (err < 0)
+ pmu_perf_event_destroy(event);
+
+ return err;
+}
+
+static struct pmu krait_l2_pmu = {
+ .pmu_enable = krait_l2_pmu_enable,
+ .pmu_disable = krait_l2_pmu_disable,
+ .event_init = krait_l2_event_init,
+ .add = krait_l2_add_event,
+ .del = krait_l2_del_event,
+ .start = krait_l2_start_counter,
+ .stop = krait_l2_stop_counter,
+ .read = krait_l2_read,
+};
+
+static const struct arm_pmu *__init krait_l2_pmu_init(void)
+{
+ /* Register our own PMU here */
+ perf_pmu_register(&krait_l2_pmu, "Krait L2", PERF_TYPE_SHARED);
+
+ memset(&hw_krait_l2_pmu, 0, sizeof(hw_krait_l2_pmu));
+
+ /* Reset all ctrs */
+ set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
+
+ /* Avoid spurious interrupt if any */
+ get_reset_pmovsr();
+
+ /* Don't return an arm_pmu here */
+ return NULL;
+}
+#else
+
+static const struct arm_pmu *__init krait_l2_pmu_init(void)
+{
+ return NULL;
+}
+#endif
diff --git a/arch/arm/kernel/perf_event_msm_l2.c b/arch/arm/kernel/perf_event_msm_l2.c
new file mode 100644
index 00000000000..8678b0ab073
--- /dev/null
+++ b/arch/arm/kernel/perf_event_msm_l2.c
@@ -0,0 +1,981 @@
+/*
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifdef CONFIG_CPU_HAS_L2_PMU
+
+#include
+
+#define MAX_BB_L2_PERIOD ((1ULL << 32) - 1)
+#define MAX_BB_L2_CTRS 5
+#define BB_L2CYCLE_CTR_BIT 31
+#define BB_L2CYCLE_CTR_EVENT_IDX 4
+#define BB_L2CYCLE_CTR_RAW_CODE 0xff
+#define SCORPIONL2_PMNC_E (1 << 0) /* Enable all counters */
+
+/*
+ * Lock to protect r/m/w sequences to the L2 PMU.
+ */
+DEFINE_RAW_SPINLOCK(bb_l2_pmu_lock);
+
+static struct platform_device *bb_l2_pmu_device;
+
+struct hw_bb_l2_pmu {
+ struct perf_event *events[MAX_BB_L2_CTRS];
+ unsigned long active_mask[BITS_TO_LONGS(MAX_BB_L2_CTRS)];
+ raw_spinlock_t lock;
+};
+
+struct hw_bb_l2_pmu hw_bb_l2_pmu;
+
+struct bb_l2_scorp_evt {
+ u32 evt_type;
+ u32 val;
+ u8 grp;
+ u32 evt_type_act;
+};
+
+enum scorpion_perf_types {
+ SCORPIONL2_TOTAL_BANK_REQ = 0x90,
+ SCORPIONL2_DSIDE_READ = 0x91,
+ SCORPIONL2_DSIDE_WRITE = 0x92,
+ SCORPIONL2_ISIDE_READ = 0x93,
+ SCORPIONL2_L2CACHE_ISIDE_READ = 0x94,
+ SCORPIONL2_L2CACHE_BANK_REQ = 0x95,
+ SCORPIONL2_L2CACHE_DSIDE_READ = 0x96,
+ SCORPIONL2_L2CACHE_DSIDE_WRITE = 0x97,
+ SCORPIONL2_L2NOCACHE_DSIDE_WRITE = 0x98,
+ SCORPIONL2_L2NOCACHE_ISIDE_READ = 0x99,
+ SCORPIONL2_L2NOCACHE_TOTAL_REQ = 0x9a,
+ SCORPIONL2_L2NOCACHE_DSIDE_READ = 0x9b,
+ SCORPIONL2_DSIDE_READ_NOL1 = 0x9c,
+ SCORPIONL2_L2CACHE_WRITETHROUGH = 0x9d,
+ SCORPIONL2_BARRIERS = 0x9e,
+ SCORPIONL2_HARDWARE_TABLE_WALKS = 0x9f,
+ SCORPIONL2_MVA_POC = 0xa0,
+ SCORPIONL2_L2CACHE_HW_TABLE_WALKS = 0xa1,
+ SCORPIONL2_SETWAY_CACHE_OPS = 0xa2,
+ SCORPIONL2_DSIDE_WRITE_HITS = 0xa3,
+ SCORPIONL2_ISIDE_READ_HITS = 0xa4,
+ SCORPIONL2_CACHE_DSIDE_READ_NOL1 = 0xa5,
+ SCORPIONL2_TOTAL_CACHE_HITS = 0xa6,
+ SCORPIONL2_CACHE_MATCH_MISS = 0xa7,
+ SCORPIONL2_DREAD_HIT_L1_DATA = 0xa8,
+ SCORPIONL2_L2LINE_LOCKED = 0xa9,
+ SCORPIONL2_HW_TABLE_WALK_HIT = 0xaa,
+ SCORPIONL2_CACHE_MVA_POC = 0xab,
+ SCORPIONL2_L2ALLOC_DWRITE_MISS = 0xac,
+ SCORPIONL2_CORRECTED_TAG_ARRAY = 0xad,
+ SCORPIONL2_CORRECTED_DATA_ARRAY = 0xae,
+ SCORPIONL2_CORRECTED_REPLACEMENT_ARRAY = 0xaf,
+ SCORPIONL2_PMBUS_MPAAF = 0xb0,
+ SCORPIONL2_PMBUS_MPWDAF = 0xb1,
+ SCORPIONL2_PMBUS_MPBRT = 0xb2,
+ SCORPIONL2_CPU0_GRANT = 0xb3,
+ SCORPIONL2_CPU1_GRANT = 0xb4,
+ SCORPIONL2_CPU0_NOGRANT = 0xb5,
+ SCORPIONL2_CPU1_NOGRANT = 0xb6,
+ SCORPIONL2_CPU0_LOSING_ARB = 0xb7,
+ SCORPIONL2_CPU1_LOSING_ARB = 0xb8,
+ SCORPIONL2_SLAVEPORT_NOGRANT = 0xb9,
+ SCORPIONL2_SLAVEPORT_BPQ_FULL = 0xba,
+ SCORPIONL2_SLAVEPORT_LOSING_ARB = 0xbb,
+ SCORPIONL2_SLAVEPORT_GRANT = 0xbc,
+ SCORPIONL2_SLAVEPORT_GRANTLOCK = 0xbd,
+ SCORPIONL2_L2EM_STREX_PASS = 0xbe,
+ SCORPIONL2_L2EM_STREX_FAIL = 0xbf,
+ SCORPIONL2_LDREX_RESERVE_L2EM = 0xc0,
+ SCORPIONL2_SLAVEPORT_LDREX = 0xc1,
+ SCORPIONL2_CPU0_L2EM_CLEARED = 0xc2,
+ SCORPIONL2_CPU1_L2EM_CLEARED = 0xc3,
+ SCORPIONL2_SLAVEPORT_L2EM_CLEARED = 0xc4,
+ SCORPIONL2_CPU0_CLAMPED = 0xc5,
+ SCORPIONL2_CPU1_CLAMPED = 0xc6,
+ SCORPIONL2_CPU0_WAIT = 0xc7,
+ SCORPIONL2_CPU1_WAIT = 0xc8,
+ SCORPIONL2_CPU0_NONAMBAS_WAIT = 0xc9,
+ SCORPIONL2_CPU1_NONAMBAS_WAIT = 0xca,
+ SCORPIONL2_CPU0_DSB_WAIT = 0xcb,
+ SCORPIONL2_CPU1_DSB_WAIT = 0xcc,
+ SCORPIONL2_AXI_READ = 0xcd,
+ SCORPIONL2_AXI_WRITE = 0xce,
+
+ SCORPIONL2_1BEAT_WRITE = 0xcf,
+ SCORPIONL2_2BEAT_WRITE = 0xd0,
+ SCORPIONL2_4BEAT_WRITE = 0xd1,
+ SCORPIONL2_8BEAT_WRITE = 0xd2,
+ SCORPIONL2_12BEAT_WRITE = 0xd3,
+ SCORPIONL2_16BEAT_WRITE = 0xd4,
+ SCORPIONL2_1BEAT_DSIDE_READ = 0xd5,
+ SCORPIONL2_2BEAT_DSIDE_READ = 0xd6,
+ SCORPIONL2_4BEAT_DSIDE_READ = 0xd7,
+ SCORPIONL2_8BEAT_DSIDE_READ = 0xd8,
+ SCORPIONL2_CSYS_READ_1BEAT = 0xd9,
+ SCORPIONL2_CSYS_READ_2BEAT = 0xda,
+ SCORPIONL2_CSYS_READ_4BEAT = 0xdb,
+ SCORPIONL2_CSYS_READ_8BEAT = 0xdc,
+ SCORPIONL2_4BEAT_IFETCH_READ = 0xdd,
+ SCORPIONL2_8BEAT_IFETCH_READ = 0xde,
+ SCORPIONL2_CSYS_WRITE_1BEAT = 0xdf,
+ SCORPIONL2_CSYS_WRITE_2BEAT = 0xe0,
+ SCORPIONL2_AXI_READ_DATA_BEAT = 0xe1,
+ SCORPIONL2_AXI_WRITE_EVT1 = 0xe2,
+ SCORPIONL2_AXI_WRITE_EVT2 = 0xe3,
+ SCORPIONL2_LDREX_REQ = 0xe4,
+ SCORPIONL2_STREX_PASS = 0xe5,
+ SCORPIONL2_STREX_FAIL = 0xe6,
+ SCORPIONL2_CPREAD = 0xe7,
+ SCORPIONL2_CPWRITE = 0xe8,
+ SCORPIONL2_BARRIER_REQ = 0xe9,
+ SCORPIONL2_AXI_READ_SLVPORT = 0xea,
+ SCORPIONL2_AXI_WRITE_SLVPORT = 0xeb,
+ SCORPIONL2_AXI_READ_SLVPORT_DATABEAT = 0xec,
+ SCORPIONL2_AXI_WRITE_SLVPORT_DATABEAT = 0xed,
+ SCORPIONL2_SNOOPKILL_PREFILTER = 0xee,
+ SCORPIONL2_SNOOPKILL_FILTEROUT = 0xef,
+ SCORPIONL2_SNOOPED_IC = 0xf0,
+ SCORPIONL2_SNOOPED_BP = 0xf1,
+ SCORPIONL2_SNOOPED_BARRIERS = 0xf2,
+ SCORPIONL2_SNOOPED_TLB = 0xf3,
+ BB_L2_MAX_EVT,
+};
+
+static const struct bb_l2_scorp_evt sc_evt[] = {
+ {SCORPIONL2_TOTAL_BANK_REQ, 0x80000001, 0, 0x00},
+ {SCORPIONL2_DSIDE_READ, 0x80000100, 0, 0x01},
+ {SCORPIONL2_DSIDE_WRITE, 0x80010000, 0, 0x02},
+ {SCORPIONL2_ISIDE_READ, 0x81000000, 0, 0x03},
+ {SCORPIONL2_L2CACHE_ISIDE_READ, 0x80000002, 0, 0x00},
+ {SCORPIONL2_L2CACHE_BANK_REQ, 0x80000200, 0, 0x01},
+ {SCORPIONL2_L2CACHE_DSIDE_READ, 0x80020000, 0, 0x02},
+ {SCORPIONL2_L2CACHE_DSIDE_WRITE, 0x82000000, 0, 0x03},
+ {SCORPIONL2_L2NOCACHE_DSIDE_WRITE, 0x80000003, 0, 0x00},
+ {SCORPIONL2_L2NOCACHE_ISIDE_READ, 0x80000300, 0, 0x01},
+ {SCORPIONL2_L2NOCACHE_TOTAL_REQ, 0x80030000, 0, 0x02},
+ {SCORPIONL2_L2NOCACHE_DSIDE_READ, 0x83000000, 0, 0x03},
+ {SCORPIONL2_DSIDE_READ_NOL1, 0x80000004, 0, 0x00},
+ {SCORPIONL2_L2CACHE_WRITETHROUGH, 0x80000400, 0, 0x01},
+ {SCORPIONL2_BARRIERS, 0x84000000, 0, 0x03},
+ {SCORPIONL2_HARDWARE_TABLE_WALKS, 0x80000005, 0, 0x00},
+ {SCORPIONL2_MVA_POC, 0x80000500, 0, 0x01},
+ {SCORPIONL2_L2CACHE_HW_TABLE_WALKS, 0x80050000, 0, 0x02},
+ {SCORPIONL2_SETWAY_CACHE_OPS, 0x85000000, 0, 0x03},
+ {SCORPIONL2_DSIDE_WRITE_HITS, 0x80000006, 0, 0x00},
+ {SCORPIONL2_ISIDE_READ_HITS, 0x80000600, 0, 0x01},
+ {SCORPIONL2_CACHE_DSIDE_READ_NOL1, 0x80060000, 0, 0x02},
+ {SCORPIONL2_TOTAL_CACHE_HITS, 0x86000000, 0, 0x03},
+ {SCORPIONL2_CACHE_MATCH_MISS, 0x80000007, 0, 0x00},
+ {SCORPIONL2_DREAD_HIT_L1_DATA, 0x87000000, 0, 0x03},
+ {SCORPIONL2_L2LINE_LOCKED, 0x80000008, 0, 0x00},
+ {SCORPIONL2_HW_TABLE_WALK_HIT, 0x80000800, 0, 0x01},
+ {SCORPIONL2_CACHE_MVA_POC, 0x80080000, 0, 0x02},
+ {SCORPIONL2_L2ALLOC_DWRITE_MISS, 0x88000000, 0, 0x03},
+ {SCORPIONL2_CORRECTED_TAG_ARRAY, 0x80001A00, 0, 0x01},
+ {SCORPIONL2_CORRECTED_DATA_ARRAY, 0x801A0000, 0, 0x02},
+ {SCORPIONL2_CORRECTED_REPLACEMENT_ARRAY, 0x9A000000, 0, 0x03},
+ {SCORPIONL2_PMBUS_MPAAF, 0x80001C00, 0, 0x01},
+ {SCORPIONL2_PMBUS_MPWDAF, 0x801C0000, 0, 0x02},
+ {SCORPIONL2_PMBUS_MPBRT, 0x9C000000, 0, 0x03},
+
+ {SCORPIONL2_CPU0_GRANT, 0x80000001, 1, 0x04},
+ {SCORPIONL2_CPU1_GRANT, 0x80000100, 1, 0x05},
+ {SCORPIONL2_CPU0_NOGRANT, 0x80020000, 1, 0x06},
+ {SCORPIONL2_CPU1_NOGRANT, 0x82000000, 1, 0x07},
+ {SCORPIONL2_CPU0_LOSING_ARB, 0x80040000, 1, 0x06},
+ {SCORPIONL2_CPU1_LOSING_ARB, 0x84000000, 1, 0x07},
+ {SCORPIONL2_SLAVEPORT_NOGRANT, 0x80000007, 1, 0x04},
+ {SCORPIONL2_SLAVEPORT_BPQ_FULL, 0x80000700, 1, 0x05},
+ {SCORPIONL2_SLAVEPORT_LOSING_ARB, 0x80070000, 1, 0x06},
+ {SCORPIONL2_SLAVEPORT_GRANT, 0x87000000, 1, 0x07},
+ {SCORPIONL2_SLAVEPORT_GRANTLOCK, 0x80000008, 1, 0x04},
+ {SCORPIONL2_L2EM_STREX_PASS, 0x80000009, 1, 0x04},
+ {SCORPIONL2_L2EM_STREX_FAIL, 0x80000900, 1, 0x05},
+ {SCORPIONL2_LDREX_RESERVE_L2EM, 0x80090000, 1, 0x06},
+ {SCORPIONL2_SLAVEPORT_LDREX, 0x89000000, 1, 0x07},
+ {SCORPIONL2_CPU0_L2EM_CLEARED, 0x800A0000, 1, 0x06},
+ {SCORPIONL2_CPU1_L2EM_CLEARED, 0x8A000000, 1, 0x07},
+ {SCORPIONL2_SLAVEPORT_L2EM_CLEARED, 0x80000B00, 1, 0x05},
+ {SCORPIONL2_CPU0_CLAMPED, 0x8000000E, 1, 0x04},
+ {SCORPIONL2_CPU1_CLAMPED, 0x80000E00, 1, 0x05},
+ {SCORPIONL2_CPU0_WAIT, 0x800F0000, 1, 0x06},
+ {SCORPIONL2_CPU1_WAIT, 0x8F000000, 1, 0x07},
+ {SCORPIONL2_CPU0_NONAMBAS_WAIT, 0x80000010, 1, 0x04},
+ {SCORPIONL2_CPU1_NONAMBAS_WAIT, 0x80001000, 1, 0x05},
+ {SCORPIONL2_CPU0_DSB_WAIT, 0x80000014, 1, 0x04},
+ {SCORPIONL2_CPU1_DSB_WAIT, 0x80001400, 1, 0x05},
+
+ {SCORPIONL2_AXI_READ, 0x80000001, 2, 0x08},
+ {SCORPIONL2_AXI_WRITE, 0x80000100, 2, 0x09},
+ {SCORPIONL2_1BEAT_WRITE, 0x80010000, 2, 0x0a},
+ {SCORPIONL2_2BEAT_WRITE, 0x80010000, 2, 0x0b},
+ {SCORPIONL2_4BEAT_WRITE, 0x80000002, 2, 0x08},
+ {SCORPIONL2_8BEAT_WRITE, 0x80000200, 2, 0x09},
+ {SCORPIONL2_12BEAT_WRITE, 0x80020000, 2, 0x0a},
+ {SCORPIONL2_16BEAT_WRITE, 0x82000000, 2, 0x0b},
+ {SCORPIONL2_1BEAT_DSIDE_READ, 0x80000003, 2, 0x08},
+ {SCORPIONL2_2BEAT_DSIDE_READ, 0x80000300, 2, 0x09},
+ {SCORPIONL2_4BEAT_DSIDE_READ, 0x80030000, 2, 0x0a},
+ {SCORPIONL2_8BEAT_DSIDE_READ, 0x83000000, 2, 0x0b},
+ {SCORPIONL2_CSYS_READ_1BEAT, 0x80000004, 2, 0x08},
+ {SCORPIONL2_CSYS_READ_2BEAT, 0x80000400, 2, 0x09},
+ {SCORPIONL2_CSYS_READ_4BEAT, 0x80040000, 2, 0x0a},
+ {SCORPIONL2_CSYS_READ_8BEAT, 0x84000000, 2, 0x0b},
+ {SCORPIONL2_4BEAT_IFETCH_READ, 0x80000005, 2, 0x08},
+ {SCORPIONL2_8BEAT_IFETCH_READ, 0x80000500, 2, 0x09},
+ {SCORPIONL2_CSYS_WRITE_1BEAT, 0x80050000, 2, 0x0a},
+ {SCORPIONL2_CSYS_WRITE_2BEAT, 0x85000000, 2, 0x0b},
+ {SCORPIONL2_AXI_READ_DATA_BEAT, 0x80000600, 2, 0x09},
+ {SCORPIONL2_AXI_WRITE_EVT1, 0x80060000, 2, 0x0a},
+ {SCORPIONL2_AXI_WRITE_EVT2, 0x86000000, 2, 0x0b},
+ {SCORPIONL2_LDREX_REQ, 0x80000007, 2, 0x08},
+ {SCORPIONL2_STREX_PASS, 0x80000700, 2, 0x09},
+ {SCORPIONL2_STREX_FAIL, 0x80070000, 2, 0x0a},
+ {SCORPIONL2_CPREAD, 0x80000008, 2, 0x08},
+ {SCORPIONL2_CPWRITE, 0x80000800, 2, 0x09},
+ {SCORPIONL2_BARRIER_REQ, 0x88000000, 2, 0x0b},
+
+ {SCORPIONL2_AXI_READ_SLVPORT, 0x80000001, 3, 0x0c},
+ {SCORPIONL2_AXI_WRITE_SLVPORT, 0x80000100, 3, 0x0d},
+ {SCORPIONL2_AXI_READ_SLVPORT_DATABEAT, 0x80010000, 3, 0x0e},
+ {SCORPIONL2_AXI_WRITE_SLVPORT_DATABEAT, 0x81000000, 3, 0x0f},
+
+ {SCORPIONL2_SNOOPKILL_PREFILTER, 0x80000001, 4, 0x10},
+ {SCORPIONL2_SNOOPKILL_FILTEROUT, 0x80000100, 4, 0x11},
+ {SCORPIONL2_SNOOPED_IC, 0x80000002, 4, 0x10},
+ {SCORPIONL2_SNOOPED_BP, 0x80000200, 4, 0x11},
+ {SCORPIONL2_SNOOPED_BARRIERS, 0x80020000, 4, 0x12},
+ {SCORPIONL2_SNOOPED_TLB, 0x82000000, 4, 0x13},
+};
+
+static u32 bb_l2_read_l2pm0(void)
+{
+ u32 val;
+ asm volatile ("mrc p15, 3, %0, c15, c7, 0" : "=r" (val));
+ return val;
+}
+
+static void bb_l2_write_l2pm0(u32 val)
+{
+ asm volatile ("mcr p15, 3, %0, c15, c7, 0" : : "r" (val));
+}
+
+static u32 bb_l2_read_l2pm1(void)
+{
+ u32 val;
+ asm volatile ("mrc p15, 3, %0, c15, c7, 1" : "=r" (val));
+ return val;
+}
+
+static void bb_l2_write_l2pm1(u32 val)
+{
+ asm volatile ("mcr p15, 3, %0, c15, c7, 1" : : "r" (val));
+}
+
+static u32 bb_l2_read_l2pm2(void)
+{
+ u32 val;
+ asm volatile ("mrc p15, 3, %0, c15, c7, 2" : "=r" (val));
+ return val;
+}
+
+static void bb_l2_write_l2pm2(u32 val)
+{
+ asm volatile ("mcr p15, 3, %0, c15, c7, 2" : : "r" (val));
+}
+
+static u32 bb_l2_read_l2pm3(void)
+{
+ u32 val;
+ asm volatile ("mrc p15, 3, %0, c15, c7, 3" : "=r" (val));
+ return val;
+}
+
+static void bb_l2_write_l2pm3(u32 val)
+{
+ asm volatile ("mcr p15, 3, %0, c15, c7, 3" : : "r" (val));
+}
+
+static u32 bb_l2_read_l2pm4(void)
+{
+ u32 val;
+ asm volatile ("mrc p15, 3, %0, c15, c7, 4" : "=r" (val));
+ return val;
+}
+
+static void bb_l2_write_l2pm4(u32 val)
+{
+ asm volatile ("mcr p15, 3, %0, c15, c7, 4" : : "r" (val));
+}
+
+struct bb_scorpion_access_funcs {
+ u32(*read) (void);
+ void (*write) (u32);
+ void (*pre) (void);
+ void (*post) (void);
+};
+
+struct bb_scorpion_access_funcs bb_l2_func[] = {
+ {bb_l2_read_l2pm0, bb_l2_write_l2pm0, NULL, NULL},
+ {bb_l2_read_l2pm1, bb_l2_write_l2pm1, NULL, NULL},
+ {bb_l2_read_l2pm2, bb_l2_write_l2pm2, NULL, NULL},
+ {bb_l2_read_l2pm3, bb_l2_write_l2pm3, NULL, NULL},
+ {bb_l2_read_l2pm4, bb_l2_write_l2pm4, NULL, NULL},
+};
+
+#define COLMN0MASK 0x000000ff
+#define COLMN1MASK 0x0000ff00
+#define COLMN2MASK 0x00ff0000
+
+static u32 bb_l2_get_columnmask(u32 setval)
+{
+ if (setval & COLMN0MASK)
+ return 0xffffff00;
+ else if (setval & COLMN1MASK)
+ return 0xffff00ff;
+ else if (setval & COLMN2MASK)
+ return 0xff00ffff;
+ else
+ return 0x80ffffff;
+}
+
+static void bb_l2_evt_setup(u32 gr, u32 setval)
+{
+ u32 val;
+ if (bb_l2_func[gr].pre)
+ bb_l2_func[gr].pre();
+ val = bb_l2_get_columnmask(setval) & bb_l2_func[gr].read();
+ val = val | setval;
+ bb_l2_func[gr].write(val);
+ if (bb_l2_func[gr].post)
+ bb_l2_func[gr].post();
+}
+
+#define BB_L2_EVT_START_IDX 0x90
+#define BB_L2_INV_EVTYPE 0
+
+static unsigned int get_bb_l2_evtinfo(unsigned int evt_type,
+ struct bb_l2_scorp_evt *evtinfo)
+{
+ u32 idx;
+ if (evt_type < BB_L2_EVT_START_IDX || evt_type >= BB_L2_MAX_EVT)
+ return BB_L2_INV_EVTYPE;
+ idx = evt_type - BB_L2_EVT_START_IDX;
+ if (sc_evt[idx].evt_type == evt_type) {
+ evtinfo->val = sc_evt[idx].val;
+ evtinfo->grp = sc_evt[idx].grp;
+ evtinfo->evt_type_act = sc_evt[idx].evt_type_act;
+ return sc_evt[idx].evt_type_act;
+ }
+ return BB_L2_INV_EVTYPE;
+}
+
+static inline void bb_l2_pmnc_write(unsigned long val)
+{
+ val &= 0xff;
+ asm volatile ("mcr p15, 3, %0, c15, c4, 0" : : "r" (val));
+}
+
+static inline unsigned long bb_l2_pmnc_read(void)
+{
+ u32 val;
+ asm volatile ("mrc p15, 3, %0, c15, c4, 0" : "=r" (val));
+ return val;
+}
+
+static void bb_l2_set_evcntcr(void)
+{
+ u32 val = 0x0;
+ asm volatile ("mcr p15, 3, %0, c15, c6, 4" : : "r" (val));
+}
+
+static inline void bb_l2_set_evtyper(int ctr, int val)
+{
+ /* select ctr */
+ asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (ctr));
+
+ /* write into EVTYPER */
+ asm volatile ("mcr p15, 3, %0, c15, c6, 7" : : "r" (val));
+}
+
+static void bb_l2_set_evfilter(void)
+{
+ u32 filter_val = 0x000f0030 | 1 << smp_processor_id();
+
+ asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
+}
+
+static void bb_l2_enable_intenset(u32 idx)
+{
+ if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
+ asm volatile ("mcr p15, 3, %0, c15, c5, 1" : : "r"
+ (1 << BB_L2CYCLE_CTR_BIT));
+ } else {
+ asm volatile ("mcr p15, 3, %0, c15, c5, 1" : : "r" (1 << idx));
+ }
+}
+
+static void bb_l2_disable_intenclr(u32 idx)
+{
+ if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
+ asm volatile ("mcr p15, 3, %0, c15, c5, 0" : : "r"
+ (1 << BB_L2CYCLE_CTR_BIT));
+ } else {
+ asm volatile ("mcr p15, 3, %0, c15, c5, 0" : : "r" (1 << idx));
+ }
+}
+
+static void bb_l2_enable_counter(u32 idx)
+{
+ if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
+ asm volatile ("mcr p15, 3, %0, c15, c4, 3" : : "r"
+ (1 << BB_L2CYCLE_CTR_BIT));
+ } else {
+ asm volatile ("mcr p15, 3, %0, c15, c4, 3" : : "r" (1 << idx));
+ }
+}
+
+static void bb_l2_disable_counter(u32 idx)
+{
+ if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
+ asm volatile ("mcr p15, 3, %0, c15, c4, 2" : : "r"
+ (1 << BB_L2CYCLE_CTR_BIT));
+
+ } else {
+ asm volatile ("mcr p15, 3, %0, c15, c4, 2" : : "r" (1 << idx));
+ }
+}
+
+static u64 bb_l2_read_counter(u32 idx)
+{
+ u32 val;
+ unsigned long flags;
+
+ if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
+ asm volatile ("mrc p15, 3, %0, c15, c4, 5" : "=r" (val));
+ } else {
+ raw_spin_lock_irqsave(&bb_l2_pmu_lock, flags);
+ asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (idx));
+
+ /* read val from counter */
+ asm volatile ("mrc p15, 3, %0, c15, c6, 5" : "=r" (val));
+ raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, flags);
+ }
+
+ return val;
+}
+
+static void bb_l2_write_counter(u32 idx, u32 val)
+{
+ unsigned long flags;
+
+ if (idx == BB_L2CYCLE_CTR_EVENT_IDX) {
+ asm volatile ("mcr p15, 3, %0, c15, c4, 5" : : "r" (val));
+ } else {
+ raw_spin_lock_irqsave(&bb_l2_pmu_lock, flags);
+ /* select counter */
+ asm volatile ("mcr p15, 3, %0, c15, c6, 0" : : "r" (idx));
+
+ /* write val into counter */
+ asm volatile ("mcr p15, 3, %0, c15, c6, 5" : : "r" (val));
+ raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, flags);
+ }
+}
+
+static int
+bb_pmu_event_set_period(struct perf_event *event,
+ struct hw_perf_event *hwc, int idx)
+{
+ s64 left = local64_read(&hwc->period_left);
+ s64 period = hwc->sample_period;
+ int ret = 0;
+
+ if (unlikely(left <= -period)) {
+ left = period;
+ local64_set(&hwc->period_left, left);
+ hwc->last_period = period;
+ ret = 1;
+ }
+
+ if (unlikely(left <= 0)) {
+ left += period;
+ local64_set(&hwc->period_left, left);
+ hwc->last_period = period;
+ ret = 1;
+ }
+
+ if (left > (s64) MAX_BB_L2_PERIOD)
+ left = MAX_BB_L2_PERIOD;
+
+ local64_set(&hwc->prev_count, (u64)-left);
+
+ bb_l2_write_counter(idx, (u64) (-left) & 0xffffffff);
+
+ perf_event_update_userpage(event);
+
+ return ret;
+}
+
+static u64
+bb_pmu_event_update(struct perf_event *event, struct hw_perf_event *hwc,
+ int idx, int overflow)
+{
+ u64 prev_raw_count, new_raw_count;
+ u64 delta;
+
+again:
+ prev_raw_count = local64_read(&hwc->prev_count);
+ new_raw_count = bb_l2_read_counter(idx);
+
+ if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+ new_raw_count) != prev_raw_count)
+ goto again;
+
+ new_raw_count &= MAX_BB_L2_PERIOD;
+ prev_raw_count &= MAX_BB_L2_PERIOD;
+
+ if (overflow) {
+ delta = MAX_BB_L2_PERIOD - prev_raw_count + new_raw_count;
+ pr_err("%s: delta: %lld\n", __func__, delta);
+ } else
+ delta = new_raw_count - prev_raw_count;
+
+ local64_add(delta, &event->count);
+ local64_sub(delta, &hwc->period_left);
+
+ pr_debug("%s: new: %lld, prev: %lld, event: %ld count: %lld\n",
+ __func__, new_raw_count, prev_raw_count,
+ hwc->config_base, local64_read(&event->count));
+
+ return new_raw_count;
+}
+
+static void bb_l2_read(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ bb_pmu_event_update(event, hwc, hwc->idx, 0);
+}
+
+static void bb_l2_stop_counter(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+
+ if (!(hwc->state & PERF_HES_STOPPED)) {
+ bb_l2_disable_intenclr(idx);
+ bb_l2_disable_counter(idx);
+
+ bb_pmu_event_update(event, hwc, idx, 0);
+ hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
+ }
+
+ pr_debug("%s: event: %ld ctr: %d stopped\n", __func__, hwc->config_base,
+ idx);
+}
+
+static void bb_l2_start_counter(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+ struct bb_l2_scorp_evt evtinfo;
+ int evtype = hwc->config_base;
+ int ev_typer;
+ unsigned long iflags;
+ int cpu_id = smp_processor_id();
+
+ if (flags & PERF_EF_RELOAD)
+ WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+ hwc->state = 0;
+
+ bb_pmu_event_set_period(event, hwc, idx);
+
+ if (hwc->config_base == BB_L2CYCLE_CTR_RAW_CODE)
+ goto out;
+
+ memset(&evtinfo, 0, sizeof(evtinfo));
+
+ ev_typer = get_bb_l2_evtinfo(evtype, &evtinfo);
+
+ raw_spin_lock_irqsave(&bb_l2_pmu_lock, iflags);
+
+ bb_l2_set_evtyper(idx, ev_typer);
+
+ bb_l2_set_evcntcr();
+
+ bb_l2_set_evfilter();
+
+ bb_l2_evt_setup(evtinfo.grp, evtinfo.val);
+
+ raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, iflags);
+
+out:
+
+ bb_l2_enable_intenset(idx);
+
+ bb_l2_enable_counter(idx);
+
+ pr_debug("%s: idx: %d, event: %d, val: %x, cpu: %d\n",
+ __func__, idx, evtype, evtinfo.val, cpu_id);
+}
+
+static void bb_l2_del_event(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+ unsigned long iflags;
+
+ raw_spin_lock_irqsave(&hw_bb_l2_pmu.lock, iflags);
+
+ clear_bit(idx, (long unsigned int *)(&hw_bb_l2_pmu.active_mask));
+
+ bb_l2_stop_counter(event, PERF_EF_UPDATE);
+ hw_bb_l2_pmu.events[idx] = NULL;
+ hwc->idx = -1;
+
+ raw_spin_unlock_irqrestore(&hw_bb_l2_pmu.lock, iflags);
+
+ pr_debug("%s: event: %ld deleted\n", __func__, hwc->config_base);
+
+ perf_event_update_userpage(event);
+}
+
+static int bb_l2_add_event(struct perf_event *event, int flags)
+{
+ int ctr = 0;
+ struct hw_perf_event *hwc = &event->hw;
+ unsigned long iflags;
+ int err = 0;
+
+ perf_pmu_disable(event->pmu);
+
+ raw_spin_lock_irqsave(&hw_bb_l2_pmu.lock, iflags);
+
+ /* Cycle counter has a resrvd index */
+ if (hwc->config_base == BB_L2CYCLE_CTR_RAW_CODE) {
+ if (hw_bb_l2_pmu.events[BB_L2CYCLE_CTR_EVENT_IDX]) {
+ pr_err("%s: Stale cycle ctr event ptr !\n", __func__);
+ err = -EINVAL;
+ goto out;
+ }
+ hwc->idx = BB_L2CYCLE_CTR_EVENT_IDX;
+ hw_bb_l2_pmu.events[BB_L2CYCLE_CTR_EVENT_IDX] = event;
+ set_bit(BB_L2CYCLE_CTR_EVENT_IDX,
+ (long unsigned int *)&hw_bb_l2_pmu.active_mask);
+ goto skip_ctr_loop;
+ }
+
+ for (ctr = 0; ctr < MAX_BB_L2_CTRS - 1; ctr++) {
+ if (!hw_bb_l2_pmu.events[ctr]) {
+ hwc->idx = ctr;
+ hw_bb_l2_pmu.events[ctr] = event;
+ set_bit(ctr, (long unsigned int *)
+ &hw_bb_l2_pmu.active_mask);
+ break;
+ }
+ }
+
+ if (hwc->idx < 0) {
+ err = -ENOSPC;
+ pr_err("%s: No space for event: %llx!!\n", __func__,
+ event->attr.config);
+ goto out;
+ }
+
+skip_ctr_loop:
+
+ bb_l2_disable_counter(hwc->idx);
+
+ hwc->state = PERF_HES_STOPPED | PERF_HES_UPTODATE;
+
+ if (flags & PERF_EF_START)
+ bb_l2_start_counter(event, PERF_EF_RELOAD);
+
+ perf_event_update_userpage(event);
+
+ pr_debug("%s: event: %ld, ctr: %d added from cpu:%d\n",
+ __func__, hwc->config_base, hwc->idx, smp_processor_id());
+out:
+ raw_spin_unlock_irqrestore(&hw_bb_l2_pmu.lock, iflags);
+
+ /* Resume the PMU even if this event could not be added */
+ perf_pmu_enable(event->pmu);
+
+ return err;
+}
+
+static void bb_l2_pmu_enable(struct pmu *pmu)
+{
+ unsigned long flags;
+ isb();
+ raw_spin_lock_irqsave(&bb_l2_pmu_lock, flags);
+ /* Enable all counters */
+ bb_l2_pmnc_write(bb_l2_pmnc_read() | SCORPIONL2_PMNC_E);
+ raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, flags);
+}
+
+static void bb_l2_pmu_disable(struct pmu *pmu)
+{
+ unsigned long flags;
+ raw_spin_lock_irqsave(&bb_l2_pmu_lock, flags);
+ /* Disable all counters */
+ bb_l2_pmnc_write(bb_l2_pmnc_read() & ~SCORPIONL2_PMNC_E);
+ raw_spin_unlock_irqrestore(&bb_l2_pmu_lock, flags);
+ isb();
+}
+
+static inline u32 bb_l2_get_reset_pmovsr(void)
+{
+ u32 val;
+
+ /* Read */
+ asm volatile ("mrc p15, 3, %0, c15, c4, 1" : "=r" (val));
+
+ /* Write to clear flags */
+ val &= 0xffffffff;
+ asm volatile ("mcr p15, 3, %0, c15, c4, 1" : : "r" (val));
+
+ return val;
+}
+
+static irqreturn_t bb_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 = bb_l2_get_reset_pmovsr();
+
+ if (!(pmovsr & 0xffffffff))
+ return IRQ_NONE;
+
+ regs = get_irq_regs();
+
+ perf_sample_data_init(&data, 0);
+
+ raw_spin_lock(&hw_bb_l2_pmu.lock);
+
+ while (pmovsr) {
+ bitp = __ffs(pmovsr);
+
+ if (bitp == BB_L2CYCLE_CTR_BIT)
+ idx = BB_L2CYCLE_CTR_EVENT_IDX;
+ else
+ idx = bitp;
+
+ event = hw_bb_l2_pmu.events[idx];
+
+ if (!event)
+ goto next;
+
+ if (!test_bit(idx, hw_bb_l2_pmu.active_mask))
+ goto next;
+
+ hwc = &event->hw;
+ bb_pmu_event_update(event, hwc, idx, 1);
+ data.period = event->hw.last_period;
+
+ if (!bb_pmu_event_set_period(event, hwc, idx))
+ goto next;
+
+ if (perf_event_overflow(event, 0, &data, regs))
+ bb_l2_disable_counter(hwc->idx);
+next:
+ pmovsr &= (pmovsr - 1);
+ }
+
+ raw_spin_unlock(&hw_bb_l2_pmu.lock);
+
+ irq_work_run();
+
+ return IRQ_HANDLED;
+}
+
+static atomic_t active_bb_l2_events = ATOMIC_INIT(0);
+static DEFINE_MUTEX(bb_pmu_reserve_mutex);
+
+static int bb_pmu_reserve_hardware(void)
+{
+ int i, err = -ENODEV, irq;
+
+ bb_l2_pmu_device = reserve_pmu(ARM_PMU_DEVICE_L2);
+
+ if (IS_ERR(bb_l2_pmu_device)) {
+ pr_warning("unable to reserve pmu\n");
+ return PTR_ERR(bb_l2_pmu_device);
+ }
+
+ if (bb_l2_pmu_device->num_resources < 1) {
+ pr_err("no irqs for PMUs defined\n");
+ return -ENODEV;
+ }
+
+ if (strncmp(bb_l2_pmu_device->name, "l2-arm-pmu", 6)) {
+ pr_err("Incorrect pdev reserved !\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bb_l2_pmu_device->num_resources; ++i) {
+ irq = platform_get_irq(bb_l2_pmu_device, i);
+ if (irq < 0)
+ continue;
+
+ err = request_irq(irq, bb_l2_handle_irq,
+ IRQF_DISABLED | IRQF_NOBALANCING,
+ "bb-l2-pmu", NULL);
+ if (err) {
+ pr_warning("unable to request IRQ%d for Krait L2 perf "
+ "counters\n", irq);
+ break;
+ }
+
+ irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
+ }
+
+ if (err) {
+ for (i = i - 1; i >= 0; --i) {
+ irq = platform_get_irq(bb_l2_pmu_device, i);
+ if (irq >= 0)
+ free_irq(irq, NULL);
+ }
+ release_pmu(bb_l2_pmu_device);
+ bb_l2_pmu_device = NULL;
+ }
+
+ return err;
+}
+
+static void bb_pmu_release_hardware(void)
+{
+ int i, irq;
+
+ for (i = bb_l2_pmu_device->num_resources - 1; i >= 0; --i) {
+ irq = platform_get_irq(bb_l2_pmu_device, i);
+ if (irq >= 0)
+ free_irq(irq, NULL);
+ }
+
+ bb_l2_pmu_disable(NULL);
+
+ release_pmu(bb_l2_pmu_device);
+ bb_l2_pmu_device = NULL;
+}
+
+static void bb_pmu_perf_event_destroy(struct perf_event *event)
+{
+ if (atomic_dec_and_mutex_lock
+ (&active_bb_l2_events, &bb_pmu_reserve_mutex)) {
+ bb_pmu_release_hardware();
+ mutex_unlock(&bb_pmu_reserve_mutex);
+ }
+}
+
+static int bb_l2_event_init(struct perf_event *event)
+{
+ int err = 0;
+ struct hw_perf_event *hwc = &event->hw;
+ int status = 0;
+
+ switch (event->attr.type) {
+ case PERF_TYPE_SHARED:
+ break;
+
+ default:
+ return -ENOENT;
+ }
+
+ hwc->idx = -1;
+
+ event->destroy = bb_pmu_perf_event_destroy;
+
+ if (!atomic_inc_not_zero(&active_bb_l2_events)) {
+ /* 0 active events */
+ mutex_lock(&bb_pmu_reserve_mutex);
+ err = bb_pmu_reserve_hardware();
+ mutex_unlock(&bb_pmu_reserve_mutex);
+ if (!err)
+ atomic_inc(&active_bb_l2_events);
+ else
+ return err;
+ } else {
+ if (atomic_read(&active_bb_l2_events) > (MAX_BB_L2_CTRS - 1)) {
+ pr_err("%s: No space left on PMU for event: %llx\n",
+ __func__, event->attr.config);
+ atomic_dec(&active_bb_l2_events);
+ return -ENOSPC;
+ }
+ }
+
+ hwc->config_base = event->attr.config & 0xff;
+ hwc->config = 0;
+ hwc->event_base = 0;
+
+ /* Only one CPU can control the cycle counter */
+ if (hwc->config_base == BB_L2CYCLE_CTR_RAW_CODE) {
+ /* Check if its already running */
+ asm volatile ("mrc p15, 3, %0, c15, c4, 6" : "=r" (status));
+ if (status == 0x2) {
+ err = -ENOSPC;
+ goto out;
+ }
+ }
+
+ if (!hwc->sample_period) {
+ hwc->sample_period = MAX_BB_L2_PERIOD;
+ hwc->last_period = hwc->sample_period;
+ local64_set(&hwc->period_left, hwc->sample_period);
+ }
+
+ pr_debug("%s: event: %lld init'd\n", __func__, event->attr.config);
+
+out:
+ if (err < 0)
+ bb_pmu_perf_event_destroy(event);
+
+ return err;
+}
+
+static struct pmu bb_l2_pmu = {
+ .pmu_enable = bb_l2_pmu_enable,
+ .pmu_disable = bb_l2_pmu_disable,
+ .event_init = bb_l2_event_init,
+ .add = bb_l2_add_event,
+ .del = bb_l2_del_event,
+ .start = bb_l2_start_counter,
+ .stop = bb_l2_stop_counter,
+ .read = bb_l2_read,
+};
+
+static const struct arm_pmu *__init scorpionmp_l2_pmu_init(void)
+{
+ /* Register our own PMU here */
+ perf_pmu_register(&bb_l2_pmu, "BB L2", PERF_TYPE_SHARED);
+
+ memset(&hw_bb_l2_pmu, 0, sizeof(hw_bb_l2_pmu));
+
+ /* Avoid spurious interrupts at startup */
+ bb_l2_get_reset_pmovsr();
+
+ /* Don't return an arm_pmu here */
+ return NULL;
+}
+#else
+
+static const struct arm_pmu *__init scorpionmp_l2_pmu_init(void)
+{
+ return NULL;
+}
+
+#endif
diff --git a/arch/arm/kernel/pmu.c b/arch/arm/kernel/pmu.c
index 2c79eec1926..a4688e8e8f6 100644
--- a/arch/arm/kernel/pmu.c
+++ b/arch/arm/kernel/pmu.c
@@ -45,16 +45,41 @@ static int __devinit pmu_device_probe(struct platform_device *pdev)
return 0;
}
-static struct platform_driver pmu_driver = {
+static struct platform_driver cpu_pmu_driver = {
.driver = {
- .name = "arm-pmu",
+ .name = "cpu-arm-pmu",
},
.probe = pmu_device_probe,
};
+static struct platform_driver l2_pmu_driver = {
+ .driver = {
+ .name = "l2-arm-pmu",
+ },
+ .probe = pmu_device_probe,
+};
+
+static struct platform_driver *pmu_drivers[] __initdata = {
+ &cpu_pmu_driver,
+ &l2_pmu_driver,
+};
+
static int __init register_pmu_driver(void)
{
- return platform_driver_register(&pmu_driver);
+ int i;
+ int err;
+
+ for (i = 0; i < ARM_NUM_PMU_DEVICES; i++) {
+ err = platform_driver_register(pmu_drivers[i]);
+ if (err) {
+ pr_err("%s: failed to register id:%d\n", __func__, i);
+ while (--i >= 0)
+ platform_driver_unregister(pmu_drivers[i]);
+ break;
+ }
+ }
+
+ return err;
}
device_initcall(register_pmu_driver);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index acbb447ac6b..6b1ee832309 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -29,6 +29,9 @@
#include
#include
#include
+#ifdef CONFIG_MEMORY_HOTPLUG
+#include
+#endif
#include
#include
@@ -97,6 +100,8 @@ EXPORT_SYMBOL(system_serial_high);
unsigned int elf_hwcap __read_mostly;
EXPORT_SYMBOL(elf_hwcap);
+unsigned int boot_reason;
+EXPORT_SYMBOL(boot_reason);
#ifdef MULTI_CPU
struct processor processor __read_mostly;
@@ -517,6 +522,62 @@ static int __init early_mem(char *p)
}
early_param("mem", early_mem);
+#ifdef CONFIG_MEMORY_HOTPLUG
+static void __init early_mem_reserved(char **p)
+{
+ unsigned int start;
+ unsigned int size;
+ unsigned int end;
+ unsigned int h_end;
+
+ start = PHYS_OFFSET;
+ size = memparse(*p, p);
+ if (**p == '@')
+ start = memparse(*p + 1, p);
+
+ if (movable_reserved_start) {
+ end = start + size;
+ h_end = movable_reserved_start + movable_reserved_size;
+ end = max(end, h_end);
+ movable_reserved_start = min(movable_reserved_start,
+ (unsigned long)start);
+ movable_reserved_size = end - movable_reserved_start;
+ } else {
+ movable_reserved_start = start;
+ movable_reserved_size = size;
+ }
+}
+__early_param("mem_reserved=", early_mem_reserved);
+
+static void __init early_mem_low_power(char **p)
+{
+ unsigned int start;
+ unsigned int size;
+ unsigned int end;
+ unsigned int h_end;
+
+ start = PHYS_OFFSET;
+ size = memparse(*p, p);
+ if (**p == '@')
+ start = memparse(*p + 1, p);
+
+ if (low_power_memory_start) {
+ end = start + size;
+ h_end = low_power_memory_start + low_power_memory_size;
+ end = max(end, h_end);
+ low_power_memory_start = min(low_power_memory_start,
+ (unsigned long)start);
+ low_power_memory_size = end - low_power_memory_start;
+ } else {
+ low_power_memory_start = start;
+ low_power_memory_size = size;
+ }
+
+ arm_add_memory(start, size);
+}
+__early_param("mem_low_power=", early_mem_low_power);
+#endif
+
static void __init
setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
{
@@ -606,6 +667,66 @@ static int __init parse_tag_mem32(const struct tag *tag)
__tagtable(ATAG_MEM, parse_tag_mem32);
+#ifdef CONFIG_MEMORY_HOTPLUG
+static int __init parse_tag_mem32_reserved(const struct tag *tag)
+{
+ unsigned int start;
+ unsigned int size;
+ unsigned int end;
+ unsigned int h_end;
+
+ start = tag->u.mem.start;
+ size = tag->u.mem.size;
+
+ if (movable_reserved_start) {
+ end = start + size;
+ h_end = movable_reserved_start + movable_reserved_size;
+ end = max(end, h_end);
+ movable_reserved_start = min(movable_reserved_start,
+ (unsigned long)start);
+ movable_reserved_size = end - movable_reserved_start;
+ } else {
+ movable_reserved_start = tag->u.mem.start;
+ movable_reserved_size = tag->u.mem.size;
+ }
+ printk(KERN_ALERT "reserved %lx at %lx for hotplug\n",
+ movable_reserved_size, movable_reserved_start);
+
+ return 0;
+}
+
+__tagtable(ATAG_MEM_RESERVED, parse_tag_mem32_reserved);
+
+static int __init parse_tag_mem32_low_power(const struct tag *tag)
+{
+ unsigned int start;
+ unsigned int size;
+ unsigned int end;
+ unsigned int h_end;
+
+ start = tag->u.mem.start;
+ size = tag->u.mem.size;
+
+ if (low_power_memory_start) {
+ end = start + size;
+ h_end = low_power_memory_start + low_power_memory_size;
+ end = max(end, h_end);
+ low_power_memory_start = min(low_power_memory_start,
+ (unsigned long)start);
+ low_power_memory_size = end - low_power_memory_start;
+ } else {
+ low_power_memory_start = tag->u.mem.start;
+ low_power_memory_size = tag->u.mem.size;
+ }
+ printk(KERN_ALERT "low power memory %lx at %lx\n",
+ low_power_memory_size, low_power_memory_start);
+
+ return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
+}
+
+__tagtable(ATAG_MEM_LOW_POWER, parse_tag_mem32_low_power);
+#endif
+
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
struct screen_info screen_info = {
.orig_video_lines = 30,
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index e7f92a4321f..1b2887b3bb8 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -597,6 +597,11 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
void smp_send_reschedule(int cpu)
{
+ if (unlikely(cpu_is_offline(cpu))) {
+ pr_warn("%s: attempt to send resched-IPI to an offline cpu.\n",
+ __func__);
+ return;
+ }
smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
}
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 2c277d40cee..f62743c6088 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -127,8 +127,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
twd_calibrate_rate();
clk->name = "local_timer";
- clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
- CLOCK_EVT_FEAT_C3STOP;
+ clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
clk->rating = 350;
clk->set_mode = twd_set_mode;
clk->set_next_event = twd_set_next_event;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 56b2715355b..aaca029f295 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -453,6 +453,10 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
up_read(&mm->mmap_sem);
flush_cache_user_range(start, end);
+
+#ifdef CONFIG_ARCH_MSM7X27
+ mb();
+#endif
return;
}
up_read(&mm->mmap_sem);
diff --git a/arch/arm/lib/delay.c b/arch/arm/lib/delay.c
new file mode 100644
index 00000000000..59fdf64b122
--- /dev/null
+++ b/arch/arm/lib/delay.c
@@ -0,0 +1,90 @@
+/*
+ * Originally from linux/arch/arm/lib/delay.S
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 1993 Linus Torvalds
+ * Copyright (C) 1997 Martin Mares
+ * Copyright (C) 2005-2006 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include
+#include
+#include
+
+/*
+ * Oh, if only we had a cycle counter...
+ */
+void delay_loop(unsigned long loops)
+{
+ asm volatile(
+ "1: subs %0, %0, #1 \n"
+ " bhi 1b \n"
+ : /* No output */
+ : "r" (loops)
+ );
+}
+
+#ifdef ARCH_HAS_READ_CURRENT_TIMER
+/*
+ * Assuming read_current_timer() is monotonically increasing
+ * across calls.
+ */
+void read_current_timer_delay_loop(unsigned long loops)
+{
+ unsigned long bclock, now;
+
+ read_current_timer(&bclock);
+ do {
+ read_current_timer(&now);
+ } while ((now - bclock) < loops);
+}
+#endif
+
+static void (*delay_fn)(unsigned long) = delay_loop;
+
+void set_delay_fn(void (*fn)(unsigned long))
+{
+ delay_fn = fn;
+}
+
+/*
+ * loops = usecs * HZ * loops_per_jiffy / 1000000
+ */
+void __delay(unsigned long loops)
+{
+ delay_fn(loops);
+}
+EXPORT_SYMBOL(__delay);
+
+/*
+ * 0 <= xloops <= 0x7fffff06
+ * loops_per_jiffy <= 0x01ffffff (max. 3355 bogomips)
+ */
+void __const_udelay(unsigned long xloops)
+{
+ unsigned long lpj;
+ unsigned long loops;
+
+ xloops >>= 14; /* max = 0x01ffffff */
+ lpj = loops_per_jiffy >> 10; /* max = 0x0001ffff */
+ loops = lpj * xloops; /* max = 0x00007fff */
+ loops >>= 6; /* max = 2^32-1 */
+
+ if (loops)
+ __delay(loops);
+}
+EXPORT_SYMBOL(__const_udelay);
+
+/*
+ * usecs <= 2000
+ * HZ <= 1000
+ */
+void __udelay(unsigned long usecs)
+{
+ __const_udelay(usecs * ((2199023*HZ)>>11));
+}
+EXPORT_SYMBOL(__udelay);
diff --git a/arch/arm/lib/lib1funcs.S b/arch/arm/lib/lib1funcs.S
index c562f649734..63b75df56d2 100644
--- a/arch/arm/lib/lib1funcs.S
+++ b/arch/arm/lib/lib1funcs.S
@@ -351,7 +351,7 @@ ENDPROC(__aeabi_idivmod)
#endif
-Ldiv0:
+ENTRY(Ldiv0)
UNWIND(.fnstart)
UNWIND(.pad #4)
UNWIND(.save {lr})
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 1516896e8d1..0685c96923d 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1,139 +1,440 @@
if ARCH_MSM
choice
- prompt "Qualcomm MSM SoC Type"
+ prompt "MSM SoC Type"
default ARCH_MSM7X00A
-config ARCH_MSM7X00A
+config ARCH_MSM7X01A
bool "MSM7x00A / MSM7x01A"
- select MACH_TROUT if !MACH_HALIBUT
select ARCH_MSM_ARM11
- select MSM_SMD
- select MSM_SMD_PKG3
+ select MSM_VIC
+ select CPU_V6
+ select MSM_REMOTE_SPINLOCK_SWP
+
+config ARCH_MSM7X25
+ bool "MSM7x25"
+ select ARCH_MSM_ARM11
+ select MSM_VIC
select CPU_V6
- select MSM_PROC_COMM
- select HAS_MSM_DEBUG_UART_PHYS
+ select MSM_REMOTE_SPINLOCK_SWP
+
+config ARCH_MSM7X27
+ bool "MSM7x27"
+ select ARCH_MSM_ARM11 if MSM_SOC_REV_NONE
+ select ARCH_HAS_BARRIERS if MSM_SOC_REV_NONE
+ select ARCH_MSM_CORTEX_A5 if MSM_SOC_REV_A
+ select MSM_VIC
+ select CPU_V6 if MSM_SOC_REV_NONE
+ select CPU_V7 if MSM_SOC_REV_A
+ select MSM_REMOTE_SPINLOCK_SWP if MSM_SOC_REV_NONE
+ select MSM_GPIOMUX
+ select REGULATOR
config ARCH_MSM7X30
bool "MSM7x30"
- select MACH_MSM7X30_SURF # if !
select ARCH_MSM_SCORPION
- select MSM_SMD
select MSM_VIC
select CPU_V7
+ select MSM_REMOTE_SPINLOCK_DEKKERS
+ select ARCH_SPARSEMEM_ENABLE
+ select MEMORY_HOTPLUG
+ select MEMORY_HOTREMOVE
+ select MIGRATION
+ select ARCH_MEMORY_PROBE
+ select ARCH_MEMORY_REMOVE
+ select DONT_RESERVE_FROM_MOVABLE_ZONE
select MSM_GPIOMUX
- select MSM_PROC_COMM
- select HAS_MSM_DEBUG_UART_PHYS
+ select RESERVE_FIRST_PAGE
+ select MSM_DALRPC
+ select MSM_SPM_V1
+ select REGULATOR
config ARCH_QSD8X50
bool "QSD8X50"
- select MACH_QSD8X50_SURF if !MACH_QSD8X50A_ST1_5
select ARCH_MSM_SCORPION
- select MSM_SMD
select MSM_VIC
select CPU_V7
+ select MSM_REMOTE_SPINLOCK_LDREX
+ select CPU_USE_DOMAINS
+ select EMULATE_DOMAIN_MANAGER_V7
select MSM_GPIOMUX
- select MSM_PROC_COMM
- select HAS_MSM_DEBUG_UART_PHYS
+ select MSM_DALRPC
config ARCH_MSM8X60
bool "MSM8X60"
- select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \
- && !MACH_MSM8X60_FFA)
select ARCH_MSM_SCORPIONMP
+ select SMP_PARALLEL_START if SMP
select ARM_GIC
select CPU_V7
+ select MSM_REMOTE_SPINLOCK_LDREX
+ select ARCH_REQUIRE_GPIOLIB
+ select MSM_ADM3
+ select REGULATOR
select MSM_V2_TLMM
+ select MSM_PIL
+ select MSM_SCM
+ select ARCH_HAS_CPU_IDLE_WAIT
+ select MSM_DIRECT_SCLK_ACCESS
+ select MSM_RPM
+ select MSM_XO
select MSM_GPIOMUX
- select MSM_SCM if SMP
+ select MSM_BUS_SCALING
+ select MSM_SECURE_IO
+ select MSM_DALRPC
+ select MSM_QDSP6_APR
+ select MSM_NATIVE_RESTART
+ select ARCH_INLINE_SPIN_TRYLOCK
+ select ARCH_INLINE_SPIN_TRYLOCK_BH
+ select ARCH_INLINE_SPIN_LOCK
+ select ARCH_INLINE_SPIN_LOCK_BH
+ select ARCH_INLINE_SPIN_LOCK_IRQ
+ select ARCH_INLINE_SPIN_LOCK_IRQSAVE
+ select ARCH_INLINE_SPIN_UNLOCK
+ select ARCH_INLINE_SPIN_UNLOCK_BH
+ select ARCH_INLINE_SPIN_UNLOCK_IRQ
+ select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE
+ select ARCH_INLINE_READ_TRYLOCK
+ select ARCH_INLINE_READ_LOCK
+ select ARCH_INLINE_READ_LOCK_BH
+ select ARCH_INLINE_READ_LOCK_IRQ
+ select ARCH_INLINE_READ_LOCK_IRQSAVE
+ select ARCH_INLINE_READ_UNLOCK
+ select ARCH_INLINE_READ_UNLOCK_BH
+ select ARCH_INLINE_READ_UNLOCK_IRQ
+ select ARCH_INLINE_READ_UNLOCK_IRQRESTORE
+ select ARCH_INLINE_WRITE_TRYLOCK
+ select ARCH_INLINE_WRITE_LOCK
+ select ARCH_INLINE_WRITE_LOCK_BH
+ select ARCH_INLINE_WRITE_LOCK_IRQ
+ select ARCH_INLINE_WRITE_LOCK_IRQSAVE
+ select ARCH_INLINE_WRITE_UNLOCK
+ select ARCH_INLINE_WRITE_UNLOCK_BH
+ select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
+ select CPU_HAS_L2_PMU
+ select MSM_SPM_V1
config ARCH_MSM8960
bool "MSM8960"
- select ARCH_MSM_SCORPIONMP
- select MACH_MSM8960_SIM if (!MACH_MSM8960_RUMI3)
+ select ARCH_MSM_KRAITMP
select ARM_GIC
select CPU_V7
select MSM_V2_TLMM
select MSM_GPIOMUX
select MSM_SCM if SMP
+ select MSM_DIRECT_SCLK_ACCESS
+ select REGULATOR
+ select MSM_RPM
+ select MSM_XO
+ select MSM_QDSP6_APR
+ select MSM_PIL
+ select MSM_AUDIO_QDSP6 if SND_SOC
+ select CPU_HAS_L2_PMU
+ select MSM_SPM_V2
+ select MSM_L2_SPM
+ select MSM_NATIVE_RESTART
+
+config ARCH_APQ8064
+ bool "APQ8064"
+ select ARCH_MSM_KRAITMP
+ select MACH_APQ8064_SIM
+ select MSM_V2_TLMM
+ select ARM_GIC
+ select CPU_V7
+ select MSM_SCM if SMP
+
+config ARCH_FSM9XXX
+ bool "FSM9XXX"
+ select ARCH_MSM_SCORPION
+ select MSM_VIC
+ select CPU_V7
+ select MSM_REMOTE_SPINLOCK_LDREX
+ select FSM9XXX_TLMM
endchoice
+choice
+ prompt "MSM SoC Revision"
+ default MSM_SOC_REV_NONE
+config MSM_SOC_REV_NONE
+ bool "N/A"
+ select EMULATE_DOMAIN_MANAGER_V7 if ARCH_QSD8X50
+ select VERIFY_PERMISSION_FAULT if ARCH_QSD8X50
config MSM_SOC_REV_A
+ bool "Rev. A"
+ select ARCH_MSM7X27A if ARCH_MSM7X27
+endchoice
+
+config ARCH_MSM_ARM11
+ bool
+
+config ARCH_MSM_SCORPION
+ bool
+
+config ARCH_MSM_KRAIT
+ bool
+
+config MSM_SMP
bool
+
config ARCH_MSM_SCORPIONMP
+ select ARCH_MSM_SCORPION
+ select MSM_SMP
bool
-config ARCH_MSM_ARM11
+config ARCH_MSM_KRAITMP
+ select ARCH_MSM_KRAIT
+ select MSM_SMP
bool
-config ARCH_MSM_SCORPION
+
+config ARCH_MSM_CORTEX_A5
bool
+ select HAVE_HW_BRKPT_RESERVED_RW_ACCESS
-config HAS_MSM_DEBUG_UART_PHYS
+config ARCH_MSM7X27A
bool
+ select MSM_DALRPC
config MSM_VIC
bool
-menu "Qualcomm MSM Board Type"
+config MSM_RPM
+ bool "Resource Power Manager"
+ select MSM_MPM
+
+config MSM_MPM
+ bool "Modem Power Manager"
+
+config MSM_XO
+ bool
+
+config MSM_REMOTE_SPINLOCK_DEKKERS
+ bool
+config MSM_REMOTE_SPINLOCK_SWP
+ bool
+config MSM_REMOTE_SPINLOCK_LDREX
+ bool
+config MSM_ADM3
+ bool
+
+menu "MSM Board Selection"
config MACH_HALIBUT
- depends on ARCH_MSM
- depends on ARCH_MSM7X00A
+ depends on ARCH_MSM7X01A
+ depends on MSM_STACKED_MEMORY
+ default y
bool "Halibut Board (QCT SURF7201A)"
help
Support for the Qualcomm SURF7201A eval board.
+config MACH_MSM7201A_SURF
+ depends on ARCH_MSM7X01A
+ depends on MSM_STACKED_MEMORY
+ default y
+ bool "MSM7201A SURF"
+ help
+ Support for the Qualcomm MSM7201A SURF eval board.
+
+config MACH_MSM7201A_FFA
+ depends on ARCH_MSM7X01A
+ depends on MSM_STACKED_MEMORY
+ default y
+ bool "MSM7201A FFA"
+ help
+ Support for the Qualcomm MSM7201A FFA eval board.
+
config MACH_TROUT
- depends on ARCH_MSM
- depends on ARCH_MSM7X00A
- bool "HTC Dream (aka trout)"
+ depends on ARCH_MSM7X01A
+ depends on MSM_STACKED_MEMORY
+ default y
+ bool "Trout"
+
+config MACH_MSM7X27_SURF
+ depends on ARCH_MSM7X27
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x27 SURF"
help
- Support for the HTC Dream, T-Mobile G1, Android ADP1 devices.
+ Support for the Qualcomm MSM7x27 SURF eval board.
-config MACH_MSM7X30_SURF
- depends on ARCH_MSM7X30
- bool "MSM7x30 SURF"
+config MACH_MSM7X27_FFA
+ depends on ARCH_MSM7X27
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x27 FFA"
help
- Support for the Qualcomm MSM7x30 SURF eval board.
+ Support for the Qualcomm MSM7x27 FFA eval board.
+
+config MACH_MSM7X27A_RUMI3
+ depends on ARCH_MSM7X27A
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x27A RUMI3"
+ help
+ Support for the Qualcomm MSM7x27A RUMI3 Emulation Platform.
+
+config MACH_MSM7X27A_SURF
+ depends on ARCH_MSM7X27A
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x27A SURF"
+ help
+ Support for the Qualcomm MSM7x27A SURF.
+
+config MACH_MSM7X27A_FFA
+ depends on ARCH_MSM7X27A
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x27A FFA"
+ help
+ Support for the Qualcomm MSM7x27A FFA.
+
+config MACH_MSM7X30_SURF
+ depends on ARCH_MSM7X30
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x30 SURF"
+ help
+ Support for the Qualcomm MSM7x30 SURF eval board.
+
+config MACH_MSM7X30_FFA
+ depends on ARCH_MSM7X30
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x30 FFA"
+ help
+ Support for the Qualcomm MSM7x30 FFA eval board.
+
+config MACH_MSM7X30_FLUID
+ depends on ARCH_MSM7X30
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x30 FLUID"
+ help
+ Support for the Qualcomm MSM7x30 FLUID eval board.
+
+config MACH_SAPPHIRE
+ depends on ARCH_MSM7X01A
+ default n
+ bool "Sapphire"
config MACH_QSD8X50_SURF
depends on ARCH_QSD8X50
+ depends on MSM_SOC_REV_NONE
+ depends on MSM_STACKED_MEMORY
+ default y
bool "QSD8x50 SURF"
help
Support for the Qualcomm QSD8x50 SURF eval board.
-config MACH_QSD8X50A_ST1_5
+config MACH_QSD8X50_FFA
depends on ARCH_QSD8X50
- select MSM_SOC_REV_A
- bool "QSD8x50A ST1.5"
+ depends on MSM_SOC_REV_NONE
+ depends on MSM_STACKED_MEMORY
+ default y
+ bool "QSD8x50 FFA"
help
- Support for the Qualcomm ST1.5.
+ Support for the Qualcomm QSD8x50 FFA eval board.
+
+config MACH_MSM7X25_SURF
+ depends on ARCH_MSM7X25
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x25 SURF"
+ help
+ Support for the Qualcomm MSM7x25 SURF eval board.
+
+config MACH_MSM7X25_FFA
+ depends on ARCH_MSM7X25
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM7x25 FFA"
+ help
+ Support for the Qualcomm MSM7x25 FFA eval board.
+
+config MACH_MSM8X55_SURF
+ depends on ARCH_MSM7X30
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM8X55 SURF"
+ help
+ Support for the Qualcomm MSM8x55 SURF eval board.
+
+config MACH_MSM8X55_FFA
+ depends on ARCH_MSM7X30
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM8X55 FFA"
+ help
+ Support for the Qualcomm MSM8x55 FFA eval board.
+
+config MACH_MSM8X55_SVLTE_FFA
+ depends on ARCH_MSM7X30
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM8X55 SVLTE FFA"
+ help
+ Support for the Qualcomm MSM8x55 SVLTE FFA eval board.
+
+config MACH_MSM8X55_SVLTE_SURF
+ depends on ARCH_MSM7X30
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "MSM8X55 SVLTE SURF"
+ help
+ Support for the Qualcomm MSM8x55 SVLTE SURF eval board.
config MACH_MSM8X60_RUMI3
depends on ARCH_MSM8X60
+ default n
bool "MSM8x60 RUMI3"
help
Support for the Qualcomm MSM8x60 RUMI3 emulator.
-config MACH_MSM8X60_SURF
- depends on ARCH_MSM8X60
- bool "MSM8x60 SURF"
- help
- Support for the Qualcomm MSM8x60 SURF eval board.
-
config MACH_MSM8X60_SIM
depends on ARCH_MSM8X60
+ default n
bool "MSM8x60 Simulator"
help
Support for the Qualcomm MSM8x60 simulator.
+config MACH_MSM8X60_SURF
+ depends on ARCH_MSM8X60
+ default n
+ bool "MSM8x60 SURF"
+ help
+ Support for the Qualcomm MSM8x60 SURF eval board.
+
config MACH_MSM8X60_FFA
depends on ARCH_MSM8X60
+ default n
bool "MSM8x60 FFA"
help
Support for the Qualcomm MSM8x60 FFA eval board.
+config MACH_MSM8X60_FLUID
+ depends on ARCH_MSM8X60
+ default n
+ bool "MSM8x60 FLUID"
+ help
+ Support for the Qualcomm MSM8x60 FLUID platform. The FLUID is an
+ 8x60 target which has a form factor that is much closer to that
+ of a phone than other targets. It also has a new display and
+ touchscreen controller.
+
+config MACH_MSM8X60_FUSION
+ depends on ARCH_MSM8X60
+ default n
+ bool "MSM8x60 FUSION"
+ help
+ Support for the Qualcomm MSM8x60 Fusion SURF device.
+
+config MACH_MSM8X60_FUSN_FFA
+ depends on ARCH_MSM8X60
+ default n
+ bool "MSM8x60 FUSN FFA"
+ help
+ Support for the Qualcomm MSM8x60 Fusion FFA device.
+
config MACH_MSM8960_SIM
depends on ARCH_MSM8960
bool "MSM8960 Simulator"
@@ -146,23 +447,110 @@ config MACH_MSM8960_RUMI3
help
Support for the Qualcomm MSM8960 RUMI3 emulator.
+config MACH_MSM8960_CDP
+ depends on ARCH_MSM8960
+ bool "MSM8960 CDP"
+ help
+ Support for the Qualcomm MSM8960 CDP device.
+
+config MACH_MSM8960_MTP
+ depends on ARCH_MSM8960
+ bool "MSM8960 MTP"
+ help
+ Support for the Qualcomm MSM8960 MTP device.
+
+config MACH_MSM8960_FLUID
+ depends on ARCH_MSM8960
+ bool "MSM8960 FLUID"
+ help
+ Support for the Qualcomm MSM8960 FLUID device.
+
+config MSM_USE_TSIF1
+ depends on ARCH_MSM8X60
+ bool "MSM8x60 use TSIF1"
+ help
+ Selects TSIF1 core to be used rather than TSIF0.
+ The two TSIF cores share the same DM configuration
+ so they cannot be used simultaneously.
+
+config MACH_APQ8064_SIM
+ depends on ARCH_APQ8064
+ bool "APQ8064 Simulator"
+ help
+ Support for the Qualcomm APQ8064 simulator.
+
+config MACH_FSM9XXX_SURF
+ depends on ARCH_FSM9XXX
+ depends on !MSM_STACKED_MEMORY
+ default y
+ bool "FSM9XXX SURF"
+ help
+ Support for the Qualcomm FSM9xxx femtocell
+ chipset based SURF evaluation board and
+ FFA board.
+
endmenu
-config MSM_IOMMU
- bool "MSM IOMMU Support"
- depends on ARCH_MSM8X60 || ARCH_MSM8960
- select IOMMU_API
- default n
+config MSM_STACKED_MEMORY
+ bool "Stacked Memory"
+ default y
help
- Support for the IOMMUs found on certain Qualcomm SOCs.
- These IOMMUs allow virtualization of the address space used by most
- cores within the multimedia subsystem.
+ This option is used to indicate the presence of on-die stacked
+ memory. When present this memory bank is used for a high speed
+ shared memory interface. When not present regular RAM is used.
- If unsure, say N here.
+config PHYS_OFFSET
+ hex
+ default "0x80200000" if ARCH_APQ8064
+ default "0x80200000" if ARCH_MSM8960
+ default "0x10000000" if ARCH_FSM9XXX
+ default "0x00200000" if !MSM_STACKED_MEMORY
+ default "0x00000000" if ARCH_QSD8X50 && MSM_SOC_REV_A
+ default "0x20000000" if ARCH_QSD8X50
+ default "0x40200000" if ARCH_MSM8X60
+ default "0x10000000"
-config IOMMU_PGTABLES_L2
- def_bool y
- depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
+config KERNEL_PMEM_EBI_REGION
+ bool "Enable in-kernel PMEM region for EBI"
+ default y if ARCH_MSM8X60
+ depends on ANDROID_PMEM && (ARCH_MSM8X60 || ARCH_MSM8960)
+ help
+ Enable the in-kernel PMEM allocator to use EBI memory.
+
+config KERNEL_PMEM_SMI_REGION
+ bool "Enable in-kernel PMEM region for SMI"
+ default y if ARCH_MSM8X60
+ depends on ANDROID_PMEM && ((ARCH_QSD8X50 && !PMEM_GPU0) || (ARCH_MSM8X60 && !VCM))
+ help
+ Enable the in-kernel PMEM allocator to use SMI memory.
+
+config PMEM_GPU0
+ bool "Enable PMEM GPU0 region"
+ default y
+ depends on ARCH_QSD8X50 && ANDROID_PMEM
+ help
+ Enable the PMEM GPU0 device on SMI Memory.
+
+config MSM_AMSS_VERSION
+ int
+ default 6210 if MSM_AMSS_VERSION_6210
+ default 6220 if MSM_AMSS_VERSION_6220
+ default 6225 if MSM_AMSS_VERSION_6225
+
+choice
+ prompt "AMSS modem firmware version"
+
+ default MSM_AMSS_VERSION_6225
+
+ config MSM_AMSS_VERSION_6210
+ bool "6.2.10"
+
+ config MSM_AMSS_VERSION_6220
+ bool "6.2.20"
+
+ config MSM_AMSS_VERSION_6225
+ bool "6.2.20 + New ADSP"
+endchoice
config MSM_DEBUG_UART
int
@@ -170,7 +558,6 @@ config MSM_DEBUG_UART
default 2 if MSM_DEBUG_UART2
default 3 if MSM_DEBUG_UART3
-if HAS_MSM_DEBUG_UART_PHYS
choice
prompt "Debug UART"
@@ -188,26 +575,1024 @@ choice
config MSM_DEBUG_UART3
bool "UART3"
endchoice
-endif
-config MSM_SMD_PKG3
- bool
+choice
+ prompt "Default Timer"
+ default MSM7X00A_USE_GP_TIMER
+
+ config MSM7X00A_USE_GP_TIMER
+ bool "GP Timer"
+ help
+ Low resolution timer that allows power collapse from idle.
+
+ config MSM7X00A_USE_DG_TIMER
+ bool "DG Timer"
+ help
+ High resolution timer.
+endchoice
+
+choice
+ prompt "Suspend sleep mode"
+ default MSM7X00A_SLEEP_MODE_POWER_COLLAPSE_SUSPEND
+ help
+ Allows overriding the sleep mode used. Leave at power
+ collapse suspend unless the arm9 image has problems.
+
+ config MSM7X00A_SLEEP_MODE_POWER_COLLAPSE_SUSPEND
+ bool "Power collapse suspend"
+ help
+ Lowest sleep state. Returns through reset vector.
+
+ config MSM7X00A_SLEEP_MODE_POWER_COLLAPSE
+ bool "Power collapse"
+ help
+ Sleep state that returns through reset vector.
+
+ config MSM7X00A_SLEEP_MODE_APPS_SLEEP
+ bool "Apps Sleep"
+
+ config MSM7X00A_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT
+ bool "Ramp down cpu clock and wait for interrupt"
+
+ config MSM7X00A_SLEEP_WAIT_FOR_INTERRUPT
+ bool "Wait for interrupt"
+endchoice
+
+config MSM7X00A_SLEEP_MODE
+ int
+ default 0 if MSM7X00A_SLEEP_MODE_POWER_COLLAPSE_SUSPEND
+ default 1 if MSM7X00A_SLEEP_MODE_POWER_COLLAPSE
+ default 2 if MSM7X00A_SLEEP_MODE_APPS_SLEEP
+ default 3 if MSM7X00A_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT
+ default 4 if MSM7X00A_SLEEP_WAIT_FOR_INTERRUPT
+
+choice
+ prompt "Idle sleep mode"
+ default MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE
+ help
+ Allows overriding the sleep mode used from idle. Leave at power
+ collapse suspend unless the arm9 image has problems.
+
+ config MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE_SUSPEND
+ bool "Power collapse suspend"
+ help
+ Lowest sleep state. Returns through reset vector.
+
+ config MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE
+ bool "Power collapse"
+ help
+ Sleep state that returns through reset vector.
+
+ config MSM7X00A_IDLE_SLEEP_MODE_APPS_SLEEP
+ bool "Apps Sleep"
+
+ config MSM7X00A_IDLE_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT
+ bool "Ramp down cpu clock and wait for interrupt"
+
+ config MSM7X00A_IDLE_SLEEP_WAIT_FOR_INTERRUPT
+ bool "Wait for interrupt"
+endchoice
+
+config MSM7X00A_IDLE_SLEEP_MODE
+ int
+ default 0 if MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE_SUSPEND
+ default 1 if MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE
+ default 2 if MSM7X00A_IDLE_SLEEP_MODE_APPS_SLEEP
+ default 3 if MSM7X00A_IDLE_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT
+ default 4 if MSM7X00A_IDLE_SLEEP_WAIT_FOR_INTERRUPT
+
+config MSM7X00A_IDLE_SLEEP_MIN_TIME
+ int "Minimum idle time before sleep"
+ default 20000000
+ help
+ Minimum idle time in nanoseconds before entering low power mode.
+
+config MSM7X00A_IDLE_SPIN_TIME
+ int "Idle spin time before cpu ramp down"
+ default 80000
+ help
+ Spin time in nanoseconds before ramping down cpu clock and entering
+ any low power state.
+
+menuconfig MSM_IDLE_STATS
+ bool "Collect idle statistics"
+ default y
+ help
+ Collect idle statistics and export them in proc/msm_pm_stats.
+
+if MSM_IDLE_STATS
+
+config MSM_IDLE_STATS_FIRST_BUCKET
+ int "First bucket time"
+ default 62500
+ help
+ Upper time limit in nanoseconds of first bucket.
+
+config MSM_IDLE_STATS_BUCKET_SHIFT
+ int "Bucket shift"
+ default 2
+
+config MSM_IDLE_STATS_BUCKET_COUNT
+ int "Bucket count"
+ default 10
+
+config MSM_SUSPEND_STATS_FIRST_BUCKET
+ int "First bucket time for suspend"
+ default 1000000000
+ help
+ Upper time limit in nanoseconds of first bucket of the
+ histogram. This is for collecting statistics on suspend.
+
+endif # MSM_IDLE_STATS
+
+config CPU_HAS_L2_PMU
+ bool "L2CC PMU Support"
+ help
+ Select this if the L2 cache controller has a Performance Monitoring Unit.
+
+config MSM_JTAG_V7
+ depends on CPU_V7
+ default y if DEBUG_KERNEL
+ bool "JTAG debug support"
+ help
+ Add additional support for JTAG kernel debugging.
+
+config HTC_HEADSET
+ tristate "HTC 2 Wire detection driver"
+ default n
+ help
+ Provides support for detecting HTC 2 wire devices, such as wired
+ headset, on the trout platform. Can be used with the msm serial
+ debugger, but not with serial console.
+
+config TROUT_BATTCHG
+ depends on MACH_TROUT && POWER_SUPPLY
+ default y
+ bool "Trout battery / charger driver"
+
+config HTC_PWRSINK
+ depends on MSM_SMD
+ default n
+ bool "HTC Power Sink Driver"
+
+config QSD_SVS
+ bool "QSD Static Voltage Scaling"
+ depends on (MACH_QSD8X50_SURF || MACH_QSD8X50_FFA)
+ default y
+ select TPS65023
+ help
+ Enables static voltage scaling using the TPS65023 PMIC.
+
+config QSD_PMIC_DEFAULT_DCDC1
+ int "PMIC default output voltage"
+ depends on (MACH_QSD8X50_SURF || MACH_QSD8X50_FFA)
+ default 1250
+ help
+ This is the PMIC voltage at Linux kernel boot.
+
+config MSM_FIQ_SUPPORT
+ default y
+ bool "Enable installation of an FIQ handler."
+
+config MSM_SERIAL_DEBUGGER
+ select MSM_FIQ_SUPPORT
+ select KERNEL_DEBUGGER_CORE
+ default n
+ bool "FIQ Mode Serial Debugger"
+ help
+ The FIQ serial debugger can accept commands even when the
+ kernel is unresponsive due to being stuck with interrupts
+ disabled. Depends on the kernel debugger core in drivers/misc.
+
+config MSM_SERIAL_DEBUGGER_CONSOLE
+ depends on MSM_SERIAL_DEBUGGER
+ default n
+ bool "Console on FIQ Serial Debugger port"
+ help
+ Enables a console so that printk messages are displayed on
+ the debugger serial port as the occur.
config MSM_PROC_COMM
- bool
+ default y
+ bool "Proc-Comm RPC Interface"
+ help
+ Enables a lightweight communications interface to the
+ baseband processor.
config MSM_SMD
- bool
+ bool "MSM Shared Memory Driver (SMD)"
+ help
+ Support for the shared memory interface between the apps
+ processor and the baseband processor. Provides access to
+ the "shared heap", as well as virtual serial channels
+ used to communicate with various services on the baseband
+ processor.
+
+choice
+ prompt "MSM Shared memory interface version"
+ depends on MSM_SMD
+ default MSM_SMD_PKG3 if ARCH_MSM_ARM11
+ default MSM_SMD_PKG4 if ARCH_MSM_SCORPION
+
+ config MSM_SMD_PKG3
+ bool
+ prompt "Package 3"
+
+ config MSM_SMD_PKG4
+ bool
+ prompt "Package 4"
+endchoice
+
+config MSM_IPC_ROUTER_SMD_XPRT
+ depends on MSM_SMD
+ default n
+ bool "MSM SMD XPRT Layer"
+ help
+ SMD Transport Layer for IPC Router
+
+config MSM_RPC_SDIO_XPRT
+ depends on MSM_SDIO_AL
+ default y
+ bool "MSM SDIO XPRT Layer"
+ help
+ SDIO Transport Layer for RPC Rouer
+
+config MSM_RPC_SDIO_DEBUG
+ depends on MSM_RPC_SDIO_XPRT
+ default y
+ bool "MSM SDIO XPRT debug support"
+ help
+ Support for debugging SDIO XPRT
+
+config MSM_SMD_DEBUG
+ depends on MSM_SMD
+ default y
+ bool "MSM SMD debug support"
+ help
+ Support for debugging the SMD for communication
+ between the ARM9 and ARM11
+
+config MSM_SDIO_AL
+ depends on ((ARCH_MSM7X30 || MACH_MSM8X60_FUSN_FFA || MACH_TYPE_MSM8X60_FUSION) && HAS_WAKELOCK)
+ default y
+ tristate "SDIO-Abstraction-Layer"
+ help
+ Support MSM<->MDM Communication over SDIO bus.
+ MDM SDIO-Client should have pipes support.
+
+config MSM_SDIO_DMUX
+ bool "SDIO Data Mux Driver"
+ depends on MSM_SDIO_AL
+ default n
+ help
+ Support Muxed Data Channels over SDIO interface.
+
+config MSM_BAM_DMUX
+ bool "BAM Data Mux Driver"
+ depends on SPS
+ default n
+ help
+ Support Muxed Data Channels over BAM interface.
+ BAM has a limited number of pipes. This driver
+ provides a means to support more logical channels
+ via muxing than BAM could without muxing.
+
+config MSM_N_WAY_SMD
+ depends on (MSM_SMD && (ARCH_MSM_SCORPION || ARCH_MSM8960 || ARCH_MSM7X27 || ARCH_MSM7X25))
+ default y
+ bool "MSM N-WAY SMD support"
+ help
+ Supports APPS-QDSP SMD communication along with
+ normal APPS-MODEM SMD communication.
+
+config MSM_N_WAY_SMSM
+ depends on (MSM_SMD && (ARCH_MSM_SCORPION || ARCH_MSM8960 || ARCH_MSM7X27 || ARCH_MSM7X25))
+ default y
+ bool "MSM N-WAY SMSM support"
+ help
+ Supports APPS-QDSP SMSM communication along with
+ normal APPS-MODEM SMSM communication.
+
+config MSM_RESET_MODEM
+ tristate "Reset Modem Driver"
+ depends on MSM_SMD
+ default m
+ help
+ Allows the user to reset the modem through a device node.
+
+config MSM_SMD_LOGGING
+ depends on MSM_SMD
+ default y
+ bool "MSM Shared Memory Logger"
+ help
+ This option exposes the shared memory logger at /dev/smem_log
+ and a debugfs node named smem_log.
+
+ If in doubt, say yes.
+
+config MSM_SMD_NMEA
+ bool "NMEA GPS Driver"
+ depends on MSM_SMD
+ default y
+ help
+ Enable this to support the NMEA GPS device.
+
+ If in doubt, say yes.
+
+config MSM_SDIO_TTY
+ bool "SDIO TTY Driver"
+ depends on MSM_SDIO_AL
+ default n
+ help
+ Provides a TTY driver SDIO TTY
+ This driver can be used by user space
+ applications for passing data through the
+ SDIO interface.
+
+config MSM_SMD_TTY
+ bool "SMD TTY Driver"
+ depends on MSM_SMD
+ default y
+ help
+ Provides TTY interfaces to interact with the modem.
+
+ If in doubt, say yes.
+
+config MSM_SMD_QMI
+ bool "SMD QMI Driver"
+ depends on MSM_SMD
+ default y
+ help
+ Manages network data connections.
+
+ If in doubt, say yes.
+
+config MSM_SMD_PKT
+ bool "SMD Packet Driver"
+ depends on MSM_SMD
+ default y
+ help
+ Provides a binary SMD non-muxed packet port interface.
+
+ If in doubt, say yes.
+
+config MSM_SDIO_CMUX
+ bool "SDIO CMUX Driver"
+ depends on MSM_SDIO_AL
+ default n
+ help
+ Provides a Muxed port interface over SDIO QMI
+
+config MSM_DSPS
+ bool "Sensors DSPS driver"
+ depends on (MSM_PIL && (ARCH_MSM8X60 || ARCH_MSM8960))
+ default n
+ help
+ Provides user-space interface to the sensors manager
+ to turn on/off the Sensors Processor system clocks.
+ It is the DSPS responsibility to turn on/off the sensors
+ themself.
+ The number of clocks and their name may vary between targets.
+ It also triggers the PIL to load the DSPS firmware.
+
+config MSM_SDIO_CTL
+ bool "SDIO CTL Driver"
+ depends on MSM_SDIO_CMUX
+ default n
+ help
+ Provides a binary SDIO control port interface.
+
+config MSM_ONCRPCROUTER
+ depends on MSM_SMD
+ default n
+ bool "MSM ONCRPC router support"
+ help
+ Support for the MSM ONCRPC router for communication between
+ the ARM9 and ARM11
+
+config MSM_IPC_ROUTER
+ depends on MSM_IPC_ROUTER_SMD_XPRT
+ default n
+ bool "MSM IPC Router support"
+ help
+ Support for the MSM IPC Router for communication between
+ the APPs and the MODEM
+
+config MSM_ONCRPCROUTER_DEBUG
+ depends on MSM_ONCRPCROUTER
+ default y
+ bool "MSM debug ONCRPC router support"
+ help
+ Support for debugging the ONCRPC router for communication
+ between the ARM9 and ARM11
+
+config MSM_RPC_LOOPBACK_XPRT
+ depends on MSM_ONCRPCROUTER
+ default n
+ bool "MSM RPC local routing support"
+ help
+ Support for routing RPC messages between APPS clients
+ and APPS servers. Helps in testing APPS RPC framework.
+
+config MSM_RPCSERVER_TIME_REMOTE
+ depends on MSM_ONCRPCROUTER && RTC_HCTOSYS
+ default y
+ bool "Time remote RPC server"
+ help
+ The time remote server receives notification of time bases and
+ reports these events to registered callback functions.
+
+config MSM_RPCSERVER_WATCHDOG
+ depends on MSM_ONCRPCROUTER
+ default y
+ bool "Watchdog RPC server"
+ help
+ The dog_keepalive server handles watchdog events.
+
+config MSM_RPC_WATCHDOG
+ depends on MSM_ONCRPCROUTER
+ default n
+ bool "Watchdog RPC client"
+ help
+ The dog_keepalive client module.
+
+config MSM_RPC_PING
+ depends on MSM_ONCRPCROUTER && DEBUG_FS
+ default m
+ bool "MSM rpc ping"
+ help
+ Implements MSM rpc ping test module.
+
+config MSM_RPC_PROC_COMM_TEST
+ depends on DEBUG_FS && MSM_PROC_COMM
+ default m
+ bool "MSM rpc proc comm test"
+ help
+ Implements MSM rpc proc comm test module.
+
+config MSM_RPC_OEM_RAPI
+ depends on MSM_ONCRPCROUTER
+ default m
+ bool "MSM oem rapi"
+ help
+ Implements MSM oem rapi client module.
+
+config MSM_RPCSERVER_HANDSET
+ depends on MSM_ONCRPCROUTER
+ default y
+ bool "Handset events RPC server"
+ help
+ Support for receiving handset events like headset detect,
+ headset switch and clamshell state.
+
+config MSM_RMT_STORAGE_CLIENT
+ depends on (ARCH_MSM && MSM_ONCRPCROUTER)
+ default n
+ bool "Remote Storage RPC client"
+ help
+ Provide RPC mechanism for remote processors to access storage
+ device on apps processor.
+
+config MSM_RMT_STORAGE_CLIENT_STATS
+ depends on (MSM_RMT_STORAGE_CLIENT && DEBUG_FS)
+ default n
+ bool "Remote storage RPC client performance statistics"
+ help
+ Collects performance statistics and shows this information
+ through a debugfs file rmt_storage_stats.
+
+config MSM_SDIO_SMEM
+ depends on MSM_SDIO_AL
+ default n
+ bool "SDIO SMEM for remote storage"
+ help
+ Copies data from remote MDM9K memory to local MSM8x60
+ memory. Used by remote storage client to shadow
+ MDM9K filesystem.
+
+config MSM_DALRPC
+ bool "DAL RPC support"
+ depends on ARCH_MSM_SCORPION || ARCH_MSM_KRAIT
+ default y
+ help
+ Supports RPC calls to DAL devices on remote processor cores.
+
+config MSM_DALRPC_TEST
+ tristate "DAL RPC test module"
+ depends on (MSM_DALRPC && DEBUG_FS)
+ default m
+ help
+ Exercises DAL RPC calls to QDSP6.
+
+if CPU_FREQ_MSM
+
+config MSM_CPU_FREQ_SET_MIN_MAX
+ bool "Set Min/Max CPU frequencies."
+ default n
+ help
+ Allow setting min and max CPU frequencies. Sysfs can be used
+ to override these values.
+
+config MSM_CPU_FREQ_MAX
+ int "Max CPU Frequency"
+ depends on MSM_CPU_FREQ_SET_MIN_MAX
+ default 384000
+
+config MSM_CPU_FREQ_MIN
+ int "Min CPU Frequency"
+ depends on MSM_CPU_FREQ_SET_MIN_MAX
+ default 245760
+
+endif # CPU_FREQ_MSM
+
+config MSM_CPU_AVS
+ bool "Enable software controlled Adaptive Voltage Scaling (AVS)"
+ depends on (ARCH_MSM_SCORPION && QSD_SVS)
+ depends on ARCH_QSD8X50
+ default n
+ select MSM_AVS_HW
+ help
+ This enables the s/w control of Adaptive Voltage Scaling feature
+ in Qualcomm ARMv7 CPUs. It adjusts the voltage for each frequency
+ based on feedback from three ring oscillators in the CPU.
+
+config MSM_AVS_HW
+ bool "Enable Adaptive Voltage Scaling (AVS)"
+ default n
+ help
+ Enable AVS hardware to fine tune voltage at each frequency. The
+ AVS hardware blocks associated with each Qualcomm ARMv7 cores can
+ fine tune the voltages based on the feedback from the ring
+ oscillators.
+
+config MSM_HW3D
+ tristate "MSM Hardware 3D Register Driver"
+ depends on ANDROID_PMEM
+ default y
+ help
+ Provides access to registers needed by the userspace OpenGL|ES
+ library.
+
+config MSM_ADSP
+ depends on (ARCH_MSM7X01A || ARCH_MSM7X25 || ARCH_MSM7X27)
+ tristate "MSM ADSP driver"
+ depends on ANDROID_PMEM
+ default y
+ help
+ Provides access to registers needed by the userspace aDSP library.
+
+config ADSP_RPC_VER
+ hex
+ default 0x30002 if (ARCH_MSM7X27 || (ARCH_MSM7X25 && AMSS_7X25_VERSION_2009))
+ default 0x30001 if (ARCH_MSM7X01A || (ARCH_MSM7X25 && AMSS_7X25_VERSION_2008))
+ depends on MSM_ADSP
+ help
+ Select proper ADSP RPC version
+choice
+ prompt "ADSP RPC version"
+
+ default AMSS_7X25_VERSION_2009
+
+ config AMSS_7X25_VERSION_2009
+ bool "2.0.09"
+
+ config AMSS_7X25_VERSION_2008
+ bool "2.0.08"
+endchoice
+
+config MSM7KV2_AUDIO
+ bool "MSM7K v2 audio"
+ depends on (ARCH_MSM7X30 && ANDROID_PMEM)
+ default y
+ help
+ Enables QDSP5V2-based audio drivers for audio playbacks and
+ voice call.
+
+config MSM_ADSP_REPORT_EVENTS
+ bool "Report modem events from the DSP"
+ default y
+ depends on (MSM_ADSP || MSM7KV2_AUDIO)
+ help
+ Normally, only messages from the aDSP are reported to userspace.
+ With this option, we report events from the aDSP as well.
+
+config MSM_QDSP6
+ tristate "QDSP6 support"
+ depends on ARCH_QSD8X50 && ANDROID_PMEM
+ default y
+ help
+ Enable support for qdsp6. This provides audio and video functionality.
+
+config MSM8X60_AUDIO
+ tristate "MSM8X60 audio support"
+ depends on ARCH_MSM8X60 && ANDROID_PMEM
+ default y
+ help
+ Enable support for qdsp6v2. This provides audio functionality.
+
+config MSM8X60_FTM_AUDIO_DEVICES
+ bool "MSM8X60 audio factory test mode support"
+ depends on MSM8X60_AUDIO
+ help
+ Enable support audio factory test mode devices. This is used
+ in a production line environment.
+
+config MSM8X60_RTAC
+ tristate "MSM8X60 real-time audio calibration support"
+ depends on MSM8X60_AUDIO
+ default n
+ help
+ Enable support for rtac in qdsp6v2. This enables calibration during
+ audio operation
+
+config MSM7X27A_AUDIO
+ bool "MSM7X27A audio support"
+ depends on ARCH_MSM7X27A && MSM_ADSP
+ default n
+ help
+ Enable support for 7x27a. This provides audio functionality.
+
+config MSM_VREG_SWITCH_INVERTED
+ bool "Reverse vreg switch polarity"
+ default n
+ help
+ Reverses the enable and disable for vreg switch.
+
+config MSM_DMA_TEST
+ tristate "MSM DMA test module"
+ default m
+ help
+ Intended to be compiled as a module. Provides a device node
+ and ioctls for testing the MSM dma system.
+
+config WIFI_CONTROL_FUNC
+ bool "Enable WiFi control function abstraction"
+ help
+ Enables Power/Reset/Carddetect function abstraction
+
+config WIFI_MEM_PREALLOC
+ depends on WIFI_CONTROL_FUNC
+ bool "Preallocate memory for WiFi buffers"
+ help
+ Preallocates memory buffers for WiFi driver
+
+config QSD_AUDIO
+ bool "QSD audio"
+ depends on ARCH_MSM_SCORPION && MSM_DALRPC && ANDROID_PMEM && !MSM_SMP
+ default y
+ help
+ Provides PCM, MP3, and AAC audio playback.
+
+config AUDIO_AAC_PLUS
+ depends on (MSM_ADSP || QSD_AUDIO || MSM7KV2_AUDIO)
+ bool "AAC+ Audio"
+ default y
+ help
+ Provides AAC+ decoding
+
+config AUDIO_ENHANCED_AAC_PLUS
+ depends on AUDIO_AAC_PLUS
+ bool "Enhanced AAC+ Audio"
+ default y
+ help
+ Provides Enhanced AAC+ decoding
+
+config SURF_FFA_GPIO_KEYPAD
+ bool "MSM SURF/FFA GPIO keypad"
+ depends on INPUT_GPIO = "y"
+ default y
+ help
+ Select if the GPIO keypad is attached.
+
+config MSM_SLEEP_TIME_OVERRIDE
+ bool "Allow overriding suspend/sleep time with PM module parameter"
+ default y
+ help
+ Enable the module parameter sleep_time_override. Specified
+ in units of seconds, it overwrites the normal sleep time of
+ suspend. The feature is required for automated power management
+ testing.
+
+config MSM_MEMORY_LOW_POWER_MODE
+ bool "Control the low power modes of memory"
+ default n
+ help
+ The application processor controls whether memory should enter
+ which low power mode.
+
+choice
+ prompt "Default Memory Low Power Mode during Idle"
+ depends on MSM_MEMORY_LOW_POWER_MODE
+ default MSM_MEMORY_LOW_POWER_MODE_IDLE_ACTIVE
+ help
+ Selects the default low power mode of the memory during idle
+ sleep.
+
+ config MSM_MEMORY_LOW_POWER_MODE_IDLE_ACTIVE
+ bool "Memory active"
+
+ config MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION
+ bool "Memory in retention"
+
+ config MSM_MEMORY_LOW_POWER_MODE_IDLE_DEEP_POWER_DOWN
+ bool "Memory in deep power down"
+endchoice
+
+choice
+ prompt "Default Memory Low Power Mode during Suspend"
+ depends on MSM_MEMORY_LOW_POWER_MODE
+ default MSM_MEMORY_LOW_POWER_MODE_SUSPEND_ACTIVE
+ help
+ Selects the default low power mode of the memory during suspend
+ sleep.
+
+ config MSM_MEMORY_LOW_POWER_MODE_SUSPEND_ACTIVE
+ bool "Memory active"
+
+ config MSM_MEMORY_LOW_POWER_MODE_SUSPEND_RETENTION
+ bool "Memory in retention"
+
+ config MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN
+ bool "Memory in deep power down"
+endchoice
+
+choice
+ prompt "Power management timeout action"
+ default MSM_PM_TIMEOUT_HALT
+ help
+ Selects the Application Processor's action when Power Management
+ times out waiting for Modem's handshake.
+
+ config MSM_PM_TIMEOUT_HALT
+ bool "Halt the Application Processor"
+
+ config MSM_PM_TIMEOUT_RESET_MODEM
+ bool "Reset the Modem Processor"
+
+ config MSM_PM_TIMEOUT_RESET_CHIP
+ bool "Reset the entire chip"
+endchoice
+
+config MSM_IDLE_WAIT_ON_MODEM
+ int "Wait for Modem to become ready for idle power collapse"
+ default 0
+ help
+ If Modem is not ready to handle Application Processor's request
+ for idle power collapse, wait the number of microseconds in case
+ Modem becomes ready soon.
+
+config MSM_PIL
+ bool "Peripheral image loading"
+ select FW_LOADER
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+ default n
+ help
+ Some peripherals need to be loaded into memory before they can be
+ brought out of reset.
+
+ Say yes to support these devices.
+
+config MSM_SECURE_PIL
+ bool "Secure Peripheral image loading"
+ depends on MSM_PIL
+ default n
+
+config MSM_SCM
+ bool "Secure Channel Manager (SCM) support"
+ default n
+
+config MSM_SUBSYSTEM_RESTART
+ bool "MSM Subsystem Restart Driver"
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+ default n
+ help
+ This option enables the MSM subsystem restart driver, which provides
+ a framework to handle subsystem crashes.
+
+config MSM_MODEM_8960
+ bool "MSM 8960 Modem driver"
+ depends on (ARCH_MSM8960)
+ help
+ This option enables the modem driver for the MSM8960, which monitors
+ modem hardware watchdog interrupt lines and plugs into the subsystem
+ restart and PIL drivers.
+
+config SCORPION_Uni_45nm_BUG
+ bool "Scorpion Uni 45nm(SC45U): Workaround for ICIMVAU and BPIMVA"
+ depends on ARCH_MSM7X30 || (ARCH_QSD8X50 && MSM_SOC_REV_A)
+ default y
+ help
+ Invalidating the Instruction Cache by Modified Virtual Address to PoU and
+ invalidating the Branch Predictor Array by Modified Virtual Address can
+ create invalid entries in the TLB with the wrong ASID values on Scorpion
+ Uniprocessor 45nm (SC45U) cores. This option enables the recommended software
+ workaround for Scorpion Uniprocessor 45nm cores.
+
+ This bug is not applicable to any ScorpionMP or Scorpion Uni 65nm(SC65U) cores.
+
+config MSM_RPM_LOG
+ tristate "MSM Resource Power Manager Log Driver"
+ depends on DEBUG_FS
+ depends on ARCH_MSM8X60
+ default n
+ help
+ This option enables a driver which can read from a circular buffer
+ of messages produced by the RPM. These messages provide diagnostic
+ information about RPM operation. The driver outputs the messages
+ via a debugfs node.
+
+config MSM_RPM_STATS_LOG
+ tristate "MSM Resource Power Manager Stat Driver"
+ depends on DEBUG_FS
+ depends on ARCH_MSM8X60
+ default n
+ help
+ This option enables a driver which reads RPM messages from a shared
+ memory location. These messages provide statistical information about
+ the low power modes that RPM enters. The drivers outputs the message
+ via a debugfs node.
+
+config MSM_IOMMU
+ bool "MSM IOMMU Support"
+ depends on ARCH_MSM8X60 || ARCH_MSM8960
+ select IOMMU_API
+ default n
+ help
+ Support for the IOMMUs found on certain Qualcomm SOCs.
+ These IOMMUs allow virtualization of the address space used by most
+ cores within the multimedia subsystem.
+
+ If unsure, say N here.
+
+config IOMMU_PGTABLES_L2
+ bool "Allow SMMU page tables in the L2 cache (Experimental)"
+ depends on MSM_IOMMU=y
+ depends on MMU
+ depends on CPU_DCACHE_DISABLE=n
+ depends on SMP
+ default y
+ help
+ Improves TLB miss latency at the expense of potential L2 pollution.
+ However, with large multimedia buffers, the TLB should mostly contain
+ section mappings and TLB misses should be quite infrequent.
+ Most people can probably say Y here.
+
+config MSM_DIRECT_SCLK_ACCESS
+ bool "Direct access to the SCLK timer"
+ default n
+
+config IOMMU_API
+ bool
config MSM_GPIOMUX
bool
config MSM_V2_TLMM
+ bool
+
+config FSM9XXX_TLMM
bool
-config IOMMU_API
+config MSM_SECURE_IO
bool
-config MSM_SCM
+config MSM_NATIVE_RESTART
bool
+
+config MSM_BUS_SCALING
+ bool "Bus scaling driver"
+ default n
+
+config MSM_WATCHDOG
+ bool "MSM Watchdog Support"
+ depends on ARCH_MSM8X60 || ARCH_MSM8960
+ help
+ This enables the watchdog as is present on 8x60. Currently we use
+ core 0's watchdog, and reset the entire SoC if it times out. It does
+ not run during the bootup process, so it will not catch any early
+ lockups.
+
+config MSM_DLOAD_MODE
+ bool "Enable download mode on crashes"
+ depends on ARCH_MSM8X60 || ARCH_MSM8960
+ default n
+ help
+ This makes the SoC enter download mode when it resets
+ due to a kernel panic. Note that this doesn't by itself
+ make the kernel reboot on a kernel panic - that must be
+ enabled via another mechanism.
+
+config MSM_ETM
+ tristate "Enable MSM ETM and ETB"
+ depends on ARCH_MSM8X60
+ help
+ This enables embedded trace collection on Qualcomm v7 CPUs.
+
+config MSM_SLEEP_STATS
+ bool "Enable exporting of MSM sleep stats to userspace"
+ depends on CPU_IDLE
+ default n
+
+config MSM_STANDALONE_POWER_COLLAPSE
+ bool "Enable standalone power collapse"
+ default n
+
+config MSM_GSBI9_UART
+ bool "Enable GSBI9 UART device"
+ default n
+ help
+ This enables GSBI9 configured into UART.
+
+config MSM_SHARED_GPIO_FOR_UART2DM
+ bool "Use shared GPIOs into UART mode"
+ depends on (ARCH_MSM7X27A && !MMC_MSM_SDC3_8_BIT_SUPPORT && !MMC_MSM_SDC4_SUPPORT)
+ help
+ This option configures GPIO muxed with SDC4/MMC3
+ 8-bit mode into UART mode. It is used for serial
+ console on UART2DM. Say Y if you want to have
+ serial console on UART2DM.
+
+config MSM_SHOW_RESUME_IRQ
+ bool "Enable logging of interrupts that could have caused resume"
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960)
+ default n
+ help
+ This option logs wake up interrupts that have triggered just before
+ the resume loop unrolls. Say Y if you want to debug why the system
+ resumed.
+
+config BT_MSM_PINTEST
+ tristate "MSM Bluetooth Pin Connectivity Test"
+ depends on ((ARCH_MSM8X60 || ARCH_MSM7X27A) && DEBUG_FS)
+ default n
+ help
+ Bluetooth MSM Pin Connectivity test module.
+ This driver provides support for verifying the MSM to BT pin
+ connectivity.
+
+config MSM_FAKE_BATTERY
+ depends on POWER_SUPPLY
+ default n
+ bool "MSM Fake Battery"
+ help
+ Enables MSM fake battery driver.
+
+config MSM_QDSP6_APR
+ bool "Audio QDSP6 APR support"
+ depends on MSM_SMD
+ default n
+ help
+ Enable APR IPC protocol support between
+ application processor and QDSP6. APR is
+ used by audio driver to configure QDSP6's
+ ASM, ADM and AFE.
+
+
+config MSM_AUDIO_QDSP6
+ bool "QDSP6 HW Audio support"
+ select SND_SOC_MSM_QDSP6_INTF
+ default n
+ help
+ Enable HW audio support in QDSP6.
+ QDSP6 can support HW encoder & decoder and audio processing
+
+config MSM_RPC_VIBRATOR
+ bool "RPC based MSM Vibrator Support"
+ depends on MSM_ONCRPCROUTER
+ help
+ Enable the vibrator support on MSM over RPC. The vibrator
+ is connected on the PMIC. Say Y if you want to enable this
+ feature.
+
+config PM8XXX_RPC_VIBRATOR
+ bool "RPC based Vibrator on PM8xxx PMICs"
+ depends on MSM_RPC_VIBRATOR
+ help
+ Enable the vibrator support on MSM over RPC. The vibrator
+ is connected on the PM8XXX PMIC. Say Y if you want to enable
+ this feature.
+
+config MSM_SPM_V1
+ bool "Driver support for SPM Version 1"
+ help
+ Enables the support for Version 1 of the SPM driver. SPM hardware is
+ used to manage the processor power during sleep. The driver allows
+ configuring SPM to allow different power modes.
+
+config MSM_SPM_V2
+ bool "Driver support for SPM Version 2"
+ help
+ Enables the support for Version 2 of the SPM driver. SPM hardware is
+ used to manage the processor power during sleep. The driver allows
+ configuring SPM to allow different power modes.
+
+config MSM_L2_SPM
+ bool "SPM support for L2 cache"
+ depends on MSM_SPM_V2
+ help
+ Enable SPM driver support for L2 cache. Some MSM chipsets allow
+ control of L2 cache low power mode with a Subsystem Power manager.
+ Enabling this driver allows configuring L2 SPM for low power modes
+ on supported chipsets.
+
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 9519fd28a02..e265f8780af 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,39 +1,252 @@
-obj-y += io.o idle.o timer.o
-obj-y += clock.o
-obj-$(CONFIG_DEBUG_FS) += clock-debug.o
+obj-y += io.o dma.o memory.o timer.o
+obj-y += clock.o clock-voter.o clock-dummy.o
+obj-y += modem_notifier.o subsystem_map.o
+obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
+obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o
+obj-$(CONFIG_KEXEC) += msm_kexec.o
+
+obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o
+ifndef CONFIG_ARCH_MSM8X60
+ obj-$(CONFIG_MSM_PROC_COMM) += clock-pcom.o
+ obj-$(CONFIG_MSM_PROC_COMM) += vreg.o mpp.o
+ ifdef CONFIG_MSM_PROC_COMM
+ifndef CONFIG_ARCH_FSM9XXX
+ obj-$(CONFIG_REGULATOR) += footswitch-pcom.o
+endif
+ obj-$(CONFIG_DEBUG_FS) += pmic_debugfs.o
+ endif
+endif
+
+obj-$(CONFIG_ARCH_MSM_ARM11) += acpuclock.o
+obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
+obj-$(CONFIG_ARCH_MSM_CORTEX_A5) += acpuclock.o
+obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o
+
+ifndef CONFIG_MSM_SMP
+obj-$(CONFIG_ARCH_MSM_SCORPION) += msm_fault_handlers.o
+endif
obj-$(CONFIG_MSM_VIC) += irq-vic.o
-obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o
-obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o
-obj-$(CONFIG_ARCH_MSM7X30) += dma.o
-obj-$(CONFIG_ARCH_QSD8X50) += dma.o sirc.o
+ifdef CONFIG_ARCH_QSD8X50
+ obj-$(CONFIG_MSM_SOC_REV_NONE) += acpuclock-8x50.o
+endif
+
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
+
+obj-$(CONFIG_MSM_CPU_AVS) += avs.o
+obj-$(CONFIG_MSM_AVS_HW) += avs_hw.o
+obj-$(CONFIG_CPU_V6) += idle-v6.o
+obj-$(CONFIG_CPU_V7) += idle-v7.o
+obj-$(CONFIG_MSM_JTAG_V7) += jtag-v7.o
-obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
+msm-etm-objs := cp14.o etm.o
+obj-$(CONFIG_MSM_ETM) += msm-etm.o
+
+quiet_cmd_mkrpcsym = MKCAP $@
+ cmd_mkrpcsym = $(PERL) $(srctree)/$(src)/mkrpcsym.pl $< $@
+
+target += smd_rpc_sym.c
+$(obj)/smd_rpc_sym.c: $(src)/smd_rpc_sym $(src)/mkrpcsym.pl
+ $(call if_changed,mkrpcsym)
-obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
-obj-$(CONFIG_MSM_SMD) += last_radio_log.o
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
+obj-$(CONFIG_MSM_SECURE_IO) += scm-io.o
+obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
+ifdef CONFIG_MSM_PIL
+obj-$(CONFIG_ARCH_MSM8X60) += peripheral-reset.o
+obj-$(CONFIG_ARCH_MSM8960) += peripheral-reset-8960.o
+endif
+obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
+obj-$(CONFIG_ARCH_FSM9XXX) += sirc-fsm9xxx.o
+obj-$(CONFIG_MSM_FIQ_SUPPORT) += fiq_glue.o
+obj-$(CONFIG_MACH_TROUT) += board-trout-rfkill.o
+obj-$(CONFIG_MSM_SDIO_AL) += sdio_al.o
+obj-$(CONFIG_MSM_SDIO_AL) += sdio_al_test.o
+obj-$(CONFIG_MSM_SDIO_AL) += sdio_al_dloader.o
+obj-$(CONFIG_MSM_SDIO_DMUX) += sdio_dmux.o
+obj-$(CONFIG_MSM_BAM_DMUX) += bam_dmux.o
+obj-$(CONFIG_MSM_SMD_LOGGING) += smem_log.o
+obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o
+ obj-y += socinfo.o
+ifndef CONFIG_ARCH_MSM8960
+ifndef CONFIG_ARCH_MSM8X60
+ obj-$(CONFIG_MSM_SMD) += pmic.o
+ obj-$(CONFIG_MSM_SMD) += nand_partitions.o
+ obj-$(CONFIG_MSM_ONCRPCROUTER) += rpc_hsusb.o rpc_pmapp.o rpc_fsusb.o
+endif
+endif
+obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o sdio_tty_ciq.o
+obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
+obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
+obj-$(CONFIG_MSM_SMD_PKT) += smd_pkt.o
+obj-$(CONFIG_MSM_SDIO_CMUX) += sdio_cmux.o
+obj-$(CONFIG_MSM_DSPS) += msm_dsps.o
+obj-$(CONFIG_MSM_SDIO_CTL) += sdio_ctl.o
+obj-$(CONFIG_MSM_SMD_NMEA) += smd_nmea.o
+obj-$(CONFIG_MSM_RESET_MODEM) += reset_modem.o
+obj-$(CONFIG_MSM_IPC_ROUTER_SMD_XPRT) += ipc_router_smd_xprt.o
+obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter.o
+obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_device.o
+obj-$(CONFIG_MSM_IPC_ROUTER) += ipc_router.o
+obj-$(CONFIG_MSM_IPC_ROUTER)+= ipc_socket.o
+obj-$(CONFIG_DEBUG_FS) += smd_rpc_sym.o
+obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_servers.o
+obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_clients.o
+obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_xdr.o
+obj-$(CONFIG_MSM_ONCRPCROUTER) += rpcrouter_smd_xprt.o
+obj-$(CONFIG_MSM_RPC_SDIO_XPRT) += rpcrouter_sdio_xprt.o
+obj-$(CONFIG_MSM_RPC_PING) += ping_mdm_rpc_client.o
+obj-$(CONFIG_MSM_RPC_PROC_COMM_TEST) += proc_comm_test.o
+obj-$(CONFIG_MSM_RPC_PING) += ping_mdm_rpc_client.o ping_apps_server.o
+obj-$(CONFIG_MSM_RPC_OEM_RAPI) += oem_rapi_client.o
+obj-$(CONFIG_MSM_RPC_WATCHDOG) += rpc_dog_keepalive.o
+obj-$(CONFIG_MSM_RPCSERVER_WATCHDOG) += rpc_server_dog_keepalive.o
+obj-$(CONFIG_MSM_RPCSERVER_TIME_REMOTE) += rpc_server_time_remote.o
+obj-$(CONFIG_MSM_DALRPC) += dal.o
+obj-$(CONFIG_MSM_DALRPC_TEST) += dal_remotetest.o
+obj-$(CONFIG_ARCH_MSM7X30) += dal_axi.o
+obj-$(CONFIG_ARCH_MSM7X27A) += dal_axi.o
+obj-$(CONFIG_MSM_ADSP) += qdsp5/
+obj-$(CONFIG_MSM7KV2_AUDIO) += qdsp5v2/
+obj-$(CONFIG_MSM_RPCSERVER_HANDSET) += rpc_server_handset.o
+obj-$(CONFIG_MSM_QDSP6) += qdsp6/
+obj-$(CONFIG_MSM8X60_AUDIO) += qdsp6v2/
+obj-$(CONFIG_MSM_AUDIO_QDSP6) += qdsp6v2/
+obj-$(CONFIG_MSM_HW3D) += hw3d.o
+ifdef CONFIG_PM
+ obj-$(CONFIG_ARCH_MSM8960) += pm-8x60.o
+ obj-$(CONFIG_ARCH_MSM8X60) += pm-8x60.o
+ obj-$(CONFIG_ARCH_QSD8X50) += pm2.o
+ obj-$(CONFIG_ARCH_MSM7X30) += pm2.o
+ obj-$(CONFIG_ARCH_MSM7X27) += pm2.o
+ obj-$(CONFIG_ARCH_MSM7X27A) += pm2.o
+ obj-$(CONFIG_ARCH_MSM7X25) += pm.o
+ obj-$(CONFIG_ARCH_MSM7X01A) += pm.o
+else
+ obj-y += no-pm.o
+endif
-obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
-obj-$(CONFIG_SMP) += headsmp.o platsmp.o
+obj-$(CONFIG_MSM_SPM_V1) += spm.o
+obj-$(CONFIG_MSM_SPM_V2) += spm-v2.o spm_devices.o
+
+obj-$(CONFIG_MSM_DMA_TEST) += dma_test.o
+obj-$(CONFIG_SURF_FFA_GPIO_KEYPAD) += keypad-surf-ffa.o
-obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
-obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o
-obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
-obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
-obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
-obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
-obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
+obj-$(CONFIG_ARCH_MSM7X01A) += board-halibut.o devices-msm7x01a.o clock-pcom-lookup.o
+obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o
+obj-$(CONFIG_MACH_TROUT) += board-trout-keypad.o board-trout-panel.o
+obj-$(CONFIG_MACH_TROUT) += htc_akm_cal.o htc_wifi_nvs.o htc_acoustic.o
+obj-$(CONFIG_MACH_TROUT) += board-trout-mmc.o board-trout-wifi.o
+obj-$(CONFIG_ARCH_QSD8X50) += devices-qsd8x50.o clock-pcom-lookup.o
+obj-$(CONFIG_MACH_QSD8X50_SURF) += board-qsd8x50.o
+obj-$(CONFIG_MACH_QSD8X50_FFA) += board-qsd8x50.o
+obj-$(CONFIG_ARCH_MSM8X60) += devices-msm8x60.o clock-local.o clock-8x60.o acpuclock-8x60.o
+obj-$(CONFIG_ARCH_MSM8X60) += clock-rpm.o
+obj-$(CONFIG_ARCH_MSM8X60) += saw-regulator.o
+obj-$(CONFIG_ARCH_MSM8X60) += rpm-regulator.o
+obj-$(CONFIG_ARCH_MSM8X60) += footswitch-8x60.o
-obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o
+ifdef CONFIG_MSM_SUBSYSTEM_RESTART
+ obj-y += subsystem_notif.o
+ obj-y += subsystem_restart.o
+ obj-y += ramdump.o
+ obj-$(CONFIG_ARCH_MSM8X60) += subsystem-fatal-8x60.o
+endif
+obj-$(CONFIG_MSM_MODEM_8960) += modem-8960.o
+
+ifdef CONFIG_CPU_IDLE
+ obj-$(CONFIG_ARCH_MSM8960) += cpuidle.o
+ obj-$(CONFIG_ARCH_MSM8X60) += cpuidle.o
+endif
+
+obj-$(CONFIG_ARCH_FSM9XXX) += devices-fsm9xxx.o
+obj-$(CONFIG_ARCH_FSM9XXX) += clock-fsm9xxx.o clock-local.o acpuclock-fsm9xxx.o
+obj-$(CONFIG_ARCH_FSM9XXX) += dfe-fsm9xxx.o rfic-fsm9xxx.o
+obj-$(CONFIG_ARCH_FSM9XXX) += restart-fsm9xxx.o
+
+obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog.o
+obj-$(CONFIG_MACH_MSM8X60_RUMI3) += board-msm8x60.o
+obj-$(CONFIG_MACH_MSM8X60_SIM) += board-msm8x60.o
+obj-$(CONFIG_MACH_MSM8X60_SURF) += board-msm8x60.o
+obj-$(CONFIG_MACH_MSM8X60_FFA) += board-msm8x60.o
+obj-$(CONFIG_MACH_MSM8X60_FLUID) += board-msm8x60.o
+obj-$(CONFIG_MACH_TYPE_MSM8X60_FUSION) += board-msm8x60.o mdm.o
+obj-$(CONFIG_MACH_MSM8X60_FUSN_FFA) += board-msm8x60.o mdm.o
+obj-$(CONFIG_TROUT_H2W) += board-trout-h2w.o
+obj-$(CONFIG_TROUT_BATTCHG) += htc_battery.o
+obj-$(CONFIG_TROUT_PWRSINK) += htc_pwrsink.o
+obj-$(CONFIG_ARCH_MSM7X27) += clock-pcom-lookup.o
+obj-$(CONFIG_MACH_MSM7X27_SURF) += board-msm7x27.o devices-msm7x27.o
+obj-$(CONFIG_MACH_MSM7X27_FFA) += board-msm7x27.o devices-msm7x27.o
+obj-$(CONFIG_ARCH_MSM7X27A) += clock-pcom-lookup.o
+obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o devices-msm7x27a.o
+obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o devices-msm7x27a.o
+obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o devices-msm7x27a.o
+obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o memory_topology.o
+obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o clock-7x30.o acpuclock-7x30.o
+obj-$(CONFIG_MACH_MSM7X25_SURF) += board-msm7x27.o devices-msm7x25.o
+obj-$(CONFIG_MACH_MSM7X25_FFA) += board-msm7x27.o devices-msm7x25.o
+obj-$(CONFIG_ARCH_MSM8960) += clock-local.o clock-dss-8960.o clock-8960.o clock-rpm.o
+obj-$(CONFIG_ARCH_MSM8960) += footswitch-8x60.o
+obj-$(CONFIG_ARCH_MSM8960) += acpuclock-8960.o
+obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o rpm-regulator-8960.o
+obj-$(CONFIG_MACH_MSM8960_SIM) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
+obj-$(CONFIG_MACH_MSM8960_RUMI3) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
+obj-$(CONFIG_MACH_MSM8960_CDP) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
+obj-$(CONFIG_MACH_MSM8960_MTP) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
+obj-$(CONFIG_MACH_MSM8960_FLUID) += board-msm8960.o devices-8960.o board-msm8960-regulator.o
+obj-$(CONFIG_ARCH_MSM8960) += bms-batterydata.o
+obj-$(CONFIG_ARCH_APQ8064) += board-apq8064.o devices-8064.o
+
+obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
+obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
+obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-mmc.o board-sapphire-wifi.o
+obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-rfkill.o msm_vibrator.o
+
+CFLAGS_msm_vibrator.o += -Idrivers/staging/android
+
+obj-$(CONFIG_ARCH_FSM9XXX) += board-fsm9xxx.o
+
+obj-$(CONFIG_TROUT_BATTCHG) += htc_battery.o
+
+obj-$(CONFIG_HTC_PWRSINK) += htc_pwrsink.o
+obj-$(CONFIG_HTC_HEADSET) += htc_headset.o
+obj-$(CONFIG_MSM_RMT_STORAGE_CLIENT) += rmt_storage_client.o
+obj-$(CONFIG_MSM_SDIO_SMEM) += sdio_smem.o
+obj-$(CONFIG_PMIC8058) += pmic8058-gpio.o pmic8058-mpp.o
+obj-$(CONFIG_MSM_RPM) += rpm.o rpm_resources.o
+obj-$(CONFIG_MSM_MPM) += mpm.o
+obj-$(CONFIG_MSM_RPM_STATS_LOG) += rpm_stats.o
+obj-$(CONFIG_MSM_RPM_LOG) += rpm_log.o
+obj-$(CONFIG_MSM_XO) += msm_xo.o
+obj-$(CONFIG_MSM_BUS_SCALING) += msm_bus/
+
+obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o iommu_domains.o
+
+ifdef CONFIG_VCM
+obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
+endif
+
+obj-$(CONFIG_ARCH_MSM7X27) += gpiomux-7x27.o gpiomux-v1.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM8960) += gpiomux-v2.o gpiomux.o
+
+ifdef CONFIG_FSM9XXX_TLMM
+obj-y += gpio-fsm9xxx.o
+else
ifdef CONFIG_MSM_V2_TLMM
-ifndef CONFIG_ARCH_MSM8960
-# TODO: TLMM Mapping issues need to be resolved
obj-y += gpio-v2.o
-endif
else
obj-y += gpio.o
endif
+endif
+
+obj-$(CONFIG_MSM_SLEEP_STATS) += msm_rq_stats.o idle_stats.o
+obj-$(CONFIG_MSM_SHOW_RESUME_IRQ) += msm_show_resume_irq.o
+obj-$(CONFIG_BT_MSM_PINTEST) += btpintest.o
+obj-$(CONFIG_MSM_FAKE_BATTERY) += fish_battery.o
+obj-$(CONFIG_MSM_RPC_VIBRATOR) += msm_vibrator.o
+obj-$(CONFIG_MSM_NATIVE_RESTART) += restart.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 24dfbf8c07c..1bbaeaf6a09 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -1,3 +1,44 @@
- zreladdr-y := 0x10008000
-params_phys-y := 0x10000100
-initrd_phys-y := 0x10800000
+# MSM7x01A
+ zreladdr-$(CONFIG_ARCH_MSM7X01A) := 0x10008000
+params_phys-$(CONFIG_ARCH_MSM7X01A) := 0x10000100
+initrd_phys-$(CONFIG_ARCH_MSM7X01A) := 0x10800000
+
+# MSM7x25
+ zreladdr-$(CONFIG_ARCH_MSM7X25) := 0x00208000
+params_phys-$(CONFIG_ARCH_MSM7X25) := 0x00200100
+initrd_phys-$(CONFIG_ARCH_MSM7X25) := 0x0A000000
+
+# MSM7x27
+ zreladdr-$(CONFIG_ARCH_MSM7X27) := 0x00208000
+params_phys-$(CONFIG_ARCH_MSM7X27) := 0x00200100
+initrd_phys-$(CONFIG_ARCH_MSM7X27) := 0x0A000000
+
+# MSM7x27A
+ zreladdr-$(CONFIG_ARCH_MSM7X27A) := 0x00208000
+params_phys-$(CONFIG_ARCH_MSM7X27A) := 0x00200100
+
+# MSM7x30
+ zreladdr-$(CONFIG_ARCH_MSM7X30) := 0x00208000
+params_phys-$(CONFIG_ARCH_MSM7X30) := 0x00200100
+initrd_phys-$(CONFIG_ARCH_MSM7X30) := 0x01200000
+
+ifeq ($(CONFIG_MSM_SOC_REV_A),y)
+# QSD8x50
+ zreladdr-$(CONFIG_ARCH_QSD8X50) := 0x20008000
+params_phys-$(CONFIG_ARCH_QSD8X50) := 0x20000100
+initrd_phys-$(CONFIG_ARCH_QSD8X50) := 0x24000000
+endif
+
+# MSM8x60
+ zreladdr-$(CONFIG_ARCH_MSM8X60) := 0x40208000
+
+# MSM8960
+ zreladdr-$(CONFIG_ARCH_MSM8960) := 0x80208000
+
+# APQ8064
+ zreladdr-$(CONFIG_ARCH_APQ8064) := 0x80208000
+
+# FSM9XXX
+ zreladdr-$(CONFIG_ARCH_FSM9XXX) := 0x10008000
+params_phys-$(CONFIG_ARCH_FSM9XXX) := 0x10000100
+initrd_phys-$(CONFIG_ARCH_FSM9XXX) := 0x12000000
diff --git a/arch/arm/mach-msm/acpuclock-7x30.c b/arch/arm/mach-msm/acpuclock-7x30.c
new file mode 100644
index 00000000000..2180a8daf4b
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-7x30.c
@@ -0,0 +1,502 @@
+/*
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "smd_private.h"
+#include "clock.h"
+#include "acpuclock.h"
+#include "spm.h"
+
+#define SCSS_CLK_CTL_ADDR (MSM_ACC_BASE + 0x04)
+#define SCSS_CLK_SEL_ADDR (MSM_ACC_BASE + 0x08)
+
+#define PLL2_L_VAL_ADDR (MSM_CLK_CTL_BASE + 0x33C)
+#define PLL2_M_VAL_ADDR (MSM_CLK_CTL_BASE + 0x340)
+#define PLL2_N_VAL_ADDR (MSM_CLK_CTL_BASE + 0x344)
+#define PLL2_CONFIG_ADDR (MSM_CLK_CTL_BASE + 0x34C)
+
+#define VREF_SEL 1 /* 0: 0.625V (50mV step), 1: 0.3125V (25mV step). */
+#define V_STEP (25 * (2 - VREF_SEL)) /* Minimum voltage step size. */
+#define VREG_DATA (VREG_CONFIG | (VREF_SEL << 5))
+#define VREG_CONFIG (BIT(7) | BIT(6)) /* Enable VREG, pull-down if disabled. */
+/* Cause a compile error if the voltage is not a multiple of the step size. */
+#define MV(mv) ((mv) / (!((mv) % V_STEP)))
+/* mv = (750mV + (raw * 25mV)) * (2 - VREF_SEL) */
+#define VDD_RAW(mv) (((MV(mv) / V_STEP) - 30) | VREG_DATA)
+
+#define MAX_AXI_KHZ 192000
+
+struct clock_state {
+ struct clkctl_acpu_speed *current_speed;
+ struct mutex lock;
+ uint32_t acpu_switch_time_us;
+ uint32_t vdd_switch_time_us;
+ struct clk *ebi1_clk;
+};
+
+struct pll {
+ unsigned int l;
+ unsigned int m;
+ unsigned int n;
+ unsigned int pre_div;
+};
+
+struct clkctl_acpu_speed {
+ unsigned int use_for_scaling;
+ unsigned int acpu_clk_khz;
+ int src;
+ unsigned int acpu_src_sel;
+ unsigned int acpu_src_div;
+ unsigned int axi_clk_hz;
+ unsigned int vdd_mv;
+ unsigned int vdd_raw;
+ struct pll *pll_rate;
+ unsigned long lpj; /* loops_per_jiffy */
+};
+
+static struct clock_state drv_state = { 0 };
+
+/* Switch to this when reprogramming PLL2 */
+static struct clkctl_acpu_speed *backup_s;
+
+static struct pll pll2_tbl[] = {
+ { 42, 0, 1, 0 }, /* 806 MHz */
+ { 53, 1, 3, 0 }, /* 1024 MHz */
+ { 125, 0, 1, 1 }, /* 1200 MHz */
+ { 73, 0, 1, 0 }, /* 1401 MHz */
+};
+
+/* Use negative numbers for sources that can't be enabled/disabled */
+
+enum acpuclk_source {
+ LPXO = -2,
+ AXI = -1,
+ PLL_0 = 0,
+ PLL_1,
+ PLL_2,
+ PLL_3,
+ MAX_SOURCE
+};
+
+static struct clk *acpuclk_sources[MAX_SOURCE];
+
+/*
+ * Each ACPU frequency has a certain minimum MSMC1 voltage requirement
+ * that is implicitly met by voting for a specific minimum AXI frequency.
+ * Do NOT change the AXI frequency unless you are _absoulutely_ sure you
+ * know all the h/w requirements.
+ */
+static struct clkctl_acpu_speed acpu_freq_tbl[] = {
+ { 0, 24576, LPXO, 0, 0, 30720000, 900, VDD_RAW(900) },
+ { 0, 61440, PLL_3, 5, 11, 61440000, 900, VDD_RAW(900) },
+ { 1, 122880, PLL_3, 5, 5, 61440000, 900, VDD_RAW(900) },
+ { 0, 184320, PLL_3, 5, 4, 61440000, 900, VDD_RAW(900) },
+ { 0, MAX_AXI_KHZ, AXI, 1, 0, 61440000, 900, VDD_RAW(900) },
+ { 1, 245760, PLL_3, 5, 2, 61440000, 900, VDD_RAW(900) },
+ { 1, 368640, PLL_3, 5, 1, 122800000, 900, VDD_RAW(900) },
+ /* AXI has MSMC1 implications. See above. */
+ { 1, 768000, PLL_1, 2, 0, 153600000, 1050, VDD_RAW(1050) },
+ /*
+ * AXI has MSMC1 implications. See above.
+ */
+ { 1, 806400, PLL_2, 3, 0, UINT_MAX, 1100, VDD_RAW(1100), &pll2_tbl[0]},
+ { 1, 1024000, PLL_2, 3, 0, UINT_MAX, 1200, VDD_RAW(1200), &pll2_tbl[1]},
+ { 1, 1200000, PLL_2, 3, 0, UINT_MAX, 1200, VDD_RAW(1200), &pll2_tbl[2]},
+ { 1, 1401600, PLL_2, 3, 0, UINT_MAX, 1250, VDD_RAW(1250), &pll2_tbl[3]},
+ { 0 }
+};
+
+#define POWER_COLLAPSE_KHZ MAX_AXI_KHZ
+unsigned long acpuclk_power_collapse(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), POWER_COLLAPSE_KHZ, SETRATE_PC);
+ return ret;
+}
+
+#define WAIT_FOR_IRQ_KHZ MAX_AXI_KHZ
+unsigned long acpuclk_wait_for_irq(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), WAIT_FOR_IRQ_KHZ, SETRATE_SWFI);
+ return ret;
+}
+
+static int acpuclk_set_acpu_vdd(struct clkctl_acpu_speed *s)
+{
+ int ret = msm_spm_set_vdd(0, s->vdd_raw);
+ if (ret)
+ return ret;
+
+ /* Wait for voltage to stabilize. */
+ udelay(drv_state.vdd_switch_time_us);
+ return 0;
+}
+
+/* Assumes PLL2 is off and the acpuclock isn't sourced from PLL2 */
+static void acpuclk_config_pll2(struct pll *pll)
+{
+ uint32_t config = readl_relaxed(PLL2_CONFIG_ADDR);
+
+ /* Make sure write to disable PLL_2 has completed
+ * before reconfiguring that PLL. */
+ mb();
+ writel_relaxed(pll->l, PLL2_L_VAL_ADDR);
+ writel_relaxed(pll->m, PLL2_M_VAL_ADDR);
+ writel_relaxed(pll->n, PLL2_N_VAL_ADDR);
+ if (pll->pre_div)
+ config |= BIT(15);
+ else
+ config &= ~BIT(15);
+ writel_relaxed(config, PLL2_CONFIG_ADDR);
+ /* Make sure PLL is programmed before returning. */
+ mb();
+}
+
+/* Set clock source and divider given a clock speed */
+static void acpuclk_set_src(const struct clkctl_acpu_speed *s)
+{
+ uint32_t reg_clksel, reg_clkctl, src_sel;
+
+ reg_clksel = readl_relaxed(SCSS_CLK_SEL_ADDR);
+
+ /* CLK_SEL_SRC1NO */
+ src_sel = reg_clksel & 1;
+
+ /* Program clock source and divider. */
+ reg_clkctl = readl_relaxed(SCSS_CLK_CTL_ADDR);
+ reg_clkctl &= ~(0xFF << (8 * src_sel));
+ reg_clkctl |= s->acpu_src_sel << (4 + 8 * src_sel);
+ reg_clkctl |= s->acpu_src_div << (0 + 8 * src_sel);
+ writel_relaxed(reg_clkctl, SCSS_CLK_CTL_ADDR);
+
+ /* Toggle clock source. */
+ reg_clksel ^= 1;
+
+ /* Program clock source selection. */
+ writel_relaxed(reg_clksel, SCSS_CLK_SEL_ADDR);
+
+ /* Make sure switch to new source is complete. */
+ mb();
+}
+
+int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason)
+{
+ struct clkctl_acpu_speed *tgt_s, *strt_s;
+ int res, rc = 0;
+
+ if (reason == SETRATE_CPUFREQ)
+ mutex_lock(&drv_state.lock);
+
+ strt_s = drv_state.current_speed;
+
+ if (rate == strt_s->acpu_clk_khz)
+ goto out;
+
+ for (tgt_s = acpu_freq_tbl; tgt_s->acpu_clk_khz != 0; tgt_s++) {
+ if (tgt_s->acpu_clk_khz == rate)
+ break;
+ }
+ if (tgt_s->acpu_clk_khz == 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (reason == SETRATE_CPUFREQ) {
+ /* Increase VDD if needed. */
+ if (tgt_s->vdd_mv > strt_s->vdd_mv) {
+ rc = acpuclk_set_acpu_vdd(tgt_s);
+ if (rc < 0) {
+ pr_err("ACPU VDD increase to %d mV failed "
+ "(%d)\n", tgt_s->vdd_mv, rc);
+ goto out;
+ }
+ }
+ }
+
+ pr_debug("Switching from ACPU rate %u KHz -> %u KHz\n",
+ strt_s->acpu_clk_khz, tgt_s->acpu_clk_khz);
+
+ /* Increase the AXI bus frequency if needed. This must be done before
+ * increasing the ACPU frequency, since voting for high AXI rates
+ * implicitly takes care of increasing the MSMC1 voltage, as needed. */
+ if (tgt_s->axi_clk_hz > strt_s->axi_clk_hz) {
+ rc = clk_set_min_rate(drv_state.ebi1_clk,
+ tgt_s->axi_clk_hz);
+ if (rc < 0) {
+ pr_err("Setting AXI min rate failed (%d)\n", rc);
+ goto out;
+ }
+ }
+
+ /* Move off of PLL2 if we're reprogramming it */
+ if (tgt_s->src == PLL_2 && strt_s->src == PLL_2) {
+ clk_enable(acpuclk_sources[backup_s->src]);
+ acpuclk_set_src(backup_s);
+ clk_disable(acpuclk_sources[strt_s->src]);
+ }
+
+ /* Reconfigure PLL2 if we're moving to it */
+ if (tgt_s->src == PLL_2)
+ acpuclk_config_pll2(tgt_s->pll_rate);
+
+ /* Make sure target PLL is on. */
+ if ((strt_s->src != tgt_s->src && tgt_s->src >= 0) ||
+ (tgt_s->src == PLL_2 && strt_s->src == PLL_2)) {
+ pr_debug("Enabling PLL %d\n", tgt_s->src);
+ clk_enable(acpuclk_sources[tgt_s->src]);
+ }
+
+ /* Perform the frequency switch */
+ acpuclk_set_src(tgt_s);
+ drv_state.current_speed = tgt_s;
+ loops_per_jiffy = tgt_s->lpj;
+
+ if (tgt_s->src == PLL_2 && strt_s->src == PLL_2)
+ clk_disable(acpuclk_sources[backup_s->src]);
+
+ /* Nothing else to do for SWFI. */
+ if (reason == SETRATE_SWFI)
+ goto out;
+
+ /* Turn off previous PLL if not used. */
+ if (strt_s->src != tgt_s->src && strt_s->src >= 0) {
+ pr_debug("Disabling PLL %d\n", strt_s->src);
+ clk_disable(acpuclk_sources[strt_s->src]);
+ }
+
+ /* Decrease the AXI bus frequency if we can. */
+ if (tgt_s->axi_clk_hz < strt_s->axi_clk_hz) {
+ res = clk_set_min_rate(drv_state.ebi1_clk,
+ tgt_s->axi_clk_hz);
+ if (res < 0)
+ pr_warning("Setting AXI min rate failed (%d)\n", res);
+ }
+
+ /* Nothing else to do for power collapse. */
+ if (reason == SETRATE_PC)
+ goto out;
+
+ /* Drop VDD level if we can. */
+ if (tgt_s->vdd_mv < strt_s->vdd_mv) {
+ res = acpuclk_set_acpu_vdd(tgt_s);
+ if (res)
+ pr_warning("ACPU VDD decrease to %d mV failed (%d)\n",
+ tgt_s->vdd_mv, res);
+ }
+
+ pr_debug("ACPU speed change complete\n");
+out:
+ if (reason == SETRATE_CPUFREQ)
+ mutex_unlock(&drv_state.lock);
+
+ return rc;
+}
+
+unsigned long acpuclk_get_rate(int cpu)
+{
+ WARN_ONCE(drv_state.current_speed == NULL,
+ "acpuclk_get_rate: not initialized\n");
+ if (drv_state.current_speed)
+ return drv_state.current_speed->acpu_clk_khz;
+ else
+ return 0;
+}
+
+uint32_t acpuclk_get_switch_time(void)
+{
+ return drv_state.acpu_switch_time_us;
+}
+
+/*----------------------------------------------------------------------------
+ * Clock driver initialization
+ *---------------------------------------------------------------------------*/
+
+static void __init acpuclk_init(void)
+{
+ struct clkctl_acpu_speed *s;
+ uint32_t div, sel, src_num;
+ uint32_t reg_clksel, reg_clkctl;
+ int res;
+ u8 pll2_l = readl_relaxed(PLL2_L_VAL_ADDR) & 0xFF;
+
+ drv_state.ebi1_clk = clk_get(NULL, "ebi1_clk");
+ BUG_ON(IS_ERR(drv_state.ebi1_clk));
+
+ reg_clksel = readl_relaxed(SCSS_CLK_SEL_ADDR);
+
+ /* Determine the ACPU clock rate. */
+ switch ((reg_clksel >> 1) & 0x3) {
+ case 0: /* Running off the output of the raw clock source mux. */
+ reg_clkctl = readl_relaxed(SCSS_CLK_CTL_ADDR);
+ src_num = reg_clksel & 0x1;
+ sel = (reg_clkctl >> (12 - (8 * src_num))) & 0x7;
+ div = (reg_clkctl >> (8 - (8 * src_num))) & 0xF;
+
+ /* Check frequency table for matching sel/div pair. */
+ for (s = acpu_freq_tbl; s->acpu_clk_khz != 0; s++) {
+ if (s->acpu_src_sel == sel && s->acpu_src_div == div)
+ break;
+ }
+ if (s->acpu_clk_khz == 0) {
+ pr_err("Error - ACPU clock reports invalid speed\n");
+ return;
+ }
+ break;
+ case 2: /* Running off of the SCPLL selected through the core mux. */
+ /* Switch to run off of the SCPLL selected through the raw
+ * clock source mux. */
+ for (s = acpu_freq_tbl; s->acpu_clk_khz != 0
+ && s->src != PLL_2 && s->acpu_src_div == 0; s++)
+ ;
+ if (s->acpu_clk_khz != 0) {
+ /* Program raw clock source mux. */
+ acpuclk_set_src(s);
+
+ /* Switch to raw clock source input of the core mux. */
+ reg_clksel = readl_relaxed(SCSS_CLK_SEL_ADDR);
+ reg_clksel &= ~(0x3 << 1);
+ writel_relaxed(reg_clksel, SCSS_CLK_SEL_ADDR);
+ break;
+ }
+ /* else fall through */
+ default:
+ pr_err("Error - ACPU clock reports invalid source\n");
+ return;
+ }
+
+ /* Look at PLL2's L val to determine what speed PLL2 is running at */
+ if (s->src == PLL_2)
+ for ( ; s->acpu_clk_khz; s++)
+ if (s->pll_rate && s->pll_rate->l == pll2_l)
+ break;
+
+ /* Set initial ACPU VDD. */
+ acpuclk_set_acpu_vdd(s);
+
+ drv_state.current_speed = s;
+
+ /* Initialize current PLL's reference count. */
+ if (s->src >= 0)
+ clk_enable(acpuclk_sources[s->src]);
+
+ res = clk_set_min_rate(drv_state.ebi1_clk, s->axi_clk_hz);
+ if (res < 0)
+ pr_warning("Setting AXI min rate failed!\n");
+
+ pr_info("ACPU running at %d KHz\n", s->acpu_clk_khz);
+
+ return;
+}
+
+/* Initalize the lpj field in the acpu_freq_tbl. */
+static void __init lpj_init(void)
+{
+ int i;
+ const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
+
+ for (i = 0; acpu_freq_tbl[i].acpu_clk_khz; i++) {
+ acpu_freq_tbl[i].lpj = cpufreq_scale(loops_per_jiffy,
+ base_clk->acpu_clk_khz,
+ acpu_freq_tbl[i].acpu_clk_khz);
+ }
+}
+
+#ifdef CONFIG_CPU_FREQ_MSM
+static struct cpufreq_frequency_table cpufreq_tbl[ARRAY_SIZE(acpu_freq_tbl)];
+
+static void setup_cpufreq_table(void)
+{
+ unsigned i = 0;
+ const struct clkctl_acpu_speed *speed;
+
+ for (speed = acpu_freq_tbl; speed->acpu_clk_khz; speed++)
+ if (speed->use_for_scaling) {
+ cpufreq_tbl[i].index = i;
+ cpufreq_tbl[i].frequency = speed->acpu_clk_khz;
+ i++;
+ }
+ cpufreq_tbl[i].frequency = CPUFREQ_TABLE_END;
+
+ cpufreq_frequency_table_get_attr(cpufreq_tbl, smp_processor_id());
+}
+#else
+static inline void setup_cpufreq_table(void) { }
+#endif
+
+/*
+ * Truncate the frequency table at the current PLL2 rate and determine the
+ * backup PLL to use when scaling PLL2.
+ */
+void __init pll2_fixup(void)
+{
+ struct clkctl_acpu_speed *speed = acpu_freq_tbl;
+ u8 pll2_l = readl_relaxed(PLL2_L_VAL_ADDR) & 0xFF;
+
+ for ( ; speed->acpu_clk_khz; speed++) {
+ if (speed->src != PLL_2)
+ backup_s = speed;
+ if (speed->pll_rate && speed->pll_rate->l == pll2_l) {
+ speed++;
+ speed->acpu_clk_khz = 0;
+ return;
+ }
+ }
+
+ pr_err("Unknown PLL2 lval %d\n", pll2_l);
+ BUG();
+}
+
+#define RPM_BYPASS_MASK (1 << 3)
+#define PMIC_MODE_MASK (1 << 4)
+
+static void __init populate_plls(void)
+{
+ acpuclk_sources[PLL_1] = clk_get_sys("acpu", "pll1_clk");
+ BUG_ON(IS_ERR(acpuclk_sources[PLL_1]));
+ acpuclk_sources[PLL_2] = clk_get_sys("acpu", "pll2_clk");
+ BUG_ON(IS_ERR(acpuclk_sources[PLL_2]));
+ acpuclk_sources[PLL_3] = clk_get_sys("acpu", "pll3_clk");
+ BUG_ON(IS_ERR(acpuclk_sources[PLL_3]));
+}
+
+void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
+{
+ pr_info("acpu_clock_init()\n");
+
+ mutex_init(&drv_state.lock);
+ drv_state.acpu_switch_time_us = clkdata->acpu_switch_time_us;
+ drv_state.vdd_switch_time_us = clkdata->vdd_switch_time_us;
+ pll2_fixup();
+ populate_plls();
+ acpuclk_init();
+ lpj_init();
+ setup_cpufreq_table();
+}
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
new file mode 100644
index 00000000000..dab55fc4bac
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -0,0 +1,969 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "acpuclock.h"
+
+/*
+ * Source IDs.
+ * These must be negative to not overlap with the source IDs
+ * used by the 8x60 local clock driver.
+ */
+#define PLL_8 0
+#define HFPLL -1
+#define QSB -2
+
+/* Mux source selects. */
+#define PRI_SRC_SEL_SEC_SRC 0
+#define PRI_SRC_SEL_HFPLL 1
+#define PRI_SRC_SEL_HFPLL_DIV2 2
+#define SEC_SRC_SEL_QSB 0
+
+/* HFPLL registers offsets. */
+#define HFPLL_MODE 0x00
+#define HFPLL_CONFIG_CTL 0x04
+#define HFPLL_L_VAL 0x08
+#define HFPLL_M_VAL 0x0C
+#define HFPLL_N_VAL 0x10
+#define HFPLL_DROOP_CTL 0x14
+
+/* CP15 L2 indirect addresses. */
+#define L2CPMR_IADDR 0x500
+#define L2CPUCPMR_IADDR 0x501
+
+#define STBY_KHZ 1
+
+#define HFPLL_NOMINAL_VDD 1050000
+#define HFPLL_LOW_VDD 1050000
+#define HFPLL_LOW_VDD_PLL_L_MAX 0x28
+
+#define SECCLKAGD BIT(4)
+
+enum scalables {
+ CPU0 = 0,
+ CPU1,
+ L2,
+ NUM_SCALABLES
+};
+
+enum vregs {
+ VREG_CORE,
+ VREG_MEM,
+ VREG_DIG,
+ NUM_VREG
+};
+
+struct vreg {
+ const char name[15];
+ const unsigned int max_vdd;
+ const int rpm_vreg_voter;
+ const int rpm_vreg_id;
+ struct regulator *reg;
+ unsigned int cur_vdd;
+};
+
+struct core_speed {
+ unsigned int khz;
+ int src;
+ unsigned int pri_src_sel;
+ unsigned int sec_src_sel;
+ unsigned int pll_l_val;
+};
+
+struct l2_level {
+ struct core_speed speed;
+ unsigned int vdd_dig;
+ unsigned int vdd_mem;
+ unsigned int bw_level;
+};
+
+struct acpu_level {
+ unsigned int use_for_scaling;
+ struct core_speed speed;
+ struct l2_level *l2_level;
+ unsigned int vdd_core;
+};
+
+struct scalable {
+ void * __iomem const hfpll_base;
+ void * __iomem const aux_clk_sel;
+ const uint32_t l2cpmr_iaddr;
+ struct core_speed *current_speed;
+ struct l2_level *l2_vote;
+ struct vreg vreg[NUM_VREG];
+ bool first_set_call;
+};
+
+static struct scalable scalable[] = {
+ [CPU0] = {
+ .hfpll_base = MSM_HFPLL_BASE + 0x200,
+ .aux_clk_sel = MSM_ACC0_BASE + 0x014,
+ .l2cpmr_iaddr = L2CPUCPMR_IADDR,
+ .vreg[VREG_CORE] = { "krait0", 1150000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000,
+ RPM_VREG_VOTER1,
+ RPM_VREG_ID_PM8921_L24 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000,
+ RPM_VREG_VOTER1,
+ RPM_VREG_ID_PM8921_S3 },
+ },
+ [CPU1] = {
+ .hfpll_base = MSM_HFPLL_BASE + 0x300,
+ .aux_clk_sel = MSM_ACC1_BASE + 0x014,
+ .l2cpmr_iaddr = L2CPUCPMR_IADDR,
+ .vreg[VREG_CORE] = { "krait1", 1150000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000,
+ RPM_VREG_VOTER2,
+ RPM_VREG_ID_PM8921_L24 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000,
+ RPM_VREG_VOTER2,
+ RPM_VREG_ID_PM8921_S3 },
+ },
+ [L2] = {
+ .hfpll_base = MSM_HFPLL_BASE + 0x400,
+ .aux_clk_sel = MSM_APCS_GCC_BASE + 0x028,
+ .l2cpmr_iaddr = L2CPMR_IADDR,
+ },
+};
+
+struct mutex driver_lock;
+static spinlock_t l2_lock;
+
+/* Instantaneous bandwidth requests in MB/s. */
+#define BW_MBPS(_bw) \
+ { \
+ .vectors = (struct msm_bus_vectors[]){ \
+ {\
+ .src = MSM_BUS_MASTER_AMPSS_M0, \
+ .dst = MSM_BUS_SLAVE_EBI_CH0, \
+ .ib = (_bw) * 1000000UL, \
+ .ab = (_bw) * 100000UL, \
+ }, \
+ { \
+ .src = MSM_BUS_MASTER_AMPSS_M1, \
+ .dst = MSM_BUS_SLAVE_EBI_CH0, \
+ .ib = (_bw) * 1000000UL, \
+ .ab = (_bw) * 100000UL, \
+ }, \
+ }, \
+ .num_paths = 2, \
+ }
+static struct msm_bus_paths bw_level_tbl[] = {
+ [0] = BW_MBPS(616), /* At least 77 MHz on bus. */
+ [1] = BW_MBPS(1024), /* At least 128 MHz on bus. */
+ [2] = BW_MBPS(1536), /* At least 192 MHz on bus. */
+ [3] = BW_MBPS(2048), /* At least 256 MHz on bus. */
+ [4] = BW_MBPS(3080), /* At least 385 MHz on bus. */
+ [5] = BW_MBPS(3968), /* At least 496 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_client_pdata = {
+ .usecase = bw_level_tbl,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl),
+ .active_only = 1,
+ .name = "acpuclock",
+};
+
+static uint32_t bus_perf_client;
+
+/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
+#define L2(x) (&l2_freq_tbl[(x)])
+#define L2_BOOT_IDX 11
+static struct l2_level l2_freq_tbl[] = {
+ [0] = { {STBY_KHZ, QSB, 0, 0, 0x00 }, 1050000, 1050000, 0 },
+ [1] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 0 },
+ [2] = { { 432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
+ [3] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 1 },
+ [4] = { { 540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 1 },
+ [5] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
+ [6] = { { 648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 2 },
+ [7] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 2 },
+ [8] = { { 756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 3 },
+ [9] = { { 810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
+ [10] = { { 864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
+ [11] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
+ [12] = { { 972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 3 },
+ [13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 3 },
+ [14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 4 },
+ [15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 4 },
+ [16] = { { 1188000, HFPLL, 1, 0, 0x2C }, 1150000, 1150000, 4 },
+ [17] = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 4 },
+ [18] = { { 1296000, HFPLL, 1, 0, 0x30 }, 1150000, 1150000, 4 },
+ [19] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 4 },
+ [20] = { { 1404000, HFPLL, 1, 0, 0x34 }, 1150000, 1150000, 4 },
+ [21] = { { 1458000, HFPLL, 1, 0, 0x36 }, 1150000, 1150000, 5 },
+ [22] = { { 1512000, HFPLL, 1, 0, 0x38 }, 1150000, 1150000, 5 },
+ [23] = { { 1566000, HFPLL, 1, 0, 0x3A }, 1150000, 1150000, 5 },
+ [24] = { { 1620000, HFPLL, 1, 0, 0x3C }, 1150000, 1150000, 5 },
+ [25] = { { 1674000, HFPLL, 1, 0, 0x3E }, 1150000, 1150000, 5 },
+};
+
+/* TODO: Update core voltages when data is available. */
+#define CPU_BOOT_IDX 11
+static struct acpu_level acpu_freq_tbl[] = {
+ { 0, {STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 1050000 },
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 1050000 },
+ { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(2), 1050000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(3), 1050000 },
+ { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(4), 1050000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(5), 1050000 },
+ { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1050000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1050000 },
+ { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(8), 1150000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(9), 1150000 },
+ { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(10), 1150000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1150000 },
+ { 0, { 0 } }
+};
+
+unsigned long acpuclk_get_rate(int cpu)
+{
+ return scalable[cpu].current_speed->khz;
+}
+
+uint32_t acpuclk_get_switch_time(void)
+{
+ return 0;
+}
+
+unsigned long acpuclk_power_collapse(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), STBY_KHZ, SETRATE_PC);
+ return ret;
+}
+
+unsigned long acpuclk_wait_for_irq(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), STBY_KHZ, SETRATE_SWFI);
+ return ret;
+}
+
+/* Read an 'indirectly' addressed L2 CP15 register. */
+static uint32_t readl_cp15_l2ind(uint32_t addr)
+{
+ uint32_t regval;
+
+ /*
+ * TODO: CP15 registers are not emulated on RUMI3.
+ * Remove this check if/when they are.
+ */
+ if (machine_is_msm8960_rumi3())
+ return 0;
+
+ asm volatile ("mcr p15, 3, %[l2cpsler], c15, c0, 6\n\t"
+ "mrc p15, 3, %[l2cpdr], c15, c0, 7\n\t"
+ : [l2cpdr]"=r" (regval)
+ : [l2cpsler]"r" (addr)
+ : "cc"
+ );
+ return regval;
+}
+
+/* Write an 'indirectly' addressed L2 CP15 register. */
+static void writel_cp15_l2ind(uint32_t regval, uint32_t addr)
+{
+ /*
+ * TODO: CP15 registers are not emulated on RUMI3.
+ * Remove this check if/when they are.
+ */
+ if (machine_is_msm8960_rumi3())
+ return;
+
+ mb();
+ asm volatile ("mcr p15, 3, %[l2cpsler], c15, c0, 6\n\t"
+ "mcr p15, 3, %[l2cpdr], c15, c0, 7\n\t"
+ :
+ : [l2cpsler]"r" (addr), [l2cpdr]"r" (regval)
+ : "cc"
+ );
+ isb();
+}
+
+/* Get the selected source on primary MUX. */
+static int get_pri_clk_src(struct scalable *sc)
+{
+ uint32_t regval;
+
+ regval = readl_cp15_l2ind(sc->l2cpmr_iaddr);
+ return regval & 0x3;
+}
+
+/* Set the selected source on primary MUX. */
+static void set_pri_clk_src(struct scalable *sc, uint32_t pri_src_sel)
+{
+ uint32_t regval;
+
+ regval = readl_cp15_l2ind(sc->l2cpmr_iaddr);
+ regval &= ~0x3;
+ regval |= (pri_src_sel & 0x3);
+ writel_cp15_l2ind(regval, sc->l2cpmr_iaddr);
+ /* Wait for switch to complete. */
+ mb();
+ udelay(1);
+}
+
+/* Get the selected source on secondary MUX. */
+static int get_sec_clk_src(struct scalable *sc)
+{
+ uint32_t regval;
+
+ regval = readl_cp15_l2ind(sc->l2cpmr_iaddr);
+ return (regval >> 2) & 0x3;
+}
+
+/* Set the selected source on secondary MUX. */
+static void set_sec_clk_src(struct scalable *sc, uint32_t sec_src_sel)
+{
+ uint32_t regval;
+
+ /* Disable secondary source clock gating during switch. */
+ regval = readl_cp15_l2ind(sc->l2cpmr_iaddr);
+ regval |= SECCLKAGD;
+ writel_cp15_l2ind(regval, sc->l2cpmr_iaddr);
+
+ /* Program the MUX. */
+ regval &= ~(0x3 << 2);
+ regval |= ((sec_src_sel & 0x3) << 2);
+ writel_cp15_l2ind(regval, sc->l2cpmr_iaddr);
+
+ /* Wait for switch to complete. */
+ mb();
+ udelay(1);
+
+ /* Re-enable secondary source clock gating. */
+ regval &= ~SECCLKAGD;
+ writel_cp15_l2ind(regval, sc->l2cpmr_iaddr);
+}
+
+/* Enable an already-configured HFPLL. */
+static void hfpll_enable(struct scalable *sc)
+{
+ /* Disable PLL bypass mode. */
+ writel_relaxed(0x2, sc->hfpll_base + HFPLL_MODE);
+
+ /*
+ * H/W requires a 5us delay between disabling the bypass and
+ * de-asserting the reset. Delay 10us just to be safe.
+ */
+ mb();
+ udelay(10);
+
+ /* De-assert active-low PLL reset. */
+ writel_relaxed(0x6, sc->hfpll_base + HFPLL_MODE);
+
+ /* Wait for PLL to lock. */
+ mb();
+ udelay(60);
+
+ /* Enable PLL output. */
+ writel_relaxed(0x7, sc->hfpll_base + HFPLL_MODE);
+}
+
+/* Disable a HFPLL for power-savings or while its being reprogrammed. */
+static void hfpll_disable(struct scalable *sc)
+{
+ /*
+ * Disable the PLL output, disable test mode, enable
+ * the bypass mode, and assert the reset.
+ */
+ writel_relaxed(0, sc->hfpll_base + HFPLL_MODE);
+}
+
+/* Program the HFPLL rate. Assumes HFPLL is already disabled. */
+static void hfpll_set_rate(struct scalable *sc, struct core_speed *tgt_s)
+{
+ writel_relaxed(tgt_s->pll_l_val, sc->hfpll_base + HFPLL_L_VAL);
+}
+
+/* Return the L2 speed that should be applied. */
+static struct l2_level *compute_l2_level(struct scalable *sc,
+ struct l2_level *vote_l)
+{
+ struct l2_level *new_l;
+ int cpu;
+
+ /* Bounds check. */
+ BUG_ON(vote_l >= (l2_freq_tbl + ARRAY_SIZE(l2_freq_tbl)));
+
+ /* Find max L2 speed vote. */
+ sc->l2_vote = vote_l;
+ new_l = l2_freq_tbl;
+ for_each_present_cpu(cpu)
+ new_l = max(new_l, scalable[cpu].l2_vote);
+
+ return new_l;
+}
+
+/* Update the bus bandwidth request. */
+static void set_bus_bw(unsigned int bw)
+{
+ int ret;
+
+ /* Bounds check. */
+ if (bw >= ARRAY_SIZE(bw_level_tbl)) {
+ pr_err("invalid bandwidth request (%d)\n", bw);
+ return;
+ }
+
+ /* Update bandwidth if request has changed. This may sleep. */
+ ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
+ if (ret)
+ pr_err("bandwidth request failed (%d)\n", ret);
+}
+
+/* Set the CPU or L2 clock speed. */
+static void set_speed(struct scalable *sc, struct core_speed *tgt_s,
+ enum setrate_reason reason)
+{
+ struct core_speed *strt_s = sc->current_speed;
+
+ if (tgt_s == strt_s)
+ return;
+
+ if (strt_s->src == HFPLL && tgt_s->src == HFPLL) {
+ /* Move CPU to QSB source. */
+ /*
+ * TODO: If using QSB here requires elevating voltages,
+ * consider using PLL8 instead.
+ */
+ set_sec_clk_src(sc, SEC_SRC_SEL_QSB);
+ set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
+
+ /* Program CPU HFPLL. */
+ hfpll_disable(sc);
+ hfpll_set_rate(sc, tgt_s);
+ hfpll_enable(sc);
+
+ /* Move CPU to HFPLL source. */
+ set_pri_clk_src(sc, tgt_s->pri_src_sel);
+ } else if (strt_s->src == HFPLL && tgt_s->src != HFPLL) {
+ /* TODO: Enable source. */
+ /*
+ * If responding to CPU_DEAD we must be running on another
+ * CPU. Therefore, we can't access the downed CPU's CP15
+ * clock MUX registers from here and can't change clock sources.
+ * Just turn off the PLL- since the CPU is down already, halting
+ * its clock should be safe.
+ */
+ if (reason != SETRATE_HOTPLUG || sc == &scalable[L2]) {
+ set_sec_clk_src(sc, tgt_s->sec_src_sel);
+ set_pri_clk_src(sc, tgt_s->pri_src_sel);
+ }
+ hfpll_disable(sc);
+ } else if (strt_s->src != HFPLL && tgt_s->src == HFPLL) {
+ hfpll_set_rate(sc, tgt_s);
+ hfpll_enable(sc);
+ /*
+ * If responding to CPU_UP_PREPARE, we can't change CP15
+ * registers for the CPU that's coming up since we're not
+ * running on that CPU. That's okay though, since the MUX
+ * source was not changed on the way down, either.
+ */
+ if (reason != SETRATE_HOTPLUG || sc == &scalable[L2])
+ set_pri_clk_src(sc, tgt_s->pri_src_sel);
+ /* TODO: Disable source. */
+ } else {
+ /* TODO: Enable source. */
+ if (reason != SETRATE_HOTPLUG || sc == &scalable[L2])
+ set_sec_clk_src(sc, tgt_s->sec_src_sel);
+ /* TODO: Disable source. */
+ }
+
+ sc->current_speed = tgt_s;
+}
+
+/* Apply any per-cpu voltage increases. */
+static int increase_vdd(int cpu, unsigned int vdd_core, unsigned int vdd_mem,
+ unsigned int vdd_dig, enum setrate_reason reason)
+{
+ struct scalable *sc = &scalable[cpu];
+ int rc;
+
+ /*
+ * Increase vdd_mem active-set before vdd_dig and vdd_core.
+ * vdd_mem should be >= both vdd_core and vdd_dig.
+ */
+ if (vdd_mem > sc->vreg[VREG_MEM].cur_vdd) {
+ rc = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
+ sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
+ sc->vreg[VREG_MEM].max_vdd, 0);
+ if (rc) {
+ pr_err("%s: vdd_mem (cpu%d) increase failed (%d)\n",
+ __func__, cpu, rc);
+ return rc;
+ }
+ sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
+ }
+
+ /* Increase vdd_dig active-set vote. */
+ if (vdd_dig > sc->vreg[VREG_DIG].cur_vdd) {
+ rc = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
+ sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
+ sc->vreg[VREG_DIG].max_vdd, 0);
+ if (rc) {
+ pr_err("%s: vdd_dig (cpu%d) increase failed (%d)\n",
+ __func__, cpu, rc);
+ return rc;
+ }
+ sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
+ }
+
+ /*
+ * Update per-CPU core voltage. Don't do this for the hotplug path for
+ * which it should already be correct. Attempting to set it is bad
+ * because we don't know what CPU we are running on at this point, but
+ * the CPU regulator API requires we call it from the affected CPU.
+ */
+ if (vdd_core > sc->vreg[VREG_CORE].cur_vdd
+ && reason != SETRATE_HOTPLUG) {
+ rc = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
+ sc->vreg[VREG_CORE].max_vdd);
+ if (rc) {
+ pr_err("%s: vdd_core (cpu%d) increase failed (%d)\n",
+ __func__, cpu, rc);
+ return rc;
+ }
+ sc->vreg[VREG_CORE].cur_vdd = vdd_core;
+ }
+
+ return rc;
+}
+
+/* Apply any per-cpu voltage decreases. */
+static void decrease_vdd(int cpu, unsigned int vdd_core, unsigned int vdd_mem,
+ unsigned int vdd_dig, enum setrate_reason reason)
+{
+ struct scalable *sc = &scalable[cpu];
+ int ret;
+
+ /*
+ * Update per-CPU core voltage. This must be called on the CPU
+ * that's being affected. Don't do this in the hotplug remove path,
+ * where the rail is off and we're executing on the other CPU.
+ */
+ if (vdd_core < sc->vreg[VREG_CORE].cur_vdd
+ && reason != SETRATE_HOTPLUG) {
+ ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
+ sc->vreg[VREG_CORE].max_vdd);
+ if (ret) {
+ pr_err("%s: vdd_core (cpu%d) decrease failed (%d)\n",
+ __func__, cpu, ret);
+ return;
+ }
+ sc->vreg[VREG_CORE].cur_vdd = vdd_core;
+ }
+
+ /* Decrease vdd_dig active-set vote. */
+ if (vdd_dig < sc->vreg[VREG_DIG].cur_vdd) {
+ ret = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
+ sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
+ sc->vreg[VREG_DIG].max_vdd, 0);
+ if (ret) {
+ pr_err("%s: vdd_dig (cpu%d) decrease failed (%d)\n",
+ __func__, cpu, ret);
+ return;
+ }
+ sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
+ }
+
+ /*
+ * Decrease vdd_mem active-set after vdd_dig and vdd_core.
+ * vdd_mem should be >= both vdd_core and vdd_dig.
+ */
+ if (vdd_mem < sc->vreg[VREG_MEM].cur_vdd) {
+ ret = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
+ sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
+ sc->vreg[VREG_MEM].max_vdd, 0);
+ if (ret) {
+ pr_err("%s: vdd_mem (cpu%d) decrease failed (%d)\n",
+ __func__, cpu, ret);
+ return;
+ }
+ sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
+ }
+}
+
+static unsigned int calculate_vdd_mem(struct acpu_level *tgt)
+{
+ return max(tgt->vdd_core, tgt->l2_level->vdd_mem);
+}
+
+static unsigned int calculate_vdd_dig(struct acpu_level *tgt)
+{
+ unsigned int pll_vdd_dig;
+
+ if (tgt->l2_level->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
+ pll_vdd_dig = HFPLL_NOMINAL_VDD;
+ else
+ pll_vdd_dig = HFPLL_LOW_VDD;
+
+ return max(tgt->l2_level->vdd_dig, pll_vdd_dig);
+}
+
+static unsigned int calculate_vdd_core(struct acpu_level *tgt)
+{
+ unsigned int pll_vdd_core;
+
+ if (tgt->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
+ pll_vdd_core = HFPLL_NOMINAL_VDD;
+ else
+ pll_vdd_core = HFPLL_LOW_VDD;
+
+ return max(tgt->vdd_core, pll_vdd_core);
+}
+
+/* Set the CPU's clock rate and adjust the L2 rate, if appropriate. */
+int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason)
+{
+ struct core_speed *strt_acpu_s, *tgt_acpu_s;
+ struct l2_level *tgt_l2_l;
+ struct acpu_level *tgt;
+ unsigned int vdd_mem, vdd_dig, vdd_core;
+ unsigned long flags;
+ int rc = 0;
+
+ if (cpu > num_possible_cpus()) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
+ mutex_lock(&driver_lock);
+
+ strt_acpu_s = scalable[cpu].current_speed;
+
+ /* Return early if rate didn't change. */
+ if (rate == strt_acpu_s->khz && scalable[cpu].first_set_call == false)
+ goto out;
+
+ /* Find target frequency. */
+ for (tgt = acpu_freq_tbl; tgt->speed.khz != 0; tgt++) {
+ if (tgt->speed.khz == rate) {
+ tgt_acpu_s = &tgt->speed;
+ break;
+ }
+ }
+ if (tgt->speed.khz == 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Calculate voltage requirements for the current CPU. */
+ vdd_mem = calculate_vdd_mem(tgt);
+ vdd_dig = calculate_vdd_dig(tgt);
+ vdd_core = calculate_vdd_core(tgt);
+
+ /* Increase VDD levels if needed. */
+ if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG) {
+ rc = increase_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
+ if (rc)
+ goto out;
+ }
+
+ pr_debug("Switching from ACPU%d rate %u KHz -> %u KHz\n",
+ cpu, strt_acpu_s->khz, tgt_acpu_s->khz);
+
+ /* Set the CPU speed. */
+ set_speed(&scalable[cpu], tgt_acpu_s, reason);
+
+ /*
+ * Update the L2 vote and apply the rate change. A spinlock is
+ * necessary to ensure L2 rate is calulated and set atomically,
+ * even if acpuclk_set_rate() is called from an atomic context
+ * and the driver_lock mutex is not acquired.
+ */
+ spin_lock_irqsave(&l2_lock, flags);
+ tgt_l2_l = compute_l2_level(&scalable[cpu], tgt->l2_level);
+ set_speed(&scalable[L2], &tgt_l2_l->speed, reason);
+ spin_unlock_irqrestore(&l2_lock, flags);
+
+ /* Nothing else to do for power collapse or SWFI. */
+ if (reason == SETRATE_PC || reason == SETRATE_SWFI)
+ goto out;
+
+ /* Update bus bandwith request. */
+ set_bus_bw(tgt_l2_l->bw_level);
+
+ /* Drop VDD levels if we can. */
+ decrease_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
+
+ scalable[cpu].first_set_call = false;
+ pr_debug("ACPU%d speed change complete\n", cpu);
+
+out:
+ if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
+ mutex_unlock(&driver_lock);
+ return rc;
+}
+
+/* Initialize a HFPLL at a given rate and enable it. */
+static void __init hfpll_init(struct scalable *sc, struct core_speed *tgt_s)
+{
+ pr_debug("Initializing HFPLL%d\n", sc - scalable);
+
+ /* Disable the PLL for re-programming. */
+ hfpll_disable(sc);
+
+ /* Configure PLL parameters for integer mode. */
+ writel_relaxed(0x7845C665, sc->hfpll_base + HFPLL_CONFIG_CTL);
+ writel_relaxed(0, sc->hfpll_base + HFPLL_M_VAL);
+ writel_relaxed(1, sc->hfpll_base + HFPLL_N_VAL);
+
+ /* Program droop controller. */
+ writel_relaxed(0x0108C000, sc->hfpll_base + HFPLL_DROOP_CTL);
+
+ /* Set an initial rate and enable the PLL. */
+ hfpll_set_rate(sc, tgt_s);
+ hfpll_enable(sc);
+}
+
+/* Voltage regulator initialization. */
+static void __init regulator_init(void)
+{
+ int cpu, ret;
+ struct scalable *sc;
+
+ for_each_possible_cpu(cpu) {
+ sc = &scalable[cpu];
+ sc->vreg[VREG_CORE].reg = regulator_get(NULL,
+ sc->vreg[VREG_CORE].name);
+ if (IS_ERR(sc->vreg[VREG_CORE].reg)) {
+ pr_err("regulator_get(%s) failed (%ld)\n",
+ sc->vreg[VREG_CORE].name,
+ PTR_ERR(sc->vreg[VREG_CORE].reg));
+ BUG();
+ }
+
+ ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg,
+ sc->vreg[VREG_CORE].max_vdd,
+ sc->vreg[VREG_CORE].max_vdd);
+ if (ret)
+ pr_err("regulator_set_voltage(%s) failed"
+ " (%d)\n", sc->vreg[VREG_CORE].name, ret);
+
+ ret = regulator_enable(sc->vreg[VREG_CORE].reg);
+ if (ret)
+ pr_err("regulator_enable(%s) failed (%d)\n",
+ sc->vreg[VREG_CORE].name, ret);
+ }
+}
+
+#define INIT_QSB_ID 0
+#define INIT_HFPLL_ID 1
+/* Set initial rate for a given core. */
+static void __init init_clock_sources(struct scalable *sc,
+ struct core_speed *tgt_s)
+{
+ uint32_t pri_src, regval;
+
+ /*
+ * If the HFPLL is in use, program AUX source for QSB, switch to it,
+ * re-initialize the HFPLL, and switch back to the HFPLL. Otherwise,
+ * the HFPLL is not in use, so we can switch directly to it.
+ */
+ pri_src = get_pri_clk_src(scalable);
+ if (pri_src == PRI_SRC_SEL_HFPLL || pri_src == PRI_SRC_SEL_HFPLL_DIV2) {
+ set_sec_clk_src(sc, SEC_SRC_SEL_QSB);
+ set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
+ }
+ hfpll_init(sc, tgt_s);
+
+ /* Set PRI_SRC_SEL_HFPLL_DIV2 divider to div-2. */
+ regval = readl_cp15_l2ind(sc->l2cpmr_iaddr);
+ regval &= ~(0x3 << 6);
+ writel_cp15_l2ind(regval, sc->l2cpmr_iaddr);
+
+ /* Select PLL8 as AUX source input to the secondary MUX. */
+ writel_relaxed(0x3, sc->aux_clk_sel);
+
+ set_pri_clk_src(sc, tgt_s->pri_src_sel);
+ sc->current_speed = tgt_s;
+
+ /*
+ * Set this flag so that the first call to acpuclk_set_rate() can drop
+ * voltages and set initial bus bandwidth requests.
+ */
+ sc->first_set_call = true;
+}
+
+/* Perform CPU0-specific setup. */
+int __init msm_acpu_clock_early_init(void)
+{
+ init_clock_sources(&scalable[L2], &l2_freq_tbl[L2_BOOT_IDX].speed);
+ init_clock_sources(&scalable[CPU0], &acpu_freq_tbl[CPU_BOOT_IDX].speed);
+ scalable[CPU0].l2_vote = &l2_freq_tbl[L2_BOOT_IDX];
+
+ return 0;
+}
+early_initcall(msm_acpu_clock_early_init);
+
+/* Perform CPU1-specific setup. */
+void __cpuinit acpuclock_secondary_init(void)
+{
+ static bool warm_boot;
+
+ if (warm_boot)
+ return;
+
+ init_clock_sources(&scalable[CPU1], &acpu_freq_tbl[CPU_BOOT_IDX].speed);
+ scalable[CPU1].l2_vote = &l2_freq_tbl[L2_BOOT_IDX];
+
+ /* Secondary CPU has booted, don't repeat for subsequent warm boots. */
+ warm_boot = true;
+}
+
+/* Register with bus driver. */
+static void __init bus_init(void)
+{
+ int ret;
+
+ bus_perf_client = msm_bus_scale_register_client(&bus_client_pdata);
+ if (!bus_perf_client) {
+ pr_err("unable to register bus client\n");
+ BUG();
+ }
+
+ ret = msm_bus_scale_client_update_request(bus_perf_client,
+ (ARRAY_SIZE(bw_level_tbl)-1));
+ if (ret)
+ pr_err("initial bandwidth request failed (%d)\n", ret);
+}
+
+#ifdef CONFIG_CPU_FREQ_MSM
+static struct cpufreq_frequency_table freq_table[NR_CPUS][30];
+
+static void __init cpufreq_table_init(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ int i, freq_cnt = 0;
+ /* Construct the freq_table tables from acpu_freq_tbl. */
+ for (i = 0; acpu_freq_tbl[i].speed.khz != 0
+ && freq_cnt < ARRAY_SIZE(*freq_table); i++) {
+ if (acpu_freq_tbl[i].use_for_scaling) {
+ freq_table[cpu][freq_cnt].index = freq_cnt;
+ freq_table[cpu][freq_cnt].frequency
+ = acpu_freq_tbl[i].speed.khz;
+ freq_cnt++;
+ }
+ }
+ /* freq_table not big enough to store all usable freqs. */
+ BUG_ON(acpu_freq_tbl[i].speed.khz != 0);
+
+ freq_table[cpu][freq_cnt].index = freq_cnt;
+ freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
+
+ pr_info("CPU%d: %d scaling frequencies supported.\n",
+ cpu, freq_cnt);
+
+ /* Register table with CPUFreq. */
+ cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
+ }
+}
+#else
+static void __init cpufreq_table_init(void) {}
+#endif
+
+#define HOT_UNPLUG_KHZ STBY_KHZ
+static int __cpuinit acpuclock_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ static int prev_khz[NR_CPUS];
+ static int prev_pri_src[NR_CPUS];
+ static int prev_sec_src[NR_CPUS];
+ int cpu = (int)hcpu;
+ uint32_t soc_platform_version = socinfo_get_platform_version();
+
+ switch (action) {
+ case CPU_DYING:
+ case CPU_DYING_FROZEN:
+ /*
+ * 8960 HW versions < 2.1 must set their primary and secondary
+ * mux source selections to QSB before L2 power collapse and
+ * restore it after.
+ */
+ if (SOCINFO_VERSION_MAJOR(soc_platform_version) < 2 ||
+ (SOCINFO_VERSION_MAJOR(soc_platform_version) == 2 &&
+ SOCINFO_VERSION_MINOR(soc_platform_version) < 1)) {
+ prev_sec_src[cpu] = get_sec_clk_src(&scalable[cpu]);
+ prev_pri_src[cpu] = get_pri_clk_src(&scalable[cpu]);
+ set_sec_clk_src(&scalable[cpu], SEC_SRC_SEL_QSB);
+ set_pri_clk_src(&scalable[cpu], PRI_SRC_SEL_SEC_SRC);
+ }
+ break;
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ prev_khz[cpu] = acpuclk_get_rate(cpu);
+ /* Fall through. */
+ case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
+ acpuclk_set_rate(cpu, HOT_UNPLUG_KHZ, SETRATE_HOTPLUG);
+ break;
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ if (WARN_ON(!prev_khz[cpu]))
+ prev_khz[cpu] = acpu_freq_tbl->speed.khz;
+ acpuclk_set_rate(cpu, prev_khz[cpu], SETRATE_HOTPLUG);
+ break;
+ case CPU_STARTING:
+ case CPU_STARTING_FROZEN:
+ if (SOCINFO_VERSION_MAJOR(soc_platform_version) < 2 ||
+ (SOCINFO_VERSION_MAJOR(soc_platform_version) == 2 &&
+ SOCINFO_VERSION_MINOR(soc_platform_version) < 1)) {
+ set_sec_clk_src(&scalable[cpu], prev_sec_src[cpu]);
+ set_pri_clk_src(&scalable[cpu], prev_pri_src[cpu]);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata acpuclock_cpu_notifier = {
+ .notifier_call = acpuclock_cpu_callback,
+};
+
+void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
+{
+ mutex_init(&driver_lock);
+ regulator_init();
+ bus_init();
+ cpufreq_table_init();
+ register_hotcpu_notifier(&acpuclock_cpu_notifier);
+}
diff --git a/arch/arm/mach-msm/acpuclock-8x50.c b/arch/arm/mach-msm/acpuclock-8x50.c
new file mode 100644
index 00000000000..1b2416a492c
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8x50.c
@@ -0,0 +1,723 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "acpuclock.h"
+#include "avs.h"
+
+#define SHOT_SWITCH 4
+#define HOP_SWITCH 5
+#define SIMPLE_SLEW 6
+#define COMPLEX_SLEW 7
+
+#define SPSS_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
+#define SPSS_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
+
+/* Scorpion PLL registers */
+#define SCPLL_CTL_ADDR (MSM_SCPLL_BASE + 0x4)
+#define SCPLL_STATUS_ADDR (MSM_SCPLL_BASE + 0x18)
+#define SCPLL_FSM_CTL_EXT_ADDR (MSM_SCPLL_BASE + 0x10)
+
+enum {
+ ACPU_PLL_TCXO = -1,
+ ACPU_PLL_0 = 0,
+ ACPU_PLL_1,
+ ACPU_PLL_2,
+ ACPU_PLL_3,
+ ACPU_PLL_END,
+};
+
+struct clkctl_acpu_speed {
+ unsigned int use_for_scaling;
+ unsigned int acpuclk_khz;
+ int pll;
+ unsigned int acpuclk_src_sel;
+ unsigned int acpuclk_src_div;
+ unsigned int ahbclk_khz;
+ unsigned int ahbclk_div;
+ unsigned int axiclk_khz;
+ unsigned int sc_core_src_sel_mask;
+ unsigned int sc_l_value;
+ int vdd;
+ unsigned long lpj; /* loops_per_jiffy */
+};
+
+struct clkctl_acpu_speed acpu_freq_tbl_998[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 0, 0, 14000, 0, 0, 1000},
+ { 0, 128000, ACPU_PLL_1, 1, 5, 0, 0, 14000, 2, 0, 1000},
+ { 1, 245760, ACPU_PLL_0, 4, 0, 0, 0, 29000, 0, 0, 1000},
+ /* Update AXI_S and PLL0_S macros if above row numbers change. */
+ { 1, 384000, ACPU_PLL_3, 0, 0, 0, 0, 58000, 1, 0xA, 1000},
+ { 0, 422400, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xB, 1000},
+ { 0, 460800, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xC, 1000},
+ { 0, 499200, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xD, 1050},
+ { 0, 537600, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xE, 1050},
+ { 1, 576000, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xF, 1050},
+ { 0, 614400, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0x10, 1075},
+ { 0, 652800, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0x11, 1100},
+ { 0, 691200, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0x12, 1125},
+ { 0, 729600, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0x13, 1150},
+ { 1, 768000, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x14, 1150},
+ { 0, 806400, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x15, 1175},
+ { 0, 844800, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x16, 1225},
+ { 0, 883200, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x17, 1250},
+ { 0, 921600, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x18, 1300},
+ { 0, 960000, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x19, 1300},
+ { 1, 998400, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x1A, 1300},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+struct clkctl_acpu_speed acpu_freq_tbl_768[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 0, 0, 14000, 0, 0, 1000},
+ { 0, 128000, ACPU_PLL_1, 1, 5, 0, 0, 14000, 2, 0, 1000},
+ { 1, 245760, ACPU_PLL_0, 4, 0, 0, 0, 29000, 0, 0, 1000},
+ /* Update AXI_S and PLL0_S macros if above row numbers change. */
+ { 1, 384000, ACPU_PLL_3, 0, 0, 0, 0, 58000, 1, 0xA, 1075},
+ { 0, 422400, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xB, 1100},
+ { 0, 460800, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xC, 1125},
+ { 0, 499200, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xD, 1150},
+ { 0, 537600, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xE, 1150},
+ { 1, 576000, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0xF, 1150},
+ { 0, 614400, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0x10, 1175},
+ { 0, 652800, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0x11, 1200},
+ { 0, 691200, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0x12, 1225},
+ { 0, 729600, ACPU_PLL_3, 0, 0, 0, 0, 117000, 1, 0x13, 1250},
+ { 1, 768000, ACPU_PLL_3, 0, 0, 0, 0, 128000, 1, 0x14, 1250},
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+static struct clkctl_acpu_speed *acpu_freq_tbl = acpu_freq_tbl_998;
+#define AXI_S (&acpu_freq_tbl[1])
+#define PLL0_S (&acpu_freq_tbl[2])
+
+/* Use 128MHz for PC since ACPU will auto-switch to AXI (128MHz) before
+ * coming back up. This allows detection of return-from-PC, since 128MHz
+ * is only used for power collapse. */
+#define POWER_COLLAPSE_KHZ (AXI_S->acpuclk_khz)
+/* Use 245MHz (not 128MHz) for SWFI to avoid unnecessary steps between
+ * 128MHz<->245MHz. Jumping to high frequencies from 128MHz directly
+ * is not allowed. */
+#define WAIT_FOR_IRQ_KHZ (PLL0_S->acpuclk_khz)
+
+#ifdef CONFIG_CPU_FREQ_MSM
+static struct cpufreq_frequency_table freq_table[20];
+
+static void __init cpufreq_table_init(void)
+{
+ unsigned int i;
+ unsigned int freq_cnt = 0;
+
+ /* Construct the freq_table table from acpu_freq_tbl since the
+ * freq_table values need to match frequencies specified in
+ * acpu_freq_tbl and acpu_freq_tbl needs to be fixed up during init.
+ */
+ for (i = 0; acpu_freq_tbl[i].acpuclk_khz != 0
+ && freq_cnt < ARRAY_SIZE(freq_table)-1; i++) {
+ if (acpu_freq_tbl[i].use_for_scaling) {
+ freq_table[freq_cnt].index = freq_cnt;
+ freq_table[freq_cnt].frequency
+ = acpu_freq_tbl[i].acpuclk_khz;
+ freq_cnt++;
+ }
+ }
+
+ /* freq_table not big enough to store all usable freqs. */
+ BUG_ON(acpu_freq_tbl[i].acpuclk_khz != 0);
+
+ freq_table[freq_cnt].index = freq_cnt;
+ freq_table[freq_cnt].frequency = CPUFREQ_TABLE_END;
+
+ pr_info("%d scaling frequencies supported.\n", freq_cnt);
+}
+#endif
+
+struct clock_state {
+ struct clkctl_acpu_speed *current_speed;
+ struct mutex lock;
+ uint32_t acpu_switch_time_us;
+ uint32_t max_speed_delta_khz;
+ uint32_t vdd_switch_time_us;
+ unsigned int max_vdd;
+ struct clk *ebi1_clk;
+ int (*acpu_set_vdd) (int mvolts);
+};
+
+static struct clock_state drv_state = { 0 };
+
+static void scpll_set_freq(uint32_t lval, unsigned freq_switch)
+{
+ uint32_t regval;
+
+ if (lval > 33)
+ lval = 33;
+ if (lval < 10)
+ lval = 10;
+
+ /* wait for any calibrations or frequency switches to finish */
+ while (readl(SCPLL_STATUS_ADDR) & 0x3)
+ ;
+
+ /* write the new L val and switch mode */
+ regval = readl(SCPLL_FSM_CTL_EXT_ADDR);
+ regval &= ~(0x3f << 3);
+ regval |= (lval << 3);
+ if (freq_switch == SIMPLE_SLEW)
+ regval |= (0x1 << 9);
+
+ regval &= ~(0x3 << 0);
+ regval |= (freq_switch << 0);
+ writel(regval, SCPLL_FSM_CTL_EXT_ADDR);
+
+ dmb();
+
+ /* put in normal mode */
+ regval = readl(SCPLL_CTL_ADDR);
+ regval |= 0x7;
+ writel(regval, SCPLL_CTL_ADDR);
+
+ dmb();
+
+ /* wait for frequency switch to finish */
+ while (readl(SCPLL_STATUS_ADDR) & 0x1)
+ ;
+
+ /* status bit seems to clear early, using
+ * 100us to handle the worst case. */
+ udelay(100);
+}
+
+static void scpll_apps_enable(bool state)
+{
+ uint32_t regval;
+
+ if (state)
+ pr_debug("Enabling PLL 3\n");
+ else
+ pr_debug("Disabling PLL 3\n");
+
+ /* Wait for any frequency switches to finish. */
+ while (readl(SCPLL_STATUS_ADDR) & 0x1)
+ ;
+
+ /* put the pll in standby mode */
+ regval = readl(SCPLL_CTL_ADDR);
+ regval &= ~(0x7);
+ regval |= (0x2);
+ writel(regval, SCPLL_CTL_ADDR);
+
+ dmb();
+
+ if (state) {
+ /* put the pll in normal mode */
+ regval = readl(SCPLL_CTL_ADDR);
+ regval |= (0x7);
+ writel(regval, SCPLL_CTL_ADDR);
+ udelay(200);
+ } else {
+ /* put the pll in power down mode */
+ regval = readl(SCPLL_CTL_ADDR);
+ regval &= ~(0x7);
+ writel(regval, SCPLL_CTL_ADDR);
+ }
+ udelay(drv_state.vdd_switch_time_us);
+
+ if (state)
+ pr_debug("PLL 3 Enabled\n");
+ else
+ pr_debug("PLL 3 Disabled\n");
+}
+
+static void scpll_init(void)
+{
+ uint32_t regval;
+#define L_VAL_384MHZ 0xA
+#define L_VAL_768MHZ 0x14
+
+ pr_debug("Initializing PLL 3\n");
+
+ /* power down scpll */
+ writel(0x0, SCPLL_CTL_ADDR);
+
+ dmb();
+
+ /* set bypassnl, put into standby */
+ writel(0x00400002, SCPLL_CTL_ADDR);
+
+ /* set bypassnl, reset_n, full calibration */
+ writel(0x00600004, SCPLL_CTL_ADDR);
+
+ /* Ensure register write to initiate calibration has taken
+ effect before reading status flag */
+ dmb();
+
+ /* wait for cal_all_done */
+ while (readl(SCPLL_STATUS_ADDR) & 0x2)
+ ;
+
+ /* Start: Set of experimentally derived steps
+ * to work around a h/w bug. */
+
+ /* Put the pll in normal mode */
+ scpll_apps_enable(1);
+
+ /* SHOT switch to 384 MHz */
+ regval = readl(SCPLL_FSM_CTL_EXT_ADDR);
+ regval &= ~(0x3f << 3);
+ regval |= (L_VAL_384MHZ << 3);
+
+ regval &= ~0x7;
+ regval |= SHOT_SWITCH;
+ writel(regval, SCPLL_FSM_CTL_EXT_ADDR);
+
+ /* Trigger the freq switch by putting pll in normal mode. */
+ regval = readl(SCPLL_CTL_ADDR);
+ regval |= (0x7);
+ writel(regval, SCPLL_CTL_ADDR);
+
+ /* Wait for frequency switch to finish */
+ while (readl(SCPLL_STATUS_ADDR) & 0x1)
+ ;
+
+ /* Status bit seems to clear early, using
+ * 800 microseconds for the worst case. */
+ udelay(800);
+
+ /* HOP switch to 768 MHz. */
+ regval = readl(SCPLL_FSM_CTL_EXT_ADDR);
+ regval &= ~(0x3f << 3);
+ regval |= (L_VAL_768MHZ << 3);
+
+ regval &= ~0x7;
+ regval |= HOP_SWITCH;
+ writel(regval, SCPLL_FSM_CTL_EXT_ADDR);
+
+ /* Trigger the freq switch by putting pll in normal mode. */
+ regval = readl(SCPLL_CTL_ADDR);
+ regval |= (0x7);
+ writel(regval, SCPLL_CTL_ADDR);
+
+ /* Wait for frequency switch to finish */
+ while (readl(SCPLL_STATUS_ADDR) & 0x1)
+ ;
+
+ /* Status bit seems to clear early, using
+ * 100 microseconds for the worst case. */
+ udelay(100);
+
+ /* End: Work around for h/w bug */
+
+ /* Power down scpll */
+ scpll_apps_enable(0);
+}
+
+static void config_pll(struct clkctl_acpu_speed *s)
+{
+ uint32_t regval;
+
+ if (s->pll == ACPU_PLL_3)
+ scpll_set_freq(s->sc_l_value, HOP_SWITCH);
+ /* Configure the PLL divider mux if we plan to use it. */
+ else if (s->sc_core_src_sel_mask == 0) {
+ /* get the current clock source selection */
+ regval = readl(SPSS_CLK_SEL_ADDR) & 0x1;
+
+ /* configure the other clock source, then switch to it,
+ * using the glitch free mux */
+ switch (regval) {
+ case 0x0:
+ regval = readl(SPSS_CLK_CNTL_ADDR);
+ regval &= ~(0x7 << 4 | 0xf);
+ regval |= (s->acpuclk_src_sel << 4);
+ regval |= (s->acpuclk_src_div << 0);
+ writel(regval, SPSS_CLK_CNTL_ADDR);
+
+ regval = readl(SPSS_CLK_SEL_ADDR);
+ regval |= 0x1;
+ writel(regval, SPSS_CLK_SEL_ADDR);
+ break;
+
+ case 0x1:
+ regval = readl(SPSS_CLK_CNTL_ADDR);
+ regval &= ~(0x7 << 12 | 0xf << 8);
+ regval |= (s->acpuclk_src_sel << 12);
+ regval |= (s->acpuclk_src_div << 8);
+ writel(regval, SPSS_CLK_CNTL_ADDR);
+
+ regval = readl(SPSS_CLK_SEL_ADDR);
+ regval &= ~0x1;
+ writel(regval, SPSS_CLK_SEL_ADDR);
+ break;
+ }
+ dmb();
+ }
+
+ regval = readl(SPSS_CLK_SEL_ADDR);
+ regval &= ~(0x3 << 1);
+ regval |= (s->sc_core_src_sel_mask << 1);
+ writel(regval, SPSS_CLK_SEL_ADDR);
+}
+
+static int acpuclk_set_vdd_level(int vdd)
+{
+ if (drv_state.acpu_set_vdd) {
+ pr_debug("Switching VDD to %d mV\n", vdd);
+ return drv_state.acpu_set_vdd(vdd);
+ } else {
+ /* Assume that the PMIC supports scaling the processor
+ * to its maximum frequency at its default voltage.
+ */
+ return 0;
+ }
+}
+
+int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason)
+{
+ struct clkctl_acpu_speed *tgt_s, *strt_s;
+ int res, rc = 0;
+ int freq_index = 0;
+
+ if (reason == SETRATE_CPUFREQ)
+ mutex_lock(&drv_state.lock);
+
+ strt_s = drv_state.current_speed;
+
+ if (rate == strt_s->acpuclk_khz)
+ goto out;
+
+ for (tgt_s = acpu_freq_tbl; tgt_s->acpuclk_khz != 0; tgt_s++) {
+ if (tgt_s->acpuclk_khz == rate)
+ break;
+ freq_index++;
+ }
+
+ if (tgt_s->acpuclk_khz == 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (reason == SETRATE_CPUFREQ) {
+#ifdef CONFIG_MSM_CPU_AVS
+ /* Notify avs before changing frequency */
+ rc = avs_adjust_freq(freq_index, 1);
+ if (rc) {
+ pr_err("Unable to increase ACPU vdd (%d)\n", rc);
+ goto out;
+ }
+#endif
+ /* Increase VDD if needed. */
+ if (tgt_s->vdd > strt_s->vdd) {
+ rc = acpuclk_set_vdd_level(tgt_s->vdd);
+ if (rc) {
+ pr_err("Unable to increase ACPU vdd (%d)\n",
+ rc);
+ goto out;
+ }
+ }
+ } else if (reason == SETRATE_PC
+ && rate != POWER_COLLAPSE_KHZ) {
+ /* Returning from PC. ACPU is running on AXI source.
+ * Step up to PLL0 before ramping up higher. */
+ config_pll(PLL0_S);
+ }
+
+ pr_debug("Switching from ACPU rate %u KHz -> %u KHz\n",
+ strt_s->acpuclk_khz, tgt_s->acpuclk_khz);
+
+ if (strt_s->pll != ACPU_PLL_3 && tgt_s->pll != ACPU_PLL_3) {
+ config_pll(tgt_s);
+ } else if (strt_s->pll != ACPU_PLL_3 && tgt_s->pll == ACPU_PLL_3) {
+ scpll_apps_enable(1);
+ config_pll(tgt_s);
+ } else if (strt_s->pll == ACPU_PLL_3 && tgt_s->pll != ACPU_PLL_3) {
+ config_pll(tgt_s);
+ scpll_apps_enable(0);
+ } else {
+ /* Temporarily switch to PLL0 while reconfiguring PLL3. */
+ config_pll(PLL0_S);
+ config_pll(tgt_s);
+ }
+
+ /* Update the driver state with the new clock freq */
+ drv_state.current_speed = tgt_s;
+
+ /* Re-adjust lpj for the new clock speed. */
+ loops_per_jiffy = tgt_s->lpj;
+
+ /* Nothing else to do for SWFI. */
+ if (reason == SETRATE_SWFI)
+ goto out;
+
+ if (strt_s->axiclk_khz != tgt_s->axiclk_khz) {
+ res = clk_set_rate(drv_state.ebi1_clk,
+ tgt_s->axiclk_khz * 1000);
+ if (res < 0)
+ pr_warning("Setting AXI min rate failed (%d)\n", res);
+ }
+
+ /* Nothing else to do for power collapse */
+ if (reason == SETRATE_PC)
+ goto out;
+
+#ifdef CONFIG_MSM_CPU_AVS
+ /* notify avs after changing frequency */
+ res = avs_adjust_freq(freq_index, 0);
+ if (res)
+ pr_warning("Unable to drop ACPU vdd (%d)\n", res);
+#endif
+
+ /* Drop VDD level if we can. */
+ if (tgt_s->vdd < strt_s->vdd) {
+ res = acpuclk_set_vdd_level(tgt_s->vdd);
+ if (res)
+ pr_warning("Unable to drop ACPU vdd (%d)\n", res);
+ }
+
+ pr_debug("ACPU speed change complete\n");
+out:
+ if (reason == SETRATE_CPUFREQ)
+ mutex_unlock(&drv_state.lock);
+ return rc;
+}
+
+static void __init acpuclk_init(void)
+{
+ struct clkctl_acpu_speed *speed;
+ uint32_t div, sel, regval;
+ int res;
+
+ /* Determine the source of the Scorpion clock. */
+ regval = readl(SPSS_CLK_SEL_ADDR);
+ switch ((regval & 0x6) >> 1) {
+ case 0: /* raw source clock */
+ case 3: /* low jitter PLL1 (768Mhz) */
+ if (regval & 0x1) {
+ sel = ((readl(SPSS_CLK_CNTL_ADDR) >> 4) & 0x7);
+ div = ((readl(SPSS_CLK_CNTL_ADDR) >> 0) & 0xf);
+ } else {
+ sel = ((readl(SPSS_CLK_CNTL_ADDR) >> 12) & 0x7);
+ div = ((readl(SPSS_CLK_CNTL_ADDR) >> 8) & 0xf);
+ }
+
+ /* Find the matching clock rate. */
+ for (speed = acpu_freq_tbl; speed->acpuclk_khz != 0; speed++) {
+ if (speed->acpuclk_src_sel == sel &&
+ speed->acpuclk_src_div == div)
+ break;
+ }
+ break;
+
+ case 1: /* unbuffered scorpion pll (384Mhz to 998.4Mhz) */
+ sel = ((readl(SCPLL_FSM_CTL_EXT_ADDR) >> 3) & 0x3f);
+
+ /* Find the matching clock rate. */
+ for (speed = acpu_freq_tbl; speed->acpuclk_khz != 0; speed++) {
+ if (speed->sc_l_value == sel &&
+ speed->sc_core_src_sel_mask == 1)
+ break;
+ }
+ break;
+
+ case 2: /* AXI bus clock (128Mhz) */
+ speed = AXI_S;
+ break;
+ default:
+ BUG();
+ }
+
+ /* Initialize scpll only if it wasn't already initialized by the boot
+ * loader. If the CPU is already running on scpll, then the scpll was
+ * initialized by the boot loader. */
+ if (speed->pll != ACPU_PLL_3)
+ scpll_init();
+
+ if (speed->acpuclk_khz == 0) {
+ pr_err("Error - ACPU clock reports invalid speed\n");
+ return;
+ }
+
+ drv_state.current_speed = speed;
+ res = clk_set_rate(drv_state.ebi1_clk, speed->axiclk_khz * 1000);
+ if (res < 0)
+ pr_warning("Setting AXI min rate failed (%d)\n", res);
+ res = clk_enable(drv_state.ebi1_clk);
+ if (res < 0)
+ pr_warning("Enabling AXI clock failed (%d)\n", res);
+
+ pr_info("ACPU running at %d KHz\n", speed->acpuclk_khz);
+}
+
+unsigned long acpuclk_get_rate(int cpu)
+{
+ return drv_state.current_speed->acpuclk_khz;
+}
+
+uint32_t acpuclk_get_switch_time(void)
+{
+ return drv_state.acpu_switch_time_us;
+}
+
+unsigned long acpuclk_power_collapse(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), POWER_COLLAPSE_KHZ, SETRATE_PC);
+ return ret;
+}
+
+unsigned long acpuclk_wait_for_irq(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), WAIT_FOR_IRQ_KHZ, SETRATE_SWFI);
+ return ret;
+}
+
+/* Spare register populated with efuse data on max ACPU freq. */
+#define CT_CSR_PHYS 0xA8700000
+#define TCSR_SPARE2_ADDR (ct_csr_base + 0x60)
+
+#define PLL0_M_VAL_ADDR (MSM_CLK_CTL_BASE + 0x308)
+
+static void __init acpu_freq_tbl_fixup(void)
+{
+ void __iomem *ct_csr_base;
+ uint32_t tcsr_spare2, pll0_m_val;
+ unsigned int max_acpu_khz;
+ unsigned int i;
+
+ ct_csr_base = ioremap(CT_CSR_PHYS, PAGE_SIZE);
+ BUG_ON(ct_csr_base == NULL);
+
+ tcsr_spare2 = readl(TCSR_SPARE2_ADDR);
+
+ /* Check if the register is supported and meaningful. */
+ if ((tcsr_spare2 & 0xF000) != 0xA000) {
+ pr_info("Efuse data on Max ACPU freq not present.\n");
+ goto skip_efuse_fixup;
+ }
+
+ switch (tcsr_spare2 & 0xF0) {
+ case 0x70:
+ acpu_freq_tbl = acpu_freq_tbl_768;
+ max_acpu_khz = 768000;
+ break;
+ case 0x30:
+ case 0x00:
+ max_acpu_khz = 998400;
+ break;
+ case 0x10:
+ max_acpu_khz = 1267200;
+ break;
+ default:
+ pr_warning("Invalid efuse data (%x) on Max ACPU freq!\n",
+ tcsr_spare2);
+ goto skip_efuse_fixup;
+ }
+
+ pr_info("Max ACPU freq from efuse data is %d KHz\n", max_acpu_khz);
+
+ for (i = 0; acpu_freq_tbl[i].acpuclk_khz != 0; i++) {
+ if (acpu_freq_tbl[i].acpuclk_khz > max_acpu_khz) {
+ acpu_freq_tbl[i].acpuclk_khz = 0;
+ break;
+ }
+ }
+
+skip_efuse_fixup:
+ iounmap(ct_csr_base);
+ BUG_ON(drv_state.max_vdd == 0);
+
+ /* pll0_m_val will be 36 when PLL0 is run at 235MHz
+ * instead of the usual 245MHz. */
+ pll0_m_val = readl(PLL0_M_VAL_ADDR) & 0x7FFFF;
+ if (pll0_m_val == 36)
+ PLL0_S->acpuclk_khz = 235930;
+
+ for (i = 0; acpu_freq_tbl[i].acpuclk_khz != 0; i++) {
+ if (acpu_freq_tbl[i].vdd > drv_state.max_vdd) {
+ acpu_freq_tbl[i].acpuclk_khz = 0;
+ break;
+ }
+ }
+}
+
+/* Initalize the lpj field in the acpu_freq_tbl. */
+static void __init lpj_init(void)
+{
+ int i;
+ const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
+ for (i = 0; acpu_freq_tbl[i].acpuclk_khz; i++) {
+ acpu_freq_tbl[i].lpj = cpufreq_scale(loops_per_jiffy,
+ base_clk->acpuclk_khz,
+ acpu_freq_tbl[i].acpuclk_khz);
+ }
+}
+
+#ifdef CONFIG_MSM_CPU_AVS
+static int __init acpu_avs_init(int (*set_vdd) (int), int khz)
+{
+ int i;
+ int freq_count = 0;
+ int freq_index = -1;
+
+ for (i = 0; acpu_freq_tbl[i].acpuclk_khz; i++) {
+ freq_count++;
+ if (acpu_freq_tbl[i].acpuclk_khz == khz)
+ freq_index = i;
+ }
+
+ return avs_init(set_vdd, freq_count, freq_index);
+}
+#endif
+
+void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
+{
+ mutex_init(&drv_state.lock);
+ drv_state.acpu_switch_time_us = clkdata->acpu_switch_time_us;
+ drv_state.max_speed_delta_khz = clkdata->max_speed_delta_khz;
+ drv_state.vdd_switch_time_us = clkdata->vdd_switch_time_us;
+ drv_state.max_vdd = clkdata->max_vdd;
+ drv_state.acpu_set_vdd = clkdata->acpu_set_vdd;
+
+ drv_state.ebi1_clk = clk_get(NULL, "ebi1_acpu_clk");
+ BUG_ON(IS_ERR(drv_state.ebi1_clk));
+
+ acpu_freq_tbl_fixup();
+ acpuclk_init();
+ lpj_init();
+ /* Set a lower bound for ACPU rate for boot. This limits the
+ * maximum frequency hop caused by the first CPUFREQ switch. */
+ if (drv_state.current_speed->acpuclk_khz < PLL0_S->acpuclk_khz)
+ acpuclk_set_rate(0, PLL0_S->acpuclk_khz, SETRATE_CPUFREQ);
+
+#ifdef CONFIG_CPU_FREQ_MSM
+ cpufreq_table_init();
+ cpufreq_frequency_table_get_attr(freq_table, smp_processor_id());
+#endif
+#ifdef CONFIG_MSM_CPU_AVS
+ if (!acpu_avs_init(drv_state.acpu_set_vdd,
+ drv_state.current_speed->acpuclk_khz)) {
+ /* avs init successful. avs will handle voltage changes */
+ drv_state.acpu_set_vdd = NULL;
+ }
+#endif
+}
diff --git a/arch/arm/mach-msm/acpuclock-8x60.c b/arch/arm/mach-msm/acpuclock-8x60.c
new file mode 100644
index 00000000000..d840865c70e
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8x60.c
@@ -0,0 +1,965 @@
+/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "acpuclock.h"
+#include "avs.h"
+
+/* Frequency switch modes. */
+#define SHOT_SWITCH 4
+#define HOP_SWITCH 5
+#define SIMPLE_SLEW 6
+#define COMPLEX_SLEW 7
+
+/* PLL calibration limits.
+ * The PLL hardware is capable of 384MHz to 1536MHz. The L_VALs
+ * used for calibration should respect these limits. */
+#define L_VAL_SCPLL_CAL_MIN 0x08 /* = 432 MHz with 27MHz source */
+#define L_VAL_SCPLL_CAL_MAX 0x1C /* = 1512 MHz with 27MHz source */
+
+#define MAX_VDD_SC 1250000 /* uV */
+#define MAX_VDD_MEM 1250000 /* uV */
+#define MAX_VDD_DIG 1200000 /* uV */
+#define MAX_AXI 310500 /* KHz */
+#define SCPLL_LOW_VDD_FMAX 594000 /* KHz */
+#define SCPLL_LOW_VDD 1000000 /* uV */
+#define SCPLL_NOMINAL_VDD 1100000 /* uV */
+
+/* SCPLL Modes. */
+#define SCPLL_POWER_DOWN 0
+#define SCPLL_BYPASS 1
+#define SCPLL_STANDBY 2
+#define SCPLL_FULL_CAL 4
+#define SCPLL_HALF_CAL 5
+#define SCPLL_STEP_CAL 6
+#define SCPLL_NORMAL 7
+
+#define SCPLL_DEBUG_NONE 0
+#define SCPLL_DEBUG_FULL 3
+
+/* SCPLL registers offsets. */
+#define SCPLL_DEBUG_OFFSET 0x0
+#define SCPLL_CTL_OFFSET 0x4
+#define SCPLL_CAL_OFFSET 0x8
+#define SCPLL_STATUS_OFFSET 0x10
+#define SCPLL_CFG_OFFSET 0x1C
+#define SCPLL_FSM_CTL_EXT_OFFSET 0x24
+#define SCPLL_LUT_A_HW_MAX (0x38 + ((L_VAL_SCPLL_CAL_MAX / 4) * 4))
+
+/* Clock registers. */
+#define SPSS0_CLK_CTL_ADDR (MSM_ACC0_BASE + 0x04)
+#define SPSS0_CLK_SEL_ADDR (MSM_ACC0_BASE + 0x08)
+#define SPSS1_CLK_CTL_ADDR (MSM_ACC1_BASE + 0x04)
+#define SPSS1_CLK_SEL_ADDR (MSM_ACC1_BASE + 0x08)
+#define SPSS_L2_CLK_SEL_ADDR (MSM_GCC_BASE + 0x38)
+
+/* PTE EFUSE register. */
+#define QFPROM_PTE_EFUSE_ADDR (MSM_QFPROM_BASE + 0x00C0)
+
+static const void * const clk_ctl_addr[] = {SPSS0_CLK_CTL_ADDR,
+ SPSS1_CLK_CTL_ADDR};
+static const void * const clk_sel_addr[] = {SPSS0_CLK_SEL_ADDR,
+ SPSS1_CLK_SEL_ADDR, SPSS_L2_CLK_SEL_ADDR};
+
+static const int rpm_vreg_voter[] = { RPM_VREG_VOTER1, RPM_VREG_VOTER2 };
+static struct regulator *regulator_sc[NR_CPUS];
+
+enum scplls {
+ CPU0 = 0,
+ CPU1,
+ L2,
+};
+
+static const void * const sc_pll_base[] = {
+ [CPU0] = MSM_SCPLL_BASE + 0x200,
+ [CPU1] = MSM_SCPLL_BASE + 0x300,
+ [L2] = MSM_SCPLL_BASE + 0x400,
+};
+
+enum sc_src {
+ ACPU_AFAB,
+ ACPU_PLL_8,
+ ACPU_SCPLL,
+};
+
+static struct clock_state {
+ struct clkctl_acpu_speed *current_speed[NR_CPUS];
+ struct clkctl_l2_speed *current_l2_speed;
+ spinlock_t l2_lock;
+ struct mutex lock;
+ uint32_t acpu_switch_time_us;
+ uint32_t vdd_switch_time_us;
+ uint32_t max_speed_delta_khz;
+} drv_state;
+
+struct clkctl_l2_speed {
+ unsigned int khz;
+ unsigned int src_sel;
+ unsigned int l_val;
+ unsigned int vdd_dig;
+ unsigned int vdd_mem;
+ unsigned int bw_level;
+};
+
+static struct clkctl_l2_speed *l2_vote[NR_CPUS];
+
+struct clkctl_acpu_speed {
+ unsigned int use_for_scaling[2]; /* One for each CPU. */
+ unsigned int acpuclk_khz;
+ int pll;
+ unsigned int acpuclk_src_sel;
+ unsigned int acpuclk_src_div;
+ unsigned int core_src_sel;
+ unsigned int l_val;
+ struct clkctl_l2_speed *l2_level;
+ unsigned int vdd_sc;
+ unsigned int avsdscr_setting;
+};
+
+/* Instantaneous bandwidth requests in MB/s. */
+#define BW_MBPS(_bw) \
+ { \
+ .vectors = &(struct msm_bus_vectors){ \
+ .src = MSM_BUS_MASTER_AMPSS_M0, \
+ .dst = MSM_BUS_SLAVE_EBI_CH0, \
+ .ib = (_bw) * 1000000UL, \
+ .ab = 0, \
+ }, \
+ .num_paths = 1, \
+ }
+static struct msm_bus_paths bw_level_tbl[] = {
+ [0] = BW_MBPS(824), /* At least 103 MHz on bus. */
+ [1] = BW_MBPS(1336), /* At least 167 MHz on bus. */
+ [2] = BW_MBPS(2008), /* At least 251 MHz on bus. */
+ [3] = BW_MBPS(2480), /* At least 310 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_client_pdata = {
+ .usecase = bw_level_tbl,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl),
+ .active_only = 1,
+ .name = "acpuclock",
+};
+
+static uint32_t bus_perf_client;
+
+/* L2 frequencies = 2 * 27 MHz * L_VAL */
+static struct clkctl_l2_speed l2_freq_tbl_v2[] = {
+ [0] = { MAX_AXI, 0, 0, 1000000, 1100000, 0},
+ [1] = { 432000, 1, 0x08, 1000000, 1100000, 0},
+ [2] = { 486000, 1, 0x09, 1000000, 1100000, 0},
+ [3] = { 540000, 1, 0x0A, 1000000, 1100000, 0},
+ [4] = { 594000, 1, 0x0B, 1000000, 1100000, 0},
+ [5] = { 648000, 1, 0x0C, 1000000, 1100000, 1},
+ [6] = { 702000, 1, 0x0D, 1100000, 1100000, 1},
+ [7] = { 756000, 1, 0x0E, 1100000, 1100000, 1},
+ [8] = { 810000, 1, 0x0F, 1100000, 1100000, 1},
+ [9] = { 864000, 1, 0x10, 1100000, 1100000, 1},
+ [10] = { 918000, 1, 0x11, 1100000, 1100000, 2},
+ [11] = { 972000, 1, 0x12, 1100000, 1100000, 2},
+ [12] = {1026000, 1, 0x13, 1100000, 1100000, 2},
+ [13] = {1080000, 1, 0x14, 1100000, 1200000, 2},
+ [14] = {1134000, 1, 0x15, 1100000, 1200000, 2},
+ [15] = {1188000, 1, 0x16, 1200000, 1200000, 3},
+ [16] = {1242000, 1, 0x17, 1200000, 1212500, 3},
+ [17] = {1296000, 1, 0x18, 1200000, 1225000, 3},
+ [18] = {1350000, 1, 0x19, 1200000, 1225000, 3},
+ [19] = {1404000, 1, 0x1A, 1200000, 1250000, 3},
+};
+
+#define L2(x) (&l2_freq_tbl_v2[(x)])
+/* SCPLL frequencies = 2 * 27 MHz * L_VAL */
+static struct clkctl_acpu_speed acpu_freq_tbl_1188mhz[] = {
+ { {1, 1}, 192000, ACPU_PLL_8, 3, 1, 0, 0, L2(1), 812500, 0x03006000},
+ /* MAX_AXI row is used to source CPU cores and L2 from the AFAB clock. */
+ { {0, 0}, MAX_AXI, ACPU_AFAB, 1, 0, 0, 0, L2(0), 875000, 0x03006000},
+ { {1, 1}, 384000, ACPU_PLL_8, 3, 0, 0, 0, L2(1), 875000, 0x03006000},
+ { {1, 1}, 432000, ACPU_SCPLL, 0, 0, 1, 0x08, L2(1), 887500, 0x03006000},
+ { {1, 1}, 486000, ACPU_SCPLL, 0, 0, 1, 0x09, L2(2), 912500, 0x03006000},
+ { {1, 1}, 540000, ACPU_SCPLL, 0, 0, 1, 0x0A, L2(3), 925000, 0x03006000},
+ { {1, 1}, 594000, ACPU_SCPLL, 0, 0, 1, 0x0B, L2(4), 937500, 0x03006000},
+ { {1, 1}, 648000, ACPU_SCPLL, 0, 0, 1, 0x0C, L2(5), 950000, 0x03006000},
+ { {1, 1}, 702000, ACPU_SCPLL, 0, 0, 1, 0x0D, L2(6), 975000, 0x03006000},
+ { {1, 1}, 756000, ACPU_SCPLL, 0, 0, 1, 0x0E, L2(7), 1000000, 0x03006000},
+ { {1, 1}, 810000, ACPU_SCPLL, 0, 0, 1, 0x0F, L2(8), 1012500, 0x03006000},
+ { {1, 1}, 864000, ACPU_SCPLL, 0, 0, 1, 0x10, L2(9), 1037500, 0x03006000},
+ { {1, 1}, 918000, ACPU_SCPLL, 0, 0, 1, 0x11, L2(10), 1062500, 0x03006000},
+ { {1, 1}, 972000, ACPU_SCPLL, 0, 0, 1, 0x12, L2(11), 1087500, 0x03006000},
+ { {1, 1}, 1026000, ACPU_SCPLL, 0, 0, 1, 0x13, L2(12), 1125000, 0x03006000},
+ { {1, 1}, 1080000, ACPU_SCPLL, 0, 0, 1, 0x14, L2(13), 1137500, 0x03006000},
+ { {1, 1}, 1134000, ACPU_SCPLL, 0, 0, 1, 0x15, L2(14), 1162500, 0x03006000},
+ { {1, 1}, 1188000, ACPU_SCPLL, 0, 0, 1, 0x16, L2(15), 1187500, 0x03006000},
+ { {0, 0}, 0 },
+};
+
+/* SCPLL frequencies = 2 * 27 MHz * L_VAL */
+static struct clkctl_acpu_speed acpu_freq_tbl_slow[] = {
+ { {1, 1}, 192000, ACPU_PLL_8, 3, 1, 0, 0, L2(1), 812500, 0x03006000},
+ /* MAX_AXI row is used to source CPU cores and L2 from the AFAB clock. */
+ { {0, 0}, MAX_AXI, ACPU_AFAB, 1, 0, 0, 0, L2(0), 875000, 0x03006000},
+ { {1, 1}, 384000, ACPU_PLL_8, 3, 0, 0, 0, L2(1), 875000, 0x03006000},
+ { {1, 1}, 432000, ACPU_SCPLL, 0, 0, 1, 0x08, L2(1), 887500, 0x03006000},
+ { {1, 1}, 486000, ACPU_SCPLL, 0, 0, 1, 0x09, L2(2), 912500, 0x03006000},
+ { {1, 1}, 540000, ACPU_SCPLL, 0, 0, 1, 0x0A, L2(3), 925000, 0x03006000},
+ { {1, 1}, 594000, ACPU_SCPLL, 0, 0, 1, 0x0B, L2(4), 937500, 0x03006000},
+ { {1, 1}, 648000, ACPU_SCPLL, 0, 0, 1, 0x0C, L2(5), 950000, 0x03006000},
+ { {1, 1}, 702000, ACPU_SCPLL, 0, 0, 1, 0x0D, L2(6), 975000, 0x03006000},
+ { {1, 1}, 756000, ACPU_SCPLL, 0, 0, 1, 0x0E, L2(7), 1000000, 0x03006000},
+ { {1, 1}, 810000, ACPU_SCPLL, 0, 0, 1, 0x0F, L2(8), 1012500, 0x03006000},
+ { {1, 1}, 864000, ACPU_SCPLL, 0, 0, 1, 0x10, L2(9), 1037500, 0x03006000},
+ { {1, 1}, 918000, ACPU_SCPLL, 0, 0, 1, 0x11, L2(10), 1062500, 0x03006000},
+ { {1, 1}, 972000, ACPU_SCPLL, 0, 0, 1, 0x12, L2(11), 1087500, 0x03006000},
+ { {1, 1}, 1026000, ACPU_SCPLL, 0, 0, 1, 0x13, L2(12), 1100000, 0x03006000},
+ { {1, 1}, 1080000, ACPU_SCPLL, 0, 0, 1, 0x14, L2(13), 1112500, 0x03006000},
+ { {1, 1}, 1134000, ACPU_SCPLL, 0, 0, 1, 0x15, L2(14), 1125000, 0x03006000},
+ { {1, 1}, 1188000, ACPU_SCPLL, 0, 0, 1, 0x16, L2(15), 1137500, 0x03006000},
+ { {1, 1}, 1242000, ACPU_SCPLL, 0, 0, 1, 0x17, L2(16), 1150000, 0x03006000},
+ { {1, 1}, 1296000, ACPU_SCPLL, 0, 0, 1, 0x18, L2(17), 1175000, 0x03006000},
+ { {1, 1}, 1350000, ACPU_SCPLL, 0, 0, 1, 0x19, L2(18), 1200000, 0x03006000},
+ { {1, 1}, 1404000, ACPU_SCPLL, 0, 0, 1, 0x1A, L2(19), 1225000, 0x03006000},
+ { {1, 1}, 1458000, ACPU_SCPLL, 0, 0, 1, 0x1B, L2(19), 1237500, 0x03006000},
+ { {1, 1}, 1512000, ACPU_SCPLL, 0, 0, 1, 0x1C, L2(19), 1250000, 0x03006000},
+ { {0, 0}, 0 },
+};
+
+/* SCPLL frequencies = 2 * 27 MHz * L_VAL */
+static struct clkctl_acpu_speed acpu_freq_tbl_nom[] = {
+ { {1, 1}, 192000, ACPU_PLL_8, 3, 1, 0, 0, L2(1), 812500, 0x03006000},
+ /* MAX_AXI row is used to source CPU cores and L2 from the AFAB clock. */
+ { {0, 0}, MAX_AXI, ACPU_AFAB, 1, 0, 0, 0, L2(0), 875000, 0x03006000},
+ { {1, 1}, 384000, ACPU_PLL_8, 3, 0, 0, 0, L2(1), 875000, 0x03006000},
+ { {1, 1}, 432000, ACPU_SCPLL, 0, 0, 1, 0x08, L2(1), 887500, 0x03006000},
+ { {1, 1}, 486000, ACPU_SCPLL, 0, 0, 1, 0x09, L2(2), 912500, 0x03006000},
+ { {1, 1}, 540000, ACPU_SCPLL, 0, 0, 1, 0x0A, L2(3), 925000, 0x03006000},
+ { {1, 1}, 594000, ACPU_SCPLL, 0, 0, 1, 0x0B, L2(4), 937500, 0x03006000},
+ { {1, 1}, 648000, ACPU_SCPLL, 0, 0, 1, 0x0C, L2(5), 950000, 0x03006000},
+ { {1, 1}, 702000, ACPU_SCPLL, 0, 0, 1, 0x0D, L2(6), 975000, 0x03006000},
+ { {1, 1}, 756000, ACPU_SCPLL, 0, 0, 1, 0x0E, L2(7), 1000000, 0x03006000},
+ { {1, 1}, 810000, ACPU_SCPLL, 0, 0, 1, 0x0F, L2(8), 1012500, 0x03006000},
+ { {1, 1}, 864000, ACPU_SCPLL, 0, 0, 1, 0x10, L2(9), 1037500, 0x03006000},
+ { {1, 1}, 918000, ACPU_SCPLL, 0, 0, 1, 0x11, L2(10), 1062500, 0x03006000},
+ { {1, 1}, 972000, ACPU_SCPLL, 0, 0, 1, 0x12, L2(11), 1062500, 0x03006000},
+ { {1, 1}, 1026000, ACPU_SCPLL, 0, 0, 1, 0x13, L2(12), 1075000, 0x03006000},
+ { {1, 1}, 1080000, ACPU_SCPLL, 0, 0, 1, 0x14, L2(13), 1087500, 0x03006000},
+ { {1, 1}, 1134000, ACPU_SCPLL, 0, 0, 1, 0x15, L2(14), 1100000, 0x03006000},
+ { {1, 1}, 1188000, ACPU_SCPLL, 0, 0, 1, 0x16, L2(15), 1112500, 0x03006000},
+ { {1, 1}, 1242000, ACPU_SCPLL, 0, 0, 1, 0x17, L2(16), 1125000, 0x03006000},
+ { {1, 1}, 1296000, ACPU_SCPLL, 0, 0, 1, 0x18, L2(17), 1150000, 0x03006000},
+ { {1, 1}, 1350000, ACPU_SCPLL, 0, 0, 1, 0x19, L2(18), 1175000, 0x03006000},
+ { {1, 1}, 1404000, ACPU_SCPLL, 0, 0, 1, 0x1A, L2(19), 1200000, 0x03006000},
+ { {1, 1}, 1458000, ACPU_SCPLL, 0, 0, 1, 0x1B, L2(19), 1212500, 0x03006000},
+ { {1, 1}, 1512000, ACPU_SCPLL, 0, 0, 1, 0x1C, L2(19), 1225000, 0x03006000},
+ { {0, 0}, 0 },
+};
+
+/* SCPLL frequencies = 2 * 27 MHz * L_VAL */
+static struct clkctl_acpu_speed acpu_freq_tbl_fast[] = {
+ { {1, 1}, 192000, ACPU_PLL_8, 3, 1, 0, 0, L2(1), 812500, 0x03006000},
+ /* MAX_AXI row is used to source CPU cores and L2 from the AFAB clock. */
+ { {0, 0}, MAX_AXI, ACPU_AFAB, 1, 0, 0, 0, L2(0), 875000, 0x03006000},
+ { {1, 1}, 384000, ACPU_PLL_8, 3, 0, 0, 0, L2(1), 875000, 0x03006000},
+ { {1, 1}, 432000, ACPU_SCPLL, 0, 0, 1, 0x08, L2(1), 887500, 0x03006000},
+ { {1, 1}, 486000, ACPU_SCPLL, 0, 0, 1, 0x09, L2(2), 912500, 0x03006000},
+ { {1, 1}, 540000, ACPU_SCPLL, 0, 0, 1, 0x0A, L2(3), 925000, 0x03006000},
+ { {1, 1}, 594000, ACPU_SCPLL, 0, 0, 1, 0x0B, L2(4), 937500, 0x03006000},
+ { {1, 1}, 648000, ACPU_SCPLL, 0, 0, 1, 0x0C, L2(5), 950000, 0x03006000},
+ { {1, 1}, 702000, ACPU_SCPLL, 0, 0, 1, 0x0D, L2(6), 975000, 0x03006000},
+ { {1, 1}, 756000, ACPU_SCPLL, 0, 0, 1, 0x0E, L2(7), 1000000, 0x03006000},
+ { {1, 1}, 810000, ACPU_SCPLL, 0, 0, 1, 0x0F, L2(8), 1012500, 0x03006000},
+ { {1, 1}, 864000, ACPU_SCPLL, 0, 0, 1, 0x10, L2(9), 1037500, 0x03006000},
+ { {1, 1}, 918000, ACPU_SCPLL, 0, 0, 1, 0x11, L2(10), 1037500, 0x03006000},
+ { {1, 1}, 972000, ACPU_SCPLL, 0, 0, 1, 0x12, L2(11), 1037500, 0x03006000},
+ { {1, 1}, 1026000, ACPU_SCPLL, 0, 0, 1, 0x13, L2(12), 1050000, 0x03006000},
+ { {1, 1}, 1080000, ACPU_SCPLL, 0, 0, 1, 0x14, L2(13), 1062500, 0x03006000},
+ { {1, 1}, 1134000, ACPU_SCPLL, 0, 0, 1, 0x15, L2(14), 1075000, 0x03006000},
+ { {1, 1}, 1188000, ACPU_SCPLL, 0, 0, 1, 0x16, L2(15), 1087500, 0x03006000},
+ { {1, 1}, 1242000, ACPU_SCPLL, 0, 0, 1, 0x17, L2(16), 1100000, 0x03006000},
+ { {1, 1}, 1296000, ACPU_SCPLL, 0, 0, 1, 0x18, L2(17), 1125000, 0x03006000},
+ { {1, 1}, 1350000, ACPU_SCPLL, 0, 0, 1, 0x19, L2(18), 1150000, 0x03006000},
+ { {1, 1}, 1404000, ACPU_SCPLL, 0, 0, 1, 0x1A, L2(19), 1175000, 0x03006000},
+ { {1, 1}, 1458000, ACPU_SCPLL, 0, 0, 1, 0x1B, L2(19), 1187500, 0x03006000},
+ { {1, 1}, 1512000, ACPU_SCPLL, 0, 0, 1, 0x1C, L2(19), 1200000, 0x03006000},
+ { {0, 0}, 0 },
+};
+
+
+/* acpu_freq_tbl row to use when reconfiguring SC/L2 PLLs. */
+#define CAL_IDX 1
+
+static struct clkctl_acpu_speed *acpu_freq_tbl;
+static struct clkctl_l2_speed *l2_freq_tbl = l2_freq_tbl_v2;
+static unsigned int l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_v2);
+
+unsigned long acpuclk_get_rate(int cpu)
+{
+ return drv_state.current_speed[cpu]->acpuclk_khz;
+}
+
+uint32_t acpuclk_get_switch_time(void)
+{
+ return drv_state.acpu_switch_time_us;
+}
+
+#define POWER_COLLAPSE_KHZ MAX_AXI
+unsigned long acpuclk_power_collapse(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), POWER_COLLAPSE_KHZ, SETRATE_PC);
+ return ret;
+}
+
+#define WAIT_FOR_IRQ_KHZ MAX_AXI
+unsigned long acpuclk_wait_for_irq(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), WAIT_FOR_IRQ_KHZ, SETRATE_SWFI);
+ return ret;
+}
+
+static void select_core_source(unsigned int id, unsigned int src)
+{
+ uint32_t regval;
+ int shift;
+
+ shift = (id == L2) ? 0 : 1;
+ regval = readl_relaxed(clk_sel_addr[id]);
+ regval &= ~(0x3 << shift);
+ regval |= (src << shift);
+ writel_relaxed(regval, clk_sel_addr[id]);
+}
+
+static void select_clk_source_div(unsigned int id, struct clkctl_acpu_speed *s)
+{
+ uint32_t reg_clksel, reg_clkctl, src_sel;
+
+ /* Configure the PLL divider mux if we plan to use it. */
+ if (s->core_src_sel == 0) {
+
+ reg_clksel = readl_relaxed(clk_sel_addr[id]);
+
+ /* CLK_SEL_SRC1N0 (bank) bit. */
+ src_sel = reg_clksel & 1;
+
+ /* Program clock source and divider. */
+ reg_clkctl = readl_relaxed(clk_ctl_addr[id]);
+ reg_clkctl &= ~(0xFF << (8 * src_sel));
+ reg_clkctl |= s->acpuclk_src_sel << (4 + 8 * src_sel);
+ reg_clkctl |= s->acpuclk_src_div << (0 + 8 * src_sel);
+ writel_relaxed(reg_clkctl, clk_ctl_addr[id]);
+
+ /* Toggle clock source. */
+ reg_clksel ^= 1;
+
+ /* Program clock source selection. */
+ writel_relaxed(reg_clksel, clk_sel_addr[id]);
+ }
+}
+
+static void scpll_enable(int sc_pll, uint32_t l_val)
+{
+ uint32_t regval;
+
+ /* Power-up SCPLL into standby mode. */
+ writel_relaxed(SCPLL_STANDBY, sc_pll_base[sc_pll] + SCPLL_CTL_OFFSET);
+ mb();
+ udelay(10);
+
+ /* Shot-switch to target frequency. */
+ regval = (l_val << 3) | SHOT_SWITCH;
+ writel_relaxed(regval, sc_pll_base[sc_pll] + SCPLL_FSM_CTL_EXT_OFFSET);
+ writel_relaxed(SCPLL_NORMAL, sc_pll_base[sc_pll] + SCPLL_CTL_OFFSET);
+ mb();
+ udelay(20);
+}
+
+static void scpll_disable(int sc_pll)
+{
+ /* Power down SCPLL. */
+ writel_relaxed(SCPLL_POWER_DOWN,
+ sc_pll_base[sc_pll] + SCPLL_CTL_OFFSET);
+}
+
+static void scpll_change_freq(int sc_pll, uint32_t l_val)
+{
+ uint32_t regval;
+ const void *base_addr = sc_pll_base[sc_pll];
+
+ /* Complex-slew switch to target frequency. */
+ regval = (l_val << 3) | COMPLEX_SLEW;
+ writel_relaxed(regval, base_addr + SCPLL_FSM_CTL_EXT_OFFSET);
+ writel_relaxed(SCPLL_NORMAL, base_addr + SCPLL_CTL_OFFSET);
+
+ /* Wait for frequency switch to start. */
+ while (((readl_relaxed(base_addr + SCPLL_CTL_OFFSET) >> 3) & 0x3F)
+ != l_val)
+ cpu_relax();
+ /* Wait for frequency switch to finish. */
+ while (readl_relaxed(base_addr + SCPLL_STATUS_OFFSET) & 0x1)
+ cpu_relax();
+}
+
+/* Vote for the L2 speed and return the speed that should be applied. */
+static struct clkctl_l2_speed *compute_l2_speed(unsigned int voting_cpu,
+ struct clkctl_l2_speed *tgt_s)
+{
+ struct clkctl_l2_speed *new_s;
+ int cpu;
+
+ /* Bounds check. */
+ BUG_ON(tgt_s >= (l2_freq_tbl + l2_freq_tbl_size));
+
+ /* Find max L2 speed vote. */
+ l2_vote[voting_cpu] = tgt_s;
+ new_s = l2_freq_tbl;
+ for_each_present_cpu(cpu)
+ new_s = max(new_s, l2_vote[cpu]);
+
+ return new_s;
+}
+
+/* Set the L2's clock speed. */
+static void set_l2_speed(struct clkctl_l2_speed *tgt_s)
+{
+ if (tgt_s == drv_state.current_l2_speed)
+ return;
+
+ if (drv_state.current_l2_speed->src_sel == 1
+ && tgt_s->src_sel == 1)
+ scpll_change_freq(L2, tgt_s->l_val);
+ else {
+ if (tgt_s->src_sel == 1) {
+ scpll_enable(L2, tgt_s->l_val);
+ mb();
+ select_core_source(L2, tgt_s->src_sel);
+ } else {
+ select_core_source(L2, tgt_s->src_sel);
+ mb();
+ scpll_disable(L2);
+ }
+ }
+ drv_state.current_l2_speed = tgt_s;
+}
+
+/* Update the bus bandwidth request. */
+static void set_bus_bw(unsigned int bw)
+{
+ int ret;
+
+ /* Bounds check. */
+ if (bw >= ARRAY_SIZE(bw_level_tbl)) {
+ pr_err("%s: invalid bandwidth request (%d)\n", __func__, bw);
+ return;
+ }
+
+ /* Update bandwidth if requst has changed. This may sleep. */
+ ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
+ if (ret)
+ pr_err("%s: bandwidth request failed (%d)\n", __func__, ret);
+
+ return;
+}
+
+/* Apply any per-cpu voltage increases. */
+static int increase_vdd(int cpu, unsigned int vdd_sc, unsigned int vdd_mem,
+ unsigned int vdd_dig, enum setrate_reason reason)
+{
+ int rc = 0;
+
+ /* Increase vdd_mem active-set before vdd_dig and vdd_sc.
+ * vdd_mem should be >= both vdd_sc and vdd_dig. */
+ rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8058_S0, rpm_vreg_voter[cpu],
+ vdd_mem, MAX_VDD_MEM, 0);
+ if (rc) {
+ pr_err("%s: vdd_mem (cpu%d) increase failed (%d)\n",
+ __func__, cpu, rc);
+ return rc;
+ }
+
+ /* Increase vdd_dig active-set vote. */
+ rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8058_S1, rpm_vreg_voter[cpu],
+ vdd_dig, MAX_VDD_DIG, 0);
+ if (rc) {
+ pr_err("%s: vdd_dig (cpu%d) increase failed (%d)\n",
+ __func__, cpu, rc);
+ return rc;
+ }
+
+ /* Don't update the Scorpion voltage in the hotplug path. It should
+ * already be correct. Attempting to set it is bad because we don't
+ * know what CPU we are running on at this point, but the Scorpion
+ * regulator API requires we call it from the affected CPU. */
+ if (reason == SETRATE_HOTPLUG)
+ return rc;
+
+ /* Update per-core Scorpion voltage. */
+ rc = regulator_set_voltage(regulator_sc[cpu], vdd_sc, MAX_VDD_SC);
+ if (rc) {
+ pr_err("%s: vdd_sc (cpu%d) increase failed (%d)\n",
+ __func__, cpu, rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+/* Apply any per-cpu voltage decreases. */
+static void decrease_vdd(int cpu, unsigned int vdd_sc, unsigned int vdd_mem,
+ unsigned int vdd_dig, enum setrate_reason reason)
+{
+ int ret;
+
+ /* Update per-core Scorpion voltage. This must be called on the CPU
+ * that's being affected. Don't do this in the hotplug remove path,
+ * where the rail is off and we're executing on the other CPU. */
+ if (reason != SETRATE_HOTPLUG) {
+ ret = regulator_set_voltage(regulator_sc[cpu], vdd_sc,
+ MAX_VDD_SC);
+ if (ret) {
+ pr_err("%s: vdd_sc (cpu%d) decrease failed (%d)\n",
+ __func__, cpu, ret);
+ return;
+ }
+ }
+
+ /* Decrease vdd_dig active-set vote. */
+ ret = rpm_vreg_set_voltage(RPM_VREG_ID_PM8058_S1, rpm_vreg_voter[cpu],
+ vdd_dig, MAX_VDD_DIG, 0);
+ if (ret) {
+ pr_err("%s: vdd_dig (cpu%d) decrease failed (%d)\n",
+ __func__, cpu, ret);
+ return;
+ }
+
+ /* Decrease vdd_mem active-set after vdd_dig and vdd_sc.
+ * vdd_mem should be >= both vdd_sc and vdd_dig. */
+ ret = rpm_vreg_set_voltage(RPM_VREG_ID_PM8058_S0, rpm_vreg_voter[cpu],
+ vdd_mem, MAX_VDD_MEM, 0);
+ if (ret) {
+ pr_err("%s: vdd_mem (cpu%d) decrease failed (%d)\n",
+ __func__, cpu, ret);
+ return;
+ }
+}
+
+static void switch_sc_speed(int cpu, struct clkctl_acpu_speed *tgt_s)
+{
+ struct clkctl_acpu_speed *strt_s = drv_state.current_speed[cpu];
+
+ if (strt_s->pll != ACPU_SCPLL && tgt_s->pll != ACPU_SCPLL) {
+ select_clk_source_div(cpu, tgt_s);
+ /* Select core source because target may be AFAB. */
+ select_core_source(cpu, tgt_s->core_src_sel);
+ } else if (strt_s->pll != ACPU_SCPLL && tgt_s->pll == ACPU_SCPLL) {
+ scpll_enable(cpu, tgt_s->l_val);
+ mb();
+ select_core_source(cpu, tgt_s->core_src_sel);
+ } else if (strt_s->pll == ACPU_SCPLL && tgt_s->pll != ACPU_SCPLL) {
+ select_clk_source_div(cpu, tgt_s);
+ select_core_source(cpu, tgt_s->core_src_sel);
+ /* Core source switch must complete before disabling SCPLL. */
+ mb();
+ udelay(1);
+ scpll_disable(cpu);
+ } else
+ scpll_change_freq(cpu, tgt_s->l_val);
+
+ /* Update the driver state with the new clock freq */
+ drv_state.current_speed[cpu] = tgt_s;
+}
+
+int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason)
+{
+ struct clkctl_acpu_speed *tgt_s, *strt_s;
+ struct clkctl_l2_speed *tgt_l2;
+ unsigned int vdd_mem, vdd_dig, pll_vdd_dig;
+ unsigned long flags;
+ int rc = 0;
+
+ if (cpu > num_possible_cpus()) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
+ mutex_lock(&drv_state.lock);
+
+ strt_s = drv_state.current_speed[cpu];
+
+ /* Return early if rate didn't change. */
+ if (rate == strt_s->acpuclk_khz)
+ goto out;
+
+ /* Find target frequency. */
+ for (tgt_s = acpu_freq_tbl; tgt_s->acpuclk_khz != 0; tgt_s++)
+ if (tgt_s->acpuclk_khz == rate)
+ break;
+ if (tgt_s->acpuclk_khz == 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* AVS needs SAW_VCTL to be intitialized correctly, before enable,
+ * and is not initialized at acpuclk_init().
+ */
+ if (reason == SETRATE_CPUFREQ)
+ AVS_DISABLE(cpu);
+
+ /* Calculate vdd_mem and vdd_dig requirements.
+ * vdd_mem must be >= vdd_sc */
+ vdd_mem = max(tgt_s->vdd_sc, tgt_s->l2_level->vdd_mem);
+ /* Factor-in PLL vdd_dig requirements. */
+ if ((tgt_s->l2_level->khz > SCPLL_LOW_VDD_FMAX) ||
+ (tgt_s->pll == ACPU_SCPLL
+ && tgt_s->acpuclk_khz > SCPLL_LOW_VDD_FMAX))
+ pll_vdd_dig = SCPLL_NOMINAL_VDD;
+ else
+ pll_vdd_dig = SCPLL_LOW_VDD;
+ vdd_dig = max(tgt_s->l2_level->vdd_dig, pll_vdd_dig);
+
+ /* Increase VDD levels if needed. */
+ if ((reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG
+ || reason == SETRATE_INIT)
+ && (tgt_s->acpuclk_khz > strt_s->acpuclk_khz)) {
+ rc = increase_vdd(cpu, tgt_s->vdd_sc, vdd_mem, vdd_dig, reason);
+ if (rc)
+ goto out;
+ }
+
+ pr_debug("Switching from ACPU%d rate %u KHz -> %u KHz\n",
+ cpu, strt_s->acpuclk_khz, tgt_s->acpuclk_khz);
+
+ /* Switch CPU speed. */
+ switch_sc_speed(cpu, tgt_s);
+
+ /* Update the L2 vote and apply the rate change. */
+ spin_lock_irqsave(&drv_state.l2_lock, flags);
+ tgt_l2 = compute_l2_speed(cpu, tgt_s->l2_level);
+ set_l2_speed(tgt_l2);
+ spin_unlock_irqrestore(&drv_state.l2_lock, flags);
+
+ /* Nothing else to do for SWFI. */
+ if (reason == SETRATE_SWFI)
+ goto out;
+
+ /* Nothing else to do for power collapse. */
+ if (reason == SETRATE_PC)
+ goto out;
+
+ /* Update bus bandwith request. */
+ set_bus_bw(tgt_l2->bw_level);
+
+ /* Drop VDD levels if we can. */
+ if (tgt_s->acpuclk_khz < strt_s->acpuclk_khz)
+ decrease_vdd(cpu, tgt_s->vdd_sc, vdd_mem, vdd_dig, reason);
+
+ pr_debug("ACPU%d speed change complete\n", cpu);
+
+ /* Re-enable AVS */
+ if (reason == SETRATE_CPUFREQ)
+ AVS_ENABLE(cpu, tgt_s->avsdscr_setting);
+
+out:
+ if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
+ mutex_unlock(&drv_state.lock);
+ return rc;
+}
+
+static void __init scpll_init(int sc_pll)
+{
+ uint32_t regval;
+
+ pr_debug("Initializing SCPLL%d\n", sc_pll);
+
+ /* Clear calibration LUT registers containing max frequency entry.
+ * LUT registers are only writeable in debug mode. */
+ writel_relaxed(SCPLL_DEBUG_FULL,
+ sc_pll_base[sc_pll] + SCPLL_DEBUG_OFFSET);
+ writel_relaxed(0x0, sc_pll_base[sc_pll] + SCPLL_LUT_A_HW_MAX);
+ writel_relaxed(SCPLL_DEBUG_NONE,
+ sc_pll_base[sc_pll] + SCPLL_DEBUG_OFFSET);
+
+ /* Power-up SCPLL into standby mode. */
+ writel_relaxed(SCPLL_STANDBY, sc_pll_base[sc_pll] + SCPLL_CTL_OFFSET);
+ mb();
+ udelay(10);
+
+ /* Calibrate the SCPLL to the maximum range supported by the h/w. We
+ * might not use the full range of calibrated frequencies, but this
+ * simplifies changes required for future increases in max CPU freq.
+ */
+ regval = (L_VAL_SCPLL_CAL_MAX << 24) | (L_VAL_SCPLL_CAL_MIN << 16);
+ writel_relaxed(regval, sc_pll_base[sc_pll] + SCPLL_CAL_OFFSET);
+
+ /* Start calibration */
+ writel_relaxed(SCPLL_FULL_CAL, sc_pll_base[sc_pll] + SCPLL_CTL_OFFSET);
+
+ /* Wait for proof that calibration has started before checking the
+ * 'calibration done' bit in the status register. Waiting for the
+ * LUT register we cleared to contain data accomplishes this.
+ * This is required since the 'calibration done' bit takes time to
+ * transition from 'done' to 'not done' when starting a calibration.
+ */
+ while (readl_relaxed(sc_pll_base[sc_pll] + SCPLL_LUT_A_HW_MAX) == 0)
+ cpu_relax();
+
+ /* Wait for calibration to complete. */
+ while (readl_relaxed(sc_pll_base[sc_pll] + SCPLL_STATUS_OFFSET) & 0x2)
+ cpu_relax();
+
+ /* Power-down SCPLL. */
+ scpll_disable(sc_pll);
+}
+
+/* Force ACPU core and L2 cache clocks to rates that don't require SCPLLs. */
+static void __init unselect_scplls(void)
+{
+ int cpu;
+
+ /* Ensure CAL_IDX frequency uses AFAB sources for CPU cores and L2. */
+ BUG_ON(acpu_freq_tbl[CAL_IDX].core_src_sel != 0);
+ BUG_ON(acpu_freq_tbl[CAL_IDX].l2_level->src_sel != 0);
+
+ for_each_possible_cpu(cpu) {
+ select_clk_source_div(cpu, &acpu_freq_tbl[CAL_IDX]);
+ select_core_source(cpu, acpu_freq_tbl[CAL_IDX].core_src_sel);
+ drv_state.current_speed[cpu] = &acpu_freq_tbl[CAL_IDX];
+ l2_vote[cpu] = acpu_freq_tbl[CAL_IDX].l2_level;
+ }
+
+ select_core_source(L2, acpu_freq_tbl[CAL_IDX].l2_level->src_sel);
+ drv_state.current_l2_speed = acpu_freq_tbl[CAL_IDX].l2_level;
+}
+
+/* Ensure SCPLLs use the 27MHz PXO. */
+static void __init scpll_set_refs(void)
+{
+ int cpu;
+ uint32_t regval;
+
+ /* Bit 4 = 0:PXO, 1:MXO. */
+ for_each_possible_cpu(cpu) {
+ regval = readl_relaxed(sc_pll_base[cpu] + SCPLL_CFG_OFFSET);
+ regval &= ~BIT(4);
+ writel_relaxed(regval, sc_pll_base[cpu] + SCPLL_CFG_OFFSET);
+ }
+ regval = readl_relaxed(sc_pll_base[L2] + SCPLL_CFG_OFFSET);
+ regval &= ~BIT(4);
+ writel_relaxed(regval, sc_pll_base[L2] + SCPLL_CFG_OFFSET);
+}
+
+/* Voltage regulator initialization. */
+static void __init regulator_init(void)
+{
+ struct clkctl_acpu_speed **freq = drv_state.current_speed;
+ const char *regulator_sc_name[] = {"8901_s0", "8901_s1"};
+ int cpu, ret;
+
+ for_each_possible_cpu(cpu) {
+ /* VDD_SC0, VDD_SC1 */
+ regulator_sc[cpu] = regulator_get(NULL, regulator_sc_name[cpu]);
+ if (IS_ERR(regulator_sc[cpu]))
+ goto err;
+ ret = regulator_set_voltage(regulator_sc[cpu],
+ freq[cpu]->vdd_sc, MAX_VDD_SC);
+ if (ret)
+ goto err;
+ ret = regulator_enable(regulator_sc[cpu]);
+ if (ret)
+ goto err;
+ }
+
+ return;
+
+err:
+ pr_err("%s: Failed to initialize voltage regulators\n", __func__);
+ BUG();
+}
+
+/* Register with bus driver. */
+static void __init bus_init(void)
+{
+ bus_perf_client = msm_bus_scale_register_client(&bus_client_pdata);
+ if (!bus_perf_client) {
+ pr_err("%s: unable register bus client\n", __func__);
+ BUG();
+ }
+}
+
+#ifdef CONFIG_CPU_FREQ_MSM
+static struct cpufreq_frequency_table freq_table[NR_CPUS][30];
+
+static void __init cpufreq_table_init(void)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ int i, freq_cnt = 0;
+ /* Construct the freq_table tables from acpu_freq_tbl. */
+ for (i = 0; acpu_freq_tbl[i].acpuclk_khz != 0
+ && freq_cnt < ARRAY_SIZE(*freq_table); i++) {
+ if (acpu_freq_tbl[i].use_for_scaling[cpu]) {
+ freq_table[cpu][freq_cnt].index = freq_cnt;
+ freq_table[cpu][freq_cnt].frequency
+ = acpu_freq_tbl[i].acpuclk_khz;
+ freq_cnt++;
+ }
+ }
+ /* freq_table not big enough to store all usable freqs. */
+ BUG_ON(acpu_freq_tbl[i].acpuclk_khz != 0);
+
+ freq_table[cpu][freq_cnt].index = freq_cnt;
+ freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
+
+ pr_info("CPU%d: %d scaling frequencies supported.\n",
+ cpu, freq_cnt);
+
+ /* Register table with CPUFreq. */
+ cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
+ }
+}
+#else
+static void __init cpufreq_table_init(void) {}
+#endif
+
+#define HOT_UNPLUG_KHZ MAX_AXI
+static int __cpuinit acpuclock_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ static int prev_khz[NR_CPUS];
+ int cpu = (int)hcpu;
+
+ switch (action) {
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ prev_khz[cpu] = acpuclk_get_rate(cpu);
+ /* Fall through. */
+ case CPU_UP_CANCELED:
+ case CPU_UP_CANCELED_FROZEN:
+ acpuclk_set_rate(cpu, HOT_UNPLUG_KHZ, SETRATE_HOTPLUG);
+ break;
+ case CPU_UP_PREPARE:
+ case CPU_UP_PREPARE_FROZEN:
+ if (WARN_ON(!prev_khz[cpu]))
+ prev_khz[cpu] = acpu_freq_tbl->acpuclk_khz;
+ acpuclk_set_rate(cpu, prev_khz[cpu], SETRATE_HOTPLUG);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata acpuclock_cpu_notifier = {
+ .notifier_call = acpuclock_cpu_callback,
+};
+
+static unsigned int __init select_freq_plan(void)
+{
+ uint32_t pte_efuse, speed_bin, pvs, max_khz;
+ struct clkctl_acpu_speed *f;
+
+ pte_efuse = readl_relaxed(QFPROM_PTE_EFUSE_ADDR);
+
+ speed_bin = pte_efuse & 0xF;
+ if (speed_bin == 0xF)
+ speed_bin = (pte_efuse >> 4) & 0xF;
+
+ if (speed_bin == 0x1) {
+ max_khz = 1512000;
+ pvs = (pte_efuse >> 10) & 0x7;
+ if (pvs == 0x7)
+ pvs = (pte_efuse >> 13) & 0x7;
+
+ switch (pvs) {
+ case 0x0:
+ case 0x7:
+ acpu_freq_tbl = acpu_freq_tbl_slow;
+ pr_info("ACPU PVS: Slow\n");
+ break;
+ case 0x1:
+ acpu_freq_tbl = acpu_freq_tbl_nom;
+ pr_info("ACPU PVS: Nominal\n");
+ break;
+ case 0x3:
+ acpu_freq_tbl = acpu_freq_tbl_fast;
+ pr_info("ACPU PVS: Fast\n");
+ break;
+ default:
+ acpu_freq_tbl = acpu_freq_tbl_slow;
+ pr_warn("ACPU PVS: Unknown. Defaulting to slow.\n");
+ break;
+ }
+ } else {
+ max_khz = 1188000;
+ acpu_freq_tbl = acpu_freq_tbl_1188mhz;
+ }
+
+ /* Truncate the table based to max_khz. */
+ for (f = acpu_freq_tbl; f->acpuclk_khz != 0; f++) {
+ if (f->acpuclk_khz > max_khz) {
+ f->acpuclk_khz = 0;
+ break;
+ }
+ }
+ f--;
+ pr_info("Max ACPU freq: %u KHz\n", f->acpuclk_khz);
+
+ return f->acpuclk_khz;
+}
+
+void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
+{
+ unsigned int max_cpu_khz;
+ int cpu;
+
+ mutex_init(&drv_state.lock);
+ spin_lock_init(&drv_state.l2_lock);
+ drv_state.acpu_switch_time_us = clkdata->acpu_switch_time_us;
+ drv_state.vdd_switch_time_us = clkdata->vdd_switch_time_us;
+
+ /* Configure hardware. */
+ max_cpu_khz = select_freq_plan();
+ unselect_scplls();
+ scpll_set_refs();
+ for_each_possible_cpu(cpu)
+ scpll_init(cpu);
+ scpll_init(L2);
+ regulator_init();
+ bus_init();
+
+ /* Improve boot time by ramping up CPUs immediately. */
+ for_each_online_cpu(cpu)
+ acpuclk_set_rate(cpu, max_cpu_khz, SETRATE_INIT);
+
+ cpufreq_table_init();
+ register_hotcpu_notifier(&acpuclock_cpu_notifier);
+}
diff --git a/arch/arm/mach-msm/acpuclock-arm11.c b/arch/arm/mach-msm/acpuclock-arm11.c
index 805d4ee53f7..dd1e6e5b3c5 100644
--- a/arch/arm/mach-msm/acpuclock-arm11.c
+++ b/arch/arm/mach-msm/acpuclock-arm11.c
@@ -17,6 +17,7 @@
*
*/
+#include
#include
#include
#include
@@ -97,7 +98,7 @@ struct clkctl_acpu_speed {
/*
* ACPU speed table. Complete table is shown but certain speeds are commented
- * out to optimized speed switching. Initialize loops_per_jiffy to 0.
+ * out to optimized speed switching. Initalize loops_per_jiffy to 0.
*
* Table stepping up/down is optimized for 256mhz jumps while staying on the
* same PLL.
@@ -493,7 +494,7 @@ uint32_t acpuclk_get_switch_time(void)
* Clock driver initialization
*---------------------------------------------------------------------------*/
-/* Initialize the lpj field in the acpu_freq_tbl. */
+/* Initalize the lpj field in the acpu_freq_tbl. */
static void __init lpj_init(void)
{
int i;
diff --git a/arch/arm/mach-msm/acpuclock-fsm9xxx.c b/arch/arm/mach-msm/acpuclock-fsm9xxx.c
new file mode 100644
index 00000000000..b12eb9e2984
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-fsm9xxx.c
@@ -0,0 +1,42 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include
+#include
+#include
+#include
+
+#include "acpuclock.h"
+
+/* Registers */
+#define PLL1_CTL_ADDR (MSM_CLK_CTL_BASE + 0x604)
+
+unsigned long acpuclk_get_rate(int cpu)
+{
+ unsigned int pll1_ctl;
+ unsigned int pll1_l, pll1_div2;
+ unsigned int pll1_khz;
+
+ pll1_ctl = readl_relaxed(PLL1_CTL_ADDR);
+ pll1_l = ((pll1_ctl >> 3) & 0x3f) * 2;
+ pll1_div2 = pll1_ctl & 0x20000;
+ pll1_khz = 19200 * pll1_l;
+ if (pll1_div2)
+ pll1_khz >>= 1;
+
+ return pll1_khz;
+}
+
+void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
+{
+ pr_info("ACPU running at %lu KHz\n", acpuclk_get_rate(0));
+}
diff --git a/arch/arm/mach-msm/acpuclock.c b/arch/arm/mach-msm/acpuclock.c
new file mode 100644
index 00000000000..c6fba577b67
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock.c
@@ -0,0 +1,1046 @@
+/* arch/arm/mach-msm/acpuclock.c
+ *
+ * MSM architecture clock driver
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Author: San Mehat
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "proc_comm.h"
+#include "smd_private.h"
+#include "acpuclock.h"
+
+#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
+#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
+#define A11S_VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
+#define PLLn_MODE(n) (MSM_CLK_CTL_BASE + 0x300 + 28 * (n))
+#define PLLn_L_VAL(n) (MSM_CLK_CTL_BASE + 0x304 + 28 * (n))
+
+#define PLL4_MODE (MSM_CLK_CTL_BASE + 0x374)
+#define PLL4_L_VAL (MSM_CLK_CTL_BASE + 0x378)
+
+/* Max CPU frequency allowed by hardware while in standby waiting for an irq. */
+#define MAX_WAIT_FOR_IRQ_KHZ 128000
+
+enum {
+ ACPU_PLL_TCXO = -1,
+ ACPU_PLL_0 = 0,
+ ACPU_PLL_1,
+ ACPU_PLL_2,
+ ACPU_PLL_3,
+ ACPU_PLL_4,
+ ACPU_PLL_END,
+};
+
+static const struct pll {
+ void __iomem *mod_reg;
+ const uint32_t l_val_mask;
+} soc_pll[ACPU_PLL_END] = {
+ [ACPU_PLL_0] = {PLLn_MODE(ACPU_PLL_0), 0x3f},
+ [ACPU_PLL_1] = {PLLn_MODE(ACPU_PLL_1), 0x3f},
+ [ACPU_PLL_2] = {PLLn_MODE(ACPU_PLL_2), 0x3f},
+ [ACPU_PLL_3] = {PLLn_MODE(ACPU_PLL_3), 0x3f},
+ [ACPU_PLL_4] = {PLL4_MODE, 0x3ff},
+};
+
+struct clock_state {
+ struct clkctl_acpu_speed *current_speed;
+ struct mutex lock;
+ uint32_t acpu_switch_time_us;
+ uint32_t max_speed_delta_khz;
+ uint32_t vdd_switch_time_us;
+ unsigned long max_axi_khz;
+ unsigned long wait_for_irq_khz;
+ struct clk *ebi1_clk;
+};
+
+#define PLL_BASE 7
+
+struct shared_pll_control {
+ uint32_t version;
+ struct {
+ /* Denotes if the PLL is ON. Technically, this can be read
+ * directly from the PLL registers, but this feild is here,
+ * so let's use it.
+ */
+ uint32_t on;
+ /* One bit for each processor core. The application processor
+ * is allocated bit position 1. All other bits should be
+ * considered as votes from other processors.
+ */
+ uint32_t votes;
+ } pll[PLL_BASE + ACPU_PLL_END];
+};
+
+struct clkctl_acpu_speed {
+ unsigned int use_for_scaling;
+ unsigned int a11clk_khz;
+ int pll;
+ unsigned int a11clk_src_sel;
+ unsigned int a11clk_src_div;
+ unsigned int ahbclk_khz;
+ unsigned int ahbclk_div;
+ int vdd;
+ unsigned int axiclk_khz;
+ unsigned long lpj; /* loops_per_jiffy */
+ /* Pointers in acpu_freq_tbl[] for max up/down steppings. */
+ struct clkctl_acpu_speed *down[ACPU_PLL_END];
+ struct clkctl_acpu_speed *up[ACPU_PLL_END];
+};
+
+static remote_spinlock_t pll_lock;
+static struct shared_pll_control *pll_control;
+static struct clock_state drv_state = { 0 };
+static struct clkctl_acpu_speed *acpu_freq_tbl;
+
+static void __init acpuclk_init(void);
+
+/*
+ * ACPU freq tables used for different PLLs frequency combinations. The
+ * correct table is selected during init.
+ *
+ * Table stepping up/down entries are calculated during boot to choose the
+ * largest frequency jump that's less than max_speed_delta_khz on each PLL.
+ */
+
+/* 7x01/7x25 normal with GSM capable modem */
+static struct clkctl_acpu_speed pll0_245_pll1_768_pll2_1056_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 30720 },
+ { 1, 122880, ACPU_PLL_0, 4, 1, 61440, 1, 3, 61440 },
+ { 0, 128000, ACPU_PLL_1, 1, 5, 64000, 1, 3, 61440 },
+ { 0, 176000, ACPU_PLL_2, 2, 5, 88000, 1, 3, 61440 },
+ { 1, 245760, ACPU_PLL_0, 4, 0, 81920, 2, 4, 61440 },
+ { 1, 256000, ACPU_PLL_1, 1, 2, 128000, 1, 5, 128000 },
+ { 0, 352000, ACPU_PLL_2, 2, 2, 88000, 3, 5, 128000 },
+ { 1, 384000, ACPU_PLL_1, 1, 1, 128000, 2, 6, 128000 },
+ { 1, 528000, ACPU_PLL_2, 2, 1, 132000, 3, 7, 128000 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x01/7x25 normal with CDMA-only modem */
+static struct clkctl_acpu_speed pll0_196_pll1_768_pll2_1056_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 24576 },
+ { 1, 98304, ACPU_PLL_0, 4, 1, 49152, 1, 3, 24576 },
+ { 0, 128000, ACPU_PLL_1, 1, 5, 64000, 1, 3, 24576 },
+ { 0, 176000, ACPU_PLL_2, 2, 5, 88000, 1, 3, 24576 },
+ { 1, 196608, ACPU_PLL_0, 4, 0, 65536, 2, 4, 24576 },
+ { 1, 256000, ACPU_PLL_1, 1, 2, 128000, 1, 5, 128000 },
+ { 0, 352000, ACPU_PLL_2, 2, 2, 88000, 3, 5, 128000 },
+ { 1, 384000, ACPU_PLL_1, 1, 1, 128000, 2, 6, 128000 },
+ { 1, 528000, ACPU_PLL_2, 2, 1, 132000, 3, 7, 128000 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x01/7x25 turbo with GSM capable modem */
+static struct clkctl_acpu_speed pll0_245_pll1_960_pll2_1056_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 30720 },
+ { 0, 120000, ACPU_PLL_1, 1, 7, 60000, 1, 3, 61440 },
+ { 1, 122880, ACPU_PLL_0, 4, 1, 61440, 1, 3, 61440 },
+ { 0, 176000, ACPU_PLL_2, 2, 5, 88000, 1, 3, 61440 },
+ { 1, 245760, ACPU_PLL_0, 4, 0, 81920, 2, 4, 61440 },
+ { 1, 320000, ACPU_PLL_1, 1, 2, 107000, 2, 5, 120000 },
+ { 0, 352000, ACPU_PLL_2, 2, 2, 88000, 3, 5, 120000 },
+ { 1, 480000, ACPU_PLL_1, 1, 1, 120000, 3, 6, 120000 },
+ { 1, 528000, ACPU_PLL_2, 2, 1, 132000, 3, 7, 122880 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x01/7x25 turbo with CDMA-only modem */
+static struct clkctl_acpu_speed pll0_196_pll1_960_pll2_1056_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 24576 },
+ { 1, 98304, ACPU_PLL_0, 4, 1, 49152, 1, 3, 24576 },
+ { 0, 120000, ACPU_PLL_1, 1, 7, 60000, 1, 3, 24576 },
+ { 0, 176000, ACPU_PLL_2, 2, 5, 88000, 1, 3, 24576 },
+ { 1, 196608, ACPU_PLL_0, 4, 0, 65536, 2, 4, 24576 },
+ { 1, 320000, ACPU_PLL_1, 1, 2, 107000, 2, 5, 120000 },
+ { 0, 352000, ACPU_PLL_2, 2, 2, 88000, 3, 5, 120000 },
+ { 1, 480000, ACPU_PLL_1, 1, 1, 120000, 3, 6, 120000 },
+ { 1, 528000, ACPU_PLL_2, 2, 1, 132000, 3, 7, 120000 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x27 normal with GSM capable modem */
+static struct clkctl_acpu_speed pll0_245_pll1_960_pll2_1200_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 30720 },
+ { 0, 120000, ACPU_PLL_1, 1, 7, 60000, 1, 3, 61440 },
+ { 1, 122880, ACPU_PLL_0, 4, 1, 61440, 1, 3, 61440 },
+ { 0, 200000, ACPU_PLL_2, 2, 5, 66667, 2, 4, 61440 },
+ { 1, 245760, ACPU_PLL_0, 4, 0, 122880, 1, 4, 61440 },
+ { 1, 320000, ACPU_PLL_1, 1, 2, 160000, 1, 5, 122880 },
+ { 0, 400000, ACPU_PLL_2, 2, 2, 133333, 2, 5, 122880 },
+ { 1, 480000, ACPU_PLL_1, 1, 1, 160000, 2, 6, 122880 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 7, 122880 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x27 normal with CDMA-only modem */
+static struct clkctl_acpu_speed pll0_196_pll1_960_pll2_1200_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 24576 },
+ { 1, 98304, ACPU_PLL_0, 4, 1, 98304, 0, 3, 49152 },
+ { 0, 120000, ACPU_PLL_1, 1, 7, 60000, 1, 3, 49152 },
+ { 1, 196608, ACPU_PLL_0, 4, 0, 65536, 2, 4, 98304 },
+ { 0, 200000, ACPU_PLL_2, 2, 5, 66667, 2, 4, 98304 },
+ { 1, 320000, ACPU_PLL_1, 1, 2, 160000, 1, 5, 120000 },
+ { 0, 400000, ACPU_PLL_2, 2, 2, 133333, 2, 5, 120000 },
+ { 1, 480000, ACPU_PLL_1, 1, 1, 160000, 2, 6, 120000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 7, 120000 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x27 normal with GSM capable modem - PLL0 and PLL1 swapped */
+static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 30720 },
+ { 0, 120000, ACPU_PLL_0, 4, 7, 60000, 1, 3, 61440 },
+ { 1, 122880, ACPU_PLL_1, 1, 1, 61440, 1, 3, 61440 },
+ { 0, 200000, ACPU_PLL_2, 2, 5, 66667, 2, 4, 61440 },
+ { 1, 245760, ACPU_PLL_1, 1, 0, 122880, 1, 4, 61440 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 160000, 1, 5, 122880 },
+ { 0, 400000, ACPU_PLL_2, 2, 2, 133333, 2, 5, 122880 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 122880 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 7, 122880 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x27 normal with CDMA-only modem - PLL0 and PLL1 swapped */
+static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 24576 },
+ { 1, 98304, ACPU_PLL_1, 1, 1, 98304, 0, 3, 49152 },
+ { 0, 120000, ACPU_PLL_0, 4, 7, 60000, 1, 3, 49152 },
+ { 1, 196608, ACPU_PLL_1, 1, 0, 65536, 2, 4, 98304 },
+ { 0, 200000, ACPU_PLL_2, 2, 5, 66667, 2, 4, 98304 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 160000, 1, 5, 120000 },
+ { 0, 400000, ACPU_PLL_2, 2, 2, 133333, 2, 5, 120000 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 120000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 7, 120000 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x27 normal with GSM capable modem - PLL0 and PLL1 swapped and pll2 @ 800 */
+static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_800_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 30720 },
+ { 0, 120000, ACPU_PLL_0, 4, 7, 60000, 1, 3, 61440 },
+ { 1, 122880, ACPU_PLL_1, 1, 1, 61440, 1, 3, 61440 },
+ { 0, 200000, ACPU_PLL_2, 2, 3, 66667, 2, 4, 61440 },
+ { 1, 245760, ACPU_PLL_1, 1, 0, 122880, 1, 4, 61440 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 160000, 1, 5, 122880 },
+ { 0, 400000, ACPU_PLL_2, 2, 1, 133333, 2, 5, 122880 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 122880 },
+ { 1, 800000, ACPU_PLL_2, 2, 0, 200000, 3, 7, 122880 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x27 normal with CDMA-only modem - PLL0 and PLL1 swapped and pll2 @ 800 */
+static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_800_pll4_0[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 24576 },
+ { 1, 98304, ACPU_PLL_1, 1, 1, 98304, 0, 3, 49152 },
+ { 0, 120000, ACPU_PLL_0, 4, 7, 60000, 1, 3, 49152 },
+ { 1, 196608, ACPU_PLL_1, 1, 0, 65536, 2, 4, 98304 },
+ { 0, 200000, ACPU_PLL_2, 2, 3, 66667, 2, 4, 98304 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 160000, 1, 5, 120000 },
+ { 0, 400000, ACPU_PLL_2, 2, 1, 133333, 2, 5, 120000 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 6, 120000 },
+ { 1, 800000, ACPU_PLL_2, 2, 0, 200000, 3, 7, 120000 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x27a pll2 at 1200mhz with GSM capable modem */
+static struct clkctl_acpu_speed pll0_960_pll1_245_pll2_1200_pll4_800[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 30720 },
+ { 0, 61440, ACPU_PLL_1, 1, 3, 61440, 0, 1, 61440 },
+ { 1, 122880, ACPU_PLL_1, 1, 1, 61440, 1, 2, 61440 },
+ { 1, 245760, ACPU_PLL_1, 1, 0, 122880, 1, 3, 61440 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 150000, 1, 4, 150000 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 160000, 1, 4, 122880 },
+ { 0, 400000, ACPU_PLL_4, 6, 1, 133333, 2, 4, 122880 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 5, 122880 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 6, 200000 },
+ { 1, 800000, ACPU_PLL_4, 6, 0, 200000, 3, 7, 200000 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+/* 7x27a pll2 at 1200mhz with CDMA only modem */
+static struct clkctl_acpu_speed pll0_960_pll1_196_pll2_1200_pll4_800[] = {
+ { 0, 19200, ACPU_PLL_TCXO, 0, 0, 19200, 0, 0, 24576 },
+ { 0, 65536, ACPU_PLL_1, 1, 3, 65536, 0, 1, 49152 },
+ { 1, 98304, ACPU_PLL_1, 1, 1, 49152, 1, 2, 49152 },
+ { 1, 196608, ACPU_PLL_1, 1, 0, 98304, 1, 3, 98304 },
+ { 0, 300000, ACPU_PLL_2, 2, 3, 150000, 1, 4, 150000 },
+ { 1, 320000, ACPU_PLL_0, 4, 2, 160000, 1, 4, 160000 },
+ { 0, 400000, ACPU_PLL_4, 6, 1, 200000, 1, 4, 160000 },
+ { 1, 480000, ACPU_PLL_0, 4, 1, 160000, 2, 5, 160000 },
+ { 1, 600000, ACPU_PLL_2, 2, 1, 200000, 2, 6, 200000 },
+ { 1, 800000, ACPU_PLL_4, 6, 0, 200000, 3, 7, 200000 },
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0}, {0, 0, 0, 0} }
+};
+
+#define PLL_0_MHZ 0
+#define PLL_196_MHZ 10
+#define PLL_245_MHZ 12
+#define PLL_491_MHZ 25
+#define PLL_768_MHZ 40
+#define PLL_800_MHZ 41
+#define PLL_960_MHZ 50
+#define PLL_1056_MHZ 55
+#define PLL_1200_MHZ 62
+
+#define PLL_CONFIG(m0, m1, m2, m4) { \
+ PLL_##m0##_MHZ, PLL_##m1##_MHZ, PLL_##m2##_MHZ, PLL_##m4##_MHZ, \
+ pll0_##m0##_pll1_##m1##_pll2_##m2##_pll4_##m4 \
+}
+
+struct pll_freq_tbl_map {
+ unsigned int pll0_l;
+ unsigned int pll1_l;
+ unsigned int pll2_l;
+ unsigned int pll4_l;
+ struct clkctl_acpu_speed *tbl;
+};
+
+static struct pll_freq_tbl_map acpu_freq_tbl_list[] = {
+ PLL_CONFIG(196, 768, 1056, 0),
+ PLL_CONFIG(245, 768, 1056, 0),
+ PLL_CONFIG(196, 960, 1056, 0),
+ PLL_CONFIG(245, 960, 1056, 0),
+ PLL_CONFIG(196, 960, 1200, 0),
+ PLL_CONFIG(245, 960, 1200, 0),
+ PLL_CONFIG(960, 196, 1200, 0),
+ PLL_CONFIG(960, 245, 1200, 0),
+ PLL_CONFIG(960, 196, 800, 0),
+ PLL_CONFIG(960, 245, 800, 0),
+ PLL_CONFIG(960, 245, 1200, 800),
+ PLL_CONFIG(960, 196, 1200, 800),
+ { 0, 0, 0, 0, 0 }
+};
+
+#ifdef CONFIG_CPU_FREQ_MSM
+static struct cpufreq_frequency_table freq_table[20];
+
+static void __init cpufreq_table_init(void)
+{
+ unsigned int i;
+ unsigned int freq_cnt = 0;
+
+ /* Construct the freq_table table from acpu_freq_tbl since the
+ * freq_table values need to match frequencies specified in
+ * acpu_freq_tbl and acpu_freq_tbl needs to be fixed up during init.
+ */
+ for (i = 0; acpu_freq_tbl[i].a11clk_khz != 0
+ && freq_cnt < ARRAY_SIZE(freq_table)-1; i++) {
+ if (acpu_freq_tbl[i].use_for_scaling) {
+ freq_table[freq_cnt].index = freq_cnt;
+ freq_table[freq_cnt].frequency
+ = acpu_freq_tbl[i].a11clk_khz;
+ freq_cnt++;
+ }
+ }
+
+ /* freq_table not big enough to store all usable freqs. */
+ BUG_ON(acpu_freq_tbl[i].a11clk_khz != 0);
+
+ freq_table[freq_cnt].index = freq_cnt;
+ freq_table[freq_cnt].frequency = CPUFREQ_TABLE_END;
+
+ pr_info("%d scaling frequencies supported.\n", freq_cnt);
+}
+#endif
+
+static void pll_enable(void __iomem *addr, unsigned on)
+{
+ if (on) {
+ writel_relaxed(2, addr);
+ mb();
+ udelay(5);
+ writel_relaxed(6, addr);
+ mb();
+ udelay(50);
+ writel_relaxed(7, addr);
+ } else {
+ writel_relaxed(0, addr);
+ }
+}
+
+static int pc_pll_request(unsigned id, unsigned on)
+{
+ int res = 0;
+ on = !!on;
+
+ if (on)
+ pr_debug("Enabling PLL %d\n", id);
+ else
+ pr_debug("Disabling PLL %d\n", id);
+
+ if (id >= ACPU_PLL_END)
+ return -EINVAL;
+
+ if (pll_control) {
+ remote_spin_lock(&pll_lock);
+ if (on) {
+ pll_control->pll[PLL_BASE + id].votes |= 2;
+ if (!pll_control->pll[PLL_BASE + id].on) {
+ pll_enable(soc_pll[id].mod_reg, 1);
+ pll_control->pll[PLL_BASE + id].on = 1;
+ }
+ } else {
+ pll_control->pll[PLL_BASE + id].votes &= ~2;
+ if (pll_control->pll[PLL_BASE + id].on
+ && !pll_control->pll[PLL_BASE + id].votes) {
+ pll_enable(soc_pll[id].mod_reg, 0);
+ pll_control->pll[PLL_BASE + id].on = 0;
+ }
+ }
+ remote_spin_unlock(&pll_lock);
+ } else {
+ res = msm_proc_comm(PCOM_CLKCTL_RPC_PLL_REQUEST, &id, &on);
+ if (res < 0)
+ return res;
+ else if ((int) id < 0)
+ return -EINVAL;
+ }
+
+ if (on)
+ pr_debug("PLL enabled\n");
+ else
+ pr_debug("PLL disabled\n");
+
+ return res;
+}
+
+
+/*----------------------------------------------------------------------------
+ * ARM11 'owned' clock control
+ *---------------------------------------------------------------------------*/
+
+#define POWER_COLLAPSE_KHZ 19200
+unsigned long acpuclk_power_collapse(void)
+{
+ int ret = acpuclk_get_rate(smp_processor_id());
+ acpuclk_set_rate(smp_processor_id(), POWER_COLLAPSE_KHZ, SETRATE_PC);
+ return ret;
+}
+
+unsigned long acpuclk_wait_for_irq(void)
+{
+ int rate = acpuclk_get_rate(smp_processor_id());
+ if (rate > MAX_WAIT_FOR_IRQ_KHZ)
+ acpuclk_set_rate(smp_processor_id(), drv_state.wait_for_irq_khz,
+ SETRATE_SWFI);
+ return rate;
+}
+
+static int acpuclk_set_vdd_level(int vdd)
+{
+ uint32_t current_vdd;
+
+ /*
+ * NOTE: v1.0 of 7x27a/7x25a chip doesn't have working
+ * VDD switching support.
+ */
+ if ((cpu_is_msm7x27a() || cpu_is_msm7x25a()) &&
+ (SOCINFO_VERSION_MINOR(socinfo_get_version()) < 1))
+ return 0;
+
+ current_vdd = readl_relaxed(A11S_VDD_SVS_PLEVEL_ADDR) & 0x07;
+
+ pr_debug("Switching VDD from %u mV -> %d mV\n",
+ current_vdd, vdd);
+
+ writel_relaxed((1 << 7) | (vdd << 3), A11S_VDD_SVS_PLEVEL_ADDR);
+ mb();
+ udelay(drv_state.vdd_switch_time_us);
+ if ((readl_relaxed(A11S_VDD_SVS_PLEVEL_ADDR) & 0x7) != vdd) {
+ pr_err("VDD set failed\n");
+ return -EIO;
+ }
+
+ pr_debug("VDD switched\n");
+
+ return 0;
+}
+
+/* Set proper dividers for the given clock speed. */
+static void acpuclk_set_div(const struct clkctl_acpu_speed *hunt_s)
+{
+ uint32_t reg_clkctl, reg_clksel, clk_div, src_sel;
+
+ reg_clksel = readl_relaxed(A11S_CLK_SEL_ADDR);
+
+ /* AHB_CLK_DIV */
+ clk_div = (reg_clksel >> 1) & 0x03;
+ /* CLK_SEL_SRC1NO */
+ src_sel = reg_clksel & 1;
+
+ /*
+ * If the new clock divider is higher than the previous, then
+ * program the divider before switching the clock
+ */
+ if (hunt_s->ahbclk_div > clk_div) {
+ reg_clksel &= ~(0x3 << 1);
+ reg_clksel |= (hunt_s->ahbclk_div << 1);
+ writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+ }
+
+ /* Program clock source and divider */
+ reg_clkctl = readl_relaxed(A11S_CLK_CNTL_ADDR);
+ reg_clkctl &= ~(0xFF << (8 * src_sel));
+ reg_clkctl |= hunt_s->a11clk_src_sel << (4 + 8 * src_sel);
+ reg_clkctl |= hunt_s->a11clk_src_div << (0 + 8 * src_sel);
+ writel_relaxed(reg_clkctl, A11S_CLK_CNTL_ADDR);
+
+ /* Program clock source selection */
+ reg_clksel ^= 1;
+ writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+
+ /*
+ * If the new clock divider is lower than the previous, then
+ * program the divider after switching the clock
+ */
+ if (hunt_s->ahbclk_div < clk_div) {
+ reg_clksel &= ~(0x3 << 1);
+ reg_clksel |= (hunt_s->ahbclk_div << 1);
+ writel_relaxed(reg_clksel, A11S_CLK_SEL_ADDR);
+ }
+}
+
+int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason)
+{
+ uint32_t reg_clkctl;
+ struct clkctl_acpu_speed *cur_s, *tgt_s, *strt_s;
+ int res, rc = 0;
+ unsigned int plls_enabled = 0, pll;
+
+ if (reason == SETRATE_CPUFREQ)
+ mutex_lock(&drv_state.lock);
+
+ strt_s = cur_s = drv_state.current_speed;
+
+ WARN_ONCE(cur_s == NULL, "acpuclk_set_rate: not initialized\n");
+ if (cur_s == NULL) {
+ rc = -ENOENT;
+ goto out;
+ }
+
+ if (rate == cur_s->a11clk_khz)
+ goto out;
+
+ for (tgt_s = acpu_freq_tbl; tgt_s->a11clk_khz != 0; tgt_s++) {
+ if (tgt_s->a11clk_khz == rate)
+ break;
+ }
+
+ if (tgt_s->a11clk_khz == 0) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ /* Choose the highest speed at or below 'rate' with same PLL. */
+ if (reason != SETRATE_CPUFREQ
+ && tgt_s->a11clk_khz < cur_s->a11clk_khz) {
+ while (tgt_s->pll != ACPU_PLL_TCXO && tgt_s->pll != cur_s->pll)
+ tgt_s--;
+ }
+
+ if (strt_s->pll != ACPU_PLL_TCXO)
+ plls_enabled |= 1 << strt_s->pll;
+
+ if (reason == SETRATE_CPUFREQ) {
+ if (strt_s->pll != tgt_s->pll && tgt_s->pll != ACPU_PLL_TCXO) {
+ rc = pc_pll_request(tgt_s->pll, 1);
+ if (rc < 0) {
+ pr_err("PLL%d enable failed (%d)\n",
+ tgt_s->pll, rc);
+ goto out;
+ }
+ plls_enabled |= 1 << tgt_s->pll;
+ }
+ }
+ /* Need to do this when coming out of power collapse since some modem
+ * firmwares reset the VDD when the application processor enters power
+ * collapse. */
+ if (reason == SETRATE_CPUFREQ || reason == SETRATE_PC) {
+ /* Increase VDD if needed. */
+ if (tgt_s->vdd > cur_s->vdd) {
+ rc = acpuclk_set_vdd_level(tgt_s->vdd);
+ if (rc < 0) {
+ pr_err("Unable to switch ACPU vdd (%d)\n", rc);
+ goto out;
+ }
+ }
+ }
+
+ /* Set wait states for CPU inbetween frequency changes */
+ reg_clkctl = readl_relaxed(A11S_CLK_CNTL_ADDR);
+ reg_clkctl |= (100 << 16); /* set WT_ST_CNT */
+ writel_relaxed(reg_clkctl, A11S_CLK_CNTL_ADDR);
+
+ pr_debug("Switching from ACPU rate %u KHz -> %u KHz\n",
+ strt_s->a11clk_khz, tgt_s->a11clk_khz);
+
+ while (cur_s != tgt_s) {
+ /*
+ * Always jump to target freq if within 256mhz, regulardless of
+ * PLL. If differnece is greater, use the predefinied
+ * steppings in the table.
+ */
+ int d = abs((int)(cur_s->a11clk_khz - tgt_s->a11clk_khz));
+ if (d > drv_state.max_speed_delta_khz) {
+
+ if (tgt_s->a11clk_khz > cur_s->a11clk_khz) {
+ /* Step up: jump to target PLL as early as
+ * possible so indexing using TCXO (up[-1])
+ * never occurs. */
+ if (likely(cur_s->up[tgt_s->pll]))
+ cur_s = cur_s->up[tgt_s->pll];
+ else
+ cur_s = cur_s->up[cur_s->pll];
+ } else {
+ /* Step down: stay on current PLL as long as
+ * possible so indexing using TCXO (down[-1])
+ * never occurs. */
+ if (likely(cur_s->down[cur_s->pll]))
+ cur_s = cur_s->down[cur_s->pll];
+ else
+ cur_s = cur_s->down[tgt_s->pll];
+ }
+
+ if (cur_s == NULL) { /* This should not happen. */
+ pr_err("No stepping frequencies found. "
+ "strt_s:%u tgt_s:%u\n",
+ strt_s->a11clk_khz, tgt_s->a11clk_khz);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ } else {
+ cur_s = tgt_s;
+ }
+
+ pr_debug("STEP khz = %u, pll = %d\n",
+ cur_s->a11clk_khz, cur_s->pll);
+
+ if (cur_s->pll != ACPU_PLL_TCXO
+ && !(plls_enabled & (1 << cur_s->pll))) {
+ rc = pc_pll_request(cur_s->pll, 1);
+ if (rc < 0) {
+ pr_err("PLL%d enable failed (%d)\n",
+ cur_s->pll, rc);
+ goto out;
+ }
+ plls_enabled |= 1 << cur_s->pll;
+ }
+
+ acpuclk_set_div(cur_s);
+ drv_state.current_speed = cur_s;
+ /* Re-adjust lpj for the new clock speed. */
+ loops_per_jiffy = cur_s->lpj;
+ mb();
+ udelay(drv_state.acpu_switch_time_us);
+ }
+
+ /* Nothing else to do for SWFI. */
+ if (reason == SETRATE_SWFI)
+ goto out;
+
+ /* Change the AXI bus frequency if we can. */
+ if (strt_s->axiclk_khz != tgt_s->axiclk_khz) {
+ res = clk_set_rate(drv_state.ebi1_clk,
+ tgt_s->axiclk_khz * 1000);
+ if (res < 0)
+ pr_warning("Setting AXI min rate failed (%d)\n", res);
+ }
+
+ /* Disable PLLs we are not using anymore. */
+ if (tgt_s->pll != ACPU_PLL_TCXO)
+ plls_enabled &= ~(1 << tgt_s->pll);
+ for (pll = ACPU_PLL_0; pll < ACPU_PLL_END; pll++)
+ if (plls_enabled & (1 << pll)) {
+ res = pc_pll_request(pll, 0);
+ if (res < 0)
+ pr_warning("PLL%d disable failed (%d)\n",
+ pll, res);
+ }
+
+ /* Nothing else to do for power collapse. */
+ if (reason == SETRATE_PC)
+ goto out;
+
+ /* Drop VDD level if we can. */
+ if (tgt_s->vdd < strt_s->vdd) {
+ res = acpuclk_set_vdd_level(tgt_s->vdd);
+ if (res < 0)
+ pr_warning("Unable to drop ACPU vdd (%d)\n", res);
+ }
+
+ pr_debug("ACPU speed change complete\n");
+out:
+ if (reason == SETRATE_CPUFREQ)
+ mutex_unlock(&drv_state.lock);
+ return rc;
+}
+
+static void __init acpuclk_init(void)
+{
+ struct clkctl_acpu_speed *speed;
+ uint32_t div, sel;
+ int res;
+
+ /*
+ * Determine the rate of ACPU clock
+ */
+
+ if (!(readl_relaxed(A11S_CLK_SEL_ADDR) & 0x01)) { /* CLK_SEL_SRC1N0 */
+ /* CLK_SRC0_SEL */
+ sel = (readl_relaxed(A11S_CLK_CNTL_ADDR) >> 12) & 0x7;
+ /* CLK_SRC0_DIV */
+ div = (readl_relaxed(A11S_CLK_CNTL_ADDR) >> 8) & 0x0f;
+ } else {
+ /* CLK_SRC1_SEL */
+ sel = (readl_relaxed(A11S_CLK_CNTL_ADDR) >> 4) & 0x07;
+ /* CLK_SRC1_DIV */
+ div = readl_relaxed(A11S_CLK_CNTL_ADDR) & 0x0f;
+ }
+
+ /* Accomodate bootloaders that might not be implementing the
+ * workaround for the h/w bug in 7x25. */
+ if (cpu_is_msm7x25() && sel == 2)
+ sel = 3;
+
+ for (speed = acpu_freq_tbl; speed->a11clk_khz != 0; speed++) {
+ if (speed->a11clk_src_sel == sel
+ && (speed->a11clk_src_div == div))
+ break;
+ }
+ if (speed->a11clk_khz == 0) {
+ pr_err("Error - ACPU clock reports invalid speed\n");
+ return;
+ }
+
+ drv_state.current_speed = speed;
+ if (speed->pll != ACPU_PLL_TCXO)
+ if (pc_pll_request(speed->pll, 1))
+ pr_warning("Failed to vote for boot PLL\n");
+
+ res = clk_set_rate(drv_state.ebi1_clk, speed->axiclk_khz * 1000);
+ if (res < 0)
+ pr_warning("Setting AXI min rate failed (%d)\n", res);
+ res = clk_enable(drv_state.ebi1_clk);
+ if (res < 0)
+ pr_warning("Enabling AXI clock failed (%d)\n", res);
+
+ pr_info("ACPU running at %d KHz\n", speed->a11clk_khz);
+}
+
+unsigned long acpuclk_get_rate(int cpu)
+{
+ WARN_ONCE(drv_state.current_speed == NULL,
+ "acpuclk_get_rate: not initialized\n");
+ if (drv_state.current_speed)
+ return drv_state.current_speed->a11clk_khz;
+ else
+ return 0;
+}
+
+uint32_t acpuclk_get_switch_time(void)
+{
+ return drv_state.acpu_switch_time_us;
+}
+
+/*----------------------------------------------------------------------------
+ * Clock driver initialization
+ *---------------------------------------------------------------------------*/
+
+#define DIV2REG(n) ((n)-1)
+#define REG2DIV(n) ((n)+1)
+#define SLOWER_BY(div, factor) div = DIV2REG(REG2DIV(div) * factor)
+
+static void __init acpu_freq_tbl_fixup(void)
+{
+ unsigned long pll0_l, pll1_l, pll2_l, pll4_l;
+ int axi_160mhz = 0, axi_200mhz = 0;
+ struct pll_freq_tbl_map *lst;
+ struct clkctl_acpu_speed *t;
+ unsigned int pll0_needs_fixup = 0;
+
+ /* Wait for the PLLs to be initialized and then read their frequency.
+ */
+ do {
+ pll0_l = readl_relaxed(PLLn_L_VAL(0)) &
+ soc_pll[ACPU_PLL_0].l_val_mask;
+ cpu_relax();
+ udelay(50);
+ } while (pll0_l == 0);
+ do {
+ pll1_l = readl_relaxed(PLLn_L_VAL(1)) &
+ soc_pll[ACPU_PLL_1].l_val_mask;
+ cpu_relax();
+ udelay(50);
+ } while (pll1_l == 0);
+ do {
+ pll2_l = readl_relaxed(PLLn_L_VAL(2)) &
+ soc_pll[ACPU_PLL_2].l_val_mask;
+ cpu_relax();
+ udelay(50);
+ } while (pll2_l == 0);
+
+ pr_info("L val: PLL0: %d, PLL1: %d, PLL2: %d\n",
+ (int)pll0_l, (int)pll1_l, (int)pll2_l);
+
+ if (!cpu_is_msm7x27() && !cpu_is_msm7x25a()) {
+ do {
+ pll4_l = readl_relaxed(PLL4_L_VAL) &
+ soc_pll[ACPU_PLL_4].l_val_mask;
+ cpu_relax();
+ udelay(50);
+ } while (pll4_l == 0);
+ pr_info("L val: PLL4: %d\n", (int)pll4_l);
+ } else {
+ pll4_l = 0;
+ }
+
+ /* Some configurations run PLL0 twice as fast. Instead of having
+ * separate tables for this case, we simply fix up the ACPU clock
+ * source divider since it's a simple fix up.
+ */
+ if (pll0_l == PLL_491_MHZ) {
+ pll0_l = PLL_245_MHZ;
+ pll0_needs_fixup = 1;
+ }
+
+ /* Select the right table to use. */
+ for (lst = acpu_freq_tbl_list; lst->tbl != 0; lst++) {
+ if (lst->pll0_l == pll0_l && lst->pll1_l == pll1_l
+ && lst->pll2_l == pll2_l
+ && lst->pll4_l == pll4_l) {
+ acpu_freq_tbl = lst->tbl;
+ break;
+ }
+ }
+
+ if (acpu_freq_tbl == NULL) {
+ pr_crit("Unknown PLL configuration!\n");
+ BUG();
+ }
+
+ /* Fix up PLL0 source divider if necessary. Also, fix up the AXI to
+ * the max that's supported by the board (RAM used in board).
+ */
+ axi_160mhz = (pll0_l == PLL_960_MHZ || pll1_l == PLL_960_MHZ);
+ axi_200mhz = (pll2_l == PLL_1200_MHZ || pll2_l == PLL_800_MHZ);
+ for (t = &acpu_freq_tbl[0]; t->a11clk_khz != 0; t++) {
+
+ if (pll0_needs_fixup && t->pll == ACPU_PLL_0)
+ SLOWER_BY(t->a11clk_src_div, 2);
+ if (axi_160mhz && drv_state.max_axi_khz >= 160000
+ && t->ahbclk_khz > 128000)
+ t->axiclk_khz = 160000;
+ if (axi_200mhz && drv_state.max_axi_khz >= 200000
+ && t->ahbclk_khz > 160000)
+ t->axiclk_khz = 200000;
+ }
+
+ t--;
+ drv_state.max_axi_khz = t->axiclk_khz;
+
+ /* The default 7x27 ACPU clock plan supports running the AXI bus at
+ * 200 MHz. So we don't classify it as Turbo mode.
+ */
+ if (cpu_is_msm7x27())
+ return;
+
+ if (!axi_160mhz)
+ pr_info("Turbo mode not supported.\n");
+ else if (t->axiclk_khz == 160000)
+ pr_info("Turbo mode supported and enabled.\n");
+ else
+ pr_info("Turbo mode supported but not enabled.\n");
+}
+
+/*
+ * Hardware requires the CPU to be dropped to less than MAX_WAIT_FOR_IRQ_KHZ
+ * before entering a wait for irq low-power mode. Find a suitable rate.
+ */
+static unsigned long __init find_wait_for_irq_khz(void)
+{
+ unsigned long found_khz = 0;
+ int i;
+
+ for (i = 0; acpu_freq_tbl[i].a11clk_khz &&
+ acpu_freq_tbl[i].a11clk_khz <= MAX_WAIT_FOR_IRQ_KHZ; i++)
+ found_khz = acpu_freq_tbl[i].a11clk_khz;
+
+ return found_khz;
+}
+
+/* Initalize the lpj field in the acpu_freq_tbl. */
+static void __init lpj_init(void)
+{
+ int i;
+ const struct clkctl_acpu_speed *base_clk = drv_state.current_speed;
+ for (i = 0; acpu_freq_tbl[i].a11clk_khz; i++) {
+ acpu_freq_tbl[i].lpj = cpufreq_scale(loops_per_jiffy,
+ base_clk->a11clk_khz,
+ acpu_freq_tbl[i].a11clk_khz);
+ }
+}
+
+static void __init precompute_stepping(void)
+{
+ int i, step_idx;
+
+#define cur_freq acpu_freq_tbl[i].a11clk_khz
+#define step_freq acpu_freq_tbl[step_idx].a11clk_khz
+#define cur_pll acpu_freq_tbl[i].pll
+#define step_pll acpu_freq_tbl[step_idx].pll
+
+ for (i = 0; acpu_freq_tbl[i].a11clk_khz; i++) {
+
+ /* Calculate max "up" step for each destination PLL */
+ step_idx = i + 1;
+ while (step_freq && (step_freq - cur_freq)
+ <= drv_state.max_speed_delta_khz) {
+ acpu_freq_tbl[i].up[step_pll] =
+ &acpu_freq_tbl[step_idx];
+ step_idx++;
+ }
+ if (step_idx == (i + 1) && step_freq) {
+ pr_crit("Delta between freqs %u KHz and %u KHz is"
+ " too high!\n", cur_freq, step_freq);
+ BUG();
+ }
+
+ /* Calculate max "down" step for each destination PLL */
+ step_idx = i - 1;
+ while (step_idx >= 0 && (cur_freq - step_freq)
+ <= drv_state.max_speed_delta_khz) {
+ acpu_freq_tbl[i].down[step_pll] =
+ &acpu_freq_tbl[step_idx];
+ step_idx--;
+ }
+ if (step_idx == (i - 1) && i > 0) {
+ pr_crit("Delta between freqs %u KHz and %u KHz is"
+ " too high!\n", cur_freq, step_freq);
+ BUG();
+ }
+ }
+}
+
+static void __init print_acpu_freq_tbl(void)
+{
+ struct clkctl_acpu_speed *t;
+ short down_idx[ACPU_PLL_END];
+ short up_idx[ACPU_PLL_END];
+ int i, j;
+
+#define FREQ_IDX(freq_ptr) (freq_ptr - acpu_freq_tbl)
+ pr_info("Id CPU-KHz PLL DIV AHB-KHz ADIV AXI-KHz "
+ "D0 D1 D2 D4 U0 U1 U2 U4\n");
+
+ t = &acpu_freq_tbl[0];
+ for (i = 0; t->a11clk_khz != 0; i++) {
+
+ for (j = 0; j < ACPU_PLL_END; j++) {
+ down_idx[j] = t->down[j] ? FREQ_IDX(t->down[j]) : -1;
+ up_idx[j] = t->up[j] ? FREQ_IDX(t->up[j]) : -1;
+ }
+
+ pr_info("%2d %7d %3d %3d %7d %4d %7d "
+ "%2d %2d %2d %2d %2d %2d %2d %2d\n",
+ i, t->a11clk_khz, t->pll, t->a11clk_src_div + 1,
+ t->ahbclk_khz, t->ahbclk_div + 1, t->axiclk_khz,
+ down_idx[0], down_idx[1], down_idx[2], down_idx[4],
+ up_idx[0], up_idx[1], up_idx[2], up_idx[4]);
+
+ t++;
+ }
+}
+
+static void msm7x25_acpu_pll_hw_bug_fix(void)
+{
+ unsigned int n;
+
+ /* The 7625 has a hardware bug and in order to select PLL2 we
+ * must program PLL3. Use the same table, and just fix up the
+ * numbers on this target. */
+ for (n = 0; acpu_freq_tbl[n].a11clk_khz != 0; n++)
+ if (acpu_freq_tbl[n].pll == ACPU_PLL_2)
+ acpu_freq_tbl[n].a11clk_src_sel = 3;
+}
+
+static void shared_pll_control_init(void)
+{
+#define PLL_REMOTE_SPINLOCK_ID "S:7"
+ unsigned smem_size;
+ remote_spin_lock_init(&pll_lock, PLL_REMOTE_SPINLOCK_ID);
+ pll_control = smem_get_entry(SMEM_CLKREGIM_SOURCES, &smem_size);
+
+ if (!pll_control)
+ pr_warning("Can't find shared PLL control data structure!\n");
+ /* There might be more PLLs than what the application processor knows
+ * about. But the index used for each PLL is guaranteed to remain the
+ * same. */
+ else if (smem_size < sizeof(struct shared_pll_control))
+ pr_warning("Shared PLL control data structure too small!\n");
+ else if (pll_control->version != 0xCCEE0001)
+ pr_warning("Shared PLL control version mismatch!\n");
+ else {
+ pr_info("Shared PLL control available.\n");
+ return;
+ }
+
+ pll_control = NULL;
+ pr_warning("Falling back to proc_comm PLL control.\n");
+}
+
+void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *clkdata)
+{
+ pr_info("acpu_clock_init()\n");
+
+ drv_state.ebi1_clk = clk_get(NULL, "ebi1_acpu_clk");
+ BUG_ON(IS_ERR(drv_state.ebi1_clk));
+
+ mutex_init(&drv_state.lock);
+ shared_pll_control_init();
+ drv_state.acpu_switch_time_us = clkdata->acpu_switch_time_us;
+ drv_state.max_speed_delta_khz = clkdata->max_speed_delta_khz;
+ drv_state.vdd_switch_time_us = clkdata->vdd_switch_time_us;
+ drv_state.max_axi_khz = clkdata->max_axi_khz;
+ acpu_freq_tbl_fixup();
+ drv_state.wait_for_irq_khz = find_wait_for_irq_khz();
+ precompute_stepping();
+ if (cpu_is_msm7x25())
+ msm7x25_acpu_pll_hw_bug_fix();
+ acpuclk_init();
+ lpj_init();
+ print_acpu_freq_tbl();
+#ifdef CONFIG_CPU_FREQ_MSM
+ cpufreq_table_init();
+ cpufreq_frequency_table_get_attr(freq_table, smp_processor_id());
+#endif
+}
diff --git a/arch/arm/mach-msm/acpuclock.h b/arch/arm/mach-msm/acpuclock.h
index 415de2eb9a5..2aa288476a0 100644
--- a/arch/arm/mach-msm/acpuclock.h
+++ b/arch/arm/mach-msm/acpuclock.h
@@ -3,7 +3,7 @@
* MSM architecture clock driver header
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2007 QUALCOMM Incorporated
+ * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
* Author: San Mehat
*
* This software is licensed under the terms of the GNU General Public
@@ -20,13 +20,25 @@
#ifndef __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
-int acpuclk_set_rate(unsigned long rate, int for_power_collapse);
-unsigned long acpuclk_get_rate(void);
+#include
+
+enum setrate_reason {
+ SETRATE_CPUFREQ = 0,
+ SETRATE_SWFI,
+ SETRATE_PC,
+ SETRATE_HOTPLUG,
+ SETRATE_INIT,
+};
+
+int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason);
+unsigned long acpuclk_get_rate(int cpu);
uint32_t acpuclk_get_switch_time(void);
unsigned long acpuclk_wait_for_irq(void);
unsigned long acpuclk_power_collapse(void);
-unsigned long acpuclk_get_wfi_rate(void);
-
-
+#ifdef CONFIG_ARCH_MSM8960
+void acpuclock_secondary_init(void);
+#else
+static inline void acpuclock_secondary_init(void) { }
#endif
+#endif
diff --git a/arch/arm/mach-msm/arch-init-scorpion.S b/arch/arm/mach-msm/arch-init-scorpion.S
new file mode 100644
index 00000000000..82a6db8bb07
--- /dev/null
+++ b/arch/arm/mach-msm/arch-init-scorpion.S
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google, Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+/* TODO:
+ * - style cleanup
+ * - do we need to do *all* of this at boot?
+ */
+
+.text
+.code 32
+
+#define DSB .byte 0x4f, 0xf0, 0x7f, 0xf5
+#define ISB .byte 0x6f, 0xf0, 0x7f, 0xf5
+
+.equ TCSR_SPARE2, 0xA8700060
+
+SET_SA:
+ ldr r0, =TCSR_SPARE2
+ ldr r12, [r0]
+
+ /* pack bits 8,2,0 into 2,1,0 */
+ and r0, r12, #0x001
+ and r1, r12, #0x004
+ and r2, r12, #0x100
+ orr r0, r1, lsr #1
+ orr r0, r2, lsr #6
+
+ adr r1, table_l1_acc
+ mov r0, r0, lsl #2
+ ldr r3, [r1, r0]
+
+ /* write 3800XXXX to PVR0F0 */
+ orr r0, r3, #0x38000000
+ mcr p15, 0, r0, c15, c15, 0
+
+ /* write XXXX0000 to PVR2F0 */
+ mov r1, r3, lsl #16
+ mcr p15, 2, r1, c15, c15, 0
+
+ adr r1, table_l2_acc
+ and r0, r12, #0x008
+ and r2, r12, #0x002
+ orr r0, r0, r2, lsl #1
+ ldr r2, [r1, r0]
+
+ /* write to L2VR3F1 */
+ mcr p15, 3, r2, c15, c15, 1
+
+ bx lr
+
+table_l1_acc:
+ .word 0xFC00
+ .word 0xFC00
+ .word 0x7C00
+ .word 0xFC00
+ .word 0x3C00
+ .word 0x0400
+ .word 0x0C00
+ .word 0x1C00
+
+table_l2_acc:
+ .word 0x010102
+ .word 0x010102
+ .word 0x010101
+ .word 0x212102
+
+.globl __cpu_early_init
+__cpu_early_init:
+ //; Zero out r0 for use throughout this code. All other GPRs
+ //; (r1-r3) are set throughout this code to help establish
+ //; a consistent startup state for any code that follows.
+ //; Users should add code at the end of this routine to establish
+ //; their own stack address (r13), add translation page tables, enable
+ //; the caches, etc.
+ MOV r0, #0x0
+
+
+ //; Remove hardcoded cache settings. appsbl_handler.s calls Set_SA
+ //; API to dynamically configure cache for slow/nominal/fast parts
+
+ //; DCIALL to invalidate L2 cache bank (needs to be run 4 times, once per bank)
+ //; This must be done early in code (prior to enabling the caches)
+ MOV r1, #0x2
+ MCR p15, 0, r1, c9, c0, 6 //; DCIALL bank D ([15:14] == 2'b00)
+ ORR r1, r1, #0x00004000
+ MCR p15, 0, r1, c9, c0, 6 //; DCIALL bank C ([15:14] == 2'b01)
+ ADD r1, r1, #0x00004000
+ MCR p15, 0, r1, c9, c0, 6 //; DCIALL bank B ([15:14] == 2'b10)
+ ADD r1, r1, #0x00004000
+ MCR p15, 0, r1, c9, c0, 6 //; DCIALL bank A ([15:14] == 2'b11)
+
+ //; Initialize the BPCR - setup Global History Mask (GHRM) to all 1's
+ //; and have all address bits (AM) participate.
+ //; Different settings can be used to improve performance
+ // MOVW r1, #0x01FF
+.word 0xe30011ff // hardcoded MOVW instruction due to lack of compiler support
+ // MOVT r1, #0x01FF
+.word 0xe34011ff // hardcoded MOVT instruction due to lack of compiler support
+ MCR p15, 7, r1, c15, c0, 2 //; WCP15_BPCR
+
+
+ //; Initialize all I$ Victim Registers to 0 for startup
+ MCR p15, 0, r0, c9, c1, 0 //; WCP15_ICVIC0 r0
+ MCR p15, 0, r0, c9, c1, 1 //; WCP15_ICVIC1 r0
+ MCR p15, 0, r0, c9, c1, 2 //; WCP15_ICVIC2 r0
+ MCR p15, 0, r0, c9, c1, 3 //; WCP15_ICVIC3 r0
+ MCR p15, 0, r0, c9, c1, 4 //; WCP15_ICVIC4 r0
+ MCR p15, 0, r0, c9, c1, 5 //; WCP15_ICVIC5 r0
+ MCR p15, 0, r0, c9, c1, 6 //; WCP15_ICVIC5 r0
+ MCR p15, 0, r0, c9, c1, 7 //; WCP15_ICVIC7 r0
+
+ //; Initialize all I$ Locked Victim Registers (Unlocked Floors) to 0
+ MCR p15, 1, r0, c9, c1, 0 //; WCP15_ICFLOOR0 r0
+ MCR p15, 1, r0, c9, c1, 1 //; WCP15_ICFLOOR1 r0
+ MCR p15, 1, r0, c9, c1, 2 //; WCP15_ICFLOOR2 r0
+ MCR p15, 1, r0, c9, c1, 3 //; WCP15_ICFLOOR3 r0
+ MCR p15, 1, r0, c9, c1, 4 //; WCP15_ICFLOOR4 r0
+ MCR p15, 1, r0, c9, c1, 5 //; WCP15_ICFLOOR5 r0
+ MCR p15, 1, r0, c9, c1, 6 //; WCP15_ICFLOOR6 r0
+ MCR p15, 1, r0, c9, c1, 7 //; WCP15_ICFLOOR7 r0
+
+ //; Initialize all D$ Victim Registers to 0
+ MCR p15, 2, r0, c9, c1, 0 //; WP15_DCVIC0 r0
+ MCR p15, 2, r0, c9, c1, 1 //; WP15_DCVIC1 r0
+ MCR p15, 2, r0, c9, c1, 2 //; WP15_DCVIC2 r0
+ MCR p15, 2, r0, c9, c1, 3 //; WP15_DCVIC3 r0
+ MCR p15, 2, r0, c9, c1, 4 //; WP15_DCVIC4 r0
+ MCR p15, 2, r0, c9, c1, 5 //; WP15_DCVIC5 r0
+ MCR p15, 2, r0, c9, c1, 6 //; WP15_DCVIC6 r0
+ MCR p15, 2, r0, c9, c1, 7 //; WP15_DCVIC7 r0
+
+ //; Initialize all D$ Locked VDCtim Registers (Unlocked Floors) to 0
+ MCR p15, 3, r0, c9, c1, 0 //; WCP15_DCFLOOR0 r0
+ MCR p15, 3, r0, c9, c1, 1 //; WCP15_DCFLOOR1 r0
+ MCR p15, 3, r0, c9, c1, 2 //; WCP15_DCFLOOR2 r0
+ MCR p15, 3, r0, c9, c1, 3 //; WCP15_DCFLOOR3 r0
+ MCR p15, 3, r0, c9, c1, 4 //; WCP15_DCFLOOR4 r0
+ MCR p15, 3, r0, c9, c1, 5 //; WCP15_DCFLOOR5 r0
+ MCR p15, 3, r0, c9, c1, 6 //; WCP15_DCFLOOR6 r0
+ MCR p15, 3, r0, c9, c1, 7 //; WCP15_DCFLOOR7 r0
+
+ //; Initialize ASID to zero
+ MCR p15, 0, r0, c13, c0, 1 //; WCP15_CONTEXTIDR r0
+
+ //; ICIALL to invalidate entire I-Cache
+ MCR p15, 0, r0, c7, c5, 0 //; ICIALLU
+
+ //; DCIALL to invalidate entire D-Cache
+ MCR p15, 0, r0, c9, c0, 6 //; DCIALL r0
+
+
+ //; The VBAR (Vector Base Address Register) should be initialized
+ //; early in your code. We are setting it to zero
+ MCR p15, 0, r0, c12, c0, 0 //; WCP15_VBAR r0
+
+ //; Ensure the MCR's above have completed their operation before continuing
+ DSB
+ ISB
+
+ //;-------------------------------------------------------------------
+ //; There are a number of registers that must be set prior to enabling
+ //; the MMU. The DCAR is one of these registers. We are setting
+ //; it to zero (no access) to easily detect improper setup in subsequent
+ //; code sequences
+ //;-------------------------------------------------------------------
+ //; Setup DACR (Domain Access Control Register) to zero
+ MCR p15, 0, r0, c3, c0, 0 //; WCP15_DACR r0
+
+ //; Setup DCLKCR to allow normal D-Cache line fills
+ MCR p15, 1, r0, c9, c0, 7 //; WCP15_DCLKCR r0
+
+ //; Initialize the ADFSR and EFSR registers.
+ MCR p15, 0, r0, c5, c1, 0 //; ADFSR
+ MCR p15, 7, r0, c15, c0, 1 //; EFSR
+
+ //; Setup the TLBLKCR
+ //; Victim = 6'b000000; Floor = 6'b000000;
+ //; IASIDCFG = 2'b00 (State-Machine); IALLCFG = 2'b01 (Flash); BNA = 1'b0;
+ MOV r1, #0x02
+ MCR p15, 0, r1, c10, c1, 3 //; WCP15_TLBLKCR r1
+
+ //;Make sure TLBLKCR is complete before continuing
+ ISB
+
+ //; Invalidate the UTLB
+ MCR p15, 0, r0, c8, c7, 0 //; UTLBIALL
+
+ //; Make sure UTLB request has been presented to macro before continuing
+ ISB
+
+ //; setup L2CR1 to some default Instruction and data prefetching values
+ //; Users may want specific settings for various performance enhancements
+ //; In Halcyon we do not have broadcasting barriers. So we need to turn
+ // ; on bit 8 of L2CR1; which DBB:( Disable barrier broadcast )
+ MOV r2, #0x100
+ MCR p15, 3, r2, c15, c0, 3 //; WCP15_L2CR1 r0
+
+
+ //; Enable Z bit to enable branch prediction (default is off)
+ MRC p15, 0, r2, c1, c0, 0 //; RCP15_SCTLR r2
+ ORR r2, r2, #0x00000800
+ MCR p15, 0, r2, c1, c0, 0 //; WCP15_SCTLR r2
+
+#ifdef CONFIG_ARCH_QSD8X50
+ /* disable predecode repair cache for thumb2 (DPRC, set bit 4 in PVR0F2) */
+ mrc p15, 0, r2, c15, c15, 2
+ orr r2, r2, #0x10
+ mcr p15, 0, r2, c15, c15, 2
+#endif
+
+ mov r1, lr
+ //; Make sure Link stack is initialized with branch and links to sequential addresses
+ //; This aids in creating a predictable startup environment
+ BL SEQ1
+SEQ1: BL SEQ2
+SEQ2: BL SEQ3
+SEQ3: BL SEQ4
+SEQ4: BL SEQ5
+SEQ5: BL SEQ6
+SEQ6: BL SEQ7
+SEQ7: BL SEQ8
+SEQ8:
+ mov lr, r1
+
+ //; REMOVE FOLLOWING THREE INSTRUCTIONS WHEN POWER COLLAPSE IS ENA
+ //;Make sure the DBGOSLSR[LOCK] bit is cleared to allow access to the debug registers
+ //; Writing anything but the "secret code" to the DBGOSLAR clears the DBGOSLSR[LOCK] bit
+ MCR p14, 0, r0, c1, c0, 4 //; WCP14_DBGOSLAR r0
+
+
+ //; Read the DBGPRSR to clear the DBGPRSR[STICKYPD]
+ //; Any read to DBGPRSR clear the STICKYPD bit
+ //; ISB guarantees the read completes before attempting to
+ //; execute a CP14 instruction.
+ MRC p14, 0, r3, c1, c5, 4 //; RCP14_DBGPRSR r3
+ ISB
+
+ //; Initialize the Watchpoint Control Registers to zero (optional)
+ //;;; MCR p14, 0, r0, c0, c0, 7 ; WCP14_DBGWCR0 r0
+ //;;; MCR p14, 0, r0, c0, c1, 7 ; WCP14_DBGWCR1 r0
+
+
+ //;----------------------------------------------------------------------
+ //; The saved Program Status Registers (SPSRs) should be setup
+ //; prior to any automatic mode switches. The following
+ //; code sets these registers up to a known state. Users will need to
+ //; customize these settings to meet their needs.
+ //;----------------------------------------------------------------------
+ MOV r2, #0x1f
+ MOV r1, #0x17 //;ABT mode
+ msr cpsr_c, r1 //;ABT mode
+ msr spsr_cxfs, r2 //;clear the spsr
+ MOV r1, #0x1b //;UND mode
+ msr cpsr_c, r1 //;UND mode
+ msr spsr_cxfs, r2 //;clear the spsr
+ MOV r1, #0x11 //;FIQ mode
+ msr cpsr_c, r1 //;FIQ mode
+ msr spsr_cxfs, r2 //;clear the spsr
+ MOV r1, #0x12 //;IRQ mode
+ msr cpsr_c, r1 //;IRQ mode
+ msr spsr_cxfs, r2 //;clear the spsr
+ MOV r1, #0x16 //;Monitor mode
+ msr cpsr_c, r1 //;Monitor mode
+ msr spsr_cxfs, r2 //;clear the spsr
+ MOV r1, #0x13 //;SVC mode
+ msr cpsr_c, r1 //;SVC mode
+ msr spsr_cxfs, r2 //;clear the spsr
+
+
+ //;----------------------------------------------------------------------
+ //; Enabling Error reporting is something users may want to do at
+ //; some other point in time. We have chosen some default settings
+ //; that should be reviewed. Most of these registers come up in an
+ //; unpredictable state after reset.
+ //;----------------------------------------------------------------------
+//;Start of error and control setting
+
+ //; setup L2CR0 with various L2/TCM control settings
+ //; enable out of order bus attributes and error reporting
+ //; this register comes up unpredictable after reset
+ // MOVW r1, #0x0F0F
+.word 0xe3001f0f // hardcoded MOVW instruction due to lack of compiler support
+ // MOVT r1, #0xC005
+.word 0xe34c1005 // hardcoded MOVW instruction due to lack of compiler support
+ MCR p15, 3, r1, c15, c0, 1 //; WCP15_L2CR0 r1
+
+ //; setup L2CPUCR
+ //; MOV r2, #0xFF
+ //; Enable I and D cache parity
+ //;L2CPUCR[7:5] = 3~Rh7 ~V enable parity error reporting for modified,
+ //;tag, and data parity errors
+ MOV r2, #0xe0
+ MCR p15, 3, r2, c15, c0, 2 //; WCP15_L2CPUCR r2
+
+ //; setup SPCR
+ //; enable all error reporting (reset value is unpredicatble for most bits)
+ MOV r3, #0x0F
+ MCR p15, 0, r3, c9, c7, 0 //; WCP15_SPCR r3
+
+ //; setup DMACHCRs (reset value unpredictable)
+ //; control setting and enable all error reporting
+ MOV r1, #0x0F
+
+ //; DMACHCR0 = 0000000F
+ MOV r2, #0x00 //; channel 0
+ MCR p15, 0, r2, c11, c0, 0 //; WCP15_DMASELR r2
+ MCR p15, 0, r1, c11, c0, 2 //; WCP15_DMACHCR r1
+
+ //; DMACHCR1 = 0000000F
+ MOV r2, #0x01 //; channel 1
+ MCR p15, 0, r2, c11, c0, 0 //; WCP15_DMASELR r2
+ MCR p15, 0, r1, c11, c0, 2 //; WCP15_DMACHCR r1
+
+ //; DMACHCR2 = 0000000F
+ MOV r2, #0x02 //; channel 2
+ MCR p15, 0, r2, c11, c0, 0 //; WCP15_DMASELR r2
+ MCR p15, 0, r1, c11, c0, 2 //; WCP15_DMACHCR r1
+
+ //; DMACHCR3 = 0000000F
+ MOV r2, #0x03 //; channel 3
+ MCR p15, 0, r2, c11, c0, 0 //; WCP15_DMASELR r2
+ MCR p15, 0, r1, c11, c0, 2 //; WCP15_DMACHCR r1
+
+ //; Set ACTLR (reset unpredictable)
+ //; Set AVIVT control, error reporting, etc.
+ //; MOV r3, #0x07
+ //; Enable I and D cache parity
+ //;ACTLR[2:0] = 3'h7 - enable parity error reporting from L2/I$/D$)
+ //;ACTLR[5:4] = 2'h3 - enable parity
+ //;ACTLR[19:18] =2'h3 - always generate and check parity(when MMU disabled).
+ //;Value to be written #0xC0037
+ // MOVW r3, #0x0037
+.word 0xe3003037 // hardcoded MOVW instruction due to lack of compiler support
+ // MOVT r3, #0x000C
+.word 0xe340300c // hardcoded MOVW instruction due to lack of compiler support
+ //; read the version_id to determine if d-cache should be disabled
+ LDR r2, = 0xa8e00270 //;Read HW_REVISION_NUMBER, HWIO_HW_REVISION_NUMBER_ADDR
+ LDR r2,[r2]
+ AND r2,r2,#0xf0000000 //;hw_revision mask off bits 28-31
+ //;if HW_revision is 1.0 or older, (revision==0)
+ CMP r2,#0
+ //; Disable d-cache on older QSD8650 (Rev 1.0) silicon
+ orreq r3, r3, #0x4000 //;disable dcache
+ MCR p15, 0, r3, c1, c0, 1 //; WCP15_ACTLR r3
+
+//;End of error and control setting
+
+ //;----------------------------------------------------------------------
+ //; Unlock ETM and read StickyPD to halt the ETM clocks from running.
+ //; This is required for power saving whether the ETM is used or not.
+ //;----------------------------------------------------------------------
+
+ //;Clear ETMOSLSR[LOCK] bit
+ MOV r1, #0x00000000
+ MCR p14, 1, r1, c1, c0, 4 //; WCP14_ETMOSLAR r1
+
+ //;Clear ETMPDSR[STICKYPD] bit
+ MRC p14, 1, r2, c1, c5, 4 //; RCP14_ETMPDSR r2
+
+/*
+#ifdef APPSBL_ETM_ENABLE
+ ;----------------------------------------------------------------------
+ ; Optionally Enable the ETM (Embedded Trace Macro) which is used for debug
+ ;----------------------------------------------------------------------
+
+ ; enable ETM clock if disabled
+ MRC p15, 7, r1, c15, c0, 5 ; RCP15_CPMR r1
+ ORR r1, r1, #0x00000008
+ MCR p15, 7, r1, c15, c0, 5 ; WCP15_CPMR r1
+ ISB
+
+ ; set trigger event to counter1 being zero
+ MOV r3, #0x00000040
+ MCR p14, 1, r3, c0, c2, 0 ; WCP14_ETMTRIGGER r3
+
+ ; clear ETMSR
+ MOV r2, #0x00000000
+ MCR p14, 1, r2, c0, c4, 0 ; WCP14_ETMSR r2
+
+ ; clear trace enable single address comparator usage
+ MCR p14, 1, r2, c0, c7, 0 ; WCP14_ETMTECR2 r2
+
+ ; set trace enable to always
+ MOV r2, #0x0000006F
+ MCR p14, 1, r2, c0, c8, 0 ; WCP14_ETMTEEVR r2
+
+ ; clear trace enable address range comparator usage and exclude nothing
+ MOV r2, #0x01000000
+ MCR p14, 1, r2, c0, c9, 0 ; WCP14_ETMTECR1 r2
+
+ ; set view data to always
+ MOV r2, #0x0000006F
+ MCR p14, 1, r2, c0, c12, 0 ; WCP14_ETMVDEVR r2
+
+ ; clear view data single address comparator usage
+ MOV r2, #0x00000000
+ MCR p14, 1, r2, c0, c13, 0 ; WCP14_ETMVDCR1 r2
+
+ ; clear view data address range comparator usage and exclude nothing
+ MOV r2, #0x00010000
+ MCR p14, 1, r2, c0, c15, 0 ; WCP14_ETMVDCR3 r2
+
+ ; set counter1 to 194
+ MOV r2, #0x000000C2
+ MCR p14, 1, r2, c0, c0, 5 ; WCP14_ETMCNTRLDVR1 r2
+
+ ; set counter1 to never reload
+ MOV r2, #0x0000406F
+ MCR p14, 1, r2, c0, c8, 5 ; WCP14_ETMCNTRLDEVR1 r2
+
+ ; set counter1 to decrement every cycle
+ MOV r2, #0x0000006F
+ MCR p14, 1, r2, c0, c4, 5 ; WCP14_ETMCNTENR1 r2
+
+ ; Set trace synchronization frequency 1024 bytes
+ MOV r2, #0x00000400
+ MCR p14, 1, r2, c0, c8, 7 ; WCP14_ETMSYNCFR r2
+
+ ; Program etm control register
+ ; - Set the CPU to ETM clock ratio to 1:1
+ ; - Set the ETM to perform data address tracing
+ MOV r2, #0x00002008
+ MCR p14, 1, r2, c0, c0, 0 ; WCP14_ETMCR r2
+ ISB
+#endif *//* APPSBL_ETM_ENABLE */
+
+/*
+#ifdef APPSBL_VFP_ENABLE
+ ;----------------------------------------------------------------------
+ ; Perform the following operations if you intend to make use of
+ ; the VFP/Neon unit. Note that the FMXR instruction requires a CPU ID
+ ; indicating the VFP unit is present (i.e.Cortex-A8). .
+ ; Some tools will require full double precision floating point support
+ ; which will become available in Scorpion pass 2
+ ;----------------------------------------------------------------------
+ ; allow full access to CP 10 and 11 space for VFP/NEON use
+ MRC p15, 0, r1, c1, c0, 2 ; Read CP Access Control Register
+ ORR r1, r1, #0x00F00000 ; enable full access for p10,11
+ MCR p15, 0, r1, c1, c0, 2 ; Write CPACR
+
+ ;make sure the CPACR is complete before continuing
+ ISB
+
+ ; Enable VFP itself (certain OSes may want to dynamically set/clear
+ ; the enable bit based on the application being executed
+ MOV r1, #0x40000000
+ FMXR FPEXC, r1
+#endif *//* APPSBL_VFP_ENABLE */
+
+ /* we have no stack, so just tail-call into the SET_SA routine... */
+ b SET_SA
+
+.ltorg
diff --git a/arch/arm/mach-msm/avs.c b/arch/arm/mach-msm/avs.c
new file mode 100644
index 00000000000..827adab00e2
--- /dev/null
+++ b/arch/arm/mach-msm/avs.c
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "avs.h"
+
+#define AVSDSCR_INPUT 0x01004860 /* magic # from circuit designer */
+#define TSCSR_INPUT 0x00000001 /* enable temperature sense */
+
+#define TEMPRS 16 /* total number of temperature regions */
+#define GET_TEMPR() (avs_get_tscsr() >> 28) /* scale TSCSR[CTEMP] to regions */
+
+struct mutex avs_lock;
+
+static struct avs_state_s
+{
+ u32 freq_cnt; /* Frequencies supported list */
+ short *avs_v; /* Dyanmically allocated storage for
+ * 2D table of voltages over temp &
+ * freq. Used as a set of 1D tables.
+ * Each table is for a single temp.
+ * For usage see avs_get_voltage
+ */
+ int (*set_vdd) (int); /* Function Ptr for setting voltage */
+ int changing; /* Clock frequency is changing */
+ u32 freq_idx; /* Current frequency index */
+ int vdd; /* Current ACPU voltage */
+} avs_state;
+
+/*
+ * Update the AVS voltage vs frequency table, for current temperature
+ * Adjust based on the AVS delay circuit hardware status
+ */
+static void avs_update_voltage_table(short *vdd_table)
+{
+ u32 avscsr;
+ int cpu;
+ int vu;
+ int l2;
+ int i;
+ u32 cur_freq_idx;
+ short cur_voltage;
+
+ cur_freq_idx = avs_state.freq_idx;
+ cur_voltage = avs_state.vdd;
+
+ avscsr = avs_test_delays();
+ AVSDEBUG("avscsr=%x, avsdscr=%x\n", avscsr, avs_get_avsdscr());
+
+ /*
+ * Read the results for the various unit's AVS delay circuits
+ * 2=> up, 1=>down, 0=>no-change
+ */
+ cpu = ((avscsr >> 23) & 2) + ((avscsr >> 16) & 1);
+ vu = ((avscsr >> 28) & 2) + ((avscsr >> 21) & 1);
+ l2 = ((avscsr >> 29) & 2) + ((avscsr >> 22) & 1);
+
+ if ((cpu == 3) || (vu == 3) || (l2 == 3)) {
+ printk(KERN_ERR "AVS: Dly Synth O/P error\n");
+ } else if ((cpu == 2) || (l2 == 2) || (vu == 2)) {
+ /*
+ * even if one oscillator asks for up, increase the voltage,
+ * as its an indication we are running outside the
+ * critical acceptable range of v-f combination.
+ */
+ AVSDEBUG("cpu=%d l2=%d vu=%d\n", cpu, l2, vu);
+ AVSDEBUG("Voltage up at %d\n", cur_freq_idx);
+
+ if (cur_voltage >= VOLTAGE_MAX)
+ printk(KERN_ERR
+ "AVS: Voltage can not get high enough!\n");
+
+ /* Raise the voltage for all frequencies */
+ for (i = 0; i < avs_state.freq_cnt; i++) {
+ vdd_table[i] = cur_voltage + VOLTAGE_STEP;
+ if (vdd_table[i] > VOLTAGE_MAX)
+ vdd_table[i] = VOLTAGE_MAX;
+ }
+ } else if ((cpu == 1) && (l2 == 1) && (vu == 1)) {
+ if ((cur_voltage - VOLTAGE_STEP >= VOLTAGE_MIN) &&
+ (cur_voltage <= vdd_table[cur_freq_idx])) {
+ vdd_table[cur_freq_idx] = cur_voltage - VOLTAGE_STEP;
+ AVSDEBUG("Voltage down for %d and lower levels\n",
+ cur_freq_idx);
+
+ /* clamp to this voltage for all lower levels */
+ for (i = 0; i < cur_freq_idx; i++) {
+ if (vdd_table[i] > vdd_table[cur_freq_idx])
+ vdd_table[i] = vdd_table[cur_freq_idx];
+ }
+ }
+ }
+}
+
+/*
+ * Return the voltage for the target performance freq_idx and optionally
+ * use AVS hardware to check the present voltage freq_idx
+ */
+static short avs_get_target_voltage(int freq_idx, bool update_table)
+{
+ unsigned cur_tempr = GET_TEMPR();
+ unsigned temp_index = cur_tempr*avs_state.freq_cnt;
+
+ /* Table of voltages vs frequencies for this temp */
+ short *vdd_table = avs_state.avs_v + temp_index;
+
+ if (update_table)
+ avs_update_voltage_table(vdd_table);
+
+ return vdd_table[freq_idx];
+}
+
+
+/*
+ * Set the voltage for the freq_idx and optionally
+ * use AVS hardware to update the voltage
+ */
+static int avs_set_target_voltage(int freq_idx, bool update_table)
+{
+ int rc = 0;
+ int new_voltage = avs_get_target_voltage(freq_idx, update_table);
+ if (avs_state.vdd != new_voltage) {
+ AVSDEBUG("AVS setting V to %d mV @%d\n",
+ new_voltage, freq_idx);
+ rc = avs_state.set_vdd(new_voltage);
+ if (rc)
+ return rc;
+ avs_state.vdd = new_voltage;
+ }
+ return rc;
+}
+
+/*
+ * Notify avs of clk frquency transition begin & end
+ */
+int avs_adjust_freq(u32 freq_idx, int begin)
+{
+ int rc = 0;
+
+ if (!avs_state.set_vdd) {
+ /* AVS not initialized */
+ return 0;
+ }
+
+ if (freq_idx >= avs_state.freq_cnt) {
+ AVSDEBUG("Out of range :%d\n", freq_idx);
+ return -EINVAL;
+ }
+
+ mutex_lock(&avs_lock);
+ if ((begin && (freq_idx > avs_state.freq_idx)) ||
+ (!begin && (freq_idx < avs_state.freq_idx))) {
+ /* Update voltage before increasing frequency &
+ * after decreasing frequency
+ */
+ rc = avs_set_target_voltage(freq_idx, 0);
+ if (rc)
+ goto aaf_out;
+
+ avs_state.freq_idx = freq_idx;
+ }
+ avs_state.changing = begin;
+aaf_out:
+ mutex_unlock(&avs_lock);
+
+ return rc;
+}
+
+
+static struct delayed_work avs_work;
+static struct workqueue_struct *kavs_wq;
+#define AVS_DELAY ((CONFIG_HZ * 50 + 999) / 1000)
+
+static void do_avs_timer(struct work_struct *work)
+{
+ int cur_freq_idx;
+
+ mutex_lock(&avs_lock);
+ if (!avs_state.changing) {
+ /* Only adjust the voltage if clk is stable */
+ cur_freq_idx = avs_state.freq_idx;
+ avs_set_target_voltage(cur_freq_idx, 1);
+ }
+ mutex_unlock(&avs_lock);
+ queue_delayed_work_on(0, kavs_wq, &avs_work, AVS_DELAY);
+}
+
+
+static void __init avs_timer_init(void)
+{
+ INIT_DELAYED_WORK_DEFERRABLE(&avs_work, do_avs_timer);
+ queue_delayed_work_on(0, kavs_wq, &avs_work, AVS_DELAY);
+}
+
+static void __exit avs_timer_exit(void)
+{
+ cancel_delayed_work(&avs_work);
+}
+
+static int __init avs_work_init(void)
+{
+ kavs_wq = create_workqueue("avs");
+ if (!kavs_wq) {
+ printk(KERN_ERR "AVS initialization failed\n");
+ return -EFAULT;
+ }
+ avs_timer_init();
+
+ return 1;
+}
+
+static void __exit avs_work_exit(void)
+{
+ avs_timer_exit();
+ destroy_workqueue(kavs_wq);
+}
+
+int __init avs_init(int (*set_vdd)(int), u32 freq_cnt, u32 freq_idx)
+{
+ int i;
+
+ mutex_init(&avs_lock);
+
+ if (freq_cnt == 0)
+ return -EINVAL;
+
+ avs_state.freq_cnt = freq_cnt;
+
+ if (freq_idx >= avs_state.freq_cnt)
+ return -EINVAL;
+
+ avs_state.avs_v = kmalloc(TEMPRS * avs_state.freq_cnt *
+ sizeof(avs_state.avs_v[0]), GFP_KERNEL);
+
+ if (avs_state.avs_v == 0)
+ return -ENOMEM;
+
+ for (i = 0; i < TEMPRS*avs_state.freq_cnt; i++)
+ avs_state.avs_v[i] = VOLTAGE_MAX;
+
+ avs_reset_delays(AVSDSCR_INPUT);
+ avs_set_tscsr(TSCSR_INPUT);
+
+ avs_state.set_vdd = set_vdd;
+ avs_state.changing = 0;
+ avs_state.freq_idx = -1;
+ avs_state.vdd = -1;
+ avs_adjust_freq(freq_idx, 0);
+
+ avs_work_init();
+
+ return 0;
+}
+
+void __exit avs_exit()
+{
+ avs_work_exit();
+
+ kfree(avs_state.avs_v);
+}
+
+
diff --git a/arch/arm/mach-msm/avs.h b/arch/arm/mach-msm/avs.h
new file mode 100644
index 00000000000..a549e9de7f2
--- /dev/null
+++ b/arch/arm/mach-msm/avs.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef AVS_H
+#define AVS_H
+
+#define VOLTAGE_MIN 1000 /* mV */
+#define VOLTAGE_MAX 1250
+#define VOLTAGE_STEP 25
+
+int __init avs_init(int (*set_vdd)(int), u32 freq_cnt, u32 freq_idx);
+void __exit avs_exit(void);
+
+int avs_adjust_freq(u32 freq_index, int begin);
+
+/* Routines exported from avs_hw.S */
+#ifdef CONFIG_MSM_CPU_AVS
+u32 avs_test_delays(void);
+#else
+static inline u32 avs_test_delays(void)
+{ return 0; }
+#endif
+
+#ifdef CONFIG_MSM_AVS_HW
+u32 avs_reset_delays(u32 avsdscr);
+u32 avs_get_avscsr(void);
+u32 avs_get_avsdscr(void);
+u32 avs_get_tscsr(void);
+void avs_set_tscsr(u32 to_tscsr);
+void avs_disable(void);
+#else
+static inline u32 avs_reset_delays(u32 avsdscr)
+{ return 0; }
+static inline u32 avs_get_avscsr(void)
+{ return 0; }
+static inline u32 avs_get_avsdscr(void)
+{ return 0; }
+static inline u32 avs_get_tscsr(void)
+{ return 0; }
+static inline void avs_set_tscsr(u32 to_tscsr) {}
+static inline void avs_disable(void) {}
+#endif
+
+/*#define AVSDEBUG(x...) pr_info("AVS: " x);*/
+#define AVSDEBUG(...)
+
+#define AVS_DISABLE(cpu) do { \
+ if (get_cpu() == (cpu)) \
+ avs_disable(); \
+ put_cpu(); \
+ } while (0);
+
+#define AVS_ENABLE(cpu, x) do { \
+ if (get_cpu() == (cpu)) \
+ avs_reset_delays((x)); \
+ put_cpu(); \
+ } while (0);
+
+#endif /* AVS_H */
diff --git a/arch/arm/mach-msm/avs_hw.S b/arch/arm/mach-msm/avs_hw.S
new file mode 100644
index 00000000000..1cc3ce0b107
--- /dev/null
+++ b/arch/arm/mach-msm/avs_hw.S
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+ .text
+
+#ifdef CONFIG_MSM_CPU_AVS
+ .global avs_test_delays
+avs_test_delays:
+
+/* Read r1=CPMR and enable Never Sleep for VSLPDLY */
+ mrc p15, 7, r1, c15, c0, 5
+ orr r12, r1, #3, 24
+ mcr p15, 7, r12, c15, c0, 5
+
+/* Read r2=CPACR and enable full access to CP10 and CP11 space */
+ mrc p15, 0, r2, c1, c0, 2
+ orr r12, r2, #(0xf << 20)
+ mcr p15, 0, r12, c1, c0, 2
+ isb
+
+/* Read r3=FPEXC and or in FP enable, VFP/ASE enable = FPEXC[30]; */
+ fmrx r3, fpexc
+ orr r12, r3, #1, 2
+ fmxr fpexc, r12
+
+/*
+ * Do floating-point operations to prime the VFP pipeline. Use
+ * fcpyd d0, d0 as a floating point nop. This avoids changing VFP
+ * state.
+ */
+ fcpyd d0, d0
+ fcpyd d0, d0
+ fcpyd d0, d0
+
+/* Read r0=AVSCSR to get status from CPU, VFP, and L2 ring oscillators */
+ mrc p15, 7, r0, c15, c1, 7
+
+/* Restore FPEXC */
+ fmxr fpexc, r3
+
+/* Restore CPACR */
+ MCR p15, 0, r2, c1, c0, 2
+
+/* Restore CPMR */
+ mcr p15, 7, r1, c15, c0, 5
+ isb
+
+ bx lr
+#endif
+
+
+ .global avs_get_avscsr
+/* Read r0=AVSCSR to get status from CPU, VFP, and L2 ring oscillators */
+
+avs_get_avscsr:
+ mrc p15, 7, r0, c15, c1, 7
+ bx lr
+
+ .global avs_get_avsdscr
+/* Read r0=AVSDSCR to get the AVS Delay Synthesizer control settings */
+
+avs_get_avsdscr:
+ mrc p15, 7, r0, c15, c0, 6
+ bx lr
+
+
+
+
+ .global avs_get_tscsr
+/* Read r0=TSCSR to get temperature sensor control and status */
+
+avs_get_tscsr:
+ mrc p15, 7, r0, c15, c1, 0
+ bx lr
+
+ .global avs_set_tscsr
+/* Write TSCSR=r0 to set temperature sensor control and status */
+
+avs_set_tscsr:
+ mcr p15, 7, r0, c15, c1, 0
+ bx lr
+
+
+
+
+
+ .global avs_reset_delays
+avs_reset_delays:
+
+/* AVSDSCR(dly) to program delay */
+ mcr p15, 7, r0, c15, c0, 6
+
+/* Read r0=AVSDSCR */
+ mrc p15, 7, r0, c15, c0, 6
+
+/* AVSCSR(0x61) to enable CPU, V and L2 AVS module */
+ mov r3, #0x61
+ mcr p15, 7, r3, c15, c1, 7
+
+ bx lr
+
+
+
+ .global avs_disable
+avs_disable:
+
+/* Clear AVSCSR */
+ mov r0, #0
+
+/* Write AVSCSR */
+ mcr p15, 7, r0, c15, c1, 7
+
+ bx lr
+
+ .end
+
+
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
new file mode 100644
index 00000000000..667016d9e3c
--- /dev/null
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -0,0 +1,784 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+ * BAM DMUX module.
+ */
+
+#define DEBUG
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#define BAM_CH_LOCAL_OPEN 0x1
+#define BAM_CH_REMOTE_OPEN 0x2
+
+#define BAM_MUX_HDR_MAGIC_NO 0x33fc
+
+#define BAM_MUX_HDR_CMD_DATA 0
+#define BAM_MUX_HDR_CMD_OPEN 1
+#define BAM_MUX_HDR_CMD_CLOSE 2
+
+#define RX_STATE_HDR_QUEUED 0
+#define RX_STATE_DATA_QUEUED 1
+
+
+static int msm_bam_dmux_debug_enable;
+module_param_named(debug_enable, msm_bam_dmux_debug_enable,
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#if defined(DEBUG)
+static uint32_t bam_dmux_read_cnt;
+static uint32_t bam_dmux_write_cnt;
+static uint32_t bam_dmux_write_cpy_cnt;
+static uint32_t bam_dmux_write_cpy_bytes;
+
+#define DBG(x...) do { \
+ if (msm_bam_dmux_debug_enable) \
+ pr_debug(x); \
+ } while (0)
+
+#define DBG_INC_READ_CNT(x) do { \
+ bam_dmux_read_cnt += (x); \
+ if (msm_bam_dmux_debug_enable) \
+ pr_debug("%s: total read bytes %u\n", \
+ __func__, bam_dmux_read_cnt); \
+ } while (0)
+
+#define DBG_INC_WRITE_CNT(x) do { \
+ bam_dmux_write_cnt += (x); \
+ if (msm_bam_dmux_debug_enable) \
+ pr_debug("%s: total written bytes %u\n", \
+ __func__, bam_dmux_write_cnt); \
+ } while (0)
+
+#define DBG_INC_WRITE_CPY(x) do { \
+ bam_dmux_write_cpy_bytes += (x); \
+ bam_dmux_write_cpy_cnt++; \
+ if (msm_bam_dmux_debug_enable) \
+ pr_debug("%s: total write copy cnt %u, bytes %u\n", \
+ __func__, bam_dmux_write_cpy_cnt, \
+ bam_dmux_write_cpy_bytes); \
+ } while (0)
+#else
+#define DBG(x...) do { } while (0)
+#define DBG_INC_READ_CNT(x...) do { } while (0)
+#define DBG_INC_WRITE_CNT(x...) do { } while (0)
+#define DBG_INC_WRITE_CPY(x...) do { } while (0)
+#endif
+
+struct bam_ch_info {
+ uint32_t status;
+ void (*receive_cb)(void *, struct sk_buff *);
+ void (*write_done)(void *, struct sk_buff *);
+ void *priv;
+ spinlock_t lock;
+};
+
+struct tx_pkt_info {
+ struct sk_buff *skb;
+ dma_addr_t dma_address;
+ char is_cmd;
+ uint32_t len;
+ struct work_struct work;
+};
+
+struct rx_pkt_info {
+ struct sk_buff *skb;
+ dma_addr_t dma_address;
+ struct work_struct work;
+ struct list_head list_node;
+};
+
+#define A2_NUM_PIPES 6
+#define A2_SUMMING_THRESHOLD 4096
+#define A2_DEFAULT_DESCRIPTORS 32
+#define A2_PHYS_BASE 0x124C2000
+#define A2_PHYS_SIZE 0x2000
+#define BUFFER_SIZE 2048
+#define NUM_BUFFERS 32
+static struct delayed_work bam_init_work;
+static struct sps_bam_props a2_props;
+static struct sps_pipe *bam_tx_pipe;
+static struct sps_pipe *bam_rx_pipe;
+static struct sps_connect tx_connection;
+static struct sps_connect rx_connection;
+static struct sps_mem_buffer tx_desc_mem_buf;
+static struct sps_mem_buffer rx_desc_mem_buf;
+static struct sps_register_event tx_register_event;
+
+static struct bam_ch_info bam_ch[BAM_DMUX_NUM_CHANNELS];
+static int bam_mux_initialized;
+
+static LIST_HEAD(bam_rx_pool);
+static DEFINE_MUTEX(bam_rx_pool_lock);
+
+struct bam_mux_hdr {
+ uint16_t magic_num;
+ uint8_t reserved;
+ uint8_t cmd;
+ uint8_t pad_len;
+ uint8_t ch_id;
+ uint16_t pkt_len;
+};
+
+static void bam_mux_write_done(struct work_struct *work);
+static void handle_bam_mux_cmd(struct work_struct *work);
+static void rx_timer_work_func(struct work_struct *work);
+
+static DEFINE_MUTEX(bam_mux_lock);
+static DECLARE_WORK(rx_timer_work, rx_timer_work_func);
+
+static struct workqueue_struct *bam_mux_rx_workqueue;
+static struct workqueue_struct *bam_mux_tx_workqueue;
+
+#define bam_ch_is_open(x) \
+ (bam_ch[(x)].status == (BAM_CH_LOCAL_OPEN | BAM_CH_REMOTE_OPEN))
+
+#define bam_ch_is_local_open(x) \
+ (bam_ch[(x)].status & BAM_CH_LOCAL_OPEN)
+
+#define bam_ch_is_remote_open(x) \
+ (bam_ch[(x)].status & BAM_CH_REMOTE_OPEN)
+
+static void queue_rx(void)
+{
+ void *ptr;
+ struct rx_pkt_info *info;
+
+ info = kmalloc(sizeof(struct rx_pkt_info), GFP_KERNEL);
+ if (!info)
+ return; /*need better way to handle this */
+
+ INIT_WORK(&info->work, handle_bam_mux_cmd);
+
+ info->skb = __dev_alloc_skb(BUFFER_SIZE, GFP_KERNEL);
+ ptr = skb_put(info->skb, BUFFER_SIZE);
+
+ mutex_lock(&bam_rx_pool_lock);
+ list_add_tail(&info->list_node, &bam_rx_pool);
+ mutex_unlock(&bam_rx_pool_lock);
+
+ /* need a way to handle error case */
+ info->dma_address = dma_map_single(NULL, ptr, BUFFER_SIZE,
+ DMA_FROM_DEVICE);
+ sps_transfer_one(bam_rx_pipe, info->dma_address,
+ BUFFER_SIZE, info, 0);
+}
+
+static void bam_mux_process_data(struct sk_buff *rx_skb)
+{
+ unsigned long flags;
+ struct bam_mux_hdr *rx_hdr;
+
+ rx_hdr = (struct bam_mux_hdr *)rx_skb->data;
+
+ rx_skb->data = (unsigned char *)(rx_hdr + 1);
+ rx_skb->tail = rx_skb->data + rx_hdr->pkt_len;
+ rx_skb->len = rx_hdr->pkt_len;
+
+ spin_lock_irqsave(&bam_ch[rx_hdr->ch_id].lock, flags);
+ if (bam_ch[rx_hdr->ch_id].receive_cb)
+ bam_ch[rx_hdr->ch_id].receive_cb(bam_ch[rx_hdr->ch_id].priv,
+ rx_skb);
+ else
+ dev_kfree_skb_any(rx_skb);
+ spin_unlock_irqrestore(&bam_ch[rx_hdr->ch_id].lock, flags);
+
+ queue_rx();
+}
+
+static void handle_bam_mux_cmd(struct work_struct *work)
+{
+ unsigned long flags;
+ struct bam_mux_hdr *rx_hdr;
+ struct rx_pkt_info *info;
+ struct sk_buff *rx_skb;
+
+ info = container_of(work, struct rx_pkt_info, work);
+ rx_skb = info->skb;
+ kfree(info);
+
+ rx_hdr = (struct bam_mux_hdr *)rx_skb->data;
+
+ DBG_INC_READ_CNT(sizeof(struct bam_mux_hdr));
+ DBG("%s: magic %x reserved %d cmd %d pad %d ch %d len %d\n", __func__,
+ rx_hdr->magic_num, rx_hdr->reserved, rx_hdr->cmd,
+ rx_hdr->pad_len, rx_hdr->ch_id, rx_hdr->pkt_len);
+ if (rx_hdr->magic_num != BAM_MUX_HDR_MAGIC_NO) {
+ pr_err("%s: dropping invalid hdr. magic %x reserved %d cmd %d"
+ " pad %d ch %d len %d\n", __func__,
+ rx_hdr->magic_num, rx_hdr->reserved, rx_hdr->cmd,
+ rx_hdr->pad_len, rx_hdr->ch_id, rx_hdr->pkt_len);
+ dev_kfree_skb_any(rx_skb);
+ queue_rx();
+ return;
+ }
+ switch (rx_hdr->cmd) {
+ case BAM_MUX_HDR_CMD_DATA:
+ DBG_INC_READ_CNT(rx_hdr->pkt_len);
+ bam_mux_process_data(rx_skb);
+ break;
+ case BAM_MUX_HDR_CMD_OPEN:
+ spin_lock_irqsave(&bam_ch[rx_hdr->ch_id].lock, flags);
+ bam_ch[rx_hdr->ch_id].status |= BAM_CH_REMOTE_OPEN;
+ spin_unlock_irqrestore(&bam_ch[rx_hdr->ch_id].lock, flags);
+ dev_kfree_skb_any(rx_skb);
+ queue_rx();
+ break;
+ case BAM_MUX_HDR_CMD_CLOSE:
+ /* probably should drop pending write */
+ spin_lock_irqsave(&bam_ch[rx_hdr->ch_id].lock, flags);
+ bam_ch[rx_hdr->ch_id].status &= ~BAM_CH_REMOTE_OPEN;
+ spin_unlock_irqrestore(&bam_ch[rx_hdr->ch_id].lock, flags);
+ dev_kfree_skb_any(rx_skb);
+ queue_rx();
+ break;
+ default:
+ pr_err("%s: dropping invalid hdr. magic %x reserved %d cmd %d"
+ " pad %d ch %d len %d\n", __func__,
+ rx_hdr->magic_num, rx_hdr->reserved, rx_hdr->cmd,
+ rx_hdr->pad_len, rx_hdr->ch_id, rx_hdr->pkt_len);
+ dev_kfree_skb_any(rx_skb);
+ queue_rx();
+ return;
+ }
+}
+
+static int bam_mux_write_cmd(void *data, uint32_t len)
+{
+ int rc;
+ struct tx_pkt_info *pkt;
+ dma_addr_t dma_address;
+
+ mutex_lock(&bam_mux_lock);
+ pkt = kmalloc(sizeof(struct tx_pkt_info), GFP_KERNEL);
+ if (pkt == NULL) {
+ pr_err("%s: mem alloc for tx_pkt_info failed\n", __func__);
+ rc = -ENOMEM;
+ mutex_unlock(&bam_mux_lock);
+ return rc;
+ }
+
+ dma_address = dma_map_single(NULL, data, len,
+ DMA_TO_DEVICE);
+ if (!dma_address) {
+ pr_err("%s: dma_map_single() failed\n", __func__);
+ rc = -ENOMEM;
+ mutex_unlock(&bam_mux_lock);
+ return rc;
+ }
+ pkt->skb = (struct sk_buff *)(data);
+ pkt->len = len;
+ pkt->dma_address = dma_address;
+ pkt->is_cmd = 1;
+ rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
+ pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+
+ mutex_unlock(&bam_mux_lock);
+ return rc;
+}
+
+static void bam_mux_write_done(struct work_struct *work)
+{
+ struct sk_buff *skb;
+ struct bam_mux_hdr *hdr;
+ struct tx_pkt_info *info;
+
+ info = container_of(work, struct tx_pkt_info, work);
+ skb = info->skb;
+ kfree(info);
+ hdr = (struct bam_mux_hdr *)skb->data;
+ DBG_INC_WRITE_CNT(skb->data_len);
+ if (bam_ch[hdr->ch_id].write_done)
+ bam_ch[hdr->ch_id].write_done(
+ bam_ch[hdr->ch_id].priv, skb);
+ else
+ dev_kfree_skb_any(skb);
+}
+
+int msm_bam_dmux_write(uint32_t id, struct sk_buff *skb)
+{
+ int rc = 0;
+ struct bam_mux_hdr *hdr;
+ unsigned long flags;
+ struct sk_buff *new_skb = NULL;
+ dma_addr_t dma_address;
+ struct tx_pkt_info *pkt;
+
+ if (id >= BAM_DMUX_NUM_CHANNELS)
+ return -EINVAL;
+ if (!skb)
+ return -EINVAL;
+ if (!bam_mux_initialized)
+ return -ENODEV;
+
+ DBG("%s: writing to ch %d len %d\n", __func__, id, skb->len);
+ spin_lock_irqsave(&bam_ch[id].lock, flags);
+ if (!bam_ch_is_open(id)) {
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+ pr_err("%s: port not open: %d\n", __func__, bam_ch[id].status);
+ return -ENODEV;
+ }
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+
+ /* if skb do not have any tailroom for padding,
+ copy the skb into a new expanded skb */
+ if ((skb->len & 0x3) && (skb_tailroom(skb) < (4 - (skb->len & 0x3)))) {
+ /* revisit, probably dev_alloc_skb and memcpy is effecient */
+ new_skb = skb_copy_expand(skb, skb_headroom(skb),
+ 4 - (skb->len & 0x3), GFP_ATOMIC);
+ if (new_skb == NULL) {
+ pr_err("%s: cannot allocate skb\n", __func__);
+ return -ENOMEM;
+ }
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+ DBG_INC_WRITE_CPY(skb->len);
+ }
+
+ hdr = (struct bam_mux_hdr *)skb_push(skb, sizeof(struct bam_mux_hdr));
+
+ /* caller should allocate for hdr and padding
+ hdr is fine, padding is tricky */
+ hdr->magic_num = BAM_MUX_HDR_MAGIC_NO;
+ hdr->cmd = BAM_MUX_HDR_CMD_DATA;
+ hdr->reserved = 0;
+ hdr->ch_id = id;
+ hdr->pkt_len = skb->len - sizeof(struct bam_mux_hdr);
+ if (skb->len & 0x3)
+ skb_put(skb, 4 - (skb->len & 0x3));
+
+ hdr->pad_len = skb->len - (sizeof(struct bam_mux_hdr) + hdr->pkt_len);
+
+ DBG("%s: data %p, tail %p skb len %d pkt len %d pad len %d\n",
+ __func__, skb->data, skb->tail, skb->len,
+ hdr->pkt_len, hdr->pad_len);
+
+ pkt = kmalloc(sizeof(struct tx_pkt_info), GFP_ATOMIC);
+ if (pkt == NULL) {
+ pr_err("%s: mem alloc for tx_pkt_info failed\n", __func__);
+ if (new_skb)
+ dev_kfree_skb_any(new_skb);
+ return -ENOMEM;
+ }
+
+ dma_address = dma_map_single(NULL, skb->data, skb->len,
+ DMA_TO_DEVICE);
+ if (!dma_address) {
+ pr_err("%s: dma_map_single() failed\n", __func__);
+ if (new_skb)
+ dev_kfree_skb_any(new_skb);
+ kfree(pkt);
+ return -ENOMEM;
+ }
+ pkt->skb = skb;
+ pkt->dma_address = dma_address;
+ pkt->is_cmd = 0;
+ INIT_WORK(&pkt->work, bam_mux_write_done);
+ rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
+ pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+ return rc;
+}
+
+int msm_bam_dmux_open(uint32_t id, void *priv,
+ void (*receive_cb)(void *, struct sk_buff *),
+ void (*write_done)(void *, struct sk_buff *))
+{
+ struct bam_mux_hdr *hdr;
+ unsigned long flags;
+ int rc = 0;
+
+ DBG("%s: opening ch %d\n", __func__, id);
+ if (!bam_mux_initialized)
+ return -ENODEV;
+ if (id >= BAM_DMUX_NUM_CHANNELS)
+ return -EINVAL;
+
+ hdr = kmalloc(sizeof(struct bam_mux_hdr), GFP_KERNEL);
+ if (hdr == NULL) {
+ pr_err("%s: hdr kmalloc failed. ch: %d\n", __func__, id);
+ return -ENOMEM;
+ }
+ spin_lock_irqsave(&bam_ch[id].lock, flags);
+ if (bam_ch_is_open(id)) {
+ DBG("%s: Already opened %d\n", __func__, id);
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+ kfree(hdr);
+ goto open_done;
+ }
+ if (!bam_ch_is_remote_open(id)) {
+ DBG("%s: Remote not open; ch: %d\n", __func__, id);
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+ kfree(hdr);
+ rc = -ENODEV;
+ goto open_done;
+ }
+
+ bam_ch[id].receive_cb = receive_cb;
+ bam_ch[id].write_done = write_done;
+ bam_ch[id].priv = priv;
+ bam_ch[id].status |= BAM_CH_LOCAL_OPEN;
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+
+ hdr->magic_num = BAM_MUX_HDR_MAGIC_NO;
+ hdr->cmd = BAM_MUX_HDR_CMD_OPEN;
+ hdr->reserved = 0;
+ hdr->ch_id = id;
+ hdr->pkt_len = 0;
+ hdr->pad_len = 0;
+
+ rc = bam_mux_write_cmd((void *)hdr, sizeof(struct bam_mux_hdr));
+
+open_done:
+ DBG("%s: opened ch %d\n", __func__, id);
+ return rc;
+}
+
+int msm_bam_dmux_close(uint32_t id)
+{
+ struct bam_mux_hdr *hdr;
+ unsigned long flags;
+ int rc;
+
+ if (id >= BAM_DMUX_NUM_CHANNELS)
+ return -EINVAL;
+ DBG("%s: closing ch %d\n", __func__, id);
+ if (!bam_mux_initialized)
+ return -ENODEV;
+ spin_lock_irqsave(&bam_ch[id].lock, flags);
+
+ bam_ch[id].write_done = NULL;
+ bam_ch[id].receive_cb = NULL;
+ bam_ch[id].priv = NULL;
+ bam_ch[id].status &= ~BAM_CH_LOCAL_OPEN;
+ spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+
+ hdr = kmalloc(sizeof(struct bam_mux_hdr), GFP_KERNEL);
+ if (hdr == NULL) {
+ pr_err("%s: hdr kmalloc failed. ch: %d\n", __func__, id);
+ return -ENOMEM;
+ }
+ hdr->magic_num = BAM_MUX_HDR_MAGIC_NO;
+ hdr->cmd = BAM_MUX_HDR_CMD_CLOSE;
+ hdr->reserved = 0;
+ hdr->ch_id = id;
+ hdr->pkt_len = 0;
+ hdr->pad_len = 0;
+
+ rc = bam_mux_write_cmd((void *)hdr, sizeof(struct bam_mux_hdr));
+
+ DBG("%s: closed ch %d\n", __func__, id);
+ return rc;
+}
+
+static void rx_timer_work_func(struct work_struct *work)
+{
+ struct sps_iovec iov;
+ struct list_head *node;
+ struct rx_pkt_info *info;
+
+ while (1) {
+ sps_get_iovec(bam_rx_pipe, &iov);
+ if (iov.addr == 0)
+ break;
+ mutex_lock(&bam_rx_pool_lock);
+ node = bam_rx_pool.next;
+ list_del(node);
+ mutex_unlock(&bam_rx_pool_lock);
+ info = container_of(node, struct rx_pkt_info, list_node);
+ handle_bam_mux_cmd(&info->work);
+ }
+
+ msleep(1);
+ queue_work(bam_mux_rx_workqueue, &rx_timer_work);
+}
+
+static void bam_mux_tx_notify(struct sps_event_notify *notify)
+{
+ struct tx_pkt_info *pkt;
+
+ DBG("%s: event %d notified\n", __func__, notify->event_id);
+
+ switch (notify->event_id) {
+ case SPS_EVENT_EOT:
+ pkt = notify->data.transfer.user;
+ if (!pkt->is_cmd) {
+ dma_unmap_single(NULL, pkt->dma_address,
+ pkt->skb->len,
+ DMA_TO_DEVICE);
+ queue_work(bam_mux_tx_workqueue, &pkt->work);
+ } else {
+ dma_unmap_single(NULL, pkt->dma_address,
+ pkt->len,
+ DMA_TO_DEVICE);
+ kfree(pkt->skb);
+ kfree(pkt);
+ }
+ break;
+ default:
+ pr_err("%s: recieved unexpected event id %d\n", __func__,
+ notify->event_id);
+ }
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static int debug_tbl(char *buf, int max)
+{
+ int i = 0;
+ int j;
+
+ for (j = 0; j < BAM_DMUX_NUM_CHANNELS; ++j) {
+ i += scnprintf(buf + i, max - i,
+ "ch%02d local open=%s remote open=%s\n",
+ j, bam_ch_is_local_open(j) ? "Y" : "N",
+ bam_ch_is_remote_open(j) ? "Y" : "N");
+ }
+
+ return i;
+}
+
+#define DEBUG_BUFMAX 4096
+static char debug_buffer[DEBUG_BUFMAX];
+
+static ssize_t debug_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int (*fill)(char *buf, int max) = file->private_data;
+ int bsize = fill(debug_buffer, DEBUG_BUFMAX);
+ return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
+}
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+
+static const struct file_operations debug_ops = {
+ .read = debug_read,
+ .open = debug_open,
+};
+
+static void debug_create(const char *name, mode_t mode,
+ struct dentry *dent,
+ int (*fill)(char *buf, int max))
+{
+ debugfs_create_file(name, mode, dent, fill, &debug_ops);
+}
+
+#endif
+
+static void bam_init(struct work_struct *work)
+{
+ u32 h;
+ dma_addr_t dma_addr;
+ int ret;
+ void *a2_virt_addr;
+ int i;
+
+ /* init BAM */
+ a2_virt_addr = ioremap_nocache(A2_PHYS_BASE, A2_PHYS_SIZE);
+ if (!a2_virt_addr) {
+ pr_err("%s: ioremap failed\n", __func__);
+ ret = -ENOMEM;
+ goto register_bam_failed;
+ }
+ a2_props.phys_addr = A2_PHYS_BASE;
+ a2_props.virt_addr = a2_virt_addr;
+ a2_props.virt_size = A2_PHYS_SIZE;
+ a2_props.irq = A2_BAM_IRQ;
+ a2_props.num_pipes = A2_NUM_PIPES;
+ a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
+ /* need to free on tear down */
+ ret = sps_register_bam_device(&a2_props, &h);
+ if (ret < 0) {
+ pr_err("%s: register bam error %d\n", __func__, ret);
+ goto register_bam_failed;
+ }
+
+ bam_tx_pipe = sps_alloc_endpoint();
+ if (bam_tx_pipe == NULL) {
+ pr_err("%s: tx alloc endpoint failed\n", __func__);
+ ret = -ENOMEM;
+ goto register_bam_failed;
+ }
+ ret = sps_get_config(bam_tx_pipe, &tx_connection);
+ if (ret) {
+ pr_err("%s: tx get config failed %d\n", __func__, ret);
+ goto tx_get_config_failed;
+ }
+
+ tx_connection.source = SPS_DEV_HANDLE_MEM;
+ tx_connection.src_pipe_index = 0;
+ tx_connection.destination = h;
+ tx_connection.dest_pipe_index = 4;
+ tx_connection.mode = SPS_MODE_DEST;
+ tx_connection.options = SPS_O_AUTO_ENABLE | SPS_O_EOT;
+ tx_desc_mem_buf.size = 0x800; /* 2k */
+ tx_desc_mem_buf.base = dma_alloc_coherent(NULL, tx_desc_mem_buf.size,
+ &dma_addr, 0);
+ if (tx_desc_mem_buf.base == NULL) {
+ pr_err("%s: tx memory alloc failed\n", __func__);
+ ret = -ENOMEM;
+ goto tx_mem_failed;
+ }
+ tx_desc_mem_buf.phys_base = dma_addr;
+ memset(tx_desc_mem_buf.base, 0x0, tx_desc_mem_buf.size);
+ tx_connection.desc = tx_desc_mem_buf;
+ tx_connection.event_thresh = 0x10;
+
+ ret = sps_connect(bam_tx_pipe, &tx_connection);
+ if (ret < 0) {
+ pr_err("%s: tx connect error %d\n", __func__, ret);
+ goto tx_connect_failed;
+ }
+
+ bam_rx_pipe = sps_alloc_endpoint();
+ if (bam_rx_pipe == NULL) {
+ pr_err("%s: rx alloc endpoint failed\n", __func__);
+ ret = -ENOMEM;
+ goto tx_connect_failed;
+ }
+ ret = sps_get_config(bam_rx_pipe, &rx_connection);
+ if (ret) {
+ pr_err("%s: rx get config failed %d\n", __func__, ret);
+ goto rx_get_config_failed;
+ }
+
+ rx_connection.source = h;
+ rx_connection.src_pipe_index = 5;
+ rx_connection.destination = SPS_DEV_HANDLE_MEM;
+ rx_connection.dest_pipe_index = 1;
+ rx_connection.mode = SPS_MODE_SRC;
+ rx_connection.options = SPS_O_AUTO_ENABLE | SPS_O_EOT |
+ SPS_O_ACK_TRANSFERS | SPS_O_POLL;
+ rx_desc_mem_buf.size = 0x800; /* 2k */
+ rx_desc_mem_buf.base = dma_alloc_coherent(NULL, rx_desc_mem_buf.size,
+ &dma_addr, 0);
+ if (rx_desc_mem_buf.base == NULL) {
+ pr_err("%s: rx memory alloc failed\n", __func__);
+ ret = -ENOMEM;
+ goto rx_mem_failed;
+ }
+ rx_desc_mem_buf.phys_base = dma_addr;
+ memset(rx_desc_mem_buf.base, 0x0, rx_desc_mem_buf.size);
+ rx_connection.desc = rx_desc_mem_buf;
+ rx_connection.event_thresh = 0x10;
+
+ ret = sps_connect(bam_rx_pipe, &rx_connection);
+ if (ret < 0) {
+ pr_err("%s: rx connect error %d\n", __func__, ret);
+ goto rx_connect_failed;
+ }
+
+ tx_register_event.options = SPS_O_EOT;
+ tx_register_event.mode = SPS_TRIGGER_CALLBACK;
+ tx_register_event.xfer_done = NULL;
+ tx_register_event.callback = bam_mux_tx_notify;
+ tx_register_event.user = NULL;
+ ret = sps_register_event(bam_tx_pipe, &tx_register_event);
+ if (ret < 0) {
+ pr_err("%s: tx register event error %d\n", __func__, ret);
+ goto rx_event_reg_failed;
+ }
+
+ bam_mux_initialized = 1;
+ for (i = 0; i < NUM_BUFFERS; ++i)
+ queue_rx();
+
+ queue_work(bam_mux_rx_workqueue, &rx_timer_work);
+ return;
+
+rx_event_reg_failed:
+ sps_disconnect(bam_rx_pipe);
+rx_connect_failed:
+ dma_free_coherent(NULL, rx_desc_mem_buf.size, rx_desc_mem_buf.base,
+ rx_desc_mem_buf.phys_base);
+rx_mem_failed:
+ sps_disconnect(bam_tx_pipe);
+rx_get_config_failed:
+ sps_free_endpoint(bam_rx_pipe);
+tx_connect_failed:
+ dma_free_coherent(NULL, tx_desc_mem_buf.size, tx_desc_mem_buf.base,
+ tx_desc_mem_buf.phys_base);
+tx_get_config_failed:
+ sps_free_endpoint(bam_tx_pipe);
+tx_mem_failed:
+ sps_deregister_bam_device(h);
+register_bam_failed:
+ /*destroy_workqueue(bam_mux_workqueue);*/
+ /*return ret;*/
+ return;
+}
+static int bam_dmux_probe(struct platform_device *pdev)
+{
+ int rc;
+
+ DBG("%s probe called\n", __func__);
+ if (bam_mux_initialized)
+ return 0;
+
+ bam_mux_rx_workqueue = create_singlethread_workqueue("bam_dmux_rx");
+ if (!bam_mux_rx_workqueue)
+ return -ENOMEM;
+
+ bam_mux_tx_workqueue = create_singlethread_workqueue("bam_dmux_tx");
+ if (!bam_mux_tx_workqueue) {
+ destroy_workqueue(bam_mux_rx_workqueue);
+ return -ENOMEM;
+ }
+
+ for (rc = 0; rc < BAM_DMUX_NUM_CHANNELS; ++rc)
+ spin_lock_init(&bam_ch[rc].lock);
+
+ /* switch over to A2 power status mechanism when avaliable */
+ INIT_DELAYED_WORK(&bam_init_work, bam_init);
+ schedule_delayed_work(&bam_init_work, msecs_to_jiffies(40000));
+
+ return 0;
+}
+
+static struct platform_driver bam_dmux_driver = {
+ .probe = bam_dmux_probe,
+ .driver = {
+ .name = "BAM_RMNT",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init bam_dmux_init(void)
+{
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dent;
+
+ dent = debugfs_create_dir("bam_dmux", 0);
+ if (!IS_ERR(dent))
+ debug_create("tbl", 0444, dent, debug_tbl);
+#endif
+ return platform_driver_register(&bam_dmux_driver);
+}
+
+module_init(bam_dmux_init);
+MODULE_DESCRIPTION("MSM BAM DMUX");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
new file mode 100644
index 00000000000..42871536065
--- /dev/null
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+
+static struct single_row_lut fcc_temp = {
+ .x = {-30, -20, -10, 0, 10, 25, 40, 60},
+ .y = {1103, 1179, 1284, 1330, 1420, 1511, 1541, 1571},
+ .cols = 8,
+};
+
+static struct single_row_lut fcc_sf = {
+ .x = {100, 200, 300, 400, 500},
+ .y = {97, 93, 93, 90, 87},
+ .cols = 5,
+};
+
+static struct pc_sf_lut pc_sf = {
+ .rows = 10,
+ .cols = 5,
+ .cycles = {100, 200, 300, 400, 500},
+ .percent = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10},
+ .sf = {
+ {97, 93, 93, 90, 87},
+ {97, 93, 93, 90, 87},
+ {98, 94, 92, 89, 86},
+ {98, 94, 92, 89, 86},
+ {99, 94, 92, 88, 86},
+ {99, 95, 92, 88, 87},
+ {99, 95, 92, 88, 87},
+ {99, 95, 92, 88, 87},
+ {99, 95, 92, 88, 87},
+ {99, 95, 92, 88, 87}
+ },
+};
+
+static struct pc_temp_ocv_lut pc_temp_ocv = {
+ .rows = 29,
+ .cols = 8,
+ .temp = {-30, -20, -10, 0, 10, 25, 40, 60},
+ .percent = {100, 95, 90, 85, 80, 75, 70, 65, 60, 55,
+ 50, 45, 40, 35, 30, 25, 20, 15, 10, 9,
+ 8, 7, 6, 5, 4, 3, 2, 1, 0
+ },
+ .ocv = {
+ {3673, 3814, 3945, 4025, 4106, 4176, 4218, 4260},
+ {3613, 3751, 3880, 3959, 4038, 4107, 4149, 4190},
+ {3573, 3710, 3837, 3916, 3994, 4062, 4103, 4144},
+ {3534, 3670, 3796, 3873, 3951, 4019, 4059, 4099},
+ {3491, 3625, 3749, 3826, 3902, 3969, 4009, 4049},
+ {3464, 3597, 3721, 3796, 3872, 3939, 3978, 4018},
+ {3436, 3568, 3691, 3766, 3841, 3907, 3946, 3985},
+ {3407, 3537, 3659, 3733, 3808, 3873, 3912, 3951},
+ {3377, 3507, 3627, 3701, 3775, 3840, 3878, 3917},
+ {3355, 3484, 3604, 3677, 3751, 3815, 3853, 3891},
+ {3339, 3467, 3586, 3659, 3732, 3796, 3834, 3872},
+ {3324, 3452, 3570, 3643, 3716, 3780, 3818, 3855},
+ {3312, 3440, 3558, 3630, 3703, 3766, 3804, 3842},
+ {3303, 3430, 3548, 3620, 3692, 3756, 3793, 3831},
+ {3297, 3424, 3541, 3614, 3686, 3749, 3787, 3824},
+ {3288, 3414, 3531, 3603, 3675, 3738, 3776, 3813},
+ {3272, 3398, 3514, 3586, 3658, 3720, 3757, 3795},
+ {3240, 3365, 3480, 3551, 3622, 3684, 3721, 3758},
+ {3224, 3348, 3463, 3533, 3604, 3666, 3702, 3739},
+ {3221, 3344, 3459, 3530, 3600, 3662, 3695, 3728},
+ {3216, 3340, 3454, 3525, 3595, 3657, 3686, 3715},
+ {3212, 3335, 3449, 3520, 3590, 3652, 3677, 3703},
+ {3203, 3326, 3440, 3510, 3580, 3642, 3664, 3686},
+ {3185, 3307, 3420, 3490, 3560, 3621, 3639, 3657},
+ {3176, 3298, 3411, 3481, 3550, 3611, 3626, 3640},
+ {3151, 3272, 3384, 3453, 3522, 3583, 3593, 3604},
+ {3106, 3225, 3335, 3446, 3472, 3531, 3538, 3545},
+ {3021, 3217, 3245, 3417, 3429, 3435, 3439, 3442},
+ {3000, 3000, 3000, 3000, 3000, 3000, 3000, 3000}
+ },
+};
+
+struct pm8921_bms_battery_data palladium_1500_data = {
+ .fcc = 1500,
+ .fcc_temp_lut = &fcc_temp,
+ .fcc_sf_lut = &fcc_sf,
+ .pc_temp_ocv_lut = &pc_temp_ocv,
+ .pc_sf_lut = &pc_sf,
+};
diff --git a/arch/arm/mach-msm/board-apq8064.c b/arch/arm/mach-msm/board-apq8064.c
new file mode 100644
index 00000000000..4a21203ee6b
--- /dev/null
+++ b/arch/arm/mach-msm/board-apq8064.c
@@ -0,0 +1,101 @@
+/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include "timer.h"
+#include "devices.h"
+
+static void __init apq8064_map_io(void)
+{
+ msm_map_apq8064_io();
+}
+
+static void __init apq8064_init_irq(void)
+{
+ unsigned int i;
+ gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+ (void *)MSM_QGIC_CPU_BASE);
+
+ /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+ writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+ writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
+ mb();
+
+ /*
+ * FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
+ * as they are configured as level, which does not play nice with
+ * handle_percpu_irq.
+ */
+ for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
+ if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
+ irq_set_handler(i, handle_percpu_irq);
+ }
+}
+
+static struct platform_device *common_devices[] __initdata = {
+ &apq8064_device_uart_gsbi3
+};
+
+static struct msm_otg_platform_data msm_otg_pdata = {
+ .mode = USB_PERIPHERAL,
+ .otg_control = OTG_PHY_CONTROL,
+ .phy_type = SNPS_28NM_INTEGRATED_PHY,
+ .pclk_src_name = "dfab_usb_hs_clk",
+};
+
+static struct msm_ssbi_platform_data apq8064_ssbi_pm8921_pdata __devinitdata = {
+ .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
+ .slave = {
+ .name = "pm8921-core",
+ },
+};
+
+static struct msm_ssbi_platform_data apq8064_ssbi_pm8821_pdata __devinitdata = {
+ .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
+ .slave = {
+ .name = "pm8821-core",
+ },
+};
+
+static void __init apq8064_common_init(void)
+{
+ if (socinfo_init() < 0)
+ pr_err("socinfo_init() failed!\n");
+ msm_clock_init(msm_clocks_8064_dummy, msm_num_clocks_8064_dummy);
+ platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+}
+
+static void __init apq8064_sim_init(void)
+{
+ apq8064_common_init();
+}
+
+MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
+ .map_io = apq8064_map_io,
+ .init_irq = apq8064_init_irq,
+ .timer = &msm_timer,
+ .init_machine = apq8064_sim_init,
+MACHINE_END
+
diff --git a/arch/arm/mach-msm/board-fsm9xxx.c b/arch/arm/mach-msm/board-fsm9xxx.c
new file mode 100644
index 00000000000..3fbd97e7310
--- /dev/null
+++ b/arch/arm/mach-msm/board-fsm9xxx.c
@@ -0,0 +1,854 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include "devices.h"
+#include "timer.h"
+#include "pm.h"
+#include "spm.h"
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define PMIC_GPIO_INT 144
+#define PMIC_VREG_WLAN_LEVEL 2900
+#define PMIC_GPIO_SD_DET 165
+
+#define GPIO_EPHY_RST_N 37
+
+#define GPIO_GRFC_FTR0_0 136 /* GRFC 20 */
+#define GPIO_GRFC_FTR0_1 137 /* GRFC 21 */
+#define GPIO_GRFC_FTR1_0 145 /* GRFC 22 */
+#define GPIO_GRFC_FTR1_1 93 /* GRFC 19 */
+#define GPIO_GRFC_2 110
+#define GPIO_GRFC_3 109
+#define GPIO_GRFC_4 108
+#define GPIO_GRFC_5 107
+#define GPIO_GRFC_6 106
+#define GPIO_GRFC_7 105
+#define GPIO_GRFC_8 104
+#define GPIO_GRFC_9 103
+#define GPIO_GRFC_10 102
+#define GPIO_GRFC_11 101
+#define GPIO_GRFC_13 99
+#define GPIO_GRFC_14 98
+#define GPIO_GRFC_15 97
+#define GPIO_GRFC_16 96
+#define GPIO_GRFC_17 95
+#define GPIO_GRFC_18 94
+#define GPIO_GRFC_24 150
+#define GPIO_GRFC_25 151
+#define GPIO_GRFC_26 152
+#define GPIO_GRFC_27 153
+#define GPIO_GRFC_28 154
+#define GPIO_GRFC_29 155
+
+#define FPGA_SDCC_STATUS 0x8E0001A8
+
+/* Macros assume PMIC GPIOs start at 0 */
+#define PM8058_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio + NR_MSM_GPIOS)
+#define PM8058_GPIO_SYS_TO_PM(sys_gpio) (sys_gpio - NR_MSM_GPIOS)
+
+#define PMIC_GPIO_5V_PA_PWR 21 /* PMIC GPIO Number 22 */
+#define PMIC_GPIO_4_2V_PA_PWR 22 /* PMIC GPIO Number 23 */
+#define PMIC_MPP_3 2 /* PMIC MPP Number 3 */
+#define PMIC_MPP_6 5 /* PMIC MPP Number 6 */
+#define PMIC_MPP_7 6 /* PMIC MPP Number 7 */
+#define PMIC_MPP_10 9 /* PMIC MPP Number 10 */
+
+/*
+ * PM8058
+ */
+
+static int pm8058_gpios_init(void)
+{
+ int i;
+ int rc;
+ struct pm8058_gpio_cfg {
+ int gpio;
+ struct pm8058_gpio cfg;
+ };
+
+ struct pm8058_gpio_cfg gpio_cfgs[] = {
+ { /* 5V PA Power */
+ PMIC_GPIO_5V_PA_PWR,
+ {
+ .vin_sel = 0,
+ .direction = PM_GPIO_DIR_BOTH,
+ .output_value = 1,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .pull = PM_GPIO_PULL_DN,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ },
+ },
+ { /* 4.2V PA Power */
+ PMIC_GPIO_4_2V_PA_PWR,
+ {
+ .vin_sel = 0,
+ .direction = PM_GPIO_DIR_BOTH,
+ .output_value = 1,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .pull = PM_GPIO_PULL_DN,
+ .out_strength = PM_GPIO_STRENGTH_HIGH,
+ .function = PM_GPIO_FUNC_NORMAL,
+ .inv_int_pol = 0,
+ },
+ },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(gpio_cfgs); ++i) {
+ rc = pm8058_gpio_config(gpio_cfgs[i].gpio, &gpio_cfgs[i].cfg);
+ if (rc < 0) {
+ pr_err("%s pmic gpio config failed\n", __func__);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+static int pm8058_mpps_init(void)
+{
+ int rc;
+
+ /* Set up MPP 3 and 6 as analog outputs at 1.25V */
+ rc = pm8058_mpp_config_analog_output(PMIC_MPP_3,
+ PM_MPP_AOUT_LVL_1V25_2, PM_MPP_AOUT_CTL_ENABLE);
+ if (rc) {
+ pr_err("%s: Config mpp3 on pmic 8058 failed\n", __func__);
+ return rc;
+ }
+
+ rc = pm8058_mpp_config_analog_output(PMIC_MPP_6,
+ PM_MPP_AOUT_LVL_1V25_2, PM_MPP_AOUT_CTL_ENABLE);
+ if (rc) {
+ pr_err("%s: Config mpp5 on pmic 8058 failed\n", __func__);
+ return rc;
+ }
+ return 0;
+}
+
+static struct pm8058_gpio_platform_data pm8058_gpio_data = {
+ .gpio_base = PM8058_GPIO_PM_TO_SYS(0),
+ .irq_base = PM8058_GPIO_IRQ(PMIC8058_IRQ_BASE, 0),
+ .init = pm8058_gpios_init,
+};
+
+static struct pm8058_gpio_platform_data pm8058_mpp_data = {
+ .gpio_base = PM8058_GPIO_PM_TO_SYS(PM8058_GPIOS),
+ .irq_base = PM8058_MPP_IRQ(PMIC8058_IRQ_BASE, 0),
+ .init = pm8058_mpps_init,
+};
+
+static struct regulator_consumer_supply pm8058_vreg_supply[PM8058_VREG_MAX] = {
+ [PM8058_VREG_ID_L3] = REGULATOR_SUPPLY("8058_l3", NULL),
+ [PM8058_VREG_ID_L8] = REGULATOR_SUPPLY("8058_l8", NULL),
+ [PM8058_VREG_ID_L9] = REGULATOR_SUPPLY("8058_l9", NULL),
+ [PM8058_VREG_ID_L14] = REGULATOR_SUPPLY("8058_l14", NULL),
+ [PM8058_VREG_ID_L15] = REGULATOR_SUPPLY("8058_l15", NULL),
+ [PM8058_VREG_ID_L18] = REGULATOR_SUPPLY("8058_l18", NULL),
+ [PM8058_VREG_ID_S4] = REGULATOR_SUPPLY("8058_s4", NULL),
+
+ [PM8058_VREG_ID_LVS0] = REGULATOR_SUPPLY("8058_lvs0", NULL),
+};
+
+#define PM8058_VREG_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, \
+ _always_on, _pull_down) \
+ [_id] = { \
+ .init_data = { \
+ .constraints = { \
+ .valid_modes_mask = _modes, \
+ .valid_ops_mask = _ops, \
+ .min_uV = _min_uV, \
+ .max_uV = _max_uV, \
+ .apply_uV = _apply_uV, \
+ .always_on = _always_on, \
+ }, \
+ .num_consumer_supplies = 1, \
+ .consumer_supplies = &pm8058_vreg_supply[_id], \
+ }, \
+ .pull_down_enable = _pull_down, \
+ .pin_ctrl = 0, \
+ .pin_fn = PM8058_VREG_PIN_FN_ENABLE, \
+ }
+
+#define PM8058_VREG_INIT_LDO(_id, _min_uV, _max_uV) \
+ PM8058_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL | \
+ REGULATOR_MODE_IDLE | REGULATOR_MODE_STANDBY, \
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS | \
+ REGULATOR_CHANGE_MODE, 1, 1, 1)
+
+#define PM8058_VREG_INIT_SMPS(_id, _min_uV, _max_uV) \
+ PM8058_VREG_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL | \
+ REGULATOR_MODE_IDLE | REGULATOR_MODE_STANDBY, \
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS | \
+ REGULATOR_CHANGE_MODE, 1, 1, 1)
+
+#define PM8058_VREG_INIT_LVS(_id, _min_uV, _max_uV) \
+ PM8058_VREG_INIT(_id, _min_uV, _min_uV, REGULATOR_MODE_NORMAL, \
+ REGULATOR_CHANGE_STATUS, 0, 0, 1)
+
+static struct pm8058_vreg_pdata pm8058_vreg_init[PM8058_VREG_MAX] = {
+ PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L3, 1800000, 1800000),
+ PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L8, 2200000, 2200000),
+ PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L9, 2050000, 2050000),
+ PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L14, 2850000, 2850000),
+ PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L15, 2200000, 2200000),
+ PM8058_VREG_INIT_LDO(PM8058_VREG_ID_L18, 2200000, 2200000),
+ PM8058_VREG_INIT_LVS(PM8058_VREG_ID_LVS0, 1800000, 1800000),
+ PM8058_VREG_INIT_SMPS(PM8058_VREG_ID_S4, 1300000, 1300000),
+};
+
+#define PM8058_VREG(_id) { \
+ .name = "pm8058-regulator", \
+ .id = _id, \
+ .platform_data = &pm8058_vreg_init[_id], \
+}
+
+#ifdef CONFIG_SENSORS_MSM_ADC
+static struct resource resources_adc[] = {
+ {
+ .start = PM8058_ADC_IRQ(PMIC8058_IRQ_BASE),
+ .end = PM8058_ADC_IRQ(PMIC8058_IRQ_BASE),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct adc_access_fn xoadc_fn = {
+ pm8058_xoadc_select_chan_and_start_conv,
+ pm8058_xoadc_read_adc_code,
+ pm8058_xoadc_get_properties,
+ pm8058_xoadc_slot_request,
+ pm8058_xoadc_restore_slot,
+ pm8058_xoadc_calibrate,
+};
+
+static struct msm_adc_channels msm_adc_channels_data[] = {
+ {"pmic_therm", CHANNEL_ADC_DIE_TEMP, 0, &xoadc_fn, CHAN_PATH_TYPE12,
+ ADC_CONFIG_TYPE2, ADC_CALIB_CONFIG_TYPE1, scale_pmic_therm},
+ {"ref_1250mv", CHANNEL_ADC_1250_REF, 0, &xoadc_fn, CHAN_PATH_TYPE13,
+ ADC_CONFIG_TYPE2, ADC_CALIB_CONFIG_TYPE2, scale_default},
+ {"xo_therm", CHANNEL_ADC_XOTHERM, 0, &xoadc_fn, CHAN_PATH_TYPE_NONE,
+ ADC_CONFIG_TYPE2, ADC_CALIB_CONFIG_TYPE5, tdkntcgtherm},
+ {"fsm_therm", CHANNEL_ADC_FSM_THERM, 0, &xoadc_fn, CHAN_PATH_TYPE6,
+ ADC_CONFIG_TYPE2, ADC_CALIB_CONFIG_TYPE5, tdkntcgtherm},
+ {"pa_therm", CHANNEL_ADC_PA_THERM, 0, &xoadc_fn, CHAN_PATH_TYPE7,
+ ADC_CONFIG_TYPE2, ADC_CALIB_CONFIG_TYPE5, tdkntcgtherm},
+};
+
+static struct msm_adc_platform_data msm_adc_pdata = {
+ .channel = msm_adc_channels_data,
+ .num_chan_supported = ARRAY_SIZE(msm_adc_channels_data),
+ .target_hw = FSM_9xxx,
+};
+
+static struct platform_device msm_adc_device = {
+ .name = "msm_adc",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_adc_pdata,
+ },
+};
+
+static void pmic8058_xoadc_mpp_config(void)
+{
+ int rc;
+
+ rc = pm8058_mpp_config_analog_input(XOADC_MPP_7,
+ PM_MPP_AIN_AMUX_CH5, PM_MPP_AOUT_CTL_DISABLE);
+ if (rc)
+ pr_err("%s: Config mpp7 on pmic 8058 failed\n", __func__);
+
+ rc = pm8058_mpp_config_analog_input(XOADC_MPP_10,
+ PM_MPP_AIN_AMUX_CH6, PM_MPP_AOUT_CTL_DISABLE);
+ if (rc)
+ pr_err("%s: Config mpp10 on pmic 8058 failed\n", __func__);
+}
+
+static struct regulator *vreg_ldo18_adc;
+
+static int pmic8058_xoadc_vreg_config(int on)
+{
+ int rc;
+
+ if (on) {
+ rc = regulator_enable(vreg_ldo18_adc);
+ if (rc)
+ pr_err("%s: Enable of regulator ldo18_adc "
+ "failed\n", __func__);
+ } else {
+ rc = regulator_disable(vreg_ldo18_adc);
+ if (rc)
+ pr_err("%s: Disable of regulator ldo18_adc "
+ "failed\n", __func__);
+ }
+
+ return rc;
+}
+
+static int pmic8058_xoadc_vreg_setup(void)
+{
+ int rc;
+
+ vreg_ldo18_adc = regulator_get(NULL, "8058_l18");
+ if (IS_ERR(vreg_ldo18_adc)) {
+ pr_err("%s: vreg get failed (%ld)\n",
+ __func__, PTR_ERR(vreg_ldo18_adc));
+ rc = PTR_ERR(vreg_ldo18_adc);
+ goto fail;
+ }
+
+ rc = regulator_set_voltage(vreg_ldo18_adc, 2200000, 2200000);
+ if (rc) {
+ pr_err("%s: unable to set ldo18 voltage to 2.2V\n", __func__);
+ goto fail;
+ }
+
+ return rc;
+fail:
+ regulator_put(vreg_ldo18_adc);
+ return rc;
+}
+
+static void pmic8058_xoadc_vreg_shutdown(void)
+{
+ regulator_put(vreg_ldo18_adc);
+}
+
+/* usec. For this ADC,
+ * this time represents clk rate @ txco w/ 1024 decimation ratio.
+ * Each channel has different configuration, thus at the time of starting
+ * the conversion, xoadc will return actual conversion time
+ * */
+static struct adc_properties pm8058_xoadc_data = {
+ .adc_reference = 2200, /* milli-voltage for this adc */
+ .bitresolution = 15,
+ .bipolar = 0,
+ .conversiontime = 54,
+};
+
+static struct xoadc_platform_data xoadc_pdata = {
+ .xoadc_prop = &pm8058_xoadc_data,
+ .xoadc_mpp_config = pmic8058_xoadc_mpp_config,
+ .xoadc_vreg_set = pmic8058_xoadc_vreg_config,
+ .xoadc_num = XOADC_PMIC_0,
+ .xoadc_vreg_setup = pmic8058_xoadc_vreg_setup,
+ .xoadc_vreg_shutdown = pmic8058_xoadc_vreg_shutdown,
+};
+#endif
+
+/* Put sub devices with fixed location first in sub_devices array */
+static struct mfd_cell pm8058_subdevs[] = {
+ { .name = "pm8058-mpp",
+ .platform_data = &pm8058_mpp_data,
+ .pdata_size = sizeof(pm8058_mpp_data),
+ },
+ {
+ .name = "pm8058-gpio",
+ .id = -1,
+ .platform_data = &pm8058_gpio_data,
+ .pdata_size = sizeof(pm8058_gpio_data),
+ },
+#ifdef CONFIG_SENSORS_MSM_ADC
+ {
+ .name = "pm8058-xoadc",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(resources_adc),
+ .resources = resources_adc,
+ .platform_data = &xoadc_pdata,
+ .pdata_size =sizeof(xoadc_pdata),
+ },
+#endif
+ PM8058_VREG(PM8058_VREG_ID_L3),
+ PM8058_VREG(PM8058_VREG_ID_L8),
+ PM8058_VREG(PM8058_VREG_ID_L9),
+ PM8058_VREG(PM8058_VREG_ID_L14),
+ PM8058_VREG(PM8058_VREG_ID_L15),
+ PM8058_VREG(PM8058_VREG_ID_L18),
+ PM8058_VREG(PM8058_VREG_ID_S4),
+ PM8058_VREG(PM8058_VREG_ID_LVS0),
+ PM8058_XO(PM8058_XO_ID_A0),
+ PM8058_XO(PM8058_XO_ID_A1),
+};
+
+static struct pm8058_platform_data pm8058_fsm9xxx_data = {
+ .irq_base = PMIC8058_IRQ_BASE,
+
+ .num_subdevs = ARRAY_SIZE(pm8058_subdevs),
+ .sub_devices = pm8058_subdevs,
+};
+
+static struct i2c_board_info pm8058_boardinfo[] __initdata = {
+ {
+ I2C_BOARD_INFO("pm8058-core", 0x55),
+ .irq = MSM_GPIO_TO_INT(47),
+ .platform_data = &pm8058_fsm9xxx_data,
+ },
+};
+
+static int __init buses_init(void)
+{
+ if (gpio_tlmm_config(GPIO_CFG(PMIC_GPIO_INT, 5, GPIO_CFG_INPUT,
+ GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE))
+ pr_err("%s: gpio_tlmm_config (gpio=%d) failed\n",
+ __func__, PMIC_GPIO_INT);
+
+ i2c_register_board_info(0 /* I2C_SSBI ID */, pm8058_boardinfo,
+ ARRAY_SIZE(pm8058_boardinfo));
+
+ return 0;
+}
+
+/*
+ * EPHY
+ */
+
+static struct msm_gpio phy_config_data[] = {
+ { GPIO_CFG(GPIO_EPHY_RST_N, 0, GPIO_CFG_OUTPUT,
+ GPIO_CFG_NO_PULL, GPIO_CFG_2MA), "MAC_RST_N" },
+};
+
+static int __init phy_init(void)
+{
+ msm_gpios_request_enable(phy_config_data, ARRAY_SIZE(phy_config_data));
+ gpio_direction_output(GPIO_EPHY_RST_N, 0);
+ udelay(100);
+ gpio_set_value(GPIO_EPHY_RST_N, 1);
+
+ return 0;
+}
+
+/*
+ * RF
+ */
+
+static struct msm_gpio grfc_config_data[] = {
+ { GPIO_CFG(GPIO_GRFC_FTR0_0, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "HH_RFMODE1_0" },
+ { GPIO_CFG(GPIO_GRFC_FTR0_1, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "HH_RFMODE1_1" },
+ { GPIO_CFG(GPIO_GRFC_FTR1_0, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "HH_RFMODE2_0" },
+ { GPIO_CFG(GPIO_GRFC_FTR1_1, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "HH_RFMODE2_1" },
+ { GPIO_CFG(GPIO_GRFC_2, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_2" },
+ { GPIO_CFG(GPIO_GRFC_3, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_3" },
+ { GPIO_CFG(GPIO_GRFC_4, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_4" },
+ { GPIO_CFG(GPIO_GRFC_5, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_5" },
+ { GPIO_CFG(GPIO_GRFC_6, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_6" },
+ { GPIO_CFG(GPIO_GRFC_7, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_7" },
+ { GPIO_CFG(GPIO_GRFC_8, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_8" },
+ { GPIO_CFG(GPIO_GRFC_9, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_9" },
+ { GPIO_CFG(GPIO_GRFC_10, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_10" },
+ { GPIO_CFG(GPIO_GRFC_11, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_11" },
+ { GPIO_CFG(GPIO_GRFC_13, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_13" },
+ { GPIO_CFG(GPIO_GRFC_14, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_14" },
+ { GPIO_CFG(GPIO_GRFC_15, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_15" },
+ { GPIO_CFG(GPIO_GRFC_16, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_16" },
+ { GPIO_CFG(GPIO_GRFC_17, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_17" },
+ { GPIO_CFG(GPIO_GRFC_18, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_18" },
+ { GPIO_CFG(GPIO_GRFC_24, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_24" },
+ { GPIO_CFG(GPIO_GRFC_25, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_25" },
+ { GPIO_CFG(GPIO_GRFC_26, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_26" },
+ { GPIO_CFG(GPIO_GRFC_27, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_27" },
+ { GPIO_CFG(GPIO_GRFC_28, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_28" },
+ { GPIO_CFG(GPIO_GRFC_29, 7, GPIO_CFG_OUTPUT,
+ GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA), "GPIO_GRFC_29" },
+ { GPIO_CFG(39, 1, GPIO_CFG_OUTPUT,
+ GPIO_CFG_NO_PULL, GPIO_CFG_2MA), "PP2S_EXT_SYNC" },
+};
+
+static int __init grfc_init(void)
+{
+ msm_gpios_request_enable(grfc_config_data,
+ ARRAY_SIZE(grfc_config_data));
+
+ return 0;
+}
+
+/*
+ * UART
+ */
+
+#ifdef CONFIG_SERIAL_MSM_CONSOLE
+static struct msm_gpio uart1_config_data[] = {
+ { GPIO_CFG(138, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ "UART1_Rx" },
+ { GPIO_CFG(139, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ "UART1_Tx" },
+};
+
+static void fsm9xxx_init_uart1(void)
+{
+ msm_gpios_request_enable(uart1_config_data,
+ ARRAY_SIZE(uart1_config_data));
+
+}
+#endif
+
+/*
+ * SSBI
+ */
+
+#ifdef CONFIG_I2C_SSBI
+static struct msm_i2c_ssbi_platform_data msm_i2c_ssbi1_pdata = {
+ .controller_type = FSM_SBI_CTRL_SSBI,
+};
+
+static struct msm_i2c_ssbi_platform_data msm_i2c_ssbi2_pdata = {
+ .controller_type = FSM_SBI_CTRL_SSBI,
+};
+
+static struct msm_i2c_ssbi_platform_data msm_i2c_ssbi3_pdata = {
+ .controller_type = FSM_SBI_CTRL_SSBI,
+};
+
+/* Intialize GPIO configuration for SSBI */
+static struct msm_gpio ssbi_gpio_config_data[] = {
+ { GPIO_CFG(140, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA),
+ "SSBI_1" },
+ { GPIO_CFG(141, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA),
+ "SSBI_2" },
+ { GPIO_CFG(92, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_4MA),
+ "SSBI_3" },
+};
+
+static void
+fsm9xxx_init_ssbi_gpio(void)
+{
+ msm_gpios_request_enable(ssbi_gpio_config_data,
+ ARRAY_SIZE(ssbi_gpio_config_data));
+
+}
+#endif
+
+/*
+ * Crypto
+ */
+
+#define QCE_SIZE 0x10000
+
+#define QCE_0_BASE 0x80C00000
+#define QCE_1_BASE 0x80E00000
+#define QCE_2_BASE 0x81000000
+
+#define QCE_NO_HW_KEY_SUPPORT 0 /* No shared HW key with external */
+#define QCE_NO_SHARE_CE_RESOURCE 0 /* No CE resource shared with TZ */
+#define QCE_NO_CE_SHARED 0 /* CE not shared with TZ */
+#define QCE_NO_SHA_HMAC_SUPPORT 0 /* No SHA-HMAC by SHA operation */
+
+static struct resource qcrypto_resources[] = {
+ [0] = {
+ .start = QCE_0_BASE,
+ .end = QCE_0_BASE + QCE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "crypto_channels",
+ .start = DMOV_CE1_IN_CHAN,
+ .end = DMOV_CE1_OUT_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .name = "crypto_crci_in",
+ .start = DMOV_CE1_IN_CRCI,
+ .end = DMOV_CE1_IN_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .name = "crypto_crci_out",
+ .start = DMOV_CE1_OUT_CRCI,
+ .end = DMOV_CE1_OUT_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [4] = {
+ .name = "crypto_crci_hash",
+ .start = DMOV_CE1_HASH_CRCI,
+ .end = DMOV_CE1_HASH_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct msm_ce_hw_support qcrypto_ce_hw_suppport = {
+ .ce_shared = QCE_NO_CE_SHARED,
+ .shared_ce_resource = QCE_NO_SHARE_CE_RESOURCE,
+ .hw_key_support = QCE_NO_HW_KEY_SUPPORT,
+ .sha_hmac = QCE_NO_SHA_HMAC_SUPPORT,
+};
+
+struct platform_device qcrypto_device = {
+ .name = "qcrypto",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(qcrypto_resources),
+ .resource = qcrypto_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &qcrypto_ce_hw_suppport,
+ },
+};
+
+static struct resource qcedev_resources[] = {
+ [0] = {
+ .start = QCE_0_BASE,
+ .end = QCE_0_BASE + QCE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "crypto_channels",
+ .start = DMOV_CE1_IN_CHAN,
+ .end = DMOV_CE1_OUT_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .name = "crypto_crci_in",
+ .start = DMOV_CE1_IN_CRCI,
+ .end = DMOV_CE1_IN_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .name = "crypto_crci_out",
+ .start = DMOV_CE1_OUT_CRCI,
+ .end = DMOV_CE1_OUT_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [4] = {
+ .name = "crypto_crci_hash",
+ .start = DMOV_CE1_HASH_CRCI,
+ .end = DMOV_CE1_HASH_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+static struct msm_ce_hw_support qcedev_ce_hw_suppport = {
+ .ce_shared = QCE_NO_CE_SHARED,
+ .shared_ce_resource = QCE_NO_SHARE_CE_RESOURCE,
+ .hw_key_support = QCE_NO_HW_KEY_SUPPORT,
+ .sha_hmac = QCE_NO_SHA_HMAC_SUPPORT,
+};
+
+static struct platform_device qcedev_device = {
+ .name = "qce",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(qcedev_resources),
+ .resource = qcedev_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &qcedev_ce_hw_suppport,
+ },
+};
+
+static struct resource ota_qcrypto_resources[] = {
+ [0] = {
+ .start = QCE_1_BASE,
+ .end = QCE_1_BASE + QCE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "crypto_channels",
+ .start = DMOV_CE2_IN_CHAN,
+ .end = DMOV_CE2_OUT_CHAN,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .name = "crypto_crci_in",
+ .start = DMOV_CE2_IN_CRCI,
+ .end = DMOV_CE2_IN_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .name = "crypto_crci_out",
+ .start = DMOV_CE2_OUT_CRCI,
+ .end = DMOV_CE2_OUT_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+ [4] = {
+ .name = "crypto_crci_hash",
+ .start = DMOV_CE2_HASH_CRCI,
+ .end = DMOV_CE2_HASH_CRCI,
+ .flags = IORESOURCE_DMA,
+ },
+};
+
+struct platform_device ota_qcrypto_device = {
+ .name = "qcota",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(ota_qcrypto_resources),
+ .resource = ota_qcrypto_resources,
+ .dev = {
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+/*
+ * Devices
+ */
+
+static struct platform_device *devices[] __initdata = {
+ &msm_device_smd,
+ &msm_device_dmov,
+ &msm_device_nand,
+#ifdef CONFIG_I2C_SSBI
+ &msm_device_ssbi1,
+ &msm_device_ssbi2,
+ &msm_device_ssbi3,
+#endif
+#ifdef CONFIG_SENSORS_MSM_ADC
+ &msm_adc_device,
+#endif
+#ifdef CONFIG_I2C_QUP
+ &msm_gsbi1_qup_i2c_device,
+#endif
+#if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
+ &msm_device_uart1,
+#endif
+#if defined(CONFIG_QFP_FUSE)
+ &fsm_qfp_fuse_device,
+#endif
+ &qfec_device,
+ &qcrypto_device,
+ &qcedev_device,
+ &ota_qcrypto_device,
+};
+
+static struct msm_acpu_clock_platform_data fsm9xxx_clock_data = {
+ .acpu_switch_time_us = 50,
+ .vdd_switch_time_us = 62,
+};
+
+static void __init fsm9xxx_init_irq(void)
+{
+ msm_init_irq();
+ msm_init_sirc();
+}
+
+#ifdef CONFIG_MSM_SPM
+static struct msm_spm_platform_data msm_spm_data __initdata = {
+ .reg_base_addr = MSM_SAW_BASE,
+
+ .reg_init_values[MSM_SPM_REG_SAW_CFG] = 0x05,
+ .reg_init_values[MSM_SPM_REG_SAW_SPM_CTL] = 0x18,
+ .reg_init_values[MSM_SPM_REG_SAW_SPM_SLP_TMR_DLY] = 0x00006666,
+ .reg_init_values[MSM_SPM_REG_SAW_SPM_WAKE_TMR_DLY] = 0xFF000666,
+
+ .reg_init_values[MSM_SPM_REG_SAW_SPM_PMIC_CTL] = 0xE0F272,
+ .reg_init_values[MSM_SPM_REG_SAW_SLP_CLK_EN] = 0x01,
+ .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_PRECLMP_EN] = 0x03,
+ .reg_init_values[MSM_SPM_REG_SAW_SLP_HSFS_POSTCLMP_EN] = 0x00,
+
+ .reg_init_values[MSM_SPM_REG_SAW_SLP_CLMP_EN] = 0x01,
+ .reg_init_values[MSM_SPM_REG_SAW_SLP_RST_EN] = 0x00,
+ .reg_init_values[MSM_SPM_REG_SAW_SPM_MPM_CFG] = 0x00,
+
+ .awake_vlevel = 0xF2,
+ .retention_vlevel = 0xE0,
+ .collapse_vlevel = 0x72,
+ .retention_mid_vlevel = 0xE0,
+ .collapse_mid_vlevel = 0xE0,
+};
+#endif
+
+static void __init fsm9xxx_init(void)
+{
+ if (socinfo_init() < 0)
+ pr_err("%s: socinfo_init() failed!\n",
+ __func__);
+
+ msm_acpu_clock_init(&fsm9xxx_clock_data);
+
+ regulator_has_full_constraints();
+
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+
+#ifdef CONFIG_MSM_SPM
+ msm_spm_init(&msm_spm_data, 1);
+#endif
+ buses_init();
+ phy_init();
+ grfc_init();
+
+#ifdef CONFIG_SERIAL_MSM_CONSOLE
+ fsm9xxx_init_uart1();
+#endif
+#ifdef CONFIG_I2C_SSBI
+ fsm9xxx_init_ssbi_gpio();
+ msm_device_ssbi1.dev.platform_data = &msm_i2c_ssbi1_pdata;
+ msm_device_ssbi2.dev.platform_data = &msm_i2c_ssbi2_pdata;
+ msm_device_ssbi3.dev.platform_data = &msm_i2c_ssbi3_pdata;
+#endif
+}
+
+static void __init fsm9xxx_map_io(void)
+{
+ msm_shared_ram_phys = 0x00100000;
+ msm_map_fsm9xxx_io();
+ msm_clock_init(msm_clocks_fsm9xxx, msm_num_clocks_fsm9xxx);
+}
+
+MACHINE_START(FSM9XXX_SURF, "QCT FSM9XXX")
+ .boot_params = PHYS_OFFSET + 0x100,
+ .map_io = fsm9xxx_map_io,
+ .init_irq = fsm9xxx_init_irq,
+ .init_machine = fsm9xxx_init,
+ .timer = &msm_timer,
+MACHINE_END
diff --git a/arch/arm/mach-msm/board-halibut-keypad.c b/arch/arm/mach-msm/board-halibut-keypad.c
new file mode 100644
index 00000000000..49c1075627d
--- /dev/null
+++ b/arch/arm/mach-msm/board-halibut-keypad.c
@@ -0,0 +1,177 @@
+/* linux/arch/arm/mach-msm/board-halibut-keypad.c
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include
+#include
+#include
+
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX "board_halibut."
+static int halibut_ffa;
+module_param_named(ffa, halibut_ffa, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define SCAN_FUNCTION_KEYS 0 /* don't turn this on without updating the ffa support */
+
+static unsigned int halibut_row_gpios[] = {
+ 31, 32, 33, 34, 35, 41
+#if SCAN_FUNCTION_KEYS
+ , 42
+#endif
+};
+
+static unsigned int halibut_col_gpios[] = { 36, 37, 38, 39, 40 };
+
+/* FFA:
+ 36: KEYSENSE_N(0)
+ 37: KEYSENSE_N(1)
+ 38: KEYSENSE_N(2)
+ 39: KEYSENSE_N(3)
+ 40: KEYSENSE_N(4)
+
+ 31: KYPD_17
+ 32: KYPD_15
+ 33: KYPD_13
+ 34: KYPD_11
+ 35: KYPD_9
+ 41: KYPD_MEMO
+*/
+
+#define KEYMAP_INDEX(row, col) ((row)*ARRAY_SIZE(halibut_col_gpios) + (col))
+
+static const unsigned short halibut_keymap[ARRAY_SIZE(halibut_col_gpios) * ARRAY_SIZE(halibut_row_gpios)] = {
+ [KEYMAP_INDEX(0, 0)] = KEY_5,
+ [KEYMAP_INDEX(0, 1)] = KEY_9,
+ [KEYMAP_INDEX(0, 2)] = 229, /* SOFT1 */
+ [KEYMAP_INDEX(0, 3)] = KEY_6,
+ [KEYMAP_INDEX(0, 4)] = KEY_LEFT,
+
+ [KEYMAP_INDEX(1, 0)] = KEY_0,
+ [KEYMAP_INDEX(1, 1)] = KEY_RIGHT,
+ [KEYMAP_INDEX(1, 2)] = KEY_1,
+ [KEYMAP_INDEX(1, 3)] = 228, /* KEY_SHARP */
+ [KEYMAP_INDEX(1, 4)] = KEY_SEND,
+
+ [KEYMAP_INDEX(2, 0)] = KEY_VOLUMEUP,
+ [KEYMAP_INDEX(2, 1)] = KEY_HOME, /* FA */
+ [KEYMAP_INDEX(2, 2)] = KEY_F8, /* QCHT */
+ [KEYMAP_INDEX(2, 3)] = KEY_F6, /* R+ */
+ [KEYMAP_INDEX(2, 4)] = KEY_F7, /* R- */
+
+ [KEYMAP_INDEX(3, 0)] = KEY_UP,
+ [KEYMAP_INDEX(3, 1)] = KEY_CLEAR,
+ [KEYMAP_INDEX(3, 2)] = KEY_4,
+ [KEYMAP_INDEX(3, 3)] = KEY_MUTE, /* SPKR */
+ [KEYMAP_INDEX(3, 4)] = KEY_2,
+
+ [KEYMAP_INDEX(4, 0)] = 230, /* SOFT2 */
+ [KEYMAP_INDEX(4, 1)] = 232, /* KEY_CENTER */
+ [KEYMAP_INDEX(4, 2)] = KEY_DOWN,
+ [KEYMAP_INDEX(4, 3)] = KEY_BACK, /* FB */
+ [KEYMAP_INDEX(4, 4)] = KEY_8,
+
+ [KEYMAP_INDEX(5, 0)] = KEY_VOLUMEDOWN,
+ [KEYMAP_INDEX(5, 1)] = 227, /* KEY_STAR */
+ [KEYMAP_INDEX(5, 2)] = KEY_MAIL, /* MESG */
+ [KEYMAP_INDEX(5, 3)] = KEY_3,
+ [KEYMAP_INDEX(5, 4)] = KEY_7,
+
+#if SCAN_FUNCTION_KEYS
+ [KEYMAP_INDEX(6, 0)] = KEY_F5,
+ [KEYMAP_INDEX(6, 1)] = KEY_F4,
+ [KEYMAP_INDEX(6, 2)] = KEY_F3,
+ [KEYMAP_INDEX(6, 3)] = KEY_F2,
+ [KEYMAP_INDEX(6, 4)] = KEY_F1
+#endif
+};
+
+static const unsigned short halibut_keymap_ffa[ARRAY_SIZE(halibut_col_gpios) * ARRAY_SIZE(halibut_row_gpios)] = {
+ /*[KEYMAP_INDEX(0, 0)] = ,*/
+ /*[KEYMAP_INDEX(0, 1)] = ,*/
+ [KEYMAP_INDEX(0, 2)] = KEY_1,
+ [KEYMAP_INDEX(0, 3)] = KEY_SEND,
+ [KEYMAP_INDEX(0, 4)] = KEY_LEFT,
+
+ [KEYMAP_INDEX(1, 0)] = KEY_3,
+ [KEYMAP_INDEX(1, 1)] = KEY_RIGHT,
+ [KEYMAP_INDEX(1, 2)] = KEY_VOLUMEUP,
+ /*[KEYMAP_INDEX(1, 3)] = ,*/
+ [KEYMAP_INDEX(1, 4)] = KEY_6,
+
+ [KEYMAP_INDEX(2, 0)] = KEY_HOME, /* A */
+ [KEYMAP_INDEX(2, 1)] = KEY_BACK, /* B */
+ [KEYMAP_INDEX(2, 2)] = KEY_0,
+ [KEYMAP_INDEX(2, 3)] = 228, /* KEY_SHARP */
+ [KEYMAP_INDEX(2, 4)] = KEY_9,
+
+ [KEYMAP_INDEX(3, 0)] = KEY_UP,
+ [KEYMAP_INDEX(3, 1)] = 232, /* KEY_CENTER */ /* i */
+ [KEYMAP_INDEX(3, 2)] = KEY_4,
+ /*[KEYMAP_INDEX(3, 3)] = ,*/
+ [KEYMAP_INDEX(3, 4)] = KEY_2,
+
+ [KEYMAP_INDEX(4, 0)] = KEY_VOLUMEDOWN,
+ [KEYMAP_INDEX(4, 1)] = KEY_SOUND,
+ [KEYMAP_INDEX(4, 2)] = KEY_DOWN,
+ [KEYMAP_INDEX(4, 3)] = KEY_8,
+ [KEYMAP_INDEX(4, 4)] = KEY_5,
+
+ /*[KEYMAP_INDEX(5, 0)] = ,*/
+ [KEYMAP_INDEX(5, 1)] = 227, /* KEY_STAR */
+ [KEYMAP_INDEX(5, 2)] = 230, /*SOFT2*/ /* 2 */
+ [KEYMAP_INDEX(5, 3)] = KEY_MENU, /* 1 */
+ [KEYMAP_INDEX(5, 4)] = KEY_7,
+};
+
+static struct gpio_event_matrix_info halibut_matrix_info = {
+ .info.func = gpio_event_matrix_func,
+ .keymap = halibut_keymap,
+ .output_gpios = halibut_row_gpios,
+ .input_gpios = halibut_col_gpios,
+ .noutputs = ARRAY_SIZE(halibut_row_gpios),
+ .ninputs = ARRAY_SIZE(halibut_col_gpios),
+ .settle_time.tv.nsec = 0,
+ .poll_time.tv.nsec = 20 * NSEC_PER_MSEC,
+ .flags = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE | GPIOKPF_PRINT_UNMAPPED_KEYS /*| GPIOKPF_PRINT_MAPPED_KEYS*/
+};
+
+struct gpio_event_info *halibut_keypad_info[] = {
+ &halibut_matrix_info.info
+};
+
+static struct gpio_event_platform_data halibut_keypad_data = {
+ .name = "halibut_keypad",
+ .info = halibut_keypad_info,
+ .info_count = ARRAY_SIZE(halibut_keypad_info)
+};
+
+static struct platform_device halibut_keypad_device = {
+ .name = GPIO_EVENT_DEV_NAME,
+ .id = -1,
+ .dev = {
+ .platform_data = &halibut_keypad_data,
+ },
+};
+
+static int __init halibut_init_keypad(void)
+{
+ if (!machine_is_halibut())
+ return 0;
+ if (halibut_ffa)
+ halibut_matrix_info.keymap = halibut_keymap_ffa;
+ return platform_device_register(&halibut_keypad_device);
+}
+
+device_initcall(halibut_init_keypad);
diff --git a/arch/arm/mach-msm/board-halibut-panel.c b/arch/arm/mach-msm/board-halibut-panel.c
new file mode 100644
index 00000000000..a498c65344b
--- /dev/null
+++ b/arch/arm/mach-msm/board-halibut-panel.c
@@ -0,0 +1,73 @@
+/* linux/arch/arm/mach-msm/board-halibut-mddi.c
+** Author: Brian Swetland
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include "proc_comm.h"
+#include "devices.h"
+#include "board-halibut.h"
+
+static void halibut_mddi_power_client(struct msm_mddi_client_data *mddi,
+ int on)
+{
+}
+
+static struct resource resources_msm_fb = {
+ .start = MSM_FB_BASE,
+ .end = MSM_FB_BASE + MSM_FB_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct msm_fb_data fb_data = {
+ .xres = 800,
+ .yres = 480,
+ .output_format = 0,
+};
+
+static struct msm_mddi_platform_data mddi_pdata = {
+ .clk_rate = 122880000,
+ .power_client = halibut_mddi_power_client,
+ .fb_resource = &resources_msm_fb,
+ .num_clients = 1,
+ .client_platform_data = {
+ {
+ .product_id = (0x4474 << 16 | 0xc065),
+ .name = "mddi_c_dummy",
+ .id = 0,
+ .client_data = &fb_data,
+ .clk_rate = 0,
+ },
+ },
+};
+
+int __init halibut_init_panel(void)
+{
+ int rc;
+
+ if (!machine_is_halibut())
+ return 0;
+
+ rc = platform_device_register(&msm_device_mdp);
+ if (rc)
+ return rc;
+
+ msm_device_mddi0.dev.platform_data = &mddi_pdata;
+ return platform_device_register(&msm_device_mddi0);
+}
+
+device_initcall(halibut_init_panel);
diff --git a/arch/arm/mach-msm/board-halibut.h b/arch/arm/mach-msm/board-halibut.h
new file mode 100644
index 00000000000..edcdacb34c2
--- /dev/null
+++ b/arch/arm/mach-msm/board-halibut.h
@@ -0,0 +1,20 @@
+/* linux/arch/arm/mach-msm/board-trout.h
+ * ** Author: Brian Swetland
+ * */
+#ifndef __ARCH_ARM_MACH_MSM_BOARD_HALIBUT_H
+#define __ARCH_ARM_MACH_MSM_BOARD_HALIBUT_H
+
+#define MSM_PMEM_GPU0_BASE (0x10000000 + 64*SZ_1M)
+#define MSM_PMEM_GPU0_SIZE 0x800000
+#define MSM_PMEM_MDP_BASE (MSM_PMEM_GPU0_BASE + MSM_PMEM_GPU0_SIZE)
+#define MSM_PMEM_MDP_SIZE 0x800000
+#define MSM_PMEM_ADSP_BASE (MSM_PMEM_MDP_BASE + MSM_PMEM_MDP_SIZE)
+#define MSM_PMEM_ADSP_SIZE 0x800000
+#define MSM_PMEM_GPU1_BASE (MSM_PMEM_ADSP_BASE + MSM_PMEM_ADSP_SIZE)
+#define MSM_PMEM_GPU1_SIZE 0x800000
+#define MSM_FB_BASE (MSM_PMEM_GPU1_BASE + MSM_PMEM_GPU1_SIZE)
+#define MSM_FB_SIZE 0x200000
+#define MSM_PMEM_CAMERA_BASE (MSM_FB_BASE + MSM_FB_SIZE)
+#define MSM_PMEM_CAMERA_SIZE 0xA00000
+
+#endif
diff --git a/arch/arm/mach-msm/board-mahimahi-audio.c b/arch/arm/mach-msm/board-mahimahi-audio.c
new file mode 100644
index 00000000000..074d84e4d13
--- /dev/null
+++ b/arch/arm/mach-msm/board-mahimahi-audio.c
@@ -0,0 +1,283 @@
+/* arch/arm/mach-msm/board-mahimahi-audio.c
+ *
+ * Copyright (C) 2009 HTC Corporation
+ * Copyright (C) 2009 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.
+ *
+ */
+
+#include
+#include
+#include
+#include
+
+#include "board-mahimahi.h"
+#include "proc_comm.h"
+#include "pmic.h"
+#include "board-mahimahi-tpa2018d1.h"
+
+#if 0
+#define D(fmt, args...) printk(KERN_INFO "Audio: "fmt, ##args)
+#else
+#define D(fmt, args...) do {} while (0)
+#endif
+
+static struct mutex mic_lock;
+static struct mutex bt_sco_lock;
+
+static struct q6_hw_info q6_audio_hw[Q6_HW_COUNT] = {
+ [Q6_HW_HANDSET] = {
+ .min_gain = -2000,
+ .max_gain = 0,
+ },
+ [Q6_HW_HEADSET] = {
+ .min_gain = -2000,
+ .max_gain = 0,
+ },
+ [Q6_HW_SPEAKER] = {
+ .min_gain = -1500,
+ .max_gain = 0,
+ },
+ [Q6_HW_TTY] = {
+ .min_gain = -2000,
+ .max_gain = 0,
+ },
+ [Q6_HW_BT_SCO] = {
+ .min_gain = -2000,
+ .max_gain = 0,
+ },
+ [Q6_HW_BT_A2DP] = {
+ .min_gain = -2000,
+ .max_gain = 0,
+ },
+};
+
+void mahimahi_headset_enable(int en)
+{
+ D("%s %d\n", __func__, en);
+ /* enable audio amp */
+ if (en) mdelay(15);
+ gpio_set_value(MAHIMAHI_AUD_JACKHP_EN, !!en);
+}
+
+void mahimahi_speaker_enable(int en)
+{
+ struct spkr_config_mode scm;
+ memset(&scm, 0, sizeof(scm));
+
+ D("%s %d\n", __func__, en);
+ if (en) {
+ scm.is_right_chan_en = 0;
+ scm.is_left_chan_en = 1;
+ scm.is_stereo_en = 0;
+ scm.is_hpf_en = 1;
+ pmic_spkr_en_mute(LEFT_SPKR, 0);
+ pmic_spkr_en_mute(RIGHT_SPKR, 0);
+ pmic_set_spkr_configuration(&scm);
+ pmic_spkr_en(LEFT_SPKR, 1);
+ pmic_spkr_en(RIGHT_SPKR, 0);
+
+ /* unmute */
+ pmic_spkr_en_mute(LEFT_SPKR, 1);
+ } else {
+ pmic_spkr_en_mute(LEFT_SPKR, 0);
+
+ pmic_spkr_en(LEFT_SPKR, 0);
+ pmic_spkr_en(RIGHT_SPKR, 0);
+
+ pmic_set_spkr_configuration(&scm);
+ }
+
+ if (is_cdma_version(system_rev))
+ tpa2018d1_set_speaker_amp(en);
+}
+
+void mahimahi_receiver_enable(int en)
+{
+ if (is_cdma_version(system_rev) &&
+ ((system_rev == 0xC1) || (system_rev == 0xC2))) {
+ struct spkr_config_mode scm;
+ memset(&scm, 0, sizeof(scm));
+
+ D("%s %d\n", __func__, en);
+ if (en) {
+ scm.is_right_chan_en = 1;
+ scm.is_left_chan_en = 0;
+ scm.is_stereo_en = 0;
+ scm.is_hpf_en = 1;
+ pmic_spkr_en_mute(RIGHT_SPKR, 0);
+ pmic_set_spkr_configuration(&scm);
+ pmic_spkr_en(RIGHT_SPKR, 1);
+
+ /* unmute */
+ pmic_spkr_en_mute(RIGHT_SPKR, 1);
+ } else {
+ pmic_spkr_en_mute(RIGHT_SPKR, 0);
+
+ pmic_spkr_en(RIGHT_SPKR, 0);
+
+ pmic_set_spkr_configuration(&scm);
+ }
+ }
+}
+
+static void config_gpio_table(uint32_t *table, int len)
+{
+ int n;
+ unsigned id;
+ for (n = 0; n < len; n++) {
+ id = table[n];
+ msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &id, 0);
+ }
+}
+
+static uint32_t bt_sco_enable[] = {
+ PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_OUT, 1, GPIO_OUTPUT,
+ GPIO_NO_PULL, GPIO_2MA),
+ PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_IN, 1, GPIO_INPUT,
+ GPIO_NO_PULL, GPIO_2MA),
+ PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_SYNC, 2, GPIO_INPUT,
+ GPIO_NO_PULL, GPIO_2MA),
+ PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_CLK, 2, GPIO_INPUT,
+ GPIO_NO_PULL, GPIO_2MA),
+};
+
+static uint32_t bt_sco_disable[] = {
+ PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_OUT, 0, GPIO_OUTPUT,
+ GPIO_NO_PULL, GPIO_2MA),
+ PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_IN, 0, GPIO_INPUT,
+ GPIO_NO_PULL, GPIO_2MA),
+ PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_SYNC, 0, GPIO_INPUT,
+ GPIO_NO_PULL, GPIO_2MA),
+ PCOM_GPIO_CFG(MAHIMAHI_BT_PCM_CLK, 0, GPIO_INPUT,
+ GPIO_NO_PULL, GPIO_2MA),
+};
+
+void mahimahi_bt_sco_enable(int en)
+{
+ static int bt_sco_refcount;
+ D("%s %d\n", __func__, en);
+
+ mutex_lock(&bt_sco_lock);
+ if (en) {
+ if (++bt_sco_refcount == 1)
+ config_gpio_table(bt_sco_enable,
+ ARRAY_SIZE(bt_sco_enable));
+ } else {
+ if (--bt_sco_refcount == 0) {
+ config_gpio_table(bt_sco_disable,
+ ARRAY_SIZE(bt_sco_disable));
+ gpio_set_value(MAHIMAHI_BT_PCM_OUT, 0);
+ }
+ }
+ mutex_unlock(&bt_sco_lock);
+}
+
+void mahimahi_mic_enable(int en)
+{
+ static int old_state = 0, new_state = 0;
+
+ D("%s %d\n", __func__, en);
+
+ mutex_lock(&mic_lock);
+ if (!!en)
+ new_state++;
+ else
+ new_state--;
+
+ if (new_state == 1 && old_state == 0) {
+ gpio_set_value(MAHIMAHI_AUD_2V5_EN, 1);
+ mdelay(60);
+ } else if (new_state == 0 && old_state == 1)
+ gpio_set_value(MAHIMAHI_AUD_2V5_EN, 0);
+ else
+ D("%s: do nothing %d %d\n", __func__, old_state, new_state);
+
+ old_state = new_state;
+ mutex_unlock(&mic_lock);
+}
+
+void mahimahi_analog_init(void)
+{
+ D("%s\n", __func__);
+ /* stereo pmic init */
+ pmic_spkr_set_gain(LEFT_SPKR, SPKR_GAIN_PLUS12DB);
+ pmic_spkr_set_gain(RIGHT_SPKR, SPKR_GAIN_PLUS12DB);
+ pmic_spkr_en_right_chan(OFF_CMD);
+ pmic_spkr_en_left_chan(OFF_CMD);
+ pmic_spkr_add_right_left_chan(OFF_CMD);
+ pmic_spkr_en_stereo(OFF_CMD);
+ pmic_spkr_select_usb_with_hpf_20hz(OFF_CMD);
+ pmic_spkr_bypass_mux(OFF_CMD);
+ pmic_spkr_en_hpf(ON_CMD);
+ pmic_spkr_en_sink_curr_from_ref_volt_cir(OFF_CMD);
+ pmic_spkr_set_mux_hpf_corner_freq(SPKR_FREQ_0_73KHZ);
+ pmic_mic_set_volt(MIC_VOLT_1_80V);
+
+ gpio_request(MAHIMAHI_AUD_JACKHP_EN, "aud_jackhp_en");
+ gpio_request(MAHIMAHI_BT_PCM_OUT, "bt_pcm_out");
+
+ gpio_direction_output(MAHIMAHI_AUD_JACKHP_EN, 0);
+
+ mutex_lock(&bt_sco_lock);
+ config_gpio_table(bt_sco_disable,
+ ARRAY_SIZE(bt_sco_disable));
+ gpio_direction_output(MAHIMAHI_BT_PCM_OUT, 0);
+ mutex_unlock(&bt_sco_lock);
+}
+
+int mahimahi_get_rx_vol(uint8_t hw, int level)
+{
+ int vol;
+
+ if (level > 100)
+ level = 100;
+ else if (level < 0)
+ level = 0;
+
+ if (is_cdma_version(system_rev) && hw == Q6_HW_HANDSET) {
+ int handset_volume[6] = { -1600, -1300, -1000, -600, -300, 0 };
+ vol = handset_volume[5 * level / 100];
+ } else {
+ struct q6_hw_info *info;
+ info = &q6_audio_hw[hw];
+ vol = info->min_gain + ((info->max_gain - info->min_gain) * level) / 100;
+ }
+
+ D("%s %d\n", __func__, vol);
+ return vol;
+}
+
+static struct qsd_acoustic_ops acoustic = {
+ .enable_mic_bias = mahimahi_mic_enable,
+};
+
+static struct q6audio_analog_ops ops = {
+ .init = mahimahi_analog_init,
+ .speaker_enable = mahimahi_speaker_enable,
+ .headset_enable = mahimahi_headset_enable,
+ .receiver_enable = mahimahi_receiver_enable,
+ .bt_sco_enable = mahimahi_bt_sco_enable,
+ .int_mic_enable = mahimahi_mic_enable,
+ .ext_mic_enable = mahimahi_mic_enable,
+ .get_rx_vol = mahimahi_get_rx_vol,
+};
+
+void __init mahimahi_audio_init(void)
+{
+ mutex_init(&mic_lock);
+ mutex_init(&bt_sco_lock);
+ q6audio_register_analog_ops(&ops);
+ acoustic_register_ops(&acoustic);
+ if (is_cdma_version(system_rev) &&
+ ((system_rev == 0xC1) || (system_rev == 0xC2)))
+ q6audio_set_acdb_file("default_PMIC.acdb");
+}
diff --git a/arch/arm/mach-msm/board-mahimahi-flashlight.c b/arch/arm/mach-msm/board-mahimahi-flashlight.c
new file mode 100644
index 00000000000..829b1f11cf2
--- /dev/null
+++ b/arch/arm/mach-msm/board-mahimahi-flashlight.c
@@ -0,0 +1,279 @@
+/*
+ * arch/arm/mach-msm/flashlight.c - flashlight driver
+ *
+ * Copyright (C) 2009 zion huang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#define DEBUG
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "board-mahimahi-flashlight.h"
+
+struct flashlight_struct {
+ struct led_classdev fl_lcdev;
+ struct early_suspend early_suspend_flashlight;
+ spinlock_t spin_lock;
+ struct hrtimer timer;
+ int brightness;
+ int gpio_torch;
+ int gpio_flash;
+ int flash_duration_ms;
+};
+
+static struct flashlight_struct the_fl;
+
+static inline void toggle(void)
+{
+ gpio_direction_output(the_fl.gpio_torch, 0);
+ udelay(2);
+ gpio_direction_output(the_fl.gpio_torch, 1);
+ udelay(2);
+}
+
+static void flashlight_hw_command(uint8_t addr, uint8_t data)
+{
+ int i;
+
+ for (i = 0; i < addr + 17; i++)
+ toggle();
+ udelay(500);
+
+ for (i = 0; i < data; i++)
+ toggle();
+ udelay(500);
+}
+
+static enum hrtimer_restart flashlight_timeout(struct hrtimer *timer)
+{
+ unsigned long flags;
+
+ pr_debug("%s\n", __func__);
+
+ spin_lock_irqsave(&the_fl.spin_lock, flags);
+ gpio_direction_output(the_fl.gpio_flash, 0);
+ the_fl.brightness = LED_OFF;
+ spin_unlock_irqrestore(&the_fl.spin_lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
+int flashlight_control(int mode)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ pr_debug("%s: mode %d -> %d\n", __func__,
+ the_fl.brightness, mode);
+
+ spin_lock_irqsave(&the_fl.spin_lock, flags);
+
+ the_fl.brightness = mode;
+
+ switch (mode) {
+ case FLASHLIGHT_TORCH:
+ pr_info("%s: half\n", __func__);
+ /* If we are transitioning from flash to torch, make sure to
+ * cancel the flash timeout timer, otherwise when it expires,
+ * the torch will go off as well.
+ */
+ hrtimer_cancel(&the_fl.timer);
+ flashlight_hw_command(2, 4);
+ break;
+
+ case FLASHLIGHT_FLASH:
+ pr_info("%s: full\n", __func__);
+ hrtimer_cancel(&the_fl.timer);
+ gpio_direction_output(the_fl.gpio_flash, 0);
+ udelay(40);
+ gpio_direction_output(the_fl.gpio_flash, 1);
+ hrtimer_start(&the_fl.timer,
+ ktime_set(the_fl.flash_duration_ms / 1000,
+ (the_fl.flash_duration_ms % 1000) *
+ NSEC_PER_MSEC),
+ HRTIMER_MODE_REL);
+ /* Flash overrides torch mode, and after the flash period, the
+ * flash LED will turn off.
+ */
+ mode = LED_OFF;
+ break;
+
+ case FLASHLIGHT_OFF:
+ pr_info("%s: off\n", __func__);
+ gpio_direction_output(the_fl.gpio_flash, 0);
+ gpio_direction_output(the_fl.gpio_torch, 0);
+ break;
+
+ default:
+ pr_err("%s: unknown flash_light flags: %d\n", __func__, mode);
+ ret = -EINVAL;
+ goto done;
+ }
+
+done:
+ spin_unlock_irqrestore(&the_fl.spin_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(flashlight_control);
+
+static void fl_lcdev_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ int level;
+ switch (brightness) {
+ case LED_HALF:
+ level = FLASHLIGHT_TORCH;
+ break;
+ case LED_FULL:
+ level = FLASHLIGHT_FLASH;
+ break;
+ case LED_OFF:
+ default:
+ level = FLASHLIGHT_OFF;
+ };
+
+ flashlight_control(level);
+}
+
+static void flashlight_early_suspend(struct early_suspend *handler)
+{
+ flashlight_control(FLASHLIGHT_OFF);
+}
+
+static int flashlight_setup_gpio(struct flashlight_platform_data *fl_pdata)
+{
+ int ret;
+
+ pr_debug("%s\n", __func__);
+
+ if (fl_pdata->gpio_init) {
+ ret = fl_pdata->gpio_init();
+ if (ret < 0) {
+ pr_err("%s: gpio init failed: %d\n", __func__,
+ ret);
+ return ret;
+ }
+ }
+
+ if (fl_pdata->torch) {
+ ret = gpio_request(fl_pdata->torch, "flashlight_torch");
+ if (ret < 0) {
+ pr_err("%s: gpio_request failed\n", __func__);
+ return ret;
+ }
+ }
+
+ if (fl_pdata->flash) {
+ ret = gpio_request(fl_pdata->flash, "flashlight_flash");
+ if (ret < 0) {
+ pr_err("%s: gpio_request failed\n", __func__);
+ gpio_free(fl_pdata->torch);
+ return ret;
+ }
+ }
+
+ the_fl.gpio_torch = fl_pdata->torch;
+ the_fl.gpio_flash = fl_pdata->flash;
+ the_fl.flash_duration_ms = fl_pdata->flash_duration_ms;
+ return 0;
+}
+
+static int flashlight_probe(struct platform_device *pdev)
+{
+ struct flashlight_platform_data *fl_pdata = pdev->dev.platform_data;
+ int err = 0;
+
+ pr_debug("%s\n", __func__);
+
+ err = flashlight_setup_gpio(fl_pdata);
+ if (err < 0) {
+ pr_err("%s: setup GPIO failed\n", __func__);
+ goto fail_free_mem;
+ }
+
+ spin_lock_init(&the_fl.spin_lock);
+ the_fl.fl_lcdev.name = pdev->name;
+ the_fl.fl_lcdev.brightness_set = fl_lcdev_brightness_set;
+ the_fl.fl_lcdev.brightness = LED_OFF;
+ err = led_classdev_register(&pdev->dev, &the_fl.fl_lcdev);
+ if (err < 0) {
+ pr_err("failed on led_classdev_register\n");
+ goto fail_free_gpio;
+ }
+
+ hrtimer_init(&the_fl.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ the_fl.timer.function = flashlight_timeout;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ the_fl.early_suspend_flashlight.suspend = flashlight_early_suspend;
+ the_fl.early_suspend_flashlight.resume = NULL;
+ register_early_suspend(&the_fl.early_suspend_flashlight);
+#endif
+
+ return 0;
+
+fail_free_gpio:
+ if (fl_pdata->torch)
+ gpio_free(fl_pdata->torch);
+ if (fl_pdata->flash)
+ gpio_free(fl_pdata->flash);
+fail_free_mem:
+ return err;
+}
+
+static int flashlight_remove(struct platform_device *pdev)
+{
+ struct flashlight_platform_data *fl_pdata = pdev->dev.platform_data;
+
+ pr_debug("%s\n", __func__);
+
+ hrtimer_cancel(&the_fl.timer);
+ unregister_early_suspend(&the_fl.early_suspend_flashlight);
+ flashlight_control(FLASHLIGHT_OFF);
+ led_classdev_unregister(&the_fl.fl_lcdev);
+ if (fl_pdata->torch)
+ gpio_free(fl_pdata->torch);
+ if (fl_pdata->flash)
+ gpio_free(fl_pdata->flash);
+ return 0;
+}
+
+static struct platform_driver flashlight_driver = {
+ .probe = flashlight_probe,
+ .remove = flashlight_remove,
+ .driver = {
+ .name = FLASHLIGHT_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init flashlight_init(void)
+{
+ pr_debug("%s\n", __func__);
+ return platform_driver_register(&flashlight_driver);
+}
+
+static void __exit flashlight_exit(void)
+{
+ pr_debug("%s\n", __func__);
+ platform_driver_unregister(&flashlight_driver);
+}
+
+module_init(flashlight_init);
+module_exit(flashlight_exit);
+
+MODULE_AUTHOR("Zion Huang ");
+MODULE_DESCRIPTION("flash light driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-msm/board-mahimahi-flashlight.h b/arch/arm/mach-msm/board-mahimahi-flashlight.h
new file mode 100644
index 00000000000..93b4095edaa
--- /dev/null
+++ b/arch/arm/mach-msm/board-mahimahi-flashlight.h
@@ -0,0 +1,20 @@
+#ifndef __ASM_ARM_ARCH_FLASHLIGHT_H
+#define __ASM_ARM_ARCH_FLASHLIGHT_H
+
+#define FLASHLIGHT_NAME "flashlight"
+
+#define FLASHLIGHT_OFF 0
+#define FLASHLIGHT_TORCH 1
+#define FLASHLIGHT_FLASH 2
+#define FLASHLIGHT_NUM 3
+
+struct flashlight_platform_data {
+ int (*gpio_init) (void);
+ int torch;
+ int flash;
+ int flash_duration_ms;
+};
+
+int flashlight_control(int level);
+
+#endif /*__ASM_ARM_ARCH_FLASHLIGHT_H*/
diff --git a/arch/arm/mach-msm/board-mahimahi-keypad.c b/arch/arm/mach-msm/board-mahimahi-keypad.c
new file mode 100644
index 00000000000..ab38847d15e
--- /dev/null
+++ b/arch/arm/mach-msm/board-mahimahi-keypad.c
@@ -0,0 +1,265 @@
+/* arch/arm/mach-msm/board-mahimahi-keypad.c
+ *
+ * Copyright (C) 2009 Google, Inc
+ * Copyright (C) 2009 HTC Corporation.
+ *
+ * Author: Dima Zavin
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include