diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-u300/gpio.c | 701 | ||||
-rw-r--r-- | arch/arm/mach-u300/include/mach/gpio.h | 290 | ||||
-rw-r--r-- | arch/arm/mach-u300/padmux.c | 58 | ||||
-rw-r--r-- | arch/arm/mach-u300/padmux.h | 19 |
4 files changed, 1068 insertions, 0 deletions
diff --git a/arch/arm/mach-u300/gpio.c b/arch/arm/mach-u300/gpio.c new file mode 100644 index 000000000000..2d5ae8ecb8c8 --- /dev/null +++ b/arch/arm/mach-u300/gpio.c @@ -0,0 +1,701 @@ +/* + * + * 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> + +/* Need access to SYSCON registers for PADmuxing */ +#include <mach/syscon.h> + +#include "padmux.h" + +/* Reference to GPIO block clock */ +static struct clk *clk; + +/* Memory resource */ +static struct resource *memres; +static void __iomem *virtbase; + +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) + printk(KERN_WARNING "GPIO: %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) + printk(KERN_WARNING "GPIO: %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); + +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)) { + printk(KERN_WARNING "GPIO: 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 + printk(KERN_DEBUG "GPIO: 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 initalize + * 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 __devinit gpio_probe(struct platform_device *pdev) +{ + u32 val; + int err = 0; + int i; + int num_irqs; + + memset(gpio_pin, 0, sizeof(gpio_pin)); + + /* Get GPIO clock */ + clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk)) { + err = PTR_ERR(clk); + printk(KERN_ERR "GPIO: could not get GPIO clock\n"); + goto err_no_clk; + } + err = clk_enable(clk); + if (err) { + printk(KERN_ERR "GPIO: 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, memres->end - memres->start + 1); + if (!virtbase) { + err = -ENOMEM; + goto err_no_ioremap; + } + +#ifdef U300_COH901335 + printk(KERN_INFO "GPIO: 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 + printk(KERN_INFO "GPIO: Initializing GPIO Controller COH 901 571/3\n"); + val = readl(virtbase + U300_GPIO_CR); + printk(KERN_INFO "GPIO: 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 + + /* Set up some padmuxing here */ +#ifdef CONFIG_MMC + pmx_set_mission_mode_mmc(); +#endif +#ifdef CONFIG_SPI_PL022 + pmx_set_mission_mode_spi(); +#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) { + printk(KERN_CRIT "GPIO: 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); + } + printk(KERN_INFO "GPIO: U300 gpio module loaded\n"); + + 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: + printk(KERN_INFO "GPIO: module ERROR:%d\n", err); + return err; +} + +static int __devexit 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", + }, + .probe = gpio_probe, + .remove = __devexit_p(gpio_remove), +}; + + +static int __init u300_gpio_init(void) +{ + return platform_driver_register(&gpio_driver); +} + +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/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h new file mode 100644 index 000000000000..c8174128d7eb --- /dev/null +++ b/arch/arm/mach-u300/include/mach/gpio.h @@ -0,0 +1,290 @@ +/* + * + * arch/arm/mach-u300/include/mach/gpio.h + * + * + * Copyright (C) 2007-2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * GPIO block resgister definitions and inline macros for + * U300 GPIO COH 901 335 or COH 901 571/3 + * Author: Linus Walleij <linus.walleij@stericsson.com> + */ + +#ifndef __MACH_U300_GPIO_H +#define __MACH_U300_GPIO_H + +#include <linux/kernel.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/irq.h> + +/* Switch type depending on platform/chip variant */ +#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) +#define U300_COH901335 +#endif +#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335) +#define U300_COH901571_3 +#endif + +/* Get base address for regs here */ +#include "u300-regs.h" +/* IRQ numbers */ +#include "irqs.h" + +/* + * This is the GPIO block definitions. GPIO (General Purpose I/O) can be + * used for anything, and often is. The event/enable etc figures are for + * the lowermost pin (pin 0 on each port), shift this left to match your + * pin if you're gonna use these values. + */ +#ifdef U300_COH901335 +#define U300_GPIO_PORTX_SPACING (0x1C) +/* Port X Pin Data Register 32bit, this is both input and output (R/W) */ +#define U300_GPIO_PXPDIR (0x00) +#define U300_GPIO_PXPDOR (0x00) +/* Port X Pin Config Register 32bit (R/W) */ +#define U300_GPIO_PXPCR (0x04) +#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) +#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) +#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) +/* Port X Interrupt Event Register 32bit (R/W) */ +#define U300_GPIO_PXIEV (0x08) +#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) +#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) +/* Port X Interrupt Enable Register 32bit (R/W) */ +#define U300_GPIO_PXIEN (0x0C) +#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) +/* Port X Interrupt Force Register 32bit (R/W) */ +#define U300_GPIO_PXIFR (0x10) +#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) +#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) +/* Port X Interrupt Config Register 32bit (R/W) */ +#define U300_GPIO_PXICR (0x14) +#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) +#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) +/* Port X Pull-up Enable Register 32bit (R/W) */ +#define U300_GPIO_PXPER (0x18) +#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) +/* Control Register 32bit (R/W) */ +#define U300_GPIO_CR (0x54) +#define U300_GPIO_CR_BLOCK_CLOCK_ENABLE (0x00000001UL) +/* three ports of 8 bits each = GPIO pins 0..23 */ +#define U300_GPIO_NUM_PORTS 3 +#define U300_GPIO_PINS_PER_PORT 8 +#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) +#endif + +#ifdef U300_COH901571_3 +/* + * Control Register 32bit (R/W) + * bit 15-9 (mask 0x0000FE00) contains the number of cores. 8*cores + * gives the number of GPIO pins. + * bit 8-2 (mask 0x000001FC) contains the core version ID. + */ +#define U300_GPIO_CR (0x00) +#define U300_GPIO_CR_SYNC_SEL_ENABLE (0x00000002UL) +#define U300_GPIO_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL) +#define U300_GPIO_PORTX_SPACING (0x30) +/* Port X Pin Data INPUT Register 32bit (R/W) */ +#define U300_GPIO_PXPDIR (0x04) +/* Port X Pin Data OUTPUT Register 32bit (R/W) */ +#define U300_GPIO_PXPDOR (0x08) +/* Port X Pin Config Register 32bit (R/W) */ +#define U300_GPIO_PXPCR (0x0C) +#define U300_GPIO_PXPCR_ALL_PINS_MODE_MASK (0x0000FFFFUL) +#define U300_GPIO_PXPCR_PIN_MODE_MASK (0x00000003UL) +#define U300_GPIO_PXPCR_PIN_MODE_SHIFT (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_INPUT (0x00000000UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL (0x00000001UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN (0x00000002UL) +#define U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE (0x00000003UL) +/* Port X Pull-up Enable Register 32bit (R/W) */ +#define U300_GPIO_PXPER (0x10) +#define U300_GPIO_PXPER_ALL_PULL_UP_DISABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXPER_PULL_UP_DISABLE (0x00000001UL) +/* Port X Interrupt Event Register 32bit (R/W) */ +#define U300_GPIO_PXIEV (0x14) +#define U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK (0x000000FFUL) +#define U300_GPIO_PXIEV_IRQ_EVENT (0x00000001UL) +/* Port X Interrupt Enable Register 32bit (R/W) */ +#define U300_GPIO_PXIEN (0x18) +#define U300_GPIO_PXIEN_ALL_IRQ_ENABLE_MASK (0x000000FFUL) +#define U300_GPIO_PXIEN_IRQ_ENABLE (0x00000001UL) +/* Port X Interrupt Force Register 32bit (R/W) */ +#define U300_GPIO_PXIFR (0x1C) +#define U300_GPIO_PXIFR_ALL_IRQ_FORCE_MASK (0x000000FFUL) +#define U300_GPIO_PXIFR_IRQ_FORCE (0x00000001UL) +/* Port X Interrupt Config Register 32bit (R/W) */ +#define U300_GPIO_PXICR (0x20) +#define U300_GPIO_PXICR_ALL_IRQ_CONFIG_MASK (0x000000FFUL) +#define U300_GPIO_PXICR_IRQ_CONFIG_MASK (0x00000001UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_FALLING_EDGE (0x00000000UL) +#define U300_GPIO_PXICR_IRQ_CONFIG_RISING_EDGE (0x00000001UL) +#ifdef CONFIG_MACH_U300_BS335 +/* seven ports of 8 bits each = GPIO pins 0..55 */ +#define U300_GPIO_NUM_PORTS 7 +#else +/* five ports of 8 bits each = GPIO pins 0..39 */ +#define U300_GPIO_NUM_PORTS 5 +#endif +#define U300_GPIO_PINS_PER_PORT 8 +#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * U300_GPIO_NUM_PORTS - 1) +#endif + +/* + * Individual pin assignments for the B26/S26. Notice that the + * actual usage of these pins depends on the PAD MUX settings, that + * is why the same number can potentially appear several times. + * In the reference design each pin is only used for one purpose. + * These were determined by inspecting the B26/S26 schematic: + * 2/1911-ROA 128 1603 + */ +#ifdef CONFIG_MACH_U300_BS2X +#define U300_GPIO_PIN_UART_RX 0 +#define U300_GPIO_PIN_UART_TX 1 +#define U300_GPIO_PIN_GPIO02 2 /* Unrouted */ +#define U300_GPIO_PIN_GPIO03 3 /* Unrouted */ +#define U300_GPIO_PIN_CAM_SLEEP 4 +#define U300_GPIO_PIN_CAM_REG_EN 5 +#define U300_GPIO_PIN_GPIO06 6 /* Unrouted */ +#define U300_GPIO_PIN_GPIO07 7 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO08 8 /* Service point SP2321 */ +#define U300_GPIO_PIN_GPIO09 9 /* Service point SP2322 */ +#define U300_GPIO_PIN_PHFSENSE 10 /* Headphone jack sensing */ +#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ +#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ +#define U300_GPIO_PIN_FLIPSENSE 13 /* Mechanical flip sensing */ +#define U300_GPIO_PIN_GPIO14 14 /* DSP JTAG Port RTCK */ +#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO16 16 /* Unrouted */ +#define U300_GPIO_PIN_GPIO17 17 /* Unrouted */ +#define U300_GPIO_PIN_GPIO18 18 /* Unrouted */ +#define U300_GPIO_PIN_GPIO19 19 /* Unrouted */ +#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ +#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ +#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ +#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ +#endif + +/* + * Individual pin assignments for the B330/S330 and B365/S365. + * Notice that the actual usage of these pins depends on the + * PAD MUX settings, that is why the same number can potentially + * appear several times. In the reference design each pin is only + * used for one purpose. These were determined by inspecting the + * S365 schematic. + */ +#if defined(CONFIG_MACH_U300_BS330) || defined(CONFIG_MACH_U300_BS365) || \ + defined(CONFIG_MACH_U300_BS335) +#define U300_GPIO_PIN_UART_RX 0 +#define U300_GPIO_PIN_UART_TX 1 +#define U300_GPIO_PIN_UART_CTS 2 +#define U300_GPIO_PIN_UART_RTS 3 +#define U300_GPIO_PIN_CAM_MAIN_STANDBY 4 /* Camera MAIN standby */ +#define U300_GPIO_PIN_GPIO05 5 /* Unrouted */ +#define U300_GPIO_PIN_MS_CD 6 /* Memory Stick Card insertion */ +#define U300_GPIO_PIN_GPIO07 7 /* Test point TP2430 */ + +#define U300_GPIO_PIN_GPIO08 8 /* Test point TP2437 */ +#define U300_GPIO_PIN_GPIO09 9 /* Test point TP2431 */ +#define U300_GPIO_PIN_GPIO10 10 /* Test point TP2432 */ +#define U300_GPIO_PIN_MMC_CLKRET 11 /* Clock return from MMC/SD card */ +#define U300_GPIO_PIN_MMC_CD 12 /* MMC Card insertion detection */ +#define U300_GPIO_PIN_CAM_SUB_STANDBY 13 /* Camera SUB standby */ +#define U300_GPIO_PIN_GPIO14 14 /* Test point TP2436 */ +#define U300_GPIO_PIN_GPIO15 15 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO16 16 /* Test point TP2438 */ +#define U300_GPIO_PIN_PHFSENSE 17 /* Headphone jack sensing */ +#define U300_GPIO_PIN_GPIO18 18 /* Test point TP2439 */ +#define U300_GPIO_PIN_GPIO19 19 /* Routed somewhere */ +#define U300_GPIO_PIN_GPIO20 20 /* Unrouted */ +#define U300_GPIO_PIN_GPIO21 21 /* Unrouted */ +#define U300_GPIO_PIN_GPIO22 22 /* Unrouted */ +#define U300_GPIO_PIN_GPIO23 23 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO24 24 /* Unrouted */ +#define U300_GPIO_PIN_GPIO25 25 /* Unrouted */ +#define U300_GPIO_PIN_GPIO26 26 /* Unrouted */ +#define U300_GPIO_PIN_GPIO27 27 /* Unrouted */ +#define U300_GPIO_PIN_GPIO28 28 /* Unrouted */ +#define U300_GPIO_PIN_GPIO29 29 /* Unrouted */ +#define U300_GPIO_PIN_GPIO30 30 /* Unrouted */ +#define U300_GPIO_PIN_GPIO31 31 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO32 32 /* Unrouted */ +#define U300_GPIO_PIN_GPIO33 33 /* Unrouted */ +#define U300_GPIO_PIN_GPIO34 34 /* Unrouted */ +#define U300_GPIO_PIN_GPIO35 35 /* Unrouted */ +#define U300_GPIO_PIN_GPIO36 36 /* Unrouted */ +#define U300_GPIO_PIN_GPIO37 37 /* Unrouted */ +#define U300_GPIO_PIN_GPIO38 38 /* Unrouted */ +#define U300_GPIO_PIN_GPIO39 39 /* Unrouted */ + +#ifdef CONFIG_MACH_U300_BS335 + +#define U300_GPIO_PIN_GPIO40 40 /* Unrouted */ +#define U300_GPIO_PIN_GPIO41 41 /* Unrouted */ +#define U300_GPIO_PIN_GPIO42 42 /* Unrouted */ +#define U300_GPIO_PIN_GPIO43 43 /* Unrouted */ +#define U300_GPIO_PIN_GPIO44 44 /* Unrouted */ +#define U300_GPIO_PIN_GPIO45 45 /* Unrouted */ +#define U300_GPIO_PIN_GPIO46 46 /* Unrouted */ +#define U300_GPIO_PIN_GPIO47 47 /* Unrouted */ + +#define U300_GPIO_PIN_GPIO48 48 /* Unrouted */ +#define U300_GPIO_PIN_GPIO49 49 /* Unrouted */ +#define U300_GPIO_PIN_GPIO50 50 /* Unrouted */ +#define U300_GPIO_PIN_GPIO51 51 /* Unrouted */ +#define U300_GPIO_PIN_GPIO52 52 /* Unrouted */ +#define U300_GPIO_PIN_GPIO53 53 /* Unrouted */ +#define U300_GPIO_PIN_GPIO54 54 /* Unrouted */ +#define U300_GPIO_PIN_GPIO55 55 /* Unrouted */ +#endif + +#endif + +/* translates a pin number to a port number */ +#define PIN_TO_PORT(val) (val >> 3) + +/* These can be found in arch/arm/mach-u300/gpio.c */ +extern int gpio_request(unsigned gpio, const char *label); +extern void gpio_free(unsigned gpio); +extern int gpio_direction_input(unsigned gpio); +extern int gpio_direction_output(unsigned gpio, int value); +extern int gpio_register_callback(unsigned gpio, + int (*func)(void *arg), + void *); +extern int gpio_unregister_callback(unsigned gpio); +extern void enable_irq_on_gpio_pin(unsigned gpio, int edge); +extern void disable_irq_on_gpio_pin(unsigned gpio); +extern void gpio_pullup(unsigned gpio, int value); +extern int gpio_get_value(unsigned gpio); +extern void gpio_set_value(unsigned gpio, int value); + +/* wrappers to sleep-enable the previous two functions */ +static inline unsigned gpio_to_irq(unsigned gpio) +{ + return PIN_TO_PORT(gpio) + IRQ_U300_GPIO_PORT0; +} + +static inline unsigned irq_to_gpio(unsigned irq) +{ + /* + * FIXME: This is no 1-1 mapping at all, it points to the + * whole block of 8 pins. + */ + return (irq - IRQ_U300_GPIO_PORT0) << 3; +} + +#endif diff --git a/arch/arm/mach-u300/padmux.c b/arch/arm/mach-u300/padmux.c new file mode 100644 index 000000000000..f3664564f086 --- /dev/null +++ b/arch/arm/mach-u300/padmux.c @@ -0,0 +1,58 @@ +/* + * + * arch/arm/mach-u300/padmux.c + * + * + * Copyright (C) 2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * U300 PADMUX functions + * Author: Linus Walleij <linus.walleij@stericsson.com> + * + */ +#include <linux/io.h> +#include <linux/err.h> +#include <mach/u300-regs.h> +#include <mach/syscon.h> + +#include "padmux.h" + +/* Set the PAD MUX to route the MMC reader correctly to GPIO0. */ +void pmx_set_mission_mode_mmc(void) +{ + u16 val; + + val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1LR); + val &= ~U300_SYSCON_PMC1LR_MMCSD_MASK; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1LR); + val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR); + val &= ~U300_SYSCON_PMC1HR_APP_GPIO_1_MASK; + val |= U300_SYSCON_PMC1HR_APP_GPIO_1_MMC; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1HR); +} + +void pmx_set_mission_mode_spi(void) +{ + u16 val; + + /* Set up padmuxing so the SPI port and its chipselects are active */ + val = readw(U300_SYSCON_VBASE + U300_SYSCON_PMC1HR); + /* + * Activate the SPI port (disable the use of these pins for generic + * GPIO, DSP, AAIF + */ + val &= ~U300_SYSCON_PMC1HR_APP_SPI_2_MASK; + val |= U300_SYSCON_PMC1HR_APP_SPI_2_SPI; + /* + * Use GPIO pin SPI CS1 for CS1 actually (it can be used for other + * things also) + */ + val &= ~U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK; + val |= U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI; + /* + * Use GPIO pin SPI CS2 for CS2 actually (it can be used for other + * things also) + */ + val &= ~U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK; + val |= U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI; + writew(val, U300_SYSCON_VBASE + U300_SYSCON_PMC1HR); +} diff --git a/arch/arm/mach-u300/padmux.h b/arch/arm/mach-u300/padmux.h new file mode 100644 index 000000000000..8c2099ac5046 --- /dev/null +++ b/arch/arm/mach-u300/padmux.h @@ -0,0 +1,19 @@ +/* + * + * arch/arm/mach-u300/padmux.h + * + * + * Copyright (C) 2009 ST-Ericsson AB + * License terms: GNU General Public License (GPL) version 2 + * U300 PADMUX API + * Author: Linus Walleij <linus.walleij@stericsson.com> + * + */ + +#ifndef __MACH_U300_PADMUX_H +#define __MACH_U300_PADMUX_H + +void pmx_set_mission_mode_mmc(void); +void pmx_set_mission_mode_spi(void); + +#endif |