summaryrefslogtreecommitdiff
path: root/arch/arm/mach-u300
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-u300')
-rw-r--r--arch/arm/mach-u300/Makefile2
-rw-r--r--arch/arm/mach-u300/clock.c6
-rw-r--r--arch/arm/mach-u300/core.c179
-rw-r--r--arch/arm/mach-u300/gpio.c700
-rw-r--r--arch/arm/mach-u300/include/mach/coh901318.h7
-rw-r--r--arch/arm/mach-u300/include/mach/memory.h6
-rw-r--r--arch/arm/mach-u300/mmc.c160
-rw-r--r--arch/arm/mach-u300/spi.c21
-rw-r--r--arch/arm/mach-u300/timer.c18
-rw-r--r--arch/arm/mach-u300/u300.c2
10 files changed, 214 insertions, 887 deletions
diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile
index fab46fe9a71f..8fd354aaf0a7 100644
--- a/arch/arm/mach-u300/Makefile
+++ b/arch/arm/mach-u300/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel, U300 machine.
#
-obj-y := core.o clock.o timer.o gpio.o padmux.o
+obj-y := core.o clock.o timer.o padmux.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c
index fabcc49abe80..5535dd0a78c9 100644
--- a/arch/arm/mach-u300/clock.c
+++ b/arch/arm/mach-u300/clock.c
@@ -263,7 +263,7 @@ static void disable_i2s0_vcxo(void)
val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
val &= ~U300_SYSCON_CCR_I2S0_USE_VCXO;
writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
- /* Deactivate VCXO if noone else is using VCXO */
+ /* Deactivate VCXO if no one else is using VCXO */
if (!(val & U300_SYSCON_CCR_I2S1_USE_VCXO))
val &= ~U300_SYSCON_CCR_TURN_VCXO_ON;
writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
@@ -283,7 +283,7 @@ static void disable_i2s1_vcxo(void)
val = readw(U300_SYSCON_VBASE + U300_SYSCON_CCR);
val &= ~U300_SYSCON_CCR_I2S1_USE_VCXO;
writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
- /* Deactivate VCXO if noone else is using VCXO */
+ /* Deactivate VCXO if no one else is using VCXO */
if (!(val & U300_SYSCON_CCR_I2S0_USE_VCXO))
val &= ~U300_SYSCON_CCR_TURN_VCXO_ON;
writew(val, U300_SYSCON_VBASE + U300_SYSCON_CCR);
@@ -649,7 +649,7 @@ static unsigned long clk_round_rate_cpuclk(struct clk *clk, unsigned long rate)
*/
long clk_round_rate(struct clk *clk, unsigned long rate)
{
- /* TODO: get apropriate switches for EMIFCLK, AHBCLK and MCLK */
+ /* TODO: get appropriate switches for EMIFCLK, AHBCLK and MCLK */
/* Else default to fixed value */
if (clk->round_rate) {
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index aa53ee22438f..513d6abec1f5 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -3,7 +3,7 @@
* arch/arm/mach-u300/core.c
*
*
- * Copyright (C) 2007-2010 ST-Ericsson AB
+ * Copyright (C) 2007-2010 ST-Ericsson SA
* License terms: GNU General Public License (GPL) version 2
* Core platform support, IRQ handling and device definitions.
* Author: Linus Walleij <linus.walleij@stericsson.com>
@@ -16,7 +16,9 @@
#include <linux/device.h>
#include <linux/mm.h>
#include <linux/termios.h>
+#include <linux/dmaengine.h>
#include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/clk.h>
@@ -96,10 +98,20 @@ void __init u300_map_io(void)
* Declaration of devices found on the U300 board and
* their respective memory locations.
*/
+
+static struct amba_pl011_data uart0_plat_data = {
+#ifdef CONFIG_COH901318
+ .dma_filter = coh901318_filter_id,
+ .dma_rx_param = (void *) U300_DMA_UART0_RX,
+ .dma_tx_param = (void *) U300_DMA_UART0_TX,
+#endif
+};
+
static struct amba_device uart0_device = {
.dev = {
+ .coherent_dma_mask = ~0,
.init_name = "uart0", /* Slow device at 0x3000 offset */
- .platform_data = NULL,
+ .platform_data = &uart0_plat_data,
},
.res = {
.start = U300_UART0_BASE,
@@ -111,10 +123,19 @@ static struct amba_device uart0_device = {
/* The U335 have an additional UART1 on the APP CPU */
#ifdef CONFIG_MACH_U300_BS335
+static struct amba_pl011_data uart1_plat_data = {
+#ifdef CONFIG_COH901318
+ .dma_filter = coh901318_filter_id,
+ .dma_rx_param = (void *) U300_DMA_UART1_RX,
+ .dma_tx_param = (void *) U300_DMA_UART1_TX,
+#endif
+};
+
static struct amba_device uart1_device = {
.dev = {
+ .coherent_dma_mask = ~0,
.init_name = "uart1", /* Fast device at 0x7000 offset */
- .platform_data = NULL,
+ .platform_data = &uart1_plat_data,
},
.res = {
.start = U300_UART1_BASE,
@@ -960,42 +981,37 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
.priority_high = 0,
.dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220,
},
+ /*
+ * Don't set up device address, burst count or size of src
+ * or dst bus for this peripheral - handled by PrimeCell
+ * DMA extension.
+ */
{
.number = U300_DMA_MMCSD_RX_TX,
.name = "MMCSD RX TX",
.priority_high = 0,
- .dev_addr = U300_MMCSD_BASE + 0x080,
.param.config = COH901318_CX_CFG_CH_DISABLE |
COH901318_CX_CFG_LCR_DISABLE |
COH901318_CX_CFG_TC_IRQ_ENABLE |
COH901318_CX_CFG_BE_IRQ_ENABLE,
.param.ctrl_lli_chained = 0 |
COH901318_CX_CTRL_TC_ENABLE |
- COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
- COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
- COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
COH901318_CX_CTRL_MASTER_MODE_M1RW |
COH901318_CX_CTRL_TCP_ENABLE |
- COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_DISABLE |
COH901318_CX_CTRL_HSP_ENABLE |
COH901318_CX_CTRL_HSS_DISABLE |
COH901318_CX_CTRL_DDMA_LEGACY,
.param.ctrl_lli = 0 |
COH901318_CX_CTRL_TC_ENABLE |
- COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
- COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
- COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
COH901318_CX_CTRL_MASTER_MODE_M1RW |
COH901318_CX_CTRL_TCP_ENABLE |
- COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_DISABLE |
COH901318_CX_CTRL_HSP_ENABLE |
COH901318_CX_CTRL_HSS_DISABLE |
COH901318_CX_CTRL_DDMA_LEGACY,
.param.ctrl_lli_last = 0 |
COH901318_CX_CTRL_TC_ENABLE |
- COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
- COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
- COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
COH901318_CX_CTRL_MASTER_MODE_M1RW |
COH901318_CX_CTRL_TCP_DISABLE |
COH901318_CX_CTRL_TC_IRQ_ENABLE |
@@ -1014,15 +1030,76 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
.name = "MSPRO RX",
.priority_high = 0,
},
+ /*
+ * Don't set up device address, burst count or size of src
+ * or dst bus for this peripheral - handled by PrimeCell
+ * DMA extension.
+ */
{
.number = U300_DMA_UART0_TX,
.name = "UART0 TX",
.priority_high = 0,
+ .param.config = COH901318_CX_CFG_CH_DISABLE |
+ COH901318_CX_CFG_LCR_DISABLE |
+ COH901318_CX_CFG_TC_IRQ_ENABLE |
+ COH901318_CX_CFG_BE_IRQ_ENABLE,
+ .param.ctrl_lli_chained = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_DISABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+ .param.ctrl_lli = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+ .param.ctrl_lli_last = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
},
{
.number = U300_DMA_UART0_RX,
.name = "UART0 RX",
.priority_high = 0,
+ .param.config = COH901318_CX_CFG_CH_DISABLE |
+ COH901318_CX_CFG_LCR_DISABLE |
+ COH901318_CX_CFG_TC_IRQ_ENABLE |
+ COH901318_CX_CFG_BE_IRQ_ENABLE,
+ .param.ctrl_lli_chained = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_DISABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+ .param.ctrl_lli = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+ .param.ctrl_lli_last = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
},
{
.number = U300_DMA_APEX_TX,
@@ -1080,7 +1157,7 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
COH901318_CX_CTRL_MASTER_MODE_M1RW |
COH901318_CX_CTRL_TCP_ENABLE |
- COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_TC_IRQ_DISABLE |
COH901318_CX_CTRL_HSP_ENABLE |
COH901318_CX_CTRL_HSS_DISABLE |
COH901318_CX_CTRL_DDMA_LEGACY |
@@ -1252,15 +1329,77 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
.name = "XGAM PDI",
.priority_high = 0,
},
+ /*
+ * Don't set up device address, burst count or size of src
+ * or dst bus for this peripheral - handled by PrimeCell
+ * DMA extension.
+ */
{
.number = U300_DMA_SPI_TX,
.name = "SPI TX",
.priority_high = 0,
+ .param.config = COH901318_CX_CFG_CH_DISABLE |
+ COH901318_CX_CFG_LCR_DISABLE |
+ COH901318_CX_CFG_TC_IRQ_ENABLE |
+ COH901318_CX_CFG_BE_IRQ_ENABLE,
+ .param.ctrl_lli_chained = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_DISABLE |
+ COH901318_CX_CTRL_TC_IRQ_DISABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+ .param.ctrl_lli = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_DISABLE |
+ COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+ .param.ctrl_lli_last = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_DISABLE |
+ COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
},
{
.number = U300_DMA_SPI_RX,
.name = "SPI RX",
.priority_high = 0,
+ .param.config = COH901318_CX_CFG_CH_DISABLE |
+ COH901318_CX_CFG_LCR_DISABLE |
+ COH901318_CX_CFG_TC_IRQ_ENABLE |
+ COH901318_CX_CFG_BE_IRQ_ENABLE,
+ .param.ctrl_lli_chained = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_DISABLE |
+ COH901318_CX_CTRL_TC_IRQ_DISABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+ .param.ctrl_lli = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_DISABLE |
+ COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+ .param.ctrl_lli_last = 0 |
+ COH901318_CX_CTRL_TC_ENABLE |
+ COH901318_CX_CTRL_MASTER_MODE_M1RW |
+ COH901318_CX_CTRL_TCP_DISABLE |
+ COH901318_CX_CTRL_TC_IRQ_ENABLE |
+ COH901318_CX_CTRL_HSP_ENABLE |
+ COH901318_CX_CTRL_HSS_DISABLE |
+ COH901318_CX_CTRL_DDMA_LEGACY,
+
},
{
.number = U300_DMA_GENERAL_PURPOSE_0,
@@ -1617,7 +1756,7 @@ static void __init u300_init_check_chip(void)
#endif
#ifdef CONFIG_MACH_U300_BS335
if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
- printk(KERN_ERR "Platform configured for BS365 " \
+ printk(KERN_ERR "Platform configured for BS335 " \
" with DB3350 but %s detected, expect problems!",
chipname);
}
@@ -1692,12 +1831,12 @@ void __init u300_init_devices(void)
/* Register subdevices on the I2C buses */
u300_i2c_register_board_devices();
- /* Register subdevices on the SPI bus */
- u300_spi_register_board_devices();
-
/* Register the platform devices */
platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+ /* Register subdevices on the SPI bus */
+ u300_spi_register_board_devices();
+
#ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
/*
* Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
diff --git a/arch/arm/mach-u300/gpio.c b/arch/arm/mach-u300/gpio.c
deleted file mode 100644
index d92790140fe5..000000000000
--- a/arch/arm/mach-u300/gpio.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/gpio.c
- *
- *
- * Copyright (C) 2007-2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 GPIO module.
- * This can driver either of the two basic GPIO cores
- * available in the U300 platforms:
- * COH 901 335 - Used in DB3150 (U300 1.0) and DB3200 (U330 1.0)
- * COH 901 571/3 - Used in DB3210 (U365 2.0) and DB3350 (U335 1.0)
- * Notice that you also have inline macros in <asm-arch/gpio.h>
- * Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
- *
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-
-/* Reference to GPIO block clock */
-static struct clk *clk;
-
-/* Memory resource */
-static struct resource *memres;
-static void __iomem *virtbase;
-static struct device *gpiodev;
-
-struct u300_gpio_port {
- const char *name;
- int irq;
- int number;
-};
-
-
-static struct u300_gpio_port gpio_ports[] = {
- {
- .name = "gpio0",
- .number = 0,
- },
- {
- .name = "gpio1",
- .number = 1,
- },
- {
- .name = "gpio2",
- .number = 2,
- },
-#ifdef U300_COH901571_3
- {
- .name = "gpio3",
- .number = 3,
- },
- {
- .name = "gpio4",
- .number = 4,
- },
-#ifdef CONFIG_MACH_U300_BS335
- {
- .name = "gpio5",
- .number = 5,
- },
- {
- .name = "gpio6",
- .number = 6,
- },
-#endif
-#endif
-
-};
-
-
-#ifdef U300_COH901571_3
-
-/* Default input value */
-#define DEFAULT_OUTPUT_LOW 0
-#define DEFAULT_OUTPUT_HIGH 1
-
-/* GPIO Pull-Up status */
-#define DISABLE_PULL_UP 0
-#define ENABLE_PULL_UP 1
-
-#define GPIO_NOT_USED 0
-#define GPIO_IN 1
-#define GPIO_OUT 2
-
-struct u300_gpio_configuration_data {
- unsigned char pin_usage;
- unsigned char default_output_value;
- unsigned char pull_up;
-};
-
-/* Initial configuration */
-const struct u300_gpio_configuration_data
-u300_gpio_config[U300_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = {
-#ifdef CONFIG_MACH_U300_BS335
- /* Port 0, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
- },
- /* Port 1, pins 0-7 */
- {
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
- },
- /* Port 2, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
- },
- /* Port 3, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
- },
- /* Port 4, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
- },
- /* Port 5, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
- },
- /* Port 6, pind 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
- }
-#endif
-
-#ifdef CONFIG_MACH_U300_BS365
- /* Port 0, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
- },
- /* Port 1, pins 0-7 */
- {
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_HIGH, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP}
- },
- /* Port 2, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, DISABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
- },
- /* Port 3, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
- },
- /* Port 4, pins 0-7 */
- {
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_IN, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- /* These 4 pins doesn't exist on DB3210 */
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP},
- {GPIO_OUT, DEFAULT_OUTPUT_LOW, ENABLE_PULL_UP}
- }
-#endif
-};
-#endif
-
-
-/* No users == we can power down GPIO */
-static int gpio_users;
-
-struct gpio_struct {
- int (*callback)(void *);
- void *data;
- int users;
-};
-
-static struct gpio_struct gpio_pin[U300_GPIO_MAX];
-
-/*
- * Let drivers register callback in order to get notified when there is
- * an interrupt on the gpio pin
- */
-int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data)
-{
- if (gpio_pin[gpio].callback)
- dev_warn(gpiodev, "%s: WARNING: callback already "
- "registered for gpio pin#%d\n", __func__, gpio);
- gpio_pin[gpio].callback = func;
- gpio_pin[gpio].data = data;
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_register_callback);
-
-int gpio_unregister_callback(unsigned gpio)
-{
- if (!gpio_pin[gpio].callback)
- dev_warn(gpiodev, "%s: WARNING: callback already "
- "unregistered for gpio pin#%d\n", __func__, gpio);
- gpio_pin[gpio].callback = NULL;
- gpio_pin[gpio].data = NULL;
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_unregister_callback);
-
-/* Non-zero means valid */
-int gpio_is_valid(int number)
-{
- if (number >= 0 &&
- number < (U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT))
- return 1;
- return 0;
-}
-EXPORT_SYMBOL(gpio_is_valid);
-
-int gpio_request(unsigned gpio, const char *label)
-{
- if (gpio_pin[gpio].users)
- return -EINVAL;
- else
- gpio_pin[gpio].users++;
-
- gpio_users++;
-
- return 0;
-}
-EXPORT_SYMBOL(gpio_request);
-
-void gpio_free(unsigned gpio)
-{
- gpio_users--;
- gpio_pin[gpio].users--;
- if (unlikely(gpio_pin[gpio].users < 0)) {
- dev_warn(gpiodev, "warning: gpio#%d release mismatch\n",
- gpio);
- gpio_pin[gpio].users = 0;
- }
-
- return;
-}
-EXPORT_SYMBOL(gpio_free);
-
-/* This returns zero or nonzero */
-int gpio_get_value(unsigned gpio)
-{
- return readl(virtbase + U300_GPIO_PXPDIR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING) & (1 << (gpio & 0x07));
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-/*
- * We hope that the compiler will optimize away the unused branch
- * in case "value" is a constant
- */
-void gpio_set_value(unsigned gpio, int value)
-{
- u32 val;
- unsigned long flags;
-
- local_irq_save(flags);
- if (value) {
- /* set */
- val = readl(virtbase + U300_GPIO_PXPDOR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
- & (1 << (gpio & 0x07));
- writel(val | (1 << (gpio & 0x07)), virtbase +
- U300_GPIO_PXPDOR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
- } else {
- /* clear */
- val = readl(virtbase + U300_GPIO_PXPDOR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING)
- & (1 << (gpio & 0x07));
- writel(val & ~(1 << (gpio & 0x07)), virtbase +
- U300_GPIO_PXPDOR +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
- }
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(gpio_set_value);
-
-int gpio_direction_input(unsigned gpio)
-{
- unsigned long flags;
- u32 val;
-
- if (gpio > U300_GPIO_MAX)
- return -EINVAL;
-
- local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- /* Mask out this pin*/
- val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
- /* This is not needed since it sets the bits to zero.*/
- /* val |= (U300_GPIO_PXPCR_PIN_MODE_INPUT << (gpio*2)); */
- writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_input);
-
-int gpio_direction_output(unsigned gpio, int value)
-{
- unsigned long flags;
- u32 val;
-
- if (gpio > U300_GPIO_MAX)
- return -EINVAL;
-
- local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- /* Mask out this pin */
- val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((gpio & 0x07) << 1));
- /*
- * FIXME: configure for push/pull, open drain or open source per pin
- * in setup. The current driver will only support push/pull.
- */
- val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL
- << ((gpio & 0x07) << 1));
- writel(val, virtbase + U300_GPIO_PXPCR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- gpio_set_value(gpio, value);
- local_irq_restore(flags);
- return 0;
-}
-EXPORT_SYMBOL(gpio_direction_output);
-
-/*
- * Enable an IRQ, edge is rising edge (!= 0) or falling edge (==0).
- */
-void enable_irq_on_gpio_pin(unsigned gpio, int edge)
-{
- u32 val;
- unsigned long flags;
- local_irq_save(flags);
-
- val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- val |= (1 << (gpio & 0x07));
- writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- val = readl(virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- if (edge)
- val |= (1 << (gpio & 0x07));
- else
- val &= ~(1 << (gpio & 0x07));
- writel(val, virtbase + U300_GPIO_PXICR + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(enable_irq_on_gpio_pin);
-
-void disable_irq_on_gpio_pin(unsigned gpio)
-{
- u32 val;
- unsigned long flags;
-
- local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- val &= ~(1 << (gpio & 0x07));
- writel(val, virtbase + U300_GPIO_PXIEN + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(disable_irq_on_gpio_pin);
-
-/* Enable (value == 0) or disable (value == 1) internal pullup */
-void gpio_pullup(unsigned gpio, int value)
-{
- u32 val;
- unsigned long flags;
-
- local_irq_save(flags);
- if (value) {
- val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- writel(val | (1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
- } else {
- val = readl(virtbase + U300_GPIO_PXPER + PIN_TO_PORT(gpio) *
- U300_GPIO_PORTX_SPACING);
- writel(val & ~(1 << (gpio & 0x07)), virtbase + U300_GPIO_PXPER +
- PIN_TO_PORT(gpio) * U300_GPIO_PORTX_SPACING);
- }
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(gpio_pullup);
-
-static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
-{
- struct u300_gpio_port *port = dev_id;
- u32 val;
- int pin;
-
- /* Read event register */
- val = readl(virtbase + U300_GPIO_PXIEV + port->number *
- U300_GPIO_PORTX_SPACING);
- /* Mask with enable register */
- val &= readl(virtbase + U300_GPIO_PXIEV + port->number *
- U300_GPIO_PORTX_SPACING);
- /* Mask relevant bits */
- val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK;
- /* ACK IRQ (clear event) */
- writel(val, virtbase + U300_GPIO_PXIEV + port->number *
- U300_GPIO_PORTX_SPACING);
- /* Print message */
- while (val != 0) {
- unsigned gpio;
-
- pin = __ffs(val);
- /* mask off this pin */
- val &= ~(1 << pin);
- gpio = (port->number << 3) + pin;
-
- if (gpio_pin[gpio].callback)
- (void)gpio_pin[gpio].callback(gpio_pin[gpio].data);
- else
- dev_dbg(gpiodev, "stray GPIO IRQ on line %d\n",
- gpio);
- }
- return IRQ_HANDLED;
-}
-
-static void gpio_set_initial_values(void)
-{
-#ifdef U300_COH901571_3
- int i, j;
- unsigned long flags;
- u32 val;
-
- /* Write default values to all pins */
- for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
- val = 0;
- for (j = 0; j < 8; j++)
- val |= (u32) (u300_gpio_config[i][j].default_output_value != DEFAULT_OUTPUT_LOW) << j;
- local_irq_save(flags);
- writel(val, virtbase + U300_GPIO_PXPDOR + i * U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
- }
-
- /*
- * Put all pins that are set to either 'GPIO_OUT' or 'GPIO_NOT_USED'
- * to output and 'GPIO_IN' to input for each port. And initialize
- * default value on outputs.
- */
- for (i = 0; i < U300_GPIO_NUM_PORTS; i++) {
- for (j = 0; j < U300_GPIO_PINS_PER_PORT; j++) {
- local_irq_save(flags);
- val = readl(virtbase + U300_GPIO_PXPCR +
- i * U300_GPIO_PORTX_SPACING);
- /* Mask out this pin */
- val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << (j << 1));
-
- if (u300_gpio_config[i][j].pin_usage != GPIO_IN)
- val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL << (j << 1));
- writel(val, virtbase + U300_GPIO_PXPCR +
- i * U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
- }
- }
-
- /* Enable or disable the internal pull-ups in the GPIO ASIC block */
- for (i = 0; i < U300_GPIO_MAX; i++) {
- val = 0;
- for (j = 0; j < 8; j++)
- val |= (u32)((u300_gpio_config[i][j].pull_up == DISABLE_PULL_UP) << j);
- local_irq_save(flags);
- writel(val, virtbase + U300_GPIO_PXPER + i * U300_GPIO_PORTX_SPACING);
- local_irq_restore(flags);
- }
-#endif
-}
-
-static int __init gpio_probe(struct platform_device *pdev)
-{
- u32 val;
- int err = 0;
- int i;
- int num_irqs;
-
- gpiodev = &pdev->dev;
- memset(gpio_pin, 0, sizeof(gpio_pin));
-
- /* Get GPIO clock */
- clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk)) {
- err = PTR_ERR(clk);
- dev_err(gpiodev, "could not get GPIO clock\n");
- goto err_no_clk;
- }
- err = clk_enable(clk);
- if (err) {
- dev_err(gpiodev, "could not enable GPIO clock\n");
- goto err_no_clk_enable;
- }
-
- memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!memres)
- goto err_no_resource;
-
- if (request_mem_region(memres->start, memres->end - memres->start, "GPIO Controller")
- == NULL) {
- err = -ENODEV;
- goto err_no_ioregion;
- }
-
- virtbase = ioremap(memres->start, resource_size(memres));
- if (!virtbase) {
- err = -ENOMEM;
- goto err_no_ioremap;
- }
- dev_info(gpiodev, "remapped 0x%08x to %p\n",
- memres->start, virtbase);
-
-#ifdef U300_COH901335
- dev_info(gpiodev, "initializing GPIO Controller COH 901 335\n");
- /* Turn on the GPIO block */
- writel(U300_GPIO_CR_BLOCK_CLOCK_ENABLE, virtbase + U300_GPIO_CR);
-#endif
-
-#ifdef U300_COH901571_3
- dev_info(gpiodev, "initializing GPIO Controller COH 901 571/3\n");
- val = readl(virtbase + U300_GPIO_CR);
- dev_info(gpiodev, "COH901571/3 block version: %d, " \
- "number of cores: %d\n",
- ((val & 0x0000FE00) >> 9),
- ((val & 0x000001FC) >> 2));
- writel(U300_GPIO_CR_BLOCK_CLKRQ_ENABLE, virtbase + U300_GPIO_CR);
-#endif
-
- gpio_set_initial_values();
-
- for (num_irqs = 0 ; num_irqs < U300_GPIO_NUM_PORTS; num_irqs++) {
-
- gpio_ports[num_irqs].irq =
- platform_get_irq_byname(pdev,
- gpio_ports[num_irqs].name);
-
- err = request_irq(gpio_ports[num_irqs].irq,
- gpio_irq_handler, IRQF_DISABLED,
- gpio_ports[num_irqs].name,
- &gpio_ports[num_irqs]);
- if (err) {
- dev_err(gpiodev, "cannot allocate IRQ for %s!\n",
- gpio_ports[num_irqs].name);
- goto err_no_irq;
- }
- /* Turns off PortX_irq_force */
- writel(0x0, virtbase + U300_GPIO_PXIFR +
- num_irqs * U300_GPIO_PORTX_SPACING);
- }
-
- return 0;
-
- err_no_irq:
- for (i = 0; i < num_irqs; i++)
- free_irq(gpio_ports[i].irq, &gpio_ports[i]);
- iounmap(virtbase);
- err_no_ioremap:
- release_mem_region(memres->start, memres->end - memres->start);
- err_no_ioregion:
- err_no_resource:
- clk_disable(clk);
- err_no_clk_enable:
- clk_put(clk);
- err_no_clk:
- dev_info(gpiodev, "module ERROR:%d\n", err);
- return err;
-}
-
-static int __exit gpio_remove(struct platform_device *pdev)
-{
- int i;
-
- /* Turn off the GPIO block */
- writel(0x00000000U, virtbase + U300_GPIO_CR);
- for (i = 0 ; i < U300_GPIO_NUM_PORTS; i++)
- free_irq(gpio_ports[i].irq, &gpio_ports[i]);
- iounmap(virtbase);
- release_mem_region(memres->start, memres->end - memres->start);
- clk_disable(clk);
- clk_put(clk);
- return 0;
-}
-
-static struct platform_driver gpio_driver = {
- .driver = {
- .name = "u300-gpio",
- },
- .remove = __exit_p(gpio_remove),
-};
-
-
-static int __init u300_gpio_init(void)
-{
- return platform_driver_probe(&gpio_driver, gpio_probe);
-}
-
-static void __exit u300_gpio_exit(void)
-{
- platform_driver_unregister(&gpio_driver);
-}
-
-arch_initcall(u300_gpio_init);
-module_exit(u300_gpio_exit);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
-
-#ifdef U300_COH901571_3
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 571/3 GPIO driver");
-#endif
-
-#ifdef U300_COH901335
-MODULE_DESCRIPTION("ST-Ericsson AB COH 901 335 GPIO driver");
-#endif
-
-MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-u300/include/mach/coh901318.h b/arch/arm/mach-u300/include/mach/coh901318.h
index 6193aaa47794..7c3b2b2d25b6 100644
--- a/arch/arm/mach-u300/include/mach/coh901318.h
+++ b/arch/arm/mach-u300/include/mach/coh901318.h
@@ -102,6 +102,7 @@ struct coh901318_platform {
const int max_channels;
};
+#ifdef CONFIG_COH901318
/**
* coh901318_filter_id() - DMA channel filter function
* @chan: dma channel handle
@@ -110,6 +111,12 @@ struct coh901318_platform {
* In dma_request_channel() it specifies what channel id to be requested
*/
bool coh901318_filter_id(struct dma_chan *chan, void *chan_id);
+#else
+static inline bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
+{
+ return false;
+}
+#endif
/*
* DMA Controller - this access the static mappings of the coh901318 dma.
diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h
index bf134bcc129d..888e2e351ee1 100644
--- a/arch/arm/mach-u300/include/mach/memory.h
+++ b/arch/arm/mach-u300/include/mach/memory.h
@@ -15,17 +15,17 @@
#ifdef CONFIG_MACH_U300_DUAL_RAM
-#define PHYS_OFFSET UL(0x48000000)
+#define PLAT_PHYS_OFFSET UL(0x48000000)
#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100)
#else
#ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-#define PHYS_OFFSET (0x28000000 + \
+#define PLAT_PHYS_OFFSET (0x28000000 + \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
#else
-#define PHYS_OFFSET (0x28000000 + \
+#define PLAT_PHYS_OFFSET (0x28000000 + \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE + \
(CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
#endif
diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c
index de1ac9ad2213..677ccef5cd32 100644
--- a/arch/arm/mach-u300/mmc.c
+++ b/arch/arm/mach-u300/mmc.c
@@ -3,159 +3,52 @@
* arch/arm/mach-u300/mmc.c
*
*
- * Copyright (C) 2009 ST-Ericsson AB
+ * Copyright (C) 2009 ST-Ericsson SA
* License terms: GNU General Public License (GPL) version 2
*
* Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Johan Lundin <johan.lundin@stericsson.com>
+ * Author: Johan Lundin
* Author: Jonas Aaberg <jonas.aberg@stericsson.com>
*/
#include <linux/device.h>
#include <linux/amba/bus.h>
#include <linux/mmc/host.h>
-#include <linux/input.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/regulator/consumer.h>
-#include <linux/regulator/machine.h>
#include <linux/gpio.h>
+#include <linux/dmaengine.h>
#include <linux/amba/mmci.h>
#include <linux/slab.h>
+#include <mach/coh901318.h>
+#include <mach/dma_channels.h>
#include "mmc.h"
#include "padmux.h"
-struct mmci_card_event {
- struct input_dev *mmc_input;
- int mmc_inserted;
- struct work_struct workq;
- struct mmci_platform_data mmc0_plat_data;
+static struct mmci_platform_data mmc0_plat_data = {
+ /*
+ * Do not set ocr_mask or voltage translation function,
+ * we have a regulator we can control instead.
+ */
+ /* Nominally 2.85V on our platform */
+ .f_max = 24000000,
+ .gpio_wp = -1,
+ .gpio_cd = U300_GPIO_PIN_MMC_CD,
+ .cd_invert = true,
+ .capabilities = MMC_CAP_MMC_HIGHSPEED |
+ MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+#ifdef CONFIG_COH901318
+ .dma_filter = coh901318_filter_id,
+ .dma_rx_param = (void *) U300_DMA_MMCSD_RX_TX,
+ /* Don't specify a TX channel, this RX channel is bidirectional */
+#endif
};
-static unsigned int mmc_status(struct device *dev)
-{
- struct mmci_card_event *mmci_card = container_of(
- dev->platform_data,
- struct mmci_card_event, mmc0_plat_data);
-
- return mmci_card->mmc_inserted;
-}
-
-static int mmci_callback(void *data)
-{
- struct mmci_card_event *mmci_card = data;
-
- disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD);
- schedule_work(&mmci_card->workq);
-
- return 0;
-}
-
-
-static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct mmci_card_event *mmci_card = container_of(
- dev->platform_data,
- struct mmci_card_event, mmc0_plat_data);
-
-
- return sprintf(buf, "%d\n", !mmci_card->mmc_inserted);
-}
-
-static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL);
-
-static void _mmci_callback(struct work_struct *ws)
-{
-
- struct mmci_card_event *mmci_card = container_of(
- ws,
- struct mmci_card_event, workq);
-
- mdelay(20);
-
- mmci_card->mmc_inserted = !gpio_get_value(U300_GPIO_PIN_MMC_CD);
-
- input_report_switch(mmci_card->mmc_input, KEY_INSERT,
- mmci_card->mmc_inserted);
- input_sync(mmci_card->mmc_input);
-
- pr_debug("MMC/SD card was %s\n",
- mmci_card->mmc_inserted ? "inserted" : "removed");
-
- enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, mmci_card->mmc_inserted);
-}
-
int __devinit mmc_init(struct amba_device *adev)
{
- struct mmci_card_event *mmci_card;
struct device *mmcsd_device = &adev->dev;
struct pmx *pmx;
int ret = 0;
- mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL);
- if (!mmci_card)
- return -ENOMEM;
-
- /*
- * Do not set ocr_mask or voltage translation function,
- * we have a regulator we can control instead.
- */
- /* Nominally 2.85V on our platform */
- mmci_card->mmc0_plat_data.f_max = 24000000;
- mmci_card->mmc0_plat_data.status = mmc_status;
- mmci_card->mmc0_plat_data.gpio_wp = -1;
- mmci_card->mmc0_plat_data.gpio_cd = -1;
- mmci_card->mmc0_plat_data.capabilities = MMC_CAP_MMC_HIGHSPEED |
- MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-
- mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data;
-
- INIT_WORK(&mmci_card->workq, _mmci_callback);
-
- ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection");
- if (ret) {
- printk(KERN_CRIT "Could not allocate MMC card detection " \
- "GPIO pin\n");
- goto out;
- }
-
- ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD);
- if (ret) {
- printk(KERN_CRIT "Invalid GPIO pin requested\n");
- goto out;
- }
-
- ret = sysfs_create_file(&mmcsd_device->kobj,
- &dev_attr_mmc_inserted.attr);
- if (ret)
- goto out;
-
- mmci_card->mmc_input = input_allocate_device();
- if (!mmci_card->mmc_input) {
- printk(KERN_CRIT "Could not allocate MMC input device\n");
- return -ENOMEM;
- }
-
- mmci_card->mmc_input->name = "MMC insert notification";
- mmci_card->mmc_input->id.bustype = BUS_HOST;
- mmci_card->mmc_input->id.vendor = 0;
- mmci_card->mmc_input->id.product = 0;
- mmci_card->mmc_input->id.version = 0x0100;
- mmci_card->mmc_input->dev.parent = mmcsd_device;
- input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT);
-
- /*
- * Since this must always be compiled into the kernel, this input
- * is never unregistered or free:ed.
- */
- ret = input_register_device(mmci_card->mmc_input);
- if (ret) {
- input_free_device(mmci_card->mmc_input);
- goto out;
- }
-
- input_set_drvdata(mmci_card->mmc_input, mmci_card);
+ mmcsd_device->platform_data = &mmc0_plat_data;
/*
* Setup padmuxing for MMC. Since this must always be
@@ -171,12 +64,5 @@ int __devinit mmc_init(struct amba_device *adev)
pr_warning("Could not activate padmuxing\n");
}
- ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback,
- mmci_card);
-
- schedule_work(&mmci_card->workq);
-
- printk(KERN_INFO "Registered MMC insert/remove notification\n");
-out:
return ret;
}
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index 00869def5420..5767208f1c1d 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -11,6 +11,9 @@
#include <linux/spi/spi.h>
#include <linux/amba/pl022.h>
#include <linux/err.h>
+#include <mach/coh901318.h>
+#include <mach/dma_channels.h>
+
#include "padmux.h"
/*
@@ -30,11 +33,8 @@ static void select_dummy_chip(u32 chipselect)
}
struct pl022_config_chip dummy_chip_info = {
- /*
- * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
- * DMA_TRANSFER does not work
- */
- .com_mode = INTERRUPT_TRANSFER,
+ /* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */
+ .com_mode = DMA_TRANSFER,
.iface = SSP_INTERFACE_MOTOROLA_SPI,
/* We can only act as master but SSP_SLAVE is possible in theory */
.hierarchy = SSP_MASTER,
@@ -75,8 +75,6 @@ static struct spi_board_info u300_spi_devices[] = {
static struct pl022_ssp_controller ssp_platform_data = {
/* If you have several SPI buses this varies, we have only bus 0 */
.bus_id = 0,
- /* Set this to 1 when we think we got DMA working */
- .enable_dma = 0,
/*
* On the APP CPU GPIO 4, 5 and 6 are connected as generic
* chip selects for SPI. (Same on U330, U335 and U365.)
@@ -84,6 +82,14 @@ static struct pl022_ssp_controller ssp_platform_data = {
* and do padmuxing accordingly too.
*/
.num_chipselect = 3,
+#ifdef CONFIG_COH901318
+ .enable_dma = 1,
+ .dma_filter = coh901318_filter_id,
+ .dma_rx_param = (void *) U300_DMA_SPI_RX,
+ .dma_tx_param = (void *) U300_DMA_SPI_TX,
+#else
+ .enable_dma = 0,
+#endif
};
@@ -109,6 +115,7 @@ void __init u300_spi_init(struct amba_device *adev)
}
}
+
void __init u300_spi_register_board_devices(void)
{
/* Register any SPI devices */
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index 3ec58bd2d6e4..891cf44591e0 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -333,20 +333,6 @@ static struct irqaction u300_timer_irq = {
.handler = u300_timer_interrupt,
};
-/* Use general purpose timer 2 as clock source */
-static cycle_t u300_get_cycles(struct clocksource *cs)
-{
- return (cycles_t) readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
-}
-
-static struct clocksource clocksource_u300_1mhz = {
- .name = "GPT2",
- .rating = 300, /* Reasonably fast and accurate clock source */
- .read = u300_get_cycles,
- .mask = CLOCKSOURCE_MASK(32), /* 32 bits */
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
/*
* Override the global weak sched_clock symbol with this
* local implementation which uses the clocksource to get some
@@ -422,7 +408,9 @@ static void __init u300_timer_init(void)
writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2);
- if (clocksource_register_hz(&clocksource_u300_1mhz, rate))
+ /* Use general purpose timer 2 as clock source */
+ if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC,
+ "GPT2", rate, 300, 32, clocksource_mmio_readl_up))
printk(KERN_ERR "timer: failed to initialize clock "
"source %s\n", clocksource_u300_1mhz.name);
diff --git a/arch/arm/mach-u300/u300.c b/arch/arm/mach-u300/u300.c
index 07c35a846424..48b3b7f39966 100644
--- a/arch/arm/mach-u300/u300.c
+++ b/arch/arm/mach-u300/u300.c
@@ -19,9 +19,9 @@
#include <linux/io.h>
#include <mach/hardware.h>
#include <mach/platform.h>
-#include <mach/memory.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
+#include <asm/memory.h>
static void __init u300_reserve(void)
{