Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (278 commits) arm: remove machine_desc.io_pg_offst and .phys_io arm: use addruart macro to establish debug mappings arm: return both physical and virtual addresses from addruart arm/debug: consolidate addruart macros for CONFIG_DEBUG_ICEDCC ARM: make struct machine_desc definition coherent with its comment eukrea_mbimxsd-baseboard: Pass the correct GPIO to gpio_free cpuimx27: fix compile when ULPI is selected mach-pcm037_eet: fix compile errors Fixing ethernet driver compilation error for i.MX31 ADS board cpuimx51: update board support mx5: add cpuimx51sd module and its baseboard iomux-mx51: fix GPIO_1_xx 's IOMUX configuration imx-esdhc: update devices registration mx51: add resources for SD/MMC on i.MX51 iomux-mx51: fix SD1 and SD2's iomux configuration clock-mx51: rename CLOCK1 to CLOCK_CCGR for better readability clock-mx51: factorize clk_set_parent and clk_get_rate eukrea_mbimxsd: add support for DVI displays cpuimx25 & cpuimx35: fix OTG port registration in host mode i.MX31 and i.MX35 : fix errate TLSbo65953 and ENGcm09472 ...
This commit is contained in:
commit
b5153163ed
844 changed files with 25259 additions and 6703 deletions
|
@ -6,6 +6,8 @@ Interrupts
|
||||||
- ARM Interrupt subsystem documentation
|
- ARM Interrupt subsystem documentation
|
||||||
IXP2000
|
IXP2000
|
||||||
- Release Notes for Linux on Intel's IXP2000 Network Processor
|
- Release Notes for Linux on Intel's IXP2000 Network Processor
|
||||||
|
msm
|
||||||
|
- MSM specific documentation
|
||||||
Netwinder
|
Netwinder
|
||||||
- Netwinder specific documentation
|
- Netwinder specific documentation
|
||||||
Porting
|
Porting
|
||||||
|
|
176
Documentation/arm/msm/gpiomux.txt
Normal file
176
Documentation/arm/msm/gpiomux.txt
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
This document provides an overview of the msm_gpiomux interface, which
|
||||||
|
is used to provide gpio pin multiplexing and configuration on mach-msm
|
||||||
|
targets.
|
||||||
|
|
||||||
|
History
|
||||||
|
=======
|
||||||
|
|
||||||
|
The first-generation API for gpio configuration & multiplexing on msm
|
||||||
|
is the function gpio_tlmm_config(). This function has a few notable
|
||||||
|
shortcomings, which led to its deprecation and replacement by gpiomux:
|
||||||
|
|
||||||
|
The 'disable' parameter: Setting the second parameter to
|
||||||
|
gpio_tlmm_config to GPIO_CFG_DISABLE tells the peripheral
|
||||||
|
processor in charge of the subsystem to perform a look-up into a
|
||||||
|
low-power table and apply the low-power/sleep setting for the pin.
|
||||||
|
As the msm family evolved this became problematic. Not all pins
|
||||||
|
have sleep settings, not all peripheral processors will accept requests
|
||||||
|
to apply said sleep settings, and not all msm targets have their gpio
|
||||||
|
subsystems managed by a peripheral processor. In order to get consistent
|
||||||
|
behavior on all targets, drivers are forced to ignore this parameter,
|
||||||
|
rendering it useless.
|
||||||
|
|
||||||
|
The 'direction' flag: for all mux-settings other than raw-gpio (0),
|
||||||
|
the output-enable bit of a gpio is hard-wired to a known
|
||||||
|
input (usually VDD or ground). For those settings, the direction flag
|
||||||
|
is meaningless at best, and deceptive at worst. In addition, using the
|
||||||
|
direction flag to change output-enable (OE) directly can cause trouble in
|
||||||
|
gpiolib, which has no visibility into gpio direction changes made
|
||||||
|
in this way. Direction control in gpio mode should be made through gpiolib.
|
||||||
|
|
||||||
|
Key Features of gpiomux
|
||||||
|
=======================
|
||||||
|
|
||||||
|
- A consistent interface across all generations of msm. Drivers can expect
|
||||||
|
the same results on every target.
|
||||||
|
- gpiomux plays nicely with gpiolib. Functions that should belong to gpiolib
|
||||||
|
are left to gpiolib and not duplicated here. gpiomux is written with the
|
||||||
|
intent that gpio_chips will call gpiomux reference-counting methods
|
||||||
|
from their request() and free() hooks, providing full integration.
|
||||||
|
- Tabular configuration. Instead of having to call gpio_tlmm_config
|
||||||
|
hundreds of times, gpio configuration is placed in a single table.
|
||||||
|
- Per-gpio sleep. Each gpio is individually reference counted, allowing only
|
||||||
|
those lines which are in use to be put in high-power states.
|
||||||
|
- 0 means 'do nothing': all flags are designed so that the default memset-zero
|
||||||
|
equates to a sensible default of 'no configuration', preventing users
|
||||||
|
from having to provide hundreds of 'no-op' configs for unused or
|
||||||
|
unwanted lines.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
To use gpiomux, provide configuration information for relevant gpio lines
|
||||||
|
in the msm_gpiomux_configs table. Since a 0 equates to "unconfigured",
|
||||||
|
only those lines to be managed by gpiomux need to be specified. Here
|
||||||
|
is a completely fictional example:
|
||||||
|
|
||||||
|
struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
|
||||||
|
[12] = {
|
||||||
|
.active = GPIOMUX_VALID | GPIOMUX_DRV_8MA | GPIOMUX_FUNC_1,
|
||||||
|
.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
|
||||||
|
},
|
||||||
|
[34] = {
|
||||||
|
.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
To indicate that a gpio is in use, call msm_gpiomux_get() to increase
|
||||||
|
its reference count. To decrease the reference count, call msm_gpiomux_put().
|
||||||
|
|
||||||
|
The effect of this configuration is as follows:
|
||||||
|
|
||||||
|
When the system boots, gpios 12 and 34 will be initialized with their
|
||||||
|
'suspended' configurations. All other gpios, which were left unconfigured,
|
||||||
|
will not be touched.
|
||||||
|
|
||||||
|
When msm_gpiomux_get() is called on gpio 12 to raise its reference count
|
||||||
|
above 0, its active configuration will be applied. Since no other gpio
|
||||||
|
line has a valid active configuration, msm_gpiomux_get() will have no
|
||||||
|
effect on any other line.
|
||||||
|
|
||||||
|
When msm_gpiomux_put() is called on gpio 12 or 34 to drop their reference
|
||||||
|
count to 0, their suspended configurations will be applied.
|
||||||
|
Since no other gpio line has a valid suspended configuration, no other
|
||||||
|
gpio line will be effected by msm_gpiomux_put(). Since gpio 34 has no valid
|
||||||
|
active configuration, this is effectively a no-op for gpio 34 as well,
|
||||||
|
with one small caveat, see the section "About Output-Enable Settings".
|
||||||
|
|
||||||
|
All of the GPIOMUX_VALID flags may seem like unnecessary overhead, but
|
||||||
|
they address some important issues. As unused entries (all those
|
||||||
|
except 12 and 34) are zero-filled, gpiomux needs a way to distinguish
|
||||||
|
the used fields from the unused. In addition, the all-zero pattern
|
||||||
|
is a valid configuration! Therefore, gpiomux defines an additional bit
|
||||||
|
which is used to indicate when a field is used. This has the pleasant
|
||||||
|
side-effect of allowing calls to msm_gpiomux_write to use '0' to indicate
|
||||||
|
that a value should not be changed:
|
||||||
|
|
||||||
|
msm_gpiomux_write(0, GPIOMUX_VALID, 0);
|
||||||
|
|
||||||
|
replaces the active configuration of gpio 0 with an all-zero configuration,
|
||||||
|
but leaves the suspended configuration as it was.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
[34] = {
|
||||||
|
.suspended = GPIOMUX_VALID | GPIOMUX_PULL_DOWN,
|
||||||
|
},
|
||||||
|
|
||||||
|
The suspended setting is applied during boot, and the lack of any valid
|
||||||
|
active setting prevents any other setting from being applied at runtime.
|
||||||
|
If other subsystems attempting to access the line is a concern, one could
|
||||||
|
*really* anchor the configuration down by calling msm_gpiomux_get on the
|
||||||
|
line at initialization to move the line into active mode. With the line
|
||||||
|
held, it will never be re-suspended, and with no valid active configuration,
|
||||||
|
no new configurations will be applied.
|
||||||
|
|
||||||
|
But then, if having other subsystems grabbing for the line is truly a concern,
|
||||||
|
it should be reserved with gpio_request instead, which carries an implicit
|
||||||
|
msm_gpiomux_get.
|
||||||
|
|
||||||
|
gpiomux and gpiolib
|
||||||
|
===================
|
||||||
|
|
||||||
|
It is expected that msm gpio_chips will call msm_gpiomux_get() and
|
||||||
|
msm_gpiomux_put() from their request and free hooks, like this fictional
|
||||||
|
example:
|
||||||
|
|
||||||
|
static int request(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
return msm_gpiomux_get(chip->base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
msm_gpiomux_put(chip->base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
...somewhere in a gpio_chip declaration...
|
||||||
|
.request = request,
|
||||||
|
.free = free,
|
||||||
|
|
||||||
|
This provides important functionality:
|
||||||
|
- It guarantees that a gpio line will have its 'active' config applied
|
||||||
|
when the line is requested, and will not be suspended while the line
|
||||||
|
remains requested; and
|
||||||
|
- It guarantees that gpio-direction settings from gpiolib behave sensibly.
|
||||||
|
See "About Output-Enable Settings."
|
||||||
|
|
||||||
|
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.
|
12
MAINTAINERS
12
MAINTAINERS
|
@ -990,11 +990,23 @@ S: Supported
|
||||||
F: arch/arm/mach-shmobile/
|
F: arch/arm/mach-shmobile/
|
||||||
F: drivers/sh/
|
F: drivers/sh/
|
||||||
|
|
||||||
|
ARM/TELECHIPS ARM ARCHITECTURE
|
||||||
|
M: "Hans J. Koch" <hjk@linutronix.de>
|
||||||
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
|
S: Maintained
|
||||||
|
F: arch/arm/plat-tcc/
|
||||||
|
F: arch/arm/mach-tcc8k/
|
||||||
|
|
||||||
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
|
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
|
||||||
M: Lennert Buytenhek <kernel@wantstofly.org>
|
M: Lennert Buytenhek <kernel@wantstofly.org>
|
||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
ARM/TETON BGA MACHINE SUPPORT
|
||||||
|
M: Mark F. Brown <mark.brown314@gmail.com>
|
||||||
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
ARM/THECUS N2100 MACHINE SUPPORT
|
ARM/THECUS N2100 MACHINE SUPPORT
|
||||||
M: Lennert Buytenhek <kernel@wantstofly.org>
|
M: Lennert Buytenhek <kernel@wantstofly.org>
|
||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
|
|
7
Makefile
7
Makefile
|
@ -554,8 +554,15 @@ endif
|
||||||
ifdef CONFIG_FRAME_POINTER
|
ifdef CONFIG_FRAME_POINTER
|
||||||
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||||
else
|
else
|
||||||
|
# Some targets (ARM with Thumb2, for example), can't be built with frame
|
||||||
|
# pointers. For those, we don't have FUNCTION_TRACER automatically
|
||||||
|
# select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is
|
||||||
|
# incompatible with -fomit-frame-pointer with current GCC, so we don't use
|
||||||
|
# -fomit-frame-pointer with FUNCTION_TRACER.
|
||||||
|
ifndef CONFIG_FUNCTION_TRACER
|
||||||
KBUILD_CFLAGS += -fomit-frame-pointer
|
KBUILD_CFLAGS += -fomit-frame-pointer
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_DEBUG_INFO
|
ifdef CONFIG_DEBUG_INFO
|
||||||
KBUILD_CFLAGS += -g
|
KBUILD_CFLAGS += -g
|
||||||
|
|
|
@ -19,6 +19,8 @@ config ARM
|
||||||
select HAVE_KPROBES if (!XIP_KERNEL)
|
select HAVE_KPROBES if (!XIP_KERNEL)
|
||||||
select HAVE_KRETPROBES if (HAVE_KPROBES)
|
select HAVE_KRETPROBES if (HAVE_KPROBES)
|
||||||
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
|
select HAVE_FUNCTION_TRACER if (!XIP_KERNEL)
|
||||||
|
select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
|
||||||
|
select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL)
|
||||||
select HAVE_GENERIC_DMA_COHERENT
|
select HAVE_GENERIC_DMA_COHERENT
|
||||||
select HAVE_KERNEL_GZIP
|
select HAVE_KERNEL_GZIP
|
||||||
select HAVE_KERNEL_LZO
|
select HAVE_KERNEL_LZO
|
||||||
|
@ -27,6 +29,7 @@ config ARM
|
||||||
select HAVE_PERF_EVENTS
|
select HAVE_PERF_EVENTS
|
||||||
select PERF_USE_VMALLOC
|
select PERF_USE_VMALLOC
|
||||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||||
|
select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
|
||||||
help
|
help
|
||||||
The ARM series is a line of low-power-consumption RISC chip designs
|
The ARM series is a line of low-power-consumption RISC chip designs
|
||||||
licensed by ARM Ltd and targeted at embedded applications and
|
licensed by ARM Ltd and targeted at embedded applications and
|
||||||
|
@ -146,6 +149,9 @@ config ARCH_HAS_CPUFREQ
|
||||||
and that the relevant menu configurations are displayed for
|
and that the relevant menu configurations are displayed for
|
||||||
it.
|
it.
|
||||||
|
|
||||||
|
config ARCH_HAS_CPU_IDLE_WAIT
|
||||||
|
def_bool y
|
||||||
|
|
||||||
config GENERIC_HWEIGHT
|
config GENERIC_HWEIGHT
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
@ -511,6 +517,7 @@ config ARCH_MMP
|
||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
select TICK_ONESHOT
|
select TICK_ONESHOT
|
||||||
select PLAT_PXA
|
select PLAT_PXA
|
||||||
|
select SPARSE_IRQ
|
||||||
help
|
help
|
||||||
Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
|
Support for Marvell's PXA168/PXA910(MMP) and MMP2 processor line.
|
||||||
|
|
||||||
|
@ -588,6 +595,7 @@ config ARCH_PXA
|
||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
select TICK_ONESHOT
|
select TICK_ONESHOT
|
||||||
select PLAT_PXA
|
select PLAT_PXA
|
||||||
|
select SPARSE_IRQ
|
||||||
help
|
help
|
||||||
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
|
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
|
||||||
|
|
||||||
|
@ -679,8 +687,8 @@ config ARCH_S3C64XX
|
||||||
help
|
help
|
||||||
Samsung S3C64XX series based systems
|
Samsung S3C64XX series based systems
|
||||||
|
|
||||||
config ARCH_S5P6440
|
config ARCH_S5P64X0
|
||||||
bool "Samsung S5P6440"
|
bool "Samsung S5P6440 S5P6450"
|
||||||
select CPU_V6
|
select CPU_V6
|
||||||
select GENERIC_GPIO
|
select GENERIC_GPIO
|
||||||
select HAVE_CLK
|
select HAVE_CLK
|
||||||
|
@ -689,7 +697,8 @@ config ARCH_S5P6440
|
||||||
select HAVE_S3C2410_I2C
|
select HAVE_S3C2410_I2C
|
||||||
select HAVE_S3C_RTC
|
select HAVE_S3C_RTC
|
||||||
help
|
help
|
||||||
Samsung S5P6440 CPU based systems
|
Samsung S5P64X0 CPU based systems, such as the Samsung SMDK6440,
|
||||||
|
SMDK6450.
|
||||||
|
|
||||||
config ARCH_S5P6442
|
config ARCH_S5P6442
|
||||||
bool "Samsung S5P6442"
|
bool "Samsung S5P6442"
|
||||||
|
@ -748,6 +757,15 @@ config ARCH_SHARK
|
||||||
Support for the StrongARM based Digital DNARD machine, also known
|
Support for the StrongARM based Digital DNARD machine, also known
|
||||||
as "Shark" (<http://www.shark-linux.de/shark.html>).
|
as "Shark" (<http://www.shark-linux.de/shark.html>).
|
||||||
|
|
||||||
|
config ARCH_TCC_926
|
||||||
|
bool "Telechips TCC ARM926-based systems"
|
||||||
|
select CPU_ARM926T
|
||||||
|
select HAVE_CLK
|
||||||
|
select COMMON_CLKDEV
|
||||||
|
select GENERIC_CLOCKEVENTS
|
||||||
|
help
|
||||||
|
Support for Telechips TCC ARM926-based systems.
|
||||||
|
|
||||||
config ARCH_LH7A40X
|
config ARCH_LH7A40X
|
||||||
bool "Sharp LH7A40X"
|
bool "Sharp LH7A40X"
|
||||||
select CPU_ARM922T
|
select CPU_ARM922T
|
||||||
|
@ -916,6 +934,8 @@ source "arch/arm/plat-s5p/Kconfig"
|
||||||
|
|
||||||
source "arch/arm/plat-spear/Kconfig"
|
source "arch/arm/plat-spear/Kconfig"
|
||||||
|
|
||||||
|
source "arch/arm/plat-tcc/Kconfig"
|
||||||
|
|
||||||
if ARCH_S3C2410
|
if ARCH_S3C2410
|
||||||
source "arch/arm/mach-s3c2400/Kconfig"
|
source "arch/arm/mach-s3c2400/Kconfig"
|
||||||
source "arch/arm/mach-s3c2410/Kconfig"
|
source "arch/arm/mach-s3c2410/Kconfig"
|
||||||
|
@ -929,7 +949,7 @@ if ARCH_S3C64XX
|
||||||
source "arch/arm/mach-s3c64xx/Kconfig"
|
source "arch/arm/mach-s3c64xx/Kconfig"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
source "arch/arm/mach-s5p6440/Kconfig"
|
source "arch/arm/mach-s5p64x0/Kconfig"
|
||||||
|
|
||||||
source "arch/arm/mach-s5p6442/Kconfig"
|
source "arch/arm/mach-s5p6442/Kconfig"
|
||||||
|
|
||||||
|
@ -1003,7 +1023,7 @@ endif
|
||||||
|
|
||||||
config ARM_ERRATA_411920
|
config ARM_ERRATA_411920
|
||||||
bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
|
bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
|
||||||
depends on CPU_V6 && !SMP
|
depends on CPU_V6
|
||||||
help
|
help
|
||||||
Invalidation of the Instruction Cache operation can
|
Invalidation of the Instruction Cache operation can
|
||||||
fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
|
fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
|
||||||
|
@ -1182,13 +1202,13 @@ source "kernel/time/Kconfig"
|
||||||
|
|
||||||
config SMP
|
config SMP
|
||||||
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
|
bool "Symmetric Multi-Processing (EXPERIMENTAL)"
|
||||||
depends on EXPERIMENTAL && (REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP ||\
|
depends on EXPERIMENTAL
|
||||||
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
|
|
||||||
ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
|
|
||||||
depends on GENERIC_CLOCKEVENTS
|
depends on GENERIC_CLOCKEVENTS
|
||||||
|
depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
|
||||||
|
MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 ||\
|
||||||
|
ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
|
||||||
select USE_GENERIC_SMP_HELPERS
|
select USE_GENERIC_SMP_HELPERS
|
||||||
select HAVE_ARM_SCU if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 ||\
|
select HAVE_ARM_SCU
|
||||||
ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4
|
|
||||||
help
|
help
|
||||||
This enables support for systems with more than one CPU. If you have
|
This enables support for systems with more than one CPU. If you have
|
||||||
a system with only one CPU, like most personal computers, say N. If
|
a system with only one CPU, like most personal computers, say N. If
|
||||||
|
@ -1206,6 +1226,19 @@ config SMP
|
||||||
|
|
||||||
If you don't know what to do here, say N.
|
If you don't know what to do here, say N.
|
||||||
|
|
||||||
|
config SMP_ON_UP
|
||||||
|
bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
|
||||||
|
depends on EXPERIMENTAL
|
||||||
|
depends on SMP && !XIP && !THUMB2_KERNEL
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
SMP kernels contain instructions which fail on non-SMP processors.
|
||||||
|
Enabling this option allows the kernel to modify itself to make
|
||||||
|
these instructions safe. Disabling it allows about 1K of space
|
||||||
|
savings.
|
||||||
|
|
||||||
|
If you don't know what to do here, say Y.
|
||||||
|
|
||||||
config HAVE_ARM_SCU
|
config HAVE_ARM_SCU
|
||||||
bool
|
bool
|
||||||
depends on SMP
|
depends on SMP
|
||||||
|
@ -1256,12 +1289,9 @@ config HOTPLUG_CPU
|
||||||
|
|
||||||
config LOCAL_TIMERS
|
config LOCAL_TIMERS
|
||||||
bool "Use local timer interrupts"
|
bool "Use local timer interrupts"
|
||||||
depends on SMP && (REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || \
|
depends on SMP
|
||||||
REALVIEW_EB_A9MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
|
|
||||||
ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4)
|
|
||||||
default y
|
default y
|
||||||
select HAVE_ARM_TWD if ARCH_REALVIEW || ARCH_OMAP4 || ARCH_S5PV310 || \
|
select HAVE_ARM_TWD
|
||||||
ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS
|
|
||||||
help
|
help
|
||||||
Enable support for local timers on SMP platforms, rather then the
|
Enable support for local timers on SMP platforms, rather then the
|
||||||
legacy IPI broadcast method. Local timers allows the system
|
legacy IPI broadcast method. Local timers allows the system
|
||||||
|
@ -1272,7 +1302,7 @@ source kernel/Kconfig.preempt
|
||||||
|
|
||||||
config HZ
|
config HZ
|
||||||
int
|
int
|
||||||
default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P6440 || \
|
default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \
|
||||||
ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310
|
ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310
|
||||||
default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
|
default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
|
||||||
default AT91_TIMER_HZ if ARCH_AT91
|
default AT91_TIMER_HZ if ARCH_AT91
|
||||||
|
@ -1478,6 +1508,20 @@ config UACCESS_WITH_MEMCPY
|
||||||
However, if the CPU data cache is using a write-allocate mode,
|
However, if the CPU data cache is using a write-allocate mode,
|
||||||
this option is unlikely to provide any performance gain.
|
this option is unlikely to provide any performance gain.
|
||||||
|
|
||||||
|
config SECCOMP
|
||||||
|
bool
|
||||||
|
prompt "Enable seccomp to safely compute untrusted bytecode"
|
||||||
|
---help---
|
||||||
|
This kernel feature is useful for number crunching applications
|
||||||
|
that may need to compute untrusted bytecode during their
|
||||||
|
execution. By using pipes or other transports made available to
|
||||||
|
the process as file descriptors supporting the read/write
|
||||||
|
syscalls, it's possible to isolate those applications in
|
||||||
|
their own address space using seccomp. Once seccomp is
|
||||||
|
enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
|
||||||
|
and the task is only allowed to execute a few safe syscalls
|
||||||
|
defined by each seccomp mode.
|
||||||
|
|
||||||
config CC_STACKPROTECTOR
|
config CC_STACKPROTECTOR
|
||||||
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
|
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
|
||||||
help
|
help
|
||||||
|
|
|
@ -2,6 +2,20 @@ menu "Kernel hacking"
|
||||||
|
|
||||||
source "lib/Kconfig.debug"
|
source "lib/Kconfig.debug"
|
||||||
|
|
||||||
|
config STRICT_DEVMEM
|
||||||
|
bool "Filter access to /dev/mem"
|
||||||
|
depends on MMU
|
||||||
|
---help---
|
||||||
|
If this option is disabled, you allow userspace (root) access to all
|
||||||
|
of memory, including kernel and userspace memory. Accidental
|
||||||
|
access to this is obviously disastrous, but specific access can
|
||||||
|
be used by people debugging the kernel.
|
||||||
|
|
||||||
|
If this option is switched on, the /dev/mem file only allows
|
||||||
|
userspace access to memory mapped peripherals.
|
||||||
|
|
||||||
|
If in doubt, say Y.
|
||||||
|
|
||||||
# RMK wants arm kernels compiled with frame pointers or stack unwinding.
|
# RMK wants arm kernels compiled with frame pointers or stack unwinding.
|
||||||
# If you know what you are doing and are willing to live without stack
|
# If you know what you are doing and are willing to live without stack
|
||||||
# traces, you can get a slightly smaller kernel by setting this option to
|
# traces, you can get a slightly smaller kernel by setting this option to
|
||||||
|
@ -27,6 +41,11 @@ config ARM_UNWIND
|
||||||
the performance is not affected. Currently, this feature
|
the performance is not affected. Currently, this feature
|
||||||
only works with EABI compilers. If unsure say Y.
|
only works with EABI compilers. If unsure say Y.
|
||||||
|
|
||||||
|
config OLD_MCOUNT
|
||||||
|
bool
|
||||||
|
depends on FUNCTION_TRACER && FRAME_POINTER
|
||||||
|
default y
|
||||||
|
|
||||||
config DEBUG_USER
|
config DEBUG_USER
|
||||||
bool "Verbose user fault messages"
|
bool "Verbose user fault messages"
|
||||||
help
|
help
|
||||||
|
|
|
@ -173,7 +173,7 @@ machine-$(CONFIG_ARCH_RPC) := rpc
|
||||||
machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443
|
machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2416 s3c2440 s3c2443
|
||||||
machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0
|
machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0
|
||||||
machine-$(CONFIG_ARCH_S3C64XX) := s3c64xx
|
machine-$(CONFIG_ARCH_S3C64XX) := s3c64xx
|
||||||
machine-$(CONFIG_ARCH_S5P6440) := s5p6440
|
machine-$(CONFIG_ARCH_S5P64X0) := s5p64x0
|
||||||
machine-$(CONFIG_ARCH_S5P6442) := s5p6442
|
machine-$(CONFIG_ARCH_S5P6442) := s5p6442
|
||||||
machine-$(CONFIG_ARCH_S5PC100) := s5pc100
|
machine-$(CONFIG_ARCH_S5PC100) := s5pc100
|
||||||
machine-$(CONFIG_ARCH_S5PV210) := s5pv210
|
machine-$(CONFIG_ARCH_S5PV210) := s5pv210
|
||||||
|
@ -183,6 +183,7 @@ machine-$(CONFIG_ARCH_SHARK) := shark
|
||||||
machine-$(CONFIG_ARCH_SHMOBILE) := shmobile
|
machine-$(CONFIG_ARCH_SHMOBILE) := shmobile
|
||||||
machine-$(CONFIG_ARCH_STMP378X) := stmp378x
|
machine-$(CONFIG_ARCH_STMP378X) := stmp378x
|
||||||
machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx
|
machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx
|
||||||
|
machine-$(CONFIG_ARCH_TCC8K) := tcc8k
|
||||||
machine-$(CONFIG_ARCH_TEGRA) := tegra
|
machine-$(CONFIG_ARCH_TEGRA) := tegra
|
||||||
machine-$(CONFIG_ARCH_U300) := u300
|
machine-$(CONFIG_ARCH_U300) := u300
|
||||||
machine-$(CONFIG_ARCH_U8500) := ux500
|
machine-$(CONFIG_ARCH_U8500) := ux500
|
||||||
|
@ -202,6 +203,7 @@ plat-$(CONFIG_ARCH_MXC) := mxc
|
||||||
plat-$(CONFIG_ARCH_OMAP) := omap
|
plat-$(CONFIG_ARCH_OMAP) := omap
|
||||||
plat-$(CONFIG_ARCH_S3C64XX) := samsung
|
plat-$(CONFIG_ARCH_S3C64XX) := samsung
|
||||||
plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
|
plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
|
||||||
|
plat-$(CONFIG_ARCH_TCC_926) := tcc
|
||||||
plat-$(CONFIG_PLAT_IOP) := iop
|
plat-$(CONFIG_PLAT_IOP) := iop
|
||||||
plat-$(CONFIG_PLAT_NOMADIK) := nomadik
|
plat-$(CONFIG_PLAT_NOMADIK) := nomadik
|
||||||
plat-$(CONFIG_PLAT_ORION) := orion
|
plat-$(CONFIG_PLAT_ORION) := orion
|
||||||
|
@ -245,13 +247,14 @@ ifeq ($(FASTFPE),$(wildcard $(FASTFPE)))
|
||||||
FASTFPE_OBJ :=$(FASTFPE)/
|
FASTFPE_OBJ :=$(FASTFPE)/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# If we have a machine-specific directory, then include it in the build.
|
|
||||||
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
|
|
||||||
core-y += $(machdirs) $(platdirs)
|
|
||||||
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
|
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
|
||||||
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
|
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
|
||||||
core-$(CONFIG_VFP) += arch/arm/vfp/
|
core-$(CONFIG_VFP) += arch/arm/vfp/
|
||||||
|
|
||||||
|
# If we have a machine-specific directory, then include it in the build.
|
||||||
|
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
|
||||||
|
core-y += $(machdirs) $(platdirs)
|
||||||
|
|
||||||
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
|
||||||
|
|
||||||
libs-y := arch/arm/lib/ $(libs-y)
|
libs-y := arch/arm/lib/ $(libs-y)
|
||||||
|
|
|
@ -67,25 +67,11 @@ static inline unsigned int gic_irq(unsigned int irq)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Routines to acknowledge, disable and enable interrupts
|
* Routines to acknowledge, disable and enable interrupts
|
||||||
*
|
|
||||||
* Linux assumes that when we're done with an interrupt we need to
|
|
||||||
* unmask it, in the same way we need to unmask an interrupt when
|
|
||||||
* we first enable it.
|
|
||||||
*
|
|
||||||
* The GIC has a separate notion of "end of interrupt" to re-enable
|
|
||||||
* an interrupt after handling, in order to support hardware
|
|
||||||
* prioritisation.
|
|
||||||
*
|
|
||||||
* We can make the GIC behave in the way that Linux expects by making
|
|
||||||
* our "acknowledge" routine disable the interrupt, then mark it as
|
|
||||||
* complete.
|
|
||||||
*/
|
*/
|
||||||
static void gic_ack_irq(unsigned int irq)
|
static void gic_ack_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
u32 mask = 1 << (irq % 32);
|
|
||||||
|
|
||||||
spin_lock(&irq_controller_lock);
|
spin_lock(&irq_controller_lock);
|
||||||
writel(mask, gic_dist_base(irq) + GIC_DIST_ENABLE_CLEAR + (gic_irq(irq) / 32) * 4);
|
|
||||||
writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
|
writel(gic_irq(irq), gic_cpu_base(irq) + GIC_CPU_EOI);
|
||||||
spin_unlock(&irq_controller_lock);
|
spin_unlock(&irq_controller_lock);
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,8 +146,7 @@
|
||||||
#define DESIGNER 0x41
|
#define DESIGNER 0x41
|
||||||
#define REVISION 0x0
|
#define REVISION 0x0
|
||||||
#define INTEG_CFG 0x0
|
#define INTEG_CFG 0x0
|
||||||
#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12) \
|
#define PERIPH_ID_VAL ((PART << 0) | (DESIGNER << 12))
|
||||||
| (REVISION << 20) | (INTEG_CFG << 24))
|
|
||||||
|
|
||||||
#define PCELL_ID_VAL 0xb105f00d
|
#define PCELL_ID_VAL 0xb105f00d
|
||||||
|
|
||||||
|
@ -1859,10 +1858,10 @@ int pl330_add(struct pl330_info *pi)
|
||||||
regs = pi->base;
|
regs = pi->base;
|
||||||
|
|
||||||
/* Check if we can handle this DMAC */
|
/* Check if we can handle this DMAC */
|
||||||
if (get_id(pi, PERIPH_ID) != PERIPH_ID_VAL
|
if ((get_id(pi, PERIPH_ID) & 0xfffff) != PERIPH_ID_VAL
|
||||||
|| get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
|
|| get_id(pi, PCELL_ID) != PCELL_ID_VAL) {
|
||||||
dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
|
dev_err(pi->dev, "PERIPH_ID 0x%x, PCELL_ID 0x%x !\n",
|
||||||
readl(regs + PERIPH_ID), readl(regs + PCELL_ID));
|
get_id(pi, PERIPH_ID), get_id(pi, PCELL_ID));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -678,7 +678,7 @@ out:
|
||||||
* %-EBUSY physical address already marked in-use.
|
* %-EBUSY physical address already marked in-use.
|
||||||
* %0 successful.
|
* %0 successful.
|
||||||
*/
|
*/
|
||||||
static int
|
static int __devinit
|
||||||
__sa1111_probe(struct device *me, struct resource *mem, int irq)
|
__sa1111_probe(struct device *me, struct resource *mem, int irq)
|
||||||
{
|
{
|
||||||
struct sa1111 *sachip;
|
struct sa1111 *sachip;
|
||||||
|
|
|
@ -13,6 +13,7 @@ CONFIG_MODULE_UNLOAD=y
|
||||||
CONFIG_ARCH_AT91=y
|
CONFIG_ARCH_AT91=y
|
||||||
CONFIG_ARCH_AT91SAM9G20=y
|
CONFIG_ARCH_AT91SAM9G20=y
|
||||||
CONFIG_MACH_AT91SAM9G20EK=y
|
CONFIG_MACH_AT91SAM9G20EK=y
|
||||||
|
CONFIG_MACH_AT91SAM9G20EK_2MMC=y
|
||||||
CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
|
CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
|
||||||
# CONFIG_ARM_THUMB is not set
|
# CONFIG_ARM_THUMB is not set
|
||||||
CONFIG_AEABI=y
|
CONFIG_AEABI=y
|
||||||
|
|
|
@ -15,6 +15,7 @@ CONFIG_MACH_MV88F6281GTW_GE=y
|
||||||
CONFIG_MACH_SHEEVAPLUG=y
|
CONFIG_MACH_SHEEVAPLUG=y
|
||||||
CONFIG_MACH_ESATA_SHEEVAPLUG=y
|
CONFIG_MACH_ESATA_SHEEVAPLUG=y
|
||||||
CONFIG_MACH_GURUPLUG=y
|
CONFIG_MACH_GURUPLUG=y
|
||||||
|
CONFIG_MACH_DOCKSTAR=y
|
||||||
CONFIG_MACH_TS219=y
|
CONFIG_MACH_TS219=y
|
||||||
CONFIG_MACH_TS41X=y
|
CONFIG_MACH_TS41X=y
|
||||||
CONFIG_MACH_OPENRD_BASE=y
|
CONFIG_MACH_OPENRD_BASE=y
|
||||||
|
|
|
@ -21,8 +21,14 @@ CONFIG_ARCH_MX2=y
|
||||||
CONFIG_MACH_MX27=y
|
CONFIG_MACH_MX27=y
|
||||||
CONFIG_MACH_MX27ADS=y
|
CONFIG_MACH_MX27ADS=y
|
||||||
CONFIG_MACH_PCM038=y
|
CONFIG_MACH_PCM038=y
|
||||||
|
CONFIG_MACH_CPUIMX27=y
|
||||||
|
CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2=y
|
||||||
|
CONFIG_MACH_EUKREA_CPUIMX27_USEUART4=y
|
||||||
CONFIG_MACH_MX27_3DS=y
|
CONFIG_MACH_MX27_3DS=y
|
||||||
|
CONFIG_MACH_IMX27_VISSTRIM_M10=y
|
||||||
CONFIG_MACH_IMX27LITE=y
|
CONFIG_MACH_IMX27LITE=y
|
||||||
|
CONFIG_MACH_PCA100=y
|
||||||
|
CONFIG_MACH_MXT_TD60=y
|
||||||
CONFIG_MXC_IRQ_PRIOR=y
|
CONFIG_MXC_IRQ_PRIOR=y
|
||||||
CONFIG_MXC_PWM=y
|
CONFIG_MXC_PWM=y
|
||||||
CONFIG_NO_HZ=y
|
CONFIG_NO_HZ=y
|
||||||
|
@ -76,7 +82,9 @@ CONFIG_INPUT_EVDEV=y
|
||||||
# CONFIG_INPUT_KEYBOARD is not set
|
# CONFIG_INPUT_KEYBOARD is not set
|
||||||
# CONFIG_INPUT_MOUSE is not set
|
# CONFIG_INPUT_MOUSE is not set
|
||||||
CONFIG_INPUT_TOUCHSCREEN=y
|
CONFIG_INPUT_TOUCHSCREEN=y
|
||||||
|
CONFIG_TOUCHSCREEN_ADS7846=m
|
||||||
# CONFIG_SERIO is not set
|
# CONFIG_SERIO is not set
|
||||||
|
CONFIG_SERIAL_8250=m
|
||||||
CONFIG_SERIAL_IMX=y
|
CONFIG_SERIAL_IMX=y
|
||||||
CONFIG_SERIAL_IMX_CONSOLE=y
|
CONFIG_SERIAL_IMX_CONSOLE=y
|
||||||
# CONFIG_LEGACY_PTYS is not set
|
# CONFIG_LEGACY_PTYS is not set
|
||||||
|
@ -85,19 +93,20 @@ CONFIG_I2C=y
|
||||||
CONFIG_I2C_CHARDEV=y
|
CONFIG_I2C_CHARDEV=y
|
||||||
CONFIG_I2C_IMX=y
|
CONFIG_I2C_IMX=y
|
||||||
CONFIG_SPI=y
|
CONFIG_SPI=y
|
||||||
CONFIG_SPI_BITBANG=y
|
CONFIG_SPI_IMX=y
|
||||||
CONFIG_W1=y
|
CONFIG_W1=y
|
||||||
CONFIG_W1_MASTER_MXC=y
|
CONFIG_W1_MASTER_MXC=y
|
||||||
CONFIG_W1_SLAVE_THERM=y
|
CONFIG_W1_SLAVE_THERM=y
|
||||||
# CONFIG_HWMON is not set
|
# CONFIG_HWMON is not set
|
||||||
CONFIG_FB=y
|
CONFIG_FB=y
|
||||||
CONFIG_FB_IMX=y
|
CONFIG_FB_IMX=y
|
||||||
# CONFIG_VGA_CONSOLE is not set
|
|
||||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||||
CONFIG_FONTS=y
|
CONFIG_FONTS=y
|
||||||
CONFIG_FONT_8x8=y
|
CONFIG_FONT_8x8=y
|
||||||
# CONFIG_HID_SUPPORT is not set
|
# CONFIG_HID_SUPPORT is not set
|
||||||
# CONFIG_USB_SUPPORT is not set
|
CONFIG_USB=m
|
||||||
|
# CONFIG_USB_DEVICE_CLASS is not set
|
||||||
|
CONFIG_USB_ULPI=y
|
||||||
CONFIG_MMC=y
|
CONFIG_MMC=y
|
||||||
CONFIG_MMC_MXC=y
|
CONFIG_MMC_MXC=y
|
||||||
CONFIG_RTC_CLASS=y
|
CONFIG_RTC_CLASS=y
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
# CONFIG_LOCALVERSION_AUTO is not set
|
|
||||||
# CONFIG_SWAP is not set
|
|
||||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
|
||||||
# CONFIG_COMPAT_BRK is not set
|
|
||||||
# CONFIG_IOSCHED_DEADLINE is not set
|
|
||||||
# CONFIG_IOSCHED_CFQ is not set
|
|
||||||
CONFIG_ARCH_MXC=y
|
|
||||||
# CONFIG_MACH_MX31ADS is not set
|
|
||||||
CONFIG_MACH_MX31_3DS=y
|
|
||||||
CONFIG_AEABI=y
|
|
||||||
CONFIG_NET=y
|
|
||||||
CONFIG_PACKET=y
|
|
||||||
CONFIG_UNIX=y
|
|
||||||
CONFIG_NET_KEY=y
|
|
||||||
CONFIG_INET=y
|
|
||||||
CONFIG_IP_PNP=y
|
|
||||||
CONFIG_IP_PNP_DHCP=y
|
|
||||||
# CONFIG_INET_LRO is not set
|
|
||||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
|
||||||
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
|
||||||
# CONFIG_FIRMWARE_IN_KERNEL is not set
|
|
||||||
# CONFIG_BLK_DEV is not set
|
|
||||||
# CONFIG_MISC_DEVICES is not set
|
|
||||||
CONFIG_NETDEVICES=y
|
|
||||||
CONFIG_NET_ETHERNET=y
|
|
||||||
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
|
|
||||||
# CONFIG_INPUT_KEYBOARD is not set
|
|
||||||
# CONFIG_INPUT_MOUSE is not set
|
|
||||||
# CONFIG_SERIO is not set
|
|
||||||
# CONFIG_DEVKMEM is not set
|
|
||||||
CONFIG_SERIAL_IMX=y
|
|
||||||
CONFIG_SERIAL_IMX_CONSOLE=y
|
|
||||||
# CONFIG_LEGACY_PTYS is not set
|
|
||||||
# CONFIG_HW_RANDOM is not set
|
|
||||||
# CONFIG_HWMON is not set
|
|
||||||
# CONFIG_VGA_CONSOLE is not set
|
|
||||||
# CONFIG_HID_SUPPORT is not set
|
|
||||||
# CONFIG_USB_SUPPORT is not set
|
|
||||||
# CONFIG_DNOTIFY is not set
|
|
||||||
# CONFIG_ENABLE_WARN_DEPRECATED is not set
|
|
||||||
# CONFIG_ENABLE_MUST_CHECK is not set
|
|
||||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
|
||||||
# CONFIG_CRYPTO_ANSI_CPRNG is not set
|
|
||||||
# CONFIG_CRC32 is not set
|
|
|
@ -24,6 +24,7 @@ CONFIG_MACH_PCM043=y
|
||||||
CONFIG_MACH_ARMADILLO5X0=y
|
CONFIG_MACH_ARMADILLO5X0=y
|
||||||
CONFIG_MACH_MX35_3DS=y
|
CONFIG_MACH_MX35_3DS=y
|
||||||
CONFIG_MACH_KZM_ARM11_01=y
|
CONFIG_MACH_KZM_ARM11_01=y
|
||||||
|
CONFIG_MACH_EUKREA_CPUIMX35=y
|
||||||
CONFIG_MXC_IRQ_PRIOR=y
|
CONFIG_MXC_IRQ_PRIOR=y
|
||||||
CONFIG_MXC_PWM=y
|
CONFIG_MXC_PWM=y
|
||||||
CONFIG_NO_HZ=y
|
CONFIG_NO_HZ=y
|
||||||
|
@ -108,7 +109,6 @@ CONFIG_MMC=y
|
||||||
CONFIG_MMC_MXC=y
|
CONFIG_MMC_MXC=y
|
||||||
CONFIG_DMADEVICES=y
|
CONFIG_DMADEVICES=y
|
||||||
# CONFIG_DNOTIFY is not set
|
# CONFIG_DNOTIFY is not set
|
||||||
CONFIG_INOTIFY=y
|
|
||||||
CONFIG_TMPFS=y
|
CONFIG_TMPFS=y
|
||||||
CONFIG_JFFS2_FS=y
|
CONFIG_JFFS2_FS=y
|
||||||
CONFIG_UBIFS_FS=y
|
CONFIG_UBIFS_FS=y
|
||||||
|
|
|
@ -15,6 +15,8 @@ CONFIG_MODULE_SRCVERSION_ALL=y
|
||||||
CONFIG_ARCH_MXC=y
|
CONFIG_ARCH_MXC=y
|
||||||
CONFIG_ARCH_MX5=y
|
CONFIG_ARCH_MX5=y
|
||||||
CONFIG_MACH_MX51_BABBAGE=y
|
CONFIG_MACH_MX51_BABBAGE=y
|
||||||
|
CONFIG_MACH_MX51_3DS=y
|
||||||
|
CONFIG_MACH_EUKREA_CPUIMX51=y
|
||||||
CONFIG_NO_HZ=y
|
CONFIG_NO_HZ=y
|
||||||
CONFIG_HIGH_RES_TIMERS=y
|
CONFIG_HIGH_RES_TIMERS=y
|
||||||
CONFIG_PREEMPT_VOLUNTARY=y
|
CONFIG_PREEMPT_VOLUNTARY=y
|
||||||
|
@ -69,7 +71,6 @@ CONFIG_REALTEK_PHY=y
|
||||||
CONFIG_NATIONAL_PHY=y
|
CONFIG_NATIONAL_PHY=y
|
||||||
CONFIG_STE10XP=y
|
CONFIG_STE10XP=y
|
||||||
CONFIG_LSI_ET1011C_PHY=y
|
CONFIG_LSI_ET1011C_PHY=y
|
||||||
CONFIG_FIXED_PHY=y
|
|
||||||
CONFIG_MDIO_BITBANG=y
|
CONFIG_MDIO_BITBANG=y
|
||||||
CONFIG_MDIO_GPIO=y
|
CONFIG_MDIO_GPIO=y
|
||||||
CONFIG_NET_ETHERNET=y
|
CONFIG_NET_ETHERNET=y
|
||||||
|
@ -100,7 +101,6 @@ CONFIG_I2C_ALGOPCF=m
|
||||||
CONFIG_I2C_ALGOPCA=m
|
CONFIG_I2C_ALGOPCA=m
|
||||||
CONFIG_GPIO_SYSFS=y
|
CONFIG_GPIO_SYSFS=y
|
||||||
# CONFIG_HWMON is not set
|
# CONFIG_HWMON is not set
|
||||||
# CONFIG_VGA_CONSOLE is not set
|
|
||||||
# CONFIG_HID_SUPPORT is not set
|
# CONFIG_HID_SUPPORT is not set
|
||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_USB_EHCI_HCD=y
|
CONFIG_USB_EHCI_HCD=y
|
||||||
|
@ -117,13 +117,11 @@ CONFIG_EXT2_FS_XATTR=y
|
||||||
CONFIG_EXT2_FS_POSIX_ACL=y
|
CONFIG_EXT2_FS_POSIX_ACL=y
|
||||||
CONFIG_EXT2_FS_SECURITY=y
|
CONFIG_EXT2_FS_SECURITY=y
|
||||||
CONFIG_EXT3_FS=y
|
CONFIG_EXT3_FS=y
|
||||||
CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
|
|
||||||
CONFIG_EXT3_FS_POSIX_ACL=y
|
CONFIG_EXT3_FS_POSIX_ACL=y
|
||||||
CONFIG_EXT3_FS_SECURITY=y
|
CONFIG_EXT3_FS_SECURITY=y
|
||||||
CONFIG_EXT4_FS=y
|
CONFIG_EXT4_FS=y
|
||||||
CONFIG_EXT4_FS_POSIX_ACL=y
|
CONFIG_EXT4_FS_POSIX_ACL=y
|
||||||
CONFIG_EXT4_FS_SECURITY=y
|
CONFIG_EXT4_FS_SECURITY=y
|
||||||
CONFIG_INOTIFY=y
|
|
||||||
CONFIG_QUOTA=y
|
CONFIG_QUOTA=y
|
||||||
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
CONFIG_QUOTA_NETLINK_INTERFACE=y
|
||||||
# CONFIG_PRINT_QUOTA_WARNING is not set
|
# CONFIG_PRINT_QUOTA_WARNING is not set
|
||||||
|
@ -136,6 +134,7 @@ CONFIG_ZISOFS=y
|
||||||
CONFIG_UDF_FS=m
|
CONFIG_UDF_FS=m
|
||||||
CONFIG_MSDOS_FS=m
|
CONFIG_MSDOS_FS=m
|
||||||
CONFIG_VFAT_FS=y
|
CONFIG_VFAT_FS=y
|
||||||
|
CONFIG_TMPFS=y
|
||||||
CONFIG_CONFIGFS_FS=m
|
CONFIG_CONFIGFS_FS=m
|
||||||
CONFIG_NFS_FS=y
|
CONFIG_NFS_FS=y
|
||||||
CONFIG_NFS_V3=y
|
CONFIG_NFS_V3=y
|
||||||
|
@ -151,7 +150,6 @@ CONFIG_NLS_UTF8=y
|
||||||
CONFIG_MAGIC_SYSRQ=y
|
CONFIG_MAGIC_SYSRQ=y
|
||||||
CONFIG_DEBUG_FS=y
|
CONFIG_DEBUG_FS=y
|
||||||
CONFIG_DEBUG_KERNEL=y
|
CONFIG_DEBUG_KERNEL=y
|
||||||
# CONFIG_DETECT_SOFTLOCKUP is not set
|
|
||||||
# CONFIG_SCHED_DEBUG is not set
|
# CONFIG_SCHED_DEBUG is not set
|
||||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||||
|
@ -159,7 +157,6 @@ CONFIG_DEBUG_KERNEL=y
|
||||||
# CONFIG_ARM_UNWIND is not set
|
# CONFIG_ARM_UNWIND is not set
|
||||||
CONFIG_DEBUG_LL=y
|
CONFIG_DEBUG_LL=y
|
||||||
CONFIG_EARLY_PRINTK=y
|
CONFIG_EARLY_PRINTK=y
|
||||||
CONFIG_KEYS=y
|
|
||||||
CONFIG_SECURITYFS=y
|
CONFIG_SECURITYFS=y
|
||||||
CONFIG_CRYPTO_DEFLATE=y
|
CONFIG_CRYPTO_DEFLATE=y
|
||||||
CONFIG_CRYPTO_LZO=y
|
CONFIG_CRYPTO_LZO=y
|
||||||
|
|
|
@ -39,6 +39,7 @@ CONFIG_MTD_CFI=y
|
||||||
CONFIG_MTD_CFI_INTELEXT=y
|
CONFIG_MTD_CFI_INTELEXT=y
|
||||||
CONFIG_MTD_CFI_AMDSTD=y
|
CONFIG_MTD_CFI_AMDSTD=y
|
||||||
CONFIG_MTD_ARM_INTEGRATOR=y
|
CONFIG_MTD_ARM_INTEGRATOR=y
|
||||||
|
CONFIG_ARM_CHARLCD=y
|
||||||
CONFIG_NETDEVICES=y
|
CONFIG_NETDEVICES=y
|
||||||
CONFIG_SMSC_PHY=y
|
CONFIG_SMSC_PHY=y
|
||||||
CONFIG_NET_ETHERNET=y
|
CONFIG_NET_ETHERNET=y
|
||||||
|
@ -52,10 +53,13 @@ CONFIG_SERIAL_AMBA_PL011=y
|
||||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||||
CONFIG_LEGACY_PTY_COUNT=16
|
CONFIG_LEGACY_PTY_COUNT=16
|
||||||
# CONFIG_HW_RANDOM is not set
|
# CONFIG_HW_RANDOM is not set
|
||||||
|
CONFIG_I2C=y
|
||||||
|
CONFIG_I2C_VERSATILE=y
|
||||||
|
CONFIG_SPI=y
|
||||||
|
CONFIG_GPIOLIB=y
|
||||||
# CONFIG_HWMON is not set
|
# CONFIG_HWMON is not set
|
||||||
CONFIG_FB=y
|
CONFIG_FB=y
|
||||||
CONFIG_FB_ARMCLCD=y
|
CONFIG_FB_ARMCLCD=y
|
||||||
# CONFIG_VGA_CONSOLE is not set
|
|
||||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||||
CONFIG_LOGO=y
|
CONFIG_LOGO=y
|
||||||
# CONFIG_LOGO_LINUX_MONO is not set
|
# CONFIG_LOGO_LINUX_MONO is not set
|
||||||
|
@ -70,7 +74,13 @@ CONFIG_SND_ARMAACI=y
|
||||||
# CONFIG_USB_SUPPORT is not set
|
# CONFIG_USB_SUPPORT is not set
|
||||||
CONFIG_MMC=y
|
CONFIG_MMC=y
|
||||||
CONFIG_MMC_ARMMMCI=y
|
CONFIG_MMC_ARMMMCI=y
|
||||||
CONFIG_INOTIFY=y
|
CONFIG_NEW_LEDS=y
|
||||||
|
CONFIG_LEDS_CLASS=y
|
||||||
|
CONFIG_LEDS_TRIGGERS=y
|
||||||
|
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
|
||||||
|
CONFIG_RTC_CLASS=y
|
||||||
|
CONFIG_RTC_DRV_DS1307=y
|
||||||
|
CONFIG_RTC_DRV_PL031=y
|
||||||
CONFIG_VFAT_FS=y
|
CONFIG_VFAT_FS=y
|
||||||
CONFIG_TMPFS=y
|
CONFIG_TMPFS=y
|
||||||
CONFIG_CRAMFS=y
|
CONFIG_CRAMFS=y
|
||||||
|
@ -80,6 +90,7 @@ CONFIG_ROOT_NFS=y
|
||||||
CONFIG_NLS_CODEPAGE_437=y
|
CONFIG_NLS_CODEPAGE_437=y
|
||||||
CONFIG_NLS_ISO8859_1=y
|
CONFIG_NLS_ISO8859_1=y
|
||||||
CONFIG_MAGIC_SYSRQ=y
|
CONFIG_MAGIC_SYSRQ=y
|
||||||
|
CONFIG_DEBUG_FS=y
|
||||||
CONFIG_DEBUG_KERNEL=y
|
CONFIG_DEBUG_KERNEL=y
|
||||||
# CONFIG_SCHED_DEBUG is not set
|
# CONFIG_SCHED_DEBUG is not set
|
||||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||||
|
|
|
@ -38,6 +38,7 @@ CONFIG_MTD_CFI=y
|
||||||
CONFIG_MTD_CFI_INTELEXT=y
|
CONFIG_MTD_CFI_INTELEXT=y
|
||||||
CONFIG_MTD_CFI_AMDSTD=y
|
CONFIG_MTD_CFI_AMDSTD=y
|
||||||
CONFIG_MTD_ARM_INTEGRATOR=y
|
CONFIG_MTD_ARM_INTEGRATOR=y
|
||||||
|
CONFIG_ARM_CHARLCD=y
|
||||||
CONFIG_NETDEVICES=y
|
CONFIG_NETDEVICES=y
|
||||||
CONFIG_SMSC_PHY=y
|
CONFIG_SMSC_PHY=y
|
||||||
CONFIG_NET_ETHERNET=y
|
CONFIG_NET_ETHERNET=y
|
||||||
|
@ -51,10 +52,13 @@ CONFIG_SERIAL_AMBA_PL011=y
|
||||||
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||||
CONFIG_LEGACY_PTY_COUNT=16
|
CONFIG_LEGACY_PTY_COUNT=16
|
||||||
# CONFIG_HW_RANDOM is not set
|
# CONFIG_HW_RANDOM is not set
|
||||||
|
CONFIG_I2C=y
|
||||||
|
CONFIG_I2C_VERSATILE=y
|
||||||
|
CONFIG_SPI=y
|
||||||
|
CONFIG_GPIOLIB=y
|
||||||
# CONFIG_HWMON is not set
|
# CONFIG_HWMON is not set
|
||||||
CONFIG_FB=y
|
CONFIG_FB=y
|
||||||
CONFIG_FB_ARMCLCD=y
|
CONFIG_FB_ARMCLCD=y
|
||||||
# CONFIG_VGA_CONSOLE is not set
|
|
||||||
CONFIG_FRAMEBUFFER_CONSOLE=y
|
CONFIG_FRAMEBUFFER_CONSOLE=y
|
||||||
CONFIG_LOGO=y
|
CONFIG_LOGO=y
|
||||||
# CONFIG_LOGO_LINUX_MONO is not set
|
# CONFIG_LOGO_LINUX_MONO is not set
|
||||||
|
@ -69,7 +73,13 @@ CONFIG_SND_ARMAACI=y
|
||||||
# CONFIG_USB_SUPPORT is not set
|
# CONFIG_USB_SUPPORT is not set
|
||||||
CONFIG_MMC=y
|
CONFIG_MMC=y
|
||||||
CONFIG_MMC_ARMMMCI=y
|
CONFIG_MMC_ARMMMCI=y
|
||||||
CONFIG_INOTIFY=y
|
CONFIG_NEW_LEDS=y
|
||||||
|
CONFIG_LEDS_CLASS=y
|
||||||
|
CONFIG_LEDS_TRIGGERS=y
|
||||||
|
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
|
||||||
|
CONFIG_RTC_CLASS=y
|
||||||
|
CONFIG_RTC_DRV_DS1307=y
|
||||||
|
CONFIG_RTC_DRV_PL031=y
|
||||||
CONFIG_VFAT_FS=y
|
CONFIG_VFAT_FS=y
|
||||||
CONFIG_TMPFS=y
|
CONFIG_TMPFS=y
|
||||||
CONFIG_CRAMFS=y
|
CONFIG_CRAMFS=y
|
||||||
|
@ -79,6 +89,7 @@ CONFIG_ROOT_NFS=y
|
||||||
CONFIG_NLS_CODEPAGE_437=y
|
CONFIG_NLS_CODEPAGE_437=y
|
||||||
CONFIG_NLS_ISO8859_1=y
|
CONFIG_NLS_ISO8859_1=y
|
||||||
CONFIG_MAGIC_SYSRQ=y
|
CONFIG_MAGIC_SYSRQ=y
|
||||||
|
CONFIG_DEBUG_FS=y
|
||||||
CONFIG_DEBUG_KERNEL=y
|
CONFIG_DEBUG_KERNEL=y
|
||||||
# CONFIG_SCHED_DEBUG is not set
|
# CONFIG_SCHED_DEBUG is not set
|
||||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||||
|
|
|
@ -5,10 +5,11 @@ CONFIG_KALLSYMS_ALL=y
|
||||||
CONFIG_MODULES=y
|
CONFIG_MODULES=y
|
||||||
CONFIG_MODULE_UNLOAD=y
|
CONFIG_MODULE_UNLOAD=y
|
||||||
# CONFIG_BLK_DEV_BSG is not set
|
# CONFIG_BLK_DEV_BSG is not set
|
||||||
CONFIG_ARCH_S5P6440=y
|
CONFIG_ARCH_S5P64X0=y
|
||||||
CONFIG_S3C_BOOT_ERROR_RESET=y
|
CONFIG_S3C_BOOT_ERROR_RESET=y
|
||||||
CONFIG_S3C_LOWLEVEL_UART_PORT=1
|
CONFIG_S3C_LOWLEVEL_UART_PORT=1
|
||||||
CONFIG_MACH_SMDK6440=y
|
CONFIG_MACH_SMDK6440=y
|
||||||
|
CONFIG_MACH_SMDK6450=y
|
||||||
CONFIG_CPU_32v6K=y
|
CONFIG_CPU_32v6K=y
|
||||||
CONFIG_AEABI=y
|
CONFIG_AEABI=y
|
||||||
CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
|
CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
|
|
@ -28,26 +28,9 @@ CONFIG_CPU_IDLE=y
|
||||||
CONFIG_FPE_NWFPE=y
|
CONFIG_FPE_NWFPE=y
|
||||||
CONFIG_PM=y
|
CONFIG_PM=y
|
||||||
# CONFIG_SUSPEND is not set
|
# CONFIG_SUSPEND is not set
|
||||||
CONFIG_NET=y
|
|
||||||
CONFIG_PACKET=y
|
|
||||||
CONFIG_UNIX=y
|
|
||||||
CONFIG_INET=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 is not set
|
|
||||||
# CONFIG_WIRELESS is not set
|
|
||||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||||
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
|
||||||
CONFIG_MTD=y
|
# CONFIG_MISC_DEVICES is not set
|
||||||
CONFIG_MTD_PARTITIONS=y
|
|
||||||
CONFIG_MTD_CMDLINE_PARTS=y
|
|
||||||
CONFIG_MTD_CHAR=y
|
|
||||||
CONFIG_MTD_BLOCK=y
|
|
||||||
CONFIG_MTD_NAND=y
|
|
||||||
CONFIG_MTD_NAND_ECC_SMC=y
|
|
||||||
# CONFIG_INPUT_MOUSEDEV is not set
|
# CONFIG_INPUT_MOUSEDEV is not set
|
||||||
CONFIG_INPUT_EVDEV=y
|
CONFIG_INPUT_EVDEV=y
|
||||||
# CONFIG_KEYBOARD_ATKBD is not set
|
# CONFIG_KEYBOARD_ATKBD is not set
|
||||||
|
@ -58,7 +41,6 @@ CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
|
||||||
CONFIG_LEGACY_PTY_COUNT=16
|
CONFIG_LEGACY_PTY_COUNT=16
|
||||||
# CONFIG_HW_RANDOM is not set
|
# CONFIG_HW_RANDOM is not set
|
||||||
CONFIG_I2C=y
|
CONFIG_I2C=y
|
||||||
CONFIG_POWER_SUPPLY=y
|
|
||||||
# CONFIG_HWMON is not set
|
# CONFIG_HWMON is not set
|
||||||
CONFIG_WATCHDOG=y
|
CONFIG_WATCHDOG=y
|
||||||
CONFIG_REGULATOR=y
|
CONFIG_REGULATOR=y
|
||||||
|
@ -66,24 +48,10 @@ CONFIG_FB=y
|
||||||
CONFIG_BACKLIGHT_LCD_SUPPORT=y
|
CONFIG_BACKLIGHT_LCD_SUPPORT=y
|
||||||
# CONFIG_LCD_CLASS_DEVICE is not set
|
# CONFIG_LCD_CLASS_DEVICE is not set
|
||||||
CONFIG_BACKLIGHT_CLASS_DEVICE=y
|
CONFIG_BACKLIGHT_CLASS_DEVICE=y
|
||||||
# CONFIG_VGA_CONSOLE is not set
|
|
||||||
CONFIG_SOUND=y
|
|
||||||
CONFIG_SND=y
|
|
||||||
# CONFIG_SND_SUPPORT_OLD_API is not set
|
|
||||||
# CONFIG_SND_VERBOSE_PROCFS is not set
|
|
||||||
# CONFIG_SND_DRIVERS is not set
|
|
||||||
# CONFIG_SND_ARM is not set
|
|
||||||
# CONFIG_SND_SPI is not set
|
|
||||||
CONFIG_SND_SOC=y
|
|
||||||
# CONFIG_HID_SUPPORT is not set
|
# CONFIG_HID_SUPPORT is not set
|
||||||
# CONFIG_USB_SUPPORT is not set
|
# CONFIG_USB_SUPPORT is not set
|
||||||
CONFIG_MMC=y
|
CONFIG_MMC=y
|
||||||
CONFIG_MMC_DEBUG=y
|
|
||||||
CONFIG_MMC_ARMMMCI=y
|
CONFIG_MMC_ARMMMCI=y
|
||||||
CONFIG_NEW_LEDS=y
|
|
||||||
CONFIG_LEDS_CLASS=y
|
|
||||||
CONFIG_LEDS_TRIGGERS=y
|
|
||||||
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
|
|
||||||
CONFIG_RTC_CLASS=y
|
CONFIG_RTC_CLASS=y
|
||||||
# CONFIG_RTC_HCTOSYS is not set
|
# CONFIG_RTC_HCTOSYS is not set
|
||||||
CONFIG_RTC_DRV_COH901331=y
|
CONFIG_RTC_DRV_COH901331=y
|
||||||
|
@ -93,12 +61,11 @@ CONFIG_COH901318=y
|
||||||
CONFIG_FUSE_FS=y
|
CONFIG_FUSE_FS=y
|
||||||
CONFIG_VFAT_FS=y
|
CONFIG_VFAT_FS=y
|
||||||
CONFIG_TMPFS=y
|
CONFIG_TMPFS=y
|
||||||
# CONFIG_NETWORK_FILESYSTEMS is not set
|
|
||||||
CONFIG_NLS_CODEPAGE_437=y
|
CONFIG_NLS_CODEPAGE_437=y
|
||||||
CONFIG_NLS_ISO8859_1=y
|
CONFIG_NLS_ISO8859_1=y
|
||||||
CONFIG_PRINTK_TIME=y
|
CONFIG_PRINTK_TIME=y
|
||||||
|
CONFIG_DEBUG_FS=y
|
||||||
CONFIG_DEBUG_KERNEL=y
|
CONFIG_DEBUG_KERNEL=y
|
||||||
# CONFIG_DETECT_SOFTLOCKUP is not set
|
|
||||||
# CONFIG_SCHED_DEBUG is not set
|
# CONFIG_SCHED_DEBUG is not set
|
||||||
CONFIG_TIMER_STATS=y
|
CONFIG_TIMER_STATS=y
|
||||||
# CONFIG_DEBUG_PREEMPT is not set
|
# CONFIG_DEBUG_PREEMPT is not set
|
||||||
|
|
|
@ -154,16 +154,39 @@
|
||||||
.long 9999b,9001f; \
|
.long 9999b,9001f; \
|
||||||
.popsection
|
.popsection
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
#define ALT_SMP(instr...) \
|
||||||
|
9998: instr
|
||||||
|
#define ALT_UP(instr...) \
|
||||||
|
.pushsection ".alt.smp.init", "a" ;\
|
||||||
|
.long 9998b ;\
|
||||||
|
instr ;\
|
||||||
|
.popsection
|
||||||
|
#define ALT_UP_B(label) \
|
||||||
|
.equ up_b_offset, label - 9998b ;\
|
||||||
|
.pushsection ".alt.smp.init", "a" ;\
|
||||||
|
.long 9998b ;\
|
||||||
|
b . + up_b_offset ;\
|
||||||
|
.popsection
|
||||||
|
#else
|
||||||
|
#define ALT_SMP(instr...)
|
||||||
|
#define ALT_UP(instr...) instr
|
||||||
|
#define ALT_UP_B(label) b label
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SMP data memory barrier
|
* SMP data memory barrier
|
||||||
*/
|
*/
|
||||||
.macro smp_dmb
|
.macro smp_dmb
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
#if __LINUX_ARM_ARCH__ >= 7
|
#if __LINUX_ARM_ARCH__ >= 7
|
||||||
dmb
|
ALT_SMP(dmb)
|
||||||
#elif __LINUX_ARM_ARCH__ == 6
|
#elif __LINUX_ARM_ARCH__ == 6
|
||||||
mcr p15, 0, r0, c7, c10, 5 @ dmb
|
ALT_SMP(mcr p15, 0, r0, c7, c10, 5) @ dmb
|
||||||
|
#else
|
||||||
|
#error Incompatible SMP platform
|
||||||
#endif
|
#endif
|
||||||
|
ALT_UP(nop)
|
||||||
#endif
|
#endif
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
|
|
@ -137,10 +137,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This flag is used to indicate that the page pointed to by a pte
|
* This flag is used to indicate that the page pointed to by a pte is clean
|
||||||
* is dirty and requires cleaning before returning it to the user.
|
* and does not require cleaning before returning it to the user.
|
||||||
*/
|
*/
|
||||||
#define PG_dcache_dirty PG_arch_1
|
#define PG_dcache_clean PG_arch_1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MM Cache Management
|
* MM Cache Management
|
||||||
|
@ -156,6 +156,12 @@
|
||||||
* Please note that the implementation of these, and the required
|
* Please note that the implementation of these, and the required
|
||||||
* effects are cache-type (VIVT/VIPT/PIPT) specific.
|
* effects are cache-type (VIVT/VIPT/PIPT) specific.
|
||||||
*
|
*
|
||||||
|
* flush_icache_all()
|
||||||
|
*
|
||||||
|
* Unconditionally clean and invalidate the entire icache.
|
||||||
|
* Currently only needed for cache-v6.S and cache-v7.S, see
|
||||||
|
* __flush_icache_all for the generic implementation.
|
||||||
|
*
|
||||||
* flush_kern_all()
|
* flush_kern_all()
|
||||||
*
|
*
|
||||||
* Unconditionally clean and invalidate the entire cache.
|
* Unconditionally clean and invalidate the entire cache.
|
||||||
|
@ -206,6 +212,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct cpu_cache_fns {
|
struct cpu_cache_fns {
|
||||||
|
void (*flush_icache_all)(void);
|
||||||
void (*flush_kern_all)(void);
|
void (*flush_kern_all)(void);
|
||||||
void (*flush_user_all)(void);
|
void (*flush_user_all)(void);
|
||||||
void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
|
void (*flush_user_range)(unsigned long, unsigned long, unsigned int);
|
||||||
|
@ -227,6 +234,7 @@ struct cpu_cache_fns {
|
||||||
|
|
||||||
extern struct cpu_cache_fns cpu_cache;
|
extern struct cpu_cache_fns cpu_cache;
|
||||||
|
|
||||||
|
#define __cpuc_flush_icache_all cpu_cache.flush_icache_all
|
||||||
#define __cpuc_flush_kern_all cpu_cache.flush_kern_all
|
#define __cpuc_flush_kern_all cpu_cache.flush_kern_all
|
||||||
#define __cpuc_flush_user_all cpu_cache.flush_user_all
|
#define __cpuc_flush_user_all cpu_cache.flush_user_all
|
||||||
#define __cpuc_flush_user_range cpu_cache.flush_user_range
|
#define __cpuc_flush_user_range cpu_cache.flush_user_range
|
||||||
|
@ -246,6 +254,7 @@ extern struct cpu_cache_fns cpu_cache;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all)
|
||||||
#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all)
|
#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all)
|
||||||
#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all)
|
#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all)
|
||||||
#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range)
|
#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range)
|
||||||
|
@ -253,6 +262,7 @@ extern struct cpu_cache_fns cpu_cache;
|
||||||
#define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range)
|
#define __cpuc_coherent_user_range __glue(_CACHE,_coherent_user_range)
|
||||||
#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area)
|
#define __cpuc_flush_dcache_area __glue(_CACHE,_flush_kern_dcache_area)
|
||||||
|
|
||||||
|
extern void __cpuc_flush_icache_all(void);
|
||||||
extern void __cpuc_flush_kern_all(void);
|
extern void __cpuc_flush_kern_all(void);
|
||||||
extern void __cpuc_flush_user_all(void);
|
extern void __cpuc_flush_user_all(void);
|
||||||
extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
|
extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
|
||||||
|
@ -291,6 +301,37 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
|
||||||
/*
|
/*
|
||||||
* Convert calls to our calling convention.
|
* Convert calls to our calling convention.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Invalidate I-cache */
|
||||||
|
#define __flush_icache_all_generic() \
|
||||||
|
asm("mcr p15, 0, %0, c7, c5, 0" \
|
||||||
|
: : "r" (0));
|
||||||
|
|
||||||
|
/* Invalidate I-cache inner shareable */
|
||||||
|
#define __flush_icache_all_v7_smp() \
|
||||||
|
asm("mcr p15, 0, %0, c7, c1, 0" \
|
||||||
|
: : "r" (0));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optimized __flush_icache_all for the common cases. Note that UP ARMv7
|
||||||
|
* will fall through to use __flush_icache_all_generic.
|
||||||
|
*/
|
||||||
|
#if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) || \
|
||||||
|
defined(CONFIG_SMP_ON_UP)
|
||||||
|
#define __flush_icache_preferred __cpuc_flush_icache_all
|
||||||
|
#elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
|
||||||
|
#define __flush_icache_preferred __flush_icache_all_v7_smp
|
||||||
|
#elif __LINUX_ARM_ARCH__ == 6 && defined(CONFIG_ARM_ERRATA_411920)
|
||||||
|
#define __flush_icache_preferred __cpuc_flush_icache_all
|
||||||
|
#else
|
||||||
|
#define __flush_icache_preferred __flush_icache_all_generic
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void __flush_icache_all(void)
|
||||||
|
{
|
||||||
|
__flush_icache_preferred();
|
||||||
|
}
|
||||||
|
|
||||||
#define flush_cache_all() __cpuc_flush_kern_all()
|
#define flush_cache_all() __cpuc_flush_kern_all()
|
||||||
|
|
||||||
static inline void vivt_flush_cache_mm(struct mm_struct *mm)
|
static inline void vivt_flush_cache_mm(struct mm_struct *mm)
|
||||||
|
@ -366,21 +407,6 @@ extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr
|
||||||
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
|
||||||
extern void flush_dcache_page(struct page *);
|
extern void flush_dcache_page(struct page *);
|
||||||
|
|
||||||
static inline void __flush_icache_all(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_ARM_ERRATA_411920
|
|
||||||
extern void v6_icache_inval_all(void);
|
|
||||||
v6_icache_inval_all();
|
|
||||||
#elif defined(CONFIG_SMP) && __LINUX_ARM_ARCH__ >= 7
|
|
||||||
asm("mcr p15, 0, %0, c7, c1, 0 @ invalidate I-cache inner shareable\n"
|
|
||||||
:
|
|
||||||
: "r" (0));
|
|
||||||
#else
|
|
||||||
asm("mcr p15, 0, %0, c7, c5, 0 @ invalidate I-cache\n"
|
|
||||||
:
|
|
||||||
: "r" (0));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
static inline void flush_kernel_vmap_range(void *addr, int size)
|
static inline void flush_kernel_vmap_range(void *addr, int size)
|
||||||
{
|
{
|
||||||
if ((cache_is_vivt() || cache_is_vipt_aliasing()))
|
if ((cache_is_vivt() || cache_is_vipt_aliasing()))
|
||||||
|
@ -405,9 +431,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
|
||||||
#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
|
#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
|
||||||
static inline void flush_kernel_dcache_page(struct page *page)
|
static inline void flush_kernel_dcache_page(struct page *page)
|
||||||
{
|
{
|
||||||
/* highmem pages are always flushed upon kunmap already */
|
|
||||||
if ((cache_is_vivt() || cache_is_vipt_aliasing()) && !PageHighMem(page))
|
|
||||||
__cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define flush_dcache_mmap_lock(mapping) \
|
#define flush_dcache_mmap_lock(mapping) \
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#define CACHEID_VIPT_ALIASING (1 << 2)
|
#define CACHEID_VIPT_ALIASING (1 << 2)
|
||||||
#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
|
#define CACHEID_VIPT (CACHEID_VIPT_ALIASING|CACHEID_VIPT_NONALIASING)
|
||||||
#define CACHEID_ASID_TAGGED (1 << 3)
|
#define CACHEID_ASID_TAGGED (1 << 3)
|
||||||
|
#define CACHEID_VIPT_I_ALIASING (1 << 4)
|
||||||
|
|
||||||
extern unsigned int cacheid;
|
extern unsigned int cacheid;
|
||||||
|
|
||||||
|
@ -14,15 +15,18 @@ extern unsigned int cacheid;
|
||||||
#define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING)
|
#define cache_is_vipt_nonaliasing() cacheid_is(CACHEID_VIPT_NONALIASING)
|
||||||
#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
|
#define cache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_ALIASING)
|
||||||
#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
|
#define icache_is_vivt_asid_tagged() cacheid_is(CACHEID_ASID_TAGGED)
|
||||||
|
#define icache_is_vipt_aliasing() cacheid_is(CACHEID_VIPT_I_ALIASING)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
|
* __LINUX_ARM_ARCH__ is the minimum supported CPU architecture
|
||||||
* Mask out support which will never be present on newer CPUs.
|
* Mask out support which will never be present on newer CPUs.
|
||||||
* - v6+ is never VIVT
|
* - v6+ is never VIVT
|
||||||
* - v7+ VIPT never aliases
|
* - v7+ VIPT never aliases on D-side
|
||||||
*/
|
*/
|
||||||
#if __LINUX_ARM_ARCH__ >= 7
|
#if __LINUX_ARM_ARCH__ >= 7
|
||||||
#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING | CACHEID_ASID_TAGGED)
|
#define __CACHEID_ARCH_MIN (CACHEID_VIPT_NONALIASING |\
|
||||||
|
CACHEID_ASID_TAGGED |\
|
||||||
|
CACHEID_VIPT_I_ALIASING)
|
||||||
#elif __LINUX_ARM_ARCH__ >= 6
|
#elif __LINUX_ARM_ARCH__ >= 6
|
||||||
#define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
|
#define __CACHEID_ARCH_MIN (~CACHEID_VIVT)
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -127,4 +127,8 @@ struct mm_struct;
|
||||||
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
|
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
|
||||||
#define arch_randomize_brk arch_randomize_brk
|
#define arch_randomize_brk arch_randomize_brk
|
||||||
|
|
||||||
|
extern int vectors_user_mapping(void);
|
||||||
|
#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
|
||||||
|
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,12 +2,30 @@
|
||||||
#define _ASM_ARM_FTRACE
|
#define _ASM_ARM_FTRACE
|
||||||
|
|
||||||
#ifdef CONFIG_FUNCTION_TRACER
|
#ifdef CONFIG_FUNCTION_TRACER
|
||||||
#define MCOUNT_ADDR ((long)(mcount))
|
#define MCOUNT_ADDR ((unsigned long)(__gnu_mcount_nc))
|
||||||
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
|
#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
extern void mcount(void);
|
extern void mcount(void);
|
||||||
extern void __gnu_mcount_nc(void);
|
extern void __gnu_mcount_nc(void);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||||
|
struct dyn_arch_ftrace {
|
||||||
|
#ifdef CONFIG_OLD_MCOUNT
|
||||||
|
bool old_mcount;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline unsigned long ftrace_call_adjust(unsigned long addr)
|
||||||
|
{
|
||||||
|
/* With Thumb-2, the recorded addresses have the lsb set */
|
||||||
|
return addr & ~1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void ftrace_caller_old(void);
|
||||||
|
extern void ftrace_call_old(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,18 +21,6 @@
|
||||||
#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT)
|
#define TRACER_RUNNING BIT(TRACER_RUNNING_BIT)
|
||||||
#define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT)
|
#define TRACER_CYCLE_ACC BIT(TRACER_CYCLE_ACC_BIT)
|
||||||
|
|
||||||
struct tracectx {
|
|
||||||
unsigned int etb_bufsz;
|
|
||||||
void __iomem *etb_regs;
|
|
||||||
void __iomem *etm_regs;
|
|
||||||
unsigned long flags;
|
|
||||||
int ncmppairs;
|
|
||||||
int etm_portsz;
|
|
||||||
struct device *dev;
|
|
||||||
struct clk *emu_clk;
|
|
||||||
struct mutex mutex;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TRACER_TIMEOUT 10000
|
#define TRACER_TIMEOUT 10000
|
||||||
|
|
||||||
#define etm_writel(t, v, x) \
|
#define etm_writel(t, v, x) \
|
||||||
|
@ -112,10 +100,10 @@ struct tracectx {
|
||||||
|
|
||||||
/* ETM status register, "ETM Architecture", 3.3.2 */
|
/* ETM status register, "ETM Architecture", 3.3.2 */
|
||||||
#define ETMR_STATUS (0x10)
|
#define ETMR_STATUS (0x10)
|
||||||
#define ETMST_OVERFLOW (1 << 0)
|
#define ETMST_OVERFLOW BIT(0)
|
||||||
#define ETMST_PROGBIT (1 << 1)
|
#define ETMST_PROGBIT BIT(1)
|
||||||
#define ETMST_STARTSTOP (1 << 2)
|
#define ETMST_STARTSTOP BIT(2)
|
||||||
#define ETMST_TRIGGER (1 << 3)
|
#define ETMST_TRIGGER BIT(3)
|
||||||
|
|
||||||
#define etm_progbit(t) (etm_readl((t), ETMR_STATUS) & ETMST_PROGBIT)
|
#define etm_progbit(t) (etm_readl((t), ETMR_STATUS) & ETMST_PROGBIT)
|
||||||
#define etm_started(t) (etm_readl((t), ETMR_STATUS) & ETMST_STARTSTOP)
|
#define etm_started(t) (etm_readl((t), ETMR_STATUS) & ETMST_STARTSTOP)
|
||||||
|
@ -123,7 +111,7 @@ struct tracectx {
|
||||||
|
|
||||||
#define ETMR_TRACEENCTRL2 0x1c
|
#define ETMR_TRACEENCTRL2 0x1c
|
||||||
#define ETMR_TRACEENCTRL 0x24
|
#define ETMR_TRACEENCTRL 0x24
|
||||||
#define ETMTE_INCLEXCL (1 << 24)
|
#define ETMTE_INCLEXCL BIT(24)
|
||||||
#define ETMR_TRACEENEVT 0x20
|
#define ETMR_TRACEENEVT 0x20
|
||||||
#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \
|
#define ETMCTRL_OPTS (ETMCTRL_DO_CPRT | \
|
||||||
ETMCTRL_DATA_DO_ADDR | \
|
ETMCTRL_DATA_DO_ADDR | \
|
||||||
|
@ -146,12 +134,12 @@ struct tracectx {
|
||||||
#define ETBR_CTRL 0x20
|
#define ETBR_CTRL 0x20
|
||||||
#define ETBR_FORMATTERCTRL 0x304
|
#define ETBR_FORMATTERCTRL 0x304
|
||||||
#define ETBFF_ENFTC 1
|
#define ETBFF_ENFTC 1
|
||||||
#define ETBFF_ENFCONT (1 << 1)
|
#define ETBFF_ENFCONT BIT(1)
|
||||||
#define ETBFF_FONFLIN (1 << 4)
|
#define ETBFF_FONFLIN BIT(4)
|
||||||
#define ETBFF_MANUAL_FLUSH (1 << 6)
|
#define ETBFF_MANUAL_FLUSH BIT(6)
|
||||||
#define ETBFF_TRIGIN (1 << 8)
|
#define ETBFF_TRIGIN BIT(8)
|
||||||
#define ETBFF_TRIGEVT (1 << 9)
|
#define ETBFF_TRIGEVT BIT(9)
|
||||||
#define ETBFF_TRIGFL (1 << 10)
|
#define ETBFF_TRIGFL BIT(10)
|
||||||
|
|
||||||
#define etb_writel(t, v, x) \
|
#define etb_writel(t, v, x) \
|
||||||
(__raw_writel((v), (t)->etb_regs + (x)))
|
(__raw_writel((v), (t)->etb_regs + (x)))
|
||||||
|
|
133
arch/arm/include/asm/hw_breakpoint.h
Normal file
133
arch/arm/include/asm/hw_breakpoint.h
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
#ifndef _ARM_HW_BREAKPOINT_H
|
||||||
|
#define _ARM_HW_BREAKPOINT_H
|
||||||
|
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
struct task_struct;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||||
|
|
||||||
|
struct arch_hw_breakpoint_ctrl {
|
||||||
|
u32 __reserved : 9,
|
||||||
|
mismatch : 1,
|
||||||
|
: 9,
|
||||||
|
len : 8,
|
||||||
|
type : 2,
|
||||||
|
privilege : 2,
|
||||||
|
enabled : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct arch_hw_breakpoint {
|
||||||
|
u32 address;
|
||||||
|
u32 trigger;
|
||||||
|
struct perf_event *suspended_wp;
|
||||||
|
struct arch_hw_breakpoint_ctrl ctrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline u32 encode_ctrl_reg(struct arch_hw_breakpoint_ctrl ctrl)
|
||||||
|
{
|
||||||
|
return (ctrl.mismatch << 22) | (ctrl.len << 5) | (ctrl.type << 3) |
|
||||||
|
(ctrl.privilege << 1) | ctrl.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void decode_ctrl_reg(u32 reg,
|
||||||
|
struct arch_hw_breakpoint_ctrl *ctrl)
|
||||||
|
{
|
||||||
|
ctrl->enabled = reg & 0x1;
|
||||||
|
reg >>= 1;
|
||||||
|
ctrl->privilege = reg & 0x3;
|
||||||
|
reg >>= 2;
|
||||||
|
ctrl->type = reg & 0x3;
|
||||||
|
reg >>= 2;
|
||||||
|
ctrl->len = reg & 0xff;
|
||||||
|
reg >>= 17;
|
||||||
|
ctrl->mismatch = reg & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Debug architecture numbers. */
|
||||||
|
#define ARM_DEBUG_ARCH_RESERVED 0 /* In case of ptrace ABI updates. */
|
||||||
|
#define ARM_DEBUG_ARCH_V6 1
|
||||||
|
#define ARM_DEBUG_ARCH_V6_1 2
|
||||||
|
#define ARM_DEBUG_ARCH_V7_ECP14 3
|
||||||
|
#define ARM_DEBUG_ARCH_V7_MM 4
|
||||||
|
|
||||||
|
/* Breakpoint */
|
||||||
|
#define ARM_BREAKPOINT_EXECUTE 0
|
||||||
|
|
||||||
|
/* Watchpoints */
|
||||||
|
#define ARM_BREAKPOINT_LOAD 1
|
||||||
|
#define ARM_BREAKPOINT_STORE 2
|
||||||
|
|
||||||
|
/* Privilege Levels */
|
||||||
|
#define ARM_BREAKPOINT_PRIV 1
|
||||||
|
#define ARM_BREAKPOINT_USER 2
|
||||||
|
|
||||||
|
/* Lengths */
|
||||||
|
#define ARM_BREAKPOINT_LEN_1 0x1
|
||||||
|
#define ARM_BREAKPOINT_LEN_2 0x3
|
||||||
|
#define ARM_BREAKPOINT_LEN_4 0xf
|
||||||
|
#define ARM_BREAKPOINT_LEN_8 0xff
|
||||||
|
|
||||||
|
/* Limits */
|
||||||
|
#define ARM_MAX_BRP 16
|
||||||
|
#define ARM_MAX_WRP 16
|
||||||
|
#define ARM_MAX_HBP_SLOTS (ARM_MAX_BRP + ARM_MAX_WRP)
|
||||||
|
|
||||||
|
/* DSCR method of entry bits. */
|
||||||
|
#define ARM_DSCR_MOE(x) ((x >> 2) & 0xf)
|
||||||
|
#define ARM_ENTRY_BREAKPOINT 0x1
|
||||||
|
#define ARM_ENTRY_ASYNC_WATCHPOINT 0x2
|
||||||
|
#define ARM_ENTRY_SYNC_WATCHPOINT 0xa
|
||||||
|
|
||||||
|
/* DSCR monitor/halting bits. */
|
||||||
|
#define ARM_DSCR_HDBGEN (1 << 14)
|
||||||
|
#define ARM_DSCR_MDBGEN (1 << 15)
|
||||||
|
|
||||||
|
/* opcode2 numbers for the co-processor instructions. */
|
||||||
|
#define ARM_OP2_BVR 4
|
||||||
|
#define ARM_OP2_BCR 5
|
||||||
|
#define ARM_OP2_WVR 6
|
||||||
|
#define ARM_OP2_WCR 7
|
||||||
|
|
||||||
|
/* Base register numbers for the debug registers. */
|
||||||
|
#define ARM_BASE_BVR 64
|
||||||
|
#define ARM_BASE_BCR 80
|
||||||
|
#define ARM_BASE_WVR 96
|
||||||
|
#define ARM_BASE_WCR 112
|
||||||
|
|
||||||
|
/* Accessor macros for the debug registers. */
|
||||||
|
#define ARM_DBG_READ(M, OP2, VAL) do {\
|
||||||
|
asm volatile("mrc p14, 0, %0, c0," #M ", " #OP2 : "=r" (VAL));\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define ARM_DBG_WRITE(M, OP2, VAL) do {\
|
||||||
|
asm volatile("mcr p14, 0, %0, c0," #M ", " #OP2 : : "r" (VAL));\
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
struct notifier_block;
|
||||||
|
struct perf_event;
|
||||||
|
struct pmu;
|
||||||
|
|
||||||
|
extern struct pmu perf_ops_bp;
|
||||||
|
extern int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
|
||||||
|
int *gen_len, int *gen_type);
|
||||||
|
extern int arch_check_bp_in_kernelspace(struct perf_event *bp);
|
||||||
|
extern int arch_validate_hwbkpt_settings(struct perf_event *bp);
|
||||||
|
extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
|
||||||
|
unsigned long val, void *data);
|
||||||
|
|
||||||
|
extern u8 arch_get_debug_arch(void);
|
||||||
|
extern u8 arch_get_max_wp_len(void);
|
||||||
|
extern void clear_ptrace_hw_breakpoint(struct task_struct *tsk);
|
||||||
|
|
||||||
|
int arch_install_hw_breakpoint(struct perf_event *bp);
|
||||||
|
void arch_uninstall_hw_breakpoint(struct perf_event *bp);
|
||||||
|
void hw_breakpoint_pmu_read(struct perf_event *bp);
|
||||||
|
int hw_breakpoint_slots(int type);
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline void clear_ptrace_hw_breakpoint(struct task_struct *tsk) {}
|
||||||
|
|
||||||
|
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
|
||||||
|
#endif /* __KERNEL__ */
|
||||||
|
#endif /* _ARM_HW_BREAKPOINT_H */
|
|
@ -294,6 +294,7 @@ extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
|
||||||
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
|
#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
|
||||||
extern int valid_phys_addr_range(unsigned long addr, size_t size);
|
extern int valid_phys_addr_range(unsigned long addr, size_t size);
|
||||||
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
|
extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
|
||||||
|
extern int devmem_is_allowed(unsigned long pfn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -16,18 +16,15 @@ struct sys_timer;
|
||||||
|
|
||||||
struct machine_desc {
|
struct machine_desc {
|
||||||
/*
|
/*
|
||||||
* Note! The first four elements are used
|
* Note! The first two elements are used
|
||||||
* by assembler code in head.S, head-common.S
|
* by assembler code in head.S, head-common.S
|
||||||
*/
|
*/
|
||||||
unsigned int nr; /* architecture number */
|
unsigned int nr; /* architecture number */
|
||||||
unsigned int nr_irqs; /* number of IRQs */
|
|
||||||
unsigned int phys_io; /* start of physical io */
|
|
||||||
unsigned int io_pg_offst; /* byte offset for io
|
|
||||||
* page tabe entry */
|
|
||||||
|
|
||||||
const char *name; /* architecture name */
|
const char *name; /* architecture name */
|
||||||
unsigned long boot_params; /* tagged list */
|
unsigned long boot_params; /* tagged list */
|
||||||
|
|
||||||
|
unsigned int nr_irqs; /* number of IRQs */
|
||||||
|
|
||||||
unsigned int video_start; /* start of video RAM */
|
unsigned int video_start; /* start of video RAM */
|
||||||
unsigned int video_end; /* end of video RAM */
|
unsigned int video_end; /* end of video RAM */
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/cachetype.h>
|
#include <asm/cachetype.h>
|
||||||
#include <asm/proc-fns.h>
|
#include <asm/proc-fns.h>
|
||||||
#include <asm-generic/mm_hooks.h>
|
|
||||||
|
|
||||||
void __check_kvm_seq(struct mm_struct *mm);
|
void __check_kvm_seq(struct mm_struct *mm);
|
||||||
|
|
||||||
|
@ -134,4 +133,32 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
||||||
#define deactivate_mm(tsk,mm) do { } while (0)
|
#define deactivate_mm(tsk,mm) do { } while (0)
|
||||||
#define activate_mm(prev,next) switch_mm(prev, next, NULL)
|
#define activate_mm(prev,next) switch_mm(prev, next, NULL)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We are inserting a "fake" vma for the user-accessible vector page so
|
||||||
|
* gdb and friends can get to it through ptrace and /proc/<pid>/mem.
|
||||||
|
* But we also want to remove it before the generic code gets to see it
|
||||||
|
* during process exit or the unmapping of it would cause total havoc.
|
||||||
|
* (the macro is used as remove_vma() is static to mm/mmap.c)
|
||||||
|
*/
|
||||||
|
#define arch_exit_mmap(mm) \
|
||||||
|
do { \
|
||||||
|
struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \
|
||||||
|
if (high_vma) { \
|
||||||
|
BUG_ON(high_vma->vm_next); /* it should be last */ \
|
||||||
|
if (high_vma->vm_prev) \
|
||||||
|
high_vma->vm_prev->vm_next = NULL; \
|
||||||
|
else \
|
||||||
|
mm->mmap = NULL; \
|
||||||
|
rb_erase(&high_vma->vm_rb, &mm->mm_rb); \
|
||||||
|
mm->mmap_cache = NULL; \
|
||||||
|
mm->map_count--; \
|
||||||
|
remove_vma(high_vma); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static inline void arch_dup_mmap(struct mm_struct *oldmm,
|
||||||
|
struct mm_struct *mm)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,20 +7,27 @@
|
||||||
|
|
||||||
struct unwind_table;
|
struct unwind_table;
|
||||||
|
|
||||||
struct mod_arch_specific
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_ARM_UNWIND
|
#ifdef CONFIG_ARM_UNWIND
|
||||||
Elf_Shdr *unw_sec_init;
|
struct arm_unwind_mapping {
|
||||||
Elf_Shdr *unw_sec_devinit;
|
Elf_Shdr *unw_sec;
|
||||||
Elf_Shdr *unw_sec_core;
|
Elf_Shdr *sec_text;
|
||||||
Elf_Shdr *sec_init_text;
|
struct unwind_table *unwind;
|
||||||
Elf_Shdr *sec_devinit_text;
|
|
||||||
Elf_Shdr *sec_core_text;
|
|
||||||
struct unwind_table *unwind_init;
|
|
||||||
struct unwind_table *unwind_devinit;
|
|
||||||
struct unwind_table *unwind_core;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
enum {
|
||||||
|
ARM_SEC_INIT,
|
||||||
|
ARM_SEC_DEVINIT,
|
||||||
|
ARM_SEC_CORE,
|
||||||
|
ARM_SEC_EXIT,
|
||||||
|
ARM_SEC_DEVEXIT,
|
||||||
|
ARM_SEC_MAX,
|
||||||
|
};
|
||||||
|
struct mod_arch_specific {
|
||||||
|
struct arm_unwind_mapping map[ARM_SEC_MAX];
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct mod_arch_specific {
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Include the ARM architecture version.
|
* Include the ARM architecture version.
|
||||||
|
|
|
@ -278,9 +278,24 @@ extern struct page *empty_zero_page;
|
||||||
|
|
||||||
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
|
#define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
|
||||||
|
|
||||||
#define set_pte_at(mm,addr,ptep,pteval) do { \
|
#if __LINUX_ARM_ARCH__ < 6
|
||||||
set_pte_ext(ptep, pteval, (addr) >= TASK_SIZE ? 0 : PTE_EXT_NG); \
|
static inline void __sync_icache_dcache(pte_t pteval)
|
||||||
} while (0)
|
{
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
extern void __sync_icache_dcache(pte_t pteval);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
|
||||||
|
pte_t *ptep, pte_t pteval)
|
||||||
|
{
|
||||||
|
if (addr >= TASK_SIZE)
|
||||||
|
set_pte_ext(ptep, pteval, 0);
|
||||||
|
else {
|
||||||
|
__sync_icache_dcache(pteval);
|
||||||
|
set_pte_ext(ptep, pteval, PTE_EXT_NG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following only work if pte_present() is true.
|
* The following only work if pte_present() is true.
|
||||||
|
@ -290,8 +305,13 @@ extern struct page *empty_zero_page;
|
||||||
#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
|
#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)
|
||||||
#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
|
#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)
|
||||||
#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
|
#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)
|
||||||
|
#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC)
|
||||||
#define pte_special(pte) (0)
|
#define pte_special(pte) (0)
|
||||||
|
|
||||||
|
#define pte_present_user(pte) \
|
||||||
|
((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \
|
||||||
|
(L_PTE_PRESENT | L_PTE_USER))
|
||||||
|
|
||||||
#define PTE_BIT_FUNC(fn,op) \
|
#define PTE_BIT_FUNC(fn,op) \
|
||||||
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
|
static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
|
#include <asm/hw_breakpoint.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/types.h>
|
#include <asm/types.h>
|
||||||
|
|
||||||
|
@ -41,6 +42,9 @@ struct debug_entry {
|
||||||
struct debug_info {
|
struct debug_info {
|
||||||
int nsaved;
|
int nsaved;
|
||||||
struct debug_entry bp[2];
|
struct debug_entry bp[2];
|
||||||
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||||
|
struct perf_event *hbp[ARM_MAX_HBP_SLOTS];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct thread_struct {
|
struct thread_struct {
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#define PTRACE_SETCRUNCHREGS 26
|
#define PTRACE_SETCRUNCHREGS 26
|
||||||
#define PTRACE_GETVFPREGS 27
|
#define PTRACE_GETVFPREGS 27
|
||||||
#define PTRACE_SETVFPREGS 28
|
#define PTRACE_SETVFPREGS 28
|
||||||
|
#define PTRACE_GETHBPREGS 29
|
||||||
|
#define PTRACE_SETHBPREGS 30
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PSR bits
|
* PSR bits
|
||||||
|
|
11
arch/arm/include/asm/seccomp.h
Normal file
11
arch/arm/include/asm/seccomp.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef _ASM_ARM_SECCOMP_H
|
||||||
|
#define _ASM_ARM_SECCOMP_H
|
||||||
|
|
||||||
|
#include <linux/unistd.h>
|
||||||
|
|
||||||
|
#define __NR_seccomp_read __NR_read
|
||||||
|
#define __NR_seccomp_write __NR_write
|
||||||
|
#define __NR_seccomp_exit __NR_exit
|
||||||
|
#define __NR_seccomp_sigreturn __NR_rt_sigreturn
|
||||||
|
|
||||||
|
#endif /* _ASM_ARM_SECCOMP_H */
|
17
arch/arm/include/asm/smp_mpidr.h
Normal file
17
arch/arm/include/asm/smp_mpidr.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef ASMARM_SMP_MIDR_H
|
||||||
|
#define ASMARM_SMP_MIDR_H
|
||||||
|
|
||||||
|
#define hard_smp_processor_id() \
|
||||||
|
({ \
|
||||||
|
unsigned int cpunum; \
|
||||||
|
__asm__("\n" \
|
||||||
|
"1: mrc p15, 0, %0, c0, c0, 5\n" \
|
||||||
|
" .pushsection \".alt.smp.init\", \"a\"\n"\
|
||||||
|
" .long 1b\n" \
|
||||||
|
" mov %0, #0\n" \
|
||||||
|
" .popsection" \
|
||||||
|
: "=r" (cpunum)); \
|
||||||
|
cpunum &= 0x0F; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#endif
|
|
@ -7,15 +7,40 @@
|
||||||
|
|
||||||
#include <asm/cputype.h>
|
#include <asm/cputype.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return true if we are running on a SMP platform
|
||||||
|
*/
|
||||||
|
static inline bool is_smp(void)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_SMP
|
||||||
|
return false;
|
||||||
|
#elif defined(CONFIG_SMP_ON_UP)
|
||||||
|
extern unsigned int smp_on_up;
|
||||||
|
return !!smp_on_up;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* all SMP configurations have the extended CPUID registers */
|
/* all SMP configurations have the extended CPUID registers */
|
||||||
static inline int tlb_ops_need_broadcast(void)
|
static inline int tlb_ops_need_broadcast(void)
|
||||||
{
|
{
|
||||||
|
if (!is_smp())
|
||||||
|
return 0;
|
||||||
|
|
||||||
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
|
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(CONFIG_SMP) || __LINUX_ARM_ARCH__ >= 7
|
||||||
|
#define cache_ops_need_broadcast() 0
|
||||||
|
#else
|
||||||
static inline int cache_ops_need_broadcast(void)
|
static inline int cache_ops_need_broadcast(void)
|
||||||
{
|
{
|
||||||
|
if (!is_smp())
|
||||||
|
return 0;
|
||||||
|
|
||||||
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1;
|
return ((read_cpuid_ext(CPUID_EXT_MMFR3) >> 12) & 0xf) < 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -85,6 +85,10 @@ void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
|
||||||
struct pt_regs *),
|
struct pt_regs *),
|
||||||
int sig, int code, const char *name);
|
int sig, int code, const char *name);
|
||||||
|
|
||||||
|
void hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int,
|
||||||
|
struct pt_regs *),
|
||||||
|
int sig, int code, const char *name);
|
||||||
|
|
||||||
#define xchg(ptr,x) \
|
#define xchg(ptr,x) \
|
||||||
((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
|
((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
|
||||||
|
|
||||||
|
@ -325,6 +329,8 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
|
||||||
extern void disable_hlt(void);
|
extern void disable_hlt(void);
|
||||||
extern void enable_hlt(void);
|
extern void enable_hlt(void);
|
||||||
|
|
||||||
|
void cpu_idle_wait(void);
|
||||||
|
|
||||||
#include <asm-generic/cmpxchg-local.h>
|
#include <asm-generic/cmpxchg-local.h>
|
||||||
|
|
||||||
#if __LINUX_ARM_ARCH__ < 6
|
#if __LINUX_ARM_ARCH__ < 6
|
||||||
|
|
|
@ -144,6 +144,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
|
||||||
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
|
#define TIF_MEMDIE 18 /* is terminating due to OOM killer */
|
||||||
#define TIF_FREEZE 19
|
#define TIF_FREEZE 19
|
||||||
#define TIF_RESTORE_SIGMASK 20
|
#define TIF_RESTORE_SIGMASK 20
|
||||||
|
#define TIF_SECCOMP 21
|
||||||
|
|
||||||
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
|
||||||
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
|
||||||
|
@ -153,6 +154,7 @@ extern void vfp_flush_hwstate(struct thread_info *);
|
||||||
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
|
#define _TIF_USING_IWMMXT (1 << TIF_USING_IWMMXT)
|
||||||
#define _TIF_FREEZE (1 << TIF_FREEZE)
|
#define _TIF_FREEZE (1 << TIF_FREEZE)
|
||||||
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
|
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
|
||||||
|
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change these and you break ASM code in entry-common.S
|
* Change these and you break ASM code in entry-common.S
|
||||||
|
|
|
@ -70,6 +70,10 @@
|
||||||
#undef _TLB
|
#undef _TLB
|
||||||
#undef MULTI_TLB
|
#undef MULTI_TLB
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP_ON_UP
|
||||||
|
#define MULTI_TLB 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE)
|
#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE)
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_TLB_V3
|
#ifdef CONFIG_CPU_TLB_V3
|
||||||
|
@ -185,17 +189,23 @@
|
||||||
# define v6wbi_always_flags (-1UL)
|
# define v6wbi_always_flags (-1UL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#define v7wbi_tlb_flags_smp (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
|
||||||
#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_V7_IS_BTB | \
|
|
||||||
TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
|
TLB_V7_UIS_FULL | TLB_V7_UIS_PAGE | TLB_V7_UIS_ASID)
|
||||||
#else
|
#define v7wbi_tlb_flags_up (TLB_WB | TLB_DCLEAN | TLB_BTB | \
|
||||||
#define v7wbi_tlb_flags (TLB_WB | TLB_DCLEAN | TLB_BTB | \
|
|
||||||
TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
|
TLB_V6_U_FULL | TLB_V6_U_PAGE | TLB_V6_U_ASID)
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_TLB_V7
|
#ifdef CONFIG_CPU_TLB_V7
|
||||||
# define v7wbi_possible_flags v7wbi_tlb_flags
|
|
||||||
# define v7wbi_always_flags v7wbi_tlb_flags
|
# ifdef CONFIG_SMP_ON_UP
|
||||||
|
# define v7wbi_possible_flags (v7wbi_tlb_flags_smp | v7wbi_tlb_flags_up)
|
||||||
|
# define v7wbi_always_flags (v7wbi_tlb_flags_smp & v7wbi_tlb_flags_up)
|
||||||
|
# elif defined(CONFIG_SMP)
|
||||||
|
# define v7wbi_possible_flags v7wbi_tlb_flags_smp
|
||||||
|
# define v7wbi_always_flags v7wbi_tlb_flags_smp
|
||||||
|
# else
|
||||||
|
# define v7wbi_possible_flags v7wbi_tlb_flags_up
|
||||||
|
# define v7wbi_always_flags v7wbi_tlb_flags_up
|
||||||
|
# endif
|
||||||
# ifdef _TLB
|
# ifdef _TLB
|
||||||
# define MULTI_TLB 1
|
# define MULTI_TLB 1
|
||||||
# else
|
# else
|
||||||
|
@ -560,12 +570,20 @@ extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if PG_dcache_dirty is set for the page, we need to ensure that any
|
* If PG_dcache_clean is not set for the page, we need to ensure that any
|
||||||
* cache entries for the kernels virtual memory range are written
|
* cache entries for the kernels virtual memory range are written
|
||||||
* back to the page.
|
* back to the page. On ARMv6 and later, the cache coherency is handled via
|
||||||
|
* the set_pte_at() function.
|
||||||
*/
|
*/
|
||||||
|
#if __LINUX_ARM_ARCH__ < 6
|
||||||
extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
|
extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
|
||||||
pte_t *ptep);
|
pte_t *ptep);
|
||||||
|
#else
|
||||||
|
static inline void update_mmu_cache(struct vm_area_struct *vma,
|
||||||
|
unsigned long addr, pte_t *ptep)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ obj-$(CONFIG_KGDB) += kgdb.o
|
||||||
obj-$(CONFIG_ARM_UNWIND) += unwind.o
|
obj-$(CONFIG_ARM_UNWIND) += unwind.o
|
||||||
obj-$(CONFIG_HAVE_TCM) += tcm.o
|
obj-$(CONFIG_HAVE_TCM) += tcm.o
|
||||||
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
||||||
|
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
|
||||||
|
|
||||||
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
|
obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o
|
||||||
AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
|
AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312
|
||||||
|
|
|
@ -165,6 +165,8 @@ EXPORT_SYMBOL(_find_next_bit_be);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_FUNCTION_TRACER
|
#ifdef CONFIG_FUNCTION_TRACER
|
||||||
|
#ifdef CONFIG_OLD_MCOUNT
|
||||||
EXPORT_SYMBOL(mcount);
|
EXPORT_SYMBOL(mcount);
|
||||||
|
#endif
|
||||||
EXPORT_SYMBOL(__gnu_mcount_nc);
|
EXPORT_SYMBOL(__gnu_mcount_nc);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -102,8 +102,6 @@ int main(void)
|
||||||
DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc));
|
DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc));
|
||||||
DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr));
|
DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr));
|
||||||
DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name));
|
DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name));
|
||||||
DEFINE(MACHINFO_PHYSIO, offsetof(struct machine_desc, phys_io));
|
|
||||||
DEFINE(MACHINFO_PGOFFIO, offsetof(struct machine_desc, io_pg_offst));
|
|
||||||
BLANK();
|
BLANK();
|
||||||
DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list));
|
DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list));
|
||||||
DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));
|
DEFINE(PROCINFO_INITFUNC, offsetof(struct proc_info_list, __cpu_flush));
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
#if defined(CONFIG_DEBUG_ICEDCC)
|
#if defined(CONFIG_DEBUG_ICEDCC)
|
||||||
@@ debug using ARM EmbeddedICE DCC channel
|
@@ debug using ARM EmbeddedICE DCC channel
|
||||||
|
|
||||||
#if defined(CONFIG_CPU_V6)
|
.macro addruart, rp, rv
|
||||||
|
|
||||||
.macro addruart, rx, tmp
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
#if defined(CONFIG_CPU_V6)
|
||||||
|
|
||||||
.macro senduart, rd, rx
|
.macro senduart, rd, rx
|
||||||
mcr p14, 0, \rd, c0, c5, 0
|
mcr p14, 0, \rd, c0, c5, 0
|
||||||
.endm
|
.endm
|
||||||
|
@ -51,9 +51,6 @@
|
||||||
|
|
||||||
#elif defined(CONFIG_CPU_V7)
|
#elif defined(CONFIG_CPU_V7)
|
||||||
|
|
||||||
.macro addruart, rx, tmp
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro senduart, rd, rx
|
.macro senduart, rd, rx
|
||||||
mcr p14, 0, \rd, c0, c5, 0
|
mcr p14, 0, \rd, c0, c5, 0
|
||||||
.endm
|
.endm
|
||||||
|
@ -71,9 +68,6 @@ wait: mrc p14, 0, pc, c0, c1, 0
|
||||||
|
|
||||||
#elif defined(CONFIG_CPU_XSCALE)
|
#elif defined(CONFIG_CPU_XSCALE)
|
||||||
|
|
||||||
.macro addruart, rx, tmp
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro senduart, rd, rx
|
.macro senduart, rd, rx
|
||||||
mcr p14, 0, \rd, c8, c0, 0
|
mcr p14, 0, \rd, c8, c0, 0
|
||||||
.endm
|
.endm
|
||||||
|
@ -98,9 +92,6 @@ wait: mrc p14, 0, pc, c0, c1, 0
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
.macro addruart, rx, tmp
|
|
||||||
.endm
|
|
||||||
|
|
||||||
.macro senduart, rd, rx
|
.macro senduart, rd, rx
|
||||||
mcr p14, 0, \rd, c1, c0, 0
|
mcr p14, 0, \rd, c1, c0, 0
|
||||||
.endm
|
.endm
|
||||||
|
@ -130,6 +121,22 @@ wait: mrc p14, 0, pc, c0, c1, 0
|
||||||
#include <mach/debug-macro.S>
|
#include <mach/debug-macro.S>
|
||||||
#endif /* CONFIG_DEBUG_ICEDCC */
|
#endif /* CONFIG_DEBUG_ICEDCC */
|
||||||
|
|
||||||
|
#ifdef CONFIG_MMU
|
||||||
|
.macro addruart_current, rx, tmp1, tmp2
|
||||||
|
addruart \tmp1, \tmp2
|
||||||
|
mrc p15, 0, \rx, c1, c0
|
||||||
|
tst \rx, #1
|
||||||
|
moveq \rx, \tmp1
|
||||||
|
movne \rx, \tmp2
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#else /* !CONFIG_MMU */
|
||||||
|
.macro addruart_current, rx, tmp1, tmp2
|
||||||
|
addruart \rx, \tmp1
|
||||||
|
.endm
|
||||||
|
|
||||||
|
#endif /* CONFIG_MMU */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Useful debugging routines
|
* Useful debugging routines
|
||||||
*/
|
*/
|
||||||
|
@ -164,7 +171,7 @@ ENDPROC(printhex2)
|
||||||
.ltorg
|
.ltorg
|
||||||
|
|
||||||
ENTRY(printascii)
|
ENTRY(printascii)
|
||||||
addruart r3, r1
|
addruart_current r3, r1, r2
|
||||||
b 2f
|
b 2f
|
||||||
1: waituart r2, r3
|
1: waituart r2, r3
|
||||||
senduart r1, r3
|
senduart r1, r3
|
||||||
|
@ -180,7 +187,7 @@ ENTRY(printascii)
|
||||||
ENDPROC(printascii)
|
ENDPROC(printascii)
|
||||||
|
|
||||||
ENTRY(printch)
|
ENTRY(printch)
|
||||||
addruart r3, r1
|
addruart_current r3, r1, r2
|
||||||
mov r1, r0
|
mov r1, r0
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
b 1b
|
b 1b
|
||||||
|
|
|
@ -46,7 +46,8 @@
|
||||||
* this macro assumes that irqstat (r6) and base (r5) are
|
* this macro assumes that irqstat (r6) and base (r5) are
|
||||||
* preserved from get_irqnr_and_base above
|
* preserved from get_irqnr_and_base above
|
||||||
*/
|
*/
|
||||||
test_for_ipi r0, r6, r5, lr
|
ALT_SMP(test_for_ipi r0, r6, r5, lr)
|
||||||
|
ALT_UP_B(9997f)
|
||||||
movne r0, sp
|
movne r0, sp
|
||||||
adrne lr, BSYM(1b)
|
adrne lr, BSYM(1b)
|
||||||
bne do_IPI
|
bne do_IPI
|
||||||
|
@ -57,6 +58,7 @@
|
||||||
adrne lr, BSYM(1b)
|
adrne lr, BSYM(1b)
|
||||||
bne do_local_timer
|
bne do_local_timer
|
||||||
#endif
|
#endif
|
||||||
|
9997:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
.endm
|
.endm
|
||||||
|
@ -965,11 +967,8 @@ kuser_cmpxchg_fixup:
|
||||||
beq 1b
|
beq 1b
|
||||||
rsbs r0, r3, #0
|
rsbs r0, r3, #0
|
||||||
/* beware -- each __kuser slot must be 8 instructions max */
|
/* beware -- each __kuser slot must be 8 instructions max */
|
||||||
#ifdef CONFIG_SMP
|
ALT_SMP(b __kuser_memory_barrier)
|
||||||
b __kuser_memory_barrier
|
ALT_UP(usr_ret lr)
|
||||||
#else
|
|
||||||
usr_ret lr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -129,30 +129,58 @@ ENDPROC(ret_from_fork)
|
||||||
* clobber the ip register. This is OK because the ARM calling convention
|
* clobber the ip register. This is OK because the ARM calling convention
|
||||||
* allows it to be clobbered in subroutines and doesn't use it to hold
|
* allows it to be clobbered in subroutines and doesn't use it to hold
|
||||||
* parameters.)
|
* parameters.)
|
||||||
|
*
|
||||||
|
* When using dynamic ftrace, we patch out the mcount call by a "mov r0, r0"
|
||||||
|
* for the mcount case, and a "pop {lr}" for the __gnu_mcount_nc case (see
|
||||||
|
* arch/arm/kernel/ftrace.c).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef CONFIG_OLD_MCOUNT
|
||||||
|
#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
|
||||||
|
#error Ftrace requires CONFIG_FRAME_POINTER=y with GCC older than 4.4.0.
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||||
ENTRY(mcount)
|
ENTRY(__gnu_mcount_nc)
|
||||||
|
mov ip, lr
|
||||||
|
ldmia sp!, {lr}
|
||||||
|
mov pc, ip
|
||||||
|
ENDPROC(__gnu_mcount_nc)
|
||||||
|
|
||||||
|
ENTRY(ftrace_caller)
|
||||||
stmdb sp!, {r0-r3, lr}
|
stmdb sp!, {r0-r3, lr}
|
||||||
mov r0, lr
|
mov r0, lr
|
||||||
sub r0, r0, #MCOUNT_INSN_SIZE
|
sub r0, r0, #MCOUNT_INSN_SIZE
|
||||||
|
ldr r1, [sp, #20]
|
||||||
|
|
||||||
.globl mcount_call
|
.global ftrace_call
|
||||||
mcount_call:
|
ftrace_call:
|
||||||
bl ftrace_stub
|
bl ftrace_stub
|
||||||
ldr lr, [fp, #-4] @ restore lr
|
ldmia sp!, {r0-r3, ip, lr}
|
||||||
ldmia sp!, {r0-r3, pc}
|
mov pc, ip
|
||||||
|
ENDPROC(ftrace_caller)
|
||||||
|
|
||||||
ENTRY(ftrace_caller)
|
#ifdef CONFIG_OLD_MCOUNT
|
||||||
|
ENTRY(mcount)
|
||||||
|
stmdb sp!, {lr}
|
||||||
|
ldr lr, [fp, #-4]
|
||||||
|
ldmia sp!, {pc}
|
||||||
|
ENDPROC(mcount)
|
||||||
|
|
||||||
|
ENTRY(ftrace_caller_old)
|
||||||
stmdb sp!, {r0-r3, lr}
|
stmdb sp!, {r0-r3, lr}
|
||||||
ldr r1, [fp, #-4]
|
ldr r1, [fp, #-4]
|
||||||
mov r0, lr
|
mov r0, lr
|
||||||
sub r0, r0, #MCOUNT_INSN_SIZE
|
sub r0, r0, #MCOUNT_INSN_SIZE
|
||||||
|
|
||||||
.globl ftrace_call
|
.globl ftrace_call_old
|
||||||
ftrace_call:
|
ftrace_call_old:
|
||||||
bl ftrace_stub
|
bl ftrace_stub
|
||||||
ldr lr, [fp, #-4] @ restore lr
|
ldr lr, [fp, #-4] @ restore lr
|
||||||
ldmia sp!, {r0-r3, pc}
|
ldmia sp!, {r0-r3, pc}
|
||||||
|
ENDPROC(ftrace_caller_old)
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -160,7 +188,7 @@ ENTRY(__gnu_mcount_nc)
|
||||||
stmdb sp!, {r0-r3, lr}
|
stmdb sp!, {r0-r3, lr}
|
||||||
ldr r0, =ftrace_trace_function
|
ldr r0, =ftrace_trace_function
|
||||||
ldr r2, [r0]
|
ldr r2, [r0]
|
||||||
adr r0, ftrace_stub
|
adr r0, .Lftrace_stub
|
||||||
cmp r0, r2
|
cmp r0, r2
|
||||||
bne gnu_trace
|
bne gnu_trace
|
||||||
ldmia sp!, {r0-r3, ip, lr}
|
ldmia sp!, {r0-r3, ip, lr}
|
||||||
|
@ -170,11 +198,19 @@ gnu_trace:
|
||||||
ldr r1, [sp, #20] @ lr of instrumented routine
|
ldr r1, [sp, #20] @ lr of instrumented routine
|
||||||
mov r0, lr
|
mov r0, lr
|
||||||
sub r0, r0, #MCOUNT_INSN_SIZE
|
sub r0, r0, #MCOUNT_INSN_SIZE
|
||||||
mov lr, pc
|
adr lr, BSYM(1f)
|
||||||
mov pc, r2
|
mov pc, r2
|
||||||
|
1:
|
||||||
ldmia sp!, {r0-r3, ip, lr}
|
ldmia sp!, {r0-r3, ip, lr}
|
||||||
mov pc, ip
|
mov pc, ip
|
||||||
|
ENDPROC(__gnu_mcount_nc)
|
||||||
|
|
||||||
|
#ifdef CONFIG_OLD_MCOUNT
|
||||||
|
/*
|
||||||
|
* This is under an ifdef in order to force link-time errors for people trying
|
||||||
|
* to build with !FRAME_POINTER with a GCC which doesn't use the new-style
|
||||||
|
* mcount.
|
||||||
|
*/
|
||||||
ENTRY(mcount)
|
ENTRY(mcount)
|
||||||
stmdb sp!, {r0-r3, lr}
|
stmdb sp!, {r0-r3, lr}
|
||||||
ldr r0, =ftrace_trace_function
|
ldr r0, =ftrace_trace_function
|
||||||
|
@ -193,12 +229,15 @@ trace:
|
||||||
mov pc, r2
|
mov pc, r2
|
||||||
ldr lr, [fp, #-4] @ restore lr
|
ldr lr, [fp, #-4] @ restore lr
|
||||||
ldmia sp!, {r0-r3, pc}
|
ldmia sp!, {r0-r3, pc}
|
||||||
|
ENDPROC(mcount)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_DYNAMIC_FTRACE */
|
#endif /* CONFIG_DYNAMIC_FTRACE */
|
||||||
|
|
||||||
.globl ftrace_stub
|
ENTRY(ftrace_stub)
|
||||||
ftrace_stub:
|
.Lftrace_stub:
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
|
ENDPROC(ftrace_stub)
|
||||||
|
|
||||||
#endif /* CONFIG_FUNCTION_TRACER */
|
#endif /* CONFIG_FUNCTION_TRACER */
|
||||||
|
|
||||||
|
@ -295,7 +334,6 @@ ENTRY(vector_swi)
|
||||||
|
|
||||||
get_thread_info tsk
|
get_thread_info tsk
|
||||||
adr tbl, sys_call_table @ load syscall table pointer
|
adr tbl, sys_call_table @ load syscall table pointer
|
||||||
ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing
|
|
||||||
|
|
||||||
#if defined(CONFIG_OABI_COMPAT)
|
#if defined(CONFIG_OABI_COMPAT)
|
||||||
/*
|
/*
|
||||||
|
@ -312,8 +350,20 @@ ENTRY(vector_swi)
|
||||||
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
|
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing
|
||||||
stmdb sp!, {r4, r5} @ push fifth and sixth args
|
stmdb sp!, {r4, r5} @ push fifth and sixth args
|
||||||
tst ip, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
|
|
||||||
|
#ifdef CONFIG_SECCOMP
|
||||||
|
tst r10, #_TIF_SECCOMP
|
||||||
|
beq 1f
|
||||||
|
mov r0, scno
|
||||||
|
bl __secure_computing
|
||||||
|
add r0, sp, #S_R0 + S_OFF @ pointer to regs
|
||||||
|
ldmia r0, {r0 - r3} @ have to reload r0 - r3
|
||||||
|
1:
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tst r10, #_TIF_SYSCALL_TRACE @ are we tracing syscalls?
|
||||||
bne __sys_trace
|
bne __sys_trace
|
||||||
|
|
||||||
cmp scno, #NR_syscalls @ check upper syscall limit
|
cmp scno, #NR_syscalls @ check upper syscall limit
|
||||||
|
|
|
@ -30,6 +30,21 @@
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("Alexander Shishkin");
|
MODULE_AUTHOR("Alexander Shishkin");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ETM tracer state
|
||||||
|
*/
|
||||||
|
struct tracectx {
|
||||||
|
unsigned int etb_bufsz;
|
||||||
|
void __iomem *etb_regs;
|
||||||
|
void __iomem *etm_regs;
|
||||||
|
unsigned long flags;
|
||||||
|
int ncmppairs;
|
||||||
|
int etm_portsz;
|
||||||
|
struct device *dev;
|
||||||
|
struct clk *emu_clk;
|
||||||
|
struct mutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
static struct tracectx tracer;
|
static struct tracectx tracer;
|
||||||
|
|
||||||
static inline bool trace_isrunning(struct tracectx *t)
|
static inline bool trace_isrunning(struct tracectx *t)
|
||||||
|
|
|
@ -2,102 +2,194 @@
|
||||||
* Dynamic function tracing support.
|
* Dynamic function tracing support.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
|
* Copyright (C) 2008 Abhishek Sagar <sagar.abhishek@gmail.com>
|
||||||
|
* Copyright (C) 2010 Rabin Vincent <rabin@rab.in>
|
||||||
*
|
*
|
||||||
* For licencing details, see COPYING.
|
* For licencing details, see COPYING.
|
||||||
*
|
*
|
||||||
* Defines low-level handling of mcount calls when the kernel
|
* Defines low-level handling of mcount calls when the kernel
|
||||||
* is compiled with the -pg flag. When using dynamic ftrace, the
|
* is compiled with the -pg flag. When using dynamic ftrace, the
|
||||||
* mcount call-sites get patched lazily with NOP till they are
|
* mcount call-sites get patched with NOP till they are enabled.
|
||||||
* enabled. All code mutation routines here take effect atomically.
|
* All code mutation routines here are called under stop_machine().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/ftrace.h>
|
#include <linux/ftrace.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/ftrace.h>
|
#include <asm/ftrace.h>
|
||||||
|
|
||||||
#define PC_OFFSET 8
|
#ifdef CONFIG_THUMB2_KERNEL
|
||||||
#define BL_OPCODE 0xeb000000
|
#define NOP 0xeb04f85d /* pop.w {lr} */
|
||||||
#define BL_OFFSET_MASK 0x00ffffff
|
#else
|
||||||
|
#define NOP 0xe8bd4000 /* pop {lr} */
|
||||||
|
#endif
|
||||||
|
|
||||||
static unsigned long bl_insn;
|
#ifdef CONFIG_OLD_MCOUNT
|
||||||
static const unsigned long NOP = 0xe1a00000; /* mov r0, r0 */
|
#define OLD_MCOUNT_ADDR ((unsigned long) mcount)
|
||||||
|
#define OLD_FTRACE_ADDR ((unsigned long) ftrace_caller_old)
|
||||||
|
|
||||||
unsigned char *ftrace_nop_replace(void)
|
#define OLD_NOP 0xe1a00000 /* mov r0, r0 */
|
||||||
|
|
||||||
|
static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
|
||||||
{
|
{
|
||||||
return (char *)&NOP;
|
return rec->arch.old_mcount ? OLD_NOP : NOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
|
||||||
|
{
|
||||||
|
if (!rec->arch.old_mcount)
|
||||||
|
return addr;
|
||||||
|
|
||||||
|
if (addr == MCOUNT_ADDR)
|
||||||
|
addr = OLD_MCOUNT_ADDR;
|
||||||
|
else if (addr == FTRACE_ADDR)
|
||||||
|
addr = OLD_FTRACE_ADDR;
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static unsigned long ftrace_nop_replace(struct dyn_ftrace *rec)
|
||||||
|
{
|
||||||
|
return NOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr)
|
||||||
|
{
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* construct a branch (BL) instruction to addr */
|
/* construct a branch (BL) instruction to addr */
|
||||||
unsigned char *ftrace_call_replace(unsigned long pc, unsigned long addr)
|
#ifdef CONFIG_THUMB2_KERNEL
|
||||||
|
static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
|
||||||
|
{
|
||||||
|
unsigned long s, j1, j2, i1, i2, imm10, imm11;
|
||||||
|
unsigned long first, second;
|
||||||
|
long offset;
|
||||||
|
|
||||||
|
offset = (long)addr - (long)(pc + 4);
|
||||||
|
if (offset < -16777216 || offset > 16777214) {
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = (offset >> 24) & 0x1;
|
||||||
|
i1 = (offset >> 23) & 0x1;
|
||||||
|
i2 = (offset >> 22) & 0x1;
|
||||||
|
imm10 = (offset >> 12) & 0x3ff;
|
||||||
|
imm11 = (offset >> 1) & 0x7ff;
|
||||||
|
|
||||||
|
j1 = (!i1) ^ s;
|
||||||
|
j2 = (!i2) ^ s;
|
||||||
|
|
||||||
|
first = 0xf000 | (s << 10) | imm10;
|
||||||
|
second = 0xd000 | (j1 << 13) | (j2 << 11) | imm11;
|
||||||
|
|
||||||
|
return (second << 16) | first;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static unsigned long ftrace_call_replace(unsigned long pc, unsigned long addr)
|
||||||
{
|
{
|
||||||
long offset;
|
long offset;
|
||||||
|
|
||||||
offset = (long)addr - (long)(pc + PC_OFFSET);
|
offset = (long)addr - (long)(pc + 8);
|
||||||
if (unlikely(offset < -33554432 || offset > 33554428)) {
|
if (unlikely(offset < -33554432 || offset > 33554428)) {
|
||||||
/* Can't generate branches that far (from ARM ARM). Ftrace
|
/* Can't generate branches that far (from ARM ARM). Ftrace
|
||||||
* doesn't generate branches outside of kernel text.
|
* doesn't generate branches outside of kernel text.
|
||||||
*/
|
*/
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
offset = (offset >> 2) & BL_OFFSET_MASK;
|
|
||||||
bl_insn = BL_OPCODE | offset;
|
offset = (offset >> 2) & 0x00ffffff;
|
||||||
return (unsigned char *)&bl_insn;
|
|
||||||
|
return 0xeb000000 | offset;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int ftrace_modify_code(unsigned long pc, unsigned char *old_code,
|
static int ftrace_modify_code(unsigned long pc, unsigned long old,
|
||||||
unsigned char *new_code)
|
unsigned long new)
|
||||||
{
|
{
|
||||||
unsigned long err = 0, replaced = 0, old, new;
|
unsigned long replaced;
|
||||||
|
|
||||||
old = *(unsigned long *)old_code;
|
if (probe_kernel_read(&replaced, (void *)pc, MCOUNT_INSN_SIZE))
|
||||||
new = *(unsigned long *)new_code;
|
return -EFAULT;
|
||||||
|
|
||||||
__asm__ __volatile__ (
|
if (replaced != old)
|
||||||
"1: ldr %1, [%2] \n"
|
return -EINVAL;
|
||||||
" cmp %1, %4 \n"
|
|
||||||
"2: streq %3, [%2] \n"
|
|
||||||
" cmpne %1, %3 \n"
|
|
||||||
" movne %0, #2 \n"
|
|
||||||
"3:\n"
|
|
||||||
|
|
||||||
".pushsection .fixup, \"ax\"\n"
|
if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
|
||||||
"4: mov %0, #1 \n"
|
return -EPERM;
|
||||||
" b 3b \n"
|
|
||||||
".popsection\n"
|
|
||||||
|
|
||||||
".pushsection __ex_table, \"a\"\n"
|
flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
|
||||||
" .long 1b, 4b \n"
|
|
||||||
" .long 2b, 4b \n"
|
|
||||||
".popsection\n"
|
|
||||||
|
|
||||||
: "=r"(err), "=r"(replaced)
|
return 0;
|
||||||
: "r"(pc), "r"(new), "r"(old), "0"(err), "1"(replaced)
|
|
||||||
: "memory");
|
|
||||||
|
|
||||||
if (!err && (replaced == old))
|
|
||||||
flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ftrace_update_ftrace_func(ftrace_func_t func)
|
int ftrace_update_ftrace_func(ftrace_func_t func)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
unsigned long pc, old;
|
unsigned long pc, old;
|
||||||
unsigned char *new;
|
unsigned long new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pc = (unsigned long)&ftrace_call;
|
pc = (unsigned long)&ftrace_call;
|
||||||
memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
|
memcpy(&old, &ftrace_call, MCOUNT_INSN_SIZE);
|
||||||
new = ftrace_call_replace(pc, (unsigned long)func);
|
new = ftrace_call_replace(pc, (unsigned long)func);
|
||||||
ret = ftrace_modify_code(pc, (unsigned char *)&old, new);
|
|
||||||
|
ret = ftrace_modify_code(pc, old, new);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OLD_MCOUNT
|
||||||
|
if (!ret) {
|
||||||
|
pc = (unsigned long)&ftrace_call_old;
|
||||||
|
memcpy(&old, &ftrace_call_old, MCOUNT_INSN_SIZE);
|
||||||
|
new = ftrace_call_replace(pc, (unsigned long)func);
|
||||||
|
|
||||||
|
ret = ftrace_modify_code(pc, old, new);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||||
|
{
|
||||||
|
unsigned long new, old;
|
||||||
|
unsigned long ip = rec->ip;
|
||||||
|
|
||||||
|
old = ftrace_nop_replace(rec);
|
||||||
|
new = ftrace_call_replace(ip, adjust_address(rec, addr));
|
||||||
|
|
||||||
|
return ftrace_modify_code(rec->ip, old, new);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ftrace_make_nop(struct module *mod,
|
||||||
|
struct dyn_ftrace *rec, unsigned long addr)
|
||||||
|
{
|
||||||
|
unsigned long ip = rec->ip;
|
||||||
|
unsigned long old;
|
||||||
|
unsigned long new;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
old = ftrace_call_replace(ip, adjust_address(rec, addr));
|
||||||
|
new = ftrace_nop_replace(rec);
|
||||||
|
ret = ftrace_modify_code(ip, old, new);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OLD_MCOUNT
|
||||||
|
if (ret == -EINVAL && addr == MCOUNT_ADDR) {
|
||||||
|
rec->arch.old_mcount = true;
|
||||||
|
|
||||||
|
old = ftrace_call_replace(ip, adjust_address(rec, addr));
|
||||||
|
new = ftrace_nop_replace(rec);
|
||||||
|
ret = ftrace_modify_code(ip, old, new);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* run from ftrace_init with irqs disabled */
|
|
||||||
int __init ftrace_dyn_arch_init(void *data)
|
int __init ftrace_dyn_arch_init(void *data)
|
||||||
{
|
{
|
||||||
ftrace_mcount_set(data);
|
*(unsigned long *)data = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,55 +15,6 @@
|
||||||
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
|
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
|
||||||
#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
|
#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)
|
||||||
|
|
||||||
.align 2
|
|
||||||
.type __switch_data, %object
|
|
||||||
__switch_data:
|
|
||||||
.long __mmap_switched
|
|
||||||
.long __data_loc @ r4
|
|
||||||
.long _data @ r5
|
|
||||||
.long __bss_start @ r6
|
|
||||||
.long _end @ r7
|
|
||||||
.long processor_id @ r4
|
|
||||||
.long __machine_arch_type @ r5
|
|
||||||
.long __atags_pointer @ r6
|
|
||||||
.long cr_alignment @ r7
|
|
||||||
.long init_thread_union + THREAD_START_SP @ sp
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following fragment of code is executed with the MMU on in MMU mode,
|
|
||||||
* and uses absolute addresses; this is not position independent.
|
|
||||||
*
|
|
||||||
* r0 = cp#15 control register
|
|
||||||
* r1 = machine ID
|
|
||||||
* r2 = atags pointer
|
|
||||||
* r9 = processor ID
|
|
||||||
*/
|
|
||||||
__mmap_switched:
|
|
||||||
adr r3, __switch_data + 4
|
|
||||||
|
|
||||||
ldmia r3!, {r4, r5, r6, r7}
|
|
||||||
cmp r4, r5 @ Copy data segment if needed
|
|
||||||
1: cmpne r5, r6
|
|
||||||
ldrne fp, [r4], #4
|
|
||||||
strne fp, [r5], #4
|
|
||||||
bne 1b
|
|
||||||
|
|
||||||
mov fp, #0 @ Clear BSS (and zero fp)
|
|
||||||
1: cmp r6, r7
|
|
||||||
strcc fp, [r6],#4
|
|
||||||
bcc 1b
|
|
||||||
|
|
||||||
ARM( ldmia r3, {r4, r5, r6, r7, sp})
|
|
||||||
THUMB( ldmia r3, {r4, r5, r6, r7} )
|
|
||||||
THUMB( ldr sp, [r3, #16] )
|
|
||||||
str r9, [r4] @ Save processor ID
|
|
||||||
str r1, [r5] @ Save machine type
|
|
||||||
str r2, [r6] @ Save atags pointer
|
|
||||||
bic r4, r0, #CR_A @ Clear 'A' bit
|
|
||||||
stmia r7, {r0, r4} @ Save control register values
|
|
||||||
b start_kernel
|
|
||||||
ENDPROC(__mmap_switched)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exception handling. Something went wrong and we can't proceed. We
|
* Exception handling. Something went wrong and we can't proceed. We
|
||||||
* ought to tell the user, but since we don't have any guarantee that
|
* ought to tell the user, but since we don't have any guarantee that
|
||||||
|
@ -73,21 +24,7 @@ ENDPROC(__mmap_switched)
|
||||||
* and hope for the best (useful if bootloader fails to pass a proper
|
* and hope for the best (useful if bootloader fails to pass a proper
|
||||||
* machine ID for example).
|
* machine ID for example).
|
||||||
*/
|
*/
|
||||||
__error_p:
|
__HEAD
|
||||||
#ifdef CONFIG_DEBUG_LL
|
|
||||||
adr r0, str_p1
|
|
||||||
bl printascii
|
|
||||||
mov r0, r9
|
|
||||||
bl printhex8
|
|
||||||
adr r0, str_p2
|
|
||||||
bl printascii
|
|
||||||
b __error
|
|
||||||
str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x"
|
|
||||||
str_p2: .asciz ").\n"
|
|
||||||
.align
|
|
||||||
#endif
|
|
||||||
ENDPROC(__error_p)
|
|
||||||
|
|
||||||
__error_a:
|
__error_a:
|
||||||
#ifdef CONFIG_DEBUG_LL
|
#ifdef CONFIG_DEBUG_LL
|
||||||
mov r4, r1 @ preserve machine ID
|
mov r4, r1 @ preserve machine ID
|
||||||
|
@ -97,7 +34,7 @@ __error_a:
|
||||||
bl printhex8
|
bl printhex8
|
||||||
adr r0, str_a2
|
adr r0, str_a2
|
||||||
bl printascii
|
bl printascii
|
||||||
adr r3, 4f
|
adr r3, __lookup_machine_type_data
|
||||||
ldmia r3, {r4, r5, r6} @ get machine desc list
|
ldmia r3, {r4, r5, r6} @ get machine desc list
|
||||||
sub r4, r3, r4 @ get offset between virt&phys
|
sub r4, r3, r4 @ get offset between virt&phys
|
||||||
add r5, r5, r4 @ convert virt addresses to
|
add r5, r5, r4 @ convert virt addresses to
|
||||||
|
@ -125,78 +62,6 @@ str_a3: .asciz "\nPlease check your kernel config and/or bootloader.\n"
|
||||||
.align
|
.align
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__error:
|
|
||||||
#ifdef CONFIG_ARCH_RPC
|
|
||||||
/*
|
|
||||||
* Turn the screen red on a error - RiscPC only.
|
|
||||||
*/
|
|
||||||
mov r0, #0x02000000
|
|
||||||
mov r3, #0x11
|
|
||||||
orr r3, r3, r3, lsl #8
|
|
||||||
orr r3, r3, r3, lsl #16
|
|
||||||
str r3, [r0], #4
|
|
||||||
str r3, [r0], #4
|
|
||||||
str r3, [r0], #4
|
|
||||||
str r3, [r0], #4
|
|
||||||
#endif
|
|
||||||
1: mov r0, r0
|
|
||||||
b 1b
|
|
||||||
ENDPROC(__error)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read processor ID register (CP#15, CR0), and look up in the linker-built
|
|
||||||
* supported processor list. Note that we can't use the absolute addresses
|
|
||||||
* for the __proc_info lists since we aren't running with the MMU on
|
|
||||||
* (and therefore, we are not in the correct address space). We have to
|
|
||||||
* calculate the offset.
|
|
||||||
*
|
|
||||||
* r9 = cpuid
|
|
||||||
* Returns:
|
|
||||||
* r3, r4, r6 corrupted
|
|
||||||
* r5 = proc_info pointer in physical address space
|
|
||||||
* r9 = cpuid (preserved)
|
|
||||||
*/
|
|
||||||
__lookup_processor_type:
|
|
||||||
adr r3, 3f
|
|
||||||
ldmia r3, {r5 - r7}
|
|
||||||
add r3, r3, #8
|
|
||||||
sub r3, r3, r7 @ get offset between virt&phys
|
|
||||||
add r5, r5, r3 @ convert virt addresses to
|
|
||||||
add r6, r6, r3 @ physical address space
|
|
||||||
1: ldmia r5, {r3, r4} @ value, mask
|
|
||||||
and r4, r4, r9 @ mask wanted bits
|
|
||||||
teq r3, r4
|
|
||||||
beq 2f
|
|
||||||
add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
|
|
||||||
cmp r5, r6
|
|
||||||
blo 1b
|
|
||||||
mov r5, #0 @ unknown processor
|
|
||||||
2: mov pc, lr
|
|
||||||
ENDPROC(__lookup_processor_type)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This provides a C-API version of the above function.
|
|
||||||
*/
|
|
||||||
ENTRY(lookup_processor_type)
|
|
||||||
stmfd sp!, {r4 - r7, r9, lr}
|
|
||||||
mov r9, r0
|
|
||||||
bl __lookup_processor_type
|
|
||||||
mov r0, r5
|
|
||||||
ldmfd sp!, {r4 - r7, r9, pc}
|
|
||||||
ENDPROC(lookup_processor_type)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for
|
|
||||||
* more information about the __proc_info and __arch_info structures.
|
|
||||||
*/
|
|
||||||
.align 2
|
|
||||||
3: .long __proc_info_begin
|
|
||||||
.long __proc_info_end
|
|
||||||
4: .long .
|
|
||||||
.long __arch_info_begin
|
|
||||||
.long __arch_info_end
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lookup machine architecture in the linker-build list of architectures.
|
* Lookup machine architecture in the linker-build list of architectures.
|
||||||
* Note that we can't use the absolute addresses for the __arch_info
|
* Note that we can't use the absolute addresses for the __arch_info
|
||||||
|
@ -209,7 +74,7 @@ ENDPROC(lookup_processor_type)
|
||||||
* r5 = mach_info pointer in physical address space
|
* r5 = mach_info pointer in physical address space
|
||||||
*/
|
*/
|
||||||
__lookup_machine_type:
|
__lookup_machine_type:
|
||||||
adr r3, 4b
|
adr r3, __lookup_machine_type_data
|
||||||
ldmia r3, {r4, r5, r6}
|
ldmia r3, {r4, r5, r6}
|
||||||
sub r3, r3, r4 @ get offset between virt&phys
|
sub r3, r3, r4 @ get offset between virt&phys
|
||||||
add r5, r5, r3 @ convert virt addresses to
|
add r5, r5, r3 @ convert virt addresses to
|
||||||
|
@ -225,15 +90,16 @@ __lookup_machine_type:
|
||||||
ENDPROC(__lookup_machine_type)
|
ENDPROC(__lookup_machine_type)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This provides a C-API version of the above function.
|
* Look in arch/arm/kernel/arch.[ch] for information about the
|
||||||
|
* __arch_info structures.
|
||||||
*/
|
*/
|
||||||
ENTRY(lookup_machine_type)
|
.align 2
|
||||||
stmfd sp!, {r4 - r6, lr}
|
.type __lookup_machine_type_data, %object
|
||||||
mov r1, r0
|
__lookup_machine_type_data:
|
||||||
bl __lookup_machine_type
|
.long .
|
||||||
mov r0, r5
|
.long __arch_info_begin
|
||||||
ldmfd sp!, {r4 - r6, pc}
|
.long __arch_info_end
|
||||||
ENDPROC(lookup_machine_type)
|
.size __lookup_machine_type_data, . - __lookup_machine_type_data
|
||||||
|
|
||||||
/* Determine validity of the r2 atags pointer. The heuristic requires
|
/* Determine validity of the r2 atags pointer. The heuristic requires
|
||||||
* that the pointer be aligned, in the first 16k of physical RAM and
|
* that the pointer be aligned, in the first 16k of physical RAM and
|
||||||
|
@ -265,3 +131,150 @@ __vet_atags:
|
||||||
1: mov r2, #0
|
1: mov r2, #0
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
ENDPROC(__vet_atags)
|
ENDPROC(__vet_atags)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following fragment of code is executed with the MMU on in MMU mode,
|
||||||
|
* and uses absolute addresses; this is not position independent.
|
||||||
|
*
|
||||||
|
* r0 = cp#15 control register
|
||||||
|
* r1 = machine ID
|
||||||
|
* r2 = atags pointer
|
||||||
|
* r9 = processor ID
|
||||||
|
*/
|
||||||
|
__INIT
|
||||||
|
__mmap_switched:
|
||||||
|
adr r3, __mmap_switched_data
|
||||||
|
|
||||||
|
ldmia r3!, {r4, r5, r6, r7}
|
||||||
|
cmp r4, r5 @ Copy data segment if needed
|
||||||
|
1: cmpne r5, r6
|
||||||
|
ldrne fp, [r4], #4
|
||||||
|
strne fp, [r5], #4
|
||||||
|
bne 1b
|
||||||
|
|
||||||
|
mov fp, #0 @ Clear BSS (and zero fp)
|
||||||
|
1: cmp r6, r7
|
||||||
|
strcc fp, [r6],#4
|
||||||
|
bcc 1b
|
||||||
|
|
||||||
|
ARM( ldmia r3, {r4, r5, r6, r7, sp})
|
||||||
|
THUMB( ldmia r3, {r4, r5, r6, r7} )
|
||||||
|
THUMB( ldr sp, [r3, #16] )
|
||||||
|
str r9, [r4] @ Save processor ID
|
||||||
|
str r1, [r5] @ Save machine type
|
||||||
|
str r2, [r6] @ Save atags pointer
|
||||||
|
bic r4, r0, #CR_A @ Clear 'A' bit
|
||||||
|
stmia r7, {r0, r4} @ Save control register values
|
||||||
|
b start_kernel
|
||||||
|
ENDPROC(__mmap_switched)
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
.type __mmap_switched_data, %object
|
||||||
|
__mmap_switched_data:
|
||||||
|
.long __data_loc @ r4
|
||||||
|
.long _sdata @ r5
|
||||||
|
.long __bss_start @ r6
|
||||||
|
.long _end @ r7
|
||||||
|
.long processor_id @ r4
|
||||||
|
.long __machine_arch_type @ r5
|
||||||
|
.long __atags_pointer @ r6
|
||||||
|
.long cr_alignment @ r7
|
||||||
|
.long init_thread_union + THREAD_START_SP @ sp
|
||||||
|
.size __mmap_switched_data, . - __mmap_switched_data
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This provides a C-API version of __lookup_machine_type
|
||||||
|
*/
|
||||||
|
ENTRY(lookup_machine_type)
|
||||||
|
stmfd sp!, {r4 - r6, lr}
|
||||||
|
mov r1, r0
|
||||||
|
bl __lookup_machine_type
|
||||||
|
mov r0, r5
|
||||||
|
ldmfd sp!, {r4 - r6, pc}
|
||||||
|
ENDPROC(lookup_machine_type)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This provides a C-API version of __lookup_processor_type
|
||||||
|
*/
|
||||||
|
ENTRY(lookup_processor_type)
|
||||||
|
stmfd sp!, {r4 - r6, r9, lr}
|
||||||
|
mov r9, r0
|
||||||
|
bl __lookup_processor_type
|
||||||
|
mov r0, r5
|
||||||
|
ldmfd sp!, {r4 - r6, r9, pc}
|
||||||
|
ENDPROC(lookup_processor_type)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read processor ID register (CP#15, CR0), and look up in the linker-built
|
||||||
|
* supported processor list. Note that we can't use the absolute addresses
|
||||||
|
* for the __proc_info lists since we aren't running with the MMU on
|
||||||
|
* (and therefore, we are not in the correct address space). We have to
|
||||||
|
* calculate the offset.
|
||||||
|
*
|
||||||
|
* r9 = cpuid
|
||||||
|
* Returns:
|
||||||
|
* r3, r4, r6 corrupted
|
||||||
|
* r5 = proc_info pointer in physical address space
|
||||||
|
* r9 = cpuid (preserved)
|
||||||
|
*/
|
||||||
|
__CPUINIT
|
||||||
|
__lookup_processor_type:
|
||||||
|
adr r3, __lookup_processor_type_data
|
||||||
|
ldmia r3, {r4 - r6}
|
||||||
|
sub r3, r3, r4 @ get offset between virt&phys
|
||||||
|
add r5, r5, r3 @ convert virt addresses to
|
||||||
|
add r6, r6, r3 @ physical address space
|
||||||
|
1: ldmia r5, {r3, r4} @ value, mask
|
||||||
|
and r4, r4, r9 @ mask wanted bits
|
||||||
|
teq r3, r4
|
||||||
|
beq 2f
|
||||||
|
add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
|
||||||
|
cmp r5, r6
|
||||||
|
blo 1b
|
||||||
|
mov r5, #0 @ unknown processor
|
||||||
|
2: mov pc, lr
|
||||||
|
ENDPROC(__lookup_processor_type)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look in <asm/procinfo.h> for information about the __proc_info structure.
|
||||||
|
*/
|
||||||
|
.align 2
|
||||||
|
.type __lookup_processor_type_data, %object
|
||||||
|
__lookup_processor_type_data:
|
||||||
|
.long .
|
||||||
|
.long __proc_info_begin
|
||||||
|
.long __proc_info_end
|
||||||
|
.size __lookup_processor_type_data, . - __lookup_processor_type_data
|
||||||
|
|
||||||
|
__error_p:
|
||||||
|
#ifdef CONFIG_DEBUG_LL
|
||||||
|
adr r0, str_p1
|
||||||
|
bl printascii
|
||||||
|
mov r0, r9
|
||||||
|
bl printhex8
|
||||||
|
adr r0, str_p2
|
||||||
|
bl printascii
|
||||||
|
b __error
|
||||||
|
str_p1: .asciz "\nError: unrecognized/unsupported processor variant (0x"
|
||||||
|
str_p2: .asciz ").\n"
|
||||||
|
.align
|
||||||
|
#endif
|
||||||
|
ENDPROC(__error_p)
|
||||||
|
|
||||||
|
__error:
|
||||||
|
#ifdef CONFIG_ARCH_RPC
|
||||||
|
/*
|
||||||
|
* Turn the screen red on a error - RiscPC only.
|
||||||
|
*/
|
||||||
|
mov r0, #0x02000000
|
||||||
|
mov r3, #0x11
|
||||||
|
orr r3, r3, r3, lsl #8
|
||||||
|
orr r3, r3, r3, lsl #16
|
||||||
|
str r3, [r0], #4
|
||||||
|
str r3, [r0], #4
|
||||||
|
str r3, [r0], #4
|
||||||
|
str r3, [r0], #4
|
||||||
|
#endif
|
||||||
|
1: mov r0, r0
|
||||||
|
b 1b
|
||||||
|
ENDPROC(__error)
|
||||||
|
|
|
@ -48,8 +48,6 @@ ENTRY(stext)
|
||||||
movs r8, r5 @ invalid machine (r5=0)?
|
movs r8, r5 @ invalid machine (r5=0)?
|
||||||
beq __error_a @ yes, error 'a'
|
beq __error_a @ yes, error 'a'
|
||||||
|
|
||||||
ldr r13, __switch_data @ address to jump to after
|
|
||||||
@ the initialization is done
|
|
||||||
adr lr, BSYM(__after_proc_init) @ return (PIC) address
|
adr lr, BSYM(__after_proc_init) @ return (PIC) address
|
||||||
ARM( add pc, r10, #PROCINFO_INITFUNC )
|
ARM( add pc, r10, #PROCINFO_INITFUNC )
|
||||||
THUMB( add r12, r10, #PROCINFO_INITFUNC )
|
THUMB( add r12, r10, #PROCINFO_INITFUNC )
|
||||||
|
@ -87,8 +85,7 @@ __after_proc_init:
|
||||||
mcr p15, 0, r0, c1, c0, 0 @ write control reg
|
mcr p15, 0, r0, c1, c0, 0 @ write control reg
|
||||||
#endif /* CONFIG_CPU_CP15 */
|
#endif /* CONFIG_CPU_CP15 */
|
||||||
|
|
||||||
mov r3, r13
|
b __mmap_switched @ clear the BSS and jump
|
||||||
mov pc, r3 @ clear the BSS and jump
|
|
||||||
@ to start_kernel
|
@ to start_kernel
|
||||||
ENDPROC(__after_proc_init)
|
ENDPROC(__after_proc_init)
|
||||||
.ltorg
|
.ltorg
|
||||||
|
|
|
@ -22,6 +22,10 @@
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_LL
|
||||||
|
#include <mach/debug-macro.S>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (PHYS_OFFSET & 0x001fffff)
|
#if (PHYS_OFFSET & 0x001fffff)
|
||||||
#error "PHYS_OFFSET must be at an even 2MiB boundary!"
|
#error "PHYS_OFFSET must be at an even 2MiB boundary!"
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,6 +90,9 @@ ENTRY(stext)
|
||||||
movs r8, r5 @ invalid machine (r5=0)?
|
movs r8, r5 @ invalid machine (r5=0)?
|
||||||
beq __error_a @ yes, error 'a'
|
beq __error_a @ yes, error 'a'
|
||||||
bl __vet_atags
|
bl __vet_atags
|
||||||
|
#ifdef CONFIG_SMP_ON_UP
|
||||||
|
bl __fixup_smp
|
||||||
|
#endif
|
||||||
bl __create_page_tables
|
bl __create_page_tables
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -95,113 +102,15 @@ ENTRY(stext)
|
||||||
* above. On return, the CPU will be ready for the MMU to be
|
* above. On return, the CPU will be ready for the MMU to be
|
||||||
* turned on, and r0 will hold the CPU control register value.
|
* turned on, and r0 will hold the CPU control register value.
|
||||||
*/
|
*/
|
||||||
ldr r13, __switch_data @ address to jump to after
|
ldr r13, =__mmap_switched @ address to jump to after
|
||||||
@ mmu has been enabled
|
@ mmu has been enabled
|
||||||
adr lr, BSYM(__enable_mmu) @ return (PIC) address
|
adr lr, BSYM(1f) @ return (PIC) address
|
||||||
ARM( add pc, r10, #PROCINFO_INITFUNC )
|
ARM( add pc, r10, #PROCINFO_INITFUNC )
|
||||||
THUMB( add r12, r10, #PROCINFO_INITFUNC )
|
THUMB( add r12, r10, #PROCINFO_INITFUNC )
|
||||||
THUMB( mov pc, r12 )
|
THUMB( mov pc, r12 )
|
||||||
|
1: b __enable_mmu
|
||||||
ENDPROC(stext)
|
ENDPROC(stext)
|
||||||
|
.ltorg
|
||||||
#if defined(CONFIG_SMP)
|
|
||||||
ENTRY(secondary_startup)
|
|
||||||
/*
|
|
||||||
* Common entry point for secondary CPUs.
|
|
||||||
*
|
|
||||||
* Ensure that we're in SVC mode, and IRQs are disabled. Lookup
|
|
||||||
* the processor type - there is no need to check the machine type
|
|
||||||
* as it has already been validated by the primary processor.
|
|
||||||
*/
|
|
||||||
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
|
|
||||||
mrc p15, 0, r9, c0, c0 @ get processor id
|
|
||||||
bl __lookup_processor_type
|
|
||||||
movs r10, r5 @ invalid processor?
|
|
||||||
moveq r0, #'p' @ yes, error 'p'
|
|
||||||
beq __error
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Use the page tables supplied from __cpu_up.
|
|
||||||
*/
|
|
||||||
adr r4, __secondary_data
|
|
||||||
ldmia r4, {r5, r7, r12} @ address to jump to after
|
|
||||||
sub r4, r4, r5 @ mmu has been enabled
|
|
||||||
ldr r4, [r7, r4] @ get secondary_data.pgdir
|
|
||||||
adr lr, BSYM(__enable_mmu) @ return address
|
|
||||||
mov r13, r12 @ __secondary_switched address
|
|
||||||
ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor
|
|
||||||
@ (return control reg)
|
|
||||||
THUMB( add r12, r10, #PROCINFO_INITFUNC )
|
|
||||||
THUMB( mov pc, r12 )
|
|
||||||
ENDPROC(secondary_startup)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* r6 = &secondary_data
|
|
||||||
*/
|
|
||||||
ENTRY(__secondary_switched)
|
|
||||||
ldr sp, [r7, #4] @ get secondary_data.stack
|
|
||||||
mov fp, #0
|
|
||||||
b secondary_start_kernel
|
|
||||||
ENDPROC(__secondary_switched)
|
|
||||||
|
|
||||||
.type __secondary_data, %object
|
|
||||||
__secondary_data:
|
|
||||||
.long .
|
|
||||||
.long secondary_data
|
|
||||||
.long __secondary_switched
|
|
||||||
#endif /* defined(CONFIG_SMP) */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Setup common bits before finally enabling the MMU. Essentially
|
|
||||||
* this is just loading the page table pointer and domain access
|
|
||||||
* registers.
|
|
||||||
*/
|
|
||||||
__enable_mmu:
|
|
||||||
#ifdef CONFIG_ALIGNMENT_TRAP
|
|
||||||
orr r0, r0, #CR_A
|
|
||||||
#else
|
|
||||||
bic r0, r0, #CR_A
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_CPU_DCACHE_DISABLE
|
|
||||||
bic r0, r0, #CR_C
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_CPU_BPREDICT_DISABLE
|
|
||||||
bic r0, r0, #CR_Z
|
|
||||||
#endif
|
|
||||||
#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) | \
|
|
||||||
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
|
|
||||||
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
|
|
||||||
ENDPROC(__enable_mmu)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable the MMU. This completely changes the structure of the visible
|
|
||||||
* memory space. You will not be able to trace execution through this.
|
|
||||||
* If you have an enquiry about this, *please* check the linux-arm-kernel
|
|
||||||
* mailing list archives BEFORE sending another post to the list.
|
|
||||||
*
|
|
||||||
* r0 = cp#15 control register
|
|
||||||
* r13 = *virtual* address to jump to upon completion
|
|
||||||
*
|
|
||||||
* other registers depend on the function called upon completion
|
|
||||||
*/
|
|
||||||
.align 5
|
|
||||||
__turn_mmu_on:
|
|
||||||
mov r0, r0
|
|
||||||
mcr p15, 0, r0, c1, c0, 0 @ write control reg
|
|
||||||
mrc p15, 0, r3, c0, c0, 0 @ read id reg
|
|
||||||
mov r3, r3
|
|
||||||
mov r3, r13
|
|
||||||
mov pc, r3
|
|
||||||
ENDPROC(__turn_mmu_on)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the initial page tables. We only setup the barest
|
* Setup the initial page tables. We only setup the barest
|
||||||
|
@ -213,7 +122,7 @@ ENDPROC(__turn_mmu_on)
|
||||||
* r10 = procinfo
|
* r10 = procinfo
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* r0, r3, r6, r7 corrupted
|
* r0, r3, r5-r7 corrupted
|
||||||
* r4 = physical page table address
|
* r4 = physical page table address
|
||||||
*/
|
*/
|
||||||
__create_page_tables:
|
__create_page_tables:
|
||||||
|
@ -235,20 +144,30 @@ __create_page_tables:
|
||||||
ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
|
ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create identity mapping for first MB of kernel to
|
* Create identity mapping to cater for __enable_mmu.
|
||||||
* cater for the MMU enable. This identity mapping
|
* This identity mapping will be removed by paging_init().
|
||||||
* will be removed by paging_init(). We use our current program
|
|
||||||
* counter to determine corresponding section base address.
|
|
||||||
*/
|
*/
|
||||||
mov r6, pc
|
adr r0, __enable_mmu_loc
|
||||||
mov r6, r6, lsr #20 @ start of kernel section
|
ldmia r0, {r3, r5, r6}
|
||||||
orr r3, r7, r6, lsl #20 @ flags + kernel base
|
sub r0, r0, r3 @ virt->phys offset
|
||||||
str r3, [r4, r6, lsl #2] @ identity mapping
|
add r5, r5, r0 @ phys __enable_mmu
|
||||||
|
add r6, r6, r0 @ phys __enable_mmu_end
|
||||||
|
mov r5, r5, lsr #20
|
||||||
|
mov r6, r6, lsr #20
|
||||||
|
|
||||||
|
1: orr r3, r7, r5, lsl #20 @ flags + kernel base
|
||||||
|
str r3, [r4, r5, lsl #2] @ identity mapping
|
||||||
|
teq r5, r6
|
||||||
|
addne r5, r5, #1 @ next section
|
||||||
|
bne 1b
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now setup the pagetables for our kernel direct
|
* Now setup the pagetables for our kernel direct
|
||||||
* mapped region.
|
* mapped region.
|
||||||
*/
|
*/
|
||||||
|
mov r3, pc
|
||||||
|
mov r3, r3, lsr #20
|
||||||
|
orr r3, r7, r3, lsl #20
|
||||||
add r0, r4, #(KERNEL_START & 0xff000000) >> 18
|
add r0, r4, #(KERNEL_START & 0xff000000) >> 18
|
||||||
str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
|
str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
|
||||||
ldr r6, =(KERNEL_END - 1)
|
ldr r6, =(KERNEL_END - 1)
|
||||||
|
@ -289,24 +208,35 @@ __create_page_tables:
|
||||||
str r6, [r0]
|
str r6, [r0]
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_LL
|
#ifdef CONFIG_DEBUG_LL
|
||||||
ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
|
#ifndef CONFIG_DEBUG_ICEDCC
|
||||||
/*
|
/*
|
||||||
* Map in IO space for serial debugging.
|
* Map in IO space for serial debugging.
|
||||||
* This allows debug messages to be output
|
* This allows debug messages to be output
|
||||||
* via a serial console before paging_init.
|
* via a serial console before paging_init.
|
||||||
*/
|
*/
|
||||||
ldr r3, [r8, #MACHINFO_PGOFFIO]
|
addruart r7, r3
|
||||||
|
|
||||||
|
mov r3, r3, lsr #20
|
||||||
|
mov r3, r3, lsl #2
|
||||||
|
|
||||||
add r0, r4, r3
|
add r0, r4, r3
|
||||||
rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long)
|
rsb r3, r3, #0x4000 @ PTRS_PER_PGD*sizeof(long)
|
||||||
cmp r3, #0x0800 @ limit to 512MB
|
cmp r3, #0x0800 @ limit to 512MB
|
||||||
movhi r3, #0x0800
|
movhi r3, #0x0800
|
||||||
add r6, r0, r3
|
add r6, r0, r3
|
||||||
ldr r3, [r8, #MACHINFO_PHYSIO]
|
mov r3, r7, lsr #20
|
||||||
orr r3, r3, r7
|
ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
|
||||||
|
orr r3, r7, r3, lsl #20
|
||||||
1: str r3, [r0], #4
|
1: str r3, [r0], #4
|
||||||
add r3, r3, #1 << 20
|
add r3, r3, #1 << 20
|
||||||
teq r0, r6
|
teq r0, r6
|
||||||
bne 1b
|
bne 1b
|
||||||
|
|
||||||
|
#else /* CONFIG_DEBUG_ICEDCC */
|
||||||
|
/* we don't need any serial debugging mappings for ICEDCC */
|
||||||
|
ldr r7, [r10, #PROCINFO_IO_MMUFLAGS] @ io_mmuflags
|
||||||
|
#endif /* !CONFIG_DEBUG_ICEDCC */
|
||||||
|
|
||||||
#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
|
#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)
|
||||||
/*
|
/*
|
||||||
* If we're using the NetWinder or CATS, we also need to map
|
* If we're using the NetWinder or CATS, we also need to map
|
||||||
|
@ -332,5 +262,168 @@ __create_page_tables:
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
ENDPROC(__create_page_tables)
|
ENDPROC(__create_page_tables)
|
||||||
.ltorg
|
.ltorg
|
||||||
|
__enable_mmu_loc:
|
||||||
|
.long .
|
||||||
|
.long __enable_mmu
|
||||||
|
.long __enable_mmu_end
|
||||||
|
|
||||||
|
#if defined(CONFIG_SMP)
|
||||||
|
__CPUINIT
|
||||||
|
ENTRY(secondary_startup)
|
||||||
|
/*
|
||||||
|
* Common entry point for secondary CPUs.
|
||||||
|
*
|
||||||
|
* Ensure that we're in SVC mode, and IRQs are disabled. Lookup
|
||||||
|
* the processor type - there is no need to check the machine type
|
||||||
|
* as it has already been validated by the primary processor.
|
||||||
|
*/
|
||||||
|
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
|
||||||
|
mrc p15, 0, r9, c0, c0 @ get processor id
|
||||||
|
bl __lookup_processor_type
|
||||||
|
movs r10, r5 @ invalid processor?
|
||||||
|
moveq r0, #'p' @ yes, error 'p'
|
||||||
|
beq __error_p
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the page tables supplied from __cpu_up.
|
||||||
|
*/
|
||||||
|
adr r4, __secondary_data
|
||||||
|
ldmia r4, {r5, r7, r12} @ address to jump to after
|
||||||
|
sub r4, r4, r5 @ mmu has been enabled
|
||||||
|
ldr r4, [r7, r4] @ get secondary_data.pgdir
|
||||||
|
adr lr, BSYM(__enable_mmu) @ return address
|
||||||
|
mov r13, r12 @ __secondary_switched address
|
||||||
|
ARM( add pc, r10, #PROCINFO_INITFUNC ) @ initialise processor
|
||||||
|
@ (return control reg)
|
||||||
|
THUMB( add r12, r10, #PROCINFO_INITFUNC )
|
||||||
|
THUMB( mov pc, r12 )
|
||||||
|
ENDPROC(secondary_startup)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* r6 = &secondary_data
|
||||||
|
*/
|
||||||
|
ENTRY(__secondary_switched)
|
||||||
|
ldr sp, [r7, #4] @ get secondary_data.stack
|
||||||
|
mov fp, #0
|
||||||
|
b secondary_start_kernel
|
||||||
|
ENDPROC(__secondary_switched)
|
||||||
|
|
||||||
|
.type __secondary_data, %object
|
||||||
|
__secondary_data:
|
||||||
|
.long .
|
||||||
|
.long secondary_data
|
||||||
|
.long __secondary_switched
|
||||||
|
#endif /* defined(CONFIG_SMP) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Setup common bits before finally enabling the MMU. Essentially
|
||||||
|
* this is just loading the page table pointer and domain access
|
||||||
|
* registers.
|
||||||
|
*
|
||||||
|
* r0 = cp#15 control register
|
||||||
|
* r1 = machine ID
|
||||||
|
* r2 = atags pointer
|
||||||
|
* r4 = page table pointer
|
||||||
|
* r9 = processor ID
|
||||||
|
* r13 = *virtual* address to jump to upon completion
|
||||||
|
*/
|
||||||
|
__enable_mmu:
|
||||||
|
#ifdef CONFIG_ALIGNMENT_TRAP
|
||||||
|
orr r0, r0, #CR_A
|
||||||
|
#else
|
||||||
|
bic r0, r0, #CR_A
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CPU_DCACHE_DISABLE
|
||||||
|
bic r0, r0, #CR_C
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_CPU_BPREDICT_DISABLE
|
||||||
|
bic r0, r0, #CR_Z
|
||||||
|
#endif
|
||||||
|
#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) | \
|
||||||
|
domain_val(DOMAIN_IO, DOMAIN_CLIENT))
|
||||||
|
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
|
||||||
|
ENDPROC(__enable_mmu)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable the MMU. This completely changes the structure of the visible
|
||||||
|
* memory space. You will not be able to trace execution through this.
|
||||||
|
* If you have an enquiry about this, *please* check the linux-arm-kernel
|
||||||
|
* mailing list archives BEFORE sending another post to the list.
|
||||||
|
*
|
||||||
|
* r0 = cp#15 control register
|
||||||
|
* r1 = machine ID
|
||||||
|
* r2 = atags pointer
|
||||||
|
* r9 = processor ID
|
||||||
|
* r13 = *virtual* address to jump to upon completion
|
||||||
|
*
|
||||||
|
* other registers depend on the function called upon completion
|
||||||
|
*/
|
||||||
|
.align 5
|
||||||
|
__turn_mmu_on:
|
||||||
|
mov r0, r0
|
||||||
|
mcr p15, 0, r0, c1, c0, 0 @ write control reg
|
||||||
|
mrc p15, 0, r3, c0, c0, 0 @ read id reg
|
||||||
|
mov r3, r3
|
||||||
|
mov r3, r13
|
||||||
|
mov pc, r3
|
||||||
|
__enable_mmu_end:
|
||||||
|
ENDPROC(__turn_mmu_on)
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_SMP_ON_UP
|
||||||
|
__fixup_smp:
|
||||||
|
mov r7, #0x00070000
|
||||||
|
orr r6, r7, #0xff000000 @ mask 0xff070000
|
||||||
|
orr r7, r7, #0x41000000 @ val 0x41070000
|
||||||
|
and r0, r9, r6
|
||||||
|
teq r0, r7 @ ARM CPU and ARMv6/v7?
|
||||||
|
bne __fixup_smp_on_up @ no, assume UP
|
||||||
|
|
||||||
|
orr r6, r6, #0x0000ff00
|
||||||
|
orr r6, r6, #0x000000f0 @ mask 0xff07fff0
|
||||||
|
orr r7, r7, #0x0000b000
|
||||||
|
orr r7, r7, #0x00000020 @ val 0x4107b020
|
||||||
|
and r0, r9, r6
|
||||||
|
teq r0, r7 @ ARM 11MPCore?
|
||||||
|
moveq pc, lr @ yes, assume SMP
|
||||||
|
|
||||||
|
mrc p15, 0, r0, c0, c0, 5 @ read MPIDR
|
||||||
|
tst r0, #1 << 31
|
||||||
|
movne pc, lr @ bit 31 => SMP
|
||||||
|
|
||||||
|
__fixup_smp_on_up:
|
||||||
|
adr r0, 1f
|
||||||
|
ldmia r0, {r3, r6, r7}
|
||||||
|
sub r3, r0, r3
|
||||||
|
add r6, r6, r3
|
||||||
|
add r7, r7, r3
|
||||||
|
2: cmp r6, r7
|
||||||
|
ldmia r6!, {r0, r4}
|
||||||
|
strlo r4, [r0, r3]
|
||||||
|
blo 2b
|
||||||
|
mov pc, lr
|
||||||
|
ENDPROC(__fixup_smp)
|
||||||
|
|
||||||
|
1: .word .
|
||||||
|
.word __smpalt_begin
|
||||||
|
.word __smpalt_end
|
||||||
|
|
||||||
|
.pushsection .data
|
||||||
|
.globl smp_on_up
|
||||||
|
smp_on_up:
|
||||||
|
ALT_SMP(.long 1)
|
||||||
|
ALT_UP(.long 0)
|
||||||
|
.popsection
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "head-common.S"
|
#include "head-common.S"
|
||||||
|
|
849
arch/arm/kernel/hw_breakpoint.c
Normal file
849
arch/arm/kernel/hw_breakpoint.c
Normal file
|
@ -0,0 +1,849 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009, 2010 ARM Limited
|
||||||
|
*
|
||||||
|
* Author: Will Deacon <will.deacon@arm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
|
||||||
|
* using the CPU's debug registers.
|
||||||
|
*/
|
||||||
|
#define pr_fmt(fmt) "hw-breakpoint: " fmt
|
||||||
|
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/perf_event.h>
|
||||||
|
#include <linux/hw_breakpoint.h>
|
||||||
|
#include <linux/smp.h>
|
||||||
|
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/cputype.h>
|
||||||
|
#include <asm/current.h>
|
||||||
|
#include <asm/hw_breakpoint.h>
|
||||||
|
#include <asm/kdebug.h>
|
||||||
|
#include <asm/system.h>
|
||||||
|
#include <asm/traps.h>
|
||||||
|
|
||||||
|
/* Breakpoint currently in use for each BRP. */
|
||||||
|
static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
|
||||||
|
|
||||||
|
/* Watchpoint currently in use for each WRP. */
|
||||||
|
static DEFINE_PER_CPU(struct perf_event *, wp_on_reg[ARM_MAX_WRP]);
|
||||||
|
|
||||||
|
/* Number of BRP/WRP registers on this CPU. */
|
||||||
|
static int core_num_brps;
|
||||||
|
static int core_num_wrps;
|
||||||
|
|
||||||
|
/* Debug architecture version. */
|
||||||
|
static u8 debug_arch;
|
||||||
|
|
||||||
|
/* Maximum supported watchpoint length. */
|
||||||
|
static u8 max_watchpoint_len;
|
||||||
|
|
||||||
|
/* Determine number of BRP registers available. */
|
||||||
|
static int get_num_brps(void)
|
||||||
|
{
|
||||||
|
u32 didr;
|
||||||
|
ARM_DBG_READ(c0, 0, didr);
|
||||||
|
return ((didr >> 24) & 0xf) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine number of WRP registers available. */
|
||||||
|
static int get_num_wrps(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* FIXME: When a watchpoint fires, the only way to work out which
|
||||||
|
* watchpoint it was is by disassembling the faulting instruction
|
||||||
|
* and working out the address of the memory access.
|
||||||
|
*
|
||||||
|
* Furthermore, we can only do this if the watchpoint was precise
|
||||||
|
* since imprecise watchpoints prevent us from calculating register
|
||||||
|
* based addresses.
|
||||||
|
*
|
||||||
|
* For the time being, we only report 1 watchpoint register so we
|
||||||
|
* always know which watchpoint fired. In the future we can either
|
||||||
|
* add a disassembler and address generation emulator, or we can
|
||||||
|
* insert a check to see if the DFAR is set on watchpoint exception
|
||||||
|
* entry [the ARM ARM states that the DFAR is UNKNOWN, but
|
||||||
|
* experience shows that it is set on some implementations].
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
u32 didr, wrps;
|
||||||
|
ARM_DBG_READ(c0, 0, didr);
|
||||||
|
return ((didr >> 28) & 0xf) + 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hw_breakpoint_slots(int type)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We can be called early, so don't rely on
|
||||||
|
* our static variables being initialised.
|
||||||
|
*/
|
||||||
|
switch (type) {
|
||||||
|
case TYPE_INST:
|
||||||
|
return get_num_brps();
|
||||||
|
case TYPE_DATA:
|
||||||
|
return get_num_wrps();
|
||||||
|
default:
|
||||||
|
pr_warning("unknown slot type: %d\n", type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine debug architecture. */
|
||||||
|
static u8 get_debug_arch(void)
|
||||||
|
{
|
||||||
|
u32 didr;
|
||||||
|
|
||||||
|
/* Do we implement the extended CPUID interface? */
|
||||||
|
if (((read_cpuid_id() >> 16) & 0xf) != 0xf) {
|
||||||
|
pr_warning("CPUID feature registers not supported. "
|
||||||
|
"Assuming v6 debug is present.\n");
|
||||||
|
return ARM_DEBUG_ARCH_V6;
|
||||||
|
}
|
||||||
|
|
||||||
|
ARM_DBG_READ(c0, 0, didr);
|
||||||
|
return (didr >> 16) & 0xf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Does this core support mismatch breakpoints? */
|
||||||
|
static int core_has_mismatch_bps(void)
|
||||||
|
{
|
||||||
|
return debug_arch >= ARM_DEBUG_ARCH_V7_ECP14 && core_num_brps > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 arch_get_debug_arch(void)
|
||||||
|
{
|
||||||
|
return debug_arch;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_WB_REG_CASE(OP2, M, VAL) \
|
||||||
|
case ((OP2 << 4) + M): \
|
||||||
|
ARM_DBG_READ(c ## M, OP2, VAL); \
|
||||||
|
break
|
||||||
|
|
||||||
|
#define WRITE_WB_REG_CASE(OP2, M, VAL) \
|
||||||
|
case ((OP2 << 4) + M): \
|
||||||
|
ARM_DBG_WRITE(c ## M, OP2, VAL);\
|
||||||
|
break
|
||||||
|
|
||||||
|
#define GEN_READ_WB_REG_CASES(OP2, VAL) \
|
||||||
|
READ_WB_REG_CASE(OP2, 0, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 1, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 2, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 3, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 4, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 5, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 6, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 7, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 8, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 9, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 10, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 11, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 12, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 13, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 14, VAL); \
|
||||||
|
READ_WB_REG_CASE(OP2, 15, VAL)
|
||||||
|
|
||||||
|
#define GEN_WRITE_WB_REG_CASES(OP2, VAL) \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 0, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 1, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 2, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 3, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 4, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 5, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 6, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 7, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 8, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 9, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 10, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 11, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 12, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 13, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 14, VAL); \
|
||||||
|
WRITE_WB_REG_CASE(OP2, 15, VAL)
|
||||||
|
|
||||||
|
static u32 read_wb_reg(int n)
|
||||||
|
{
|
||||||
|
u32 val = 0;
|
||||||
|
|
||||||
|
switch (n) {
|
||||||
|
GEN_READ_WB_REG_CASES(ARM_OP2_BVR, val);
|
||||||
|
GEN_READ_WB_REG_CASES(ARM_OP2_BCR, val);
|
||||||
|
GEN_READ_WB_REG_CASES(ARM_OP2_WVR, val);
|
||||||
|
GEN_READ_WB_REG_CASES(ARM_OP2_WCR, val);
|
||||||
|
default:
|
||||||
|
pr_warning("attempt to read from unknown breakpoint "
|
||||||
|
"register %d\n", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_wb_reg(int n, u32 val)
|
||||||
|
{
|
||||||
|
switch (n) {
|
||||||
|
GEN_WRITE_WB_REG_CASES(ARM_OP2_BVR, val);
|
||||||
|
GEN_WRITE_WB_REG_CASES(ARM_OP2_BCR, val);
|
||||||
|
GEN_WRITE_WB_REG_CASES(ARM_OP2_WVR, val);
|
||||||
|
GEN_WRITE_WB_REG_CASES(ARM_OP2_WCR, val);
|
||||||
|
default:
|
||||||
|
pr_warning("attempt to write to unknown breakpoint "
|
||||||
|
"register %d\n", n);
|
||||||
|
}
|
||||||
|
isb();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In order to access the breakpoint/watchpoint control registers,
|
||||||
|
* we must be running in debug monitor mode. Unfortunately, we can
|
||||||
|
* be put into halting debug mode at any time by an external debugger
|
||||||
|
* but there is nothing we can do to prevent that.
|
||||||
|
*/
|
||||||
|
static int enable_monitor_mode(void)
|
||||||
|
{
|
||||||
|
u32 dscr;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ARM_DBG_READ(c1, 0, dscr);
|
||||||
|
|
||||||
|
/* Ensure that halting mode is disabled. */
|
||||||
|
if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled."
|
||||||
|
"Unable to access hardware resources.")) {
|
||||||
|
ret = -EPERM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write to the corresponding DSCR. */
|
||||||
|
switch (debug_arch) {
|
||||||
|
case ARM_DEBUG_ARCH_V6:
|
||||||
|
case ARM_DEBUG_ARCH_V6_1:
|
||||||
|
ARM_DBG_WRITE(c1, 0, (dscr | ARM_DSCR_MDBGEN));
|
||||||
|
break;
|
||||||
|
case ARM_DEBUG_ARCH_V7_ECP14:
|
||||||
|
ARM_DBG_WRITE(c2, 2, (dscr | ARM_DSCR_MDBGEN));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the write made it through. */
|
||||||
|
ARM_DBG_READ(c1, 0, dscr);
|
||||||
|
if (WARN_ONCE(!(dscr & ARM_DSCR_MDBGEN),
|
||||||
|
"failed to enable monitor mode.")) {
|
||||||
|
ret = -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if 8-bit byte-address select is available.
|
||||||
|
* This clobbers WRP 0.
|
||||||
|
*/
|
||||||
|
static u8 get_max_wp_len(void)
|
||||||
|
{
|
||||||
|
u32 ctrl_reg;
|
||||||
|
struct arch_hw_breakpoint_ctrl ctrl;
|
||||||
|
u8 size = 4;
|
||||||
|
|
||||||
|
if (debug_arch < ARM_DEBUG_ARCH_V7_ECP14)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (enable_monitor_mode())
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
memset(&ctrl, 0, sizeof(ctrl));
|
||||||
|
ctrl.len = ARM_BREAKPOINT_LEN_8;
|
||||||
|
ctrl_reg = encode_ctrl_reg(ctrl);
|
||||||
|
|
||||||
|
write_wb_reg(ARM_BASE_WVR, 0);
|
||||||
|
write_wb_reg(ARM_BASE_WCR, ctrl_reg);
|
||||||
|
if ((read_wb_reg(ARM_BASE_WCR) & ctrl_reg) == ctrl_reg)
|
||||||
|
size = 8;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 arch_get_max_wp_len(void)
|
||||||
|
{
|
||||||
|
return max_watchpoint_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handler for reactivating a suspended watchpoint when the single
|
||||||
|
* step `mismatch' breakpoint is triggered.
|
||||||
|
*/
|
||||||
|
static void wp_single_step_handler(struct perf_event *bp, int unused,
|
||||||
|
struct perf_sample_data *data,
|
||||||
|
struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
perf_event_enable(counter_arch_bp(bp)->suspended_wp);
|
||||||
|
unregister_hw_breakpoint(bp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bp_is_single_step(struct perf_event *bp)
|
||||||
|
{
|
||||||
|
return bp->overflow_handler == wp_single_step_handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Install a perf counter breakpoint.
|
||||||
|
*/
|
||||||
|
int arch_install_hw_breakpoint(struct perf_event *bp)
|
||||||
|
{
|
||||||
|
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
|
||||||
|
struct perf_event **slot, **slots;
|
||||||
|
int i, max_slots, ctrl_base, val_base, ret = 0;
|
||||||
|
|
||||||
|
/* Ensure that we are in monitor mode and halting mode is disabled. */
|
||||||
|
ret = enable_monitor_mode();
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
|
||||||
|
/* Breakpoint */
|
||||||
|
ctrl_base = ARM_BASE_BCR;
|
||||||
|
val_base = ARM_BASE_BVR;
|
||||||
|
slots = __get_cpu_var(bp_on_reg);
|
||||||
|
max_slots = core_num_brps - 1;
|
||||||
|
|
||||||
|
if (bp_is_single_step(bp)) {
|
||||||
|
info->ctrl.mismatch = 1;
|
||||||
|
i = max_slots;
|
||||||
|
slots[i] = bp;
|
||||||
|
goto setup;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Watchpoint */
|
||||||
|
ctrl_base = ARM_BASE_WCR;
|
||||||
|
val_base = ARM_BASE_WVR;
|
||||||
|
slots = __get_cpu_var(wp_on_reg);
|
||||||
|
max_slots = core_num_wrps;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < max_slots; ++i) {
|
||||||
|
slot = &slots[i];
|
||||||
|
|
||||||
|
if (!*slot) {
|
||||||
|
*slot = bp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) {
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
setup:
|
||||||
|
/* Setup the address register. */
|
||||||
|
write_wb_reg(val_base + i, info->address);
|
||||||
|
|
||||||
|
/* Setup the control register. */
|
||||||
|
write_wb_reg(ctrl_base + i, encode_ctrl_reg(info->ctrl) | 0x1);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_uninstall_hw_breakpoint(struct perf_event *bp)
|
||||||
|
{
|
||||||
|
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
|
||||||
|
struct perf_event **slot, **slots;
|
||||||
|
int i, max_slots, base;
|
||||||
|
|
||||||
|
if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) {
|
||||||
|
/* Breakpoint */
|
||||||
|
base = ARM_BASE_BCR;
|
||||||
|
slots = __get_cpu_var(bp_on_reg);
|
||||||
|
max_slots = core_num_brps - 1;
|
||||||
|
|
||||||
|
if (bp_is_single_step(bp)) {
|
||||||
|
i = max_slots;
|
||||||
|
slots[i] = NULL;
|
||||||
|
goto reset;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Watchpoint */
|
||||||
|
base = ARM_BASE_WCR;
|
||||||
|
slots = __get_cpu_var(wp_on_reg);
|
||||||
|
max_slots = core_num_wrps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the breakpoint. */
|
||||||
|
for (i = 0; i < max_slots; ++i) {
|
||||||
|
slot = &slots[i];
|
||||||
|
|
||||||
|
if (*slot == bp) {
|
||||||
|
*slot = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
reset:
|
||||||
|
/* Reset the control register. */
|
||||||
|
write_wb_reg(base + i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_hbp_len(u8 hbp_len)
|
||||||
|
{
|
||||||
|
unsigned int len_in_bytes = 0;
|
||||||
|
|
||||||
|
switch (hbp_len) {
|
||||||
|
case ARM_BREAKPOINT_LEN_1:
|
||||||
|
len_in_bytes = 1;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_LEN_2:
|
||||||
|
len_in_bytes = 2;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_LEN_4:
|
||||||
|
len_in_bytes = 4;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_LEN_8:
|
||||||
|
len_in_bytes = 8;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len_in_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether bp virtual address is in kernel space.
|
||||||
|
*/
|
||||||
|
int arch_check_bp_in_kernelspace(struct perf_event *bp)
|
||||||
|
{
|
||||||
|
unsigned int len;
|
||||||
|
unsigned long va;
|
||||||
|
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
|
||||||
|
|
||||||
|
va = info->address;
|
||||||
|
len = get_hbp_len(info->ctrl.len);
|
||||||
|
|
||||||
|
return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract generic type and length encodings from an arch_hw_breakpoint_ctrl.
|
||||||
|
* Hopefully this will disappear when ptrace can bypass the conversion
|
||||||
|
* to generic breakpoint descriptions.
|
||||||
|
*/
|
||||||
|
int arch_bp_generic_fields(struct arch_hw_breakpoint_ctrl ctrl,
|
||||||
|
int *gen_len, int *gen_type)
|
||||||
|
{
|
||||||
|
/* Type */
|
||||||
|
switch (ctrl.type) {
|
||||||
|
case ARM_BREAKPOINT_EXECUTE:
|
||||||
|
*gen_type = HW_BREAKPOINT_X;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_LOAD:
|
||||||
|
*gen_type = HW_BREAKPOINT_R;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_STORE:
|
||||||
|
*gen_type = HW_BREAKPOINT_W;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE:
|
||||||
|
*gen_type = HW_BREAKPOINT_RW;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Len */
|
||||||
|
switch (ctrl.len) {
|
||||||
|
case ARM_BREAKPOINT_LEN_1:
|
||||||
|
*gen_len = HW_BREAKPOINT_LEN_1;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_LEN_2:
|
||||||
|
*gen_len = HW_BREAKPOINT_LEN_2;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_LEN_4:
|
||||||
|
*gen_len = HW_BREAKPOINT_LEN_4;
|
||||||
|
break;
|
||||||
|
case ARM_BREAKPOINT_LEN_8:
|
||||||
|
*gen_len = HW_BREAKPOINT_LEN_8;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Construct an arch_hw_breakpoint from a perf_event.
|
||||||
|
*/
|
||||||
|
static int arch_build_bp_info(struct perf_event *bp)
|
||||||
|
{
|
||||||
|
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
|
||||||
|
|
||||||
|
/* Type */
|
||||||
|
switch (bp->attr.bp_type) {
|
||||||
|
case HW_BREAKPOINT_X:
|
||||||
|
info->ctrl.type = ARM_BREAKPOINT_EXECUTE;
|
||||||
|
break;
|
||||||
|
case HW_BREAKPOINT_R:
|
||||||
|
info->ctrl.type = ARM_BREAKPOINT_LOAD;
|
||||||
|
break;
|
||||||
|
case HW_BREAKPOINT_W:
|
||||||
|
info->ctrl.type = ARM_BREAKPOINT_STORE;
|
||||||
|
break;
|
||||||
|
case HW_BREAKPOINT_RW:
|
||||||
|
info->ctrl.type = ARM_BREAKPOINT_LOAD | ARM_BREAKPOINT_STORE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Len */
|
||||||
|
switch (bp->attr.bp_len) {
|
||||||
|
case HW_BREAKPOINT_LEN_1:
|
||||||
|
info->ctrl.len = ARM_BREAKPOINT_LEN_1;
|
||||||
|
break;
|
||||||
|
case HW_BREAKPOINT_LEN_2:
|
||||||
|
info->ctrl.len = ARM_BREAKPOINT_LEN_2;
|
||||||
|
break;
|
||||||
|
case HW_BREAKPOINT_LEN_4:
|
||||||
|
info->ctrl.len = ARM_BREAKPOINT_LEN_4;
|
||||||
|
break;
|
||||||
|
case HW_BREAKPOINT_LEN_8:
|
||||||
|
info->ctrl.len = ARM_BREAKPOINT_LEN_8;
|
||||||
|
if ((info->ctrl.type != ARM_BREAKPOINT_EXECUTE)
|
||||||
|
&& max_watchpoint_len >= 8)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Address */
|
||||||
|
info->address = bp->attr.bp_addr;
|
||||||
|
|
||||||
|
/* Privilege */
|
||||||
|
info->ctrl.privilege = ARM_BREAKPOINT_USER;
|
||||||
|
if (arch_check_bp_in_kernelspace(bp) && !bp_is_single_step(bp))
|
||||||
|
info->ctrl.privilege |= ARM_BREAKPOINT_PRIV;
|
||||||
|
|
||||||
|
/* Enabled? */
|
||||||
|
info->ctrl.enabled = !bp->attr.disabled;
|
||||||
|
|
||||||
|
/* Mismatch */
|
||||||
|
info->ctrl.mismatch = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate the arch-specific HW Breakpoint register settings.
|
||||||
|
*/
|
||||||
|
int arch_validate_hwbkpt_settings(struct perf_event *bp)
|
||||||
|
{
|
||||||
|
struct arch_hw_breakpoint *info = counter_arch_bp(bp);
|
||||||
|
int ret = 0;
|
||||||
|
u32 bytelen, max_len, offset, alignment_mask = 0x3;
|
||||||
|
|
||||||
|
/* Build the arch_hw_breakpoint. */
|
||||||
|
ret = arch_build_bp_info(bp);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Check address alignment. */
|
||||||
|
if (info->ctrl.len == ARM_BREAKPOINT_LEN_8)
|
||||||
|
alignment_mask = 0x7;
|
||||||
|
if (info->address & alignment_mask) {
|
||||||
|
/*
|
||||||
|
* Try to fix the alignment. This may result in a length
|
||||||
|
* that is too large, so we must check for that.
|
||||||
|
*/
|
||||||
|
bytelen = get_hbp_len(info->ctrl.len);
|
||||||
|
max_len = info->ctrl.type == ARM_BREAKPOINT_EXECUTE ? 4 :
|
||||||
|
max_watchpoint_len;
|
||||||
|
|
||||||
|
if (max_len >= 8)
|
||||||
|
offset = info->address & 0x7;
|
||||||
|
else
|
||||||
|
offset = info->address & 0x3;
|
||||||
|
|
||||||
|
if (bytelen > (1 << ((max_len - (offset + 1)) >> 1))) {
|
||||||
|
ret = -EFBIG;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->ctrl.len <<= offset;
|
||||||
|
info->address &= ~offset;
|
||||||
|
|
||||||
|
pr_debug("breakpoint alignment fixup: length = 0x%x, "
|
||||||
|
"address = 0x%x\n", info->ctrl.len, info->address);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Currently we rely on an overflow handler to take
|
||||||
|
* care of single-stepping the breakpoint when it fires.
|
||||||
|
* In the case of userspace breakpoints on a core with V7 debug,
|
||||||
|
* we can use the mismatch feature as a poor-man's hardware single-step.
|
||||||
|
*/
|
||||||
|
if (WARN_ONCE(!bp->overflow_handler &&
|
||||||
|
(arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_bps()),
|
||||||
|
"overflow handler required but none found")) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_mismatch_flag(int idx, int flag)
|
||||||
|
{
|
||||||
|
struct perf_event *bp = __get_cpu_var(bp_on_reg[idx]);
|
||||||
|
struct arch_hw_breakpoint *info;
|
||||||
|
|
||||||
|
if (bp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
info = counter_arch_bp(bp);
|
||||||
|
|
||||||
|
/* Update the mismatch field to enter/exit `single-step' mode */
|
||||||
|
if (!bp->overflow_handler && info->ctrl.mismatch != flag) {
|
||||||
|
info->ctrl.mismatch = flag;
|
||||||
|
write_wb_reg(ARM_BASE_BCR + idx, encode_ctrl_reg(info->ctrl) | 0x1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void watchpoint_handler(unsigned long unknown, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct perf_event *bp, **slots = __get_cpu_var(wp_on_reg);
|
||||||
|
struct arch_hw_breakpoint *info;
|
||||||
|
struct perf_event_attr attr;
|
||||||
|
|
||||||
|
/* Without a disassembler, we can only handle 1 watchpoint. */
|
||||||
|
BUG_ON(core_num_wrps > 1);
|
||||||
|
|
||||||
|
hw_breakpoint_init(&attr);
|
||||||
|
attr.bp_addr = regs->ARM_pc & ~0x3;
|
||||||
|
attr.bp_len = HW_BREAKPOINT_LEN_4;
|
||||||
|
attr.bp_type = HW_BREAKPOINT_X;
|
||||||
|
|
||||||
|
for (i = 0; i < core_num_wrps; ++i) {
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
if (slots[i] == NULL) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The DFAR is an unknown value. Since we only allow a
|
||||||
|
* single watchpoint, we can set the trigger to the lowest
|
||||||
|
* possible faulting address.
|
||||||
|
*/
|
||||||
|
info = counter_arch_bp(slots[i]);
|
||||||
|
info->trigger = slots[i]->attr.bp_addr;
|
||||||
|
pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
|
||||||
|
perf_bp_event(slots[i], regs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no overflow handler is present, insert a temporary
|
||||||
|
* mismatch breakpoint so we can single-step over the
|
||||||
|
* watchpoint trigger.
|
||||||
|
*/
|
||||||
|
if (!slots[i]->overflow_handler) {
|
||||||
|
bp = register_user_hw_breakpoint(&attr,
|
||||||
|
wp_single_step_handler,
|
||||||
|
current);
|
||||||
|
counter_arch_bp(bp)->suspended_wp = slots[i];
|
||||||
|
perf_event_disable(slots[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int mismatch;
|
||||||
|
u32 ctrl_reg, val, addr;
|
||||||
|
struct perf_event *bp, **slots = __get_cpu_var(bp_on_reg);
|
||||||
|
struct arch_hw_breakpoint *info;
|
||||||
|
struct arch_hw_breakpoint_ctrl ctrl;
|
||||||
|
|
||||||
|
/* The exception entry code places the amended lr in the PC. */
|
||||||
|
addr = regs->ARM_pc;
|
||||||
|
|
||||||
|
for (i = 0; i < core_num_brps; ++i) {
|
||||||
|
rcu_read_lock();
|
||||||
|
|
||||||
|
bp = slots[i];
|
||||||
|
|
||||||
|
if (bp == NULL) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
mismatch = 0;
|
||||||
|
|
||||||
|
/* Check if the breakpoint value matches. */
|
||||||
|
val = read_wb_reg(ARM_BASE_BVR + i);
|
||||||
|
if (val != (addr & ~0x3))
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
/* Possible match, check the byte address select to confirm. */
|
||||||
|
ctrl_reg = read_wb_reg(ARM_BASE_BCR + i);
|
||||||
|
decode_ctrl_reg(ctrl_reg, &ctrl);
|
||||||
|
if ((1 << (addr & 0x3)) & ctrl.len) {
|
||||||
|
mismatch = 1;
|
||||||
|
info = counter_arch_bp(bp);
|
||||||
|
info->trigger = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
if ((mismatch && !info->ctrl.mismatch) || bp_is_single_step(bp)) {
|
||||||
|
pr_debug("breakpoint fired: address = 0x%x\n", addr);
|
||||||
|
perf_bp_event(bp, regs);
|
||||||
|
}
|
||||||
|
|
||||||
|
update_mismatch_flag(i, mismatch);
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called from either the Data Abort Handler [watchpoint] or the
|
||||||
|
* Prefetch Abort Handler [breakpoint].
|
||||||
|
*/
|
||||||
|
static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr,
|
||||||
|
struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
int ret = 1; /* Unhandled fault. */
|
||||||
|
u32 dscr;
|
||||||
|
|
||||||
|
/* We only handle watchpoints and hardware breakpoints. */
|
||||||
|
ARM_DBG_READ(c1, 0, dscr);
|
||||||
|
|
||||||
|
/* Perform perf callbacks. */
|
||||||
|
switch (ARM_DSCR_MOE(dscr)) {
|
||||||
|
case ARM_ENTRY_BREAKPOINT:
|
||||||
|
breakpoint_handler(addr, regs);
|
||||||
|
break;
|
||||||
|
case ARM_ENTRY_ASYNC_WATCHPOINT:
|
||||||
|
WARN_ON("Asynchronous watchpoint exception taken. "
|
||||||
|
"Debugging results may be unreliable");
|
||||||
|
case ARM_ENTRY_SYNC_WATCHPOINT:
|
||||||
|
watchpoint_handler(addr, regs);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One-time initialisation.
|
||||||
|
*/
|
||||||
|
static void __init reset_ctrl_regs(void *unused)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (enable_monitor_mode())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < core_num_brps; ++i) {
|
||||||
|
write_wb_reg(ARM_BASE_BCR + i, 0UL);
|
||||||
|
write_wb_reg(ARM_BASE_BVR + i, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < core_num_wrps; ++i) {
|
||||||
|
write_wb_reg(ARM_BASE_WCR + i, 0UL);
|
||||||
|
write_wb_reg(ARM_BASE_WVR + i, 0UL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init arch_hw_breakpoint_init(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
u32 dscr;
|
||||||
|
|
||||||
|
debug_arch = get_debug_arch();
|
||||||
|
|
||||||
|
if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) {
|
||||||
|
pr_info("debug architecture 0x%x unsupported.\n", debug_arch);
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine how many BRPs/WRPs are available. */
|
||||||
|
core_num_brps = get_num_brps();
|
||||||
|
core_num_wrps = get_num_wrps();
|
||||||
|
|
||||||
|
pr_info("found %d breakpoint and %d watchpoint registers.\n",
|
||||||
|
core_num_brps, core_num_wrps);
|
||||||
|
|
||||||
|
if (core_has_mismatch_bps())
|
||||||
|
pr_info("1 breakpoint reserved for watchpoint single-step.\n");
|
||||||
|
|
||||||
|
ARM_DBG_READ(c1, 0, dscr);
|
||||||
|
if (dscr & ARM_DSCR_HDBGEN) {
|
||||||
|
pr_warning("halting debug mode enabled. Assuming maximum "
|
||||||
|
"watchpoint size of 4 bytes.");
|
||||||
|
} else {
|
||||||
|
/* Work out the maximum supported watchpoint length. */
|
||||||
|
max_watchpoint_len = get_max_wp_len();
|
||||||
|
pr_info("maximum watchpoint size is %u bytes.\n",
|
||||||
|
max_watchpoint_len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset the breakpoint resources. We assume that a halting
|
||||||
|
* debugger will leave the world in a nice state for us.
|
||||||
|
*/
|
||||||
|
smp_call_function(reset_ctrl_regs, NULL, 1);
|
||||||
|
reset_ctrl_regs(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register debug fault handler. */
|
||||||
|
hook_fault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
|
||||||
|
"watchpoint debug exception");
|
||||||
|
hook_ifault_code(2, hw_breakpoint_pending, SIGTRAP, TRAP_HWBKPT,
|
||||||
|
"breakpoint debug exception");
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
arch_initcall(arch_hw_breakpoint_init);
|
||||||
|
|
||||||
|
void hw_breakpoint_pmu_read(struct perf_event *bp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dummy function to register with die_notifier.
|
||||||
|
*/
|
||||||
|
int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
|
||||||
|
unsigned long val, void *data)
|
||||||
|
{
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
}
|
|
@ -69,20 +69,31 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_ARM_UNWIND
|
#ifdef CONFIG_ARM_UNWIND
|
||||||
Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
|
Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
|
||||||
|
struct arm_unwind_mapping *maps = mod->arch.map;
|
||||||
|
|
||||||
for (s = sechdrs; s < sechdrs_end; s++) {
|
for (s = sechdrs; s < sechdrs_end; s++) {
|
||||||
if (strcmp(".ARM.exidx.init.text", secstrings + s->sh_name) == 0)
|
char const *secname = secstrings + s->sh_name;
|
||||||
mod->arch.unw_sec_init = s;
|
|
||||||
else if (strcmp(".ARM.exidx.devinit.text", secstrings + s->sh_name) == 0)
|
if (strcmp(".ARM.exidx.init.text", secname) == 0)
|
||||||
mod->arch.unw_sec_devinit = s;
|
maps[ARM_SEC_INIT].unw_sec = s;
|
||||||
else if (strcmp(".ARM.exidx", secstrings + s->sh_name) == 0)
|
else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
|
||||||
mod->arch.unw_sec_core = s;
|
maps[ARM_SEC_DEVINIT].unw_sec = s;
|
||||||
else if (strcmp(".init.text", secstrings + s->sh_name) == 0)
|
else if (strcmp(".ARM.exidx", secname) == 0)
|
||||||
mod->arch.sec_init_text = s;
|
maps[ARM_SEC_CORE].unw_sec = s;
|
||||||
else if (strcmp(".devinit.text", secstrings + s->sh_name) == 0)
|
else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
|
||||||
mod->arch.sec_devinit_text = s;
|
maps[ARM_SEC_EXIT].unw_sec = s;
|
||||||
else if (strcmp(".text", secstrings + s->sh_name) == 0)
|
else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
|
||||||
mod->arch.sec_core_text = s;
|
maps[ARM_SEC_DEVEXIT].unw_sec = s;
|
||||||
|
else if (strcmp(".init.text", secname) == 0)
|
||||||
|
maps[ARM_SEC_INIT].sec_text = s;
|
||||||
|
else if (strcmp(".devinit.text", secname) == 0)
|
||||||
|
maps[ARM_SEC_DEVINIT].sec_text = s;
|
||||||
|
else if (strcmp(".text", secname) == 0)
|
||||||
|
maps[ARM_SEC_CORE].sec_text = s;
|
||||||
|
else if (strcmp(".exit.text", secname) == 0)
|
||||||
|
maps[ARM_SEC_EXIT].sec_text = s;
|
||||||
|
else if (strcmp(".devexit.text", secname) == 0)
|
||||||
|
maps[ARM_SEC_DEVEXIT].sec_text = s;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -292,31 +303,22 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
|
||||||
#ifdef CONFIG_ARM_UNWIND
|
#ifdef CONFIG_ARM_UNWIND
|
||||||
static void register_unwind_tables(struct module *mod)
|
static void register_unwind_tables(struct module *mod)
|
||||||
{
|
{
|
||||||
if (mod->arch.unw_sec_init && mod->arch.sec_init_text)
|
int i;
|
||||||
mod->arch.unwind_init =
|
for (i = 0; i < ARM_SEC_MAX; ++i) {
|
||||||
unwind_table_add(mod->arch.unw_sec_init->sh_addr,
|
struct arm_unwind_mapping *map = &mod->arch.map[i];
|
||||||
mod->arch.unw_sec_init->sh_size,
|
if (map->unw_sec && map->sec_text)
|
||||||
mod->arch.sec_init_text->sh_addr,
|
map->unwind = unwind_table_add(map->unw_sec->sh_addr,
|
||||||
mod->arch.sec_init_text->sh_size);
|
map->unw_sec->sh_size,
|
||||||
if (mod->arch.unw_sec_devinit && mod->arch.sec_devinit_text)
|
map->sec_text->sh_addr,
|
||||||
mod->arch.unwind_devinit =
|
map->sec_text->sh_size);
|
||||||
unwind_table_add(mod->arch.unw_sec_devinit->sh_addr,
|
}
|
||||||
mod->arch.unw_sec_devinit->sh_size,
|
|
||||||
mod->arch.sec_devinit_text->sh_addr,
|
|
||||||
mod->arch.sec_devinit_text->sh_size);
|
|
||||||
if (mod->arch.unw_sec_core && mod->arch.sec_core_text)
|
|
||||||
mod->arch.unwind_core =
|
|
||||||
unwind_table_add(mod->arch.unw_sec_core->sh_addr,
|
|
||||||
mod->arch.unw_sec_core->sh_size,
|
|
||||||
mod->arch.sec_core_text->sh_addr,
|
|
||||||
mod->arch.sec_core_text->sh_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unregister_unwind_tables(struct module *mod)
|
static void unregister_unwind_tables(struct module *mod)
|
||||||
{
|
{
|
||||||
unwind_table_del(mod->arch.unwind_init);
|
int i = ARM_SEC_MAX;
|
||||||
unwind_table_del(mod->arch.unwind_devinit);
|
while (--i >= 0)
|
||||||
unwind_table_del(mod->arch.unwind_core);
|
unwind_table_del(mod->arch.map[i].unwind);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void register_unwind_tables(struct module *mod) { }
|
static inline void register_unwind_tables(struct module *mod) { }
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <linux/utsname.h>
|
#include <linux/utsname.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
|
#include <linux/hw_breakpoint.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/leds.h>
|
#include <asm/leds.h>
|
||||||
|
@ -135,6 +136,25 @@ EXPORT_SYMBOL(pm_power_off);
|
||||||
void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;
|
void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart;
|
||||||
EXPORT_SYMBOL_GPL(arm_pm_restart);
|
EXPORT_SYMBOL_GPL(arm_pm_restart);
|
||||||
|
|
||||||
|
static void do_nothing(void *unused)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cpu_idle_wait - Used to ensure that all the CPUs discard old value of
|
||||||
|
* pm_idle and update to new pm_idle value. Required while changing pm_idle
|
||||||
|
* handler on SMP systems.
|
||||||
|
*
|
||||||
|
* Caller must have changed pm_idle to the new value before the call. Old
|
||||||
|
* pm_idle value will not be used by any CPU after the return of this function.
|
||||||
|
*/
|
||||||
|
void cpu_idle_wait(void)
|
||||||
|
{
|
||||||
|
smp_mb();
|
||||||
|
/* kick all the CPUs so that they exit out of pm_idle */
|
||||||
|
smp_call_function(do_nothing, NULL, 1);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(cpu_idle_wait);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is our default idle handler. We need to disable
|
* This is our default idle handler. We need to disable
|
||||||
|
@ -317,6 +337,8 @@ void flush_thread(void)
|
||||||
struct thread_info *thread = current_thread_info();
|
struct thread_info *thread = current_thread_info();
|
||||||
struct task_struct *tsk = current;
|
struct task_struct *tsk = current;
|
||||||
|
|
||||||
|
flush_ptrace_hw_breakpoint(tsk);
|
||||||
|
|
||||||
memset(thread->used_cp, 0, sizeof(thread->used_cp));
|
memset(thread->used_cp, 0, sizeof(thread->used_cp));
|
||||||
memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
|
memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
|
||||||
memset(&thread->fpstate, 0, sizeof(union fp_state));
|
memset(&thread->fpstate, 0, sizeof(union fp_state));
|
||||||
|
@ -345,6 +367,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
|
||||||
thread->cpu_context.sp = (unsigned long)childregs;
|
thread->cpu_context.sp = (unsigned long)childregs;
|
||||||
thread->cpu_context.pc = (unsigned long)ret_from_fork;
|
thread->cpu_context.pc = (unsigned long)ret_from_fork;
|
||||||
|
|
||||||
|
clear_ptrace_hw_breakpoint(p);
|
||||||
|
|
||||||
if (clone_flags & CLONE_SETTLS)
|
if (clone_flags & CLONE_SETTLS)
|
||||||
thread->tp_value = regs->ARM_r3;
|
thread->tp_value = regs->ARM_r3;
|
||||||
|
|
||||||
|
@ -458,3 +482,24 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
|
||||||
unsigned long range_end = mm->brk + 0x02000000;
|
unsigned long range_end = mm->brk + 0x02000000;
|
||||||
return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
|
return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The vectors page is always readable from user space for the
|
||||||
|
* atomic helpers and the signal restart code. Let's declare a mapping
|
||||||
|
* for it so it is visible through ptrace and /proc/<pid>/mem.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int vectors_user_mapping(void)
|
||||||
|
{
|
||||||
|
struct mm_struct *mm = current->mm;
|
||||||
|
return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
|
||||||
|
VM_READ | VM_EXEC |
|
||||||
|
VM_MAYREAD | VM_MAYEXEC |
|
||||||
|
VM_ALWAYSDUMP | VM_RESERVED,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *arch_vma_name(struct vm_area_struct *vma)
|
||||||
|
{
|
||||||
|
return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/signal.h>
|
#include <linux/signal.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/perf_event.h>
|
||||||
|
#include <linux/hw_breakpoint.h>
|
||||||
|
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
@ -847,6 +849,232 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||||
|
/*
|
||||||
|
* Convert a virtual register number into an index for a thread_info
|
||||||
|
* breakpoint array. Breakpoints are identified using positive numbers
|
||||||
|
* whilst watchpoints are negative. The registers are laid out as pairs
|
||||||
|
* of (address, control), each pair mapping to a unique hw_breakpoint struct.
|
||||||
|
* Register 0 is reserved for describing resource information.
|
||||||
|
*/
|
||||||
|
static int ptrace_hbp_num_to_idx(long num)
|
||||||
|
{
|
||||||
|
if (num < 0)
|
||||||
|
num = (ARM_MAX_BRP << 1) - num;
|
||||||
|
return (num - 1) >> 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the virtual register number for the address of the
|
||||||
|
* breakpoint at index idx.
|
||||||
|
*/
|
||||||
|
static long ptrace_hbp_idx_to_num(int idx)
|
||||||
|
{
|
||||||
|
long mid = ARM_MAX_BRP << 1;
|
||||||
|
long num = (idx << 1) + 1;
|
||||||
|
return num > mid ? mid - num : num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle hitting a HW-breakpoint.
|
||||||
|
*/
|
||||||
|
static void ptrace_hbptriggered(struct perf_event *bp, int unused,
|
||||||
|
struct perf_sample_data *data,
|
||||||
|
struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
|
||||||
|
long num;
|
||||||
|
int i;
|
||||||
|
siginfo_t info;
|
||||||
|
|
||||||
|
for (i = 0; i < ARM_MAX_HBP_SLOTS; ++i)
|
||||||
|
if (current->thread.debug.hbp[i] == bp)
|
||||||
|
break;
|
||||||
|
|
||||||
|
num = (i == ARM_MAX_HBP_SLOTS) ? 0 : ptrace_hbp_idx_to_num(i);
|
||||||
|
|
||||||
|
info.si_signo = SIGTRAP;
|
||||||
|
info.si_errno = (int)num;
|
||||||
|
info.si_code = TRAP_HWBKPT;
|
||||||
|
info.si_addr = (void __user *)(bkpt->trigger);
|
||||||
|
|
||||||
|
force_sig_info(SIGTRAP, &info, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set ptrace breakpoint pointers to zero for this task.
|
||||||
|
* This is required in order to prevent child processes from unregistering
|
||||||
|
* breakpoints held by their parent.
|
||||||
|
*/
|
||||||
|
void clear_ptrace_hw_breakpoint(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
memset(tsk->thread.debug.hbp, 0, sizeof(tsk->thread.debug.hbp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unregister breakpoints from this task and reset the pointers in
|
||||||
|
* the thread_struct.
|
||||||
|
*/
|
||||||
|
void flush_ptrace_hw_breakpoint(struct task_struct *tsk)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct thread_struct *t = &tsk->thread;
|
||||||
|
|
||||||
|
for (i = 0; i < ARM_MAX_HBP_SLOTS; i++) {
|
||||||
|
if (t->debug.hbp[i]) {
|
||||||
|
unregister_hw_breakpoint(t->debug.hbp[i]);
|
||||||
|
t->debug.hbp[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 ptrace_get_hbp_resource_info(void)
|
||||||
|
{
|
||||||
|
u8 num_brps, num_wrps, debug_arch, wp_len;
|
||||||
|
u32 reg = 0;
|
||||||
|
|
||||||
|
num_brps = hw_breakpoint_slots(TYPE_INST);
|
||||||
|
num_wrps = hw_breakpoint_slots(TYPE_DATA);
|
||||||
|
debug_arch = arch_get_debug_arch();
|
||||||
|
wp_len = arch_get_max_wp_len();
|
||||||
|
|
||||||
|
reg |= debug_arch;
|
||||||
|
reg <<= 8;
|
||||||
|
reg |= wp_len;
|
||||||
|
reg <<= 8;
|
||||||
|
reg |= num_wrps;
|
||||||
|
reg <<= 8;
|
||||||
|
reg |= num_brps;
|
||||||
|
|
||||||
|
return reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
|
||||||
|
{
|
||||||
|
struct perf_event_attr attr;
|
||||||
|
|
||||||
|
ptrace_breakpoint_init(&attr);
|
||||||
|
|
||||||
|
/* Initialise fields to sane defaults. */
|
||||||
|
attr.bp_addr = 0;
|
||||||
|
attr.bp_len = HW_BREAKPOINT_LEN_4;
|
||||||
|
attr.bp_type = type;
|
||||||
|
attr.disabled = 1;
|
||||||
|
|
||||||
|
return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, tsk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ptrace_gethbpregs(struct task_struct *tsk, long num,
|
||||||
|
unsigned long __user *data)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
int idx, ret = 0;
|
||||||
|
struct perf_event *bp;
|
||||||
|
struct arch_hw_breakpoint_ctrl arch_ctrl;
|
||||||
|
|
||||||
|
if (num == 0) {
|
||||||
|
reg = ptrace_get_hbp_resource_info();
|
||||||
|
} else {
|
||||||
|
idx = ptrace_hbp_num_to_idx(num);
|
||||||
|
if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bp = tsk->thread.debug.hbp[idx];
|
||||||
|
if (!bp) {
|
||||||
|
reg = 0;
|
||||||
|
goto put;
|
||||||
|
}
|
||||||
|
|
||||||
|
arch_ctrl = counter_arch_bp(bp)->ctrl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fix up the len because we may have adjusted it
|
||||||
|
* to compensate for an unaligned address.
|
||||||
|
*/
|
||||||
|
while (!(arch_ctrl.len & 0x1))
|
||||||
|
arch_ctrl.len >>= 1;
|
||||||
|
|
||||||
|
if (idx & 0x1)
|
||||||
|
reg = encode_ctrl_reg(arch_ctrl);
|
||||||
|
else
|
||||||
|
reg = bp->attr.bp_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
put:
|
||||||
|
if (put_user(reg, data))
|
||||||
|
ret = -EFAULT;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ptrace_sethbpregs(struct task_struct *tsk, long num,
|
||||||
|
unsigned long __user *data)
|
||||||
|
{
|
||||||
|
int idx, gen_len, gen_type, implied_type, ret = 0;
|
||||||
|
u32 user_val;
|
||||||
|
struct perf_event *bp;
|
||||||
|
struct arch_hw_breakpoint_ctrl ctrl;
|
||||||
|
struct perf_event_attr attr;
|
||||||
|
|
||||||
|
if (num == 0)
|
||||||
|
goto out;
|
||||||
|
else if (num < 0)
|
||||||
|
implied_type = HW_BREAKPOINT_RW;
|
||||||
|
else
|
||||||
|
implied_type = HW_BREAKPOINT_X;
|
||||||
|
|
||||||
|
idx = ptrace_hbp_num_to_idx(num);
|
||||||
|
if (idx < 0 || idx >= ARM_MAX_HBP_SLOTS) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_user(user_val, data)) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bp = tsk->thread.debug.hbp[idx];
|
||||||
|
if (!bp) {
|
||||||
|
bp = ptrace_hbp_create(tsk, implied_type);
|
||||||
|
if (IS_ERR(bp)) {
|
||||||
|
ret = PTR_ERR(bp);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
tsk->thread.debug.hbp[idx] = bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr = bp->attr;
|
||||||
|
|
||||||
|
if (num & 0x1) {
|
||||||
|
/* Address */
|
||||||
|
attr.bp_addr = user_val;
|
||||||
|
} else {
|
||||||
|
/* Control */
|
||||||
|
decode_ctrl_reg(user_val, &ctrl);
|
||||||
|
ret = arch_bp_generic_fields(ctrl, &gen_len, &gen_type);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if ((gen_type & implied_type) != gen_type) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.bp_len = gen_len;
|
||||||
|
attr.bp_type = gen_type;
|
||||||
|
attr.disabled = !ctrl.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = modify_user_hw_breakpoint(bp, &attr);
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -916,6 +1144,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||||
|
case PTRACE_GETHBPREGS:
|
||||||
|
ret = ptrace_gethbpregs(child, addr,
|
||||||
|
(unsigned long __user *)data);
|
||||||
|
break;
|
||||||
|
case PTRACE_SETHBPREGS:
|
||||||
|
ret = ptrace_sethbpregs(child, addr,
|
||||||
|
(unsigned long __user *)data);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = ptrace_request(child, request, addr, data);
|
ret = ptrace_request(child, request, addr, data);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <asm/procinfo.h>
|
#include <asm/procinfo.h>
|
||||||
#include <asm/sections.h>
|
#include <asm/sections.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
#include <asm/smp_plat.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/cachetype.h>
|
#include <asm/cachetype.h>
|
||||||
|
@ -238,6 +239,35 @@ int cpu_architecture(void)
|
||||||
return cpu_arch;
|
return cpu_arch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cpu_has_aliasing_icache(unsigned int arch)
|
||||||
|
{
|
||||||
|
int aliasing_icache;
|
||||||
|
unsigned int id_reg, num_sets, line_size;
|
||||||
|
|
||||||
|
/* arch specifies the register format */
|
||||||
|
switch (arch) {
|
||||||
|
case CPU_ARCH_ARMv7:
|
||||||
|
asm("mcr p15, 2, %0, c0, c0, 0 @ set CSSELR"
|
||||||
|
: /* No output operands */
|
||||||
|
: "r" (1));
|
||||||
|
isb();
|
||||||
|
asm("mrc p15, 1, %0, c0, c0, 0 @ read CCSIDR"
|
||||||
|
: "=r" (id_reg));
|
||||||
|
line_size = 4 << ((id_reg & 0x7) + 2);
|
||||||
|
num_sets = ((id_reg >> 13) & 0x7fff) + 1;
|
||||||
|
aliasing_icache = (line_size * num_sets) > PAGE_SIZE;
|
||||||
|
break;
|
||||||
|
case CPU_ARCH_ARMv6:
|
||||||
|
aliasing_icache = read_cpuid_cachetype() & (1 << 11);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* I-cache aliases will be handled by D-cache aliasing code */
|
||||||
|
aliasing_icache = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return aliasing_icache;
|
||||||
|
}
|
||||||
|
|
||||||
static void __init cacheid_init(void)
|
static void __init cacheid_init(void)
|
||||||
{
|
{
|
||||||
unsigned int cachetype = read_cpuid_cachetype();
|
unsigned int cachetype = read_cpuid_cachetype();
|
||||||
|
@ -249,10 +279,15 @@ static void __init cacheid_init(void)
|
||||||
cacheid = CACHEID_VIPT_NONALIASING;
|
cacheid = CACHEID_VIPT_NONALIASING;
|
||||||
if ((cachetype & (3 << 14)) == 1 << 14)
|
if ((cachetype & (3 << 14)) == 1 << 14)
|
||||||
cacheid |= CACHEID_ASID_TAGGED;
|
cacheid |= CACHEID_ASID_TAGGED;
|
||||||
} else if (cachetype & (1 << 23))
|
else if (cpu_has_aliasing_icache(CPU_ARCH_ARMv7))
|
||||||
|
cacheid |= CACHEID_VIPT_I_ALIASING;
|
||||||
|
} else if (cachetype & (1 << 23)) {
|
||||||
cacheid = CACHEID_VIPT_ALIASING;
|
cacheid = CACHEID_VIPT_ALIASING;
|
||||||
else
|
} else {
|
||||||
cacheid = CACHEID_VIPT_NONALIASING;
|
cacheid = CACHEID_VIPT_NONALIASING;
|
||||||
|
if (cpu_has_aliasing_icache(CPU_ARCH_ARMv6))
|
||||||
|
cacheid |= CACHEID_VIPT_I_ALIASING;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cacheid = CACHEID_VIVT;
|
cacheid = CACHEID_VIVT;
|
||||||
}
|
}
|
||||||
|
@ -263,7 +298,7 @@ static void __init cacheid_init(void)
|
||||||
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
|
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
|
||||||
cache_is_vivt() ? "VIVT" :
|
cache_is_vivt() ? "VIVT" :
|
||||||
icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
|
icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
|
||||||
cache_is_vipt_aliasing() ? "VIPT aliasing" :
|
icache_is_vipt_aliasing() ? "VIPT aliasing" :
|
||||||
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
|
cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +525,7 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
|
||||||
|
|
||||||
kernel_code.start = virt_to_phys(_text);
|
kernel_code.start = virt_to_phys(_text);
|
||||||
kernel_code.end = virt_to_phys(_etext - 1);
|
kernel_code.end = virt_to_phys(_etext - 1);
|
||||||
kernel_data.start = virt_to_phys(_data);
|
kernel_data.start = virt_to_phys(_sdata);
|
||||||
kernel_data.end = virt_to_phys(_end - 1);
|
kernel_data.end = virt_to_phys(_end - 1);
|
||||||
|
|
||||||
for (i = 0; i < mi->nr_banks; i++) {
|
for (i = 0; i < mi->nr_banks; i++) {
|
||||||
|
@ -825,7 +860,8 @@ void __init setup_arch(char **cmdline_p)
|
||||||
request_standard_resources(&meminfo, mdesc);
|
request_standard_resources(&meminfo, mdesc);
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
smp_init_cpus();
|
if (is_smp())
|
||||||
|
smp_init_cpus();
|
||||||
#endif
|
#endif
|
||||||
reserve_crashkernel();
|
reserve_crashkernel();
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
#include <asm/sections.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/localtimer.h>
|
#include <asm/localtimer.h>
|
||||||
|
@ -67,12 +68,47 @@ enum ipi_msg_type {
|
||||||
IPI_CPU_STOP,
|
IPI_CPU_STOP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline void identity_mapping_add(pgd_t *pgd, unsigned long start,
|
||||||
|
unsigned long end)
|
||||||
|
{
|
||||||
|
unsigned long addr, prot;
|
||||||
|
pmd_t *pmd;
|
||||||
|
|
||||||
|
prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
|
||||||
|
if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
|
||||||
|
prot |= PMD_BIT4;
|
||||||
|
|
||||||
|
for (addr = start & PGDIR_MASK; addr < end;) {
|
||||||
|
pmd = pmd_offset(pgd + pgd_index(addr), addr);
|
||||||
|
pmd[0] = __pmd(addr | prot);
|
||||||
|
addr += SECTION_SIZE;
|
||||||
|
pmd[1] = __pmd(addr | prot);
|
||||||
|
addr += SECTION_SIZE;
|
||||||
|
flush_pmd_entry(pmd);
|
||||||
|
outer_clean_range(__pa(pmd), __pa(pmd + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void identity_mapping_del(pgd_t *pgd, unsigned long start,
|
||||||
|
unsigned long end)
|
||||||
|
{
|
||||||
|
unsigned long addr;
|
||||||
|
pmd_t *pmd;
|
||||||
|
|
||||||
|
for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) {
|
||||||
|
pmd = pmd_offset(pgd + pgd_index(addr), addr);
|
||||||
|
pmd[0] = __pmd(0);
|
||||||
|
pmd[1] = __pmd(0);
|
||||||
|
clean_pmd_entry(pmd);
|
||||||
|
outer_clean_range(__pa(pmd), __pa(pmd + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int __cpuinit __cpu_up(unsigned int cpu)
|
int __cpuinit __cpu_up(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
|
struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
|
||||||
struct task_struct *idle = ci->idle;
|
struct task_struct *idle = ci->idle;
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
pmd_t *pmd;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -101,11 +137,16 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
||||||
* a 1:1 mapping for the physical address of the kernel.
|
* a 1:1 mapping for the physical address of the kernel.
|
||||||
*/
|
*/
|
||||||
pgd = pgd_alloc(&init_mm);
|
pgd = pgd_alloc(&init_mm);
|
||||||
pmd = pmd_offset(pgd + pgd_index(PHYS_OFFSET), PHYS_OFFSET);
|
if (!pgd)
|
||||||
*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
|
return -ENOMEM;
|
||||||
PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
|
|
||||||
flush_pmd_entry(pmd);
|
if (PHYS_OFFSET != PAGE_OFFSET) {
|
||||||
outer_clean_range(__pa(pmd), __pa(pmd + 1));
|
#ifndef CONFIG_HOTPLUG_CPU
|
||||||
|
identity_mapping_add(pgd, __pa(__init_begin), __pa(__init_end));
|
||||||
|
#endif
|
||||||
|
identity_mapping_add(pgd, __pa(_stext), __pa(_etext));
|
||||||
|
identity_mapping_add(pgd, __pa(_sdata), __pa(_edata));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to tell the secondary core where to find
|
* We need to tell the secondary core where to find
|
||||||
|
@ -143,8 +184,14 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
||||||
secondary_data.stack = NULL;
|
secondary_data.stack = NULL;
|
||||||
secondary_data.pgdir = 0;
|
secondary_data.pgdir = 0;
|
||||||
|
|
||||||
*pmd = __pmd(0);
|
if (PHYS_OFFSET != PAGE_OFFSET) {
|
||||||
clean_pmd_entry(pmd);
|
#ifndef CONFIG_HOTPLUG_CPU
|
||||||
|
identity_mapping_del(pgd, __pa(__init_begin), __pa(__init_end));
|
||||||
|
#endif
|
||||||
|
identity_mapping_del(pgd, __pa(_stext), __pa(_etext));
|
||||||
|
identity_mapping_del(pgd, __pa(_sdata), __pa(_edata));
|
||||||
|
}
|
||||||
|
|
||||||
pgd_free(&init_mm, pgd);
|
pgd_free(&init_mm, pgd);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -567,7 +614,8 @@ void smp_send_stop(void)
|
||||||
{
|
{
|
||||||
cpumask_t mask = cpu_online_map;
|
cpumask_t mask = cpu_online_map;
|
||||||
cpu_clear(smp_processor_id(), mask);
|
cpu_clear(smp_processor_id(), mask);
|
||||||
send_ipi_message(&mask, IPI_CPU_STOP);
|
if (!cpus_empty(mask))
|
||||||
|
send_ipi_message(&mask, IPI_CPU_STOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -146,6 +146,8 @@ static struct unwind_idx *unwind_find_idx(unsigned long addr)
|
||||||
addr < table->end_addr) {
|
addr < table->end_addr) {
|
||||||
idx = search_index(addr, table->start,
|
idx = search_index(addr, table->start,
|
||||||
table->stop - 1);
|
table->stop - 1);
|
||||||
|
/* Move-to-front to exploit common traces */
|
||||||
|
list_move(&table->list, &unwind_tables);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,19 @@
|
||||||
#include <asm/memory.h>
|
#include <asm/memory.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
|
#define PROC_INFO \
|
||||||
|
VMLINUX_SYMBOL(__proc_info_begin) = .; \
|
||||||
|
*(.proc.info.init) \
|
||||||
|
VMLINUX_SYMBOL(__proc_info_end) = .;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
|
#define ARM_CPU_DISCARD(x)
|
||||||
|
#define ARM_CPU_KEEP(x) x
|
||||||
|
#else
|
||||||
|
#define ARM_CPU_DISCARD(x) x
|
||||||
|
#define ARM_CPU_KEEP(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
OUTPUT_ARCH(arm)
|
OUTPUT_ARCH(arm)
|
||||||
ENTRY(stext)
|
ENTRY(stext)
|
||||||
|
|
||||||
|
@ -31,15 +44,18 @@ SECTIONS
|
||||||
HEAD_TEXT
|
HEAD_TEXT
|
||||||
INIT_TEXT
|
INIT_TEXT
|
||||||
_einittext = .;
|
_einittext = .;
|
||||||
__proc_info_begin = .;
|
ARM_CPU_DISCARD(PROC_INFO)
|
||||||
*(.proc.info.init)
|
|
||||||
__proc_info_end = .;
|
|
||||||
__arch_info_begin = .;
|
__arch_info_begin = .;
|
||||||
*(.arch.info.init)
|
*(.arch.info.init)
|
||||||
__arch_info_end = .;
|
__arch_info_end = .;
|
||||||
__tagtable_begin = .;
|
__tagtable_begin = .;
|
||||||
*(.taglist.init)
|
*(.taglist.init)
|
||||||
__tagtable_end = .;
|
__tagtable_end = .;
|
||||||
|
#ifdef CONFIG_SMP_ON_UP
|
||||||
|
__smpalt_begin = .;
|
||||||
|
*(.alt.smp.init)
|
||||||
|
__smpalt_end = .;
|
||||||
|
#endif
|
||||||
|
|
||||||
INIT_SETUP(16)
|
INIT_SETUP(16)
|
||||||
|
|
||||||
|
@ -68,10 +84,8 @@ SECTIONS
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
*(.ARM.exidx.exit.text)
|
*(.ARM.exidx.exit.text)
|
||||||
*(.ARM.extab.exit.text)
|
*(.ARM.extab.exit.text)
|
||||||
#ifndef CONFIG_HOTPLUG_CPU
|
ARM_CPU_DISCARD(*(.ARM.exidx.cpuexit.text))
|
||||||
*(.ARM.exidx.cpuexit.text)
|
ARM_CPU_DISCARD(*(.ARM.extab.cpuexit.text))
|
||||||
*(.ARM.extab.cpuexit.text)
|
|
||||||
#endif
|
|
||||||
#ifndef CONFIG_HOTPLUG
|
#ifndef CONFIG_HOTPLUG
|
||||||
*(.ARM.exidx.devexit.text)
|
*(.ARM.exidx.devexit.text)
|
||||||
*(.ARM.extab.devexit.text)
|
*(.ARM.extab.devexit.text)
|
||||||
|
@ -100,12 +114,11 @@ SECTIONS
|
||||||
*(.glue_7)
|
*(.glue_7)
|
||||||
*(.glue_7t)
|
*(.glue_7t)
|
||||||
*(.got) /* Global offset table */
|
*(.got) /* Global offset table */
|
||||||
|
ARM_CPU_KEEP(PROC_INFO)
|
||||||
}
|
}
|
||||||
|
|
||||||
RO_DATA(PAGE_SIZE)
|
RO_DATA(PAGE_SIZE)
|
||||||
|
|
||||||
_etext = .; /* End of text and rodata section */
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARM_UNWIND
|
#ifdef CONFIG_ARM_UNWIND
|
||||||
/*
|
/*
|
||||||
* Stack unwinding tables
|
* Stack unwinding tables
|
||||||
|
@ -123,6 +136,8 @@ SECTIONS
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
_etext = .; /* End of text and rodata section */
|
||||||
|
|
||||||
#ifdef CONFIG_XIP_KERNEL
|
#ifdef CONFIG_XIP_KERNEL
|
||||||
__data_loc = ALIGN(4); /* location in binary */
|
__data_loc = ALIGN(4); /* location in binary */
|
||||||
. = PAGE_OFFSET + TEXT_OFFSET;
|
. = PAGE_OFFSET + TEXT_OFFSET;
|
||||||
|
@ -237,6 +252,12 @@ SECTIONS
|
||||||
|
|
||||||
/* Default discards */
|
/* Default discards */
|
||||||
DISCARDS
|
DISCARDS
|
||||||
|
|
||||||
|
#ifndef CONFIG_SMP_ON_UP
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.alt.smp.init)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -95,8 +95,6 @@ static void __init aaed2000_map_io(void)
|
||||||
|
|
||||||
MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
|
MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
|
||||||
/* Maintainer: Nicolas Bellido Y Ortega */
|
/* Maintainer: Nicolas Bellido Y Ortega */
|
||||||
.phys_io = PIO_BASE,
|
|
||||||
.io_pg_offst = ((VIO_BASE) >> 18) & 0xfffc,
|
|
||||||
.map_io = aaed2000_map_io,
|
.map_io = aaed2000_map_io,
|
||||||
.init_irq = aaed2000_init_irq,
|
.init_irq = aaed2000_init_irq,
|
||||||
.timer = &aaec2000_timer,
|
.timer = &aaec2000_timer,
|
||||||
|
|
|
@ -10,12 +10,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
.macro addruart, rx, tmp
|
.macro addruart, rp, rv
|
||||||
mrc p15, 0, \rx, c1, c0
|
mov \rp, 0x00000800
|
||||||
tst \rx, #1 @ MMU enabled?
|
orr \rv, \rp, #io_p2v(0x80000000) @ virtual
|
||||||
moveq \rx, #0x80000000 @ physical
|
orr \rp, \rp, #0x80000000 @ physical
|
||||||
movne \rx, #io_p2v(0x80000000) @ virtual
|
|
||||||
orr \rx, \rx, #0x00000800
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro senduart,rd,rx
|
.macro senduart,rd,rx
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
#ifndef __ASM_ARCH_VMALLOC_H
|
#ifndef __ASM_ARCH_VMALLOC_H
|
||||||
#define __ASM_ARCH_VMALLOC_H
|
#define __ASM_ARCH_VMALLOC_H
|
||||||
|
|
||||||
#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
|
#define VMALLOC_END 0xd0000000
|
||||||
|
|
||||||
#endif /* __ASM_ARCH_VMALLOC_H */
|
#endif /* __ASM_ARCH_VMALLOC_H */
|
||||||
|
|
|
@ -33,6 +33,7 @@ config ARCH_AT91SAM9260
|
||||||
select HAVE_AT91_USART3
|
select HAVE_AT91_USART3
|
||||||
select HAVE_AT91_USART4
|
select HAVE_AT91_USART4
|
||||||
select HAVE_AT91_USART5
|
select HAVE_AT91_USART5
|
||||||
|
select HAVE_NET_MACB
|
||||||
|
|
||||||
config ARCH_AT91SAM9261
|
config ARCH_AT91SAM9261
|
||||||
bool "AT91SAM9261"
|
bool "AT91SAM9261"
|
||||||
|
@ -51,6 +52,7 @@ config ARCH_AT91SAM9263
|
||||||
select CPU_ARM926T
|
select CPU_ARM926T
|
||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
select HAVE_FB_ATMEL
|
select HAVE_FB_ATMEL
|
||||||
|
select HAVE_NET_MACB
|
||||||
|
|
||||||
config ARCH_AT91SAM9RL
|
config ARCH_AT91SAM9RL
|
||||||
bool "AT91SAM9RL"
|
bool "AT91SAM9RL"
|
||||||
|
@ -66,6 +68,7 @@ config ARCH_AT91SAM9G20
|
||||||
select HAVE_AT91_USART3
|
select HAVE_AT91_USART3
|
||||||
select HAVE_AT91_USART4
|
select HAVE_AT91_USART4
|
||||||
select HAVE_AT91_USART5
|
select HAVE_AT91_USART5
|
||||||
|
select HAVE_NET_MACB
|
||||||
|
|
||||||
config ARCH_AT91SAM9G45
|
config ARCH_AT91SAM9G45
|
||||||
bool "AT91SAM9G45"
|
bool "AT91SAM9G45"
|
||||||
|
@ -73,6 +76,7 @@ config ARCH_AT91SAM9G45
|
||||||
select GENERIC_CLOCKEVENTS
|
select GENERIC_CLOCKEVENTS
|
||||||
select HAVE_AT91_USART3
|
select HAVE_AT91_USART3
|
||||||
select HAVE_FB_ATMEL
|
select HAVE_FB_ATMEL
|
||||||
|
select HAVE_NET_MACB
|
||||||
|
|
||||||
config ARCH_AT91CAP9
|
config ARCH_AT91CAP9
|
||||||
bool "AT91CAP9"
|
bool "AT91CAP9"
|
||||||
|
@ -248,6 +252,12 @@ config MACH_CPU9260
|
||||||
Select this if you are using a Eukrea Electromatique's
|
Select this if you are using a Eukrea Electromatique's
|
||||||
CPU9260 Board <http://www.eukrea.com/>
|
CPU9260 Board <http://www.eukrea.com/>
|
||||||
|
|
||||||
|
config MACH_FLEXIBITY
|
||||||
|
bool "Flexibity Connect board"
|
||||||
|
help
|
||||||
|
Select this if you are using Flexibity Connect board
|
||||||
|
<http://www.flexibity.com>
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# ----------------------------------------------------------
|
# ----------------------------------------------------------
|
||||||
|
@ -338,6 +348,7 @@ config MACH_AT91SAM9G20EK
|
||||||
that embeds only one SD/MMC slot.
|
that embeds only one SD/MMC slot.
|
||||||
|
|
||||||
config MACH_AT91SAM9G20EK_2MMC
|
config MACH_AT91SAM9G20EK_2MMC
|
||||||
|
depends on MACH_AT91SAM9G20EK
|
||||||
bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots"
|
bool "Atmel AT91SAM9G20-EK Evaluation Kit with 2 SD/MMC Slots"
|
||||||
select HAVE_NAND_ATMEL_BUSWIDTH_16
|
select HAVE_NAND_ATMEL_BUSWIDTH_16
|
||||||
help
|
help
|
||||||
|
@ -383,8 +394,8 @@ if ARCH_AT91SAM9G45
|
||||||
|
|
||||||
comment "AT91SAM9G45 Board Type"
|
comment "AT91SAM9G45 Board Type"
|
||||||
|
|
||||||
config MACH_AT91SAM9G45EKES
|
config MACH_AT91SAM9M10G45EK
|
||||||
bool "Atmel AT91SAM9G45-EKES Evaluation Kit"
|
bool "Atmel AT91SAM9M10G45-EK Evaluation Kits"
|
||||||
select HAVE_NAND_ATMEL_BUSWIDTH_16
|
select HAVE_NAND_ATMEL_BUSWIDTH_16
|
||||||
help
|
help
|
||||||
Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit.
|
Select this if you are using Atmel's AT91SAM9G45-EKES Evaluation Kit.
|
||||||
|
|
|
@ -46,6 +46,7 @@ obj-$(CONFIG_MACH_USB_A9260) += board-usb-a9260.o
|
||||||
obj-$(CONFIG_MACH_QIL_A9260) += board-qil-a9260.o
|
obj-$(CONFIG_MACH_QIL_A9260) += board-qil-a9260.o
|
||||||
obj-$(CONFIG_MACH_AFEB9260) += board-afeb-9260v1.o
|
obj-$(CONFIG_MACH_AFEB9260) += board-afeb-9260v1.o
|
||||||
obj-$(CONFIG_MACH_CPU9260) += board-cpu9krea.o
|
obj-$(CONFIG_MACH_CPU9260) += board-cpu9krea.o
|
||||||
|
obj-$(CONFIG_MACH_FLEXIBITY) += board-flexibity.o
|
||||||
|
|
||||||
# AT91SAM9261 board-specific support
|
# AT91SAM9261 board-specific support
|
||||||
obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
|
obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o
|
||||||
|
@ -61,7 +62,6 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o
|
||||||
|
|
||||||
# AT91SAM9G20 board-specific support
|
# AT91SAM9G20 board-specific support
|
||||||
obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
|
obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
|
||||||
obj-$(CONFIG_MACH_AT91SAM9G20EK_2MMC) += board-sam9g20ek-2slot-mmc.o
|
|
||||||
obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o
|
obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o
|
||||||
obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o
|
obj-$(CONFIG_MACH_STAMP9G20) += board-stamp9g20.o
|
||||||
obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o
|
obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o
|
||||||
|
@ -70,7 +70,7 @@ obj-$(CONFIG_MACH_PORTUXG20) += board-stamp9g20.o
|
||||||
obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o
|
obj-$(CONFIG_MACH_SNAPPER_9260) += board-snapper9260.o
|
||||||
|
|
||||||
# AT91SAM9G45 board-specific support
|
# AT91SAM9G45 board-specific support
|
||||||
obj-$(CONFIG_MACH_AT91SAM9G45EKES) += board-sam9m10g45ek.o
|
obj-$(CONFIG_MACH_AT91SAM9M10G45EK) += board-sam9m10g45ek.o
|
||||||
|
|
||||||
# AT91CAP9 board-specific support
|
# AT91CAP9 board-specific support
|
||||||
obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o
|
obj-$(CONFIG_MACH_AT91CAP9ADK) += board-cap9adk.o
|
||||||
|
|
|
@ -92,8 +92,6 @@ static void __init onearm_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
|
MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
|
||||||
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = onearm_map_io,
|
.map_io = onearm_map_io,
|
||||||
|
|
|
@ -218,8 +218,6 @@ static void __init afeb9260_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AFEB9260, "Custom afeb9260 board")
|
MACHINE_START(AFEB9260, "Custom afeb9260 board")
|
||||||
/* Maintainer: Sergey Lapin <slapin@ossfans.org> */
|
/* Maintainer: Sergey Lapin <slapin@ossfans.org> */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = afeb9260_map_io,
|
.map_io = afeb9260_map_io,
|
||||||
|
|
|
@ -216,7 +216,7 @@ static struct atmel_nand_data __initdata eb_nand_data = {
|
||||||
/* .rdy_pin = AT91_PIN_PC16, */
|
/* .rdy_pin = AT91_PIN_PC16, */
|
||||||
.enable_pin = AT91_PIN_PA15,
|
.enable_pin = AT91_PIN_PA15,
|
||||||
.partition_info = nand_partitions,
|
.partition_info = nand_partitions,
|
||||||
#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
|
#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
|
||||||
.bus_width_16 = 1,
|
.bus_width_16 = 1,
|
||||||
#else
|
#else
|
||||||
.bus_width_16 = 0,
|
.bus_width_16 = 0,
|
||||||
|
@ -318,8 +318,6 @@ static void __init eb_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB")
|
MACHINE_START(AT572D940HFEB, "Atmel AT91D940HF-EB")
|
||||||
/* Maintainer: Atmel <costa.antonior@gmail.com> */
|
/* Maintainer: Atmel <costa.antonior@gmail.com> */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = eb_map_io,
|
.map_io = eb_map_io,
|
||||||
|
|
|
@ -198,8 +198,6 @@ static void __init cam60_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(CAM60, "KwikByte CAM60")
|
MACHINE_START(CAM60, "KwikByte CAM60")
|
||||||
/* Maintainer: KwikByte */
|
/* Maintainer: KwikByte */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = cam60_map_io,
|
.map_io = cam60_map_io,
|
||||||
|
|
|
@ -399,8 +399,6 @@ static void __init cap9adk_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AT91CAP9ADK, "Atmel AT91CAP9A-DK")
|
MACHINE_START(AT91CAP9ADK, "Atmel AT91CAP9A-DK")
|
||||||
/* Maintainer: Stelian Pop <stelian.pop@leadtechdesign.com> */
|
/* Maintainer: Stelian Pop <stelian.pop@leadtechdesign.com> */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = cap9adk_map_io,
|
.map_io = cap9adk_map_io,
|
||||||
|
|
|
@ -162,8 +162,6 @@ static void __init carmeva_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(CARMEVA, "Carmeva")
|
MACHINE_START(CARMEVA, "Carmeva")
|
||||||
/* Maintainer: Conitec Datasystems */
|
/* Maintainer: Conitec Datasystems */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = carmeva_map_io,
|
.map_io = carmeva_map_io,
|
||||||
|
|
|
@ -375,8 +375,6 @@ MACHINE_START(CPUAT9260, "Eukrea CPU9260")
|
||||||
MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
|
MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
|
||||||
#endif
|
#endif
|
||||||
/* Maintainer: Eric Benard - EUKREA Electromatique */
|
/* Maintainer: Eric Benard - EUKREA Electromatique */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = cpu9krea_map_io,
|
.map_io = cpu9krea_map_io,
|
||||||
|
|
|
@ -175,8 +175,6 @@ static void __init cpuat91_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(CPUAT91, "Eukrea")
|
MACHINE_START(CPUAT91, "Eukrea")
|
||||||
/* Maintainer: Eric Benard - EUKREA Electromatique */
|
/* Maintainer: Eric Benard - EUKREA Electromatique */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = cpuat91_map_io,
|
.map_io = cpuat91_map_io,
|
||||||
|
|
|
@ -257,8 +257,6 @@ static void __init csb337_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(CSB337, "Cogent CSB337")
|
MACHINE_START(CSB337, "Cogent CSB337")
|
||||||
/* Maintainer: Bill Gatliff */
|
/* Maintainer: Bill Gatliff */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = csb337_map_io,
|
.map_io = csb337_map_io,
|
||||||
|
|
|
@ -138,8 +138,6 @@ static void __init csb637_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(CSB637, "Cogent CSB637")
|
MACHINE_START(CSB637, "Cogent CSB637")
|
||||||
/* Maintainer: Bill Gatliff */
|
/* Maintainer: Bill Gatliff */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = csb637_map_io,
|
.map_io = csb637_map_io,
|
||||||
|
|
|
@ -225,8 +225,6 @@ static void __init dk_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
|
MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
|
||||||
/* Maintainer: SAN People/Atmel */
|
/* Maintainer: SAN People/Atmel */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = dk_map_io,
|
.map_io = dk_map_io,
|
||||||
|
|
|
@ -120,8 +120,6 @@ static void __init eb9200_board_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(ATEB9200, "Embest ATEB9200")
|
MACHINE_START(ATEB9200, "Embest ATEB9200")
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = eb9200_map_io,
|
.map_io = eb9200_map_io,
|
||||||
|
|
|
@ -168,8 +168,6 @@ static void __init ecb_at91board_init(void)
|
||||||
|
|
||||||
MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
|
MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
|
||||||
/* Maintainer: emQbit.com */
|
/* Maintainer: emQbit.com */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = ecb_at91map_io,
|
.map_io = ecb_at91map_io,
|
||||||
|
|
|
@ -148,8 +148,6 @@ static void __init eco920_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(ECO920, "eco920")
|
MACHINE_START(ECO920, "eco920")
|
||||||
/* Maintainer: Sascha Hauer */
|
/* Maintainer: Sascha Hauer */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = eco920_map_io,
|
.map_io = eco920_map_io,
|
||||||
|
|
|
@ -191,8 +191,6 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
|
MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
|
||||||
/* Maintainer: SAN People/Atmel */
|
/* Maintainer: SAN People/Atmel */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
162
arch/arm/mach-at91/board-flexibity.c
Normal file
162
arch/arm/mach-at91/board-flexibity.c
Normal file
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* linux/arch/arm/mach-at91/board-flexibity.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Flexibity
|
||||||
|
* Copyright (C) 2005 SAN People
|
||||||
|
* Copyright (C) 2006 Atmel
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/spi/spi.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
|
||||||
|
#include <asm/mach-types.h>
|
||||||
|
|
||||||
|
#include <asm/mach/arch.h>
|
||||||
|
#include <asm/mach/map.h>
|
||||||
|
#include <asm/mach/irq.h>
|
||||||
|
|
||||||
|
#include <mach/hardware.h>
|
||||||
|
#include <mach/board.h>
|
||||||
|
|
||||||
|
#include "generic.h"
|
||||||
|
|
||||||
|
static void __init flexibity_map_io(void)
|
||||||
|
{
|
||||||
|
/* Initialize processor: 18.432 MHz crystal */
|
||||||
|
at91sam9260_initialize(18432000);
|
||||||
|
|
||||||
|
/* DBGU on ttyS0. (Rx & Tx only) */
|
||||||
|
at91_register_uart(0, 0, 0);
|
||||||
|
|
||||||
|
/* set serial console to ttyS0 (ie, DBGU) */
|
||||||
|
at91_set_serial_console(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init flexibity_init_irq(void)
|
||||||
|
{
|
||||||
|
at91sam9260_init_interrupts(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* USB Host port */
|
||||||
|
static struct at91_usbh_data __initdata flexibity_usbh_data = {
|
||||||
|
.ports = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* USB Device port */
|
||||||
|
static struct at91_udc_data __initdata flexibity_udc_data = {
|
||||||
|
.vbus_pin = AT91_PIN_PC5,
|
||||||
|
.pullup_pin = 0, /* pull-up driven by UDC */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SPI devices */
|
||||||
|
static struct spi_board_info flexibity_spi_devices[] = {
|
||||||
|
{ /* DataFlash chip */
|
||||||
|
.modalias = "mtd_dataflash",
|
||||||
|
.chip_select = 1,
|
||||||
|
.max_speed_hz = 15 * 1000 * 1000,
|
||||||
|
.bus_num = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* MCI (SD/MMC) */
|
||||||
|
static struct at91_mmc_data __initdata flexibity_mmc_data = {
|
||||||
|
.slot_b = 0,
|
||||||
|
.wire4 = 1,
|
||||||
|
.det_pin = AT91_PIN_PC9,
|
||||||
|
.wp_pin = AT91_PIN_PC4,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* LEDs */
|
||||||
|
static struct gpio_led flexibity_leds[] = {
|
||||||
|
{
|
||||||
|
.name = "usb1:green",
|
||||||
|
.gpio = AT91_PIN_PA12,
|
||||||
|
.active_low = 1,
|
||||||
|
.default_trigger = "default-on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "usb1:red",
|
||||||
|
.gpio = AT91_PIN_PA13,
|
||||||
|
.active_low = 1,
|
||||||
|
.default_trigger = "default-on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "usb2:green",
|
||||||
|
.gpio = AT91_PIN_PB26,
|
||||||
|
.active_low = 1,
|
||||||
|
.default_trigger = "default-on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "usb2:red",
|
||||||
|
.gpio = AT91_PIN_PB27,
|
||||||
|
.active_low = 1,
|
||||||
|
.default_trigger = "default-on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "usb3:green",
|
||||||
|
.gpio = AT91_PIN_PC8,
|
||||||
|
.active_low = 1,
|
||||||
|
.default_trigger = "default-on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "usb3:red",
|
||||||
|
.gpio = AT91_PIN_PC6,
|
||||||
|
.active_low = 1,
|
||||||
|
.default_trigger = "default-on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "usb4:green",
|
||||||
|
.gpio = AT91_PIN_PB4,
|
||||||
|
.active_low = 1,
|
||||||
|
.default_trigger = "default-on",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "usb4:red",
|
||||||
|
.gpio = AT91_PIN_PB5,
|
||||||
|
.active_low = 1,
|
||||||
|
.default_trigger = "default-on",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init flexibity_board_init(void)
|
||||||
|
{
|
||||||
|
/* Serial */
|
||||||
|
at91_add_device_serial();
|
||||||
|
/* USB Host */
|
||||||
|
at91_add_device_usbh(&flexibity_usbh_data);
|
||||||
|
/* USB Device */
|
||||||
|
at91_add_device_udc(&flexibity_udc_data);
|
||||||
|
/* SPI */
|
||||||
|
at91_add_device_spi(flexibity_spi_devices,
|
||||||
|
ARRAY_SIZE(flexibity_spi_devices));
|
||||||
|
/* MMC */
|
||||||
|
at91_add_device_mmc(0, &flexibity_mmc_data);
|
||||||
|
/* LEDs */
|
||||||
|
at91_gpio_leds(flexibity_leds, ARRAY_SIZE(flexibity_leds));
|
||||||
|
}
|
||||||
|
|
||||||
|
MACHINE_START(FLEXIBITY, "Flexibity Connect")
|
||||||
|
/* Maintainer: Maxim Osipov */
|
||||||
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
|
.timer = &at91sam926x_timer,
|
||||||
|
.map_io = flexibity_map_io,
|
||||||
|
.init_irq = flexibity_init_irq,
|
||||||
|
.init_machine = flexibity_board_init,
|
||||||
|
MACHINE_END
|
|
@ -99,8 +99,6 @@ static void __init kafa_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(KAFA, "Sperry-Sun KAFA")
|
MACHINE_START(KAFA, "Sperry-Sun KAFA")
|
||||||
/* Maintainer: Sergei Sharonov */
|
/* Maintainer: Sergei Sharonov */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = kafa_map_io,
|
.map_io = kafa_map_io,
|
||||||
|
|
|
@ -136,8 +136,6 @@ static void __init kb9202_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(KB9200, "KB920x")
|
MACHINE_START(KB9200, "KB920x")
|
||||||
/* Maintainer: KwikByte, Inc. */
|
/* Maintainer: KwikByte, Inc. */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = kb9202_map_io,
|
.map_io = kb9202_map_io,
|
||||||
|
|
|
@ -387,8 +387,6 @@ static void __init neocore926_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
|
MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
|
||||||
/* Maintainer: ADENEO */
|
/* Maintainer: ADENEO */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = neocore926_map_io,
|
.map_io = neocore926_map_io,
|
||||||
|
|
|
@ -156,8 +156,6 @@ static void __init picotux200_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(PICOTUX2XX, "picotux 200")
|
MACHINE_START(PICOTUX2XX, "picotux 200")
|
||||||
/* Maintainer: Kleinhenz Elektronik GmbH */
|
/* Maintainer: Kleinhenz Elektronik GmbH */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = picotux200_map_io,
|
.map_io = picotux200_map_io,
|
||||||
|
|
|
@ -268,8 +268,6 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
|
MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
|
||||||
/* Maintainer: calao-systems */
|
/* Maintainer: calao-systems */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -212,8 +212,6 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
|
MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
|
||||||
/* Maintainer: Olimex */
|
/* Maintainer: Olimex */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -356,8 +356,6 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
|
MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
|
||||||
/* Maintainer: Atmel */
|
/* Maintainer: Atmel */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -623,8 +623,6 @@ MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK")
|
||||||
MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
|
MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
|
||||||
#endif
|
#endif
|
||||||
/* Maintainer: Atmel */
|
/* Maintainer: Atmel */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -454,8 +454,6 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
|
MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
|
||||||
/* Maintainer: Atmel */
|
/* Maintainer: Atmel */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -1,329 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2005 SAN People
|
|
||||||
* Copyright (C) 2008 Atmel
|
|
||||||
* Copyright (C) 2009 Rob Emanuele
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/mm.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/spi/spi.h>
|
|
||||||
#include <linux/spi/at73c213.h>
|
|
||||||
#include <linux/clk.h>
|
|
||||||
#include <linux/regulator/machine.h>
|
|
||||||
#include <linux/regulator/fixed.h>
|
|
||||||
#include <linux/regulator/consumer.h>
|
|
||||||
|
|
||||||
#include <mach/hardware.h>
|
|
||||||
#include <asm/setup.h>
|
|
||||||
#include <asm/mach-types.h>
|
|
||||||
#include <asm/irq.h>
|
|
||||||
|
|
||||||
#include <asm/mach/arch.h>
|
|
||||||
#include <asm/mach/map.h>
|
|
||||||
#include <asm/mach/irq.h>
|
|
||||||
|
|
||||||
#include <mach/board.h>
|
|
||||||
#include <mach/gpio.h>
|
|
||||||
#include <mach/at91sam9_smc.h>
|
|
||||||
|
|
||||||
#include "sam9_smc.h"
|
|
||||||
#include "generic.h"
|
|
||||||
|
|
||||||
|
|
||||||
static void __init ek_map_io(void)
|
|
||||||
{
|
|
||||||
/* Initialize processor: 18.432 MHz crystal */
|
|
||||||
at91sam9260_initialize(18432000);
|
|
||||||
|
|
||||||
/* DGBU on ttyS0. (Rx & Tx only) */
|
|
||||||
at91_register_uart(0, 0, 0);
|
|
||||||
|
|
||||||
/* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
|
|
||||||
at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
|
|
||||||
| ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD
|
|
||||||
| ATMEL_UART_RI);
|
|
||||||
|
|
||||||
/* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */
|
|
||||||
at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
|
|
||||||
|
|
||||||
/* set serial console to ttyS0 (ie, DBGU) */
|
|
||||||
at91_set_serial_console(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init ek_init_irq(void)
|
|
||||||
{
|
|
||||||
at91sam9260_init_interrupts(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* USB Host port
|
|
||||||
*/
|
|
||||||
static struct at91_usbh_data __initdata ek_usbh_data = {
|
|
||||||
.ports = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* USB Device port
|
|
||||||
*/
|
|
||||||
static struct at91_udc_data __initdata ek_udc_data = {
|
|
||||||
.vbus_pin = AT91_PIN_PC5,
|
|
||||||
.pullup_pin = 0, /* pull-up driven by UDC */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SPI devices.
|
|
||||||
*/
|
|
||||||
static struct spi_board_info ek_spi_devices[] = {
|
|
||||||
#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
|
|
||||||
{ /* DataFlash chip */
|
|
||||||
.modalias = "mtd_dataflash",
|
|
||||||
.chip_select = 1,
|
|
||||||
.max_speed_hz = 15 * 1000 * 1000,
|
|
||||||
.bus_num = 0,
|
|
||||||
},
|
|
||||||
#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD)
|
|
||||||
{ /* DataFlash card */
|
|
||||||
.modalias = "mtd_dataflash",
|
|
||||||
.chip_select = 0,
|
|
||||||
.max_speed_hz = 15 * 1000 * 1000,
|
|
||||||
.bus_num = 0,
|
|
||||||
},
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MACB Ethernet device
|
|
||||||
*/
|
|
||||||
static struct at91_eth_data __initdata ek_macb_data = {
|
|
||||||
.phy_irq_pin = AT91_PIN_PB0,
|
|
||||||
.is_rmii = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NAND flash
|
|
||||||
*/
|
|
||||||
static struct mtd_partition __initdata ek_nand_partition[] = {
|
|
||||||
{
|
|
||||||
.name = "Bootstrap",
|
|
||||||
.offset = 0,
|
|
||||||
.size = 4 * SZ_1M,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "Partition 1",
|
|
||||||
.offset = MTDPART_OFS_NXTBLK,
|
|
||||||
.size = 60 * SZ_1M,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "Partition 2",
|
|
||||||
.offset = MTDPART_OFS_NXTBLK,
|
|
||||||
.size = MTDPART_SIZ_FULL,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
|
||||||
{
|
|
||||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
|
||||||
return ek_nand_partition;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* det_pin is not connected */
|
|
||||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
|
||||||
.ale = 21,
|
|
||||||
.cle = 22,
|
|
||||||
.rdy_pin = AT91_PIN_PC13,
|
|
||||||
.enable_pin = AT91_PIN_PC14,
|
|
||||||
.partition_info = nand_partitions,
|
|
||||||
#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
|
|
||||||
.bus_width_16 = 1,
|
|
||||||
#else
|
|
||||||
.bus_width_16 = 0,
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
|
||||||
.ncs_read_setup = 0,
|
|
||||||
.nrd_setup = 2,
|
|
||||||
.ncs_write_setup = 0,
|
|
||||||
.nwe_setup = 2,
|
|
||||||
|
|
||||||
.ncs_read_pulse = 4,
|
|
||||||
.nrd_pulse = 4,
|
|
||||||
.ncs_write_pulse = 4,
|
|
||||||
.nwe_pulse = 4,
|
|
||||||
|
|
||||||
.read_cycle = 7,
|
|
||||||
.write_cycle = 7,
|
|
||||||
|
|
||||||
.mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
|
|
||||||
.tdf_cycles = 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void __init ek_add_device_nand(void)
|
|
||||||
{
|
|
||||||
/* setup bus-width (8 or 16) */
|
|
||||||
if (ek_nand_data.bus_width_16)
|
|
||||||
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
|
|
||||||
else
|
|
||||||
ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
|
|
||||||
|
|
||||||
/* configure chip-select 3 (NAND) */
|
|
||||||
sam9_smc_configure(3, &ek_nand_smc_config);
|
|
||||||
|
|
||||||
at91_add_device_nand(&ek_nand_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MCI (SD/MMC)
|
|
||||||
* wp_pin is not connected
|
|
||||||
*/
|
|
||||||
#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
|
|
||||||
static struct mci_platform_data __initdata ek_mmc_data = {
|
|
||||||
.slot[0] = {
|
|
||||||
.bus_width = 4,
|
|
||||||
.detect_pin = AT91_PIN_PC2,
|
|
||||||
.wp_pin = -ENODEV,
|
|
||||||
},
|
|
||||||
.slot[1] = {
|
|
||||||
.bus_width = 4,
|
|
||||||
.detect_pin = AT91_PIN_PC9,
|
|
||||||
.wp_pin = -ENODEV,
|
|
||||||
},
|
|
||||||
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
static struct at91_mmc_data __initdata ek_mmc_data = {
|
|
||||||
.slot_b = 1, /* Only one slot so use slot B */
|
|
||||||
.wire4 = 1,
|
|
||||||
.det_pin = AT91_PIN_PC9,
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* LEDs
|
|
||||||
*/
|
|
||||||
static struct gpio_led ek_leds[] = {
|
|
||||||
{ /* "bottom" led, green, userled1 to be defined */
|
|
||||||
.name = "ds5",
|
|
||||||
.gpio = AT91_PIN_PB8,
|
|
||||||
.active_low = 1,
|
|
||||||
.default_trigger = "none",
|
|
||||||
},
|
|
||||||
{ /* "power" led, yellow */
|
|
||||||
.name = "ds1",
|
|
||||||
.gpio = AT91_PIN_PB9,
|
|
||||||
.default_trigger = "heartbeat",
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(CONFIG_REGULATOR_FIXED_VOLTAGE) || defined(CONFIG_REGULATOR_FIXED_VOLTAGE_MODULE)
|
|
||||||
static struct regulator_consumer_supply ek_audio_consumer_supplies[] = {
|
|
||||||
REGULATOR_SUPPLY("AVDD", "0-001b"),
|
|
||||||
REGULATOR_SUPPLY("HPVDD", "0-001b"),
|
|
||||||
REGULATOR_SUPPLY("DBVDD", "0-001b"),
|
|
||||||
REGULATOR_SUPPLY("DCVDD", "0-001b"),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct regulator_init_data ek_avdd_reg_init_data = {
|
|
||||||
.constraints = {
|
|
||||||
.name = "3V3",
|
|
||||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
|
||||||
},
|
|
||||||
.consumer_supplies = ek_audio_consumer_supplies,
|
|
||||||
.num_consumer_supplies = ARRAY_SIZE(ek_audio_consumer_supplies),
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct fixed_voltage_config ek_vdd_pdata = {
|
|
||||||
.supply_name = "board-3V3",
|
|
||||||
.microvolts = 3300000,
|
|
||||||
.gpio = -EINVAL,
|
|
||||||
.enabled_at_boot = 0,
|
|
||||||
.init_data = &ek_avdd_reg_init_data,
|
|
||||||
};
|
|
||||||
static struct platform_device ek_voltage_regulator = {
|
|
||||||
.name = "reg-fixed-voltage",
|
|
||||||
.id = -1,
|
|
||||||
.num_resources = 0,
|
|
||||||
.dev = {
|
|
||||||
.platform_data = &ek_vdd_pdata,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
static void __init ek_add_regulators(void)
|
|
||||||
{
|
|
||||||
platform_device_register(&ek_voltage_regulator);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static void __init ek_add_regulators(void) {}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct i2c_board_info __initdata ek_i2c_devices[] = {
|
|
||||||
{
|
|
||||||
I2C_BOARD_INFO("24c512", 0x50),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void __init ek_board_init(void)
|
|
||||||
{
|
|
||||||
/* Serial */
|
|
||||||
at91_add_device_serial();
|
|
||||||
/* USB Host */
|
|
||||||
at91_add_device_usbh(&ek_usbh_data);
|
|
||||||
/* USB Device */
|
|
||||||
at91_add_device_udc(&ek_udc_data);
|
|
||||||
/* SPI */
|
|
||||||
at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
|
|
||||||
/* NAND */
|
|
||||||
ek_add_device_nand();
|
|
||||||
/* Ethernet */
|
|
||||||
at91_add_device_eth(&ek_macb_data);
|
|
||||||
/* Regulators */
|
|
||||||
ek_add_regulators();
|
|
||||||
/* MMC */
|
|
||||||
#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
|
|
||||||
at91_add_device_mci(0, &ek_mmc_data);
|
|
||||||
#else
|
|
||||||
at91_add_device_mmc(0, &ek_mmc_data);
|
|
||||||
#endif
|
|
||||||
/* I2C */
|
|
||||||
at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
|
|
||||||
/* LEDs */
|
|
||||||
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
|
|
||||||
/* PCK0 provides MCLK to the WM8731 */
|
|
||||||
at91_set_B_periph(AT91_PIN_PC1, 0);
|
|
||||||
/* SSC (for WM8731) */
|
|
||||||
at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
|
|
||||||
}
|
|
||||||
|
|
||||||
MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
|
|
||||||
/* Maintainer: Rob Emanuele */
|
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
|
||||||
.timer = &at91sam926x_timer,
|
|
||||||
.map_io = ek_map_io,
|
|
||||||
.init_irq = ek_init_irq,
|
|
||||||
.init_machine = ek_board_init,
|
|
||||||
MACHINE_END
|
|
|
@ -47,6 +47,18 @@
|
||||||
#include "sam9_smc.h"
|
#include "sam9_smc.h"
|
||||||
#include "generic.h"
|
#include "generic.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* board revision encoding
|
||||||
|
* bit 0:
|
||||||
|
* 0 => 1 sd/mmc slot
|
||||||
|
* 1 => 2 sd/mmc slots connectors (board from revision C)
|
||||||
|
*/
|
||||||
|
#define HAVE_2MMC (1 << 0)
|
||||||
|
static int inline ek_have_2mmc(void)
|
||||||
|
{
|
||||||
|
return machine_is_at91sam9g20ek_2mmc() || (system_rev & HAVE_2MMC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void __init ek_map_io(void)
|
static void __init ek_map_io(void)
|
||||||
{
|
{
|
||||||
|
@ -94,7 +106,7 @@ static struct at91_udc_data __initdata ek_udc_data = {
|
||||||
* SPI devices.
|
* SPI devices.
|
||||||
*/
|
*/
|
||||||
static struct spi_board_info ek_spi_devices[] = {
|
static struct spi_board_info ek_spi_devices[] = {
|
||||||
#if !defined(CONFIG_MMC_AT91)
|
#if !(defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_AT91))
|
||||||
{ /* DataFlash chip */
|
{ /* DataFlash chip */
|
||||||
.modalias = "mtd_dataflash",
|
.modalias = "mtd_dataflash",
|
||||||
.chip_select = 1,
|
.chip_select = 1,
|
||||||
|
@ -121,6 +133,13 @@ static struct at91_eth_data __initdata ek_macb_data = {
|
||||||
.is_rmii = 1,
|
.is_rmii = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void __init ek_add_device_macb(void)
|
||||||
|
{
|
||||||
|
if (ek_have_2mmc())
|
||||||
|
ek_macb_data.phy_irq_pin = AT91_PIN_PB0;
|
||||||
|
|
||||||
|
at91_add_device_eth(&ek_macb_data);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NAND flash
|
* NAND flash
|
||||||
|
@ -198,13 +217,36 @@ static void __init ek_add_device_nand(void)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MCI (SD/MMC)
|
* MCI (SD/MMC)
|
||||||
* det_pin, wp_pin and vcc_pin are not connected
|
* wp_pin and vcc_pin are not connected
|
||||||
*/
|
*/
|
||||||
static struct at91_mmc_data __initdata ek_mmc_data = {
|
#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
|
||||||
.slot_b = 1,
|
static struct mci_platform_data __initdata ek_mmc_data = {
|
||||||
.wire4 = 1,
|
.slot[1] = {
|
||||||
};
|
.bus_width = 4,
|
||||||
|
.detect_pin = AT91_PIN_PC9,
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
static struct at91_mmc_data __initdata ek_mmc_data = {
|
||||||
|
.slot_b = 1, /* Only one slot so use slot B */
|
||||||
|
.wire4 = 1,
|
||||||
|
.det_pin = AT91_PIN_PC9,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void __init ek_add_device_mmc(void)
|
||||||
|
{
|
||||||
|
#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
|
||||||
|
if (ek_have_2mmc()) {
|
||||||
|
ek_mmc_data.slot[0].bus_width = 4;
|
||||||
|
ek_mmc_data.slot[0].detect_pin = AT91_PIN_PC2;
|
||||||
|
}
|
||||||
|
at91_add_device_mci(0, &ek_mmc_data);
|
||||||
|
#else
|
||||||
|
at91_add_device_mmc(0, &ek_mmc_data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LEDs
|
* LEDs
|
||||||
|
@ -223,6 +265,15 @@ static struct gpio_led ek_leds[] = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void __init ek_add_device_gpio_leds(void)
|
||||||
|
{
|
||||||
|
if (ek_have_2mmc()) {
|
||||||
|
ek_leds[0].gpio = AT91_PIN_PB8;
|
||||||
|
ek_leds[1].gpio = AT91_PIN_PB9;
|
||||||
|
}
|
||||||
|
|
||||||
|
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GPIO Buttons
|
* GPIO Buttons
|
||||||
|
@ -336,15 +387,15 @@ static void __init ek_board_init(void)
|
||||||
/* NAND */
|
/* NAND */
|
||||||
ek_add_device_nand();
|
ek_add_device_nand();
|
||||||
/* Ethernet */
|
/* Ethernet */
|
||||||
at91_add_device_eth(&ek_macb_data);
|
ek_add_device_macb();
|
||||||
/* Regulators */
|
/* Regulators */
|
||||||
ek_add_regulators();
|
ek_add_regulators();
|
||||||
/* MMC */
|
/* MMC */
|
||||||
at91_add_device_mmc(0, &ek_mmc_data);
|
ek_add_device_mmc();
|
||||||
/* I2C */
|
/* I2C */
|
||||||
at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
|
at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
|
||||||
/* LEDs */
|
/* LEDs */
|
||||||
at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds));
|
ek_add_device_gpio_leds();
|
||||||
/* Push Buttons */
|
/* Push Buttons */
|
||||||
ek_add_device_buttons();
|
ek_add_device_buttons();
|
||||||
/* PCK0 provides MCLK to the WM8731 */
|
/* PCK0 provides MCLK to the WM8731 */
|
||||||
|
@ -355,8 +406,15 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
|
MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
|
||||||
/* Maintainer: Atmel */
|
/* Maintainer: Atmel */
|
||||||
.phys_io = AT91_BASE_SYS,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
.timer = &at91sam926x_timer,
|
||||||
|
.map_io = ek_map_io,
|
||||||
|
.init_irq = ek_init_irq,
|
||||||
|
.init_machine = ek_board_init,
|
||||||
|
MACHINE_END
|
||||||
|
|
||||||
|
MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
|
||||||
|
/* Maintainer: Atmel */
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -135,7 +135,7 @@ static struct atmel_nand_data __initdata ek_nand_data = {
|
||||||
.rdy_pin = AT91_PIN_PC8,
|
.rdy_pin = AT91_PIN_PC8,
|
||||||
.enable_pin = AT91_PIN_PC14,
|
.enable_pin = AT91_PIN_PC14,
|
||||||
.partition_info = nand_partitions,
|
.partition_info = nand_partitions,
|
||||||
#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16)
|
#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16)
|
||||||
.bus_width_16 = 1,
|
.bus_width_16 = 1,
|
||||||
#else
|
#else
|
||||||
.bus_width_16 = 0,
|
.bus_width_16 = 0,
|
||||||
|
@ -399,10 +399,8 @@ static void __init ek_board_init(void)
|
||||||
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
|
at91_pwm_leds(ek_pwm_led, ARRAY_SIZE(ek_pwm_led));
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(AT91SAM9G45EKES, "Atmel AT91SAM9G45-EKES")
|
MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
|
||||||
/* Maintainer: Atmel */
|
/* Maintainer: Atmel */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -329,8 +329,6 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
|
MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
|
||||||
/* Maintainer: Atmel */
|
/* Maintainer: Atmel */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -177,8 +177,6 @@ static void __init snapper9260_board_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
|
MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = snapper9260_map_io,
|
.map_io = snapper9260_map_io,
|
||||||
|
|
|
@ -294,8 +294,6 @@ static void __init stamp9g20_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(PORTUXG20, "taskit PortuxG20")
|
MACHINE_START(PORTUXG20, "taskit PortuxG20")
|
||||||
/* Maintainer: taskit GmbH */
|
/* Maintainer: taskit GmbH */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = portuxg20_map_io,
|
.map_io = portuxg20_map_io,
|
||||||
|
@ -305,8 +303,6 @@ MACHINE_END
|
||||||
|
|
||||||
MACHINE_START(STAMP9G20, "taskit Stamp9G20")
|
MACHINE_START(STAMP9G20, "taskit Stamp9G20")
|
||||||
/* Maintainer: taskit GmbH */
|
/* Maintainer: taskit GmbH */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = stamp9g20_map_io,
|
.map_io = stamp9g20_map_io,
|
||||||
|
|
|
@ -228,8 +228,6 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(USB_A9260, "CALAO USB_A9260")
|
MACHINE_START(USB_A9260, "CALAO USB_A9260")
|
||||||
/* Maintainer: calao-systems */
|
/* Maintainer: calao-systems */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -244,8 +244,6 @@ static void __init ek_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(USB_A9263, "CALAO USB_A9263")
|
MACHINE_START(USB_A9263, "CALAO USB_A9263")
|
||||||
/* Maintainer: calao-systems */
|
/* Maintainer: calao-systems */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91sam926x_timer,
|
.timer = &at91sam926x_timer,
|
||||||
.map_io = ek_map_io,
|
.map_io = ek_map_io,
|
||||||
|
|
|
@ -594,8 +594,6 @@ static void __init yl9200_board_init(void)
|
||||||
|
|
||||||
MACHINE_START(YL9200, "uCdragon YL-9200")
|
MACHINE_START(YL9200, "uCdragon YL-9200")
|
||||||
/* Maintainer: S.Birtles */
|
/* Maintainer: S.Birtles */
|
||||||
.phys_io = AT91_BASE_SYS,
|
|
||||||
.io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc,
|
|
||||||
.boot_params = AT91_SDRAM_BASE + 0x100,
|
.boot_params = AT91_SDRAM_BASE + 0x100,
|
||||||
.timer = &at91rm9200_timer,
|
.timer = &at91rm9200_timer,
|
||||||
.map_io = yl9200_map_io,
|
.map_io = yl9200_map_io,
|
||||||
|
|
|
@ -52,4 +52,10 @@
|
||||||
#define AT91_DBGU_CIDR (AT91_SF + 0) /* CIDR in PS segment */
|
#define AT91_DBGU_CIDR (AT91_SF + 0) /* CIDR in PS segment */
|
||||||
#define AT91_DBGU_EXID (AT91_SF + 4) /* EXID in PS segment */
|
#define AT91_DBGU_EXID (AT91_SF + 4) /* EXID in PS segment */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support defines for the simple Power Controller module.
|
||||||
|
*/
|
||||||
|
#define AT91_PS_CR (AT91_PS + 0) /* PS Control register */
|
||||||
|
#define AT91_PS_CR_CPU (1 << 0) /* CPU clock disable bit */
|
||||||
|
|
||||||
#endif /* AT91X40_H */
|
#endif /* AT91X40_H */
|
||||||
|
|
|
@ -14,11 +14,9 @@
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <mach/at91_dbgu.h>
|
#include <mach/at91_dbgu.h>
|
||||||
|
|
||||||
.macro addruart, rx, tmp
|
.macro addruart, rp, rv
|
||||||
mrc p15, 0, \rx, c1, c0
|
ldr \rp, =(AT91_BASE_SYS + AT91_DBGU) @ System peripherals (phys address)
|
||||||
tst \rx, #1 @ MMU enabled?
|
ldr \rv, =(AT91_VA_BASE_SYS + AT91_DBGU) @ System peripherals (virt address)
|
||||||
ldreq \rx, =(AT91_BASE_SYS + AT91_DBGU) @ System peripherals (phys address)
|
|
||||||
ldrne \rx, =(AT91_VA_BASE_SYS + AT91_DBGU) @ System peripherals (virt address)
|
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.macro senduart,rd,rx
|
.macro senduart,rd,rx
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue