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:
Bryan Huntsman
2011-08-16 17:27:22 -07:00
parent f06154cc47
commit 3f2bc4d6eb
1851 changed files with 780136 additions and 12902 deletions

64
AndroidKernel.mk Normal file
View 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

View File

@@ -96,6 +96,7 @@
<listitem><para>debug_object_deactivate</para></listitem>
<listitem><para>debug_object_destroy</para></listitem>
<listitem><para>debug_object_free</para></listitem>
<listitem><para>debug_object_assert_init</para></listitem>
</itemizedlist>
Each of these functions takes the address of the real object and
a pointer to the object type specific debug description
@@ -273,6 +274,26 @@
debug checks.
</para>
</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 id="fixupfunctions">
<title>Fixup functions</title>
@@ -381,6 +402,35 @@
statistics.
</para>
</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 id="bugs">
<title>Known Bugs And Assumptions</title>

View 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

View 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

View File

@@ -2,112 +2,79 @@ This document provides an overview of the msm_gpiomux interface, which
is used to provide gpio pin multiplexing and configuration on mach-msm
targets.
History
=======
The first-generation API for gpio configuration & multiplexing on msm
is the function gpio_tlmm_config(). This function has a few notable
shortcomings, which led to its deprecation and replacement by gpiomux:
The 'disable' parameter: Setting the second parameter to
gpio_tlmm_config to GPIO_CFG_DISABLE tells the peripheral
processor in charge of the subsystem to perform a look-up into a
low-power table and apply the low-power/sleep setting for the pin.
As the msm family evolved this became problematic. Not all pins
have sleep settings, not all peripheral processors will accept requests
to apply said sleep settings, and not all msm targets have their gpio
subsystems managed by a peripheral processor. In order to get consistent
behavior on all targets, drivers are forced to ignore this parameter,
rendering it useless.
The 'direction' flag: for all mux-settings other than raw-gpio (0),
the output-enable bit of a gpio is hard-wired to a known
input (usually VDD or ground). For those settings, the direction flag
is meaningless at best, and deceptive at worst. In addition, using the
direction flag to change output-enable (OE) directly can cause trouble in
gpiolib, which has no visibility into gpio direction changes made
in this way. Direction control in gpio mode should be made through gpiolib.
Key Features of gpiomux
=======================
- A consistent interface across all generations of msm. Drivers can expect
the same results on every target.
- gpiomux plays nicely with gpiolib. Functions that should belong to gpiolib
are left to gpiolib and not duplicated here. gpiomux is written with the
intent that gpio_chips will call gpiomux reference-counting methods
from their request() and free() hooks, providing full integration.
- Tabular configuration. Instead of having to call gpio_tlmm_config
hundreds of times, gpio configuration is placed in a single table.
- Per-gpio sleep. Each gpio is individually reference counted, allowing only
those lines which are in use to be put in high-power states.
- 0 means 'do nothing': all flags are designed so that the default memset-zero
equates to a sensible default of 'no configuration', preventing users
from having to provide hundreds of 'no-op' configs for unused or
unwanted lines.
Usage
=====
To use gpiomux, provide configuration information for relevant gpio lines
in the msm_gpiomux_configs table. Since a 0 equates to "unconfigured",
only those lines to be managed by gpiomux need to be specified. Here
is a completely fictional example:
To use gpiomux, do the following before the msmgpio gpiochips probe:
struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
[12] = {
.active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1,
.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
},
[34] = {
.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
- Call msm_gpiomux_init to allocate needed resources.
- Install one or more sets of gpiomux configuration data via
msm_gpiomux_install and/or msm_gpiomux_write.
Failing to finish these steps before the probe of msmgpio can result in calls
from msmgpio to gpiomux to try and activate lines which have not yet
been configured.
A basic gpiomux setting is described by a gpiomux_setting structure.
A gpiomux configuration is a group of those settings (one for each power
state of the board) paired with a specific gpio, like so:
struct msm_gpiomux_config gpio123_config __initdata = {
.gpio = 123,
.settings = {
[GPIOMUX_ACTIVE] = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_NONE,
.dir = GPIOMUX_OUT_HIGH,
},
[GPIOMUX_SUSPENDED] = {
.func = GPIOMUX_FUNC_3,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_DOWN,
},
},
};
To indicate that a gpio is in use, call msm_gpiomux_get() to increase
its reference count. To decrease the reference count, call msm_gpiomux_put().
The effect of this configuration is as follows:
When the system boots, gpios 12 and 34 will be initialized with their
'suspended' configurations. All other gpios, which were left unconfigured,
will not be touched.
- When the system boots, gpio 123 will be put into the SUSPENDED setting.
- When the reference count for gpio 123 rises above 0, the ACTIVE setting
will be applied.
- When the reference count falls back to 0, the SUSPENDED setting will be
reapplied.
When msm_gpiomux_get() is called on gpio 12 to raise its reference count
above 0, its active configuration will be applied. Since no other gpio
line has a valid active configuration, msm_gpiomux_get() will have no
effect on any other line.
The reference count rises when msm_gpiomux_get() is called and falls
when msm_gpiomux_put() is called. msmgpio has hooks to these functions
in its gpiolib implementation. This means that when you call gpio_request()
on an msmgpio, msm_gpiomux_get() is automatically called on your behalf.
Similarly, when you call gpio_free(), msm_gpiomux_put() is called for you.
This allows generic drivers to obtain low-level management of msmgpio lines
without having to be aware of the gpiomux layer.
When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference
count to 0, their suspended configurations will be applied.
Since no other gpio line has a valid suspended configuration, no other
gpio line will be effected by msm_gpiomux_put(). Since gpio 34 has no valid
active configuration, this is effectively a no-op for gpio 34 as well,
with one small caveat, see the section "About Output-Enable Settings".
Note that the .dir field is ignored if .func != GPIOMUX_FUNC_GPIO, since
software control of gpios is allowed only in GPIO mode. By selecting any
other .func, you assign the gpio to another piece of hardware and lose
control of it from gpiolib. You can still reserve such gpios with gpio_request
to prevent other modules from using them while they're in such a state,
but other gpiolib functions will not behave as you expect if .func != GPIO.
All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but
they address some important issues. As unused entries (all those
except 12 and 34) are zero-filled, gpiomux needs a way to distinguish
the used fields from the unused. In addition, the all-zero pattern
is a valid configuration! Therefore, gpiomux defines an additional bit
which is used to indicate when a field is used. This has the pleasant
side-effect of allowing calls to msm_gpiomux_write to use '0' to indicate
that a value should not be changed:
msm_gpiomux_write(0, GPIOMUX_VALID, 0);
replaces the active configuration of gpio 0 with an all-zero configuration,
but leaves the suspended configuration as it was.
If a configuration is omitted, nothing will happen at the relevant transitions.
This allows for the creation of 'static configurations' which do not
change as the line is requested and freed.
Static Configurations
=====================
To install a static configuration, which is applied at boot and does
not change after that, install a configuration with a suspended component
but no active component, as in the previous example:
but no active component:
[34] = {
.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
.gpio = ...,
.settings = {
[GPIOMUX_SUSPENDED] = {
...
},
},
The suspended setting is applied during boot, and the lack of any valid
@@ -153,24 +120,3 @@ This provides important functionality:
This mechanism allows for "auto-request" of gpiomux lines via gpiolib
when it is suitable. Drivers wishing more exact control are, of course,
free to also use msm_gpiomux_set and msm_gpiomux_get.
About Output-Enable Settings
============================
Some msm targets do not have the ability to query the current gpio
configuration setting. This means that changes made to the output-enable
(OE) bit by gpiolib cannot be consistently detected and preserved by gpiomux.
Therefore, when gpiomux applies a configuration setting, any direction
settings which may have been applied by gpiolib are lost and the default
input settings are re-applied.
For this reason, drivers should not assume that gpio direction settings
continue to hold if they free and then re-request a gpio. This seems like
common sense - after all, anybody could have obtained the line in the
meantime - but it needs saying.
This also means that calls to msm_gpiomux_write will reset the OE bit,
which means that if the gpio line is held by a client of gpiolib and
msm_gpiomux_write is called, the direction setting has been lost and
gpiolib's internal state has been broken.
Release gpio lines before reconfiguring them.

View 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.

View 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.

View 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.

View 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.

View 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

View 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

View 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

View 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.

View 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
View 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.

View File

@@ -2349,6 +2349,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
1: Fast pin select (default)
2: ATC IRMode
snddev_icodec.msm_codec_i2s_slave_mode= [ARM-MSM]
1, codec is I2S master
0, MSM is I2S master (default)
softlockup_panic=
[KNL] Should the soft-lockup detector generate panics.
Format: <integer>

View File

@@ -1043,9 +1043,15 @@ conf/all/forwarding - BOOLEAN
This referred to as global forwarding.
proxy_ndp - BOOLEAN
proxy_ndp - INTEGER
Do proxy ndp.
Possible values are:
0 Proxy NDP is disabled
1 Proxy NDP is enabled
2 NDP packets are sent to userspace, where a userspace proxy
can be implemented
conf/interface/*:
Change special settings per interface.

View 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

View File

@@ -21,6 +21,7 @@ show up in /proc/sys/kernel:
- acct
- bootloader_type [ X86 only ]
- bootloader_version [ X86 only ]
- boot_reason [ ARM only ]
- callhome [ S390 only ]
- auto_msgmni
- core_pattern
@@ -126,6 +127,19 @@ Documentation/x86/boot.txt for additional information.
==============================================================
boot_reason:
ARM -- reason for device boot
A single bit will be set in the unsigned integer value to identify the
reason the device was booted / powered on. The value will be zero if this
feature is not supported on the ARM device being booted.
See the power-on-status field definitions in
Documentation/arm/msm/boot.txt for Qualcomm's family of devices.
==============================================================
callhome:
Controls the kernel's callhome behavior in case of a kernel panic.

181
Documentation/tzcom.txt Normal file
View 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

View 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

View 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.

View 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).

View 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.

View 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.

View File

@@ -330,7 +330,7 @@ include $(srctree)/scripts/Kbuild.include
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
REAL_CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
@@ -345,6 +345,10 @@ KALLSYMS = scripts/kallsyms
PERL = perl
CHECK = sparse
# Use the wrapper for the compiler. This wrapper scans for new
# warnings and causes the build to stop upon encountering them.
CC = $(srctree)/scripts/gcc-wrapper.py $(REAL_CC)
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
-Wbitwise -Wno-return-void $(CF)
CFLAGS_MODULE =

View File

@@ -148,6 +148,13 @@ config HAVE_HW_BREAKPOINT
bool
depends on PERF_EVENTS
config HAVE_HW_BRKPT_RESERVED_RW_ACCESS
bool
depends on HAVE_HW_BREAKPOINT
help
Some of the hardware might not have r/w access beyond a certain number
of breakpoint register access.
config HAVE_MIXED_BREAKPOINTS_REGS
bool
depends on HAVE_HW_BREAKPOINT

View File

@@ -62,7 +62,7 @@ config GENERIC_CLOCKEVENTS
config GENERIC_CLOCKEVENTS_BROADCAST
bool
depends on GENERIC_CLOCKEVENTS
default y if SMP
default y if SMP && !LOCAL_TIMERS
config KTIME_SCALAR
bool
@@ -627,6 +627,10 @@ config ARCH_MSM
select GENERIC_CLOCKEVENTS
select ARCH_REQUIRE_GPIOLIB
select CLKDEV_LOOKUP
select ARCH_HAS_CPUFREQ
select GENERIC_GPIO
select GENERIC_TIME
select GENERIC_ALLOCATOR
help
Support for Qualcomm MSM/QSD based systems. This runs on the
apps processor of the MSM/QSD and depends on a shared memory
@@ -1033,6 +1037,19 @@ config ARM_TIMER_SP804
source arch/arm/mm/Kconfig
config DONT_RESERVE_FROM_MOVABLE_ZONE
def_bool y
depends on MEMORY_HOTPLUG
config RESERVE_FIRST_PAGE
bool
default n
help
Reserve the first page at PHYS_OFFSET. The first
physical page is used by many platforms for warm
boot operations. Reserve this page so that it is
not allocated by the kernel.
config IWMMXT
bool "Enable iWMMXt support"
depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
@@ -1234,6 +1251,29 @@ config ARM_ERRATA_754327
This workaround defines cpu_relax() as smp_mb(), preventing correctly
written polling loops from denying visibility of updates to memory.
config PL310_ERRATA_727915
bool "Background Clean & Invalidate by Way operation can cause data corruption"
depends on CACHE_L2X0
help
PL310 implements the Clean & Invalidate by Way L2 cache maintenance
operation (offset 0x7FC). This operation runs in background so that
PL310 can handle normal accesses while it is in progress. Under very
rare circumstances, due to this erratum, write data can be lost when
PL310 treats a cacheable write transaction during a Clean &
Invalidate by Way operation.
config KSAPI
tristate "KSAPI support (EXPERIMENTAL)"
depends on ARCH_MSM_SCORPION || ARCH_MSM_KRAIT
default n
help
KSAPI: Performance monitoring tool for linux.
KSAPI records performance statistics for Snapdragon linux platform.
It uses the /proc FS as a means to exchange configuration data and
counter statistics. It can monitor the counter statistics for
Scorpion processor supported hardware performance counters on a per
thread basis or AXI counters on an overall system basis.
endmenu
source "arch/arm/common/Kconfig"
@@ -1311,9 +1351,9 @@ config SMP
depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
MSM_SMP || ARCH_SHMOBILE
select USE_GENERIC_SMP_HELPERS
select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
select HAVE_ARM_SCU if !MSM_SMP
help
This enables support for systems with more than one CPU. If you have
a system with only one CPU, like most personal computers, say N. If
@@ -1395,9 +1435,11 @@ config HOTPLUG_CPU
config LOCAL_TIMERS
bool "Use local timer interrupts"
depends on SMP
depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || ARCH_U8500 || \
MSM_SMP)
default y
select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
select HAVE_ARM_TWD if (!MSM_SMP && !EXYNOS4_MCT)
help
Enable support for local timers on SMP platforms, rather then the
legacy IPI broadcast method. Local timers allows the system
@@ -1537,8 +1579,26 @@ config HW_PERF_EVENTS
Enable hardware performance counter support for perf events. If
disabled, perf events will use software events only.
config VMALLOC_RESERVE
hex "Reserved vmalloc space"
default 0x08000000
depends on MMU
help
Reserved vmalloc space if not specified on the kernel commandline.
source "mm/Kconfig"
config ARCH_MEMORY_PROBE
def_bool n
depends on MEMORY_HOTPLUG
config ARCH_MEMORY_REMOVE
def_bool n
depends on MEMORY_HOTPLUG
config DONT_RESERVE_FROM_MOVABLE_ZONE
def_bool n
config FORCE_MAX_ZONEORDER
int "Maximum zone order" if ARCH_SHMOBILE
range 11 64 if ARCH_SHMOBILE
@@ -1680,6 +1740,17 @@ config ARM_FLUSH_CONSOLE_ON_RESTART
released if it failed to be acquired, which will cause all the
pending messages to be flushed.
config CP_ACCESS
tristate "CP register access tool"
default m
help
Provide support for Coprocessor register access using /sys
interface. Read and write to CP registers from userspace
through sysfs interface. A sys file (cp_rw) will be created under
/sys/devices/system/cpaccess/cpaccess0.
If unsure, say N.
endmenu
menu "Boot options"
@@ -1940,6 +2011,14 @@ source "drivers/cpuidle/Kconfig"
endmenu
config CPU_FREQ_MSM
bool
depends on CPU_FREQ && ARCH_MSM
default y
help
This enables the CPUFreq driver for Qualcomm CPUs.
If in doubt, say Y.
menu "Floating point emulation"
comment "At least one emulation must be selected"
@@ -2029,7 +2108,7 @@ menu "Power management options"
source "kernel/power/Kconfig"
config ARCH_SUSPEND_POSSIBLE
depends on !ARCH_S5P64X0 && !ARCH_S5PC100
depends on !ARCH_S5P64X0 && !ARCH_S5PC100 && !ARCH_FSM9XXX
depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
def_bool y

View File

@@ -255,6 +255,7 @@ core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y += $(machdirs) $(platdirs)
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
core-y += arch/arm/perfmon/
libs-y := arch/arm/lib/ $(libs-y)

View File

@@ -27,6 +27,14 @@
.macro writeb, ch, rb
mcr p14, 0, \ch, c0, c5, 0
.endm
#elif defined(CONFIG_CPU_V7)
.macro loadsp, rb, tmp
.endm
.macro writeb, ch, rb
wait: mrc p14, 0, pc, c0, c1, 0
bcs wait
mcr p14, 0, \ch, c0, c5, 0
.endm
#elif defined(CONFIG_CPU_XSCALE)
.macro loadsp, rb, tmp
.endm

View File

@@ -1,5 +1,6 @@
config ARM_GIC
bool
select MSM_SHOW_RESUME_IRQ
config ARM_VIC
bool

253
arch/arm/common/cpaccess.c Normal file
View 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");

View File

@@ -28,10 +28,12 @@
#include <linux/smp.h>
#include <linux/cpumask.h>
#include <linux/io.h>
#include <linux/syscore_ops.h>
#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>
#include <asm/system.h>
static DEFINE_SPINLOCK(irq_controller_lock);
@@ -42,6 +44,11 @@ struct gic_chip_data {
unsigned int irq_offset;
void __iomem *dist_base;
void __iomem *cpu_base;
unsigned int max_irq;
#ifdef CONFIG_PM
unsigned int wakeup_irqs[32];
unsigned int enabled_irqs[32];
#endif
};
/*
@@ -55,6 +62,7 @@ struct irq_chip gic_arch_extn = {
.irq_retrigger = NULL,
.irq_set_type = NULL,
.irq_set_wake = NULL,
.irq_disable = NULL,
};
#ifndef MAX_GIC_NR
@@ -93,6 +101,7 @@ static void gic_mask_irq(struct irq_data *d)
if (gic_arch_extn.irq_mask)
gic_arch_extn.irq_mask(d);
spin_unlock(&irq_controller_lock);
}
static void gic_unmask_irq(struct irq_data *d)
@@ -106,6 +115,104 @@ static void gic_unmask_irq(struct irq_data *d)
spin_unlock(&irq_controller_lock);
}
static void gic_disable_irq(struct irq_data *d)
{
if (gic_arch_extn.irq_disable)
gic_arch_extn.irq_disable(d);
}
#ifdef CONFIG_PM
static int gic_suspend_one(struct gic_chip_data *gic)
{
unsigned int i;
void __iomem *base = gic->dist_base;
for (i = 0; i * 32 < gic->max_irq; i++) {
gic->enabled_irqs[i]
= readl_relaxed(base + GIC_DIST_ENABLE_SET + i * 4);
/* disable all of them */
writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4);
/* enable the wakeup set */
writel_relaxed(gic->wakeup_irqs[i],
base + GIC_DIST_ENABLE_SET + i * 4);
}
mb();
return 0;
}
static int gic_suspend(void)
{
int i;
for (i = 0; i < MAX_GIC_NR; i++)
gic_suspend_one(&gic_data[i]);
return 0;
}
extern int msm_show_resume_irq_mask;
static void gic_show_resume_irq(struct gic_chip_data *gic)
{
unsigned int i;
u32 enabled;
unsigned long pending[32];
void __iomem *base = gic->dist_base;
if (!msm_show_resume_irq_mask)
return;
spin_lock(&irq_controller_lock);
for (i = 0; i * 32 < gic->max_irq; i++) {
enabled = readl_relaxed(base + GIC_DIST_ENABLE_CLEAR + i * 4);
pending[i] = readl_relaxed(base + GIC_DIST_PENDING_SET + i * 4);
pending[i] &= enabled;
}
spin_unlock(&irq_controller_lock);
for (i = find_first_bit(pending, gic->max_irq);
i < gic->max_irq;
i = find_next_bit(pending, gic->max_irq, i+1)) {
pr_warning("%s: %d triggered", __func__,
i + gic->irq_offset);
}
}
static void gic_resume_one(struct gic_chip_data *gic)
{
unsigned int i;
void __iomem *base = gic->dist_base;
gic_show_resume_irq(gic);
for (i = 0; i * 32 < gic->max_irq; i++) {
/* disable all of them */
writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4);
/* enable the enabled set */
writel_relaxed(gic->enabled_irqs[i],
base + GIC_DIST_ENABLE_SET + i * 4);
}
mb();
}
static void gic_resume(void)
{
int i;
for (i = 0; i < MAX_GIC_NR; i++)
gic_resume_one(&gic_data[i]);
}
static struct syscore_ops gic_syscore_ops = {
.suspend = gic_suspend,
.resume = gic_resume,
};
static int __init gic_init_sys(void)
{
register_syscore_ops(&gic_syscore_ops);
return 0;
}
arch_initcall(gic_init_sys);
#endif
static void gic_eoi_irq(struct irq_data *d)
{
if (gic_arch_extn.irq_eoi) {
@@ -202,6 +309,20 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
static int gic_set_wake(struct irq_data *d, unsigned int on)
{
int ret = -ENXIO;
unsigned int reg_offset, bit_offset;
unsigned int gicirq = gic_irq(d);
struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
/* per-cpu interrupts cannot be wakeup interrupts */
WARN_ON(gicirq < 32);
reg_offset = gicirq / 32;
bit_offset = gicirq % 32;
if (on)
gic_data->wakeup_irqs[reg_offset] |= 1 << bit_offset;
else
gic_data->wakeup_irqs[reg_offset] &= ~(1 << bit_offset);
if (gic_arch_extn.irq_set_wake)
ret = gic_arch_extn.irq_set_wake(d, on);
@@ -250,6 +371,7 @@ static struct irq_chip gic_chip = {
#ifdef CONFIG_SMP
.irq_set_affinity = gic_set_affinity,
#endif
.irq_disable = gic_disable_irq,
.irq_set_wake = gic_set_wake,
};
@@ -324,7 +446,10 @@ static void __init gic_dist_init(struct gic_chip_data *gic,
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
gic->max_irq = gic_irqs;
writel_relaxed(1, base + GIC_DIST_CTRL);
mb();
}
static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
@@ -348,6 +473,7 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
writel_relaxed(1, base + GIC_CPU_CTRL);
mb();
}
void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
@@ -399,5 +525,47 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
/* this always happens on GIC0 */
writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
mb();
}
#endif
/* before calling this function the interrupts should be disabled
* and the irq must be disabled at gic to avoid spurious interrupts */
bool gic_is_spi_pending(unsigned int irq)
{
struct irq_data *d = irq_get_irq_data(irq);
struct gic_chip_data *gic_data = &gic_data[0];
u32 mask, val;
WARN_ON(!irqs_disabled());
spin_lock(&irq_controller_lock);
mask = 1 << (gic_irq(d) % 32);
val = readl(gic_dist_base(d) +
GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
/* warn if the interrupt is enabled */
WARN_ON(val & mask);
val = readl(gic_dist_base(d) +
GIC_DIST_PENDING_SET + (gic_irq(d) / 32) * 4);
spin_unlock(&irq_controller_lock);
return (bool) (val & mask);
}
/* before calling this function the interrupts should be disabled
* and the irq must be disabled at gic to avoid spurious interrupts */
void gic_clear_spi_pending(unsigned int irq)
{
struct gic_chip_data *gic_data = &gic_data[0];
struct irq_data *d = irq_get_irq_data(irq);
u32 mask, val;
WARN_ON(!irqs_disabled());
spin_lock(&irq_controller_lock);
mask = 1 << (gic_irq(d) % 32);
val = readl(gic_dist_base(d) +
GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
/* warn if the interrupt is enabled */
WARN_ON(val & mask);
writel(mask, gic_dist_base(d) +
GIC_DIST_PENDING_CLEAR + (gic_irq(d) / 32) * 4);
spin_unlock(&irq_controller_lock);
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -87,6 +87,21 @@
* DMA Cache Coherency
* ===================
*
* dma_inv_range(start, end)
*
* Invalidate (discard) the specified virtual address range.
* May not write back any entries. If 'start' or 'end'
* are not cache line aligned, those lines must be written
* back.
* - start - virtual start address
* - end - virtual end address
*
* dma_clean_range(start, end)
*
* Clean (write back) the specified virtual address range.
* - start - virtual start address
* - end - virtual end address
*
* dma_flush_range(start, end)
*
* Clean and invalidate the specified virtual address range.
@@ -107,6 +122,8 @@ struct cpu_cache_fns {
void (*dma_map_area)(const void *, size_t, int);
void (*dma_unmap_area)(const void *, size_t, int);
void (*dma_inv_range)(const void *, const void *);
void (*dma_clean_range)(const void *, const void *);
void (*dma_flush_range)(const void *, const void *);
};
@@ -133,6 +150,8 @@ extern struct cpu_cache_fns cpu_cache;
*/
#define dmac_map_area cpu_cache.dma_map_area
#define dmac_unmap_area cpu_cache.dma_unmap_area
#define dmac_inv_range cpu_cache.dma_inv_range
#define dmac_clean_range cpu_cache.dma_clean_range
#define dmac_flush_range cpu_cache.dma_flush_range
#else
@@ -153,6 +172,8 @@ extern void __cpuc_flush_dcache_area(void *, size_t);
*/
extern void dmac_map_area(const void *, size_t, int);
extern void dmac_unmap_area(const void *, size_t, int);
extern void dmac_inv_range(const void *, const void *);
extern void dmac_clean_range(const void *, const void *);
extern void dmac_flush_range(const void *, const void *);
#endif

View File

@@ -8,6 +8,7 @@
#define CPUID_CACHETYPE 1
#define CPUID_TCM 2
#define CPUID_TLBTYPE 3
#define CPUID_MPIDR 5
#define CPUID_EXT_PFR0 "c1, 0"
#define CPUID_EXT_PFR1 "c1, 1"
@@ -70,6 +71,11 @@ static inline unsigned int __attribute_const__ read_cpuid_tcmstatus(void)
return read_cpuid(CPUID_TCM);
}
static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
{
return read_cpuid(CPUID_MPIDR);
}
/*
* Intel's XScale3 core supports some v6 features (supersections, L2)
* but advertises itself as v5 as it does not support the v6 ISA. For

View File

@@ -8,7 +8,7 @@
#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
@@ -40,5 +40,8 @@ extern void __const_udelay(unsigned long);
__const_udelay((n) * ((2199023U*HZ)>>11))) : \
__udelay(n))
extern void set_delay_fn(void (*fn)(unsigned long));
extern void read_current_timer_delay_loop(unsigned long loops);
#endif /* defined(_ARM_DELAY_H) */

View File

@@ -172,6 +172,46 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size,
{
}
/*
* dma_coherent_pre_ops - barrier functions for coherent memory before DMA.
* A barrier is required to ensure memory operations are complete before the
* initiation of a DMA xfer.
* If the coherent memory is Strongly Ordered
* - pre ARMv7 and 8x50 guarantees ordering wrt other mem accesses
* - ARMv7 guarantees ordering only within a 1KB block, so we need a barrier
* If coherent memory is normal then we need a barrier to prevent
* reordering
*/
static inline void dma_coherent_pre_ops(void)
{
#if COHERENT_IS_NORMAL == 1
dmb();
#else
if (arch_is_coherent())
dmb();
else
barrier();
#endif
}
/*
* dma_post_coherent_ops - barrier functions for coherent memory after DMA.
* If the coherent memory is Strongly Ordered we dont need a barrier since
* there are no speculative fetches to Strongly Ordered memory.
* If coherent memory is normal then we need a barrier to prevent reordering
*/
static inline void dma_coherent_post_ops(void)
{
#if COHERENT_IS_NORMAL == 1
dmb();
#else
if (arch_is_coherent())
dmb();
else
barrier();
#endif
}
/**
* dma_alloc_coherent - allocate consistent memory for DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -385,6 +425,58 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
return addr;
}
/**
* dma_cache_pre_ops - clean or invalidate cache before dma transfer is
* initiated and perform a barrier operation.
* @virtual_addr: A kernel logical or kernel virtual address
* @size: size of buffer to map
* @dir: DMA transfer direction
*
* Ensure that any data held in the cache is appropriately discarded
* or written back.
*
*/
static inline void dma_cache_pre_ops(void *virtual_addr,
size_t size, enum dma_data_direction dir)
{
extern void ___dma_single_cpu_to_dev(const void *, size_t,
enum dma_data_direction);
BUG_ON(!valid_dma_direction(dir));
if (!arch_is_coherent())
___dma_single_cpu_to_dev(virtual_addr, size, dir);
}
/**
* dma_cache_post_ops - clean or invalidate cache after dma transfer is
* initiated and perform a barrier operation.
* @virtual_addr: A kernel logical or kernel virtual address
* @size: size of buffer to map
* @dir: DMA transfer direction
*
* Ensure that any data held in the cache is appropriately discarded
* or written back.
*
*/
static inline void dma_cache_post_ops(void *virtual_addr,
size_t size, enum dma_data_direction dir)
{
extern void ___dma_single_cpu_to_dev(const void *, size_t,
enum dma_data_direction);
BUG_ON(!valid_dma_direction(dir));
if (arch_has_speculative_dfetch() && !arch_is_coherent()
&& dir != DMA_TO_DEVICE)
/*
* Treat DMA_BIDIRECTIONAL and DMA_FROM_DEVICE
* identically: invalidate
*/
___dma_single_cpu_to_dev(virtual_addr,
size, DMA_FROM_DEVICE);
}
/**
* dma_map_page - map a portion of a page for streaming DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices

View File

@@ -2,6 +2,7 @@
* arch/arm/include/asm/domain.h
*
* Copyright (C) 1999 Russell King.
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -27,8 +28,13 @@
*
* 36-bit addressing and supersections are only available on
* CPUs based on ARMv6+ or the Intel XSC3 core.
*
* We cannot use domain 0 for the kernel on QSD8x50 since the kernel domain
* is set to manager mode when set_fs(KERNEL_DS) is called. Setting domain 0
* to manager mode will disable the workaround for a cpu bug that can cause an
* invalid fault status and/or tlb corruption (CONFIG_VERIFY_PERMISSION_FAULT).
*/
#ifndef CONFIG_IO_36
#if !defined(CONFIG_IO_36) && !defined(CONFIG_VERIFY_PERMISSION_FAULT)
#define DOMAIN_KERNEL 0
#define DOMAIN_TABLE 0
#define DOMAIN_USER 1
@@ -56,6 +62,17 @@
#ifndef __ASSEMBLY__
#ifdef CONFIG_CPU_USE_DOMAINS
#ifdef CONFIG_EMULATE_DOMAIN_MANAGER_V7
void emulate_domain_manager_set(u32 domain);
int emulate_domain_manager_data_abort(u32 dfsr, u32 dfar);
int emulate_domain_manager_prefetch_abort(u32 ifsr, u32 ifar);
void emulate_domain_manager_switch_mm(
unsigned long pgd_phys,
struct mm_struct *mm,
void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *));
#define set_domain(x) emulate_domain_manager_set(x)
#else
#define set_domain(x) \
do { \
__asm__ __volatile__( \
@@ -63,6 +80,7 @@
: : "r" (x)); \
isb(); \
} while (0)
#endif
#define modify_domain(dom,type) \
do { \

View File

@@ -59,6 +59,7 @@
/* Registers shifts and masks */
#define L2X0_CACHE_ID_PART_MASK (0xf << 6)
#define L2X0_CACHE_ID_PART_L210 (1 << 6)
#define L2X0_CACHE_ID_PART_L220 (2 << 6)
#define L2X0_CACHE_ID_PART_L310 (3 << 6)
#define L2X0_AUX_CTRL_MASK 0xc0000fff
@@ -71,9 +72,13 @@
#define L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT 28
#define L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT 29
#define L2X0_AUX_CTRL_EARLY_BRESP_SHIFT 30
#define L2X0_AUX_CTRL_EVNT_MON_BUS_EN_SHIFT 20
#ifndef __ASSEMBLY__
extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
extern void l2x0_suspend(void);
extern void l2x0_resume(int collapsed);
extern void l2x0_cache_sync(void);
#endif
#endif

View File

@@ -41,6 +41,8 @@ void gic_secondary_init(unsigned int);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
void gic_enable_ppi(unsigned int);
bool gic_is_spi_pending(unsigned int irq);
void gic_clear_spi_pending(unsigned int irq);
#endif
#endif

View File

@@ -248,6 +248,8 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
#define ioremap(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_nocache(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE)
#define ioremap_strongly_ordered(cookie, size) __arch_ioremap(cookie, size, \
MT_DEVICE_STRONGLY_ORDERED)
#define ioremap_cached(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
#define ioremap_wc(cookie,size) __arch_ioremap((cookie), (size), MT_DEVICE_WC)
#define iounmap __arch_iounmap

View File

@@ -17,6 +17,7 @@ struct mtd_info;
* map_name: the map probe function name
* name: flash device name (eg, as used with mtdparts=)
* width: width of mapped device
* interleave: interleave mode feature support
* init: method called at driver/device initialisation
* exit: method called at driver/device removal
* set_vpp: method called to enable or disable VPP
@@ -28,6 +29,7 @@ struct flash_platform_data {
const char *map_name;
const char *name;
unsigned int width;
unsigned int interleave;
int (*init)(void);
void (*exit)(void);
void (*set_vpp)(int on);

View File

@@ -29,6 +29,10 @@ struct map_desc {
#define MT_MEMORY_NONCACHED 11
#define MT_MEMORY_DTCM 12
#define MT_MEMORY_ITCM 13
#define MT_DEVICE_STRONGLY_ORDERED 14
#define MT_MEMORY_R 15
#define MT_MEMORY_RW 16
#define MT_MEMORY_RX 17
#ifdef CONFIG_MMU
extern void iotable_init(struct map_desc *, int);

View File

@@ -7,6 +7,12 @@
#include <linux/mmc/host.h>
#include <linux/mmc/card.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 sdio_cis cis;
@@ -15,6 +21,91 @@ struct embedded_sdio_data {
int num_funcs;
};
/* This structure keeps information per regulator */
struct msm_mmc_reg_data {
/* voltage regulator handle */
struct regulator *reg;
/* regulator name */
const char *name;
/* voltage level to be set */
unsigned int level;
/* Load values for low power and high power mode */
unsigned int lpm_uA;
unsigned int hpm_uA;
/*
* is set voltage supported for this regulator?
* false => set voltage is not supported
* true => set voltage is supported
*/
bool set_voltage_sup;
/* is this regulator enabled? */
bool is_enabled;
/* is this regulator needs to be always on? */
bool always_on;
/* is low power mode setting required for this regulator? */
bool lpm_sup;
};
/*
* This structure keeps information for all the
* regulators required for a SDCC slot.
*/
struct msm_mmc_slot_reg_data {
struct msm_mmc_reg_data *vdd_data; /* keeps VDD/VCC regulator info */
struct msm_mmc_reg_data *vccq_data; /* keeps VCCQ regulator info */
struct msm_mmc_reg_data *vddp_data; /* keeps VDD Pad regulator info */
};
struct msm_mmc_gpio {
u32 no;
const char *name;
bool is_always_on;
bool is_enabled;
};
struct msm_mmc_gpio_data {
struct msm_mmc_gpio *gpio;
u8 size;
};
struct msm_mmc_pad_pull {
enum msm_tlmm_pull_tgt no;
u32 val;
};
struct msm_mmc_pad_pull_data {
struct msm_mmc_pad_pull *on;
struct msm_mmc_pad_pull *off;
u8 size;
};
struct msm_mmc_pad_drv {
enum msm_tlmm_hdrive_tgt no;
u32 val;
};
struct msm_mmc_pad_drv_data {
struct msm_mmc_pad_drv *on;
struct msm_mmc_pad_drv *off;
u8 size;
};
struct msm_mmc_pad_data {
struct msm_mmc_pad_pull_data *pull;
struct msm_mmc_pad_drv_data *drv;
};
struct msm_mmc_pin_data {
/*
* = 1 if controller pins are using gpios
* = 0 if controller has dedicated MSM pads
*/
u8 is_gpio;
u8 cfg_sts;
struct msm_mmc_gpio_data *gpio_data;
struct msm_mmc_pad_data *pad_data;
};
struct mmc_platform_data {
unsigned int ocr_mask; /* available voltages */
int built_in; /* built-in device flag */
@@ -23,6 +114,35 @@ struct mmc_platform_data {
unsigned int (*status)(struct device *);
struct embedded_sdio_data *embedded_sdio;
int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
/*
* XPC controls the maximum current in the
* default speed mode of SDXC card.
*/
unsigned int xpc_cap;
/* Supported UHS-I Modes */
unsigned int uhs_caps;
void (*sdio_lpm_gpio_setup)(struct device *, unsigned int);
unsigned int status_irq;
unsigned int status_gpio;
unsigned int sdiowakeup_irq;
unsigned long irq_flags;
unsigned long mmc_bus_width;
int (*wpswitch) (struct device *);
int dummy52_required;
unsigned int msmsdcc_fmin;
unsigned int msmsdcc_fmid;
unsigned int msmsdcc_fmax;
bool nonremovable;
bool pclk_src_dfab;
int (*cfg_mpm_sdiowakeup)(struct device *, unsigned);
bool sdcc_v4_sup;
unsigned int wpswitch_gpio;
unsigned char wpswitch_polarity;
struct msm_mmc_slot_reg_data *vreg_data;
int is_sdio_al_client;
unsigned int *sup_clk_table;
unsigned char sup_clk_cnt;
struct msm_mmc_pin_data *pin_data;
};
#endif

View File

@@ -299,6 +299,13 @@ static inline __deprecated void *bus_to_virt(unsigned long x)
#define arch_is_coherent() 0
#endif
/*
* Set if the architecture speculatively fetches data into cache.
*/
#ifndef arch_has_speculative_dfetch
#define arch_has_speculative_dfetch() 0
#endif
#endif
#include <asm-generic/memory_model.h>

View File

@@ -41,6 +41,8 @@ __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
__res |= __ex_flag;
if (unlikely(__res != 0))
fail_fn(count);
else
smp_rmb();
}
static inline int
@@ -61,6 +63,9 @@ __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *))
__res |= __ex_flag;
if (unlikely(__res != 0))
__res = fail_fn(count);
else
smp_rmb();
return __res;
}
@@ -74,6 +79,7 @@ __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
{
int __ex_flag, __res, __orig;
smp_wmb();
__asm__ (
"ldrex %0, [%3] \n\t"
@@ -119,6 +125,8 @@ __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *))
: "=&r" (__orig), "=&r" (__res), "=&r" (__ex_flag)
: "r" (&count->counter)
: "cc", "memory" );
if (__orig)
smp_rmb();
return __orig;
}

