diff options
Diffstat (limited to 'arch/arm/mach-u300')
-rw-r--r-- | arch/arm/mach-u300/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-u300/clock.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-u300/core.c | 179 | ||||
-rw-r--r-- | arch/arm/mach-u300/gpio.c | 700 | ||||
-rw-r--r-- | arch/arm/mach-u300/include/mach/coh901318.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-u300/include/mach/memory.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-u300/mmc.c | 160 | ||||
-rw-r--r-- | arch/arm/mach-u300/spi.c | 21 | ||||
-rw-r--r-- | arch/arm/mach-u300/timer.c | 18 | ||||
-rw-r--r-- | arch/arm/mach-u300/u300.c | 2 |
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) { |