mirror of
https://github.com/torvalds/linux.git
synced 2024-12-06 02:52:22 +00:00
Merge branch 'msm-core' of git://codeaurora.org/quic/kernel/dwalker/linux-msm into devel-stable
This commit is contained in:
commit
3c00079b31
@ -6,6 +6,8 @@ Interrupts
|
||||
- ARM Interrupt subsystem documentation
|
||||
IXP2000
|
||||
- Release Notes for Linux on Intel's IXP2000 Network Processor
|
||||
msm
|
||||
- MSM specific documentation
|
||||
Netwinder
|
||||
- Netwinder specific documentation
|
||||
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.
|
@ -10,6 +10,8 @@ config ARCH_MSM7X00A
|
||||
select MSM_SMD
|
||||
select MSM_SMD_PKG3
|
||||
select CPU_V6
|
||||
select MSM_PROC_COMM
|
||||
select HAS_MSM_DEBUG_UART_PHYS
|
||||
|
||||
config ARCH_MSM7X30
|
||||
bool "MSM7x30"
|
||||
@ -18,6 +20,9 @@ config ARCH_MSM7X30
|
||||
select MSM_VIC
|
||||
select CPU_V7
|
||||
select MSM_REMOTE_SPINLOCK_DEKKERS
|
||||
select MSM_GPIOMUX
|
||||
select MSM_PROC_COMM
|
||||
select HAS_MSM_DEBUG_UART_PHYS
|
||||
|
||||
config ARCH_QSD8X50
|
||||
bool "QSD8X50"
|
||||
@ -26,6 +31,19 @@ config ARCH_QSD8X50
|
||||
select MSM_VIC
|
||||
select CPU_V7
|
||||
select MSM_REMOTE_SPINLOCK_LDREX
|
||||
select MSM_GPIOMUX
|
||||
select MSM_PROC_COMM
|
||||
select HAS_MSM_DEBUG_UART_PHYS
|
||||
|
||||
config ARCH_MSM8X60
|
||||
bool "MSM8X60"
|
||||
select ARM_GIC
|
||||
select CPU_V7
|
||||
select MSM_V2_TLMM
|
||||
select MSM_GPIOMUX
|
||||
select MACH_MSM8X60_SURF if (!MACH_MSM8X60_RUMI3 && !MACH_MSM8X60_SIM \
|
||||
&& !MACH_MSM8X60_FFA)
|
||||
|
||||
endchoice
|
||||
|
||||
config MSM_SOC_REV_A
|
||||
@ -36,6 +54,9 @@ config ARCH_MSM_ARM11
|
||||
config ARCH_MSM_SCORPION
|
||||
bool
|
||||
|
||||
config HAS_MSM_DEBUG_UART_PHYS
|
||||
bool
|
||||
|
||||
config MSM_VIC
|
||||
bool
|
||||
|
||||
@ -74,6 +95,30 @@ config MACH_QSD8X50A_ST1_5
|
||||
help
|
||||
Support for the Qualcomm ST1.5.
|
||||
|
||||
config MACH_MSM8X60_RUMI3
|
||||
depends on ARCH_MSM8X60
|
||||
bool "MSM8x60 RUMI3"
|
||||
help
|
||||
Support for the Qualcomm MSM8x60 RUMI3 emulator.
|
||||
|
||||
config MACH_MSM8X60_SURF
|
||||
depends on ARCH_MSM8X60
|
||||
bool "MSM8x60 SURF"
|
||||
help
|
||||
Support for the Qualcomm MSM8x60 SURF eval board.
|
||||
|
||||
config MACH_MSM8X60_SIM
|
||||
depends on ARCH_MSM8X60
|
||||
bool "MSM8x60 Simulator"
|
||||
help
|
||||
Support for the Qualcomm MSM8x60 simulator.
|
||||
|
||||
config MACH_MSM8X60_FFA
|
||||
depends on ARCH_MSM8X60
|
||||
bool "MSM8x60 FFA"
|
||||
help
|
||||
Support for the Qualcomm MSM8x60 FFA eval board.
|
||||
|
||||
endmenu
|
||||
|
||||
config MSM_DEBUG_UART
|
||||
@ -82,6 +127,7 @@ config MSM_DEBUG_UART
|
||||
default 2 if MSM_DEBUG_UART2
|
||||
default 3 if MSM_DEBUG_UART3
|
||||
|
||||
if HAS_MSM_DEBUG_UART_PHYS
|
||||
choice
|
||||
prompt "Debug UART"
|
||||
|
||||
@ -99,11 +145,20 @@ choice
|
||||
config MSM_DEBUG_UART3
|
||||
bool "UART3"
|
||||
endchoice
|
||||
endif
|
||||
|
||||
config MSM_SMD_PKG3
|
||||
bool
|
||||
|
||||
config MSM_PROC_COMM
|
||||
bool
|
||||
|
||||
config MSM_SMD
|
||||
bool
|
||||
|
||||
config MSM_GPIOMUX
|
||||
bool
|
||||
|
||||
config MSM_V2_TLMM
|
||||
bool
|
||||
endif
|
||||
|
@ -1,16 +1,20 @@
|
||||
obj-y += proc_comm.o
|
||||
obj-y += io.o idle.o timer.o dma.o
|
||||
obj-y += vreg.o
|
||||
obj-y += io.o idle.o timer.o
|
||||
ifndef CONFIG_ARCH_MSM8X60
|
||||
obj-y += acpuclock-arm11.o
|
||||
obj-y += clock.o clock-pcom.o
|
||||
obj-y += gpio.o
|
||||
obj-y += dma.o
|
||||
endif
|
||||
|
||||
ifdef CONFIG_MSM_VIC
|
||||
obj-y += irq-vic.o
|
||||
else
|
||||
ifndef CONFIG_ARCH_MSM8X60
|
||||
obj-y += irq.o
|
||||
endif
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o iommu.o iommu_dev.o devices-msm8x60-iommu.o
|
||||
obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
|
||||
obj-$(CONFIG_MSM_PROC_COMM) += clock.o
|
||||
obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
|
||||
obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
|
||||
obj-$(CONFIG_MSM_SMD) += last_radio_log.o
|
||||
@ -19,4 +23,11 @@ obj-$(CONFIG_MACH_TROUT) += board-trout.o board-trout-gpio.o board-trout-mmc.o d
|
||||
obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o devices-msm7x00.o
|
||||
obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
|
||||
obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
|
||||
obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
|
||||
|
||||
obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
|
||||
obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
|
||||
obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
|
||||
ifndef CONFIG_MSM_V2_TLMM
|
||||
obj-y += gpio.o
|
||||
endif
|
||||
|
@ -39,27 +39,11 @@
|
||||
|
||||
extern struct sys_timer msm_timer;
|
||||
|
||||
#ifdef CONFIG_SERIAL_MSM_CONSOLE
|
||||
static struct msm_gpio uart2_config_data[] = {
|
||||
{ GPIO_CFG(49, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_RFR"},
|
||||
{ GPIO_CFG(50, 2, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_CTS"},
|
||||
{ GPIO_CFG(51, 2, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"},
|
||||
{ GPIO_CFG(52, 2, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"},
|
||||
};
|
||||
|
||||
static void msm7x30_init_uart2(void)
|
||||
{
|
||||
msm_gpios_request_enable(uart2_config_data,
|
||||
ARRAY_SIZE(uart2_config_data));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
#if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
|
||||
&msm_device_uart2,
|
||||
#endif
|
||||
|
||||
&msm_device_smd,
|
||||
};
|
||||
|
||||
static void __init msm7x30_init_irq(void)
|
||||
@ -70,10 +54,6 @@ static void __init msm7x30_init_irq(void)
|
||||
static void __init msm7x30_init(void)
|
||||
{
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
#ifdef CONFIG_SERIAL_MSM_CONSOLE
|
||||
msm7x30_init_uart2();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void __init msm7x30_map_io(void)
|
||||
|
100
arch/arm/mach-msm/board-msm8x60.c
Normal file
100
arch/arm/mach-msm/board-msm8x60.c
Normal file
@ -0,0 +1,100 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
#include <mach/board.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
|
||||
void __iomem *gic_cpu_base_addr;
|
||||
|
||||
unsigned long clk_get_max_axi_khz(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init msm8x60_map_io(void)
|
||||
{
|
||||
msm_map_msm8x60_io();
|
||||
}
|
||||
|
||||
static void __init msm8x60_init_irq(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
|
||||
gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
|
||||
gic_cpu_init(0, MSM_QGIC_CPU_BASE);
|
||||
|
||||
/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
|
||||
writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
|
||||
|
||||
/* RUMI does not adhere to GIC spec by enabling STIs by default.
|
||||
* Enable/clear is supposed to be RO for STIs, but is RW on RUMI.
|
||||
*/
|
||||
if (!machine_is_msm8x60_sim())
|
||||
writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
|
||||
|
||||
/* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
|
||||
* as they are configured as level, which does not play nice with
|
||||
* handle_percpu_irq.
|
||||
*/
|
||||
for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
|
||||
if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
|
||||
set_irq_handler(i, handle_percpu_irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init msm8x60_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
|
||||
.map_io = msm8x60_map_io,
|
||||
.init_irq = msm8x60_init_irq,
|
||||
.init_machine = msm8x60_init,
|
||||
.timer = &msm_timer,
|
||||
MACHINE_END
|
||||
|
||||
MACHINE_START(MSM8X60_SURF, "QCT MSM8X60 SURF")
|
||||
.map_io = msm8x60_map_io,
|
||||
.init_irq = msm8x60_init_irq,
|
||||
.init_machine = msm8x60_init,
|
||||
.timer = &msm_timer,
|
||||
MACHINE_END
|
||||
|
||||
MACHINE_START(MSM8X60_SIM, "QCT MSM8X60 SIMULATOR")
|
||||
.map_io = msm8x60_map_io,
|
||||
.init_irq = msm8x60_init_irq,
|
||||
.init_machine = msm8x60_init,
|
||||
.timer = &msm_timer,
|
||||
MACHINE_END
|
||||
|
||||
MACHINE_START(MSM8X60_FFA, "QCT MSM8X60 FFA")
|
||||
.map_io = msm8x60_map_io,
|
||||
.init_irq = msm8x60_init_irq,
|
||||
.init_machine = msm8x60_init,
|
||||
.timer = &msm_timer,
|
||||
MACHINE_END
|
@ -35,21 +35,50 @@
|
||||
|
||||
extern struct sys_timer msm_timer;
|
||||
|
||||
static struct msm_gpio uart3_config_data[] = {
|
||||
{ GPIO_CFG(86, 1, GPIO_INPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Rx"},
|
||||
{ GPIO_CFG(87, 1, GPIO_OUTPUT, GPIO_PULL_DOWN, GPIO_2MA), "UART2_Tx"},
|
||||
static const resource_size_t qsd8x50_surf_smc91x_base __initdata = 0x70000300;
|
||||
static const unsigned qsd8x50_surf_smc91x_gpio __initdata = 156;
|
||||
|
||||
/* Leave smc91x resources empty here, as we'll fill them in
|
||||
* at run-time: they vary from board to board, and the true
|
||||
* configuration won't be known until boot.
|
||||
*/
|
||||
static struct resource smc91x_resources[] __initdata = {
|
||||
[0] = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device smc91x_device __initdata = {
|
||||
.name = "smc91x",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(smc91x_resources),
|
||||
.resource = smc91x_resources,
|
||||
};
|
||||
|
||||
static int __init msm_init_smc91x(void)
|
||||
{
|
||||
if (machine_is_qsd8x50_surf()) {
|
||||
smc91x_resources[0].start = qsd8x50_surf_smc91x_base;
|
||||
smc91x_resources[0].end = qsd8x50_surf_smc91x_base + 0xff;
|
||||
smc91x_resources[1].start =
|
||||
gpio_to_irq(qsd8x50_surf_smc91x_gpio);
|
||||
smc91x_resources[1].end =
|
||||
gpio_to_irq(qsd8x50_surf_smc91x_gpio);
|
||||
platform_device_register(&smc91x_device);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(msm_init_smc91x);
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&msm_device_uart3,
|
||||
&msm_device_smd,
|
||||
};
|
||||
|
||||
static void msm8x50_init_uart3(void)
|
||||
{
|
||||
msm_gpios_request_enable(uart3_config_data,
|
||||
ARRAY_SIZE(uart3_config_data));
|
||||
}
|
||||
|
||||
static void __init qsd8x50_map_io(void)
|
||||
{
|
||||
msm_map_qsd8x50_io();
|
||||
@ -64,7 +93,6 @@ static void __init qsd8x50_init_irq(void)
|
||||
|
||||
static void __init qsd8x50_init(void)
|
||||
{
|
||||
msm8x50_init_uart3();
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
||||
|
54
arch/arm/mach-msm/clock-dummy.c
Normal file
54
arch/arm/mach-msm/clock-dummy.c
Normal file
@ -0,0 +1,54 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
struct clk *clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get);
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_enable);
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_rate);
|
||||
|
||||
void clk_put(struct clk *clk)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL(clk_put);
|
@ -51,6 +51,11 @@ struct platform_device msm_device_uart2 = {
|
||||
.resource = resources_uart2,
|
||||
};
|
||||
|
||||
struct platform_device msm_device_smd = {
|
||||
.name = "msm_smd",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
struct clk msm_clocks_7x30[] = {
|
||||
CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
|
||||
CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
|
||||
|
883
arch/arm/mach-msm/devices-msm8x60-iommu.c
Normal file
883
arch/arm/mach-msm/devices-msm8x60-iommu.c
Normal file
@ -0,0 +1,883 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/bootmem.h>
|
||||
|
||||
#include <mach/msm_iomap-8x60.h>
|
||||
#include <mach/irqs-8x60.h>
|
||||
#include <mach/iommu.h>
|
||||
|
||||
static struct resource msm_iommu_jpegd_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_JPEGD_PHYS,
|
||||
.end = MSM_IOMMU_JPEGD_PHYS + MSM_IOMMU_JPEGD_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_JPEGD_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_JPEGD_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_vpe_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_VPE_PHYS,
|
||||
.end = MSM_IOMMU_VPE_PHYS + MSM_IOMMU_VPE_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_VPE_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_VPE_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_mdp0_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_MDP0_PHYS,
|
||||
.end = MSM_IOMMU_MDP0_PHYS + MSM_IOMMU_MDP0_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_MDP0_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_MDP0_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_mdp1_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_MDP1_PHYS,
|
||||
.end = MSM_IOMMU_MDP1_PHYS + MSM_IOMMU_MDP1_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_MDP1_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_MDP1_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_rot_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_ROT_PHYS,
|
||||
.end = MSM_IOMMU_ROT_PHYS + MSM_IOMMU_ROT_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_ROT_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_ROT_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_ijpeg_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_IJPEG_PHYS,
|
||||
.end = MSM_IOMMU_IJPEG_PHYS + MSM_IOMMU_IJPEG_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_IJPEG_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_IJPEG_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_vfe_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_VFE_PHYS,
|
||||
.end = MSM_IOMMU_VFE_PHYS + MSM_IOMMU_VFE_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_VFE_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_VFE_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_vcodec_a_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_VCODEC_A_PHYS,
|
||||
.end = MSM_IOMMU_VCODEC_A_PHYS + MSM_IOMMU_VCODEC_A_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_vcodec_b_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_VCODEC_B_PHYS,
|
||||
.end = MSM_IOMMU_VCODEC_B_PHYS + MSM_IOMMU_VCODEC_B_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_gfx3d_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_GFX3D_PHYS,
|
||||
.end = MSM_IOMMU_GFX3D_PHYS + MSM_IOMMU_GFX3D_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_GFX3D_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_GFX3D_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource msm_iommu_gfx2d0_resources[] = {
|
||||
{
|
||||
.start = MSM_IOMMU_GFX2D0_PHYS,
|
||||
.end = MSM_IOMMU_GFX2D0_PHYS + MSM_IOMMU_GFX2D0_SIZE - 1,
|
||||
.name = "physbase",
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "nonsecure_irq",
|
||||
.start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
|
||||
.end = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.name = "secure_irq",
|
||||
.start = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
|
||||
.end = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_root_iommu_dev = {
|
||||
.name = "msm_iommu",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev jpegd_smmu = {
|
||||
.name = "jpegd",
|
||||
.clk_rate = -1
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev vpe_smmu = {
|
||||
.name = "vpe"
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev mdp0_smmu = {
|
||||
.name = "mdp0"
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev mdp1_smmu = {
|
||||
.name = "mdp1"
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev rot_smmu = {
|
||||
.name = "rot"
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev ijpeg_smmu = {
|
||||
.name = "ijpeg"
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev vfe_smmu = {
|
||||
.name = "vfe",
|
||||
.clk_rate = -1
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev vcodec_a_smmu = {
|
||||
.name = "vcodec_a"
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev vcodec_b_smmu = {
|
||||
.name = "vcodec_b"
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev gfx3d_smmu = {
|
||||
.name = "gfx3d",
|
||||
.clk_rate = 27000000
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev gfx2d0_smmu = {
|
||||
.name = "gfx2d0",
|
||||
.clk_rate = 27000000
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_jpegd = {
|
||||
.name = "msm_iommu",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
|
||||
.resource = msm_iommu_jpegd_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_vpe = {
|
||||
.name = "msm_iommu",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
|
||||
.resource = msm_iommu_vpe_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_mdp0 = {
|
||||
.name = "msm_iommu",
|
||||
.id = 2,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
|
||||
.resource = msm_iommu_mdp0_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_mdp1 = {
|
||||
.name = "msm_iommu",
|
||||
.id = 3,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
|
||||
.resource = msm_iommu_mdp1_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_rot = {
|
||||
.name = "msm_iommu",
|
||||
.id = 4,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
|
||||
.resource = msm_iommu_rot_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_ijpeg = {
|
||||
.name = "msm_iommu",
|
||||
.id = 5,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
|
||||
.resource = msm_iommu_ijpeg_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_vfe = {
|
||||
.name = "msm_iommu",
|
||||
.id = 6,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
|
||||
.resource = msm_iommu_vfe_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_vcodec_a = {
|
||||
.name = "msm_iommu",
|
||||
.id = 7,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
|
||||
.resource = msm_iommu_vcodec_a_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_vcodec_b = {
|
||||
.name = "msm_iommu",
|
||||
.id = 8,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
|
||||
.resource = msm_iommu_vcodec_b_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_gfx3d = {
|
||||
.name = "msm_iommu",
|
||||
.id = 9,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
|
||||
.resource = msm_iommu_gfx3d_resources,
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_smmu_gfx2d0 = {
|
||||
.name = "msm_iommu",
|
||||
.id = 10,
|
||||
.dev = {
|
||||
.parent = &msm_root_iommu_dev.dev,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
|
||||
.resource = msm_iommu_gfx2d0_resources,
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev jpegd_src_ctx = {
|
||||
.name = "jpegd_src",
|
||||
.num = 0,
|
||||
.mids = {0, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev jpegd_dst_ctx = {
|
||||
.name = "jpegd_dst",
|
||||
.num = 1,
|
||||
.mids = {1, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev vpe_src_ctx = {
|
||||
.name = "vpe_src",
|
||||
.num = 0,
|
||||
.mids = {0, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev vpe_dst_ctx = {
|
||||
.name = "vpe_dst",
|
||||
.num = 1,
|
||||
.mids = {1, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev mdp_vg1_ctx = {
|
||||
.name = "mdp_vg1",
|
||||
.num = 0,
|
||||
.mids = {0, 2, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev mdp_rgb1_ctx = {
|
||||
.name = "mdp_rgb1",
|
||||
.num = 1,
|
||||
.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev mdp_vg2_ctx = {
|
||||
.name = "mdp_vg2",
|
||||
.num = 0,
|
||||
.mids = {0, 2, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev mdp_rgb2_ctx = {
|
||||
.name = "mdp_rgb2",
|
||||
.num = 1,
|
||||
.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev rot_src_ctx = {
|
||||
.name = "rot_src",
|
||||
.num = 0,
|
||||
.mids = {0, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev rot_dst_ctx = {
|
||||
.name = "rot_dst",
|
||||
.num = 1,
|
||||
.mids = {1, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev ijpeg_src_ctx = {
|
||||
.name = "ijpeg_src",
|
||||
.num = 0,
|
||||
.mids = {0, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev ijpeg_dst_ctx = {
|
||||
.name = "ijpeg_dst",
|
||||
.num = 1,
|
||||
.mids = {1, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev vfe_imgwr_ctx = {
|
||||
.name = "vfe_imgwr",
|
||||
.num = 0,
|
||||
.mids = {2, 3, 4, 5, 6, 7, 8, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev vfe_misc_ctx = {
|
||||
.name = "vfe_misc",
|
||||
.num = 1,
|
||||
.mids = {0, 1, 9, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = {
|
||||
.name = "vcodec_a_stream",
|
||||
.num = 0,
|
||||
.mids = {2, 5, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = {
|
||||
.name = "vcodec_a_mm1",
|
||||
.num = 1,
|
||||
.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = {
|
||||
.name = "vcodec_b_mm2",
|
||||
.num = 0,
|
||||
.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev gfx3d_rbpa_ctx = {
|
||||
.name = "gfx3d_rbpa",
|
||||
.num = 0,
|
||||
.mids = {-1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev gfx3d_cpvgttc_ctx = {
|
||||
.name = "gfx3d_cpvgttc",
|
||||
.num = 1,
|
||||
.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev gfx3d_smmu_ctx = {
|
||||
.name = "gfx3d_smmu",
|
||||
.num = 2,
|
||||
.mids = {8, 9, 10, 11, 12, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev gfx2d0_pixv1_ctx = {
|
||||
.name = "gfx2d0_pixv1_smmu",
|
||||
.num = 0,
|
||||
.mids = {0, 3, 4, -1}
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev gfx2d0_texv3_ctx = {
|
||||
.name = "gfx2d0_texv3_smmu",
|
||||
.num = 1,
|
||||
.mids = {1, 6, 7, -1}
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_jpegd_src_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_jpegd.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_jpegd_dst_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_jpegd.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_vpe_src_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 2,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_vpe.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_vpe_dst_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 3,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_vpe.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_mdp_vg1_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 4,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_mdp0.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_mdp_rgb1_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 5,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_mdp0.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_mdp_vg2_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 6,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_mdp1.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_mdp_rgb2_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 7,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_mdp1.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_rot_src_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 8,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_rot.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_rot_dst_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 9,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_rot.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_ijpeg_src_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 10,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_ijpeg.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_ijpeg_dst_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 11,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_ijpeg.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_vfe_imgwr_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 12,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_vfe.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_vfe_misc_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 13,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_vfe.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_vcodec_a_stream_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 14,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_vcodec_a.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_vcodec_a_mm1_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 15,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_vcodec_a.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_vcodec_b_mm2_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 16,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_vcodec_b.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_gfx3d_rbpa_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 17,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_gfx3d.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_gfx3d_cpvgttc_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 18,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_gfx3d.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_gfx3d_smmu_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 19,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_gfx3d.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_gfx2d0_pixv1_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 20,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_gfx2d0.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device msm_device_gfx2d0_texv3_ctx = {
|
||||
.name = "msm_iommu_ctx",
|
||||
.id = 21,
|
||||
.dev = {
|
||||
.parent = &msm_device_smmu_gfx2d0.dev,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device *msm_iommu_devs[] = {
|
||||
&msm_device_smmu_jpegd,
|
||||
&msm_device_smmu_vpe,
|
||||
&msm_device_smmu_mdp0,
|
||||
&msm_device_smmu_mdp1,
|
||||
&msm_device_smmu_rot,
|
||||
&msm_device_smmu_ijpeg,
|
||||
&msm_device_smmu_vfe,
|
||||
&msm_device_smmu_vcodec_a,
|
||||
&msm_device_smmu_vcodec_b,
|
||||
&msm_device_smmu_gfx3d,
|
||||
&msm_device_smmu_gfx2d0,
|
||||
};
|
||||
|
||||
static struct msm_iommu_dev *msm_iommu_data[] = {
|
||||
&jpegd_smmu,
|
||||
&vpe_smmu,
|
||||
&mdp0_smmu,
|
||||
&mdp1_smmu,
|
||||
&rot_smmu,
|
||||
&ijpeg_smmu,
|
||||
&vfe_smmu,
|
||||
&vcodec_a_smmu,
|
||||
&vcodec_b_smmu,
|
||||
&gfx3d_smmu,
|
||||
&gfx2d0_smmu,
|
||||
};
|
||||
|
||||
static struct platform_device *msm_iommu_ctx_devs[] = {
|
||||
&msm_device_jpegd_src_ctx,
|
||||
&msm_device_jpegd_dst_ctx,
|
||||
&msm_device_vpe_src_ctx,
|
||||
&msm_device_vpe_dst_ctx,
|
||||
&msm_device_mdp_vg1_ctx,
|
||||
&msm_device_mdp_rgb1_ctx,
|
||||
&msm_device_mdp_vg2_ctx,
|
||||
&msm_device_mdp_rgb2_ctx,
|
||||
&msm_device_rot_src_ctx,
|
||||
&msm_device_rot_dst_ctx,
|
||||
&msm_device_ijpeg_src_ctx,
|
||||
&msm_device_ijpeg_dst_ctx,
|
||||
&msm_device_vfe_imgwr_ctx,
|
||||
&msm_device_vfe_misc_ctx,
|
||||
&msm_device_vcodec_a_stream_ctx,
|
||||
&msm_device_vcodec_a_mm1_ctx,
|
||||
&msm_device_vcodec_b_mm2_ctx,
|
||||
&msm_device_gfx3d_rbpa_ctx,
|
||||
&msm_device_gfx3d_cpvgttc_ctx,
|
||||
&msm_device_gfx3d_smmu_ctx,
|
||||
&msm_device_gfx2d0_pixv1_ctx,
|
||||
&msm_device_gfx2d0_texv3_ctx,
|
||||
};
|
||||
|
||||
static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
|
||||
&jpegd_src_ctx,
|
||||
&jpegd_dst_ctx,
|
||||
&vpe_src_ctx,
|
||||
&vpe_dst_ctx,
|
||||
&mdp_vg1_ctx,
|
||||
&mdp_rgb1_ctx,
|
||||
&mdp_vg2_ctx,
|
||||
&mdp_rgb2_ctx,
|
||||
&rot_src_ctx,
|
||||
&rot_dst_ctx,
|
||||
&ijpeg_src_ctx,
|
||||
&ijpeg_dst_ctx,
|
||||
&vfe_imgwr_ctx,
|
||||
&vfe_misc_ctx,
|
||||
&vcodec_a_stream_ctx,
|
||||
&vcodec_a_mm1_ctx,
|
||||
&vcodec_b_mm2_ctx,
|
||||
&gfx3d_rbpa_ctx,
|
||||
&gfx3d_cpvgttc_ctx,
|
||||
&gfx3d_smmu_ctx,
|
||||
&gfx2d0_pixv1_ctx,
|
||||
&gfx2d0_texv3_ctx,
|
||||
};
|
||||
|
||||
static int msm8x60_iommu_init(void)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
ret = platform_device_register(&msm_root_iommu_dev);
|
||||
if (ret != 0) {
|
||||
pr_err("Failed to register root IOMMU device!\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
|
||||
ret = platform_device_add_data(msm_iommu_devs[i],
|
||||
msm_iommu_data[i],
|
||||
sizeof(struct msm_iommu_dev));
|
||||
if (ret != 0) {
|
||||
pr_err("platform_device_add_data failed, "
|
||||
"i = %d\n", i);
|
||||
goto failure_unwind;
|
||||
}
|
||||
|
||||
ret = platform_device_register(msm_iommu_devs[i]);
|
||||
|
||||
if (ret != 0) {
|
||||
pr_err("platform_device_register smmu failed, "
|
||||
"i = %d\n", i);
|
||||
goto failure_unwind;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
|
||||
ret = platform_device_add_data(msm_iommu_ctx_devs[i],
|
||||
msm_iommu_ctx_data[i],
|
||||
sizeof(*msm_iommu_ctx_devs[i]));
|
||||
if (ret != 0) {
|
||||
pr_err("platform_device_add_data smmu failed, "
|
||||
"i = %d\n", i);
|
||||
goto failure_unwind2;
|
||||
}
|
||||
|
||||
ret = platform_device_register(msm_iommu_ctx_devs[i]);
|
||||
if (ret != 0) {
|
||||
pr_err("platform_device_register ctx failed, "
|
||||
"i = %d\n", i);
|
||||
goto failure_unwind2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
failure_unwind2:
|
||||
while (--i >= 0)
|
||||
platform_device_unregister(msm_iommu_ctx_devs[i]);
|
||||
failure_unwind:
|
||||
while (--i >= 0)
|
||||
platform_device_unregister(msm_iommu_devs[i]);
|
||||
|
||||
platform_device_unregister(&msm_root_iommu_dev);
|
||||
failure:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void msm8x60_iommu_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
|
||||
platform_device_unregister(msm_iommu_ctx_devs[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
|
||||
platform_device_unregister(msm_iommu_devs[i]);
|
||||
|
||||
platform_device_unregister(&msm_root_iommu_dev);
|
||||
}
|
||||
|
||||
subsys_initcall(msm8x60_iommu_init);
|
||||
module_exit(msm8x60_iommu_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
|
@ -48,6 +48,11 @@ struct platform_device msm_device_uart3 = {
|
||||
.resource = resources_uart3,
|
||||
};
|
||||
|
||||
struct platform_device msm_device_smd = {
|
||||
.name = "msm_smd",
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
struct clk msm_clocks_8x50[] = {
|
||||
CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
|
||||
CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN),
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* linux/arch/arm/mach-msm/gpio.c
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
|
||||
* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
@ -14,72 +14,363 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/module.h>
|
||||
#include <mach/gpio.h>
|
||||
#include "proc_comm.h"
|
||||
#include "gpio_hw.h"
|
||||
#include "gpiomux.h"
|
||||
|
||||
int gpio_tlmm_config(unsigned config, unsigned disable)
|
||||
{
|
||||
return msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX, &config, &disable);
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_tlmm_config);
|
||||
#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
|
||||
|
||||
int msm_gpios_enable(const struct msm_gpio *table, int size)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
const struct msm_gpio *g;
|
||||
for (i = 0; i < size; i++) {
|
||||
g = table + i;
|
||||
rc = gpio_tlmm_config(g->gpio_cfg, GPIO_ENABLE);
|
||||
if (rc) {
|
||||
pr_err("gpio_tlmm_config(0x%08x, GPIO_ENABLE)"
|
||||
" <%s> failed: %d\n",
|
||||
g->gpio_cfg, g->label ?: "?", rc);
|
||||
pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
|
||||
GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
|
||||
GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
|
||||
GPIO_DRVSTR(g->gpio_cfg));
|
||||
goto err;
|
||||
}
|
||||
#define MSM_GPIO_BANK(bank, first, last) \
|
||||
{ \
|
||||
.regs = { \
|
||||
.out = MSM_GPIO_OUT_##bank, \
|
||||
.in = MSM_GPIO_IN_##bank, \
|
||||
.int_status = MSM_GPIO_INT_STATUS_##bank, \
|
||||
.int_clear = MSM_GPIO_INT_CLEAR_##bank, \
|
||||
.int_en = MSM_GPIO_INT_EN_##bank, \
|
||||
.int_edge = MSM_GPIO_INT_EDGE_##bank, \
|
||||
.int_pos = MSM_GPIO_INT_POS_##bank, \
|
||||
.oe = MSM_GPIO_OE_##bank, \
|
||||
}, \
|
||||
.chip = { \
|
||||
.base = (first), \
|
||||
.ngpio = (last) - (first) + 1, \
|
||||
.get = msm_gpio_get, \
|
||||
.set = msm_gpio_set, \
|
||||
.direction_input = msm_gpio_direction_input, \
|
||||
.direction_output = msm_gpio_direction_output, \
|
||||
.to_irq = msm_gpio_to_irq, \
|
||||
.request = msm_gpio_request, \
|
||||
.free = msm_gpio_free, \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MSM_GPIO_BROKEN_INT_CLEAR 1
|
||||
|
||||
struct msm_gpio_regs {
|
||||
void __iomem *out;
|
||||
void __iomem *in;
|
||||
void __iomem *int_status;
|
||||
void __iomem *int_clear;
|
||||
void __iomem *int_en;
|
||||
void __iomem *int_edge;
|
||||
void __iomem *int_pos;
|
||||
void __iomem *oe;
|
||||
};
|
||||
|
||||
struct msm_gpio_chip {
|
||||
spinlock_t lock;
|
||||
struct gpio_chip chip;
|
||||
struct msm_gpio_regs regs;
|
||||
#if MSM_GPIO_BROKEN_INT_CLEAR
|
||||
unsigned int_status_copy;
|
||||
#endif
|
||||
unsigned int both_edge_detect;
|
||||
unsigned int int_enable[2]; /* 0: awake, 1: sleep */
|
||||
};
|
||||
|
||||
static int msm_gpio_write(struct msm_gpio_chip *msm_chip,
|
||||
unsigned offset, unsigned on)
|
||||
{
|
||||
unsigned mask = BIT(offset);
|
||||
unsigned val;
|
||||
|
||||
val = readl(msm_chip->regs.out);
|
||||
if (on)
|
||||
writel(val | mask, msm_chip->regs.out);
|
||||
else
|
||||
writel(val & ~mask, msm_chip->regs.out);
|
||||
return 0;
|
||||
err:
|
||||
msm_gpios_disable(table, i);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpios_enable);
|
||||
|
||||
void msm_gpios_disable(const struct msm_gpio *table, int size)
|
||||
static void msm_gpio_update_both_edge_detect(struct msm_gpio_chip *msm_chip)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
const struct msm_gpio *g;
|
||||
for (i = size-1; i >= 0; i--) {
|
||||
g = table + i;
|
||||
rc = gpio_tlmm_config(g->gpio_cfg, GPIO_DISABLE);
|
||||
if (rc) {
|
||||
pr_err("gpio_tlmm_config(0x%08x, GPIO_DISABLE)"
|
||||
" <%s> failed: %d\n",
|
||||
g->gpio_cfg, g->label ?: "?", rc);
|
||||
pr_err("pin %d func %d dir %d pull %d drvstr %d\n",
|
||||
GPIO_PIN(g->gpio_cfg), GPIO_FUNC(g->gpio_cfg),
|
||||
GPIO_DIR(g->gpio_cfg), GPIO_PULL(g->gpio_cfg),
|
||||
GPIO_DRVSTR(g->gpio_cfg));
|
||||
int loop_limit = 100;
|
||||
unsigned pol, val, val2, intstat;
|
||||
do {
|
||||
val = readl(msm_chip->regs.in);
|
||||
pol = readl(msm_chip->regs.int_pos);
|
||||
pol = (pol & ~msm_chip->both_edge_detect) |
|
||||
(~val & msm_chip->both_edge_detect);
|
||||
writel(pol, msm_chip->regs.int_pos);
|
||||
intstat = readl(msm_chip->regs.int_status);
|
||||
val2 = readl(msm_chip->regs.in);
|
||||
if (((val ^ val2) & msm_chip->both_edge_detect & ~intstat) == 0)
|
||||
return;
|
||||
} while (loop_limit-- > 0);
|
||||
printk(KERN_ERR "msm_gpio_update_both_edge_detect, "
|
||||
"failed to reach stable state %x != %x\n", val, val2);
|
||||
}
|
||||
|
||||
static int msm_gpio_clear_detect_status(struct msm_gpio_chip *msm_chip,
|
||||
unsigned offset)
|
||||
{
|
||||
unsigned bit = BIT(offset);
|
||||
|
||||
#if MSM_GPIO_BROKEN_INT_CLEAR
|
||||
/* Save interrupts that already triggered before we loose them. */
|
||||
/* Any interrupt that triggers between the read of int_status */
|
||||
/* and the write to int_clear will still be lost though. */
|
||||
msm_chip->int_status_copy |= readl(msm_chip->regs.int_status);
|
||||
msm_chip->int_status_copy &= ~bit;
|
||||
#endif
|
||||
writel(bit, msm_chip->regs.int_clear);
|
||||
msm_gpio_update_both_edge_detect(msm_chip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct msm_gpio_chip *msm_chip;
|
||||
unsigned long irq_flags;
|
||||
|
||||
msm_chip = container_of(chip, struct msm_gpio_chip, chip);
|
||||
spin_lock_irqsave(&msm_chip->lock, irq_flags);
|
||||
writel(readl(msm_chip->regs.oe) & ~BIT(offset), msm_chip->regs.oe);
|
||||
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct msm_gpio_chip *msm_chip;
|
||||
unsigned long irq_flags;
|
||||
|
||||
msm_chip = container_of(chip, struct msm_gpio_chip, chip);
|
||||
spin_lock_irqsave(&msm_chip->lock, irq_flags);
|
||||
msm_gpio_write(msm_chip, offset, value);
|
||||
writel(readl(msm_chip->regs.oe) | BIT(offset), msm_chip->regs.oe);
|
||||
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct msm_gpio_chip *msm_chip;
|
||||
|
||||
msm_chip = container_of(chip, struct msm_gpio_chip, chip);
|
||||
return (readl(msm_chip->regs.in) & (1U << offset)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct msm_gpio_chip *msm_chip;
|
||||
unsigned long irq_flags;
|
||||
|
||||
msm_chip = container_of(chip, struct msm_gpio_chip, chip);
|
||||
spin_lock_irqsave(&msm_chip->lock, irq_flags);
|
||||
msm_gpio_write(msm_chip, offset, value);
|
||||
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
|
||||
}
|
||||
|
||||
static int msm_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return MSM_GPIO_TO_INT(chip->base + offset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MSM_GPIOMUX
|
||||
static int msm_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return msm_gpiomux_get(chip->base + offset);
|
||||
}
|
||||
|
||||
static void msm_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
msm_gpiomux_put(chip->base + offset);
|
||||
}
|
||||
#else
|
||||
#define msm_gpio_request NULL
|
||||
#define msm_gpio_free NULL
|
||||
#endif
|
||||
|
||||
struct msm_gpio_chip msm_gpio_chips[] = {
|
||||
#if defined(CONFIG_ARCH_MSM7X00A)
|
||||
MSM_GPIO_BANK(0, 0, 15),
|
||||
MSM_GPIO_BANK(1, 16, 42),
|
||||
MSM_GPIO_BANK(2, 43, 67),
|
||||
MSM_GPIO_BANK(3, 68, 94),
|
||||
MSM_GPIO_BANK(4, 95, 106),
|
||||
MSM_GPIO_BANK(5, 107, 121),
|
||||
#elif defined(CONFIG_ARCH_MSM7X25) || defined(CONFIG_ARCH_MSM7X27)
|
||||
MSM_GPIO_BANK(0, 0, 15),
|
||||
MSM_GPIO_BANK(1, 16, 42),
|
||||
MSM_GPIO_BANK(2, 43, 67),
|
||||
MSM_GPIO_BANK(3, 68, 94),
|
||||
MSM_GPIO_BANK(4, 95, 106),
|
||||
MSM_GPIO_BANK(5, 107, 132),
|
||||
#elif defined(CONFIG_ARCH_MSM7X30)
|
||||
MSM_GPIO_BANK(0, 0, 15),
|
||||
MSM_GPIO_BANK(1, 16, 43),
|
||||
MSM_GPIO_BANK(2, 44, 67),
|
||||
MSM_GPIO_BANK(3, 68, 94),
|
||||
MSM_GPIO_BANK(4, 95, 106),
|
||||
MSM_GPIO_BANK(5, 107, 133),
|
||||
MSM_GPIO_BANK(6, 134, 150),
|
||||
MSM_GPIO_BANK(7, 151, 181),
|
||||
#elif defined(CONFIG_ARCH_QSD8X50)
|
||||
MSM_GPIO_BANK(0, 0, 15),
|
||||
MSM_GPIO_BANK(1, 16, 42),
|
||||
MSM_GPIO_BANK(2, 43, 67),
|
||||
MSM_GPIO_BANK(3, 68, 94),
|
||||
MSM_GPIO_BANK(4, 95, 103),
|
||||
MSM_GPIO_BANK(5, 104, 121),
|
||||
MSM_GPIO_BANK(6, 122, 152),
|
||||
MSM_GPIO_BANK(7, 153, 164),
|
||||
#endif
|
||||
};
|
||||
|
||||
static void msm_gpio_irq_ack(unsigned int irq)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
|
||||
spin_lock_irqsave(&msm_chip->lock, irq_flags);
|
||||
msm_gpio_clear_detect_status(msm_chip,
|
||||
irq - gpio_to_irq(msm_chip->chip.base));
|
||||
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
|
||||
}
|
||||
|
||||
static void msm_gpio_irq_mask(unsigned int irq)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
|
||||
unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
|
||||
|
||||
spin_lock_irqsave(&msm_chip->lock, irq_flags);
|
||||
/* level triggered interrupts are also latched */
|
||||
if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
|
||||
msm_gpio_clear_detect_status(msm_chip, offset);
|
||||
msm_chip->int_enable[0] &= ~BIT(offset);
|
||||
writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
|
||||
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
|
||||
}
|
||||
|
||||
static void msm_gpio_irq_unmask(unsigned int irq)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
|
||||
unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
|
||||
|
||||
spin_lock_irqsave(&msm_chip->lock, irq_flags);
|
||||
/* level triggered interrupts are also latched */
|
||||
if (!(readl(msm_chip->regs.int_edge) & BIT(offset)))
|
||||
msm_gpio_clear_detect_status(msm_chip, offset);
|
||||
msm_chip->int_enable[0] |= BIT(offset);
|
||||
writel(msm_chip->int_enable[0], msm_chip->regs.int_en);
|
||||
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
|
||||
}
|
||||
|
||||
static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
|
||||
unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
|
||||
|
||||
spin_lock_irqsave(&msm_chip->lock, irq_flags);
|
||||
|
||||
if (on)
|
||||
msm_chip->int_enable[1] |= BIT(offset);
|
||||
else
|
||||
msm_chip->int_enable[1] &= ~BIT(offset);
|
||||
|
||||
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
struct msm_gpio_chip *msm_chip = get_irq_chip_data(irq);
|
||||
unsigned offset = irq - gpio_to_irq(msm_chip->chip.base);
|
||||
unsigned val, mask = BIT(offset);
|
||||
|
||||
spin_lock_irqsave(&msm_chip->lock, irq_flags);
|
||||
val = readl(msm_chip->regs.int_edge);
|
||||
if (flow_type & IRQ_TYPE_EDGE_BOTH) {
|
||||
writel(val | mask, msm_chip->regs.int_edge);
|
||||
irq_desc[irq].handle_irq = handle_edge_irq;
|
||||
} else {
|
||||
writel(val & ~mask, msm_chip->regs.int_edge);
|
||||
irq_desc[irq].handle_irq = handle_level_irq;
|
||||
}
|
||||
if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
|
||||
msm_chip->both_edge_detect |= mask;
|
||||
msm_gpio_update_both_edge_detect(msm_chip);
|
||||
} else {
|
||||
msm_chip->both_edge_detect &= ~mask;
|
||||
val = readl(msm_chip->regs.int_pos);
|
||||
if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
|
||||
writel(val | mask, msm_chip->regs.int_pos);
|
||||
else
|
||||
writel(val & ~mask, msm_chip->regs.int_pos);
|
||||
}
|
||||
spin_unlock_irqrestore(&msm_chip->lock, irq_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msm_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
int i, j, mask;
|
||||
unsigned val;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
|
||||
struct msm_gpio_chip *msm_chip = &msm_gpio_chips[i];
|
||||
val = readl(msm_chip->regs.int_status);
|
||||
val &= msm_chip->int_enable[0];
|
||||
while (val) {
|
||||
mask = val & -val;
|
||||
j = fls(mask) - 1;
|
||||
/* printk("%s %08x %08x bit %d gpio %d irq %d\n",
|
||||
__func__, v, m, j, msm_chip->chip.start + j,
|
||||
FIRST_GPIO_IRQ + msm_chip->chip.start + j); */
|
||||
val &= ~mask;
|
||||
generic_handle_irq(FIRST_GPIO_IRQ +
|
||||
msm_chip->chip.base + j);
|
||||
}
|
||||
}
|
||||
desc->chip->ack(irq);
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpios_disable);
|
||||
|
||||
int msm_gpios_request_enable(const struct msm_gpio *table, int size)
|
||||
{
|
||||
int rc = msm_gpios_enable(table, size);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpios_request_enable);
|
||||
static struct irq_chip msm_gpio_irq_chip = {
|
||||
.name = "msmgpio",
|
||||
.ack = msm_gpio_irq_ack,
|
||||
.mask = msm_gpio_irq_mask,
|
||||
.unmask = msm_gpio_irq_unmask,
|
||||
.set_wake = msm_gpio_irq_set_wake,
|
||||
.set_type = msm_gpio_irq_set_type,
|
||||
};
|
||||
|
||||
void msm_gpios_disable_free(const struct msm_gpio *table, int size)
|
||||
static int __init msm_init_gpio(void)
|
||||
{
|
||||
msm_gpios_disable(table, size);
|
||||
int i, j = 0;
|
||||
|
||||
for (i = FIRST_GPIO_IRQ; i < FIRST_GPIO_IRQ + NR_GPIO_IRQS; i++) {
|
||||
if (i - FIRST_GPIO_IRQ >=
|
||||
msm_gpio_chips[j].chip.base +
|
||||
msm_gpio_chips[j].chip.ngpio)
|
||||
j++;
|
||||
set_irq_chip_data(i, &msm_gpio_chips[j]);
|
||||
set_irq_chip(i, &msm_gpio_irq_chip);
|
||||
set_irq_handler(i, handle_edge_irq);
|
||||
set_irq_flags(i, IRQF_VALID);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msm_gpio_chips); i++) {
|
||||
spin_lock_init(&msm_gpio_chips[i].lock);
|
||||
writel(0, msm_gpio_chips[i].regs.int_en);
|
||||
gpiochip_add(&msm_gpio_chips[i].chip);
|
||||
}
|
||||
|
||||
set_irq_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
|
||||
set_irq_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
|
||||
set_irq_wake(INT_GPIO_GROUP1, 1);
|
||||
set_irq_wake(INT_GPIO_GROUP2, 2);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpios_disable_free);
|
||||
|
||||
postcore_initcall(msm_init_gpio);
|
||||
|
278
arch/arm/mach-msm/gpio_hw.h
Normal file
278
arch/arm/mach-msm/gpio_hw.h
Normal file
@ -0,0 +1,278 @@
|
||||
/* arch/arm/mach-msm/gpio_hw.h
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ARCH_ARM_MACH_MSM_GPIO_HW_H
|
||||
#define __ARCH_ARM_MACH_MSM_GPIO_HW_H
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
|
||||
/* see 80-VA736-2 Rev C pp 695-751
|
||||
**
|
||||
** These are actually the *shadow* gpio registers, since the
|
||||
** real ones (which allow full access) are only available to the
|
||||
** ARM9 side of the world.
|
||||
**
|
||||
** Since the _BASE need to be page-aligned when we're mapping them
|
||||
** to virtual addresses, adjust for the additional offset in these
|
||||
** macros.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + (off))
|
||||
#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0x400 + (off))
|
||||
#else
|
||||
#define MSM_GPIO1_REG(off) (MSM_GPIO1_BASE + 0x800 + (off))
|
||||
#define MSM_GPIO2_REG(off) (MSM_GPIO2_BASE + 0xC00 + (off))
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X25) ||\
|
||||
defined(CONFIG_ARCH_MSM7X27)
|
||||
|
||||
/* output value */
|
||||
#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
|
||||
#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 42-16 */
|
||||
#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-43 */
|
||||
#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
|
||||
#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */
|
||||
#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 107-121 */
|
||||
|
||||
/* same pin map as above, output enable */
|
||||
#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x10)
|
||||
#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
|
||||
#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x14)
|
||||
#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x18)
|
||||
#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x1C)
|
||||
#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x54)
|
||||
|
||||
/* same pin map as above, input read */
|
||||
#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x34)
|
||||
#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
|
||||
#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x38)
|
||||
#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x3C)
|
||||
#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x40)
|
||||
#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x44)
|
||||
|
||||
/* same pin map as above, 1=edge 0=level interrup */
|
||||
#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60)
|
||||
#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
|
||||
#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64)
|
||||
#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68)
|
||||
#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C)
|
||||
#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0)
|
||||
|
||||
/* same pin map as above, 1=positive 0=negative */
|
||||
#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
|
||||
#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
|
||||
#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
|
||||
#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
|
||||
#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
|
||||
#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
|
||||
|
||||
/* same pin map as above, interrupt enable */
|
||||
#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80)
|
||||
#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
|
||||
#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84)
|
||||
#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88)
|
||||
#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C)
|
||||
#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8)
|
||||
|
||||
/* same pin map as above, write 1 to clear interrupt */
|
||||
#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90)
|
||||
#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
|
||||
#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94)
|
||||
#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98)
|
||||
#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C)
|
||||
#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4)
|
||||
|
||||
/* same pin map as above, 1=interrupt pending */
|
||||
#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0)
|
||||
#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
|
||||
#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4)
|
||||
#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8)
|
||||
#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC)
|
||||
#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_QSD8X50)
|
||||
/* output value */
|
||||
#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
|
||||
#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 42-16 */
|
||||
#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-43 */
|
||||
#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
|
||||
#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 103-95 */
|
||||
#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x10) /* gpio 121-104 */
|
||||
#define MSM_GPIO_OUT_6 MSM_GPIO1_REG(0x14) /* gpio 152-122 */
|
||||
#define MSM_GPIO_OUT_7 MSM_GPIO1_REG(0x18) /* gpio 164-153 */
|
||||
|
||||
/* same pin map as above, output enable */
|
||||
#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x20)
|
||||
#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
|
||||
#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x24)
|
||||
#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x28)
|
||||
#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x2C)
|
||||
#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x30)
|
||||
#define MSM_GPIO_OE_6 MSM_GPIO1_REG(0x34)
|
||||
#define MSM_GPIO_OE_7 MSM_GPIO1_REG(0x38)
|
||||
|
||||
/* same pin map as above, input read */
|
||||
#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x50)
|
||||
#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
|
||||
#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x54)
|
||||
#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x58)
|
||||
#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x5C)
|
||||
#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x60)
|
||||
#define MSM_GPIO_IN_6 MSM_GPIO1_REG(0x64)
|
||||
#define MSM_GPIO_IN_7 MSM_GPIO1_REG(0x68)
|
||||
|
||||
/* same pin map as above, 1=edge 0=level interrup */
|
||||
#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x70)
|
||||
#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
|
||||
#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x74)
|
||||
#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x78)
|
||||
#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x7C)
|
||||
#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0x80)
|
||||
#define MSM_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0x84)
|
||||
#define MSM_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x88)
|
||||
|
||||
/* same pin map as above, 1=positive 0=negative */
|
||||
#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x90)
|
||||
#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
|
||||
#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x94)
|
||||
#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x98)
|
||||
#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x9C)
|
||||
#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xA0)
|
||||
#define MSM_GPIO_INT_POS_6 MSM_GPIO1_REG(0xA4)
|
||||
#define MSM_GPIO_INT_POS_7 MSM_GPIO1_REG(0xA8)
|
||||
|
||||
/* same pin map as above, interrupt enable */
|
||||
#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0xB0)
|
||||
#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
|
||||
#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0xB4)
|
||||
#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0xB8)
|
||||
#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0xBC)
|
||||
#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xC0)
|
||||
#define MSM_GPIO_INT_EN_6 MSM_GPIO1_REG(0xC4)
|
||||
#define MSM_GPIO_INT_EN_7 MSM_GPIO1_REG(0xC8)
|
||||
|
||||
/* same pin map as above, write 1 to clear interrupt */
|
||||
#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0xD0)
|
||||
#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
|
||||
#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0xD4)
|
||||
#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0xD8)
|
||||
#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0xDC)
|
||||
#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xE0)
|
||||
#define MSM_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xE4)
|
||||
#define MSM_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0xE8)
|
||||
|
||||
/* same pin map as above, 1=interrupt pending */
|
||||
#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xF0)
|
||||
#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
|
||||
#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xF4)
|
||||
#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xF8)
|
||||
#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xFC)
|
||||
#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0x100)
|
||||
#define MSM_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0x104)
|
||||
#define MSM_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x108)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
|
||||
/* output value */
|
||||
#define MSM_GPIO_OUT_0 MSM_GPIO1_REG(0x00) /* gpio 15-0 */
|
||||
#define MSM_GPIO_OUT_1 MSM_GPIO2_REG(0x00) /* gpio 43-16 */
|
||||
#define MSM_GPIO_OUT_2 MSM_GPIO1_REG(0x04) /* gpio 67-44 */
|
||||
#define MSM_GPIO_OUT_3 MSM_GPIO1_REG(0x08) /* gpio 94-68 */
|
||||
#define MSM_GPIO_OUT_4 MSM_GPIO1_REG(0x0C) /* gpio 106-95 */
|
||||
#define MSM_GPIO_OUT_5 MSM_GPIO1_REG(0x50) /* gpio 133-107 */
|
||||
#define MSM_GPIO_OUT_6 MSM_GPIO1_REG(0xC4) /* gpio 150-134 */
|
||||
#define MSM_GPIO_OUT_7 MSM_GPIO1_REG(0x214) /* gpio 181-151 */
|
||||
|
||||
/* same pin map as above, output enable */
|
||||
#define MSM_GPIO_OE_0 MSM_GPIO1_REG(0x10)
|
||||
#define MSM_GPIO_OE_1 MSM_GPIO2_REG(0x08)
|
||||
#define MSM_GPIO_OE_2 MSM_GPIO1_REG(0x14)
|
||||
#define MSM_GPIO_OE_3 MSM_GPIO1_REG(0x18)
|
||||
#define MSM_GPIO_OE_4 MSM_GPIO1_REG(0x1C)
|
||||
#define MSM_GPIO_OE_5 MSM_GPIO1_REG(0x54)
|
||||
#define MSM_GPIO_OE_6 MSM_GPIO1_REG(0xC8)
|
||||
#define MSM_GPIO_OE_7 MSM_GPIO1_REG(0x218)
|
||||
|
||||
/* same pin map as above, input read */
|
||||
#define MSM_GPIO_IN_0 MSM_GPIO1_REG(0x34)
|
||||
#define MSM_GPIO_IN_1 MSM_GPIO2_REG(0x20)
|
||||
#define MSM_GPIO_IN_2 MSM_GPIO1_REG(0x38)
|
||||
#define MSM_GPIO_IN_3 MSM_GPIO1_REG(0x3C)
|
||||
#define MSM_GPIO_IN_4 MSM_GPIO1_REG(0x40)
|
||||
#define MSM_GPIO_IN_5 MSM_GPIO1_REG(0x44)
|
||||
#define MSM_GPIO_IN_6 MSM_GPIO1_REG(0xCC)
|
||||
#define MSM_GPIO_IN_7 MSM_GPIO1_REG(0x21C)
|
||||
|
||||
/* same pin map as above, 1=edge 0=level interrup */
|
||||
#define MSM_GPIO_INT_EDGE_0 MSM_GPIO1_REG(0x60)
|
||||
#define MSM_GPIO_INT_EDGE_1 MSM_GPIO2_REG(0x50)
|
||||
#define MSM_GPIO_INT_EDGE_2 MSM_GPIO1_REG(0x64)
|
||||
#define MSM_GPIO_INT_EDGE_3 MSM_GPIO1_REG(0x68)
|
||||
#define MSM_GPIO_INT_EDGE_4 MSM_GPIO1_REG(0x6C)
|
||||
#define MSM_GPIO_INT_EDGE_5 MSM_GPIO1_REG(0xC0)
|
||||
#define MSM_GPIO_INT_EDGE_6 MSM_GPIO1_REG(0xD0)
|
||||
#define MSM_GPIO_INT_EDGE_7 MSM_GPIO1_REG(0x240)
|
||||
|
||||
/* same pin map as above, 1=positive 0=negative */
|
||||
#define MSM_GPIO_INT_POS_0 MSM_GPIO1_REG(0x70)
|
||||
#define MSM_GPIO_INT_POS_1 MSM_GPIO2_REG(0x58)
|
||||
#define MSM_GPIO_INT_POS_2 MSM_GPIO1_REG(0x74)
|
||||
#define MSM_GPIO_INT_POS_3 MSM_GPIO1_REG(0x78)
|
||||
#define MSM_GPIO_INT_POS_4 MSM_GPIO1_REG(0x7C)
|
||||
#define MSM_GPIO_INT_POS_5 MSM_GPIO1_REG(0xBC)
|
||||
#define MSM_GPIO_INT_POS_6 MSM_GPIO1_REG(0xD4)
|
||||
#define MSM_GPIO_INT_POS_7 MSM_GPIO1_REG(0x228)
|
||||
|
||||
/* same pin map as above, interrupt enable */
|
||||
#define MSM_GPIO_INT_EN_0 MSM_GPIO1_REG(0x80)
|
||||
#define MSM_GPIO_INT_EN_1 MSM_GPIO2_REG(0x60)
|
||||
#define MSM_GPIO_INT_EN_2 MSM_GPIO1_REG(0x84)
|
||||
#define MSM_GPIO_INT_EN_3 MSM_GPIO1_REG(0x88)
|
||||
#define MSM_GPIO_INT_EN_4 MSM_GPIO1_REG(0x8C)
|
||||
#define MSM_GPIO_INT_EN_5 MSM_GPIO1_REG(0xB8)
|
||||
#define MSM_GPIO_INT_EN_6 MSM_GPIO1_REG(0xD8)
|
||||
#define MSM_GPIO_INT_EN_7 MSM_GPIO1_REG(0x22C)
|
||||
|
||||
/* same pin map as above, write 1 to clear interrupt */
|
||||
#define MSM_GPIO_INT_CLEAR_0 MSM_GPIO1_REG(0x90)
|
||||
#define MSM_GPIO_INT_CLEAR_1 MSM_GPIO2_REG(0x68)
|
||||
#define MSM_GPIO_INT_CLEAR_2 MSM_GPIO1_REG(0x94)
|
||||
#define MSM_GPIO_INT_CLEAR_3 MSM_GPIO1_REG(0x98)
|
||||
#define MSM_GPIO_INT_CLEAR_4 MSM_GPIO1_REG(0x9C)
|
||||
#define MSM_GPIO_INT_CLEAR_5 MSM_GPIO1_REG(0xB4)
|
||||
#define MSM_GPIO_INT_CLEAR_6 MSM_GPIO1_REG(0xDC)
|
||||
#define MSM_GPIO_INT_CLEAR_7 MSM_GPIO1_REG(0x230)
|
||||
|
||||
/* same pin map as above, 1=interrupt pending */
|
||||
#define MSM_GPIO_INT_STATUS_0 MSM_GPIO1_REG(0xA0)
|
||||
#define MSM_GPIO_INT_STATUS_1 MSM_GPIO2_REG(0x70)
|
||||
#define MSM_GPIO_INT_STATUS_2 MSM_GPIO1_REG(0xA4)
|
||||
#define MSM_GPIO_INT_STATUS_3 MSM_GPIO1_REG(0xA8)
|
||||
#define MSM_GPIO_INT_STATUS_4 MSM_GPIO1_REG(0xAC)
|
||||
#define MSM_GPIO_INT_STATUS_5 MSM_GPIO1_REG(0xB0)
|
||||
#define MSM_GPIO_INT_STATUS_6 MSM_GPIO1_REG(0xE0)
|
||||
#define MSM_GPIO_INT_STATUS_7 MSM_GPIO1_REG(0x234)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
38
arch/arm/mach-msm/gpiomux-7x30.c
Normal file
38
arch/arm/mach-msm/gpiomux-7x30.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#include "gpiomux.h"
|
||||
|
||||
struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
|
||||
#ifdef CONFIG_SERIAL_MSM_CONSOLE
|
||||
[49] = { /* UART2 RFR */
|
||||
.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
|
||||
GPIOMUX_FUNC_2 | GPIOMUX_VALID,
|
||||
},
|
||||
[50] = { /* UART2 CTS */
|
||||
.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
|
||||
GPIOMUX_FUNC_2 | GPIOMUX_VALID,
|
||||
},
|
||||
[51] = { /* UART2 RX */
|
||||
.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
|
||||
GPIOMUX_FUNC_2 | GPIOMUX_VALID,
|
||||
},
|
||||
[52] = { /* UART2 TX */
|
||||
.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
|
||||
GPIOMUX_FUNC_2 | GPIOMUX_VALID,
|
||||
},
|
||||
#endif
|
||||
};
|
28
arch/arm/mach-msm/gpiomux-8x50.c
Normal file
28
arch/arm/mach-msm/gpiomux-8x50.c
Normal file
@ -0,0 +1,28 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#include "gpiomux.h"
|
||||
|
||||
struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
|
||||
[86] = { /* UART3 RX */
|
||||
.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
|
||||
GPIOMUX_FUNC_1 | GPIOMUX_VALID,
|
||||
},
|
||||
[87] = { /* UART3 TX */
|
||||
.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
|
||||
GPIOMUX_FUNC_1 | GPIOMUX_VALID,
|
||||
},
|
||||
};
|
19
arch/arm/mach-msm/gpiomux-8x60.c
Normal file
19
arch/arm/mach-msm/gpiomux-8x60.c
Normal file
@ -0,0 +1,19 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#include "gpiomux.h"
|
||||
|
||||
struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {};
|
33
arch/arm/mach-msm/gpiomux-v1.c
Normal file
33
arch/arm/mach-msm/gpiomux-v1.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include "gpiomux.h"
|
||||
#include "proc_comm.h"
|
||||
|
||||
void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
|
||||
{
|
||||
unsigned tlmm_config = (val & ~GPIOMUX_CTL_MASK) |
|
||||
((gpio & 0x3ff) << 4);
|
||||
unsigned tlmm_disable = 0;
|
||||
int rc;
|
||||
|
||||
rc = msm_proc_comm(PCOM_RPC_GPIO_TLMM_CONFIG_EX,
|
||||
&tlmm_config, &tlmm_disable);
|
||||
if (rc)
|
||||
pr_err("%s: unexpected proc_comm failure %d: %08x %08x\n",
|
||||
__func__, rc, tlmm_config, tlmm_disable);
|
||||
}
|
67
arch/arm/mach-msm/gpiomux-v1.h
Normal file
67
arch/arm/mach-msm/gpiomux-v1.h
Normal file
@ -0,0 +1,67 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
|
||||
#define __ARCH_ARM_MACH_MSM_GPIOMUX_V1_H
|
||||
|
||||
#if defined(CONFIG_ARCH_MSM7X30)
|
||||
#define GPIOMUX_NGPIOS 182
|
||||
#elif defined(CONFIG_ARCH_QSD8X50)
|
||||
#define GPIOMUX_NGPIOS 165
|
||||
#else
|
||||
#define GPIOMUX_NGPIOS 133
|
||||
#endif
|
||||
|
||||
typedef u32 gpiomux_config_t;
|
||||
|
||||
enum {
|
||||
GPIOMUX_DRV_2MA = 0UL << 17,
|
||||
GPIOMUX_DRV_4MA = 1UL << 17,
|
||||
GPIOMUX_DRV_6MA = 2UL << 17,
|
||||
GPIOMUX_DRV_8MA = 3UL << 17,
|
||||
GPIOMUX_DRV_10MA = 4UL << 17,
|
||||
GPIOMUX_DRV_12MA = 5UL << 17,
|
||||
GPIOMUX_DRV_14MA = 6UL << 17,
|
||||
GPIOMUX_DRV_16MA = 7UL << 17,
|
||||
};
|
||||
|
||||
enum {
|
||||
GPIOMUX_FUNC_GPIO = 0UL,
|
||||
GPIOMUX_FUNC_1 = 1UL,
|
||||
GPIOMUX_FUNC_2 = 2UL,
|
||||
GPIOMUX_FUNC_3 = 3UL,
|
||||
GPIOMUX_FUNC_4 = 4UL,
|
||||
GPIOMUX_FUNC_5 = 5UL,
|
||||
GPIOMUX_FUNC_6 = 6UL,
|
||||
GPIOMUX_FUNC_7 = 7UL,
|
||||
GPIOMUX_FUNC_8 = 8UL,
|
||||
GPIOMUX_FUNC_9 = 9UL,
|
||||
GPIOMUX_FUNC_A = 10UL,
|
||||
GPIOMUX_FUNC_B = 11UL,
|
||||
GPIOMUX_FUNC_C = 12UL,
|
||||
GPIOMUX_FUNC_D = 13UL,
|
||||
GPIOMUX_FUNC_E = 14UL,
|
||||
GPIOMUX_FUNC_F = 15UL,
|
||||
};
|
||||
|
||||
enum {
|
||||
GPIOMUX_PULL_NONE = 0UL << 15,
|
||||
GPIOMUX_PULL_DOWN = 1UL << 15,
|
||||
GPIOMUX_PULL_KEEPER = 2UL << 15,
|
||||
GPIOMUX_PULL_UP = 3UL << 15,
|
||||
};
|
||||
|
||||
#endif
|
25
arch/arm/mach-msm/gpiomux-v2.c
Normal file
25
arch/arm/mach-msm/gpiomux-v2.c
Normal file
@ -0,0 +1,25 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#include <linux/io.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include "gpiomux.h"
|
||||
|
||||
void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val)
|
||||
{
|
||||
writel(val & ~GPIOMUX_CTL_MASK,
|
||||
MSM_TLMM_BASE + 0x1000 + (0x10 * gpio));
|
||||
}
|
61
arch/arm/mach-msm/gpiomux-v2.h
Normal file
61
arch/arm/mach-msm/gpiomux-v2.h
Normal file
@ -0,0 +1,61 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
|
||||
#define __ARCH_ARM_MACH_MSM_GPIOMUX_V2_H
|
||||
|
||||
#define GPIOMUX_NGPIOS 173
|
||||
|
||||
typedef u16 gpiomux_config_t;
|
||||
|
||||
enum {
|
||||
GPIOMUX_DRV_2MA = 0UL << 6,
|
||||
GPIOMUX_DRV_4MA = 1UL << 6,
|
||||
GPIOMUX_DRV_6MA = 2UL << 6,
|
||||
GPIOMUX_DRV_8MA = 3UL << 6,
|
||||
GPIOMUX_DRV_10MA = 4UL << 6,
|
||||
GPIOMUX_DRV_12MA = 5UL << 6,
|
||||
GPIOMUX_DRV_14MA = 6UL << 6,
|
||||
GPIOMUX_DRV_16MA = 7UL << 6,
|
||||
};
|
||||
|
||||
enum {
|
||||
GPIOMUX_FUNC_GPIO = 0UL << 2,
|
||||
GPIOMUX_FUNC_1 = 1UL << 2,
|
||||
GPIOMUX_FUNC_2 = 2UL << 2,
|
||||
GPIOMUX_FUNC_3 = 3UL << 2,
|
||||
GPIOMUX_FUNC_4 = 4UL << 2,
|
||||
GPIOMUX_FUNC_5 = 5UL << 2,
|
||||
GPIOMUX_FUNC_6 = 6UL << 2,
|
||||
GPIOMUX_FUNC_7 = 7UL << 2,
|
||||
GPIOMUX_FUNC_8 = 8UL << 2,
|
||||
GPIOMUX_FUNC_9 = 9UL << 2,
|
||||
GPIOMUX_FUNC_A = 10UL << 2,
|
||||
GPIOMUX_FUNC_B = 11UL << 2,
|
||||
GPIOMUX_FUNC_C = 12UL << 2,
|
||||
GPIOMUX_FUNC_D = 13UL << 2,
|
||||
GPIOMUX_FUNC_E = 14UL << 2,
|
||||
GPIOMUX_FUNC_F = 15UL << 2,
|
||||
};
|
||||
|
||||
enum {
|
||||
GPIOMUX_PULL_NONE = 0UL,
|
||||
GPIOMUX_PULL_DOWN = 1UL,
|
||||
GPIOMUX_PULL_KEEPER = 2UL,
|
||||
GPIOMUX_PULL_UP = 3UL,
|
||||
};
|
||||
|
||||
#endif
|
96
arch/arm/mach-msm/gpiomux.c
Normal file
96
arch/arm/mach-msm/gpiomux.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "gpiomux.h"
|
||||
|
||||
static DEFINE_SPINLOCK(gpiomux_lock);
|
||||
|
||||
int msm_gpiomux_write(unsigned gpio,
|
||||
gpiomux_config_t active,
|
||||
gpiomux_config_t suspended)
|
||||
{
|
||||
struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
|
||||
unsigned long irq_flags;
|
||||
gpiomux_config_t setting;
|
||||
|
||||
if (gpio >= GPIOMUX_NGPIOS)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&gpiomux_lock, irq_flags);
|
||||
|
||||
if (active & GPIOMUX_VALID)
|
||||
cfg->active = active;
|
||||
|
||||
if (suspended & GPIOMUX_VALID)
|
||||
cfg->suspended = suspended;
|
||||
|
||||
setting = cfg->ref ? active : suspended;
|
||||
if (setting & GPIOMUX_VALID)
|
||||
__msm_gpiomux_write(gpio, setting);
|
||||
|
||||
spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpiomux_write);
|
||||
|
||||
int msm_gpiomux_get(unsigned gpio)
|
||||
{
|
||||
struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
|
||||
unsigned long irq_flags;
|
||||
|
||||
if (gpio >= GPIOMUX_NGPIOS)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&gpiomux_lock, irq_flags);
|
||||
if (cfg->ref++ == 0 && cfg->active & GPIOMUX_VALID)
|
||||
__msm_gpiomux_write(gpio, cfg->active);
|
||||
spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpiomux_get);
|
||||
|
||||
int msm_gpiomux_put(unsigned gpio)
|
||||
{
|
||||
struct msm_gpiomux_config *cfg = msm_gpiomux_configs + gpio;
|
||||
unsigned long irq_flags;
|
||||
|
||||
if (gpio >= GPIOMUX_NGPIOS)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&gpiomux_lock, irq_flags);
|
||||
BUG_ON(cfg->ref == 0);
|
||||
if (--cfg->ref == 0 && cfg->suspended & GPIOMUX_VALID)
|
||||
__msm_gpiomux_write(gpio, cfg->suspended);
|
||||
spin_unlock_irqrestore(&gpiomux_lock, irq_flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_gpiomux_put);
|
||||
|
||||
static int __init gpiomux_init(void)
|
||||
{
|
||||
unsigned n;
|
||||
|
||||
for (n = 0; n < GPIOMUX_NGPIOS; ++n) {
|
||||
msm_gpiomux_configs[n].ref = 0;
|
||||
if (!(msm_gpiomux_configs[n].suspended & GPIOMUX_VALID))
|
||||
continue;
|
||||
__msm_gpiomux_write(n, msm_gpiomux_configs[n].suspended);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
postcore_initcall(gpiomux_init);
|
114
arch/arm/mach-msm/gpiomux.h
Normal file
114
arch/arm/mach-msm/gpiomux.h
Normal file
@ -0,0 +1,114 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#ifndef __ARCH_ARM_MACH_MSM_GPIOMUX_H
|
||||
#define __ARCH_ARM_MACH_MSM_GPIOMUX_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#if defined(CONFIG_MSM_V2_TLMM)
|
||||
#include "gpiomux-v2.h"
|
||||
#else
|
||||
#include "gpiomux-v1.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct msm_gpiomux_config: gpiomux settings for one gpio line.
|
||||
*
|
||||
* A complete gpiomux config is the bitwise-or of a drive-strength,
|
||||
* function, and pull. For functions other than GPIO, the OE
|
||||
* is hard-wired according to the function. For GPIO mode,
|
||||
* OE is controlled by gpiolib.
|
||||
*
|
||||
* Available settings differ by target; see the gpiomux header
|
||||
* specific to your target arch for available configurations.
|
||||
*
|
||||
* @active: The configuration to be installed when the line is
|
||||
* active, or its reference count is > 0.
|
||||
* @suspended: The configuration to be installed when the line
|
||||
* is suspended, or its reference count is 0.
|
||||
* @ref: The reference count of the line. For internal use of
|
||||
* the gpiomux framework only.
|
||||
*/
|
||||
struct msm_gpiomux_config {
|
||||
gpiomux_config_t active;
|
||||
gpiomux_config_t suspended;
|
||||
unsigned ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* @GPIOMUX_VALID: If set, the config field contains 'good data'.
|
||||
* The absence of this bit will prevent the gpiomux
|
||||
* system from applying the configuration under all
|
||||
* circumstances.
|
||||
*/
|
||||
enum {
|
||||
GPIOMUX_VALID = BIT(sizeof(gpiomux_config_t) * BITS_PER_BYTE - 1),
|
||||
GPIOMUX_CTL_MASK = GPIOMUX_VALID,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MSM_GPIOMUX
|
||||
|
||||
/* Each architecture must provide its own instance of this table.
|
||||
* To avoid having gpiomux manage any given gpio, one or both of
|
||||
* the entries can avoid setting GPIOMUX_VALID - the absence
|
||||
* of that flag will prevent the configuration from being applied
|
||||
* during state transitions.
|
||||
*/
|
||||
extern struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS];
|
||||
|
||||
/* Increment a gpio's reference count, possibly activating the line. */
|
||||
int __must_check msm_gpiomux_get(unsigned gpio);
|
||||
|
||||
/* Decrement a gpio's reference count, possibly suspending the line. */
|
||||
int msm_gpiomux_put(unsigned gpio);
|
||||
|
||||
/* Install a new configuration to the gpio line. To avoid overwriting
|
||||
* a configuration, leave the VALID bit out.
|
||||
*/
|
||||
int msm_gpiomux_write(unsigned gpio,
|
||||
gpiomux_config_t active,
|
||||
gpiomux_config_t suspended);
|
||||
|
||||
/* Architecture-internal function for use by the framework only.
|
||||
* This function can assume the following:
|
||||
* - the gpio value has passed a bounds-check
|
||||
* - the gpiomux spinlock has been obtained
|
||||
*
|
||||
* This function is not for public consumption. External users
|
||||
* should use msm_gpiomux_write.
|
||||
*/
|
||||
void __msm_gpiomux_write(unsigned gpio, gpiomux_config_t val);
|
||||
#else
|
||||
static inline int __must_check msm_gpiomux_get(unsigned gpio)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int msm_gpiomux_put(unsigned gpio)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int msm_gpiomux_write(unsigned gpio,
|
||||
gpiomux_config_t active,
|
||||
gpiomux_config_t suspended)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
#endif
|
@ -33,6 +33,8 @@ struct msm_acpu_clock_platform_data
|
||||
|
||||
struct clk;
|
||||
|
||||
extern struct sys_timer msm_timer;
|
||||
|
||||
/* common init routines for use by arch/arm/mach-msm/board-*.c */
|
||||
|
||||
void __init msm_add_devices(void);
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
|
||||
#ifdef CONFIG_MSM_DEBUG_UART
|
||||
#ifdef CONFIG_HAS_MSM_DEBUG_UART_PHYS
|
||||
.macro addruart, rx, tmp
|
||||
@ see if the MMU is enabled and select appropriate base address
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
|
@ -32,10 +32,18 @@ struct msm_dmov_cmd {
|
||||
void *data;
|
||||
};
|
||||
|
||||
#ifndef CONFIG_ARCH_MSM8X60
|
||||
void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd);
|
||||
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful);
|
||||
int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr);
|
||||
|
||||
#else
|
||||
static inline
|
||||
void msm_dmov_enqueue_cmd(unsigned id, struct msm_dmov_cmd *cmd) { }
|
||||
static inline
|
||||
void msm_dmov_stop_cmd(unsigned id, struct msm_dmov_cmd *cmd, int graceful) { }
|
||||
static inline
|
||||
int msm_dmov_exec_cmd(unsigned id, unsigned int cmdptr) { return -EIO; }
|
||||
#endif
|
||||
|
||||
|
||||
#define DMOV_SD0(off, ch) (MSM_DMOV_BASE + 0x0000 + (off) + ((ch) << 2))
|
||||
|
88
arch/arm/mach-msm/include/mach/entry-macro-qgic.S
Normal file
88
arch/arm/mach-msm/include/mach/entry-macro-qgic.S
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Low-level IRQ helper macros
|
||||
*
|
||||
* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =gic_cpu_base_addr
|
||||
ldr \base, [\base]
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
/*
|
||||
* The interrupt numbering scheme is defined in the
|
||||
* interrupt controller spec. To wit:
|
||||
*
|
||||
* Migrated the code from ARM MP port to be more consistant
|
||||
* with interrupt processing , the following still holds true
|
||||
* however, all interrupts are treated the same regardless of
|
||||
* if they are local IPI or PPI
|
||||
*
|
||||
* Interrupts 0-15 are IPI
|
||||
* 16-31 are PPI
|
||||
* (16-18 are the timers)
|
||||
* 32-1020 are global
|
||||
* 1021-1022 are reserved
|
||||
* 1023 is "spurious" (no interrupt)
|
||||
*
|
||||
* A simple read from the controller will tell us the number of the
|
||||
* highest priority enabled interrupt. We then just need to check
|
||||
* whether it is in the valid range for an IRQ (0-1020 inclusive).
|
||||
*
|
||||
* Base ARM code assumes that the local (private) peripheral interrupts
|
||||
* are not valid, we treat them differently, in that the privates are
|
||||
* handled like normal shared interrupts with the exception that only
|
||||
* one processor can register the interrupt and the handler must be
|
||||
* the same for all processors.
|
||||
*/
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
|
||||
ldr \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 =srcCPU,
|
||||
9-0 =int # */
|
||||
|
||||
bic \irqnr, \irqstat, #0x1c00 @mask src
|
||||
cmp \irqnr, #15
|
||||
ldr \tmp, =1021
|
||||
cmpcc \irqnr, \irqnr
|
||||
cmpne \irqnr, \tmp
|
||||
cmpcs \irqnr, \irqnr
|
||||
|
||||
.endm
|
||||
|
||||
/* We assume that irqstat (the raw value of the IRQ acknowledge
|
||||
* register) is preserved from the macro above.
|
||||
* If there is an IPI, we immediately signal end of interrupt on the
|
||||
* controller, since this requires the original irqstat value which
|
||||
* we won't easily be able to recreate later.
|
||||
*/
|
||||
.macro test_for_ipi, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
cmp \irqnr, #16
|
||||
strcc \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmpcs \irqnr, \irqnr
|
||||
.endm
|
||||
|
||||
/* As above, this assumes that irqstat and base are preserved.. */
|
||||
|
||||
.macro test_for_ltirq, irqnr, irqstat, base, tmp
|
||||
bic \irqnr, \irqstat, #0x1c00
|
||||
mov \tmp, #0
|
||||
cmp \irqnr, #16
|
||||
moveq \tmp, #1
|
||||
streq \irqstat, [\base, #GIC_CPU_EOI]
|
||||
cmp \tmp, #0
|
||||
.endm
|
37
arch/arm/mach-msm/include/mach/entry-macro-vic.S
Normal file
37
arch/arm/mach-msm/include/mach/entry-macro-vic.S
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
@ enable imprecise aborts
|
||||
cpsie a
|
||||
mov \base, #MSM_VIC_BASE
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
@ 0xD0 has irq# or old irq# if the irq has been handled
|
||||
@ 0xD4 has irq# or -1 if none pending *but* if you just
|
||||
@ read 0xD4 you never get the first irq for some reason
|
||||
ldr \irqnr, [\base, #0xD0]
|
||||
ldr \irqnr, [\base, #0xD4]
|
||||
cmp \irqnr, #0xffffffff
|
||||
.endm
|
@ -1,38 +1,23 @@
|
||||
/* arch/arm/mach-msm7200/include/mach/entry-macro.S
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <mach/msm_iomap.h>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
@ enable imprecise aborts
|
||||
cpsie a
|
||||
mov \base, #MSM_VIC_BASE
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
@ 0xD0 has irq# or old irq# if the irq has been handled
|
||||
@ 0xD4 has irq# or -1 if none pending *but* if you just
|
||||
@ read 0xD4 you never get the first irq for some reason
|
||||
ldr \irqnr, [\base, #0xD0]
|
||||
ldr \irqnr, [\base, #0xD4]
|
||||
cmp \irqnr, #0xffffffff
|
||||
.endm
|
||||
#if defined(CONFIG_ARM_GIC)
|
||||
#include <mach/entry-macro-qgic.S>
|
||||
#else
|
||||
#include <mach/entry-macro-vic.S>
|
||||
#endif
|
||||
|
@ -23,127 +23,4 @@
|
||||
#define gpio_cansleep __gpio_cansleep
|
||||
#define gpio_to_irq __gpio_to_irq
|
||||
|
||||
/**
|
||||
* struct msm_gpio - GPIO pin description
|
||||
* @gpio_cfg - configuration bitmap, as per gpio_tlmm_config()
|
||||
* @label - textual label
|
||||
*
|
||||
* Usually, GPIO's are operated by sets.
|
||||
* This struct accumulate all GPIO information in single source
|
||||
* and facilitete group operations provided by msm_gpios_xxx()
|
||||
*/
|
||||
struct msm_gpio {
|
||||
u32 gpio_cfg;
|
||||
const char *label;
|
||||
};
|
||||
|
||||
/**
|
||||
* msm_gpios_request_enable() - request and enable set of GPIOs
|
||||
*
|
||||
* Request and configure set of GPIO's
|
||||
* In case of error, all operations rolled back.
|
||||
* Return error code.
|
||||
*
|
||||
* @table: GPIO table
|
||||
* @size: number of entries in @table
|
||||
*/
|
||||
int msm_gpios_request_enable(const struct msm_gpio *table, int size);
|
||||
|
||||
/**
|
||||
* msm_gpios_disable_free() - disable and free set of GPIOs
|
||||
*
|
||||
* @table: GPIO table
|
||||
* @size: number of entries in @table
|
||||
*/
|
||||
void msm_gpios_disable_free(const struct msm_gpio *table, int size);
|
||||
|
||||
/**
|
||||
* msm_gpios_request() - request set of GPIOs
|
||||
* In case of error, all operations rolled back.
|
||||
* Return error code.
|
||||
*
|
||||
* @table: GPIO table
|
||||
* @size: number of entries in @table
|
||||
*/
|
||||
int msm_gpios_request(const struct msm_gpio *table, int size);
|
||||
|
||||
/**
|
||||
* msm_gpios_free() - free set of GPIOs
|
||||
*
|
||||
* @table: GPIO table
|
||||
* @size: number of entries in @table
|
||||
*/
|
||||
void msm_gpios_free(const struct msm_gpio *table, int size);
|
||||
|
||||
/**
|
||||
* msm_gpios_enable() - enable set of GPIOs
|
||||
* In case of error, all operations rolled back.
|
||||
* Return error code.
|
||||
*
|
||||
* @table: GPIO table
|
||||
* @size: number of entries in @table
|
||||
*/
|
||||
int msm_gpios_enable(const struct msm_gpio *table, int size);
|
||||
|
||||
/**
|
||||
* msm_gpios_disable() - disable set of GPIOs
|
||||
*
|
||||
* @table: GPIO table
|
||||
* @size: number of entries in @table
|
||||
*/
|
||||
void msm_gpios_disable(const struct msm_gpio *table, int size);
|
||||
|
||||
/* GPIO TLMM (Top Level Multiplexing) Definitions */
|
||||
|
||||
/* GPIO TLMM: Function -- GPIO specific */
|
||||
|
||||
/* GPIO TLMM: Direction */
|
||||
enum {
|
||||
GPIO_INPUT,
|
||||
GPIO_OUTPUT,
|
||||
};
|
||||
|
||||
/* GPIO TLMM: Pullup/Pulldown */
|
||||
enum {
|
||||
GPIO_NO_PULL,
|
||||
GPIO_PULL_DOWN,
|
||||
GPIO_KEEPER,
|
||||
GPIO_PULL_UP,
|
||||
};
|
||||
|
||||
/* GPIO TLMM: Drive Strength */
|
||||
enum {
|
||||
GPIO_2MA,
|
||||
GPIO_4MA,
|
||||
GPIO_6MA,
|
||||
GPIO_8MA,
|
||||
GPIO_10MA,
|
||||
GPIO_12MA,
|
||||
GPIO_14MA,
|
||||
GPIO_16MA,
|
||||
};
|
||||
|
||||
enum {
|
||||
GPIO_ENABLE,
|
||||
GPIO_DISABLE,
|
||||
};
|
||||
|
||||
#define GPIO_CFG(gpio, func, dir, pull, drvstr) \
|
||||
((((gpio) & 0x3FF) << 4) | \
|
||||
((func) & 0xf) | \
|
||||
(((dir) & 0x1) << 14) | \
|
||||
(((pull) & 0x3) << 15) | \
|
||||
(((drvstr) & 0xF) << 17))
|
||||
|
||||
/**
|
||||
* extract GPIO pin from bit-field used for gpio_tlmm_config
|
||||
*/
|
||||
#define GPIO_PIN(gpio_cfg) (((gpio_cfg) >> 4) & 0x3ff)
|
||||
#define GPIO_FUNC(gpio_cfg) (((gpio_cfg) >> 0) & 0xf)
|
||||
#define GPIO_DIR(gpio_cfg) (((gpio_cfg) >> 14) & 0x1)
|
||||
#define GPIO_PULL(gpio_cfg) (((gpio_cfg) >> 15) & 0x3)
|
||||
#define GPIO_DRVSTR(gpio_cfg) (((gpio_cfg) >> 17) & 0xf)
|
||||
|
||||
int gpio_tlmm_config(unsigned config, unsigned disable);
|
||||
|
||||
#endif /* __ASM_ARCH_MSM_GPIO_H */
|
||||
|
@ -28,6 +28,7 @@ void __iomem *__msm_ioremap(unsigned long phys_addr, size_t size, unsigned int m
|
||||
|
||||
void msm_map_qsd8x50_io(void);
|
||||
void msm_map_msm7x30_io(void);
|
||||
void msm_map_msm8x60_io(void);
|
||||
|
||||
extern unsigned int msm_shared_ram_phys;
|
||||
|
||||
|
103
arch/arm/mach-msm/include/mach/iommu.h
Normal file
103
arch/arm/mach-msm/include/mach/iommu.h
Normal file
@ -0,0 +1,103 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef MSM_IOMMU_H
|
||||
#define MSM_IOMMU_H
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
/* Maximum number of Machine IDs that we are allowing to be mapped to the same
|
||||
* context bank. The number of MIDs mapped to the same CB does not affect
|
||||
* performance, but there is a practical limit on how many distinct MIDs may
|
||||
* be present. These mappings are typically determined at design time and are
|
||||
* not expected to change at run time.
|
||||
*/
|
||||
#define MAX_NUM_MIDS 16
|
||||
|
||||
/**
|
||||
* struct msm_iommu_dev - a single IOMMU hardware instance
|
||||
* name Human-readable name given to this IOMMU HW instance
|
||||
* clk_rate Rate to set for this IOMMU's clock, if applicable to this
|
||||
* particular IOMMU. 0 means don't set a rate.
|
||||
* -1 means it is an AXI clock with no valid rate
|
||||
*
|
||||
*/
|
||||
struct msm_iommu_dev {
|
||||
const char *name;
|
||||
int clk_rate;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct msm_iommu_ctx_dev - an IOMMU context bank instance
|
||||
* name Human-readable name given to this context bank
|
||||
* num Index of this context bank within the hardware
|
||||
* mids List of Machine IDs that are to be mapped into this context
|
||||
* bank, terminated by -1. The MID is a set of signals on the
|
||||
* AXI bus that identifies the function associated with a specific
|
||||
* memory request. (See ARM spec).
|
||||
*/
|
||||
struct msm_iommu_ctx_dev {
|
||||
const char *name;
|
||||
int num;
|
||||
int mids[MAX_NUM_MIDS];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct msm_iommu_drvdata - A single IOMMU hardware instance
|
||||
* @base: IOMMU config port base address (VA)
|
||||
* @irq: Interrupt number
|
||||
*
|
||||
* A msm_iommu_drvdata holds the global driver data about a single piece
|
||||
* of an IOMMU hardware instance.
|
||||
*/
|
||||
struct msm_iommu_drvdata {
|
||||
void __iomem *base;
|
||||
int irq;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct msm_iommu_ctx_drvdata - an IOMMU context bank instance
|
||||
* @num: Hardware context number of this context
|
||||
* @pdev: Platform device associated wit this HW instance
|
||||
* @attached_elm: List element for domains to track which devices are
|
||||
* attached to them
|
||||
*
|
||||
* A msm_iommu_ctx_drvdata holds the driver data for a single context bank
|
||||
* within each IOMMU hardware instance
|
||||
*/
|
||||
struct msm_iommu_ctx_drvdata {
|
||||
int num;
|
||||
struct platform_device *pdev;
|
||||
struct list_head attached_elm;
|
||||
};
|
||||
|
||||
/*
|
||||
* Look up an IOMMU context device by its context name. NULL if none found.
|
||||
* Useful for testing and drivers that do not yet fully have IOMMU stuff in
|
||||
* their platform devices.
|
||||
*/
|
||||
struct device *msm_iommu_get_ctx(const char *ctx_name);
|
||||
|
||||
/*
|
||||
* Interrupt handler for the IOMMU context fault interrupt. Hooking the
|
||||
* interrupt is not supported in the API yet, but this will print an error
|
||||
* message and dump useful IOMMU registers.
|
||||
*/
|
||||
irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id);
|
||||
|
||||
#endif
|
1871
arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
Normal file
1871
arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
Normal file
File diff suppressed because it is too large
Load Diff
253
arch/arm/mach-msm/include/mach/irqs-8x60.h
Normal file
253
arch/arm/mach-msm/include/mach/irqs-8x60.h
Normal file
@ -0,0 +1,253 @@
|
||||
/* Copyright (c) 2010 Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_MSM_IRQS_8X60_H
|
||||
#define __ASM_ARCH_MSM_IRQS_8X60_H
|
||||
|
||||
/* MSM ACPU Interrupt Numbers */
|
||||
|
||||
/* 0-15: STI/SGI (software triggered/generated interrupts)
|
||||
* 16-31: PPI (private peripheral interrupts)
|
||||
* 32+: SPI (shared peripheral interrupts)
|
||||
*/
|
||||
|
||||
#define GIC_PPI_START 16
|
||||
#define GIC_SPI_START 32
|
||||
|
||||
#define INT_DEBUG_TIMER_EXP (GIC_PPI_START + 0)
|
||||
#define INT_GP_TIMER_EXP (GIC_PPI_START + 1)
|
||||
#define INT_GP_TIMER2_EXP (GIC_PPI_START + 2)
|
||||
#define WDT0_ACCSCSSNBARK_INT (GIC_PPI_START + 3)
|
||||
#define WDT1_ACCSCSSNBARK_INT (GIC_PPI_START + 4)
|
||||
#define AVS_SVICINT (GIC_PPI_START + 5)
|
||||
#define AVS_SVICINTSWDONE (GIC_PPI_START + 6)
|
||||
#define CPU_DBGCPUXCOMMRXFULL (GIC_PPI_START + 7)
|
||||
#define CPU_DBGCPUXCOMMTXEMPTY (GIC_PPI_START + 8)
|
||||
#define CPU_SICCPUXPERFMONIRPTREQ (GIC_PPI_START + 9)
|
||||
#define SC_AVSCPUXDOWN (GIC_PPI_START + 10)
|
||||
#define SC_AVSCPUXUP (GIC_PPI_START + 11)
|
||||
#define SC_SICCPUXACGIRPTREQ (GIC_PPI_START + 12)
|
||||
/* PPI 13 to 15 are unused */
|
||||
|
||||
|
||||
#define SC_SICMPUIRPTREQ (GIC_SPI_START + 0)
|
||||
#define SC_SICL2IRPTREQ (GIC_SPI_START + 1)
|
||||
#define SC_SICL2ACGIRPTREQ (GIC_SPI_START + 2)
|
||||
#define NC (GIC_SPI_START + 3)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_0 (GIC_SPI_START + 4)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_1 (GIC_SPI_START + 5)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_2 (GIC_SPI_START + 6)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_3 (GIC_SPI_START + 7)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_4 (GIC_SPI_START + 8)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_5 (GIC_SPI_START + 9)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_6 (GIC_SPI_START + 10)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_7 (GIC_SPI_START + 11)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_8 (GIC_SPI_START + 12)
|
||||
#define TLMM_SCSS_DIR_CONN_IRQ_9 (GIC_SPI_START + 13)
|
||||
#define PM8058_SEC_IRQ_N (GIC_SPI_START + 14)
|
||||
#define PM8901_SEC_IRQ_N (GIC_SPI_START + 15)
|
||||
#define TLMM_SCSS_SUMMARY_IRQ (GIC_SPI_START + 16)
|
||||
#define SPDM_RT_1_IRQ (GIC_SPI_START + 17)
|
||||
#define SPDM_DIAG_IRQ (GIC_SPI_START + 18)
|
||||
#define RPM_SCSS_CPU0_GP_HIGH_IRQ (GIC_SPI_START + 19)
|
||||
#define RPM_SCSS_CPU0_GP_MEDIUM_IRQ (GIC_SPI_START + 20)
|
||||
#define RPM_SCSS_CPU0_GP_LOW_IRQ (GIC_SPI_START + 21)
|
||||
#define RPM_SCSS_CPU0_WAKE_UP_IRQ (GIC_SPI_START + 22)
|
||||
#define RPM_SCSS_CPU1_GP_HIGH_IRQ (GIC_SPI_START + 23)
|
||||
#define RPM_SCSS_CPU1_GP_MEDIUM_IRQ (GIC_SPI_START + 24)
|
||||
#define RPM_SCSS_CPU1_GP_LOW_IRQ (GIC_SPI_START + 25)
|
||||
#define RPM_SCSS_CPU1_WAKE_UP_IRQ (GIC_SPI_START + 26)
|
||||
#define SSBI2_2_SC_CPU0_SECURE_INT (GIC_SPI_START + 27)
|
||||
#define SSBI2_2_SC_CPU0_NON_SECURE_INT (GIC_SPI_START + 28)
|
||||
#define SSBI2_1_SC_CPU0_SECURE_INT (GIC_SPI_START + 29)
|
||||
#define SSBI2_1_SC_CPU0_NON_SECURE_INT (GIC_SPI_START + 30)
|
||||
#define MSMC_SC_SEC_CE_IRQ (GIC_SPI_START + 31)
|
||||
#define MSMC_SC_PRI_CE_IRQ (GIC_SPI_START + 32)
|
||||
#define MARM_FIQ (GIC_SPI_START + 33)
|
||||
#define MARM_IRQ (GIC_SPI_START + 34)
|
||||
#define MARM_L2CC_IRQ (GIC_SPI_START + 35)
|
||||
#define MARM_WDOG_EXPIRED (GIC_SPI_START + 36)
|
||||
#define MARM_SCSS_GP_IRQ_0 (GIC_SPI_START + 37)
|
||||
#define MARM_SCSS_GP_IRQ_1 (GIC_SPI_START + 38)
|
||||
#define MARM_SCSS_GP_IRQ_2 (GIC_SPI_START + 39)
|
||||
#define MARM_SCSS_GP_IRQ_3 (GIC_SPI_START + 40)
|
||||
#define MARM_SCSS_GP_IRQ_4 (GIC_SPI_START + 41)
|
||||
#define MARM_SCSS_GP_IRQ_5 (GIC_SPI_START + 42)
|
||||
#define MARM_SCSS_GP_IRQ_6 (GIC_SPI_START + 43)
|
||||
#define MARM_SCSS_GP_IRQ_7 (GIC_SPI_START + 44)
|
||||
#define MARM_SCSS_GP_IRQ_8 (GIC_SPI_START + 45)
|
||||
#define MARM_SCSS_GP_IRQ_9 (GIC_SPI_START + 46)
|
||||
#define VPE_IRQ (GIC_SPI_START + 47)
|
||||
#define VFE_IRQ (GIC_SPI_START + 48)
|
||||
#define VCODEC_IRQ (GIC_SPI_START + 49)
|
||||
#define TV_ENC_IRQ (GIC_SPI_START + 50)
|
||||
#define SMMU_VPE_CB_SC_SECURE_IRQ (GIC_SPI_START + 51)
|
||||
#define SMMU_VPE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 52)
|
||||
#define SMMU_VFE_CB_SC_SECURE_IRQ (GIC_SPI_START + 53)
|
||||
#define SMMU_VFE_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 54)
|
||||
#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ (GIC_SPI_START + 55)
|
||||
#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 56)
|
||||
#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ (GIC_SPI_START + 57)
|
||||
#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 58)
|
||||
#define SMMU_ROT_CB_SC_SECURE_IRQ (GIC_SPI_START + 59)
|
||||
#define SMMU_ROT_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 60)
|
||||
#define SMMU_MDP1_CB_SC_SECURE_IRQ (GIC_SPI_START + 61)
|
||||
#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 62)
|
||||
#define SMMU_MDP0_CB_SC_SECURE_IRQ (GIC_SPI_START + 63)
|
||||
#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 64)
|
||||
#define SMMU_JPEGD_CB_SC_SECURE_IRQ (GIC_SPI_START + 65)
|
||||
#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 66)
|
||||
#define SMMU_IJPEG_CB_SC_SECURE_IRQ (GIC_SPI_START + 67)
|
||||
#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 68)
|
||||
#define SMMU_GFX3D_CB_SC_SECURE_IRQ (GIC_SPI_START + 69)
|
||||
#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 70)
|
||||
#define SMMU_GFX2D0_CB_SC_SECURE_IRQ (GIC_SPI_START + 71)
|
||||
#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ (GIC_SPI_START + 72)
|
||||
#define ROT_IRQ (GIC_SPI_START + 73)
|
||||
#define MMSS_FABRIC_IRQ (GIC_SPI_START + 74)
|
||||
#define MDP_IRQ (GIC_SPI_START + 75)
|
||||
#define JPEGD_IRQ (GIC_SPI_START + 76)
|
||||
#define JPEG_IRQ (GIC_SPI_START + 77)
|
||||
#define MMSS_IMEM_IRQ (GIC_SPI_START + 78)
|
||||
#define HDMI_IRQ (GIC_SPI_START + 79)
|
||||
#define GFX3D_IRQ (GIC_SPI_START + 80)
|
||||
#define GFX2D0_IRQ (GIC_SPI_START + 81)
|
||||
#define DSI_IRQ (GIC_SPI_START + 82)
|
||||
#define CSI_1_IRQ (GIC_SPI_START + 83)
|
||||
#define CSI_0_IRQ (GIC_SPI_START + 84)
|
||||
#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ (GIC_SPI_START + 85)
|
||||
#define LPASS_SCSS_MIDI_IRQ (GIC_SPI_START + 86)
|
||||
#define LPASS_Q6SS_WDOG_EXPIRED (GIC_SPI_START + 87)
|
||||
#define LPASS_SCSS_GP_LOW_IRQ (GIC_SPI_START + 88)
|
||||
#define LPASS_SCSS_GP_MEDIUM_IRQ (GIC_SPI_START + 89)
|
||||
#define LPASS_SCSS_GP_HIGH_IRQ (GIC_SPI_START + 90)
|
||||
#define TOP_IMEM_IRQ (GIC_SPI_START + 91)
|
||||
#define FABRIC_SYS_IRQ (GIC_SPI_START + 92)
|
||||
#define FABRIC_APPS_IRQ (GIC_SPI_START + 93)
|
||||
#define USB1_HS_BAM_IRQ (GIC_SPI_START + 94)
|
||||
#define SDC4_BAM_IRQ (GIC_SPI_START + 95)
|
||||
#define SDC3_BAM_IRQ (GIC_SPI_START + 96)
|
||||
#define SDC2_BAM_IRQ (GIC_SPI_START + 97)
|
||||
#define SDC1_BAM_IRQ (GIC_SPI_START + 98)
|
||||
#define FABRIC_SPS_IRQ (GIC_SPI_START + 99)
|
||||
#define USB1_HS_IRQ (GIC_SPI_START + 100)
|
||||
#define SDC4_IRQ_0 (GIC_SPI_START + 101)
|
||||
#define SDC3_IRQ_0 (GIC_SPI_START + 102)
|
||||
#define SDC2_IRQ_0 (GIC_SPI_START + 103)
|
||||
#define SDC1_IRQ_0 (GIC_SPI_START + 104)
|
||||
#define SPS_BAM_DMA_IRQ (GIC_SPI_START + 105)
|
||||
#define SPS_SEC_VIOL_IRQ (GIC_SPI_START + 106)
|
||||
#define SPS_MTI_0 (GIC_SPI_START + 107)
|
||||
#define SPS_MTI_1 (GIC_SPI_START + 108)
|
||||
#define SPS_MTI_2 (GIC_SPI_START + 109)
|
||||
#define SPS_MTI_3 (GIC_SPI_START + 110)
|
||||
#define SPS_MTI_4 (GIC_SPI_START + 111)
|
||||
#define SPS_MTI_5 (GIC_SPI_START + 112)
|
||||
#define SPS_MTI_6 (GIC_SPI_START + 113)
|
||||
#define SPS_MTI_7 (GIC_SPI_START + 114)
|
||||
#define SPS_MTI_8 (GIC_SPI_START + 115)
|
||||
#define SPS_MTI_9 (GIC_SPI_START + 116)
|
||||
#define SPS_MTI_10 (GIC_SPI_START + 117)
|
||||
#define SPS_MTI_11 (GIC_SPI_START + 118)
|
||||
#define SPS_MTI_12 (GIC_SPI_START + 119)
|
||||
#define SPS_MTI_13 (GIC_SPI_START + 120)
|
||||
#define SPS_MTI_14 (GIC_SPI_START + 121)
|
||||
#define SPS_MTI_15 (GIC_SPI_START + 122)
|
||||
#define SPS_MTI_16 (GIC_SPI_START + 123)
|
||||
#define SPS_MTI_17 (GIC_SPI_START + 124)
|
||||
#define SPS_MTI_18 (GIC_SPI_START + 125)
|
||||
#define SPS_MTI_19 (GIC_SPI_START + 126)
|
||||
#define SPS_MTI_20 (GIC_SPI_START + 127)
|
||||
#define SPS_MTI_21 (GIC_SPI_START + 128)
|
||||
#define SPS_MTI_22 (GIC_SPI_START + 129)
|
||||
#define SPS_MTI_23 (GIC_SPI_START + 130)
|
||||
#define SPS_MTI_24 (GIC_SPI_START + 131)
|
||||
#define SPS_MTI_25 (GIC_SPI_START + 132)
|
||||
#define SPS_MTI_26 (GIC_SPI_START + 133)
|
||||
#define SPS_MTI_27 (GIC_SPI_START + 134)
|
||||
#define SPS_MTI_28 (GIC_SPI_START + 135)
|
||||
#define SPS_MTI_29 (GIC_SPI_START + 136)
|
||||
#define SPS_MTI_30 (GIC_SPI_START + 137)
|
||||
#define SPS_MTI_31 (GIC_SPI_START + 138)
|
||||
#define UXMC_EBI2_WR_ER_DONE_IRQ (GIC_SPI_START + 139)
|
||||
#define UXMC_EBI2_OP_DONE_IRQ (GIC_SPI_START + 140)
|
||||
#define USB2_IRQ (GIC_SPI_START + 141)
|
||||
#define USB1_IRQ (GIC_SPI_START + 142)
|
||||
#define TSSC_SSBI_IRQ (GIC_SPI_START + 143)
|
||||
#define TSSC_SAMPLE_IRQ (GIC_SPI_START + 144)
|
||||
#define TSSC_PENUP_IRQ (GIC_SPI_START + 145)
|
||||
#define INT_UART1DM_IRQ (GIC_SPI_START + 146)
|
||||
#define GSBI1_QUP_IRQ (GIC_SPI_START + 147)
|
||||
#define INT_UART2DM_IRQ (GIC_SPI_START + 148)
|
||||
#define GSBI2_QUP_IRQ (GIC_SPI_START + 149)
|
||||
#define INT_UART3DM_IRQ (GIC_SPI_START + 150)
|
||||
#define GSBI3_QUP_IRQ (GIC_SPI_START + 151)
|
||||
#define INT_UART4DM_IRQ (GIC_SPI_START + 152)
|
||||
#define GSBI4_QUP_IRQ (GIC_SPI_START + 153)
|
||||
#define INT_UART5DM_IRQ (GIC_SPI_START + 154)
|
||||
#define GSBI5_QUP_IRQ (GIC_SPI_START + 155)
|
||||
#define INT_UART6DM_IRQ (GIC_SPI_START + 156)
|
||||
#define GSBI6_QUP_IRQ (GIC_SPI_START + 157)
|
||||
#define INT_UART7DM_IRQ (GIC_SPI_START + 158)
|
||||
#define GSBI7_QUP_IRQ (GIC_SPI_START + 159)
|
||||
#define INT_UART8DM_IRQ (GIC_SPI_START + 160)
|
||||
#define GSBI8_QUP_IRQ (GIC_SPI_START + 161)
|
||||
#define TSIF_TSPP_IRQ (GIC_SPI_START + 162)
|
||||
#define TSIF_BAM_IRQ (GIC_SPI_START + 163)
|
||||
#define TSIF2_IRQ (GIC_SPI_START + 164)
|
||||
#define TSIF1_IRQ (GIC_SPI_START + 165)
|
||||
#define INT_ADM1_MASTER (GIC_SPI_START + 166)
|
||||
#define INT_ADM1_AARM (GIC_SPI_START + 167)
|
||||
#define INT_ADM1_SD2 (GIC_SPI_START + 168)
|
||||
#define INT_ADM1_SD3 (GIC_SPI_START + 169)
|
||||
#define INT_ADM0_MASTER (GIC_SPI_START + 170)
|
||||
#define INT_ADM0_AARM (GIC_SPI_START + 171)
|
||||
#define INT_ADM0_SD2 (GIC_SPI_START + 172)
|
||||
#define INT_ADM0_SD3 (GIC_SPI_START + 173)
|
||||
#define CC_SCSS_WDT1CPU1BITEEXPIRED (GIC_SPI_START + 174)
|
||||
#define CC_SCSS_WDT1CPU0BITEEXPIRED (GIC_SPI_START + 175)
|
||||
#define CC_SCSS_WDT0CPU1BITEEXPIRED (GIC_SPI_START + 176)
|
||||
#define CC_SCSS_WDT0CPU0BITEEXPIRED (GIC_SPI_START + 177)
|
||||
#define TSENS_UPPER_LOWER_INT (GIC_SPI_START + 178)
|
||||
#define SSBI2_2_SC_CPU1_SECURE_INT (GIC_SPI_START + 179)
|
||||
#define SSBI2_2_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 180)
|
||||
#define SSBI2_1_SC_CPU1_SECURE_INT (GIC_SPI_START + 181)
|
||||
#define SSBI2_1_SC_CPU1_NON_SECURE_INT (GIC_SPI_START + 182)
|
||||
#define XPU_SUMMARY_IRQ (GIC_SPI_START + 183)
|
||||
#define BUS_EXCEPTION_SUMMARY_IRQ (GIC_SPI_START + 184)
|
||||
#define HSDDRX_SMICH0_IRQ (GIC_SPI_START + 185)
|
||||
#define HSDDRX_EBI1_IRQ (GIC_SPI_START + 186)
|
||||
#define SDC5_BAM_IRQ (GIC_SPI_START + 187)
|
||||
#define SDC5_IRQ_0 (GIC_SPI_START + 188)
|
||||
#define INT_UART9DM_IRQ (GIC_SPI_START + 189)
|
||||
#define GSBI9_QUP_IRQ (GIC_SPI_START + 190)
|
||||
#define INT_UART10DM_IRQ (GIC_SPI_START + 191)
|
||||
#define GSBI10_QUP_IRQ (GIC_SPI_START + 192)
|
||||
#define INT_UART11DM_IRQ (GIC_SPI_START + 193)
|
||||
#define GSBI11_QUP_IRQ (GIC_SPI_START + 194)
|
||||
#define INT_UART12DM_IRQ (GIC_SPI_START + 195)
|
||||
#define GSBI12_QUP_IRQ (GIC_SPI_START + 196)
|
||||
/*SPI 197 to 216 arent used in 8x60*/
|
||||
#define SMPSS_SPARE_1 (GIC_SPI_START + 217)
|
||||
#define SMPSS_SPARE_2 (GIC_SPI_START + 218)
|
||||
#define SMPSS_SPARE_3 (GIC_SPI_START + 219)
|
||||
#define SMPSS_SPARE_4 (GIC_SPI_START + 220)
|
||||
#define SMPSS_SPARE_5 (GIC_SPI_START + 221)
|
||||
#define SMPSS_SPARE_6 (GIC_SPI_START + 222)
|
||||
#define SMPSS_SPARE_7 (GIC_SPI_START + 223)
|
||||
|
||||
#define NR_GPIO_IRQS 173
|
||||
#define NR_MSM_IRQS 256
|
||||
#define NR_BOARD_IRQS 0
|
||||
|
||||
#endif
|
@ -24,6 +24,8 @@
|
||||
#elif defined(CONFIG_ARCH_QSD8X50)
|
||||
#include "irqs-8x50.h"
|
||||
#include "sirc.h"
|
||||
#elif defined(CONFIG_ARCH_MSM8X60)
|
||||
#include "irqs-8x60.h"
|
||||
#elif defined(CONFIG_ARCH_MSM_ARM11)
|
||||
#include "irqs-7x00.h"
|
||||
#else
|
||||
|
@ -23,6 +23,8 @@
|
||||
#define PHYS_OFFSET UL(0x20000000)
|
||||
#elif defined(CONFIG_ARCH_MSM7X30)
|
||||
#define PHYS_OFFSET UL(0x00200000)
|
||||
#elif defined(CONFIG_ARCH_MSM8X60)
|
||||
#define PHYS_OFFSET UL(0x40200000)
|
||||
#else
|
||||
#define PHYS_OFFSET UL(0x10000000)
|
||||
#endif
|
||||
|
101
arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
Normal file
101
arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (C) 2007 Google, Inc.
|
||||
* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
|
||||
* Author: Brian Swetland <swetland@google.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*
|
||||
* The MSM peripherals are spread all over across 768MB of physical
|
||||
* space, which makes just having a simple IO_ADDRESS macro to slide
|
||||
* them into the right virtual location rough. Instead, we will
|
||||
* provide a master phys->virt mapping for peripherals here.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_MSM_IOMAP_8X60_H
|
||||
#define __ASM_ARCH_MSM_IOMAP_8X60_H
|
||||
|
||||
/* Physical base address and size of peripherals.
|
||||
* Ordered by the virtual base addresses they will be mapped at.
|
||||
*
|
||||
* MSM_VIC_BASE must be an value that can be loaded via a "mov"
|
||||
* instruction, otherwise entry-macro.S will not compile.
|
||||
*
|
||||
* If you add or remove entries here, you'll want to edit the
|
||||
* msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
|
||||
* changes.
|
||||
*
|
||||
*/
|
||||
|
||||
#define MSM_QGIC_DIST_BASE IOMEM(0xF0000000)
|
||||
#define MSM_QGIC_DIST_PHYS 0x02080000
|
||||
#define MSM_QGIC_DIST_SIZE SZ_4K
|
||||
|
||||
#define MSM_QGIC_CPU_BASE IOMEM(0xF0001000)
|
||||
#define MSM_QGIC_CPU_PHYS 0x02081000
|
||||
#define MSM_QGIC_CPU_SIZE SZ_4K
|
||||
|
||||
#define MSM_ACC_BASE IOMEM(0xF0002000)
|
||||
#define MSM_ACC_PHYS 0x02001000
|
||||
#define MSM_ACC_SIZE SZ_4K
|
||||
|
||||
#define MSM_GCC_BASE IOMEM(0xF0003000)
|
||||
#define MSM_GCC_PHYS 0x02082000
|
||||
#define MSM_GCC_SIZE SZ_4K
|
||||
|
||||
#define MSM_TLMM_BASE IOMEM(0xF0004000)
|
||||
#define MSM_TLMM_PHYS 0x00800000
|
||||
#define MSM_TLMM_SIZE SZ_16K
|
||||
|
||||
#define MSM_SHARED_RAM_BASE IOMEM(0xF0100000)
|
||||
#define MSM_SHARED_RAM_SIZE SZ_1M
|
||||
|
||||
#define MSM_TMR_BASE IOMEM(0xF0200000)
|
||||
#define MSM_TMR_PHYS 0x02000000
|
||||
#define MSM_TMR_SIZE (SZ_1M)
|
||||
|
||||
#define MSM_GPT_BASE (MSM_TMR_BASE + 0x4)
|
||||
#define MSM_DGT_BASE (MSM_TMR_BASE + 0x24)
|
||||
|
||||
#define MSM_IOMMU_JPEGD_PHYS 0x07300000
|
||||
#define MSM_IOMMU_JPEGD_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_VPE_PHYS 0x07400000
|
||||
#define MSM_IOMMU_VPE_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_MDP0_PHYS 0x07500000
|
||||
#define MSM_IOMMU_MDP0_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_MDP1_PHYS 0x07600000
|
||||
#define MSM_IOMMU_MDP1_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_ROT_PHYS 0x07700000
|
||||
#define MSM_IOMMU_ROT_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_IJPEG_PHYS 0x07800000
|
||||
#define MSM_IOMMU_IJPEG_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_VFE_PHYS 0x07900000
|
||||
#define MSM_IOMMU_VFE_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_VCODEC_A_PHYS 0x07A00000
|
||||
#define MSM_IOMMU_VCODEC_A_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_VCODEC_B_PHYS 0x07B00000
|
||||
#define MSM_IOMMU_VCODEC_B_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_GFX3D_PHYS 0x07C00000
|
||||
#define MSM_IOMMU_GFX3D_SIZE SZ_1M
|
||||
|
||||
#define MSM_IOMMU_GFX2D0_PHYS 0x07D00000
|
||||
#define MSM_IOMMU_GFX2D0_SIZE SZ_1M
|
||||
|
||||
#endif
|
@ -47,8 +47,12 @@
|
||||
#include "msm_iomap-7x30.h"
|
||||
#elif defined(CONFIG_ARCH_QSD8X50)
|
||||
#include "msm_iomap-8x50.h"
|
||||
#elif defined(CONFIG_ARCH_MSM8X60)
|
||||
#include "msm_iomap-8x60.h"
|
||||
#else
|
||||
#include "msm_iomap-7x00.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
39
arch/arm/mach-msm/include/mach/smp.h
Normal file
39
arch/arm/mach-msm/include/mach/smp.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Code Aurora nor
|
||||
* the names of its contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_MSM_SMP_H
|
||||
#define __ASM_ARCH_MSM_SMP_H
|
||||
|
||||
#include <asm/hardware/gic.h>
|
||||
|
||||
static inline void smp_cross_call(const struct cpumask *mask)
|
||||
{
|
||||
gic_raise_softirq(mask, 1);
|
||||
}
|
||||
|
||||
#endif
|
@ -100,6 +100,21 @@ void __init msm_map_qsd8x50_io(void)
|
||||
}
|
||||
#endif /* CONFIG_ARCH_QSD8X50 */
|
||||
|
||||
#ifdef CONFIG_ARCH_MSM8X60
|
||||
static struct map_desc msm8x60_io_desc[] __initdata = {
|
||||
MSM_DEVICE(QGIC_DIST),
|
||||
MSM_DEVICE(QGIC_CPU),
|
||||
MSM_DEVICE(TMR),
|
||||
MSM_DEVICE(ACC),
|
||||
MSM_DEVICE(GCC),
|
||||
};
|
||||
|
||||
void __init msm_map_msm8x60_io(void)
|
||||
{
|
||||
iotable_init(msm8x60_io_desc, ARRAY_SIZE(msm8x60_io_desc));
|
||||
}
|
||||
#endif /* CONFIG_ARCH_MSM8X60 */
|
||||
|
||||
#ifdef CONFIG_ARCH_MSM7X30
|
||||
static struct map_desc msm7x30_io_desc[] __initdata = {
|
||||
MSM_DEVICE(VIC),
|
||||
|
597
arch/arm/mach-msm/iommu.c
Normal file
597
arch/arm/mach-msm/iommu.c
Normal file
@ -0,0 +1,597 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/iommu.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#include <mach/iommu_hw-8xxx.h>
|
||||
#include <mach/iommu.h>
|
||||
|
||||
DEFINE_SPINLOCK(msm_iommu_lock);
|
||||
|
||||
struct msm_priv {
|
||||
unsigned long *pgtable;
|
||||
struct list_head list_attached;
|
||||
};
|
||||
|
||||
static void __flush_iotlb(struct iommu_domain *domain)
|
||||
{
|
||||
struct msm_priv *priv = domain->priv;
|
||||
struct msm_iommu_drvdata *iommu_drvdata;
|
||||
struct msm_iommu_ctx_drvdata *ctx_drvdata;
|
||||
|
||||
#ifndef CONFIG_IOMMU_PGTABLES_L2
|
||||
unsigned long *fl_table = priv->pgtable;
|
||||
int i;
|
||||
|
||||
dmac_flush_range(fl_table, fl_table + SZ_16K);
|
||||
|
||||
for (i = 0; i < NUM_FL_PTE; i++)
|
||||
if ((fl_table[i] & 0x03) == FL_TYPE_TABLE) {
|
||||
void *sl_table = __va(fl_table[i] & FL_BASE_MASK);
|
||||
dmac_flush_range(sl_table, sl_table + SZ_4K);
|
||||
}
|
||||
#endif
|
||||
|
||||
list_for_each_entry(ctx_drvdata, &priv->list_attached, attached_elm) {
|
||||
if (!ctx_drvdata->pdev || !ctx_drvdata->pdev->dev.parent)
|
||||
BUG();
|
||||
|
||||
iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
|
||||
SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void __reset_context(void __iomem *base, int ctx)
|
||||
{
|
||||
SET_BPRCOSH(base, ctx, 0);
|
||||
SET_BPRCISH(base, ctx, 0);
|
||||
SET_BPRCNSH(base, ctx, 0);
|
||||
SET_BPSHCFG(base, ctx, 0);
|
||||
SET_BPMTCFG(base, ctx, 0);
|
||||
SET_ACTLR(base, ctx, 0);
|
||||
SET_SCTLR(base, ctx, 0);
|
||||
SET_FSRRESTORE(base, ctx, 0);
|
||||
SET_TTBR0(base, ctx, 0);
|
||||
SET_TTBR1(base, ctx, 0);
|
||||
SET_TTBCR(base, ctx, 0);
|
||||
SET_BFBCR(base, ctx, 0);
|
||||
SET_PAR(base, ctx, 0);
|
||||
SET_FAR(base, ctx, 0);
|
||||
SET_CTX_TLBIALL(base, ctx, 0);
|
||||
SET_TLBFLPTER(base, ctx, 0);
|
||||
SET_TLBSLPTER(base, ctx, 0);
|
||||
SET_TLBLKCR(base, ctx, 0);
|
||||
SET_PRRR(base, ctx, 0);
|
||||
SET_NMRR(base, ctx, 0);
|
||||
SET_CONTEXTIDR(base, ctx, 0);
|
||||
}
|
||||
|
||||
static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
|
||||
{
|
||||
__reset_context(base, ctx);
|
||||
|
||||
/* Set up HTW mode */
|
||||
/* TLB miss configuration: perform HTW on miss */
|
||||
SET_TLBMCFG(base, ctx, 0x3);
|
||||
|
||||
/* V2P configuration: HTW for access */
|
||||
SET_V2PCFG(base, ctx, 0x3);
|
||||
|
||||
SET_TTBCR(base, ctx, 0);
|
||||
SET_TTBR0_PA(base, ctx, (pgtable >> 14));
|
||||
|
||||
/* Invalidate the TLB for this context */
|
||||
SET_CTX_TLBIALL(base, ctx, 0);
|
||||
|
||||
/* Set interrupt number to "secure" interrupt */
|
||||
SET_IRPTNDX(base, ctx, 0);
|
||||
|
||||
/* Enable context fault interrupt */
|
||||
SET_CFEIE(base, ctx, 1);
|
||||
|
||||
/* Stall access on a context fault and let the handler deal with it */
|
||||
SET_CFCFG(base, ctx, 1);
|
||||
|
||||
/* Redirect all cacheable requests to L2 slave port. */
|
||||
SET_RCISH(base, ctx, 1);
|
||||
SET_RCOSH(base, ctx, 1);
|
||||
SET_RCNSH(base, ctx, 1);
|
||||
|
||||
/* Turn on TEX Remap */
|
||||
SET_TRE(base, ctx, 1);
|
||||
|
||||
/* Do not configure PRRR / NMRR on the IOMMU for now. We will assume
|
||||
* TEX class 0 for everything until attributes are properly worked out
|
||||
*/
|
||||
SET_PRRR(base, ctx, 0);
|
||||
SET_NMRR(base, ctx, 0);
|
||||
|
||||
/* Turn on BFB prefetch */
|
||||
SET_BFBDFE(base, ctx, 1);
|
||||
|
||||
#ifdef CONFIG_IOMMU_PGTABLES_L2
|
||||
/* Configure page tables as inner-cacheable and shareable to reduce
|
||||
* the TLB miss penalty.
|
||||
*/
|
||||
SET_TTBR0_SH(base, ctx, 1);
|
||||
SET_TTBR1_SH(base, ctx, 1);
|
||||
|
||||
SET_TTBR0_NOS(base, ctx, 1);
|
||||
SET_TTBR1_NOS(base, ctx, 1);
|
||||
|
||||
SET_TTBR0_IRGNH(base, ctx, 0); /* WB, WA */
|
||||
SET_TTBR0_IRGNL(base, ctx, 1);
|
||||
|
||||
SET_TTBR1_IRGNH(base, ctx, 0); /* WB, WA */
|
||||
SET_TTBR1_IRGNL(base, ctx, 1);
|
||||
|
||||
SET_TTBR0_ORGN(base, ctx, 1); /* WB, WA */
|
||||
SET_TTBR1_ORGN(base, ctx, 1); /* WB, WA */
|
||||
#endif
|
||||
|
||||
/* Enable the MMU */
|
||||
SET_M(base, ctx, 1);
|
||||
}
|
||||
|
||||
static int msm_iommu_domain_init(struct iommu_domain *domain)
|
||||
{
|
||||
struct msm_priv *priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
|
||||
if (!priv)
|
||||
goto fail_nomem;
|
||||
|
||||
INIT_LIST_HEAD(&priv->list_attached);
|
||||
priv->pgtable = (unsigned long *)__get_free_pages(GFP_KERNEL,
|
||||
get_order(SZ_16K));
|
||||
|
||||
if (!priv->pgtable)
|
||||
goto fail_nomem;
|
||||
|
||||
memset(priv->pgtable, 0, SZ_16K);
|
||||
domain->priv = priv;
|
||||
return 0;
|
||||
|
||||
fail_nomem:
|
||||
kfree(priv);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void msm_iommu_domain_destroy(struct iommu_domain *domain)
|
||||
{
|
||||
struct msm_priv *priv;
|
||||
unsigned long flags;
|
||||
unsigned long *fl_table;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&msm_iommu_lock, flags);
|
||||
priv = domain->priv;
|
||||
domain->priv = NULL;
|
||||
|
||||
if (priv) {
|
||||
fl_table = priv->pgtable;
|
||||
|
||||
for (i = 0; i < NUM_FL_PTE; i++)
|
||||
if ((fl_table[i] & 0x03) == FL_TYPE_TABLE)
|
||||
free_page((unsigned long) __va(((fl_table[i]) &
|
||||
FL_BASE_MASK)));
|
||||
|
||||
free_pages((unsigned long)priv->pgtable, get_order(SZ_16K));
|
||||
priv->pgtable = NULL;
|
||||
}
|
||||
|
||||
kfree(priv);
|
||||
spin_unlock_irqrestore(&msm_iommu_lock, flags);
|
||||
}
|
||||
|
||||
static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
|
||||
{
|
||||
struct msm_priv *priv;
|
||||
struct msm_iommu_ctx_dev *ctx_dev;
|
||||
struct msm_iommu_drvdata *iommu_drvdata;
|
||||
struct msm_iommu_ctx_drvdata *ctx_drvdata;
|
||||
struct msm_iommu_ctx_drvdata *tmp_drvdata;
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&msm_iommu_lock, flags);
|
||||
|
||||
priv = domain->priv;
|
||||
|
||||
if (!priv || !dev) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
iommu_drvdata = dev_get_drvdata(dev->parent);
|
||||
ctx_drvdata = dev_get_drvdata(dev);
|
||||
ctx_dev = dev->platform_data;
|
||||
|
||||
if (!iommu_drvdata || !ctx_drvdata || !ctx_dev) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
|
||||
if (tmp_drvdata == ctx_drvdata) {
|
||||
ret = -EBUSY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
__program_context(iommu_drvdata->base, ctx_dev->num,
|
||||
__pa(priv->pgtable));
|
||||
|
||||
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
|
||||
__flush_iotlb(domain);
|
||||
|
||||
fail:
|
||||
spin_unlock_irqrestore(&msm_iommu_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void msm_iommu_detach_dev(struct iommu_domain *domain,
|
||||
struct device *dev)
|
||||
{
|
||||
struct msm_priv *priv;
|
||||
struct msm_iommu_ctx_dev *ctx_dev;
|
||||
struct msm_iommu_drvdata *iommu_drvdata;
|
||||
struct msm_iommu_ctx_drvdata *ctx_drvdata;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&msm_iommu_lock, flags);
|
||||
priv = domain->priv;
|
||||
|
||||
if (!priv || !dev)
|
||||
goto fail;
|
||||
|
||||
iommu_drvdata = dev_get_drvdata(dev->parent);
|
||||
ctx_drvdata = dev_get_drvdata(dev);
|
||||
ctx_dev = dev->platform_data;
|
||||
|
||||
if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
|
||||
goto fail;
|
||||
|
||||
__flush_iotlb(domain);
|
||||
__reset_context(iommu_drvdata->base, ctx_dev->num);
|
||||
list_del_init(&ctx_drvdata->attached_elm);
|
||||
|
||||
fail:
|
||||
spin_unlock_irqrestore(&msm_iommu_lock, flags);
|
||||
}
|
||||
|
||||
static int msm_iommu_map(struct iommu_domain *domain, unsigned long va,
|
||||
phys_addr_t pa, int order, int prot)
|
||||
{
|
||||
struct msm_priv *priv;
|
||||
unsigned long flags;
|
||||
unsigned long *fl_table;
|
||||
unsigned long *fl_pte;
|
||||
unsigned long fl_offset;
|
||||
unsigned long *sl_table;
|
||||
unsigned long *sl_pte;
|
||||
unsigned long sl_offset;
|
||||
size_t len = 0x1000UL << order;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&msm_iommu_lock, flags);
|
||||
priv = domain->priv;
|
||||
|
||||
if (!priv) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fl_table = priv->pgtable;
|
||||
|
||||
if (len != SZ_16M && len != SZ_1M &&
|
||||
len != SZ_64K && len != SZ_4K) {
|
||||
pr_debug("Bad size: %d\n", len);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!fl_table) {
|
||||
pr_debug("Null page table\n");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fl_offset = FL_OFFSET(va); /* Upper 12 bits */
|
||||
fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
|
||||
|
||||
if (len == SZ_16M) {
|
||||
int i = 0;
|
||||
for (i = 0; i < 16; i++)
|
||||
*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
|
||||
FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
|
||||
FL_SHARED;
|
||||
}
|
||||
|
||||
if (len == SZ_1M)
|
||||
*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE |
|
||||
FL_TYPE_SECT | FL_SHARED;
|
||||
|
||||
/* Need a 2nd level table */
|
||||
if ((len == SZ_4K || len == SZ_64K) && (*fl_pte) == 0) {
|
||||
unsigned long *sl;
|
||||
sl = (unsigned long *) __get_free_pages(GFP_KERNEL,
|
||||
get_order(SZ_4K));
|
||||
|
||||
if (!sl) {
|
||||
pr_debug("Could not allocate second level table\n");
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
memset(sl, 0, SZ_4K);
|
||||
*fl_pte = ((((int)__pa(sl)) & FL_BASE_MASK) | FL_TYPE_TABLE);
|
||||
}
|
||||
|
||||
sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
|
||||
sl_offset = SL_OFFSET(va);
|
||||
sl_pte = sl_table + sl_offset;
|
||||
|
||||
|
||||
if (len == SZ_4K)
|
||||
*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 |
|
||||
SL_SHARED | SL_TYPE_SMALL;
|
||||
|
||||
if (len == SZ_64K) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
|
||||
SL_AP1 | SL_SHARED | SL_TYPE_LARGE;
|
||||
}
|
||||
|
||||
__flush_iotlb(domain);
|
||||
fail:
|
||||
spin_unlock_irqrestore(&msm_iommu_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_iommu_unmap(struct iommu_domain *domain, unsigned long va,
|
||||
int order)
|
||||
{
|
||||
struct msm_priv *priv;
|
||||
unsigned long flags;
|
||||
unsigned long *fl_table;
|
||||
unsigned long *fl_pte;
|
||||
unsigned long fl_offset;
|
||||
unsigned long *sl_table;
|
||||
unsigned long *sl_pte;
|
||||
unsigned long sl_offset;
|
||||
size_t len = 0x1000UL << order;
|
||||
int i, ret = 0;
|
||||
|
||||
spin_lock_irqsave(&msm_iommu_lock, flags);
|
||||
|
||||
priv = domain->priv;
|
||||
|
||||
if (!priv) {
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fl_table = priv->pgtable;
|
||||
|
||||
if (len != SZ_16M && len != SZ_1M &&
|
||||
len != SZ_64K && len != SZ_4K) {
|
||||
pr_debug("Bad length: %d\n", len);
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!fl_table) {
|
||||
pr_debug("Null page table\n");
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fl_offset = FL_OFFSET(va); /* Upper 12 bits */
|
||||
fl_pte = fl_table + fl_offset; /* int pointers, 4 bytes */
|
||||
|
||||
if (*fl_pte == 0) {
|
||||
pr_debug("First level PTE is 0\n");
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Unmap supersection */
|
||||
if (len == SZ_16M)
|
||||
for (i = 0; i < 16; i++)
|
||||
*(fl_pte+i) = 0;
|
||||
|
||||
if (len == SZ_1M)
|
||||
*fl_pte = 0;
|
||||
|
||||
sl_table = (unsigned long *) __va(((*fl_pte) & FL_BASE_MASK));
|
||||
sl_offset = SL_OFFSET(va);
|
||||
sl_pte = sl_table + sl_offset;
|
||||
|
||||
if (len == SZ_64K) {
|
||||
for (i = 0; i < 16; i++)
|
||||
*(sl_pte+i) = 0;
|
||||
}
|
||||
|
||||
if (len == SZ_4K)
|
||||
*sl_pte = 0;
|
||||
|
||||
if (len == SZ_4K || len == SZ_64K) {
|
||||
int used = 0;
|
||||
|
||||
for (i = 0; i < NUM_SL_PTE; i++)
|
||||
if (sl_table[i])
|
||||
used = 1;
|
||||
if (!used) {
|
||||
free_page((unsigned long)sl_table);
|
||||
*fl_pte = 0;
|
||||
}
|
||||
}
|
||||
|
||||
__flush_iotlb(domain);
|
||||
fail:
|
||||
spin_unlock_irqrestore(&msm_iommu_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
|
||||
unsigned long va)
|
||||
{
|
||||
struct msm_priv *priv;
|
||||
struct msm_iommu_drvdata *iommu_drvdata;
|
||||
struct msm_iommu_ctx_drvdata *ctx_drvdata;
|
||||
unsigned int par;
|
||||
unsigned long flags;
|
||||
void __iomem *base;
|
||||
phys_addr_t ret = 0;
|
||||
int ctx;
|
||||
|
||||
spin_lock_irqsave(&msm_iommu_lock, flags);
|
||||
|
||||
priv = domain->priv;
|
||||
if (list_empty(&priv->list_attached))
|
||||
goto fail;
|
||||
|
||||
ctx_drvdata = list_entry(priv->list_attached.next,
|
||||
struct msm_iommu_ctx_drvdata, attached_elm);
|
||||
iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
|
||||
|
||||
base = iommu_drvdata->base;
|
||||
ctx = ctx_drvdata->num;
|
||||
|
||||
/* Invalidate context TLB */
|
||||
SET_CTX_TLBIALL(base, ctx, 0);
|
||||
SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
|
||||
|
||||
if (GET_FAULT(base, ctx))
|
||||
goto fail;
|
||||
|
||||
par = GET_PAR(base, ctx);
|
||||
|
||||
/* We are dealing with a supersection */
|
||||
if (GET_NOFAULT_SS(base, ctx))
|
||||
ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
|
||||
else /* Upper 20 bits from PAR, lower 12 from VA */
|
||||
ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
|
||||
|
||||
fail:
|
||||
spin_unlock_irqrestore(&msm_iommu_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_iommu_domain_has_cap(struct iommu_domain *domain,
|
||||
unsigned long cap)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_ctx_regs(void __iomem *base, int ctx)
|
||||
{
|
||||
unsigned int fsr = GET_FSR(base, ctx);
|
||||
pr_err("FAR = %08x PAR = %08x\n",
|
||||
GET_FAR(base, ctx), GET_PAR(base, ctx));
|
||||
pr_err("FSR = %08x [%s%s%s%s%s%s%s%s%s%s]\n", fsr,
|
||||
(fsr & 0x02) ? "TF " : "",
|
||||
(fsr & 0x04) ? "AFF " : "",
|
||||
(fsr & 0x08) ? "APF " : "",
|
||||
(fsr & 0x10) ? "TLBMF " : "",
|
||||
(fsr & 0x20) ? "HTWDEEF " : "",
|
||||
(fsr & 0x40) ? "HTWSEEF " : "",
|
||||
(fsr & 0x80) ? "MHF " : "",
|
||||
(fsr & 0x10000) ? "SL " : "",
|
||||
(fsr & 0x40000000) ? "SS " : "",
|
||||
(fsr & 0x80000000) ? "MULTI " : "");
|
||||
|
||||
pr_err("FSYNR0 = %08x FSYNR1 = %08x\n",
|
||||
GET_FSYNR0(base, ctx), GET_FSYNR1(base, ctx));
|
||||
pr_err("TTBR0 = %08x TTBR1 = %08x\n",
|
||||
GET_TTBR0(base, ctx), GET_TTBR1(base, ctx));
|
||||
pr_err("SCTLR = %08x ACTLR = %08x\n",
|
||||
GET_SCTLR(base, ctx), GET_ACTLR(base, ctx));
|
||||
pr_err("PRRR = %08x NMRR = %08x\n",
|
||||
GET_PRRR(base, ctx), GET_NMRR(base, ctx));
|
||||
}
|
||||
|
||||
irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct msm_iommu_drvdata *drvdata = dev_id;
|
||||
void __iomem *base;
|
||||
unsigned int fsr = 0;
|
||||
int ncb = 0, i = 0;
|
||||
|
||||
spin_lock(&msm_iommu_lock);
|
||||
|
||||
if (!drvdata) {
|
||||
pr_err("Invalid device ID in context interrupt handler\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
base = drvdata->base;
|
||||
|
||||
pr_err("===== WOAH! =====\n");
|
||||
pr_err("Unexpected IOMMU page fault!\n");
|
||||
pr_err("base = %08x\n", (unsigned int) base);
|
||||
|
||||
ncb = GET_NCB(base)+1;
|
||||
for (i = 0; i < ncb; i++) {
|
||||
fsr = GET_FSR(base, i);
|
||||
if (fsr) {
|
||||
pr_err("Fault occurred in context %d.\n", i);
|
||||
pr_err("Interesting registers:\n");
|
||||
print_ctx_regs(base, i);
|
||||
SET_FSR(base, i, 0x4000000F);
|
||||
}
|
||||
}
|
||||
fail:
|
||||
spin_unlock(&msm_iommu_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct iommu_ops msm_iommu_ops = {
|
||||
.domain_init = msm_iommu_domain_init,
|
||||
.domain_destroy = msm_iommu_domain_destroy,
|
||||
.attach_dev = msm_iommu_attach_dev,
|
||||
.detach_dev = msm_iommu_detach_dev,
|
||||
.map = msm_iommu_map,
|
||||
.unmap = msm_iommu_unmap,
|
||||
.iova_to_phys = msm_iommu_iova_to_phys,
|
||||
.domain_has_cap = msm_iommu_domain_has_cap
|
||||
};
|
||||
|
||||
static int msm_iommu_init(void)
|
||||
{
|
||||
register_iommu(&msm_iommu_ops);
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(msm_iommu_init);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
|
374
arch/arm/mach-msm/iommu_dev.c
Normal file
374
arch/arm/mach-msm/iommu_dev.c
Normal file
@ -0,0 +1,374 @@
|
||||
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <mach/iommu_hw-8xxx.h>
|
||||
#include <mach/iommu.h>
|
||||
|
||||
struct iommu_ctx_iter_data {
|
||||
/* input */
|
||||
const char *name;
|
||||
|
||||
/* output */
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
static struct platform_device *msm_iommu_root_dev;
|
||||
|
||||
static int each_iommu_ctx(struct device *dev, void *data)
|
||||
{
|
||||
struct iommu_ctx_iter_data *res = data;
|
||||
struct msm_iommu_ctx_dev *c = dev->platform_data;
|
||||
|
||||
if (!res || !c || !c->name || !res->name)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcmp(res->name, c->name)) {
|
||||
res->dev = dev;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int each_iommu(struct device *dev, void *data)
|
||||
{
|
||||
return device_for_each_child(dev, data, each_iommu_ctx);
|
||||
}
|
||||
|
||||
struct device *msm_iommu_get_ctx(const char *ctx_name)
|
||||
{
|
||||
struct iommu_ctx_iter_data r;
|
||||
int found;
|
||||
|
||||
if (!msm_iommu_root_dev) {
|
||||
pr_err("No root IOMMU device.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r.name = ctx_name;
|
||||
found = device_for_each_child(&msm_iommu_root_dev->dev, &r, each_iommu);
|
||||
|
||||
if (!found) {
|
||||
pr_err("Could not find context <%s>\n", ctx_name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return r.dev;
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_iommu_get_ctx);
|
||||
|
||||
static void msm_iommu_reset(void __iomem *base)
|
||||
{
|
||||
int ctx, ncb;
|
||||
|
||||
SET_RPUE(base, 0);
|
||||
SET_RPUEIE(base, 0);
|
||||
SET_ESRRESTORE(base, 0);
|
||||
SET_TBE(base, 0);
|
||||
SET_CR(base, 0);
|
||||
SET_SPDMBE(base, 0);
|
||||
SET_TESTBUSCR(base, 0);
|
||||
SET_TLBRSW(base, 0);
|
||||
SET_GLOBAL_TLBIALL(base, 0);
|
||||
SET_RPU_ACR(base, 0);
|
||||
SET_TLBLKCRWE(base, 1);
|
||||
ncb = GET_NCB(base)+1;
|
||||
|
||||
for (ctx = 0; ctx < ncb; ctx++) {
|
||||
SET_BPRCOSH(base, ctx, 0);
|
||||
SET_BPRCISH(base, ctx, 0);
|
||||
SET_BPRCNSH(base, ctx, 0);
|
||||
SET_BPSHCFG(base, ctx, 0);
|
||||
SET_BPMTCFG(base, ctx, 0);
|
||||
SET_ACTLR(base, ctx, 0);
|
||||
SET_SCTLR(base, ctx, 0);
|
||||
SET_FSRRESTORE(base, ctx, 0);
|
||||
SET_TTBR0(base, ctx, 0);
|
||||
SET_TTBR1(base, ctx, 0);
|
||||
SET_TTBCR(base, ctx, 0);
|
||||
SET_BFBCR(base, ctx, 0);
|
||||
SET_PAR(base, ctx, 0);
|
||||
SET_FAR(base, ctx, 0);
|
||||
SET_CTX_TLBIALL(base, ctx, 0);
|
||||
SET_TLBFLPTER(base, ctx, 0);
|
||||
SET_TLBSLPTER(base, ctx, 0);
|
||||
SET_TLBLKCR(base, ctx, 0);
|
||||
SET_PRRR(base, ctx, 0);
|
||||
SET_NMRR(base, ctx, 0);
|
||||
SET_CONTEXTIDR(base, ctx, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int msm_iommu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *r;
|
||||
struct clk *iommu_clk;
|
||||
struct msm_iommu_drvdata *drvdata;
|
||||
struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
|
||||
void __iomem *regs_base;
|
||||
resource_size_t len;
|
||||
int ret = 0, ncb, nm2v, irq;
|
||||
|
||||
if (pdev->id != -1) {
|
||||
drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
|
||||
|
||||
if (!drvdata) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!iommu_dev) {
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (iommu_dev->clk_rate != 0) {
|
||||
iommu_clk = clk_get(&pdev->dev, "iommu_clk");
|
||||
|
||||
if (IS_ERR(iommu_clk)) {
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (iommu_dev->clk_rate > 0) {
|
||||
ret = clk_set_rate(iommu_clk,
|
||||
iommu_dev->clk_rate);
|
||||
if (ret) {
|
||||
clk_put(iommu_clk);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_enable(iommu_clk);
|
||||
if (ret) {
|
||||
clk_put(iommu_clk);
|
||||
goto fail;
|
||||
}
|
||||
clk_put(iommu_clk);
|
||||
}
|
||||
|
||||
r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
|
||||
"physbase");
|
||||
if (!r) {
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
len = r->end - r->start + 1;
|
||||
|
||||
r = request_mem_region(r->start, len, r->name);
|
||||
if (!r) {
|
||||
pr_err("Could not request memory region: "
|
||||
"start=%p, len=%d\n", (void *) r->start, len);
|
||||
ret = -EBUSY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
regs_base = ioremap(r->start, len);
|
||||
|
||||
if (!regs_base) {
|
||||
pr_err("Could not ioremap: start=%p, len=%d\n",
|
||||
(void *) r->start, len);
|
||||
ret = -EBUSY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "secure_irq");
|
||||
if (irq < 0) {
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mb();
|
||||
|
||||
if (GET_IDR(regs_base) == 0) {
|
||||
pr_err("Invalid IDR value detected\n");
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = request_irq(irq, msm_iommu_fault_handler, 0,
|
||||
"msm_iommu_secure_irpt_handler", drvdata);
|
||||
if (ret) {
|
||||
pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
msm_iommu_reset(regs_base);
|
||||
drvdata->base = regs_base;
|
||||
drvdata->irq = irq;
|
||||
|
||||
nm2v = GET_NM2VCBMT((unsigned long) regs_base);
|
||||
ncb = GET_NCB((unsigned long) regs_base);
|
||||
|
||||
pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
|
||||
iommu_dev->name, regs_base, irq, ncb+1);
|
||||
|
||||
platform_set_drvdata(pdev, drvdata);
|
||||
} else
|
||||
msm_iommu_root_dev = pdev;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
kfree(drvdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_iommu_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_iommu_drvdata *drv = NULL;
|
||||
|
||||
drv = platform_get_drvdata(pdev);
|
||||
if (drv) {
|
||||
memset(drv, 0, sizeof(struct msm_iommu_drvdata));
|
||||
kfree(drv);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int msm_iommu_ctx_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
|
||||
struct msm_iommu_drvdata *drvdata;
|
||||
struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
|
||||
int i, ret = 0;
|
||||
if (!c || !pdev->dev.parent) {
|
||||
ret = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
drvdata = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
if (!drvdata) {
|
||||
ret = -ENODEV;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ctx_drvdata = kzalloc(sizeof(*ctx_drvdata), GFP_KERNEL);
|
||||
if (!ctx_drvdata) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
ctx_drvdata->num = c->num;
|
||||
ctx_drvdata->pdev = pdev;
|
||||
|
||||
INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
|
||||
platform_set_drvdata(pdev, ctx_drvdata);
|
||||
|
||||
/* Program the M2V tables for this context */
|
||||
for (i = 0; i < MAX_NUM_MIDS; i++) {
|
||||
int mid = c->mids[i];
|
||||
if (mid == -1)
|
||||
break;
|
||||
|
||||
SET_M2VCBR_N(drvdata->base, mid, 0);
|
||||
SET_CBACR_N(drvdata->base, c->num, 0);
|
||||
|
||||
/* Set VMID = MID */
|
||||
SET_VMID(drvdata->base, mid, mid);
|
||||
|
||||
/* Set the context number for that MID to this context */
|
||||
SET_CBNDX(drvdata->base, mid, c->num);
|
||||
|
||||
/* Set MID associated with this context bank */
|
||||
SET_CBVMID(drvdata->base, c->num, mid);
|
||||
|
||||
/* Set security bit override to be Non-secure */
|
||||
SET_NSCFG(drvdata->base, mid, 3);
|
||||
}
|
||||
|
||||
pr_info("context device %s with bank index %d\n", c->name, c->num);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
kfree(ctx_drvdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int msm_iommu_ctx_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct msm_iommu_ctx_drvdata *drv = NULL;
|
||||
drv = platform_get_drvdata(pdev);
|
||||
if (drv) {
|
||||
memset(drv, 0, sizeof(struct msm_iommu_ctx_drvdata));
|
||||
kfree(drv);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver msm_iommu_driver = {
|
||||
.driver = {
|
||||
.name = "msm_iommu",
|
||||
},
|
||||
.probe = msm_iommu_probe,
|
||||
.remove = msm_iommu_remove,
|
||||
};
|
||||
|
||||
static struct platform_driver msm_iommu_ctx_driver = {
|
||||
.driver = {
|
||||
.name = "msm_iommu_ctx",
|
||||
},
|
||||
.probe = msm_iommu_ctx_probe,
|
||||
.remove = msm_iommu_ctx_remove,
|
||||
};
|
||||
|
||||
static int msm_iommu_driver_init(void)
|
||||
{
|
||||
int ret;
|
||||
ret = platform_driver_register(&msm_iommu_driver);
|
||||
if (ret != 0) {
|
||||
pr_err("Failed to register IOMMU driver\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = platform_driver_register(&msm_iommu_ctx_driver);
|
||||
if (ret != 0) {
|
||||
pr_err("Failed to register IOMMU context driver\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void msm_iommu_driver_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&msm_iommu_ctx_driver);
|
||||
platform_driver_unregister(&msm_iommu_driver);
|
||||
}
|
||||
|
||||
subsys_initcall(msm_iommu_driver_init);
|
||||
module_exit(msm_iommu_driver_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
|
@ -28,7 +28,6 @@
|
||||
#ifndef MSM_DGT_BASE
|
||||
#define MSM_DGT_BASE (MSM_GPT_BASE + 0x10)
|
||||
#endif
|
||||
#define MSM_DGT_SHIFT (5)
|
||||
|
||||
#define TIMER_MATCH_VAL 0x0000
|
||||
#define TIMER_COUNT_VAL 0x0004
|
||||
@ -36,12 +35,28 @@
|
||||
#define TIMER_ENABLE_CLR_ON_MATCH_EN 2
|
||||
#define TIMER_ENABLE_EN 1
|
||||
#define TIMER_CLEAR 0x000C
|
||||
|
||||
#define DGT_CLK_CTL 0x0034
|
||||
enum {
|
||||
DGT_CLK_CTL_DIV_1 = 0,
|
||||
DGT_CLK_CTL_DIV_2 = 1,
|
||||
DGT_CLK_CTL_DIV_3 = 2,
|
||||
DGT_CLK_CTL_DIV_4 = 3,
|
||||
};
|
||||
#define CSR_PROTECTION 0x0020
|
||||
#define CSR_PROTECTION_EN 1
|
||||
|
||||
#define GPT_HZ 32768
|
||||
|
||||
#if defined(CONFIG_ARCH_QSD8X50)
|
||||
#define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
|
||||
#define MSM_DGT_SHIFT (0)
|
||||
#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60)
|
||||
#define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
|
||||
#define MSM_DGT_SHIFT (0)
|
||||
#else
|
||||
#define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */
|
||||
#define MSM_DGT_SHIFT (5)
|
||||
#endif
|
||||
|
||||
struct msm_clock {
|
||||
struct clock_event_device clockevent;
|
||||
@ -170,6 +185,10 @@ static void __init msm_timer_init(void)
|
||||
int i;
|
||||
int res;
|
||||
|
||||
#ifdef CONFIG_ARCH_MSM8X60
|
||||
writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(msm_clocks); i++) {
|
||||
struct msm_clock *clock = &msm_clocks[i];
|
||||
struct clock_event_device *ce = &clock->clockevent;
|
||||
|
Loading…
Reference in New Issue
Block a user