View File

@@ -201,6 +201,11 @@ typedef struct page *pgtable_t;
extern int pfn_valid(unsigned long);
#endif
#ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
extern int _early_pfn_valid(unsigned long);
#define early_pfn_valid(pfn) (_early_pfn_valid(pfn))
#endif
#include <asm/memory.h>
#endif /* !__ASSEMBLY__ */

View File

@@ -24,6 +24,9 @@ enum arm_perf_pmu_ids {
ARM_PERF_PMU_ID_V6MP,
ARM_PERF_PMU_ID_CA8,
ARM_PERF_PMU_ID_CA9,
ARM_PERF_PMU_ID_SCORPION,
ARM_PERF_PMU_ID_SCORPIONMP,
ARM_PERF_PMU_ID_KRAIT,
ARM_NUM_PMU_IDS,
};

View 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

View File

@@ -22,7 +22,9 @@
#include <asm/memory.h>
#include <mach/vmalloc.h>
#include <mach/memory.h>
#include <asm/pgtable-hwdef.h>
#include <asm/tlbflush.h>
/*
* Just any arbitrary offset to the start of the vmalloc VM area: the
@@ -232,16 +234,30 @@ extern pgprot_t pgprot_kernel;
#define pgprot_writecombine(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
#define pgprot_device(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_DEV_NONSHARED)
#define pgprot_writethroughcache(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_WRITETHROUGH)
#define pgprot_writebackcache(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_WRITEBACK)
#define pgprot_writebackwacache(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_WRITEALLOC)
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
#define pgprot_dmacoherent(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
#define __HAVE_PHYS_MEM_ACCESS_PROT
#define COHERENT_IS_NORMAL 1
struct file;
extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t vma_prot);
#else
#define pgprot_dmacoherent(prot) \
__pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
#define COHERENT_IS_NORMAL 0
#endif
#endif /* __ASSEMBLY__ */
@@ -469,8 +485,15 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
* remap a physical page `pfn' of size `size' with page protection `prot'
* into virtual address `from'
*/
#ifndef HAS_ARCH_IO_REMAP_PFN_RANGE
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
remap_pfn_range(vma, from, pfn, size, prot)
remap_pfn_range(vma,from,pfn,size,prot)
#else
extern int arch_io_remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot);
#define io_remap_pfn_range(vma,from,pfn,size,prot) \
arch_io_remap_pfn_range(vma,from,pfn,size,prot)
#endif
#define pgtable_cache_init() do { } while (0)

View File

@@ -16,6 +16,7 @@
enum arm_pmu_type {
ARM_PMU_DEVICE_CPU = 0,
ARM_PMU_DEVICE_L2 = 1,
ARM_NUM_PMU_DEVICES,
};

View File

@@ -29,6 +29,8 @@
#define STACK_TOP_MAX TASK_SIZE
#endif
extern unsigned int boot_reason;
struct debug_info {
#ifdef CONFIG_HAVE_HW_BREAKPOINT
struct perf_event *hbp[ARM_MAX_HBP_SLOTS];

View 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 */

View File

@@ -37,6 +37,15 @@ struct tag_core {
/* it is allowed to have multiple ATAG_MEM nodes */
#define ATAG_MEM 0x54410002
/* it is allowed to have multiple ATAG_MEM_RESERVED nodes */
/* these indicate places where hotpluggable memory is present */
/* which are not active during boot */
#define ATAG_MEM_RESERVED 0x5441000A
/* it is allowed to have multiple ATAG_MEM_LOW_POWER nodes */
/* these indicate memory which can be put in a low power state */
#define ATAG_MEM_LOW_POWER 0x5441000B
/* these indicate memory which can be reclaimed from OSBL memory after bootup */
#define ATAG_MEM_OSBL 0x5441000C
struct tag_mem32 {
__u32 size;
@@ -221,6 +230,18 @@ extern int arm_add_memory(phys_addr_t start, unsigned long size);
extern void early_print(const char *str, ...);
extern void dump_machine_table(void);
/*
* Early command line parameters.
*/
struct early_params {
const char *arg;
void (*fn)(char **p);
};
#define __early_param(name,fn) \
static struct early_params __early_##fn __used \
__attribute__((__section__(".early_param.init"))) = { name, fn }
#endif /* __KERNEL__ */
#endif

View File

@@ -69,6 +69,8 @@
#define __exception_irq_entry __exception
#endif
void cpu_idle_wait(void);
struct thread_info;
struct task_struct;
@@ -141,7 +143,7 @@ extern unsigned int user_debug;
#define dsb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" \
: : "r" (0) : "memory")
#define dmb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" \
: : "r" (0) : "memory")
: : "r" (0) : "memory")
#elif defined(CONFIG_CPU_FA526)
#define isb() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" \
: : "r" (0) : "memory")

View File

@@ -433,7 +433,7 @@ local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
if (tlb_flag(TLB_V6_I_PAGE))
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
if (tlb_flag(TLB_V7_UIS_PAGE))
#ifdef CONFIG_ARM_ERRATA_720789
#if defined(CONFIG_ARM_ERRATA_720789) || defined(CONFIG_ARCH_MSM8X60)
asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (uaddr & PAGE_MASK) : "cc");
#else
asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (uaddr) : "cc");
@@ -480,7 +480,11 @@ static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
if (tlb_flag(TLB_V6_I_PAGE))
asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
if (tlb_flag(TLB_V7_UIS_PAGE))
#ifdef CONFIG_ARCH_MSM8X60
asm("mcr p15, 0, %0, c8, c3, 3" : : "r" (kaddr) : "cc");
#else
asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (kaddr) : "cc");
#endif
if (tlb_flag(TLB_BTB)) {
/* flush the branch target cache */

View File

@@ -21,7 +21,7 @@
#define FPSID_FORMAT_MASK (0x3 << FPSID_FORMAT_BIT)
#define FPSID_NODOUBLE (1<<20)
#define FPSID_ARCH_BIT (16)
#define FPSID_ARCH_MASK (0xF << FPSID_ARCH_BIT)
#define FPSID_ARCH_MASK (0x7F << FPSID_ARCH_BIT)
#define FPSID_PART_BIT (8)
#define FPSID_PART_MASK (0xFF << FPSID_PART_BIT)
#define FPSID_VARIANT_BIT (4)
@@ -82,3 +82,8 @@
#define VFPOPDESC_UNUSED_BIT (24)
#define VFPOPDESC_UNUSED_MASK (0xFF << VFPOPDESC_UNUSED_BIT)
#define VFPOPDESC_OPDESC_MASK (~(VFPOPDESC_LENGTH_MASK | VFPOPDESC_UNUSED_MASK))
#ifndef __ASSEMBLY__
int vfp_flush_context(void);
void vfp_reinit(void);
#endif

View File

@@ -52,10 +52,6 @@ extern void fpundefinstr(void);
EXPORT_SYMBOL(__backtrace);
/* platform dependent support */
EXPORT_SYMBOL(__udelay);
EXPORT_SYMBOL(__const_udelay);
/* networking */
EXPORT_SYMBOL(csum_partial);
EXPORT_SYMBOL(csum_partial_copy_from_user);

View File

@@ -734,7 +734,14 @@ ENTRY(__switch_to)
ldr r7, [r7, #TSK_STACK_CANARY]
#endif
#ifdef CONFIG_CPU_USE_DOMAINS
#ifdef CONFIG_EMULATE_DOMAIN_MANAGER_V7
stmdb r13!, {r0-r3, lr}
mov r0, r6
bl emulate_domain_manager_set
ldmia r13!, {r0-r3, lr}
#else
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
#endif
#endif
mov r5, r0
add r4, r2, #TI_CPU_SAVE

View File

@@ -362,10 +362,17 @@ __enable_mmu:
#ifdef CONFIG_CPU_ICACHE_DISABLE
bic r0, r0, #CR_I
#endif
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_MANAGER) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_TABLE, DOMAIN_MANAGER) | \
#ifdef CONFIG_EMULATE_DOMAIN_MANAGER_V7
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \
domain_val(DOMAIN_KERNEL, DOMAIN_CLIENT) | \
domain_val(DOMAIN_TABLE, DOMAIN_CLIENT) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
#else
mov r5, #(domain_val(DOMAIN_USER, DOMAIN_CLIENT) | \
domain_val(DOMAIN_KERNEL, DOMAIN_MANAGER) | \
domain_val(DOMAIN_TABLE, DOMAIN_CLIENT) | \
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
#endif
mcr p15, 0, r5, c3, c0, 0 @ load domain access register
mcr p15, 0, r4, c2, c0, 0 @ load page table pointer
b __turn_mmu_on

View File

@@ -833,6 +833,18 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
return ret;
}
static void reset_brps_reserved_reg(int n)
{
int i;
/* we must also reset any reserved registers. */
for (i = 0; i < n; ++i) {
write_wb_reg(ARM_BASE_BCR + i, 0UL);
write_wb_reg(ARM_BASE_BVR + i, 0UL);
}
}
/*
* One-time initialisation.
*/
@@ -880,11 +892,11 @@ static void reset_ctrl_regs(void *info)
if (enable_monitor_mode())
return;
/* We must also reset any reserved registers. */
for (i = 0; i < core_num_brps + core_num_reserved_brps; ++i) {
write_wb_reg(ARM_BASE_BCR + i, 0UL);
write_wb_reg(ARM_BASE_BVR + i, 0UL);
}
#ifdef CONFIG_HAVE_HW_BRKPT_RESERVED_RW_ACCESS
reset_brps_reserved_reg(core_num_brps);
#else
reset_brps_reserved_reg(core_num_brps + core_num_reserved_brps);
#endif
for (i = 0; i < core_num_wrps; ++i) {
write_wb_reg(ARM_BASE_WCR + i, 0UL);

View File

@@ -42,6 +42,8 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
#include <asm/perftypes.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);
perf_mon_interrupt_in();
irq_enter();
/*
@@ -95,6 +98,7 @@ asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
irq_exit();
set_irq_regs(old_regs);
perf_mon_interrupt_out();
}
void set_irq_flags(unsigned int irq, unsigned int iflags)

View File

@@ -86,6 +86,7 @@ void machine_kexec(struct kimage *image)
unsigned long reboot_code_buffer_phys;
void *reboot_code_buffer;
arch_kexec();
page_list = image->head & PAGE_MASK;
@@ -120,5 +121,5 @@ void machine_kexec(struct kimage *image)
cpu_proc_fin();
outer_inv_all();
flush_cache_all();
cpu_reset(reboot_code_buffer_phys);
__virt_to_phys(cpu_reset)(reboot_code_buffer_phys);
}

View File

@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/irq.h>
#include <asm/cputype.h>
#include <asm/irq.h>
@@ -71,6 +72,10 @@ struct arm_pmu {
enum arm_perf_pmu_ids id;
const char *name;
irqreturn_t (*handle_irq)(int irq_num, void *dev);
#ifdef CONFIG_SMP
void (*secondary_enable)(unsigned int irq);
void (*secondary_disable)(unsigned int irq);
#endif
void (*enable)(struct hw_perf_event *evt, int idx);
void (*disable)(struct hw_perf_event *evt, int idx);
int (*get_event_idx)(struct cpu_hw_events *cpuc,
@@ -426,6 +431,10 @@ armpmu_reserve_hardware(void)
pr_warning("unable to request IRQ%d for ARM perf "
"counters\n", irq);
break;
#ifdef CONFIG_SMP
} else if (armpmu->secondary_enable) {
armpmu->secondary_enable(irq);
#endif
}
}
@@ -449,8 +458,13 @@ armpmu_release_hardware(void)
for (i = pmu_device->num_resources - 1; i >= 0; --i) {
irq = platform_get_irq(pmu_device, i);
if (irq >= 0)
if (irq >= 0) {
free_irq(irq, NULL);
#ifdef CONFIG_SMP
if (armpmu->secondary_disable)
armpmu->secondary_disable(irq);
#endif
}
}
armpmu->stop();
@@ -624,6 +638,10 @@ static struct pmu pmu = {
#include "perf_event_xscale.c"
#include "perf_event_v6.c"
#include "perf_event_v7.c"
#include "perf_event_msm.c"
#include "perf_event_msm_l2.c"
#include "perf_event_msm_krait.c"
#include "perf_event_msm_krait_l2.c"
/*
* Ensure the PMU has sane values out of reset.
@@ -674,6 +692,22 @@ init_hw_perf_events(void)
armpmu = xscale2pmu_init();
break;
}
/* Qualcomm CPUs */
} else if (0x51 == implementor) {
switch (part_number) {
case 0x00F0: /* 8x50 & 7x30*/
armpmu = armv7_scorpion_pmu_init();
break;
case 0x02D0: /* 8x60 */
armpmu = armv7_scorpionmp_pmu_init();
scorpionmp_l2_pmu_init();
break;
case 0x0490: /* 8960 sim */
case 0x04D0: /* 8960 */
armpmu = armv7_krait_pmu_init();
krait_l2_pmu_init();
break;
}
}
if (armpmu) {

View 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 */

View 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 */

View 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

View 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

View File

@@ -45,16 +45,41 @@ static int __devinit pmu_device_probe(struct platform_device *pdev)
return 0;
}
static struct platform_driver pmu_driver = {
static struct platform_driver cpu_pmu_driver = {
.driver = {
.name = "arm-pmu",
.name = "cpu-arm-pmu",
},
.probe = pmu_device_probe,
};
static struct platform_driver l2_pmu_driver = {
.driver = {
.name = "l2-arm-pmu",
},
.probe = pmu_device_probe,
};
static struct platform_driver *pmu_drivers[] __initdata = {
&cpu_pmu_driver,
&l2_pmu_driver,
};
static int __init register_pmu_driver(void)
{
return platform_driver_register(&pmu_driver);
int i;
int err;
for (i = 0; i < ARM_NUM_PMU_DEVICES; i++) {
err = platform_driver_register(pmu_drivers[i]);
if (err) {
pr_err("%s: failed to register id:%d\n", __func__, i);
while (--i >= 0)
platform_driver_unregister(pmu_drivers[i]);
break;
}
}
return err;
}
device_initcall(register_pmu_driver);

View File

@@ -29,6 +29,9 @@
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/memblock.h>
#ifdef CONFIG_MEMORY_HOTPLUG
#include <linux/memory_hotplug.h>
#endif
#include <asm/unified.h>
#include <asm/cpu.h>
@@ -97,6 +100,8 @@ EXPORT_SYMBOL(system_serial_high);
unsigned int elf_hwcap __read_mostly;
EXPORT_SYMBOL(elf_hwcap);
unsigned int boot_reason;
EXPORT_SYMBOL(boot_reason);
#ifdef MULTI_CPU
struct processor processor __read_mostly;
@@ -517,6 +522,62 @@ static int __init early_mem(char *p)
}
early_param("mem", early_mem);
#ifdef CONFIG_MEMORY_HOTPLUG
static void __init early_mem_reserved(char **p)
{
unsigned int start;
unsigned int size;
unsigned int end;
unsigned int h_end;
start = PHYS_OFFSET;
size = memparse(*p, p);
if (**p == '@')
start = memparse(*p + 1, p);
if (movable_reserved_start) {
end = start + size;
h_end = movable_reserved_start + movable_reserved_size;
end = max(end, h_end);
movable_reserved_start = min(movable_reserved_start,
(unsigned long)start);
movable_reserved_size = end - movable_reserved_start;
} else {
movable_reserved_start = start;
movable_reserved_size = size;
}
}
__early_param("mem_reserved=", early_mem_reserved);
static void __init early_mem_low_power(char **p)
{
unsigned int start;
unsigned int size;
unsigned int end;
unsigned int h_end;
start = PHYS_OFFSET;
size = memparse(*p, p);
if (**p == '@')
start = memparse(*p + 1, p);
if (low_power_memory_start) {
end = start + size;
h_end = low_power_memory_start + low_power_memory_size;
end = max(end, h_end);
low_power_memory_start = min(low_power_memory_start,
(unsigned long)start);
low_power_memory_size = end - low_power_memory_start;
} else {
low_power_memory_start = start;
low_power_memory_size = size;
}
arm_add_memory(start, size);
}
__early_param("mem_low_power=", early_mem_low_power);
#endif
static void __init
setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
{
@@ -606,6 +667,66 @@ static int __init parse_tag_mem32(const struct tag *tag)
__tagtable(ATAG_MEM, parse_tag_mem32);
#ifdef CONFIG_MEMORY_HOTPLUG
static int __init parse_tag_mem32_reserved(const struct tag *tag)
{
unsigned int start;
unsigned int size;
unsigned int end;
unsigned int h_end;
start = tag->u.mem.start;
size = tag->u.mem.size;
if (movable_reserved_start) {
end = start + size;
h_end = movable_reserved_start + movable_reserved_size;
end = max(end, h_end);
movable_reserved_start = min(movable_reserved_start,
(unsigned long)start);
movable_reserved_size = end - movable_reserved_start;
} else {
movable_reserved_start = tag->u.mem.start;
movable_reserved_size = tag->u.mem.size;
}
printk(KERN_ALERT "reserved %lx at %lx for hotplug\n",
movable_reserved_size, movable_reserved_start);
return 0;
}
__tagtable(ATAG_MEM_RESERVED, parse_tag_mem32_reserved);
static int __init parse_tag_mem32_low_power(const struct tag *tag)
{
unsigned int start;
unsigned int size;
unsigned int end;
unsigned int h_end;
start = tag->u.mem.start;
size = tag->u.mem.size;
if (low_power_memory_start) {
end = start + size;
h_end = low_power_memory_start + low_power_memory_size;
end = max(end, h_end);
low_power_memory_start = min(low_power_memory_start,
(unsigned long)start);
low_power_memory_size = end - low_power_memory_start;
} else {
low_power_memory_start = tag->u.mem.start;
low_power_memory_size = tag->u.mem.size;
}
printk(KERN_ALERT "low power memory %lx at %lx\n",
low_power_memory_size, low_power_memory_start);
return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
}
__tagtable(ATAG_MEM_LOW_POWER, parse_tag_mem32_low_power);
#endif
#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
struct screen_info screen_info = {
.orig_video_lines = 30,

View File

@@ -597,6 +597,11 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
void smp_send_reschedule(int cpu)
{
if (unlikely(cpu_is_offline(cpu))) {
pr_warn("%s: attempt to send resched-IPI to an offline cpu.\n",
__func__);
return;
}
smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
}

View File

@@ -127,8 +127,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
twd_calibrate_rate();
clk->name = "local_timer";
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
CLOCK_EVT_FEAT_C3STOP;
clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
clk->rating = 350;
clk->set_mode = twd_set_mode;
clk->set_next_event = twd_set_next_event;

View File

@@ -453,6 +453,10 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
up_read(&mm->mmap_sem);
flush_cache_user_range(start, end);
#ifdef CONFIG_ARCH_MSM7X27
mb();
#endif
return;
}
up_read(&mm->mmap_sem);

90
arch/arm/lib/delay.c Normal file
View 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);

View File

@@ -351,7 +351,7 @@ ENDPROC(__aeabi_idivmod)
#endif
Ldiv0:
ENTRY(Ldiv0)
UNWIND(.fnstart)
UNWIND(.pad #4)
UNWIND(.save {lr})

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +1,252 @@
obj-y += io.o idle.o timer.o
obj-y += clock.o
obj-$(CONFIG_DEBUG_FS) += clock-debug.o
obj-y += io.o dma.o memory.o timer.o
obj-y += clock.o clock-voter.o clock-dummy.o
obj-y += modem_notifier.o subsystem_map.o
obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o
obj-$(CONFIG_KEXEC) += msm_kexec.o
obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o
ifndef CONFIG_ARCH_MSM8X60
obj-$(CONFIG_MSM_PROC_COMM) += clock-pcom.o
obj-$(CONFIG_MSM_PROC_COMM) += vreg.o mpp.o
ifdef CONFIG_MSM_PROC_COMM
ifndef CONFIG_ARCH_FSM9XXX
obj-$(CONFIG_REGULATOR) += footswitch-pcom.o
endif
obj-$(CONFIG_DEBUG_FS) += pmic_debugfs.o
endif
endif
obj-$(CONFIG_ARCH_MSM_ARM11) += acpuclock.o
obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
obj-$(CONFIG_ARCH_MSM_CORTEX_A5) += acpuclock.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o
ifndef CONFIG_MSM_SMP
obj-$(CONFIG_ARCH_MSM_SCORPION) += msm_fault_handlers.o
endif
obj-$(CONFIG_MSM_VIC) += irq-vic.o
obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o
obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o
obj-$(CONFIG_ARCH_MSM7X30) += dma.o
obj-$(CONFIG_ARCH_QSD8X50) += dma.o sirc.o
ifdef CONFIG_ARCH_QSD8X50
obj-$(CONFIG_MSM_SOC_REV_NONE) += acpuclock-8x50.o
endif
obj-$(CONFIG_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_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o devices-msm7x00.o
obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o board-trout-panel.o devices-msm7x00.o
obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
obj-$(CONFIG_MSM_CPU_AVS) += avs.o
obj-$(CONFIG_MSM_AVS_HW) += avs_hw.o
obj-$(CONFIG_CPU_V6) += idle-v6.o
obj-$(CONFIG_CPU_V7) += idle-v7.o
obj-$(CONFIG_MSM_JTAG_V7) += jtag-v7.o
obj-$(CONFIG_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_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
obj-$(CONFIG_ARCH_MSM8960) += gpiomux-v2.o gpiomux.o
ifdef CONFIG_FSM9XXX_TLMM
obj-y += gpio-fsm9xxx.o
else
ifdef CONFIG_MSM_V2_TLMM
ifndef CONFIG_ARCH_MSM8960
# TODO: TLMM Mapping issues need to be resolved
obj-y += gpio-v2.o
endif
else
obj-y += gpio.o
endif
endif
obj-$(CONFIG_MSM_SLEEP_STATS) += msm_rq_stats.o idle_stats.o
obj-$(CONFIG_MSM_SHOW_RESUME_IRQ) += msm_show_resume_irq.o
obj-$(CONFIG_BT_MSM_PINTEST) += btpintest.o
obj-$(CONFIG_MSM_FAKE_BATTERY) += fish_battery.o
obj-$(CONFIG_MSM_RPC_VIBRATOR) += msm_vibrator.o
obj-$(CONFIG_MSM_NATIVE_RESTART) += restart.o

View File

@@ -1,3 +1,44 @@
zreladdr-y := 0x10008000
params_phys-y := 0x10000100
initrd_phys-y := 0x10800000
# MSM7x01A
zreladdr-$(CONFIG_ARCH_MSM7X01A) := 0x10008000
params_phys-$(CONFIG_ARCH_MSM7X01A) := 0x10000100
initrd_phys-$(CONFIG_ARCH_MSM7X01A) := 0x10800000
# MSM7x25
zreladdr-$(CONFIG_ARCH_MSM7X25) := 0x00208000
params_phys-$(CONFIG_ARCH_MSM7X25) := 0x00200100
initrd_phys-$(CONFIG_ARCH_MSM7X25) := 0x0A000000
# MSM7x27
zreladdr-$(CONFIG_ARCH_MSM7X27) := 0x00208000
params_phys-$(CONFIG_ARCH_MSM7X27) := 0x00200100
initrd_phys-$(CONFIG_ARCH_MSM7X27) := 0x0A000000
# MSM7x27A
zreladdr-$(CONFIG_ARCH_MSM7X27A) := 0x00208000
params_phys-$(CONFIG_ARCH_MSM7X27A) := 0x00200100
# MSM7x30
zreladdr-$(CONFIG_ARCH_MSM7X30) := 0x00208000
params_phys-$(CONFIG_ARCH_MSM7X30) := 0x00200100
initrd_phys-$(CONFIG_ARCH_MSM7X30) := 0x01200000
ifeq ($(CONFIG_MSM_SOC_REV_A),y)
# QSD8x50
zreladdr-$(CONFIG_ARCH_QSD8X50) := 0x20008000
params_phys-$(CONFIG_ARCH_QSD8X50) := 0x20000100
initrd_phys-$(CONFIG_ARCH_QSD8X50) := 0x24000000
endif
# MSM8x60
zreladdr-$(CONFIG_ARCH_MSM8X60) := 0x40208000
# MSM8960
zreladdr-$(CONFIG_ARCH_MSM8960) := 0x80208000
# APQ8064
zreladdr-$(CONFIG_ARCH_APQ8064) := 0x80208000
# FSM9XXX
zreladdr-$(CONFIG_ARCH_FSM9XXX) := 0x10008000
params_phys-$(CONFIG_ARCH_FSM9XXX) := 0x10000100
initrd_phys-$(CONFIG_ARCH_FSM9XXX) := 0x12000000

View 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();
}

View 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);
}

View 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
}

View 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);
}

View File

@@ -17,6 +17,7 @@
*
*/
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.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
* out to optimized speed switching. Initialize loops_per_jiffy to 0.
* out to optimized speed switching. Initalize loops_per_jiffy to 0.
*
* Table stepping up/down is optimized for 256mhz jumps while staying on the
* same PLL.
@@ -493,7 +494,7 @@ uint32_t acpuclk_get_switch_time(void)
* Clock driver initialization
*---------------------------------------------------------------------------*/
/* Initialize the lpj field in the acpu_freq_tbl. */
/* Initalize the lpj field in the acpu_freq_tbl. */
static void __init lpj_init(void)
{
int i;

View 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));
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
* MSM architecture clock driver header
*
* Copyright (C) 2007 Google, Inc.
* Copyright (c) 2007 QUALCOMM Incorporated
* Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
* Author: San Mehat <san@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -20,13 +20,25 @@
#ifndef __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
#define __ARCH_ARM_MACH_MSM_ACPUCLOCK_H
int acpuclk_set_rate(unsigned long rate, int for_power_collapse);
unsigned long acpuclk_get_rate(void);
#include <linux/list.h>
enum setrate_reason {
SETRATE_CPUFREQ = 0,
SETRATE_SWFI,
SETRATE_PC,
SETRATE_HOTPLUG,
SETRATE_INIT,
};
int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason);
unsigned long acpuclk_get_rate(int cpu);
uint32_t acpuclk_get_switch_time(void);
unsigned long acpuclk_wait_for_irq(void);
unsigned long acpuclk_power_collapse(void);
unsigned long acpuclk_get_wfi_rate(void);
#ifdef CONFIG_ARCH_MSM8960
void acpuclock_secondary_init(void);
#else
static inline void acpuclock_secondary_init(void) { }
#endif
#endif

View 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
View 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
View 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
View 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