Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142 Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
This commit is contained in:
64
AndroidKernel.mk
Normal file
64
AndroidKernel.mk
Normal file
@@ -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
|
||||||
@@ -96,6 +96,7 @@
|
|||||||
<listitem><para>debug_object_deactivate</para></listitem>
|
<listitem><para>debug_object_deactivate</para></listitem>
|
||||||
<listitem><para>debug_object_destroy</para></listitem>
|
<listitem><para>debug_object_destroy</para></listitem>
|
||||||
<listitem><para>debug_object_free</para></listitem>
|
<listitem><para>debug_object_free</para></listitem>
|
||||||
|
<listitem><para>debug_object_assert_init</para></listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
Each of these functions takes the address of the real object and
|
Each of these functions takes the address of the real object and
|
||||||
a pointer to the object type specific debug description
|
a pointer to the object type specific debug description
|
||||||
@@ -273,6 +274,26 @@
|
|||||||
debug checks.
|
debug checks.
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="debug_object_assert_init">
|
||||||
|
<title>debug_object_assert_init</title>
|
||||||
|
<para>
|
||||||
|
This function is called to assert that an object has been
|
||||||
|
initialized.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
When the real object is already tracked by debugobjects it is
|
||||||
|
ignored.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="fixupfunctions">
|
<chapter id="fixupfunctions">
|
||||||
<title>Fixup functions</title>
|
<title>Fixup functions</title>
|
||||||
@@ -381,6 +402,35 @@
|
|||||||
statistics.
|
statistics.
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
<sect1 id="fixup_assert_init">
|
||||||
|
<title>fixup_assert_init</title>
|
||||||
|
<para>
|
||||||
|
This function is called from the debug code whenever a problem
|
||||||
|
in debug_object_assert_init is detected.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Called from debug_object_assert_init() with a hardcoded state
|
||||||
|
ODEBUG_STATE_NOTAVAILABLE when the object is not found in the
|
||||||
|
debug bucket.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The function returns 1 when the fixup was successful,
|
||||||
|
otherwise 0. The return value is used to update the
|
||||||
|
statistics.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Note, this function should make sure debug_object_init() is
|
||||||
|
called before returning.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
|
</para>
|
||||||
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
<chapter id="bugs">
|
<chapter id="bugs">
|
||||||
<title>Known Bugs And Assumptions</title>
|
<title>Known Bugs And Assumptions</title>
|
||||||
|
|||||||
23
Documentation/arm/msm/boot.txt
Normal file
23
Documentation/arm/msm/boot.txt
Normal file
@@ -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
|
||||||
254
Documentation/arm/msm/emulate_domain_manager.txt
Normal file
254
Documentation/arm/msm/emulate_domain_manager.txt
Normal file
@@ -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
|
||||||
|
|
||||||
@@ -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
|
is used to provide gpio pin multiplexing and configuration on mach-msm
|
||||||
targets.
|
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
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
To use gpiomux, provide configuration information for relevant gpio lines
|
To use gpiomux, do the following before the msmgpio gpiochips probe:
|
||||||
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] = {
|
- Call msm_gpiomux_init to allocate needed resources.
|
||||||
[12] = {
|
- Install one or more sets of gpiomux configuration data via
|
||||||
.active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1,
|
msm_gpiomux_install and/or msm_gpiomux_write.
|
||||||
.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
|
|
||||||
|
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,
|
||||||
},
|
},
|
||||||
[34] = {
|
|
||||||
.suspended = GPIOMUX_VALID | 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:
|
The effect of this configuration is as follows:
|
||||||
|
|
||||||
When the system boots, gpios 12 and 34 will be initialized with their
|
- When the system boots, gpio 123 will be put into the SUSPENDED setting.
|
||||||
'suspended' configurations. All other gpios, which were left unconfigured,
|
- When the reference count for gpio 123 rises above 0, the ACTIVE setting
|
||||||
will not be touched.
|
will be applied.
|
||||||
|
- When the reference count falls back to 0, the SUSPENDED setting will be
|
||||||
|
reapplied.
|
||||||
|
|
||||||
When msm_gpiomux_get() is called on gpio 12 to raise its reference count
|
The reference count rises when msm_gpiomux_get() is called and falls
|
||||||
above 0, its active configuration will be applied. Since no other gpio
|
when msm_gpiomux_put() is called. msmgpio has hooks to these functions
|
||||||
line has a valid active configuration, msm_gpiomux_get() will have no
|
in its gpiolib implementation. This means that when you call gpio_request()
|
||||||
effect on any other line.
|
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.
|
||||||
|
|
||||||
When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference
|
Note that the .dir field is ignored if .func != GPIOMUX_FUNC_GPIO, since
|
||||||
count to 0, their suspended configurations will be applied.
|
software control of gpios is allowed only in GPIO mode. By selecting any
|
||||||
Since no other gpio line has a valid suspended configuration, no other
|
other .func, you assign the gpio to another piece of hardware and lose
|
||||||
gpio line will be effected by msm_gpiomux_put(). Since gpio 34 has no valid
|
control of it from gpiolib. You can still reserve such gpios with gpio_request
|
||||||
active configuration, this is effectively a no-op for gpio 34 as well,
|
to prevent other modules from using them while they're in such a state,
|
||||||
with one small caveat, see the section "About Output-Enable Settings".
|
but other gpiolib functions will not behave as you expect if .func != GPIO.
|
||||||
|
|
||||||
All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but
|
If a configuration is omitted, nothing will happen at the relevant transitions.
|
||||||
they address some important issues. As unused entries (all those
|
This allows for the creation of 'static configurations' which do not
|
||||||
except 12 and 34) are zero-filled, gpiomux needs a way to distinguish
|
change as the line is requested and freed.
|
||||||
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.
|
|
||||||
|
|
||||||
Static Configurations
|
Static Configurations
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
To install a static configuration, which is applied at boot and does
|
To install a static configuration, which is applied at boot and does
|
||||||
not change after that, install a configuration with a suspended component
|
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] = {
|
.gpio = ...,
|
||||||
.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
|
.settings = {
|
||||||
|
[GPIOMUX_SUSPENDED] = {
|
||||||
|
...
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
The suspended setting is applied during boot, and the lack of any valid
|
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
|
This mechanism allows for "auto-request" of gpiomux lines via gpiolib
|
||||||
when it is suitable. Drivers wishing more exact control are, of course,
|
when it is suitable. Drivers wishing more exact control are, of course,
|
||||||
free to also use msm_gpiomux_set and msm_gpiomux_get.
|
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.
|
|
||||||
|
|||||||
98
Documentation/arm/msm/kgsl-sysfs.txt
Normal file
98
Documentation/arm/msm/kgsl-sysfs.txt
Normal file
@@ -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.
|
||||||
75
Documentation/arm/msm/msm_rng-driver.txt
Normal file
75
Documentation/arm/msm/msm_rng-driver.txt
Normal file
@@ -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.
|
||||||
267
Documentation/arm/msm/pil.txt
Normal file
267
Documentation/arm/msm/pil.txt
Normal file
@@ -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.
|
||||||
157
Documentation/arm/msm/rpm.txt
Normal file
157
Documentation/arm/msm/rpm.txt
Normal file
@@ -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.
|
||||||
231
Documentation/arm/msm/tsif.txt
Normal file
231
Documentation/arm/msm/tsif.txt
Normal file
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
228
Documentation/crypto/msm/qce.txt
Normal file
228
Documentation/crypto/msm/qce.txt
Normal file
@@ -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
|
||||||
241
Documentation/crypto/msm/qce40.txt
Normal file
241
Documentation/crypto/msm/qce40.txt
Normal file
@@ -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
|
||||||
232
Documentation/crypto/msm/qcedev.txt
Normal file
232
Documentation/crypto/msm/qcedev.txt
Normal file
@@ -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.
|
||||||
144
Documentation/crypto/msm/qcrypto.txt
Normal file
144
Documentation/crypto/msm/qcrypto.txt
Normal file
@@ -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)
|
||||||
189
Documentation/csdio.txt
Normal file
189
Documentation/csdio.txt
Normal file
@@ -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.
|
||||||
@@ -2349,6 +2349,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||||||
1: Fast pin select (default)
|
1: Fast pin select (default)
|
||||||
2: ATC IRMode
|
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=
|
softlockup_panic=
|
||||||
[KNL] Should the soft-lockup detector generate panics.
|
[KNL] Should the soft-lockup detector generate panics.
|
||||||
Format: <integer>
|
Format: <integer>
|
||||||
|
|||||||
@@ -1043,9 +1043,15 @@ conf/all/forwarding - BOOLEAN
|
|||||||
|
|
||||||
This referred to as global forwarding.
|
This referred to as global forwarding.
|
||||||
|
|
||||||
proxy_ndp - BOOLEAN
|
proxy_ndp - INTEGER
|
||||||
Do proxy ndp.
|
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/*:
|
conf/interface/*:
|
||||||
Change special settings per interface.
|
Change special settings per interface.
|
||||||
|
|
||||||
|
|||||||
309
Documentation/networking/qfec.txt
Normal file
309
Documentation/networking/qfec.txt
Normal file
@@ -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
|
||||||
@@ -21,6 +21,7 @@ show up in /proc/sys/kernel:
|
|||||||
- acct
|
- acct
|
||||||
- bootloader_type [ X86 only ]
|
- bootloader_type [ X86 only ]
|
||||||
- bootloader_version [ X86 only ]
|
- bootloader_version [ X86 only ]
|
||||||
|
- boot_reason [ ARM only ]
|
||||||
- callhome [ S390 only ]
|
- callhome [ S390 only ]
|
||||||
- auto_msgmni
|
- auto_msgmni
|
||||||
- core_pattern
|
- 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:
|
callhome:
|
||||||
|
|
||||||
Controls the kernel's callhome behavior in case of a kernel panic.
|
Controls the kernel's callhome behavior in case of a kernel panic.
|
||||||
|
|||||||
181
Documentation/tzcom.txt
Normal file
181
Documentation/tzcom.txt
Normal file
@@ -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
|
||||||
69
Documentation/usb/ehset_compliance.txt
Normal file
69
Documentation/usb/ehset_compliance.txt
Normal file
@@ -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
|
||||||
222
Documentation/usb/gadget_rmnet.txt
Normal file
222
Documentation/usb/gadget_rmnet.txt
Normal file
@@ -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.
|
||||||
|
|
||||||
32
Documentation/usb/gadget_sdio.txt
Normal file
32
Documentation/usb/gadget_sdio.txt
Normal file
@@ -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).
|
||||||
27
Documentation/usb/gadget_smd.txt
Normal file
27
Documentation/usb/gadget_smd.txt
Normal file
@@ -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.
|
||||||
|
|
||||||
382
Documentation/usb/msm_otg.txt
Normal file
382
Documentation/usb/msm_otg.txt
Normal file
@@ -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=<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.
|
||||||
6
Makefile
6
Makefile
@@ -330,7 +330,7 @@ include $(srctree)/scripts/Kbuild.include
|
|||||||
|
|
||||||
AS = $(CROSS_COMPILE)as
|
AS = $(CROSS_COMPILE)as
|
||||||
LD = $(CROSS_COMPILE)ld
|
LD = $(CROSS_COMPILE)ld
|
||||||
CC = $(CROSS_COMPILE)gcc
|
REAL_CC = $(CROSS_COMPILE)gcc
|
||||||
CPP = $(CC) -E
|
CPP = $(CC) -E
|
||||||
AR = $(CROSS_COMPILE)ar
|
AR = $(CROSS_COMPILE)ar
|
||||||
NM = $(CROSS_COMPILE)nm
|
NM = $(CROSS_COMPILE)nm
|
||||||
@@ -345,6 +345,10 @@ KALLSYMS = scripts/kallsyms
|
|||||||
PERL = perl
|
PERL = perl
|
||||||
CHECK = sparse
|
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__ \
|
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
|
||||||
-Wbitwise -Wno-return-void $(CF)
|
-Wbitwise -Wno-return-void $(CF)
|
||||||
CFLAGS_MODULE =
|
CFLAGS_MODULE =
|
||||||
|
|||||||
@@ -148,6 +148,13 @@ config HAVE_HW_BREAKPOINT
|
|||||||
bool
|
bool
|
||||||
depends on PERF_EVENTS
|
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
|
config HAVE_MIXED_BREAKPOINTS_REGS
|
||||||
bool
|
bool
|
||||||
depends on HAVE_HW_BREAKPOINT
|
depends on HAVE_HW_BREAKPOINT
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ config GENERIC_CLOCKEVENTS
|
|||||||
config GENERIC_CLOCKEVENTS_BROADCAST
|
config GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
bool
|
bool
|
||||||
depends on GENERIC_CLOCKEVENTS
|
depends on GENERIC_CLOCKEVENTS
|
||||||
default y if SMP
|
default y if SMP && !LOCAL_TIMERS
|
||||||
|
|
||||||
config KTIME_SCALAR
|
config KTIME_SCALAR
|
||||||
bool
|
bool
|
||||||
@@ -627,6 +627,10 @@ config ARCH_MSM
|
|||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
select ARCH_REQUIRE_GPIOLIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
select CLKDEV_LOOKUP
|
select CLKDEV_LOOKUP
|
||||||
|
select ARCH_HAS_CPUFREQ
|
||||||
|
select GENERIC_GPIO
|
||||||
|
select GENERIC_TIME
|
||||||
|
select GENERIC_ALLOCATOR
|
||||||
help
|
help
|
||||||
Support for Qualcomm MSM/QSD based systems. This runs on the
|
Support for Qualcomm MSM/QSD based systems. This runs on the
|
||||||
apps processor of the MSM/QSD and depends on a shared memory
|
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
|
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
|
config IWMMXT
|
||||||
bool "Enable iWMMXt support"
|
bool "Enable iWMMXt support"
|
||||||
depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
|
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
|
This workaround defines cpu_relax() as smp_mb(), preventing correctly
|
||||||
written polling loops from denying visibility of updates to memory.
|
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
|
endmenu
|
||||||
|
|
||||||
source "arch/arm/common/Kconfig"
|
source "arch/arm/common/Kconfig"
|
||||||
@@ -1311,9 +1351,9 @@ config SMP
|
|||||||
depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
|
depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
|
||||||
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
|
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
|
||||||
ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
|
ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
|
||||||
ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
|
MSM_SMP || ARCH_SHMOBILE
|
||||||
select USE_GENERIC_SMP_HELPERS
|
select USE_GENERIC_SMP_HELPERS
|
||||||
select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
|
select HAVE_ARM_SCU if !MSM_SMP
|
||||||
help
|
help
|
||||||
This enables support for systems with more than one CPU. If you have
|
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
|
a system with only one CPU, like most personal computers, say N. If
|
||||||
@@ -1395,9 +1435,11 @@ config HOTPLUG_CPU
|
|||||||
|
|
||||||
config LOCAL_TIMERS
|
config LOCAL_TIMERS
|
||||||
bool "Use local timer interrupts"
|
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
|
default y
|
||||||
select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
|
select HAVE_ARM_TWD if (!MSM_SMP && !EXYNOS4_MCT)
|
||||||
help
|
help
|
||||||
Enable support for local timers on SMP platforms, rather then the
|
Enable support for local timers on SMP platforms, rather then the
|
||||||
legacy IPI broadcast method. Local timers allows the system
|
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
|
Enable hardware performance counter support for perf events. If
|
||||||
disabled, perf events will use software events only.
|
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"
|
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
|
config FORCE_MAX_ZONEORDER
|
||||||
int "Maximum zone order" if ARCH_SHMOBILE
|
int "Maximum zone order" if ARCH_SHMOBILE
|
||||||
range 11 64 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
|
released if it failed to be acquired, which will cause all the
|
||||||
pending messages to be flushed.
|
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
|
endmenu
|
||||||
|
|
||||||
menu "Boot options"
|
menu "Boot options"
|
||||||
@@ -1940,6 +2011,14 @@ source "drivers/cpuidle/Kconfig"
|
|||||||
|
|
||||||
endmenu
|
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"
|
menu "Floating point emulation"
|
||||||
|
|
||||||
comment "At least one emulation must be selected"
|
comment "At least one emulation must be selected"
|
||||||
@@ -2029,7 +2108,7 @@ menu "Power management options"
|
|||||||
source "kernel/power/Kconfig"
|
source "kernel/power/Kconfig"
|
||||||
|
|
||||||
config ARCH_SUSPEND_POSSIBLE
|
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 || \
|
depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
|
||||||
CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
|
CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|||||||
@@ -255,6 +255,7 @@ core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
|
|||||||
core-y += $(machdirs) $(platdirs)
|
core-y += $(machdirs) $(platdirs)
|
||||||
|
|
||||||
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
||||||
|
core-y += arch/arm/perfmon/
|
||||||
|
|
||||||
libs-y := arch/arm/lib/ $(libs-y)
|
libs-y := arch/arm/lib/ $(libs-y)
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,14 @@
|
|||||||
.macro writeb, ch, rb
|
.macro writeb, ch, rb
|
||||||
mcr p14, 0, \ch, c0, c5, 0
|
mcr p14, 0, \ch, c0, c5, 0
|
||||||
.endm
|
.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)
|
#elif defined(CONFIG_CPU_XSCALE)
|
||||||
.macro loadsp, rb, tmp
|
.macro loadsp, rb, tmp
|
||||||
.endm
|
.endm
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
config ARM_GIC
|
config ARM_GIC
|
||||||
bool
|
bool
|
||||||
|
select MSM_SHOW_RESUME_IRQ
|
||||||
|
|
||||||
config ARM_VIC
|
config ARM_VIC
|
||||||
bool
|
bool
|
||||||
|
|||||||
253
arch/arm/common/cpaccess.c
Normal file
253
arch/arm/common/cpaccess.c
Normal file
@@ -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 <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/sysrq.h>
|
||||||
|
#include <linux/time.h>
|
||||||
|
#include <linux/proc_fs.h>
|
||||||
|
#include <linux/kernel_stat.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/sysdev.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/semaphore.h>
|
||||||
|
#include <linux/file.h>
|
||||||
|
#include <linux/percpu.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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");
|
||||||
@@ -28,10 +28,12 @@
|
|||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <linux/syscore_ops.h>
|
||||||
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/mach/irq.h>
|
#include <asm/mach/irq.h>
|
||||||
#include <asm/hardware/gic.h>
|
#include <asm/hardware/gic.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(irq_controller_lock);
|
static DEFINE_SPINLOCK(irq_controller_lock);
|
||||||
|
|
||||||
@@ -42,6 +44,11 @@ struct gic_chip_data {
|
|||||||
unsigned int irq_offset;
|
unsigned int irq_offset;
|
||||||
void __iomem *dist_base;
|
void __iomem *dist_base;
|
||||||
void __iomem *cpu_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_retrigger = NULL,
|
||||||
.irq_set_type = NULL,
|
.irq_set_type = NULL,
|
||||||
.irq_set_wake = NULL,
|
.irq_set_wake = NULL,
|
||||||
|
.irq_disable = NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef MAX_GIC_NR
|
#ifndef MAX_GIC_NR
|
||||||
@@ -93,6 +101,7 @@ static void gic_mask_irq(struct irq_data *d)
|
|||||||
if (gic_arch_extn.irq_mask)
|
if (gic_arch_extn.irq_mask)
|
||||||
gic_arch_extn.irq_mask(d);
|
gic_arch_extn.irq_mask(d);
|
||||||
spin_unlock(&irq_controller_lock);
|
spin_unlock(&irq_controller_lock);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gic_unmask_irq(struct irq_data *d)
|
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);
|
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)
|
static void gic_eoi_irq(struct irq_data *d)
|
||||||
{
|
{
|
||||||
if (gic_arch_extn.irq_eoi) {
|
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)
|
static int gic_set_wake(struct irq_data *d, unsigned int on)
|
||||||
{
|
{
|
||||||
int ret = -ENXIO;
|
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)
|
if (gic_arch_extn.irq_set_wake)
|
||||||
ret = gic_arch_extn.irq_set_wake(d, on);
|
ret = gic_arch_extn.irq_set_wake(d, on);
|
||||||
@@ -250,6 +371,7 @@ static struct irq_chip gic_chip = {
|
|||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
.irq_set_affinity = gic_set_affinity,
|
.irq_set_affinity = gic_set_affinity,
|
||||||
#endif
|
#endif
|
||||||
|
.irq_disable = gic_disable_irq,
|
||||||
.irq_set_wake = gic_set_wake,
|
.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);
|
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gic->max_irq = gic_irqs;
|
||||||
|
|
||||||
writel_relaxed(1, base + GIC_DIST_CTRL);
|
writel_relaxed(1, base + GIC_DIST_CTRL);
|
||||||
|
mb();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
|
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(0xf0, base + GIC_CPU_PRIMASK);
|
||||||
writel_relaxed(1, base + GIC_CPU_CTRL);
|
writel_relaxed(1, base + GIC_CPU_CTRL);
|
||||||
|
mb();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
|
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 */
|
/* this always happens on GIC0 */
|
||||||
writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
|
writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
|
||||||
|
mb();
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
||||||
|
}
|
||||||
|
|||||||
134
arch/arm/configs/apq8064_defconfig
Normal file
134
arch/arm/configs/apq8064_defconfig
Normal file
@@ -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
|
||||||
298
arch/arm/configs/msm7627-perf_defconfig
Normal file
298
arch/arm/configs/msm7627-perf_defconfig
Normal file
@@ -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
|
||||||
299
arch/arm/configs/msm7627_defconfig
Normal file
299
arch/arm/configs/msm7627_defconfig
Normal file
@@ -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
|
||||||
315
arch/arm/configs/msm7627a-perf_defconfig
Normal file
315
arch/arm/configs/msm7627a-perf_defconfig
Normal file
@@ -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
|
||||||
308
arch/arm/configs/msm7627a_defconfig
Normal file
308
arch/arm/configs/msm7627a_defconfig
Normal file
@@ -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
|
||||||
369
arch/arm/configs/msm7630-perf_defconfig
Normal file
369
arch/arm/configs/msm7630-perf_defconfig
Normal file
@@ -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
|
||||||
358
arch/arm/configs/msm7630_defconfig
Normal file
358
arch/arm/configs/msm7630_defconfig
Normal file
@@ -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
|
||||||
427
arch/arm/configs/msm8660-perf_defconfig
Normal file
427
arch/arm/configs/msm8660-perf_defconfig
Normal file
@@ -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
|
||||||
425
arch/arm/configs/msm8660_defconfig
Normal file
425
arch/arm/configs/msm8660_defconfig
Normal file
@@ -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
|
||||||
365
arch/arm/configs/msm8960_defconfig
Normal file
365
arch/arm/configs/msm8960_defconfig
Normal file
@@ -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
|
||||||
@@ -87,6 +87,21 @@
|
|||||||
* DMA Cache Coherency
|
* 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)
|
* dma_flush_range(start, end)
|
||||||
*
|
*
|
||||||
* Clean and invalidate the specified virtual address range.
|
* 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_map_area)(const void *, size_t, int);
|
||||||
void (*dma_unmap_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 *);
|
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_map_area cpu_cache.dma_map_area
|
||||||
#define dmac_unmap_area cpu_cache.dma_unmap_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
|
#define dmac_flush_range cpu_cache.dma_flush_range
|
||||||
|
|
||||||
#else
|
#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_map_area(const void *, size_t, int);
|
||||||
extern void dmac_unmap_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 *);
|
extern void dmac_flush_range(const void *, const void *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#define CPUID_CACHETYPE 1
|
#define CPUID_CACHETYPE 1
|
||||||
#define CPUID_TCM 2
|
#define CPUID_TCM 2
|
||||||
#define CPUID_TLBTYPE 3
|
#define CPUID_TLBTYPE 3
|
||||||
|
#define CPUID_MPIDR 5
|
||||||
|
|
||||||
#define CPUID_EXT_PFR0 "c1, 0"
|
#define CPUID_EXT_PFR0 "c1, 0"
|
||||||
#define CPUID_EXT_PFR1 "c1, 1"
|
#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);
|
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)
|
* Intel's XScale3 core supports some v6 features (supersections, L2)
|
||||||
* but advertises itself as v5 as it does not support the v6 ISA. For
|
* but advertises itself as v5 as it does not support the v6 ISA. For
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <asm/param.h> /* HZ */
|
#include <asm/param.h> /* HZ */
|
||||||
|
|
||||||
extern void __delay(int loops);
|
extern void __delay(unsigned long loops);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function intentionally does not exist; if you see references to
|
* 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))) : \
|
__const_udelay((n) * ((2199023U*HZ)>>11))) : \
|
||||||
__udelay(n))
|
__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) */
|
#endif /* defined(_ARM_DELAY_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
|
* dma_alloc_coherent - allocate consistent memory for DMA
|
||||||
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
|
* @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;
|
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
|
* 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
|
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* arch/arm/include/asm/domain.h
|
* arch/arm/include/asm/domain.h
|
||||||
*
|
*
|
||||||
* Copyright (C) 1999 Russell King.
|
* 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
|
* 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
|
* 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
|
* 36-bit addressing and supersections are only available on
|
||||||
* CPUs based on ARMv6+ or the Intel XSC3 core.
|
* 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_KERNEL 0
|
||||||
#define DOMAIN_TABLE 0
|
#define DOMAIN_TABLE 0
|
||||||
#define DOMAIN_USER 1
|
#define DOMAIN_USER 1
|
||||||
@@ -56,6 +62,17 @@
|
|||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
#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) \
|
#define set_domain(x) \
|
||||||
do { \
|
do { \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
@@ -63,6 +80,7 @@
|
|||||||
: : "r" (x)); \
|
: : "r" (x)); \
|
||||||
isb(); \
|
isb(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define modify_domain(dom,type) \
|
#define modify_domain(dom,type) \
|
||||||
do { \
|
do { \
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
/* Registers shifts and masks */
|
/* Registers shifts and masks */
|
||||||
#define L2X0_CACHE_ID_PART_MASK (0xf << 6)
|
#define L2X0_CACHE_ID_PART_MASK (0xf << 6)
|
||||||
#define L2X0_CACHE_ID_PART_L210 (1 << 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_CACHE_ID_PART_L310 (3 << 6)
|
||||||
|
|
||||||
#define L2X0_AUX_CTRL_MASK 0xc0000fff
|
#define L2X0_AUX_CTRL_MASK 0xc0000fff
|
||||||
@@ -71,9 +72,13 @@
|
|||||||
#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28
|
#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28
|
||||||
#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29
|
#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29
|
||||||
#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30
|
#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30
|
||||||
|
#define L2X0_AUX_CTRL_EVNT_MON_BUS_EN_SHIFT 20
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
|
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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ void gic_secondary_init(unsigned int);
|
|||||||
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
|
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
|
||||||
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
|
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
|
||||||
void gic_enable_ppi(unsigned int);
|
void gic_enable_ppi(unsigned int);
|
||||||
|
bool gic_is_spi_pending(unsigned int irq);
|
||||||
|
void gic_clear_spi_pending(unsigned int irq);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
|
||||||
#define ioremap_nocache(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_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
|
||||||
#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
|
#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
|
||||||
#define iounmap __arch_iounmap
|
#define iounmap __arch_iounmap
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ struct mtd_info;
|
|||||||
* map_name: the map probe function name
|
* map_name: the map probe function name
|
||||||
* name: flash device name (eg, as used with mtdparts=)
|
* name: flash device name (eg, as used with mtdparts=)
|
||||||
* width: width of mapped device
|
* width: width of mapped device
|
||||||
|
* interleave: interleave mode feature support
|
||||||
* init: method called at driver/device initialisation
|
* init: method called at driver/device initialisation
|
||||||
* exit: method called at driver/device removal
|
* exit: method called at driver/device removal
|
||||||
* set_vpp: method called to enable or disable VPP
|
* set_vpp: method called to enable or disable VPP
|
||||||
@@ -28,6 +29,7 @@ struct flash_platform_data {
|
|||||||
const char *map_name;
|
const char *map_name;
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
|
unsigned int interleave;
|
||||||
int (*init)(void);
|
int (*init)(void);
|
||||||
void (*exit)(void);
|
void (*exit)(void);
|
||||||
void (*set_vpp)(int on);
|
void (*set_vpp)(int on);
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ struct map_desc {
|
|||||||
#define MT_MEMORY_NONCACHED 11
|
#define MT_MEMORY_NONCACHED 11
|
||||||
#define MT_MEMORY_DTCM 12
|
#define MT_MEMORY_DTCM 12
|
||||||
#define MT_MEMORY_ITCM 13
|
#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
|
#ifdef CONFIG_MMU
|
||||||
extern void iotable_init(struct map_desc *, int);
|
extern void iotable_init(struct map_desc *, int);
|
||||||
|
|||||||
@@ -7,6 +7,12 @@
|
|||||||
#include <linux/mmc/host.h>
|
#include <linux/mmc/host.h>
|
||||||
#include <linux/mmc/card.h>
|
#include <linux/mmc/card.h>
|
||||||
#include <linux/mmc/sdio_func.h>
|
#include <linux/mmc/sdio_func.h>
|
||||||
|
#include <mach/gpio.h>
|
||||||
|
|
||||||
|
#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 embedded_sdio_data {
|
||||||
struct sdio_cis cis;
|
struct sdio_cis cis;
|
||||||
@@ -15,6 +21,91 @@ struct embedded_sdio_data {
|
|||||||
int num_funcs;
|
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 {
|
struct mmc_platform_data {
|
||||||
unsigned int ocr_mask; /* available voltages */
|
unsigned int ocr_mask; /* available voltages */
|
||||||
int built_in; /* built-in device flag */
|
int built_in; /* built-in device flag */
|
||||||
@@ -23,6 +114,35 @@ struct mmc_platform_data {
|
|||||||
unsigned int (*status)(struct device *);
|
unsigned int (*status)(struct device *);
|
||||||
struct embedded_sdio_data *embedded_sdio;
|
struct embedded_sdio_data *embedded_sdio;
|
||||||
int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
|
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
|
#endif
|
||||||
|
|||||||
@@ -299,6 +299,13 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
|
|||||||
#define arch_is_coherent() 0
|
#define arch_is_coherent() 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set if the architecture speculatively fetches data into cache.
|
||||||
|
*/
|
||||||
|
#ifndef arch_has_speculative_dfetch
|
||||||
|
#define arch_has_speculative_dfetch() 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <asm-generic/memory_model.h>
|
#include <asm-generic/memory_model.h>
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
|||||||
__res |= __ex_flag;
|
__res |= __ex_flag;
|
||||||
if (unlikely(__res != 0))
|
if (unlikely(__res != 0))
|
||||||
fail_fn(count);
|
fail_fn(count);
|
||||||
|
else
|
||||||
|
smp_rmb();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
@@ -61,6 +63,9 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
|
|||||||
__res |= __ex_flag;
|
__res |= __ex_flag;
|
||||||
if (unlikely(__res != 0))
|
if (unlikely(__res != 0))
|
||||||
__res = fail_fn(count);
|
__res = fail_fn(count);
|
||||||
|
else
|
||||||
|
smp_rmb();
|
||||||
|
|
||||||
return __res;
|
return __res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +79,7 @@ __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
|
|||||||
{
|
{
|
||||||
int __ex_flag, __res, __orig;
|
int __ex_flag, __res, __orig;
|
||||||
|
|
||||||
|
smp_wmb();
|
||||||
__asm__ (
|
__asm__ (
|
||||||
|
|
||||||
"ldrex %0, [%3] \n\t"
|
"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" (__orig), "=&r" (__res), "=&r" (__ex_flag)
|
||||||
: "r" (&count->counter)
|
: "r" (&count->counter)
|
||||||
: "cc", "memory" );
|
: "cc", "memory" );
|
||||||
|
if (__orig)
|
||||||
|
smp_rmb();
|
||||||
|
|
||||||
return __orig;
|
return __orig;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,6 +201,11 @@ typedef struct page *pgtable_t;
|
|||||||
extern int pfn_valid(unsigned long);
|
extern int pfn_valid(unsigned long);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
|
||||||
|
extern int _early_pfn_valid(unsigned long);
|
||||||
|
#define early_pfn_valid(pfn) (_early_pfn_valid(pfn))
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asm/memory.h>
|
#include <asm/memory.h>
|
||||||
|
|
||||||
#endif /* !__ASSEMBLY__ */
|
#endif /* !__ASSEMBLY__ */
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ enum arm_perf_pmu_ids {
|
|||||||
ARM_PERF_PMU_ID_V6MP,
|
ARM_PERF_PMU_ID_V6MP,
|
||||||
ARM_PERF_PMU_ID_CA8,
|
ARM_PERF_PMU_ID_CA8,
|
||||||
ARM_PERF_PMU_ID_CA9,
|
ARM_PERF_PMU_ID_CA9,
|
||||||
|
ARM_PERF_PMU_ID_SCORPION,
|
||||||
|
ARM_PERF_PMU_ID_SCORPIONMP,
|
||||||
|
ARM_PERF_PMU_ID_KRAIT,
|
||||||
ARM_NUM_PMU_IDS,
|
ARM_NUM_PMU_IDS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
33
arch/arm/include/asm/perftypes.h
Normal file
33
arch/arm/include/asm/perftypes.h
Normal file
@@ -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
|
||||||
@@ -22,7 +22,9 @@
|
|||||||
|
|
||||||
#include <asm/memory.h>
|
#include <asm/memory.h>
|
||||||
#include <mach/vmalloc.h>
|
#include <mach/vmalloc.h>
|
||||||
|
#include <mach/memory.h>
|
||||||
#include <asm/pgtable-hwdef.h>
|
#include <asm/pgtable-hwdef.h>
|
||||||
|
#include <asm/tlbflush.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Just any arbitrary offset to the start of the vmalloc VM area: the
|
* 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) \
|
#define pgprot_writecombine(prot) \
|
||||||
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
|
__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
|
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
|
||||||
#define pgprot_dmacoherent(prot) \
|
#define pgprot_dmacoherent(prot) \
|
||||||
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
|
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
|
||||||
#define __HAVE_PHYS_MEM_ACCESS_PROT
|
#define __HAVE_PHYS_MEM_ACCESS_PROT
|
||||||
|
#define COHERENT_IS_NORMAL 1
|
||||||
struct file;
|
struct file;
|
||||||
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
|
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
|
||||||
unsigned long size, pgprot_t vma_prot);
|
unsigned long size, pgprot_t vma_prot);
|
||||||
#else
|
#else
|
||||||
#define pgprot_dmacoherent(prot) \
|
#define pgprot_dmacoherent(prot) \
|
||||||
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
|
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
|
||||||
|
#define COHERENT_IS_NORMAL 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#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'
|
* remap a physical page `pfn' of size `size' with page protection `prot'
|
||||||
* into virtual address `from'
|
* into virtual address `from'
|
||||||
*/
|
*/
|
||||||
|
#ifndef HAS_ARCH_IO_REMAP_PFN_RANGE
|
||||||
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
|
#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)
|
#define pgtable_cache_init() do { } while (0)
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
enum arm_pmu_type {
|
enum arm_pmu_type {
|
||||||
ARM_PMU_DEVICE_CPU = 0,
|
ARM_PMU_DEVICE_CPU = 0,
|
||||||
|
ARM_PMU_DEVICE_L2 = 1,
|
||||||
ARM_NUM_PMU_DEVICES,
|
ARM_NUM_PMU_DEVICES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
#define STACK_TOP_MAX TASK_SIZE
|
#define STACK_TOP_MAX TASK_SIZE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern unsigned int boot_reason;
|
||||||
|
|
||||||
struct debug_info {
|
struct debug_info {
|
||||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||||
struct perf_event *hbp[ARM_MAX_HBP_SLOTS];
|
struct perf_event *hbp[ARM_MAX_HBP_SLOTS];
|
||||||
|
|||||||
18
arch/arm/include/asm/remote_spinlock.h
Normal file
18
arch/arm/include/asm/remote_spinlock.h
Normal file
@@ -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 <mach/remote_spinlock.h>
|
||||||
|
|
||||||
|
#endif /* __ASM_REMOTE_SPINLOCK_H */
|
||||||
@@ -37,6 +37,15 @@ struct tag_core {
|
|||||||
|
|
||||||
/* it is allowed to have multiple ATAG_MEM nodes */
|
/* it is allowed to have multiple ATAG_MEM nodes */
|
||||||
#define ATAG_MEM 0x54410002
|
#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 {
|
struct tag_mem32 {
|
||||||
__u32 size;
|
__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 early_print(const char *str, ...);
|
||||||
extern void dump_machine_table(void);
|
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 /* __KERNEL__ */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -69,6 +69,8 @@
|
|||||||
#define __exception_irq_entry __exception
|
#define __exception_irq_entry __exception
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void cpu_idle_wait(void);
|
||||||
|
|
||||||
struct thread_info;
|
struct thread_info;
|
||||||
struct task_struct;
|
struct task_struct;
|
||||||
|
|
||||||
|
|||||||
@@ -433,7 +433,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
|
|||||||
if (tlb_flag(TLB_V6_I_PAGE))
|
if (tlb_flag(TLB_V6_I_PAGE))
|
||||||
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
|
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
|
||||||
if (tlb_flag(TLB_V7_UIS_PAGE))
|
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");
|
asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (uaddr & PAGE_MASK) : "cc");
|
||||||
#else
|
#else
|
||||||
asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
|
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))
|
if (tlb_flag(TLB_V6_I_PAGE))
|
||||||
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
|
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
|
||||||
if (tlb_flag(TLB_V7_UIS_PAGE))
|
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");
|
asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
|
||||||
|
#endif
|
||||||
|
|
||||||
if (tlb_flag(TLB_BTB)) {
|
if (tlb_flag(TLB_BTB)) {
|
||||||
/* flush the branch target cache */
|
/* flush the branch target cache */
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#define FPSID_FORMAT_MASK (0x3 << FPSID_FORMAT_BIT)
|
#define FPSID_FORMAT_MASK (0x3 << FPSID_FORMAT_BIT)
|
||||||
#define FPSID_NODOUBLE (1<<20)
|
#define FPSID_NODOUBLE (1<<20)
|
||||||
#define FPSID_ARCH_BIT (16)
|
#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_BIT (8)
|
||||||
#define FPSID_PART_MASK (0xFF << FPSID_PART_BIT)
|
#define FPSID_PART_MASK (0xFF << FPSID_PART_BIT)
|
||||||
#define FPSID_VARIANT_BIT (4)
|
#define FPSID_VARIANT_BIT (4)
|
||||||
@@ -82,3 +82,8 @@
|
|||||||
#define VFPOPDESC_UNUSED_BIT (24)
|
#define VFPOPDESC_UNUSED_BIT (24)
|
||||||
#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT)
|
#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT)
|
||||||
#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK))
|
#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK))
|
||||||
|
|
||||||
|
#ifndef __ASSEMBLY__
|
||||||
|
int vfp_flush_context(void);
|
||||||
|
void vfp_reinit(void);
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -52,10 +52,6 @@ extern void fpundefinstr(void);
|
|||||||
|
|
||||||
EXPORT_SYMBOL(__backtrace);
|
EXPORT_SYMBOL(__backtrace);
|
||||||
|
|
||||||
/* platform dependent support */
|
|
||||||
EXPORT_SYMBOL(__udelay);
|
|
||||||
EXPORT_SYMBOL(__const_udelay);
|
|
||||||
|
|
||||||
/* networking */
|
/* networking */
|
||||||
EXPORT_SYMBOL(csum_partial);
|
EXPORT_SYMBOL(csum_partial);
|
||||||
EXPORT_SYMBOL(csum_partial_copy_from_user);
|
EXPORT_SYMBOL(csum_partial_copy_from_user);
|
||||||
|
|||||||
@@ -734,7 +734,14 @@ ENTRY(__switch_to)
|
|||||||
ldr r7, [r7, #TSK_STACK_CANARY]
|
ldr r7, [r7, #TSK_STACK_CANARY]
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
#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
|
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
mov r5, r0
|
mov r5, r0
|
||||||
add r4, r2, #TI_CPU_SAVE
|
add r4, r2, #TI_CPU_SAVE
|
||||||
|
|||||||
@@ -362,10 +362,17 @@ __enable_mmu:
|
|||||||
#ifdef CONFIG_CPU_ICACHE_DISABLE
|
#ifdef CONFIG_CPU_ICACHE_DISABLE
|
||||||
bic r0, r0, #CR_I
|
bic r0, r0, #CR_I
|
||||||
#endif
|
#endif
|
||||||
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
|
#ifdef CONFIG_EMULATE_DOMAIN_MANAGER_V7
|
||||||
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
|
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \
|
||||||
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
|
domain_val(DOMAIN_KERNEL, DOMAIN_CLIENT) | \
|
||||||
|
domain_val(DOMAIN_TABLE, DOMAIN_CLIENT) | \
|
||||||
domain_val(DOMAIN_IO, 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_CLIENT) | \
|
||||||
|
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
|
||||||
|
#endif
|
||||||
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
|
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
|
||||||
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
|
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
|
||||||
b __turn_mmu_on
|
b __turn_mmu_on
|
||||||
|
|||||||
@@ -833,6 +833,18 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
|
|||||||
return ret;
|
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.
|
* One-time initialisation.
|
||||||
*/
|
*/
|
||||||
@@ -880,11 +892,11 @@ static void reset_ctrl_regs(void *info)
|
|||||||
if (enable_monitor_mode())
|
if (enable_monitor_mode())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* We must also reset any reserved registers. */
|
#ifdef CONFIG_HAVE_HW_BRKPT_RESERVED_RW_ACCESS
|
||||||
for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
|
reset_brps_reserved_reg(core_num_brps);
|
||||||
write_wb_reg(ARM_BASE_BCR + i, 0UL);
|
#else
|
||||||
write_wb_reg(ARM_BASE_BVR + i, 0UL);
|
reset_brps_reserved_reg(core_num_brps + core_num_reserved_brps);
|
||||||
}
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < core_num_wrps; ++i) {
|
for (i = 0; i < core_num_wrps; ++i) {
|
||||||
write_wb_reg(ARM_BASE_WCR + i, 0UL);
|
write_wb_reg(ARM_BASE_WCR + i, 0UL);
|
||||||
|
|||||||
@@ -42,6 +42,8 @@
|
|||||||
#include <asm/mach/irq.h>
|
#include <asm/mach/irq.h>
|
||||||
#include <asm/mach/time.h>
|
#include <asm/mach/time.h>
|
||||||
|
|
||||||
|
#include <asm/perftypes.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* No architecture-specific irq_finish function defined in arm/arch/irqs.h.
|
* 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);
|
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||||
|
|
||||||
|
perf_mon_interrupt_in();
|
||||||
irq_enter();
|
irq_enter();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -95,6 +98,7 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
|
|||||||
|
|
||||||
irq_exit();
|
irq_exit();
|
||||||
set_irq_regs(old_regs);
|
set_irq_regs(old_regs);
|
||||||
|
perf_mon_interrupt_out();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_irq_flags(unsigned int irq, unsigned int iflags)
|
void set_irq_flags(unsigned int irq, unsigned int iflags)
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ void machine_kexec(struct kimage *image)
|
|||||||
unsigned long reboot_code_buffer_phys;
|
unsigned long reboot_code_buffer_phys;
|
||||||
void *reboot_code_buffer;
|
void *reboot_code_buffer;
|
||||||
|
|
||||||
|
arch_kexec();
|
||||||
|
|
||||||
page_list = image->head & PAGE_MASK;
|
page_list = image->head & PAGE_MASK;
|
||||||
|
|
||||||
@@ -120,5 +121,5 @@ void machine_kexec(struct kimage *image)
|
|||||||
cpu_proc_fin();
|
cpu_proc_fin();
|
||||||
outer_inv_all();
|
outer_inv_all();
|
||||||
flush_cache_all();
|
flush_cache_all();
|
||||||
cpu_reset(reboot_code_buffer_phys);
|
__virt_to_phys(cpu_reset)(reboot_code_buffer_phys);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
|
||||||
#include <asm/cputype.h>
|
#include <asm/cputype.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
@@ -71,6 +72,10 @@ struct arm_pmu {
|
|||||||
enum arm_perf_pmu_ids id;
|
enum arm_perf_pmu_ids id;
|
||||||
const char *name;
|
const char *name;
|
||||||
irqreturn_t (*handle_irq)(int irq_num, void *dev);
|
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 (*enable)(struct hw_perf_event *evt, int idx);
|
||||||
void (*disable)(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,
|
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 "
|
pr_warning("unable to request IRQ%d for ARM perf "
|
||||||
"counters\n", irq);
|
"counters\n", irq);
|
||||||
break;
|
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) {
|
for (i = pmu_device->num_resources - 1; i >= 0; --i) {
|
||||||
irq = platform_get_irq(pmu_device, i);
|
irq = platform_get_irq(pmu_device, i);
|
||||||
if (irq >= 0)
|
if (irq >= 0) {
|
||||||
free_irq(irq, NULL);
|
free_irq(irq, NULL);
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
if (armpmu->secondary_disable)
|
||||||
|
armpmu->secondary_disable(irq);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
armpmu->stop();
|
armpmu->stop();
|
||||||
|
|
||||||
@@ -624,6 +638,10 @@ static struct pmu pmu = {
|
|||||||
#include "perf_event_xscale.c"
|
#include "perf_event_xscale.c"
|
||||||
#include "perf_event_v6.c"
|
#include "perf_event_v6.c"
|
||||||
#include "perf_event_v7.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.
|
* Ensure the PMU has sane values out of reset.
|
||||||
@@ -674,6 +692,22 @@ init_hw_perf_events(void)
|
|||||||
armpmu = xscale2pmu_init();
|
armpmu = xscale2pmu_init();
|
||||||
break;
|
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) {
|
if (armpmu) {
|
||||||
|
|||||||
710
arch/arm/kernel/perf_event_msm.c
Normal file
710
arch/arm/kernel/perf_event_msm.c
Normal file
@@ -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 <asm/vfp.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
#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 */
|
||||||
399
arch/arm/kernel/perf_event_msm_krait.c
Normal file
399
arch/arm/kernel/perf_event_msm_krait.c
Normal file
@@ -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 <asm/system.h>
|
||||||
|
|
||||||
|
#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 */
|
||||||
656
arch/arm/kernel/perf_event_msm_krait_l2.c
Normal file
656
arch/arm/kernel/perf_event_msm_krait_l2.c
Normal file
@@ -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 <linux/irq.h>
|
||||||
|
|
||||||
|
#include <mach/msm-krait-l2-accessors.h>
|
||||||
|
|
||||||
|
#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
|
||||||
981
arch/arm/kernel/perf_event_msm_l2.c
Normal file
981
arch/arm/kernel/perf_event_msm_l2.c
Normal file
@@ -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 <linux/irq.h>
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -45,16 +45,41 @@ static int __devinit pmu_device_probe(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver pmu_driver = {
|
static struct platform_driver cpu_pmu_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "arm-pmu",
|
.name = "cpu-arm-pmu",
|
||||||
},
|
},
|
||||||
.probe = pmu_device_probe,
|
.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)
|
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);
|
device_initcall(register_pmu_driver);
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,9 @@
|
|||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/proc_fs.h>
|
#include <linux/proc_fs.h>
|
||||||
#include <linux/memblock.h>
|
#include <linux/memblock.h>
|
||||||
|
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||||
|
#include <linux/memory_hotplug.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <asm/unified.h>
|
#include <asm/unified.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
@@ -97,6 +100,8 @@ EXPORT_SYMBOL(system_serial_high);
|
|||||||
unsigned int elf_hwcap __read_mostly;
|
unsigned int elf_hwcap __read_mostly;
|
||||||
EXPORT_SYMBOL(elf_hwcap);
|
EXPORT_SYMBOL(elf_hwcap);
|
||||||
|
|
||||||
|
unsigned int boot_reason;
|
||||||
|
EXPORT_SYMBOL(boot_reason);
|
||||||
|
|
||||||
#ifdef MULTI_CPU
|
#ifdef MULTI_CPU
|
||||||
struct processor processor __read_mostly;
|
struct processor processor __read_mostly;
|
||||||
@@ -517,6 +522,62 @@ static int __init early_mem(char *p)
|
|||||||
}
|
}
|
||||||
early_param("mem", early_mem);
|
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
|
static void __init
|
||||||
setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
|
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);
|
__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)
|
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
|
||||||
struct screen_info screen_info = {
|
struct screen_info screen_info = {
|
||||||
.orig_video_lines = 30,
|
.orig_video_lines = 30,
|
||||||
|
|||||||
@@ -597,6 +597,11 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
|
|||||||
|
|
||||||
void smp_send_reschedule(int cpu)
|
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);
|
smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,8 +127,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
|
|||||||
twd_calibrate_rate();
|
twd_calibrate_rate();
|
||||||
|
|
||||||
clk->name = "local_timer";
|
clk->name = "local_timer";
|
||||||
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
|
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
|
||||||
CLOCK_EVT_FEAT_C3STOP;
|
|
||||||
clk->rating = 350;
|
clk->rating = 350;
|
||||||
clk->set_mode = twd_set_mode;
|
clk->set_mode = twd_set_mode;
|
||||||
clk->set_next_event = twd_set_next_event;
|
clk->set_next_event = twd_set_next_event;
|
||||||
|
|||||||
@@ -453,6 +453,10 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
|
|||||||
|
|
||||||
up_read(&mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
flush_cache_user_range(start, end);
|
flush_cache_user_range(start, end);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_MSM7X27
|
||||||
|
mb();
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
up_read(&mm->mmap_sem);
|
up_read(&mm->mmap_sem);
|
||||||
|
|||||||
90
arch/arm/lib/delay.c
Normal file
90
arch/arm/lib/delay.c
Normal file
@@ -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 <mj@atrey.karlin.mff.cuni.cz>
|
||||||
|
* 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 <linux/module.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/timex.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
@@ -351,7 +351,7 @@ ENDPROC(__aeabi_idivmod)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Ldiv0:
|
ENTRY(Ldiv0)
|
||||||
UNWIND(.fnstart)
|
UNWIND(.fnstart)
|
||||||
UNWIND(.pad #4)
|
UNWIND(.pad #4)
|
||||||
UNWIND(.save {lr})
|
UNWIND(.save {lr})
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,39 +1,252 @@
|
|||||||
obj-y += io.o idle.o timer.o
|
obj-y += io.o dma.o memory.o timer.o
|
||||||
obj-y += clock.o
|
obj-y += clock.o clock-voter.o clock-dummy.o
|
||||||
obj-$(CONFIG_DEBUG_FS) += clock-debug.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_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
|
ifdef CONFIG_ARCH_QSD8X50
|
||||||
obj-$(CONFIG_ARCH_MSM7X30) += dma.o
|
obj-$(CONFIG_MSM_SOC_REV_NONE) += acpuclock-8x50.o
|
||||||
obj-$(CONFIG_ARCH_QSD8X50) += dma.o sirc.o
|
endif
|
||||||
|
|
||||||
obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
|
|
||||||
obj-$(CONFIG_MSM_SMD) += last_radio_log.o
|
|
||||||
obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
|
||||||
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
|
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
|
||||||
|
|
||||||
obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
|
obj-$(CONFIG_MSM_CPU_AVS) += avs.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_MSM_AVS_HW) += avs_hw.o
|
||||||
obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
|
obj-$(CONFIG_CPU_V6) += idle-v6.o
|
||||||
obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
|
obj-$(CONFIG_CPU_V7) += idle-v7.o
|
||||||
obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
|
obj-$(CONFIG_MSM_JTAG_V7) += jtag-v7.o
|
||||||
obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
|
|
||||||
obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.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_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_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_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
|
||||||
|
|
||||||
|
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_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
|
||||||
obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.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
|
ifdef CONFIG_MSM_V2_TLMM
|
||||||
ifndef CONFIG_ARCH_MSM8960
|
|
||||||
# TODO: TLMM Mapping issues need to be resolved
|
|
||||||
obj-y += gpio-v2.o
|
obj-y += gpio-v2.o
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
obj-y += gpio.o
|
obj-y += gpio.o
|
||||||
endif
|
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
|
||||||
|
|||||||
@@ -1,3 +1,44 @@
|
|||||||
zreladdr-y := 0x10008000
|
# MSM7x01A
|
||||||
params_phys-y := 0x10000100
|
zreladdr-$(CONFIG_ARCH_MSM7X01A) := 0x10008000
|
||||||
initrd_phys-y := 0x10800000
|
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
|
||||||
|
|||||||
502
arch/arm/mach-msm/acpuclock-7x30.c
Normal file
502
arch/arm/mach-msm/acpuclock-7x30.c
Normal file
@@ -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 <linux/version.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/cpufreq.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/sort.h>
|
||||||
|
#include <mach/board.h>
|
||||||
|
#include <mach/msm_iomap.h>
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
||||||
969
arch/arm/mach-msm/acpuclock-8960.c
Normal file
969
arch/arm/mach-msm/acpuclock-8960.c
Normal file
@@ -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 <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/cpufreq.h>
|
||||||
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
#include <asm/cpu.h>
|
||||||
|
|
||||||
|
#include <mach/board.h>
|
||||||
|
#include <mach/msm_iomap.h>
|
||||||
|
#include <mach/rpm-regulator.h>
|
||||||
|
#include <mach/msm_bus.h>
|
||||||
|
#include <mach/msm_bus_board.h>
|
||||||
|
#include <mach/socinfo.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
723
arch/arm/mach-msm/acpuclock-8x50.c
Normal file
723
arch/arm/mach-msm/acpuclock-8x50.c
Normal file
@@ -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 <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/cpufreq.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
|
||||||
|
#include <mach/board.h>
|
||||||
|
#include <mach/msm_iomap.h>
|
||||||
|
|
||||||
|
#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
|
||||||
|
}
|
||||||
965
arch/arm/mach-msm/acpuclock-8x60.c
Normal file
965
arch/arm/mach-msm/acpuclock-8x60.c
Normal file
@@ -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 <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/cpufreq.h>
|
||||||
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/regulator/consumer.h>
|
||||||
|
|
||||||
|
#include <asm/cpu.h>
|
||||||
|
|
||||||
|
#include <mach/board.h>
|
||||||
|
#include <mach/msm_iomap.h>
|
||||||
|
#include <mach/msm_bus.h>
|
||||||
|
#include <mach/msm_bus_board.h>
|
||||||
|
#include <mach/socinfo.h>
|
||||||
|
#include <mach/rpm-regulator.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/version.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
@@ -97,7 +98,7 @@ struct clkctl_acpu_speed {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* ACPU speed table. Complete table is shown but certain speeds are commented
|
* 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
|
* Table stepping up/down is optimized for 256mhz jumps while staying on the
|
||||||
* same PLL.
|
* same PLL.
|
||||||
@@ -493,7 +494,7 @@ uint32_t acpuclk_get_switch_time(void)
|
|||||||
* Clock driver initialization
|
* 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)
|
static void __init lpj_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
42
arch/arm/mach-msm/acpuclock-fsm9xxx.c
Normal file
42
arch/arm/mach-msm/acpuclock-fsm9xxx.c
Normal file
@@ -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 <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <mach/board.h>
|
||||||
|
|
||||||
|
#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));
|
||||||
|
}
|
||||||
1046
arch/arm/mach-msm/acpuclock.c
Normal file
1046
arch/arm/mach-msm/acpuclock.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
|||||||
* MSM architecture clock driver header
|
* MSM architecture clock driver header
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 Google, Inc.
|
* Copyright (C) 2007 Google, Inc.
|
||||||
* Copyright (c) 2007 QUALCOMM Incorporated
|
* Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
|
||||||
* Author: San Mehat <san@android.com>
|
* Author: San Mehat <san@android.com>
|
||||||
*
|
*
|
||||||
* This software is licensed under the terms of the GNU General Public
|
* This software is licensed under the terms of the GNU General Public
|
||||||
@@ -20,13 +20,25 @@
|
|||||||
#ifndef __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
|
#ifndef __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
|
||||||
#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
|
#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
|
||||||
|
|
||||||
int acpuclk_set_rate(unsigned long rate, int for_power_collapse);
|
#include <linux/list.h>
|
||||||
unsigned long acpuclk_get_rate(void);
|
|
||||||
|
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);
|
uint32_t acpuclk_get_switch_time(void);
|
||||||
unsigned long acpuclk_wait_for_irq(void);
|
unsigned long acpuclk_wait_for_irq(void);
|
||||||
unsigned long acpuclk_power_collapse(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
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
483
arch/arm/mach-msm/arch-init-scorpion.S
Normal file
483
arch/arm/mach-msm/arch-init-scorpion.S
Normal file
@@ -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
|
||||||
280
arch/arm/mach-msm/avs.c
Normal file
280
arch/arm/mach-msm/avs.c
Normal file
@@ -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 <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/kernel_stat.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
69
arch/arm/mach-msm/avs.h
Normal file
69
arch/arm/mach-msm/avs.h
Normal file
@@ -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 */
|
||||||
127
arch/arm/mach-msm/avs_hw.S
Normal file
127
arch/arm/mach-msm/avs_hw.S
Normal file
@@ -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
|
||||||
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user