From 28f65c11f2ffb3957259dece647a24f8ad2e241b Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 9 Jun 2011 09:13:32 -0700 Subject: treewide: Convert uses of struct resource to resource_size(ptr) Several fixes as well where the +1 was missing. Done via coccinelle scripts like: @@ struct resource *ptr; @@ - ptr->end - ptr->start + 1 + resource_size(ptr) and some grep and typing. Mostly uncompiled, no cross-compilers. Signed-off-by: Joe Perches Signed-off-by: Jiri Kosina --- arch/arm/mach-u300/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-u300/core.c') diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 513d6abec1f5..399c89f14dfb 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -1791,7 +1791,7 @@ static void __init u300_assign_physmem(void) 0 == res->start) { res->start = curr_start; res->end += curr_start; - curr_start += (res->end - res->start + 1); + curr_start += resource_size(res); printk(KERN_INFO "core.c: Mapping RAM " \ "%#x-%#x to device %s:%s\n", -- cgit v1.2.3 From c43ed5600b285e7b3bfe868ffe2eb259939c4b98 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 9 Aug 2011 21:30:01 +0200 Subject: mach-u300: drop SEMI config option When we have only dual-RAM configurations, the SEMI (shared memory interface) must always be enabled. Signed-off-by: Linus Walleij --- arch/arm/mach-u300/Kconfig | 8 -------- arch/arm/mach-u300/core.c | 9 +-------- 2 files changed, 1 insertion(+), 16 deletions(-) (limited to 'arch/arm/mach-u300/core.c') diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index d3a9ca45ef85..966a5a06a58c 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig @@ -54,14 +54,6 @@ config U300_DEBUG help Debug support for U300 in sysfs, procfs etc. -config MACH_U300_SEMI_IS_SHARED - bool "The SEMI is used by both the access and application side" - depends on MACH_U300 - help - This makes it possible to use the SEMI (Shared External - Memory Interface) from both from access and application - side. - config MACH_U300_SPIDUMMY bool "SSP/SPI dummy chip" select SPI diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 399c89f14dfb..8b78af90166f 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -1837,17 +1837,10 @@ void __init u300_init_devices(void) /* 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 - * both subsystems are requesting this mode. - * If we not share the Acc SDRAM, this is never the case. Therefore - * enable it here from the App side. - */ + /* Enable SEMI self refresh */ val = readw(U300_SYSCON_VBASE + U300_SYSCON_SMCR) | U300_SYSCON_SMCR_SEMI_SREFREQ_ENABLE; writew(val, U300_SYSCON_VBASE + U300_SYSCON_SMCR); -#endif /* CONFIG_MACH_U300_SEMI_IS_SHARED */ } static int core_module_init(void) -- cgit v1.2.3 From 711e2deb63bb151249fa78287f99ba1e7de77b2f Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 9 Aug 2011 21:20:20 +0200 Subject: mach-u300: delete bogus memory mappings Get rid of the bogus memory map to TCM (there is a real mechanism for handling that nowadays!) and the commented- out declaration of the ROM. Signed-off-by: Linus Walleij --- arch/arm/mach-u300/core.c | 19 ------------------- 1 file changed, 19 deletions(-) (limited to 'arch/arm/mach-u300/core.c') diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 8b78af90166f..ba0b1d3b6ed2 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -68,25 +68,6 @@ static struct map_desc u300_io_desc[] __initdata = { .length = SZ_32K, .type = MT_DEVICE, }, - { - .virtual = 0xffff2000, /* TCM memory */ - .pfn = __phys_to_pfn(0xffff2000), - .length = SZ_16K, - .type = MT_DEVICE, - }, - - /* - * This overlaps with the IRQ vectors etc at 0xffff0000, so these - * may have to be moved to 0x00000000 in order to use the ROM. - */ - /* - { - .virtual = U300_BOOTROM_VIRT_BASE, - .pfn = __phys_to_pfn(U300_BOOTROM_PHYS_BASE), - .length = SZ_64K, - .type = MT_ROM, - }, - */ }; void __init u300_map_io(void) -- cgit v1.2.3 From c21d2319efcdca6d1bc5d24d22dde8976464031e Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 9 Aug 2011 21:26:15 +0200 Subject: mach-u300: retire AVE device We need to face the fact that there will never be a mainlined driver for the U300 advanced video encoder, so let's just drop the declaration of this device. Signed-off-by: Linus Walleij --- arch/arm/mach-u300/core.c | 54 ----------------------------------------------- 1 file changed, 54 deletions(-) (limited to 'arch/arm/mach-u300/core.c') diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index ba0b1d3b6ed2..5030a455251a 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -342,51 +342,6 @@ static struct resource wdog_resources[] = { } }; -/* TODO: These should be protected by suitable #ifdef's */ -static struct resource ave_resources[] = { - { - .name = "AVE3e I/O Area", - .start = U300_VIDEOENC_BASE, - .end = U300_VIDEOENC_BASE + SZ_512K - 1, - .flags = IORESOURCE_MEM, - }, - { - .name = "AVE3e IRQ0", - .start = IRQ_U300_VIDEO_ENC_0, - .end = IRQ_U300_VIDEO_ENC_0, - .flags = IORESOURCE_IRQ, - }, - { - .name = "AVE3e IRQ1", - .start = IRQ_U300_VIDEO_ENC_1, - .end = IRQ_U300_VIDEO_ENC_1, - .flags = IORESOURCE_IRQ, - }, - { - .name = "AVE3e Physmem Area", - .start = 0, /* 0 will be remapped to reserved memory */ - .end = SZ_1M - 1, - .flags = IORESOURCE_MEM, - }, - /* - * The AVE3e requires two regions of 256MB that it considers - * "invisible". The hardware will not be able to access these - * addresses, so they should never point to system RAM. - */ - { - .name = "AVE3e Reserved 0", - .start = 0xd0000000, - .end = 0xd0000000 + SZ_256M - 1, - .flags = IORESOURCE_MEM, - }, - { - .name = "AVE3e Reserved 1", - .start = 0xe0000000, - .end = 0xe0000000 + SZ_256M - 1, - .flags = IORESOURCE_MEM, - }, -}; - static struct resource dma_resource[] = { { .start = U300_DMAC_BASE, @@ -1593,13 +1548,6 @@ static struct platform_device nand_device = { }, }; -static struct platform_device ave_device = { - .name = "video_enc", - .id = -1, - .num_resources = ARRAY_SIZE(ave_resources), - .resource = ave_resources, -}; - static struct platform_device dma_device = { .name = "coh901318", .id = -1, @@ -1624,10 +1572,8 @@ static struct platform_device *platform_devs[] __initdata = { &gpio_device, &nand_device, &wdog_device, - &ave_device }; - /* * Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected * together so some interrupts are connected to the first one and some -- cgit v1.2.3 From d70a5969e9d52ef1c0e19a1b154785f8e1acba29 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Thu, 4 Aug 2011 15:41:42 +0100 Subject: ARM: mach-u300: Setup consistent dma size at boot time Signed-off-by: Jon Medhurst Acked-by: Linus Walleij --- arch/arm/mach-u300/core.c | 3 +++ arch/arm/mach-u300/include/mach/memory.h | 5 ----- 2 files changed, 3 insertions(+), 5 deletions(-) (limited to 'arch/arm/mach-u300/core.c') diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 399c89f14dfb..376b6dfdfae9 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -92,6 +93,8 @@ static struct map_desc u300_io_desc[] __initdata = { void __init u300_map_io(void) { iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc)); + /* We enable a real big DMA buffer if need be. */ + init_consistent_dma_size(SZ_4M); } /* diff --git a/arch/arm/mach-u300/include/mach/memory.h b/arch/arm/mach-u300/include/mach/memory.h index 888e2e351ee1..38741da0d261 100644 --- a/arch/arm/mach-u300/include/mach/memory.h +++ b/arch/arm/mach-u300/include/mach/memory.h @@ -34,9 +34,4 @@ (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024 + 0x100) #endif -/* - * We enable a real big DMA buffer if need be. - */ -#define CONSISTENT_DMA_SIZE SZ_4M - #endif -- cgit v1.2.3 From cc890cd78acd7ab03442907d354b6af34e973cb3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 8 Sep 2011 09:04:51 +0100 Subject: ARM: 7083/1: rewrite U300 GPIO to use gpiolib This rewrites the U300 GPIO so as to use gpiolib and struct gpio_chip instead of just generic GPIO, hiding all the platform specifics and passing in GPIO chip variant as platform data at runtime instead of the compiletime kludges. As a result is now empty for U300 and using just defaults. Cc: Grant Likely Cc: Debian kernel maintainers Cc: Arnaud Patard Reported-by: Ben Hutchings Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-u300/Kconfig | 1 + arch/arm/mach-u300/core.c | 31 +- arch/arm/mach-u300/include/mach/gpio-u300.h | 149 +--- arch/arm/mach-u300/include/mach/gpio.h | 47 -- arch/arm/mach-u300/include/mach/irqs.h | 25 +- drivers/gpio/Kconfig | 9 + drivers/gpio/gpio-u300.c | 1189 ++++++++++++++++----------- 8 files changed, 783 insertions(+), 669 deletions(-) (limited to 'arch/arm/mach-u300/core.c') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2c71a8f3535a..05589e85c180 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -836,6 +836,7 @@ config ARCH_U300 select CLKDEV_LOOKUP select HAVE_MACH_CLKDEV select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB help Support for ST-Ericsson U300 series mobile platforms. diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index 32a7b0f7e9f7..7b5c229dc7ea 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig @@ -6,6 +6,7 @@ comment "ST-Ericsson Mobile Platform Products" config MACH_U300 bool "U300" + select GPIO_U300 comment "ST-Ericsson U300/U330/U335/U365 Feature Selections" diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 399c89f14dfb..fd435f44098b 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "clock.h" #include "mmc.h" @@ -239,7 +240,7 @@ static struct resource gpio_resources[] = { .end = IRQ_U300_GPIO_PORT2, .flags = IORESOURCE_IRQ, }, -#ifdef U300_COH901571_3 +#if defined(CONFIG_MACH_U300_BS365) || defined(CONFIG_MACH_U300_BS335) { .name = "gpio3", .start = IRQ_U300_GPIO_PORT3, @@ -252,6 +253,7 @@ static struct resource gpio_resources[] = { .end = IRQ_U300_GPIO_PORT4, .flags = IORESOURCE_IRQ, }, +#endif #ifdef CONFIG_MACH_U300_BS335 { .name = "gpio5", @@ -266,7 +268,6 @@ static struct resource gpio_resources[] = { .flags = IORESOURCE_IRQ, }, #endif /* CONFIG_MACH_U300_BS335 */ -#endif /* U300_COH901571_3 */ }; static struct resource keypad_resources[] = { @@ -1556,11 +1557,35 @@ static struct platform_device i2c1_device = { .resource = i2c1_resources, }; +/* + * The different variants have a few different versions of the + * GPIO block, with different number of ports. + */ +static struct u300_gpio_platform u300_gpio_plat = { +#if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) + .variant = U300_GPIO_COH901335, + .ports = 3, +#endif +#ifdef CONFIG_MACH_U300_BS335 + .variant = U300_GPIO_COH901571_3_BS335, + .ports = 7, +#endif +#ifdef CONFIG_MACH_U300_BS365 + .variant = U300_GPIO_COH901571_3_BS365, + .ports = 5, +#endif + .gpio_base = 0, + .gpio_irq_base = IRQ_U300_GPIO_BASE, +}; + static struct platform_device gpio_device = { .name = "u300-gpio", .id = -1, .num_resources = ARRAY_SIZE(gpio_resources), .resource = gpio_resources, + .dev = { + .platform_data = &u300_gpio_plat, + }, }; static struct platform_device keypad_device = { @@ -1666,7 +1691,7 @@ void __init u300_init_irq(void) BUG_ON(IS_ERR(clk)); clk_enable(clk); - for (i = 0; i < NR_IRQS; i++) + for (i = 0; i < U300_VIC_IRQS_END; i++) set_bit(i, (unsigned long *) &mask[0]); vic_init((void __iomem *) U300_INTCON0_VBASE, 0, mask[0], mask[0]); vic_init((void __iomem *) U300_INTCON1_VBASE, 32, mask[1], mask[1]); diff --git a/arch/arm/mach-u300/include/mach/gpio-u300.h b/arch/arm/mach-u300/include/mach/gpio-u300.h index a6119062add9..0c2b2021951a 100644 --- a/arch/arm/mach-u300/include/mach/gpio-u300.h +++ b/arch/arm/mach-u300/include/mach/gpio-u300.h @@ -9,132 +9,6 @@ #ifndef __MACH_U300_GPIO_U300_H #define __MACH_U300_GPIO_U300_H -#include -#include -#include -#include - -/* 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 @@ -250,4 +124,27 @@ #endif +/** + * enum u300_gpio_variant - the type of U300 GPIO employed + */ +enum u300_gpio_variant { + U300_GPIO_COH901335, + U300_GPIO_COH901571_3_BS335, + U300_GPIO_COH901571_3_BS365, +}; + +/** + * struct u300_gpio_platform - U300 GPIO platform data + * @variant: IP block variant + * @ports: number of GPIO block ports + * @gpio_base: first GPIO number for this block (use a free range) + * @gpio_irq_base: first GPIO IRQ number for this block (use a free range) + */ +struct u300_gpio_platform { + enum u300_gpio_variant variant; + u8 ports; + int gpio_base; + int gpio_irq_base; +}; + #endif /* __MACH_U300_GPIO_U300_H */ diff --git a/arch/arm/mach-u300/include/mach/gpio.h b/arch/arm/mach-u300/include/mach/gpio.h index 430a0544baff..e69de29bb2d1 100644 --- a/arch/arm/mach-u300/include/mach/gpio.h +++ b/arch/arm/mach-u300/include/mach/gpio.h @@ -1,47 +0,0 @@ -/* - * - * 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 - */ - -#ifndef __MACH_U300_GPIO_H -#define __MACH_U300_GPIO_H - -#define __ARM_GPIOLIB_COMPLEX - -/* These can be found in arch/arm/mach-u300/gpio.c */ -extern int gpio_is_valid(int number); -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); - -#define gpio_get_value_cansleep gpio_get_value -#define gpio_set_value_cansleep gpio_set_value - -/* translates a pin number to a port number */ -#define PIN_TO_PORT(val) (val >> 3) - -/* 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; -} -#define gpio_to_irq gpio_to_irq - -#endif /* __MACH_U300_GPIO_H */ diff --git a/arch/arm/mach-u300/include/mach/irqs.h b/arch/arm/mach-u300/include/mach/irqs.h index 09b1b28fa8fd..d270fea32926 100644 --- a/arch/arm/mach-u300/include/mach/irqs.h +++ b/arch/arm/mach-u300/include/mach/irqs.h @@ -72,7 +72,7 @@ /* DB3150 and DB3200 have only 45 IRQs */ #if defined(CONFIG_MACH_U300_BS2X) || defined(CONFIG_MACH_U300_BS330) -#define U300_NR_IRQS 45 +#define U300_VIC_IRQS_END 45 #endif /* The DB3350-specific interrupt lines */ @@ -88,7 +88,7 @@ #define IRQ_U300_GPIO_PORT4 53 #define IRQ_U300_GPIO_PORT5 54 #define IRQ_U300_GPIO_PORT6 55 -#define U300_NR_IRQS 56 +#define U300_VIC_IRQS_END 56 #endif /* The DB3210-specific interrupt lines */ @@ -106,16 +106,25 @@ #define IRQ_U300_NFIF 45 #define IRQ_U300_NFIF2 46 #define IRQ_U300_SYSCON_PLL_LOCK 47 -#define U300_NR_IRQS 48 +#define U300_VIC_IRQS_END 48 #endif -#ifdef CONFIG_AB3550_CORE -#define IRQ_AB3550_BASE (U300_NR_IRQS) -#define IRQ_AB3550_END (IRQ_AB3550_BASE + 37) +/* Maximum 8*7 GPIO lines */ +#ifdef CONFIG_GPIO_U300 +#define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END) +#define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56) +#else +#define IRQ_U300_GPIO_END (U300_VIC_IRQS_END) +#endif -#define NR_IRQS (IRQ_AB3550_END + 1) +/* Optional AB3550 mixsig chip */ +#ifdef CONFIG_AB3550_CORE +#define IRQ_AB3550_BASE (IRQ_U300_GPIO_END) +#define IRQ_AB3550_END (IRQ_AB3550_BASE + 38) #else -#define NR_IRQS U300_NR_IRQS +#define IRQ_AB3550_END (IRQ_U300_GPIO_END) #endif +#define NR_IRQS (IRQ_AB3550_END) + #endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d539efd96d4b..4caa3d37bbde 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -178,6 +178,15 @@ config GPIO_SCH The Intel Tunnel Creek processor has 5 GPIOs powered by the core power rail and 9 from suspend power supply. +config GPIO_U300 + bool "ST-Ericsson U300 COH 901 335/571 GPIO" + depends on GPIOLIB && ARCH_U300 + help + Say yes here to support GPIO interface on ST-Ericsson U300. + The names of the two IP block variants supported are + COH 901 335 and COH 901 571/3. They contain 3, 5 or 7 + ports of 8 GPIO pins each. + config GPIO_VX855 tristate "VIA VX855/VX875 GPIO" depends on MFD_SUPPORT && PCI diff --git a/drivers/gpio/gpio-u300.c b/drivers/gpio/gpio-u300.c index 92f2b8c06de1..4035778852b0 100644 --- a/drivers/gpio/gpio-u300.c +++ b/drivers/gpio/gpio-u300.c @@ -1,18 +1,17 @@ /* * U300 GPIO module. * - * Copyright (C) 2007-2009 ST-Ericsson AB + * Copyright (C) 2007-2011 ST-Ericsson AB * License terms: GNU General Public License (GPL) version 2 * 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 - * Author: Linus Walleij + * Author: Linus Walleij * Author: Jonas Aaberg - * */ #include +#include #include #include #include @@ -21,678 +20,898 @@ #include #include #include +#include +#include #include -/* Reference to GPIO block clock */ -static struct clk *clk; +/* + * Bias modes for U300 GPIOs + * + * GPIO_U300_CONFIG_BIAS_UNKNOWN: this bias mode is not known to us + * GPIO_U300_CONFIG_BIAS_FLOAT: no specific bias, the GPIO will float or state + * is not controlled by software + * GPIO_U300_CONFIG_BIAS_PULL_UP: the GPIO will be pulled up (usually with high + * impedance to VDD) + */ +#define GPIO_U300_CONFIG_BIAS_UNKNOWN 0x1000 +#define GPIO_U300_CONFIG_BIAS_FLOAT 0x1001 +#define GPIO_U300_CONFIG_BIAS_PULL_UP 0x1002 -/* Memory resource */ -static struct resource *memres; -static void __iomem *virtbase; -static struct device *gpiodev; +/* + * Drive modes for U300 GPIOs (output) + * + * GPIO_U300_CONFIG_DRIVE_PUSH_PULL: the GPIO will be driven actively high and + * low, this is the most typical case and is typically achieved with two + * active transistors on the output + * GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: the GPIO will be driven with open drain + * (open collector) which means it is usually wired with other output + * ports which are then pulled up with an external resistor + * GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: the GPIO will be driven with open drain + * (open emitter) which is the same as open drain mutatis mutandis but + * pulled to ground + */ +#define GPIO_U300_CONFIG_DRIVE_PUSH_PULL 0x2000 +#define GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN 0x2001 +#define GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE 0x2002 + +/* + * Register definitions for COH 901 335 variant + */ +#define U300_335_PORT_STRIDE (0x1C) +/* Port X Pin Data Register 32bit, this is both input and output (R/W) */ +#define U300_335_PXPDIR (0x00) +#define U300_335_PXPDOR (0x00) +/* Port X Pin Config Register 32bit (R/W) */ +#define U300_335_PXPCR (0x04) +/* This register layout is the same in both blocks */ +#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_335_PXIEV (0x08) +/* Port X Interrupt Enable Register 32bit (R/W) */ +#define U300_335_PXIEN (0x0C) +/* Port X Interrupt Force Register 32bit (R/W) */ +#define U300_335_PXIFR (0x10) +/* Port X Interrupt Config Register 32bit (R/W) */ +#define U300_335_PXICR (0x14) +/* This register layout is the same in both blocks */ +#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_335_PXPER (0x18) +/* This register layout is the same in both blocks */ +#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_335_CR (0x54) +#define U300_335_CR_BLOCK_CLOCK_ENABLE (0x00000001UL) + +/* + * Register definitions for COH 901 571 / 3 variant + */ +#define U300_571_PORT_STRIDE (0x30) +/* + * 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_571_CR (0x00) +#define U300_571_CR_SYNC_SEL_ENABLE (0x00000002UL) +#define U300_571_CR_BLOCK_CLKRQ_ENABLE (0x00000001UL) +/* + * These registers have the same layout and function as the corresponding + * COH 901 335 registers, just at different offset. + */ +#define U300_571_PXPDIR (0x04) +#define U300_571_PXPDOR (0x08) +#define U300_571_PXPCR (0x0C) +#define U300_571_PXPER (0x10) +#define U300_571_PXIEV (0x14) +#define U300_571_PXIEN (0x18) +#define U300_571_PXIFR (0x1C) +#define U300_571_PXICR (0x20) + +/* 8 bits per port, no version has more than 7 ports */ +#define U300_GPIO_PINS_PER_PORT 8 +#define U300_GPIO_MAX (U300_GPIO_PINS_PER_PORT * 7) + +struct u300_gpio { + struct gpio_chip chip; + struct list_head port_list; + struct clk *clk; + struct resource *memres; + void __iomem *base; + struct device *dev; + int irq_base; + u32 stride; + /* Register offsets */ + u32 pcr; + u32 dor; + u32 dir; + u32 per; + u32 icr; + u32 ien; + u32 iev; +}; struct u300_gpio_port { - const char *name; + struct list_head node; + struct u300_gpio *gpio; + char name[8]; int irq; int number; + u8 toggle_edge_mode; }; +/* + * Macro to expand to read a specific register found in the "gpio" + * struct. It requires the struct u300_gpio *gpio variable to exist in + * its context. It calculates the port offset from the given pin + * offset, muliplies by the port stride and adds the register offset + * so it provides a pointer to the desired register. + */ +#define U300_PIN_REG(pin, reg) \ + (gpio->base + (pin >> 3) * gpio->stride + gpio->reg) -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 +/* + * Provides a bitmask for a specific gpio pin inside an 8-bit GPIO + * register. + */ +#define U300_PIN_BIT(pin) \ + (1 << (pin & 0x07)) +struct u300_gpio_confdata { + u16 bias_mode; + bool output; + int outval; }; +/* BS335 has seven ports of 8 bits each = GPIO pins 0..55 */ +#define BS335_GPIO_NUM_PORTS 7 +/* BS365 has five ports of 8 bits each = GPIO pins 0..39 */ +#define BS365_GPIO_NUM_PORTS 5 -#ifdef U300_COH901571_3 +#define U300_FLOATING_INPUT { \ + .bias_mode = GPIO_U300_CONFIG_BIAS_FLOAT, \ + .output = false, \ +} -/* Default input value */ -#define DEFAULT_OUTPUT_LOW 0 -#define DEFAULT_OUTPUT_HIGH 1 +#define U300_PULL_UP_INPUT { \ + .bias_mode = GPIO_U300_CONFIG_BIAS_PULL_UP, \ + .output = false, \ +} -/* GPIO Pull-Up status */ -#define DISABLE_PULL_UP 0 -#define ENABLE_PULL_UP 1 +#define U300_OUTPUT_LOW { \ + .output = true, \ + .outval = 0, \ +} -#define GPIO_NOT_USED 0 -#define GPIO_IN 1 -#define GPIO_OUT 2 +#define U300_OUTPUT_HIGH { \ + .output = true, \ + .outval = 1, \ +} -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 +static const struct __initdata u300_gpio_confdata +bs335_gpio_config[BS335_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { /* 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} + U300_FLOATING_INPUT, + U300_OUTPUT_HIGH, + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, }, /* 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} + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, + U300_FLOATING_INPUT, + U300_OUTPUT_HIGH, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, }, /* 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} + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, }, /* 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} + U300_PULL_UP_INPUT, + U300_OUTPUT_LOW, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, }, /* 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} + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, }, /* 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} + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, }, /* 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} + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, } -#endif +}; -#ifdef CONFIG_MACH_U300_BS365 +static const struct __initdata u300_gpio_confdata +bs365_gpio_config[BS365_GPIO_NUM_PORTS][U300_GPIO_PINS_PER_PORT] = { /* 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} + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, + U300_FLOATING_INPUT, }, /* 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} + U300_OUTPUT_LOW, + U300_FLOATING_INPUT, + U300_OUTPUT_LOW, + U300_FLOATING_INPUT, + U300_FLOATING_INPUT, + U300_OUTPUT_HIGH, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, }, /* 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} + U300_FLOATING_INPUT, + U300_PULL_UP_INPUT, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, }, /* 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} + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, }, /* 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}, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, + U300_PULL_UP_INPUT, /* 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} + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, + U300_OUTPUT_LOW, } -#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 +/** + * to_u300_gpio() - get the pointer to u300_gpio + * @chip: the gpio chip member of the structure u300_gpio */ -int gpio_register_callback(unsigned gpio, int (*func)(void *arg), void *data) +static inline struct u300_gpio *to_u300_gpio(struct gpio_chip *chip) { - 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; + return container_of(chip, struct u300_gpio, chip); } -EXPORT_SYMBOL(gpio_register_callback); -int gpio_unregister_callback(unsigned gpio) +static int u300_gpio_get(struct gpio_chip *chip, unsigned offset) { - 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; + struct u300_gpio *gpio = to_u300_gpio(chip); - return 0; + return readl(U300_PIN_REG(offset, dir)) & U300_PIN_BIT(offset); } -EXPORT_SYMBOL(gpio_unregister_callback); -/* Non-zero means valid */ -int gpio_is_valid(int number) +static void u300_gpio_set(struct gpio_chip *chip, unsigned offset, int value) { - if (number >= 0 && - number < (U300_GPIO_NUM_PORTS * U300_GPIO_PINS_PER_PORT)) - return 1; - return 0; -} -EXPORT_SYMBOL(gpio_is_valid); + struct u300_gpio *gpio = to_u300_gpio(chip); + unsigned long flags; + u32 val; -int gpio_request(unsigned gpio, const char *label) -{ - if (gpio_pin[gpio].users) - return -EINVAL; - else - gpio_pin[gpio].users++; + local_irq_save(flags); - gpio_users++; + val = readl(U300_PIN_REG(offset, dor)); + if (value) + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, dor)); + else + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, dor)); - return 0; + local_irq_restore(flags); } -EXPORT_SYMBOL(gpio_request); -void gpio_free(unsigned gpio) +static int u300_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - 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); + struct u300_gpio *gpio = to_u300_gpio(chip); + unsigned long flags; + u32 val; -/* 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)); + local_irq_save(flags); + val = readl(U300_PIN_REG(offset, pcr)); + /* Mask out this pin, note 2 bits per setting */ + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); + local_irq_restore(flags); + return 0; } -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) +static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset, + int value) { - u32 val; + struct u300_gpio *gpio = to_u300_gpio(chip); unsigned long flags; + u32 oldmode; + u32 val; 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); + val = readl(U300_PIN_REG(offset, pcr)); + /* + * Drive mode must be set by the special mode set function, set + * push/pull mode by default if no mode has been selected. + */ + oldmode = val & (U300_GPIO_PXPCR_PIN_MODE_MASK << + ((offset & 0x07) << 1)); + /* mode = 0 means input, else some mode is already set */ + if (oldmode == 0) { + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK << + ((offset & 0x07) << 1)); + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL + << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); } + u300_gpio_set(chip, offset, value); local_irq_restore(flags); + return 0; } -EXPORT_SYMBOL(gpio_set_value); -int gpio_direction_input(unsigned gpio) +static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { + struct u300_gpio *gpio = to_u300_gpio(chip); + int retirq = gpio->irq_base + offset; + + dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset, + retirq); + return retirq; +} + +static int u300_gpio_config(struct gpio_chip *chip, unsigned offset, + u16 param, unsigned long *data) +{ + struct u300_gpio *gpio = to_u300_gpio(chip); 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); + switch (param) { + case GPIO_U300_CONFIG_BIAS_UNKNOWN: + case GPIO_U300_CONFIG_BIAS_FLOAT: + val = readl(U300_PIN_REG(offset, per)); + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); + break; + case GPIO_U300_CONFIG_BIAS_PULL_UP: + val = readl(U300_PIN_REG(offset, per)); + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, per)); + break; + case GPIO_U300_CONFIG_DRIVE_PUSH_PULL: + val = readl(U300_PIN_REG(offset, pcr)); + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK + << ((offset & 0x07) << 1)); + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_PUSH_PULL + << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); + break; + case GPIO_U300_CONFIG_DRIVE_OPEN_DRAIN: + val = readl(U300_PIN_REG(offset, pcr)); + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK + << ((offset & 0x07) << 1)); + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_DRAIN + << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); + break; + case GPIO_U300_CONFIG_DRIVE_OPEN_SOURCE: + val = readl(U300_PIN_REG(offset, pcr)); + val &= ~(U300_GPIO_PXPCR_PIN_MODE_MASK + << ((offset & 0x07) << 1)); + val |= (U300_GPIO_PXPCR_PIN_MODE_OUTPUT_OPEN_SOURCE + << ((offset & 0x07) << 1)); + writel(val, U300_PIN_REG(offset, pcr)); + break; + default: + local_irq_restore(flags); + dev_err(gpio->dev, "illegal configuration requested\n"); + return -EINVAL; + } local_irq_restore(flags); return 0; } -EXPORT_SYMBOL(gpio_direction_input); -int gpio_direction_output(unsigned gpio, int value) +static struct gpio_chip u300_gpio_chip = { + .label = "u300-gpio-chip", + .owner = THIS_MODULE, + .get = u300_gpio_get, + .set = u300_gpio_set, + .direction_input = u300_gpio_direction_input, + .direction_output = u300_gpio_direction_output, + .to_irq = u300_gpio_to_irq, +}; + +static void u300_toggle_trigger(struct u300_gpio *gpio, unsigned offset) { - 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; + val = readl(U300_PIN_REG(offset, icr)); + /* Set mode depending on state */ + if (u300_gpio_get(&gpio->chip, offset)) { + /* High now, let's trigger on falling edge next then */ + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); + dev_dbg(gpio->dev, "next IRQ on falling edge on pin %d\n", + offset); + } else { + /* Low now, let's trigger on rising edge next then */ + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); + dev_dbg(gpio->dev, "next IRQ on rising edge on pin %d\n", + offset); + } } -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) +static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger) { + struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = port->gpio; + int offset = d->irq - gpio->irq_base; 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); + if ((trigger & IRQF_TRIGGER_RISING) && + (trigger & IRQF_TRIGGER_FALLING)) { + /* + * The GPIO block can only trigger on falling OR rising edges, + * not both. So we need to toggle the mode whenever the pin + * goes from one state to the other with a special state flag + */ + dev_dbg(gpio->dev, + "trigger on both rising and falling edge on pin %d\n", + offset); + port->toggle_edge_mode |= U300_PIN_BIT(offset); + u300_toggle_trigger(gpio, offset); + } else if (trigger & IRQF_TRIGGER_RISING) { + dev_dbg(gpio->dev, "trigger on rising edge on pin %d\n", + offset); + val = readl(U300_PIN_REG(offset, icr)); + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); + port->toggle_edge_mode &= ~U300_PIN_BIT(offset); + } else if (trigger & IRQF_TRIGGER_FALLING) { + dev_dbg(gpio->dev, "trigger on falling edge on pin %d\n", + offset); + val = readl(U300_PIN_REG(offset, icr)); + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, icr)); + port->toggle_edge_mode &= ~U300_PIN_BIT(offset); + } + + return 0; } -EXPORT_SYMBOL(enable_irq_on_gpio_pin); -void disable_irq_on_gpio_pin(unsigned gpio) +static void u300_gpio_irq_enable(struct irq_data *d) { + struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = port->gpio; + int offset = d->irq - gpio->irq_base; 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(U300_PIN_REG(offset, ien)); + writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); 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) +static void u300_gpio_irq_disable(struct irq_data *d) { + struct u300_gpio_port *port = irq_data_get_irq_chip_data(d); + struct u300_gpio *gpio = port->gpio; + int offset = d->irq - gpio->irq_base; 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); - } + val = readl(U300_PIN_REG(offset, ien)); + writel(val & ~U300_PIN_BIT(offset), U300_PIN_REG(offset, ien)); local_irq_restore(flags); } -EXPORT_SYMBOL(gpio_pullup); -static irqreturn_t gpio_irq_handler(int irq, void *dev_id) +static struct irq_chip u300_gpio_irqchip = { + .name = "u300-gpio-irqchip", + .irq_enable = u300_gpio_irq_enable, + .irq_disable = u300_gpio_irq_disable, + .irq_set_type = u300_gpio_irq_type, + +}; + +static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) { - struct u300_gpio_port *port = dev_id; - u32 val; - int pin; + struct u300_gpio_port *port = irq_get_handler_data(irq); + struct u300_gpio *gpio = port->gpio; + int pinoffset = port->number << 3; /* get the right stride */ + unsigned long val; + desc->irq_data.chip->irq_ack(&desc->irq_data); /* 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); + val = readl(U300_PIN_REG(pinoffset, iev)); /* Mask relevant bits */ - val &= U300_GPIO_PXIEV_ALL_IRQ_EVENT_MASK; + val &= 0xFFU; /* 8 bits per port */ /* 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); + writel(val, U300_PIN_REG(pinoffset, iev)); + + /* Call IRQ handler */ + if (val != 0) { + int irqoffset; + + for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) { + int pin_irq = gpio->irq_base + (port->number << 3) + + irqoffset; + int offset = pinoffset + irqoffset; + + dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n", + pin_irq, offset); + generic_handle_irq(pin_irq); + /* + * Triggering IRQ on both rising and falling edge + * needs mockery + */ + if (port->toggle_edge_mode & U300_PIN_BIT(offset)) + u300_toggle_trigger(gpio, offset); + } } - return IRQ_HANDLED; + + desc->irq_data.chip->irq_unmask(&desc->irq_data); } -static void gpio_set_initial_values(void) +static void __init u300_gpio_init_pin(struct u300_gpio *gpio, + int offset, + const struct u300_gpio_confdata *conf) { -#ifdef U300_COH901571_3 - int i, j; - unsigned long flags; - u32 val; + /* Set mode: input or output */ + if (conf->output) { + u300_gpio_direction_output(&gpio->chip, offset, conf->outval); - /* 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); + /* Deactivate bias mode for output */ + u300_gpio_config(&gpio->chip, offset, + GPIO_U300_CONFIG_BIAS_FLOAT, + NULL); + + /* Set drive mode for output */ + u300_gpio_config(&gpio->chip, offset, + GPIO_U300_CONFIG_DRIVE_PUSH_PULL, NULL); + + dev_dbg(gpio->dev, "set up pin %d as output, value: %d\n", + offset, conf->outval); + } else { + u300_gpio_direction_input(&gpio->chip, offset); + + /* Always set output low on input pins */ + u300_gpio_set(&gpio->chip, offset, 0); + + /* Set bias mode for input */ + u300_gpio_config(&gpio->chip, offset, conf->bias_mode, NULL); + + dev_dbg(gpio->dev, "set up pin %d as input, bias: %04x\n", + offset, conf->bias_mode); } +} - /* - * 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); +static void __init u300_gpio_init_coh901571(struct u300_gpio *gpio, + struct u300_gpio_platform *plat) +{ + int i, j; + + /* Write default config and values to all pins */ + for (i = 0; i < plat->ports; i++) { + for (j = 0; j < 8; j++) { + const struct u300_gpio_confdata *conf; + int offset = (i*8) + j; + + if (plat->variant == U300_GPIO_COH901571_3_BS335) + conf = &bs335_gpio_config[i][j]; + else if (plat->variant == U300_GPIO_COH901571_3_BS365) + conf = &bs365_gpio_config[i][j]; + else + break; + + u300_gpio_init_pin(gpio, offset, conf); } } +} - /* 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); +static inline void u300_gpio_free_ports(struct u300_gpio *gpio) +{ + struct u300_gpio_port *port; + struct list_head *p, *n; + + list_for_each_safe(p, n, &gpio->port_list) { + port = list_entry(p, struct u300_gpio_port, node); + list_del(&port->node); + free_irq(port->irq, port); + kfree(port); } -#endif } -static int __init gpio_probe(struct platform_device *pdev) +static int __init u300_gpio_probe(struct platform_device *pdev) { - u32 val; + struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev); + struct u300_gpio *gpio; int err = 0; + int portno; + u32 val; + u32 ifr; int i; - int num_irqs; - gpiodev = &pdev->dev; - memset(gpio_pin, 0, sizeof(gpio_pin)); + gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL); + if (gpio == NULL) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + return -ENOMEM; + } + + gpio->chip = u300_gpio_chip; + gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT; + gpio->irq_base = plat->gpio_irq_base; + gpio->chip.dev = &pdev->dev; + gpio->chip.base = plat->gpio_base; + gpio->dev = &pdev->dev; /* 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"); + gpio->clk = clk_get(gpio->dev, NULL); + if (IS_ERR(gpio->clk)) { + err = PTR_ERR(gpio->clk); + dev_err(gpio->dev, "could not get GPIO clock\n"); goto err_no_clk; } - err = clk_enable(clk); + err = clk_enable(gpio->clk); if (err) { - dev_err(gpiodev, "could not enable GPIO clock\n"); + dev_err(gpio->dev, "could not enable GPIO clock\n"); goto err_no_clk_enable; } - memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!memres) + gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!gpio->memres) { + dev_err(gpio->dev, "could not get GPIO memory resource\n"); + err = -ENODEV; goto err_no_resource; + } - if (!request_mem_region(memres->start, resource_size(memres), + if (!request_mem_region(gpio->memres->start, + resource_size(gpio->memres), "GPIO Controller")) { err = -ENODEV; goto err_no_ioregion; } - virtbase = ioremap(memres->start, resource_size(memres)); - if (!virtbase) { + gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres)); + if (!gpio->base) { 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; + + if (plat->variant == U300_GPIO_COH901335) { + dev_info(gpio->dev, + "initializing GPIO Controller COH 901 335\n"); + gpio->stride = U300_335_PORT_STRIDE; + gpio->pcr = U300_335_PXPCR; + gpio->dor = U300_335_PXPDOR; + gpio->dir = U300_335_PXPDIR; + gpio->per = U300_335_PXPER; + gpio->icr = U300_335_PXICR; + gpio->ien = U300_335_PXIEN; + gpio->iev = U300_335_PXIEV; + ifr = U300_335_PXIFR; + + /* Turn on the GPIO block */ + writel(U300_335_CR_BLOCK_CLOCK_ENABLE, + gpio->base + U300_335_CR); + } else if (plat->variant == U300_GPIO_COH901571_3_BS335 || + plat->variant == U300_GPIO_COH901571_3_BS365) { + dev_info(gpio->dev, + "initializing GPIO Controller COH 901 571/3\n"); + gpio->stride = U300_571_PORT_STRIDE; + gpio->pcr = U300_571_PXPCR; + gpio->dor = U300_571_PXPDOR; + gpio->dir = U300_571_PXPDIR; + gpio->per = U300_571_PXPER; + gpio->icr = U300_571_PXICR; + gpio->ien = U300_571_PXIEN; + gpio->iev = U300_571_PXIEV; + ifr = U300_571_PXIFR; + + val = readl(gpio->base + U300_571_CR); + dev_info(gpio->dev, "COH901571/3 block version: %d, " \ + "number of cores: %d totalling %d pins\n", + ((val & 0x000001FC) >> 2), + ((val & 0x0000FE00) >> 9), + ((val & 0x0000FE00) >> 9) * 8); + writel(U300_571_CR_BLOCK_CLKRQ_ENABLE, + gpio->base + U300_571_CR); + u300_gpio_init_coh901571(gpio, plat); + } else { + dev_err(gpio->dev, "unknown block variant\n"); + err = -ENODEV; + goto err_unknown_variant; + } + + /* Add each port with its IRQ separately */ + INIT_LIST_HEAD(&gpio->port_list); + for (portno = 0 ; portno < plat->ports; portno++) { + struct u300_gpio_port *port = + kmalloc(sizeof(struct u300_gpio_port), GFP_KERNEL); + + if (!port) { + dev_err(gpio->dev, "out of memory\n"); + err = -ENOMEM; + goto err_no_port; } - /* Turns off PortX_irq_force */ - writel(0x0, virtbase + U300_GPIO_PXIFR + - num_irqs * U300_GPIO_PORTX_SPACING); + + snprintf(port->name, 8, "gpio%d", portno); + port->number = portno; + port->gpio = gpio; + + port->irq = platform_get_irq_byname(pdev, + port->name); + + dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq, + port->name); + + irq_set_chained_handler(port->irq, u300_gpio_irq_handler); + irq_set_handler_data(port->irq, port); + + /* For each GPIO pin set the unique IRQ handler */ + for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) { + int irqno = gpio->irq_base + (portno << 3) + i; + + dev_dbg(gpio->dev, "handler for IRQ %d on %s\n", + irqno, port->name); + irq_set_chip_and_handler(irqno, &u300_gpio_irqchip, + handle_simple_irq); + set_irq_flags(irqno, IRQF_VALID); + irq_set_chip_data(irqno, port); + } + + /* Turns off irq force (test register) for this port */ + writel(0x0, gpio->base + portno * gpio->stride + ifr); + + list_add_tail(&port->node, &gpio->port_list); } + dev_dbg(gpio->dev, "initialized %d GPIO ports\n", portno); + + err = gpiochip_add(&gpio->chip); + if (err) { + dev_err(gpio->dev, "unable to add gpiochip: %d\n", err); + goto err_no_chip; + } + + platform_set_drvdata(pdev, gpio); 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, resource_size(memres)); - 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); +err_no_chip: +err_no_port: + u300_gpio_free_ports(gpio); +err_unknown_variant: + iounmap(gpio->base); +err_no_ioremap: + release_mem_region(gpio->memres->start, resource_size(gpio->memres)); +err_no_ioregion: +err_no_resource: + clk_disable(gpio->clk); +err_no_clk_enable: + clk_put(gpio->clk); +err_no_clk: + kfree(gpio); + dev_info(&pdev->dev, "module ERROR:%d\n", err); return err; } -static int __exit gpio_remove(struct platform_device *pdev) +static int __exit u300_gpio_remove(struct platform_device *pdev) { - int i; + struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev); + struct u300_gpio *gpio = platform_get_drvdata(pdev); + int err; /* 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, resource_size(memres)); - clk_disable(clk); - clk_put(clk); + if (plat->variant == U300_GPIO_COH901335) + writel(0x00000000U, gpio->base + U300_335_CR); + if (plat->variant == U300_GPIO_COH901571_3_BS335 || + plat->variant == U300_GPIO_COH901571_3_BS365) + writel(0x00000000U, gpio->base + U300_571_CR); + + err = gpiochip_remove(&gpio->chip); + if (err < 0) { + dev_err(gpio->dev, "unable to remove gpiochip: %d\n", err); + return err; + } + u300_gpio_free_ports(gpio); + iounmap(gpio->base); + release_mem_region(gpio->memres->start, + resource_size(gpio->memres)); + clk_disable(gpio->clk); + clk_put(gpio->clk); + platform_set_drvdata(pdev, NULL); + kfree(gpio); return 0; } -static struct platform_driver gpio_driver = { +static struct platform_driver u300_gpio_driver = { .driver = { .name = "u300-gpio", }, - .remove = __exit_p(gpio_remove), + .remove = __exit_p(u300_gpio_remove), }; static int __init u300_gpio_init(void) { - return platform_driver_probe(&gpio_driver, gpio_probe); + return platform_driver_probe(&u300_gpio_driver, u300_gpio_probe); } static void __exit u300_gpio_exit(void) { - platform_driver_unregister(&gpio_driver); + platform_driver_unregister(&u300_gpio_driver); } arch_initcall(u300_gpio_init); module_exit(u300_gpio_exit); MODULE_AUTHOR("Linus Walleij "); - -#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_DESCRIPTION("ST-Ericsson AB COH 901 335/COH 901 571/3 GPIO driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 98da3529536ed3c78ae493f4cc3d7ac8d43fc72c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 2 May 2011 20:54:38 +0200 Subject: pinctrl: add a driver for the U300 pinmux This adds a driver for the U300 pinmux portions of the system controller "SYSCON". It also serves as an example of how to use the pinmux subsystem. This driver also houses the platform data for the only supported platform. This deletes the old U300 driver in arch/arm/mach-u300 and replace it with a driver using the new subsystem. The new driver is considerably fatter than the old one, but it also registers all 467 pins of the system and adds the power and EMIF pin groups and corresponding functions. The idea is to use this driver as a a reference for other implementation so it needs to be as complete and verbose as possible. Reviewed-by: Barry Song <21cnbao@gmail.com> [Fixup for changed function names and semantics in the v10 patch] Signed-off-by: Linus Walleij --- arch/arm/mach-u300/Kconfig | 2 + arch/arm/mach-u300/Makefile | 2 +- arch/arm/mach-u300/core.c | 84 ++- arch/arm/mach-u300/include/mach/syscon.h | 136 ---- arch/arm/mach-u300/mmc.c | 16 - arch/arm/mach-u300/padmux.c | 367 ---------- arch/arm/mach-u300/padmux.h | 39 - arch/arm/mach-u300/spi.c | 20 - drivers/pinctrl/Kconfig | 7 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinmux-u300.c | 1135 ++++++++++++++++++++++++++++++ 11 files changed, 1228 insertions(+), 581 deletions(-) delete mode 100644 arch/arm/mach-u300/padmux.c delete mode 100644 arch/arm/mach-u300/padmux.h create mode 100644 drivers/pinctrl/pinmux-u300.c (limited to 'arch/arm/mach-u300/core.c') diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig index 32a7b0f7e9f7..449fd6a8dbd6 100644 --- a/arch/arm/mach-u300/Kconfig +++ b/arch/arm/mach-u300/Kconfig @@ -6,6 +6,8 @@ comment "ST-Ericsson Mobile Platform Products" config MACH_U300 bool "U300" + select PINCTRL + select PINMUX_U300 comment "ST-Ericsson U300/U330/U335/U365 Feature Selections" diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile index 8fd354aaf0a7..285538124e5e 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 padmux.o +obj-y := core.o clock.o timer.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index 399c89f14dfb..2f5929bdeaa2 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -1535,6 +1537,14 @@ static struct coh901318_platform coh901318_platform = { .max_channels = U300_DMA_CHANNELS, }; +static struct resource pinmux_resources[] = { + { + .start = U300_SYSCON_BASE, + .end = U300_SYSCON_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, +}; + static struct platform_device wdog_device = { .name = "coh901327_wdog", .id = -1, @@ -1630,6 +1640,72 @@ static struct platform_device dma_device = { }, }; +static struct platform_device pinmux_device = { + .name = "pinmux-u300", + .id = -1, + .num_resources = ARRAY_SIZE(pinmux_resources), + .resource = pinmux_resources, +}; + +/* Pinmux settings */ +static struct pinmux_map u300_pinmux_map[] = { + /* anonymous maps for chip power and EMIFs */ + PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"), + PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"), + PINMUX_MAP_PRIMARY_SYS_HOG("EMIF1", "emif1"), + /* per-device maps for MMC/SD, SPI and UART */ + PINMUX_MAP_PRIMARY("MMCSD", "mmc0", "mmci"), + PINMUX_MAP_PRIMARY("SPI", "spi0", "pl022"), + PINMUX_MAP_PRIMARY("UART0", "uart0", "uart0"), +}; + +struct u300_mux_hog { + const char *name; + struct device *dev; + struct pinmux *pmx; +}; + +static struct u300_mux_hog u300_mux_hogs[] = { + { + .name = "uart0", + .dev = &uart0_device.dev, + }, + { + .name = "spi0", + .dev = &pl022_device.dev, + }, + { + .name = "mmc0", + .dev = &mmcsd_device.dev, + }, +}; + +static int __init u300_pinmux_fetch(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) { + struct pinmux *pmx; + int ret; + + pmx = pinmux_get(u300_mux_hogs[i].dev, NULL); + if (IS_ERR(pmx)) { + pr_err("u300: could not get pinmux hog %s\n", + u300_mux_hogs[i].name); + continue; + } + ret = pinmux_enable(pmx); + if (ret) { + pr_err("u300: could enable pinmux hog %s\n", + u300_mux_hogs[i].name); + continue; + } + u300_mux_hogs[i].pmx = pmx; + } + return 0; +} +subsys_initcall(u300_pinmux_fetch); + /* * Notice that AMBA devices are initialized before platform devices. * @@ -1643,10 +1719,10 @@ static struct platform_device *platform_devs[] __initdata = { &gpio_device, &nand_device, &wdog_device, - &ave_device + &ave_device, + &pinmux_device, }; - /* * Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected * together so some interrupts are connected to the first one and some @@ -1828,6 +1904,10 @@ void __init u300_init_devices(void) u300_assign_physmem(); + /* Initialize pinmuxing */ + pinmux_register_mappings(u300_pinmux_map, + ARRAY_SIZE(u300_pinmux_map)); + /* Register subdevices on the I2C buses */ u300_i2c_register_board_devices(); diff --git a/arch/arm/mach-u300/include/mach/syscon.h b/arch/arm/mach-u300/include/mach/syscon.h index 7444f5c7da97..6e84f07a7c6f 100644 --- a/arch/arm/mach-u300/include/mach/syscon.h +++ b/arch/arm/mach-u300/include/mach/syscon.h @@ -234,91 +234,6 @@ #define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE (0x0004) #define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE (0x0002) #define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE (0x0001) -/* PAD MUX Control register 1 (LOW) 16bit (R/W) */ -#define U300_SYSCON_PMC1LR (0x007C) -#define U300_SYSCON_PMC1LR_MASK (0xFFFF) -#define U300_SYSCON_PMC1LR_CDI_MASK (0xC000) -#define U300_SYSCON_PMC1LR_CDI_CDI (0x0000) -#define U300_SYSCON_PMC1LR_CDI_EMIF (0x4000) -#ifdef CONFIG_MACH_U300_BS335 -#define U300_SYSCON_PMC1LR_CDI_CDI2 (0x8000) -#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO (0xC000) -#elif CONFIG_MACH_U300_BS365 -#define U300_SYSCON_PMC1LR_CDI_GPIO (0x8000) -#define U300_SYSCON_PMC1LR_CDI_WCDMA (0xC000) -#endif -#define U300_SYSCON_PMC1LR_PDI_MASK (0x3000) -#define U300_SYSCON_PMC1LR_PDI_PDI (0x0000) -#define U300_SYSCON_PMC1LR_PDI_EGG (0x1000) -#define U300_SYSCON_PMC1LR_PDI_WCDMA (0x3000) -#define U300_SYSCON_PMC1LR_MMCSD_MASK (0x0C00) -#define U300_SYSCON_PMC1LR_MMCSD_MMCSD (0x0000) -#define U300_SYSCON_PMC1LR_MMCSD_MSPRO (0x0400) -#define U300_SYSCON_PMC1LR_MMCSD_DSP (0x0800) -#define U300_SYSCON_PMC1LR_MMCSD_WCDMA (0x0C00) -#define U300_SYSCON_PMC1LR_ETM_MASK (0x0300) -#define U300_SYSCON_PMC1LR_ETM_ACC (0x0000) -#define U300_SYSCON_PMC1LR_ETM_APP (0x0100) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK (0x00C0) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC (0x0000) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF (0x0040) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM (0x0080) -#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB (0x00C0) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK (0x0030) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC (0x0000) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF (0x0010) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM (0x0020) -#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI (0x0030) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK (0x000C) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC (0x0000) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF (0x0004) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM (0x0008) -#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI (0x000C) -#define U300_SYSCON_PMC1LR_EMIF_1_MASK (0x0003) -#define U300_SYSCON_PMC1LR_EMIF_1_STATIC (0x0000) -#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 (0x0001) -#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 (0x0002) -#define U300_SYSCON_PMC1LR_EMIF_1 (0x0003) -/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */ -#define U300_SYSCON_PMC1HR (0x007E) -#define U300_SYSCON_PMC1HR_MASK (0xFFFF) -#define U300_SYSCON_PMC1HR_MISC_2_MASK (0xC000) -#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_MISC_2_MSPRO (0x4000) -#define U300_SYSCON_PMC1HR_MISC_2_DSP (0x8000) -#define U300_SYSCON_PMC1HR_MISC_2_AAIF (0xC000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK (0x3000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF (0x1000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP (0x2000) -#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF (0x3000) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK (0x0C00) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC (0x0400) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP (0x0800) -#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF (0x0C00) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK (0x0300) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI (0x0100) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF (0x0300) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK (0x00C0) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI (0x0040) -#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF (0x00C0) -#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK (0x0030) -#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI (0x0010) -#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP (0x0020) -#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF (0x0030) -#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK (0x000C) -#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 (0x0004) -#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS (0x0008) -#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF (0x000C) -#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK (0x0003) -#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO (0x0000) -#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 (0x0001) -#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF (0x0003) /* Step one for killing the applications system 16bit (-/W) */ #define U300_SYSCON_KA1R (0x0080) #define U300_SYSCON_KA1R_MASK (0xFFFF) @@ -357,57 +272,6 @@ #define U300_SYSCON_PUCR_EMIF_1_16BIT_PU_ENABLE (0x0080) #define U300_SYSCON_PUCR_EMIF_1_8BIT_PU_ENABLE (0x0040) #define U300_SYSCON_PUCR_KEY_IN_PU_EN_MASK (0x003F) -/* Padmux 2 control */ -#define U300_SYSCON_PMC2R (0x100) -#define U300_SYSCON_PMC2R_APP_MISC_0_MASK (0x00C0) -#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM (0x0040) -#define U300_SYSCON_PMC2R_APP_MISC_0_MMC (0x0080) -#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2 (0x00C0) -#define U300_SYSCON_PMC2R_APP_MISC_1_MASK (0x0300) -#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM (0x0100) -#define U300_SYSCON_PMC2R_APP_MISC_1_MMC (0x0200) -#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2 (0x0300) -#define U300_SYSCON_PMC2R_APP_MISC_2_MASK (0x0C00) -#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM (0x0400) -#define U300_SYSCON_PMC2R_APP_MISC_2_MMC (0x0800) -#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2 (0x0C00) -#define U300_SYSCON_PMC2R_APP_MISC_3_MASK (0x3000) -#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM (0x1000) -#define U300_SYSCON_PMC2R_APP_MISC_3_MMC (0x2000) -#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2 (0x3000) -#define U300_SYSCON_PMC2R_APP_MISC_4_MASK (0xC000) -#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO (0x0000) -#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM (0x4000) -#define U300_SYSCON_PMC2R_APP_MISC_4_MMC (0x8000) -#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO (0xC000) -/* TODO: More SYSCON registers missing */ -#define U300_SYSCON_PMC3R (0x10c) -#define U300_SYSCON_PMC3R_APP_MISC_11_MASK (0xc000) -#define U300_SYSCON_PMC3R_APP_MISC_11_SPI (0x4000) -#define U300_SYSCON_PMC3R_APP_MISC_10_MASK (0x3000) -#define U300_SYSCON_PMC3R_APP_MISC_10_SPI (0x1000) -/* TODO: Missing other configs */ -#define U300_SYSCON_PMC4R (0x168) -#define U300_SYSCON_PMC4R_APP_MISC_12_MASK (0x0003) -#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO (0x0000) -#define U300_SYSCON_PMC4R_APP_MISC_13_MASK (0x000C) -#define U300_SYSCON_PMC4R_APP_MISC_13_CDI (0x0000) -#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA (0x0004) -#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2 (0x0008) -#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO (0x000C) -#define U300_SYSCON_PMC4R_APP_MISC_14_MASK (0x0030) -#define U300_SYSCON_PMC4R_APP_MISC_14_CDI (0x0000) -#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA (0x0010) -#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2 (0x0020) -#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO (0x0030) -#define U300_SYSCON_PMC4R_APP_MISC_16_MASK (0x0300) -#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13 (0x0000) -#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS (0x0100) -#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N (0x0200) /* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */ #define U300_SYSCON_S0CCR (0x120) #define U300_SYSCON_S0CCR_FIELD_MASK (0x43FF) diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c index 677ccef5cd32..d5e4a98a9ab8 100644 --- a/arch/arm/mach-u300/mmc.c +++ b/arch/arm/mach-u300/mmc.c @@ -21,7 +21,6 @@ #include #include "mmc.h" -#include "padmux.h" static struct mmci_platform_data mmc0_plat_data = { /* @@ -45,24 +44,9 @@ static struct mmci_platform_data mmc0_plat_data = { int __devinit mmc_init(struct amba_device *adev) { struct device *mmcsd_device = &adev->dev; - struct pmx *pmx; int ret = 0; mmcsd_device->platform_data = &mmc0_plat_data; - /* - * Setup padmuxing for MMC. Since this must always be - * compiled into the kernel, pmx is never released. - */ - pmx = pmx_get(mmcsd_device, U300_APP_PMX_MMC_SETTING); - - if (IS_ERR(pmx)) - pr_warning("Could not get padmux handle\n"); - else { - ret = pmx_activate(mmcsd_device, pmx); - if (IS_ERR_VALUE(ret)) - pr_warning("Could not activate padmuxing\n"); - } - return ret; } diff --git a/arch/arm/mach-u300/padmux.c b/arch/arm/mach-u300/padmux.c deleted file mode 100644 index 4c93c6cefd37..000000000000 --- a/arch/arm/mach-u300/padmux.c +++ /dev/null @@ -1,367 +0,0 @@ -/* - * - * 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: Martin Persson - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "padmux.h" - -static DEFINE_MUTEX(pmx_mutex); - -const u32 pmx_registers[] = { - (U300_SYSCON_VBASE + U300_SYSCON_PMC1LR), - (U300_SYSCON_VBASE + U300_SYSCON_PMC1HR), - (U300_SYSCON_VBASE + U300_SYSCON_PMC2R), - (U300_SYSCON_VBASE + U300_SYSCON_PMC3R), - (U300_SYSCON_VBASE + U300_SYSCON_PMC4R) -}; - -/* High level functionality */ - -/* Lazy dog: - * onmask = { - * {"PMC1LR" mask, "PMC1LR" value}, - * {"PMC1HR" mask, "PMC1HR" value}, - * {"PMC2R" mask, "PMC2R" value}, - * {"PMC3R" mask, "PMC3R" value}, - * {"PMC4R" mask, "PMC4R" value} - * } - */ -static struct pmx mmc_setting = { - .setting = U300_APP_PMX_MMC_SETTING, - .default_on = false, - .activated = false, - .name = "MMC", - .onmask = { - {U300_SYSCON_PMC1LR_MMCSD_MASK, - U300_SYSCON_PMC1LR_MMCSD_MMCSD}, - {0, 0}, - {0, 0}, - {0, 0}, - {U300_SYSCON_PMC4R_APP_MISC_12_MASK, - U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO} - }, -}; - -static struct pmx spi_setting = { - .setting = U300_APP_PMX_SPI_SETTING, - .default_on = false, - .activated = false, - .name = "SPI", - .onmask = {{0, 0}, - {U300_SYSCON_PMC1HR_APP_SPI_2_MASK | - U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK | - U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK, - U300_SYSCON_PMC1HR_APP_SPI_2_SPI | - U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI | - U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI}, - {0, 0}, - {0, 0}, - {0, 0} - }, -}; - -/* Available padmux settings */ -static struct pmx *pmx_settings[] = { - &mmc_setting, - &spi_setting, -}; - -static void update_registers(struct pmx *pmx, bool activate) -{ - u16 regval, val, mask; - int i; - - for (i = 0; i < ARRAY_SIZE(pmx_registers); i++) { - if (activate) - val = pmx->onmask[i].val; - else - val = 0; - - mask = pmx->onmask[i].mask; - if (mask != 0) { - regval = readw(pmx_registers[i]); - regval &= ~mask; - regval |= val; - writew(regval, pmx_registers[i]); - } - } -} - -struct pmx *pmx_get(struct device *dev, enum pmx_settings setting) -{ - int i; - struct pmx *pmx = ERR_PTR(-ENOENT); - - if (dev == NULL) - return ERR_PTR(-EINVAL); - - mutex_lock(&pmx_mutex); - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (setting == pmx_settings[i]->setting) { - - if (pmx_settings[i]->dev != NULL) { - WARN(1, "padmux: required setting " - "in use by another consumer\n"); - } else { - pmx = pmx_settings[i]; - pmx->dev = dev; - dev_dbg(dev, "padmux: setting nr %d is now " - "bound to %s and ready to use\n", - setting, dev_name(dev)); - break; - } - } - } - mutex_unlock(&pmx_mutex); - - return pmx; -} -EXPORT_SYMBOL(pmx_get); - -int pmx_put(struct device *dev, struct pmx *pmx) -{ - int i; - int ret = -ENOENT; - - if (pmx == NULL || dev == NULL) - return -EINVAL; - - mutex_lock(&pmx_mutex); - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (pmx->setting == pmx_settings[i]->setting) { - - if (dev != pmx->dev) { - WARN(1, "padmux: cannot release handle as " - "it is bound to another consumer\n"); - ret = -EINVAL; - break; - } else { - pmx_settings[i]->dev = NULL; - ret = 0; - break; - } - } - } - mutex_unlock(&pmx_mutex); - - return ret; -} -EXPORT_SYMBOL(pmx_put); - -int pmx_activate(struct device *dev, struct pmx *pmx) -{ - int i, j, ret; - ret = 0; - - if (pmx == NULL || dev == NULL) - return -EINVAL; - - mutex_lock(&pmx_mutex); - - /* Make sure the required bits are not used */ - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (pmx_settings[i]->dev == NULL || pmx_settings[i] == pmx) - continue; - - for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) { - - if (pmx_settings[i]->onmask[j].mask & pmx-> - onmask[j].mask) { - /* More than one entry on the same bits */ - WARN(1, "padmux: cannot activate " - "setting. Bit conflict with " - "an active setting\n"); - - ret = -EUSERS; - goto exit; - } - } - } - update_registers(pmx, true); - pmx->activated = true; - dev_dbg(dev, "padmux: setting nr %d is activated\n", - pmx->setting); - -exit: - mutex_unlock(&pmx_mutex); - return ret; -} -EXPORT_SYMBOL(pmx_activate); - -int pmx_deactivate(struct device *dev, struct pmx *pmx) -{ - int i; - int ret = -ENOENT; - - if (pmx == NULL || dev == NULL) - return -EINVAL; - - mutex_lock(&pmx_mutex); - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (pmx_settings[i]->dev == NULL) - continue; - - if (pmx->setting == pmx_settings[i]->setting) { - - if (dev != pmx->dev) { - WARN(1, "padmux: cannot deactivate " - "pmx setting as it was activated " - "by another consumer\n"); - - ret = -EBUSY; - continue; - } else { - update_registers(pmx, false); - pmx_settings[i]->dev = NULL; - pmx->activated = false; - ret = 0; - dev_dbg(dev, "padmux: setting nr %d is deactivated", - pmx->setting); - break; - } - } - } - mutex_unlock(&pmx_mutex); - - return ret; -} -EXPORT_SYMBOL(pmx_deactivate); - -/* - * For internal use only. If it is to be exported, - * it should be reentrant. Notice that pmx_activate - * (i.e. runtime settings) always override default settings. - */ -static int pmx_set_default(void) -{ - /* Used to identify several entries on the same bits */ - u16 modbits[ARRAY_SIZE(pmx_registers)]; - - int i, j; - - memset(modbits, 0, ARRAY_SIZE(pmx_registers) * sizeof(u16)); - - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - - if (!pmx_settings[i]->default_on) - continue; - - for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) { - - /* Make sure there is only one entry on the same bits */ - if (modbits[j] & pmx_settings[i]->onmask[j].mask) { - BUG(); - return -EUSERS; - } - modbits[j] |= pmx_settings[i]->onmask[j].mask; - } - update_registers(pmx_settings[i], true); - } - return 0; -} - -#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG)) -static int pmx_show(struct seq_file *s, void *data) -{ - int i; - seq_printf(s, "-------------------------------------------------\n"); - seq_printf(s, "SETTING BOUND TO DEVICE STATE\n"); - seq_printf(s, "-------------------------------------------------\n"); - mutex_lock(&pmx_mutex); - for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) { - /* Format pmx and device name nicely */ - char cdp[33]; - int chars; - - chars = snprintf(&cdp[0], 17, "%s", pmx_settings[i]->name); - while (chars < 16) { - cdp[chars] = ' '; - chars++; - } - chars = snprintf(&cdp[16], 17, "%s", pmx_settings[i]->dev ? - dev_name(pmx_settings[i]->dev) : "N/A"); - while (chars < 16) { - cdp[chars+16] = ' '; - chars++; - } - cdp[32] = '\0'; - - seq_printf(s, - "%s\t%s\n", - &cdp[0], - pmx_settings[i]->activated ? - "ACTIVATED" : "DEACTIVATED" - ); - - } - mutex_unlock(&pmx_mutex); - return 0; -} - -static int pmx_open(struct inode *inode, struct file *file) -{ - return single_open(file, pmx_show, NULL); -} - -static const struct file_operations pmx_operations = { - .owner = THIS_MODULE, - .open = pmx_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init init_pmx_read_debugfs(void) -{ - /* Expose a simple debugfs interface to view pmx settings */ - (void) debugfs_create_file("padmux", S_IFREG | S_IRUGO, - NULL, NULL, - &pmx_operations); - return 0; -} - -/* - * This needs to come in after the core_initcall(), - * because debugfs is not available until - * the subsystems come up. - */ -module_init(init_pmx_read_debugfs); -#endif - -static int __init pmx_init(void) -{ - int ret; - - ret = pmx_set_default(); - - if (IS_ERR_VALUE(ret)) - pr_crit("padmux: default settings could not be set\n"); - - return 0; -} - -/* Should be initialized before consumers */ -core_initcall(pmx_init); diff --git a/arch/arm/mach-u300/padmux.h b/arch/arm/mach-u300/padmux.h deleted file mode 100644 index 6e8b86064097..000000000000 --- a/arch/arm/mach-u300/padmux.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * 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: Martin Persson - */ - -#ifndef __MACH_U300_PADMUX_H -#define __MACH_U300_PADMUX_H - -enum pmx_settings { - U300_APP_PMX_MMC_SETTING, - U300_APP_PMX_SPI_SETTING -}; - -struct pmx_onmask { - u16 mask; /* Mask bits */ - u16 val; /* Value when active */ -}; - -struct pmx { - struct device *dev; - enum pmx_settings setting; - char *name; - bool activated; - bool default_on; - struct pmx_onmask onmask[]; -}; - -struct pmx *pmx_get(struct device *dev, enum pmx_settings setting); -int pmx_put(struct device *dev, struct pmx *pmx); -int pmx_activate(struct device *dev, struct pmx *pmx); -int pmx_deactivate(struct device *dev, struct pmx *pmx); - -#endif diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c index 7b597e2b19e2..a1affacfa59c 100644 --- a/arch/arm/mach-u300/spi.c +++ b/arch/arm/mach-u300/spi.c @@ -14,8 +14,6 @@ #include #include -#include "padmux.h" - /* * The following is for the actual devices on the SSP/SPI bus */ @@ -95,25 +93,7 @@ static struct pl022_ssp_controller ssp_platform_data = { void __init u300_spi_init(struct amba_device *adev) { - struct pmx *pmx; - adev->dev.platform_data = &ssp_platform_data; - /* - * Setup padmuxing for SPI. Since this must always be - * compiled into the kernel, pmx is never released. - */ - pmx = pmx_get(&adev->dev, U300_APP_PMX_SPI_SETTING); - - if (IS_ERR(pmx)) - dev_warn(&adev->dev, "Could not get padmux handle\n"); - else { - int ret; - - ret = pmx_activate(&adev->dev, pmx); - if (IS_ERR_VALUE(ret)) - dev_warn(&adev->dev, "Could not activate padmuxing\n"); - } - } void __init u300_spi_register_board_devices(void) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 02b4d4e92ffe..7b175c37731f 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -26,4 +26,11 @@ config DEBUG_PINCTRL help Say Y here to add some extra checks and diagnostics to PINCTRL calls. +config PINMUX_U300 + bool "U300 pinmux driver" + depends on ARCH_U300 + select PINMUX + help + Say Y here to enable the U300 pinmux driver + endif diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 596ce9f22896..63d4241a0918 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -4,3 +4,4 @@ ccflags-$(CONFIG_DEBUG_PINMUX) += -DDEBUG obj-$(CONFIG_PINCTRL) += core.o obj-$(CONFIG_PINMUX) += pinmux.o +obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinmux-u300.c new file mode 100644 index 000000000000..f9db1cebff00 --- /dev/null +++ b/drivers/pinctrl/pinmux-u300.c @@ -0,0 +1,1135 @@ +/* + * Driver for the U300 pin controller + * + * Based on the original U300 padmux functions + * Copyright (C) 2009-2011 ST-Ericsson AB + * Author: Martin Persson + * Author: Linus Walleij + * + * The DB3350 design and control registers are oriented around pads rather than + * pins, so we enumerate the pads we can mux rather than actual pins. The pads + * are connected to different pins in different packaging types, so it would + * be confusing. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Register definitions for the U300 Padmux control registers in the + * system controller + */ + +/* PAD MUX Control register 1 (LOW) 16bit (R/W) */ +#define U300_SYSCON_PMC1LR 0x007C +#define U300_SYSCON_PMC1LR_MASK 0xFFFF +#define U300_SYSCON_PMC1LR_CDI_MASK 0xC000 +#define U300_SYSCON_PMC1LR_CDI_CDI 0x0000 +#define U300_SYSCON_PMC1LR_CDI_EMIF 0x4000 +/* For BS335 */ +#define U300_SYSCON_PMC1LR_CDI_CDI2 0x8000 +#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO 0xC000 +/* For BS365 */ +#define U300_SYSCON_PMC1LR_CDI_GPIO 0x8000 +#define U300_SYSCON_PMC1LR_CDI_WCDMA 0xC000 +/* Common defs */ +#define U300_SYSCON_PMC1LR_PDI_MASK 0x3000 +#define U300_SYSCON_PMC1LR_PDI_PDI 0x0000 +#define U300_SYSCON_PMC1LR_PDI_EGG 0x1000 +#define U300_SYSCON_PMC1LR_PDI_WCDMA 0x3000 +#define U300_SYSCON_PMC1LR_MMCSD_MASK 0x0C00 +#define U300_SYSCON_PMC1LR_MMCSD_MMCSD 0x0000 +#define U300_SYSCON_PMC1LR_MMCSD_MSPRO 0x0400 +#define U300_SYSCON_PMC1LR_MMCSD_DSP 0x0800 +#define U300_SYSCON_PMC1LR_MMCSD_WCDMA 0x0C00 +#define U300_SYSCON_PMC1LR_ETM_MASK 0x0300 +#define U300_SYSCON_PMC1LR_ETM_ACC 0x0000 +#define U300_SYSCON_PMC1LR_ETM_APP 0x0100 +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK 0x00C0 +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC 0x0000 +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF 0x0040 +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM 0x0080 +#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB 0x00C0 +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK 0x0030 +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC 0x0000 +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF 0x0010 +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM 0x0020 +#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI 0x0030 +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK 0x000C +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC 0x0000 +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF 0x0004 +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM 0x0008 +#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI 0x000C +#define U300_SYSCON_PMC1LR_EMIF_1_MASK 0x0003 +#define U300_SYSCON_PMC1LR_EMIF_1_STATIC 0x0000 +#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 0x0001 +#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 0x0002 +#define U300_SYSCON_PMC1LR_EMIF_1 0x0003 +/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */ +#define U300_SYSCON_PMC1HR 0x007E +#define U300_SYSCON_PMC1HR_MASK 0xFFFF +#define U300_SYSCON_PMC1HR_MISC_2_MASK 0xC000 +#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO 0x0000 +#define U300_SYSCON_PMC1HR_MISC_2_MSPRO 0x4000 +#define U300_SYSCON_PMC1HR_MISC_2_DSP 0x8000 +#define U300_SYSCON_PMC1HR_MISC_2_AAIF 0xC000 +#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK 0x3000 +#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO 0x0000 +#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF 0x1000 +#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP 0x2000 +#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF 0x3000 +#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK 0x0C00 +#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO 0x0000 +#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC 0x0400 +#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP 0x0800 +#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF 0x0C00 +#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK 0x0300 +#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO 0x0000 +#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI 0x0100 +#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF 0x0300 +#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK 0x00C0 +#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO 0x0000 +#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI 0x0040 +#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF 0x00C0 +#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK 0x0030 +#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO 0x0000 +#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI 0x0010 +#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP 0x0020 +#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF 0x0030 +#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK 0x000C +#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO 0x0000 +#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 0x0004 +#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS 0x0008 +#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF 0x000C +#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK 0x0003 +#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO 0x0000 +#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 0x0001 +#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF 0x0003 +/* Padmux 2 control */ +#define U300_SYSCON_PMC2R 0x100 +#define U300_SYSCON_PMC2R_APP_MISC_0_MASK 0x00C0 +#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO 0x0000 +#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM 0x0040 +#define U300_SYSCON_PMC2R_APP_MISC_0_MMC 0x0080 +#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2 0x00C0 +#define U300_SYSCON_PMC2R_APP_MISC_1_MASK 0x0300 +#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO 0x0000 +#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM 0x0100 +#define U300_SYSCON_PMC2R_APP_MISC_1_MMC 0x0200 +#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2 0x0300 +#define U300_SYSCON_PMC2R_APP_MISC_2_MASK 0x0C00 +#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO 0x0000 +#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM 0x0400 +#define U300_SYSCON_PMC2R_APP_MISC_2_MMC 0x0800 +#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2 0x0C00 +#define U300_SYSCON_PMC2R_APP_MISC_3_MASK 0x3000 +#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO 0x0000 +#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM 0x1000 +#define U300_SYSCON_PMC2R_APP_MISC_3_MMC 0x2000 +#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2 0x3000 +#define U300_SYSCON_PMC2R_APP_MISC_4_MASK 0xC000 +#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO 0x0000 +#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM 0x4000 +#define U300_SYSCON_PMC2R_APP_MISC_4_MMC 0x8000 +#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO 0xC000 +/* TODO: More SYSCON registers missing */ +#define U300_SYSCON_PMC3R 0x10C +#define U300_SYSCON_PMC3R_APP_MISC_11_MASK 0xC000 +#define U300_SYSCON_PMC3R_APP_MISC_11_SPI 0x4000 +#define U300_SYSCON_PMC3R_APP_MISC_10_MASK 0x3000 +#define U300_SYSCON_PMC3R_APP_MISC_10_SPI 0x1000 +/* TODO: Missing other configs */ +#define U300_SYSCON_PMC4R 0x168 +#define U300_SYSCON_PMC4R_APP_MISC_12_MASK 0x0003 +#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO 0x0000 +#define U300_SYSCON_PMC4R_APP_MISC_13_MASK 0x000C +#define U300_SYSCON_PMC4R_APP_MISC_13_CDI 0x0000 +#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA 0x0004 +#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2 0x0008 +#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO 0x000C +#define U300_SYSCON_PMC4R_APP_MISC_14_MASK 0x0030 +#define U300_SYSCON_PMC4R_APP_MISC_14_CDI 0x0000 +#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA 0x0010 +#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2 0x0020 +#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO 0x0030 +#define U300_SYSCON_PMC4R_APP_MISC_16_MASK 0x0300 +#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13 0x0000 +#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS 0x0100 +#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N 0x0200 + +#define DRIVER_NAME "pinmux-u300" + +/* + * The DB3350 has 467 pads, I have enumerated the pads clockwise around the + * edges of the silicon, finger by finger. LTCORNER upper left is pad 0. + * Data taken from the PadRing chart, arranged like this: + * + * 0 ..... 104 + * 466 105 + * . . + * . . + * 358 224 + * 357 .... 225 + */ +#define U300_NUM_PADS 467 + +/* Pad names for the pinmux subsystem */ +static const struct pinctrl_pin_desc __refdata u300_pads[] = { + /* Pads along the top edge of the chip */ + PINCTRL_PIN(0, "P PAD VDD 28"), + PINCTRL_PIN(1, "P PAD GND 28"), + PINCTRL_PIN(2, "PO SIM RST N"), + PINCTRL_PIN(3, "VSSIO 25"), + PINCTRL_PIN(4, "VSSA ADDA ESDSUB"), + PINCTRL_PIN(5, "PWR VSSCOMMON"), + PINCTRL_PIN(6, "PI ADC I1 POS"), + PINCTRL_PIN(7, "PI ADC I1 NEG"), + PINCTRL_PIN(8, "PWR VSSAD0"), + PINCTRL_PIN(9, "PWR VCCAD0"), + PINCTRL_PIN(10, "PI ADC Q1 NEG"), + PINCTRL_PIN(11, "PI ADC Q1 POS"), + PINCTRL_PIN(12, "PWR VDDAD"), + PINCTRL_PIN(13, "PWR GNDAD"), + PINCTRL_PIN(14, "PI ADC I2 POS"), + PINCTRL_PIN(15, "PI ADC I2 NEG"), + PINCTRL_PIN(16, "PWR VSSAD1"), + PINCTRL_PIN(17, "PWR VCCAD1"), + PINCTRL_PIN(18, "PI ADC Q2 NEG"), + PINCTRL_PIN(19, "PI ADC Q2 POS"), + PINCTRL_PIN(20, "VSSA ADDA ESDSUB"), + PINCTRL_PIN(21, "PWR VCCGPAD"), + PINCTRL_PIN(22, "PI TX POW"), + PINCTRL_PIN(23, "PWR VSSGPAD"), + PINCTRL_PIN(24, "PO DAC I POS"), + PINCTRL_PIN(25, "PO DAC I NEG"), + PINCTRL_PIN(26, "PO DAC Q POS"), + PINCTRL_PIN(27, "PO DAC Q NEG"), + PINCTRL_PIN(28, "PWR VSSDA"), + PINCTRL_PIN(29, "PWR VCCDA"), + PINCTRL_PIN(30, "VSSA ADDA ESDSUB"), + PINCTRL_PIN(31, "P PAD VDDIO 11"), + PINCTRL_PIN(32, "PI PLL 26 FILTVDD"), + PINCTRL_PIN(33, "PI PLL 26 VCONT"), + PINCTRL_PIN(34, "PWR AGNDPLL2V5 32 13"), + PINCTRL_PIN(35, "PWR AVDDPLL2V5 32 13"), + PINCTRL_PIN(36, "VDDA PLL ESD"), + PINCTRL_PIN(37, "VSSA PLL ESD"), + PINCTRL_PIN(38, "VSS PLL"), + PINCTRL_PIN(39, "VDDC PLL"), + PINCTRL_PIN(40, "PWR AGNDPLL2V5 26 60"), + PINCTRL_PIN(41, "PWR AVDDPLL2V5 26 60"), + PINCTRL_PIN(42, "PWR AVDDPLL2V5 26 208"), + PINCTRL_PIN(43, "PWR AGNDPLL2V5 26 208"), + PINCTRL_PIN(44, "PWR AVDDPLL2V5 13 208"), + PINCTRL_PIN(45, "PWR AGNDPLL2V5 13 208"), + PINCTRL_PIN(46, "P PAD VSSIO 11"), + PINCTRL_PIN(47, "P PAD VSSIO 12"), + PINCTRL_PIN(48, "PI POW RST N"), + PINCTRL_PIN(49, "VDDC IO"), + PINCTRL_PIN(50, "P PAD VDDIO 16"), + PINCTRL_PIN(51, "PO RF WCDMA EN 4"), + PINCTRL_PIN(52, "PO RF WCDMA EN 3"), + PINCTRL_PIN(53, "PO RF WCDMA EN 2"), + PINCTRL_PIN(54, "PO RF WCDMA EN 1"), + PINCTRL_PIN(55, "PO RF WCDMA EN 0"), + PINCTRL_PIN(56, "PO GSM PA ENABLE"), + PINCTRL_PIN(57, "PO RF DATA STRB"), + PINCTRL_PIN(58, "PO RF DATA2"), + PINCTRL_PIN(59, "PIO RF DATA1"), + PINCTRL_PIN(60, "PIO RF DATA0"), + PINCTRL_PIN(61, "P PAD VDD 11"), + PINCTRL_PIN(62, "P PAD GND 11"), + PINCTRL_PIN(63, "P PAD VSSIO 16"), + PINCTRL_PIN(64, "P PAD VDDIO 18"), + PINCTRL_PIN(65, "PO RF CTRL STRB2"), + PINCTRL_PIN(66, "PO RF CTRL STRB1"), + PINCTRL_PIN(67, "PO RF CTRL STRB0"), + PINCTRL_PIN(68, "PIO RF CTRL DATA"), + PINCTRL_PIN(69, "PO RF CTRL CLK"), + PINCTRL_PIN(70, "PO TX ADC STRB"), + PINCTRL_PIN(71, "PO ANT SW 2"), + PINCTRL_PIN(72, "PO ANT SW 3"), + PINCTRL_PIN(73, "PO ANT SW 0"), + PINCTRL_PIN(74, "PO ANT SW 1"), + PINCTRL_PIN(75, "PO M CLKRQ"), + PINCTRL_PIN(76, "PI M CLK"), + PINCTRL_PIN(77, "PI RTC CLK"), + PINCTRL_PIN(78, "P PAD VDD 8"), + PINCTRL_PIN(79, "P PAD GND 8"), + PINCTRL_PIN(80, "P PAD VSSIO 13"), + PINCTRL_PIN(81, "P PAD VDDIO 13"), + PINCTRL_PIN(82, "PO SYS 1 CLK"), + PINCTRL_PIN(83, "PO SYS 2 CLK"), + PINCTRL_PIN(84, "PO SYS 0 CLK"), + PINCTRL_PIN(85, "PI SYS 0 CLKRQ"), + PINCTRL_PIN(86, "PO PWR MNGT CTRL 1"), + PINCTRL_PIN(87, "PO PWR MNGT CTRL 0"), + PINCTRL_PIN(88, "PO RESOUT2 RST N"), + PINCTRL_PIN(89, "PO RESOUT1 RST N"), + PINCTRL_PIN(90, "PO RESOUT0 RST N"), + PINCTRL_PIN(91, "PI SERVICE N"), + PINCTRL_PIN(92, "P PAD VDD 29"), + PINCTRL_PIN(93, "P PAD GND 29"), + PINCTRL_PIN(94, "P PAD VSSIO 8"), + PINCTRL_PIN(95, "P PAD VDDIO 8"), + PINCTRL_PIN(96, "PI EXT IRQ1 N"), + PINCTRL_PIN(97, "PI EXT IRQ0 N"), + PINCTRL_PIN(98, "PIO DC ON"), + PINCTRL_PIN(99, "PIO ACC APP I2C DATA"), + PINCTRL_PIN(100, "PIO ACC APP I2C CLK"), + PINCTRL_PIN(101, "P PAD VDD 12"), + PINCTRL_PIN(102, "P PAD GND 12"), + PINCTRL_PIN(103, "P PAD VSSIO 14"), + PINCTRL_PIN(104, "P PAD VDDIO 14"), + /* Pads along the right edge of the chip */ + PINCTRL_PIN(105, "PIO APP I2C1 DATA"), + PINCTRL_PIN(106, "PIO APP I2C1 CLK"), + PINCTRL_PIN(107, "PO KEY OUT0"), + PINCTRL_PIN(108, "PO KEY OUT1"), + PINCTRL_PIN(109, "PO KEY OUT2"), + PINCTRL_PIN(110, "PO KEY OUT3"), + PINCTRL_PIN(111, "PO KEY OUT4"), + PINCTRL_PIN(112, "PI KEY IN0"), + PINCTRL_PIN(113, "PI KEY IN1"), + PINCTRL_PIN(114, "PI KEY IN2"), + PINCTRL_PIN(115, "P PAD VDDIO 15"), + PINCTRL_PIN(116, "P PAD VSSIO 15"), + PINCTRL_PIN(117, "P PAD GND 13"), + PINCTRL_PIN(118, "P PAD VDD 13"), + PINCTRL_PIN(119, "PI KEY IN3"), + PINCTRL_PIN(120, "PI KEY IN4"), + PINCTRL_PIN(121, "PI KEY IN5"), + PINCTRL_PIN(122, "PIO APP PCM I2S1 DATA B"), + PINCTRL_PIN(123, "PIO APP PCM I2S1 DATA A"), + PINCTRL_PIN(124, "PIO APP PCM I2S1 WS"), + PINCTRL_PIN(125, "PIO APP PCM I2S1 CLK"), + PINCTRL_PIN(126, "PIO APP PCM I2S0 DATA B"), + PINCTRL_PIN(127, "PIO APP PCM I2S0 DATA A"), + PINCTRL_PIN(128, "PIO APP PCM I2S0 WS"), + PINCTRL_PIN(129, "PIO APP PCM I2S0 CLK"), + PINCTRL_PIN(130, "P PAD VDD 17"), + PINCTRL_PIN(131, "P PAD GND 17"), + PINCTRL_PIN(132, "P PAD VSSIO 19"), + PINCTRL_PIN(133, "P PAD VDDIO 19"), + PINCTRL_PIN(134, "UART0 RTS"), + PINCTRL_PIN(135, "UART0 CTS"), + PINCTRL_PIN(136, "UART0 TX"), + PINCTRL_PIN(137, "UART0 RX"), + PINCTRL_PIN(138, "PIO ACC SPI DO"), + PINCTRL_PIN(139, "PIO ACC SPI DI"), + PINCTRL_PIN(140, "PIO ACC SPI CS0 N"), + PINCTRL_PIN(141, "PIO ACC SPI CS1 N"), + PINCTRL_PIN(142, "PIO ACC SPI CS2 N"), + PINCTRL_PIN(143, "PIO ACC SPI CLK"), + PINCTRL_PIN(144, "PO PDI EXT RST N"), + PINCTRL_PIN(145, "P PAD VDDIO 22"), + PINCTRL_PIN(146, "P PAD VSSIO 22"), + PINCTRL_PIN(147, "P PAD GND 18"), + PINCTRL_PIN(148, "P PAD VDD 18"), + PINCTRL_PIN(149, "PIO PDI C0"), + PINCTRL_PIN(150, "PIO PDI C1"), + PINCTRL_PIN(151, "PIO PDI C2"), + PINCTRL_PIN(152, "PIO PDI C3"), + PINCTRL_PIN(153, "PIO PDI C4"), + PINCTRL_PIN(154, "PIO PDI C5"), + PINCTRL_PIN(155, "PIO PDI D0"), + PINCTRL_PIN(156, "PIO PDI D1"), + PINCTRL_PIN(157, "PIO PDI D2"), + PINCTRL_PIN(158, "PIO PDI D3"), + PINCTRL_PIN(159, "P PAD VDDIO 21"), + PINCTRL_PIN(160, "P PAD VSSIO 21"), + PINCTRL_PIN(161, "PIO PDI D4"), + PINCTRL_PIN(162, "PIO PDI D5"), + PINCTRL_PIN(163, "PIO PDI D6"), + PINCTRL_PIN(164, "PIO PDI D7"), + PINCTRL_PIN(165, "PIO MS INS"), + PINCTRL_PIN(166, "MMC DATA DIR LS"), + PINCTRL_PIN(167, "MMC DATA 3"), + PINCTRL_PIN(168, "MMC DATA 2"), + PINCTRL_PIN(169, "MMC DATA 1"), + PINCTRL_PIN(170, "MMC DATA 0"), + PINCTRL_PIN(171, "MMC CMD DIR LS"), + PINCTRL_PIN(172, "P PAD VDD 27"), + PINCTRL_PIN(173, "P PAD GND 27"), + PINCTRL_PIN(174, "P PAD VSSIO 20"), + PINCTRL_PIN(175, "P PAD VDDIO 20"), + PINCTRL_PIN(176, "MMC CMD"), + PINCTRL_PIN(177, "MMC CLK"), + PINCTRL_PIN(178, "PIO APP GPIO 14"), + PINCTRL_PIN(179, "PIO APP GPIO 13"), + PINCTRL_PIN(180, "PIO APP GPIO 11"), + PINCTRL_PIN(181, "PIO APP GPIO 25"), + PINCTRL_PIN(182, "PIO APP GPIO 24"), + PINCTRL_PIN(183, "PIO APP GPIO 23"), + PINCTRL_PIN(184, "PIO APP GPIO 22"), + PINCTRL_PIN(185, "PIO APP GPIO 21"), + PINCTRL_PIN(186, "PIO APP GPIO 20"), + PINCTRL_PIN(187, "P PAD VDD 19"), + PINCTRL_PIN(188, "P PAD GND 19"), + PINCTRL_PIN(189, "P PAD VSSIO 23"), + PINCTRL_PIN(190, "P PAD VDDIO 23"), + PINCTRL_PIN(191, "PIO APP GPIO 19"), + PINCTRL_PIN(192, "PIO APP GPIO 18"), + PINCTRL_PIN(193, "PIO APP GPIO 17"), + PINCTRL_PIN(194, "PIO APP GPIO 16"), + PINCTRL_PIN(195, "PI CI D1"), + PINCTRL_PIN(196, "PI CI D0"), + PINCTRL_PIN(197, "PI CI HSYNC"), + PINCTRL_PIN(198, "PI CI VSYNC"), + PINCTRL_PIN(199, "PI CI EXT CLK"), + PINCTRL_PIN(200, "PO CI EXT RST N"), + PINCTRL_PIN(201, "P PAD VSSIO 43"), + PINCTRL_PIN(202, "P PAD VDDIO 43"), + PINCTRL_PIN(203, "PI CI D6"), + PINCTRL_PIN(204, "PI CI D7"), + PINCTRL_PIN(205, "PI CI D2"), + PINCTRL_PIN(206, "PI CI D3"), + PINCTRL_PIN(207, "PI CI D4"), + PINCTRL_PIN(208, "PI CI D5"), + PINCTRL_PIN(209, "PI CI D8"), + PINCTRL_PIN(210, "PI CI D9"), + PINCTRL_PIN(211, "P PAD VDD 20"), + PINCTRL_PIN(212, "P PAD GND 20"), + PINCTRL_PIN(213, "P PAD VSSIO 24"), + PINCTRL_PIN(214, "P PAD VDDIO 24"), + PINCTRL_PIN(215, "P PAD VDDIO 26"), + PINCTRL_PIN(216, "PO EMIF 1 A26"), + PINCTRL_PIN(217, "PO EMIF 1 A25"), + PINCTRL_PIN(218, "P PAD VSSIO 26"), + PINCTRL_PIN(219, "PO EMIF 1 A24"), + PINCTRL_PIN(220, "PO EMIF 1 A23"), + /* Pads along the bottom edge of the chip */ + PINCTRL_PIN(221, "PO EMIF 1 A22"), + PINCTRL_PIN(222, "PO EMIF 1 A21"), + PINCTRL_PIN(223, "P PAD VDD 21"), + PINCTRL_PIN(224, "P PAD GND 21"), + PINCTRL_PIN(225, "P PAD VSSIO 27"), + PINCTRL_PIN(226, "P PAD VDDIO 27"), + PINCTRL_PIN(227, "PO EMIF 1 A20"), + PINCTRL_PIN(228, "PO EMIF 1 A19"), + PINCTRL_PIN(229, "PO EMIF 1 A18"), + PINCTRL_PIN(230, "PO EMIF 1 A17"), + PINCTRL_PIN(231, "P PAD VDDIO 28"), + PINCTRL_PIN(232, "P PAD VSSIO 28"), + PINCTRL_PIN(233, "PO EMIF 1 A16"), + PINCTRL_PIN(234, "PIO EMIF 1 D15"), + PINCTRL_PIN(235, "PO EMIF 1 A15"), + PINCTRL_PIN(236, "PIO EMIF 1 D14"), + PINCTRL_PIN(237, "P PAD VDD 22"), + PINCTRL_PIN(238, "P PAD GND 22"), + PINCTRL_PIN(239, "P PAD VSSIO 29"), + PINCTRL_PIN(240, "P PAD VDDIO 29"), + PINCTRL_PIN(241, "PO EMIF 1 A14"), + PINCTRL_PIN(242, "PIO EMIF 1 D13"), + PINCTRL_PIN(243, "PO EMIF 1 A13"), + PINCTRL_PIN(244, "PIO EMIF 1 D12"), + PINCTRL_PIN(245, "P PAD VSSIO 30"), + PINCTRL_PIN(246, "P PAD VDDIO 30"), + PINCTRL_PIN(247, "PO EMIF 1 A12"), + PINCTRL_PIN(248, "PIO EMIF 1 D11"), + PINCTRL_PIN(249, "PO EMIF 1 A11"), + PINCTRL_PIN(250, "PIO EMIF 1 D10"), + PINCTRL_PIN(251, "P PAD VSSIO 31"), + PINCTRL_PIN(252, "P PAD VDDIO 31"), + PINCTRL_PIN(253, "PO EMIF 1 A10"), + PINCTRL_PIN(254, "PIO EMIF 1 D09"), + PINCTRL_PIN(255, "PO EMIF 1 A09"), + PINCTRL_PIN(256, "P PAD VDDIO 32"), + PINCTRL_PIN(257, "P PAD VSSIO 32"), + PINCTRL_PIN(258, "P PAD GND 24"), + PINCTRL_PIN(259, "P PAD VDD 24"), + PINCTRL_PIN(260, "PIO EMIF 1 D08"), + PINCTRL_PIN(261, "PO EMIF 1 A08"), + PINCTRL_PIN(262, "PIO EMIF 1 D07"), + PINCTRL_PIN(263, "PO EMIF 1 A07"), + PINCTRL_PIN(264, "P PAD VDDIO 33"), + PINCTRL_PIN(265, "P PAD VSSIO 33"), + PINCTRL_PIN(266, "PIO EMIF 1 D06"), + PINCTRL_PIN(267, "PO EMIF 1 A06"), + PINCTRL_PIN(268, "PIO EMIF 1 D05"), + PINCTRL_PIN(269, "PO EMIF 1 A05"), + PINCTRL_PIN(270, "P PAD VDDIO 34"), + PINCTRL_PIN(271, "P PAD VSSIO 34"), + PINCTRL_PIN(272, "PIO EMIF 1 D04"), + PINCTRL_PIN(273, "PO EMIF 1 A04"), + PINCTRL_PIN(274, "PIO EMIF 1 D03"), + PINCTRL_PIN(275, "PO EMIF 1 A03"), + PINCTRL_PIN(276, "P PAD VDDIO 35"), + PINCTRL_PIN(277, "P PAD VSSIO 35"), + PINCTRL_PIN(278, "P PAD GND 23"), + PINCTRL_PIN(279, "P PAD VDD 23"), + PINCTRL_PIN(280, "PIO EMIF 1 D02"), + PINCTRL_PIN(281, "PO EMIF 1 A02"), + PINCTRL_PIN(282, "PIO EMIF 1 D01"), + PINCTRL_PIN(283, "PO EMIF 1 A01"), + PINCTRL_PIN(284, "P PAD VDDIO 36"), + PINCTRL_PIN(285, "P PAD VSSIO 36"), + PINCTRL_PIN(286, "PIO EMIF 1 D00"), + PINCTRL_PIN(287, "PO EMIF 1 BE1 N"), + PINCTRL_PIN(288, "PO EMIF 1 BE0 N"), + PINCTRL_PIN(289, "PO EMIF 1 ADV N"), + PINCTRL_PIN(290, "P PAD VDDIO 37"), + PINCTRL_PIN(291, "P PAD VSSIO 37"), + PINCTRL_PIN(292, "PO EMIF 1 SD CKE0"), + PINCTRL_PIN(293, "PO EMIF 1 OE N"), + PINCTRL_PIN(294, "PO EMIF 1 WE N"), + PINCTRL_PIN(295, "P PAD VDDIO 38"), + PINCTRL_PIN(296, "P PAD VSSIO 38"), + PINCTRL_PIN(297, "PO EMIF 1 CLK"), + PINCTRL_PIN(298, "PIO EMIF 1 SD CLK"), + PINCTRL_PIN(299, "P PAD VSSIO 45 (not bonded)"), + PINCTRL_PIN(300, "P PAD VDDIO 42"), + PINCTRL_PIN(301, "P PAD VSSIO 42"), + PINCTRL_PIN(302, "P PAD GND 31"), + PINCTRL_PIN(303, "P PAD VDD 31"), + PINCTRL_PIN(304, "PI EMIF 1 RET CLK"), + PINCTRL_PIN(305, "PI EMIF 1 WAIT N"), + PINCTRL_PIN(306, "PI EMIF 1 NFIF READY"), + PINCTRL_PIN(307, "PO EMIF 1 SD CKE1"), + PINCTRL_PIN(308, "PO EMIF 1 CS3 N"), + PINCTRL_PIN(309, "P PAD VDD 25"), + PINCTRL_PIN(310, "P PAD GND 25"), + PINCTRL_PIN(311, "P PAD VSSIO 39"), + PINCTRL_PIN(312, "P PAD VDDIO 39"), + PINCTRL_PIN(313, "PO EMIF 1 CS2 N"), + PINCTRL_PIN(314, "PO EMIF 1 CS1 N"), + PINCTRL_PIN(315, "PO EMIF 1 CS0 N"), + PINCTRL_PIN(316, "PO ETM TRACE PKT0"), + PINCTRL_PIN(317, "PO ETM TRACE PKT1"), + PINCTRL_PIN(318, "PO ETM TRACE PKT2"), + PINCTRL_PIN(319, "P PAD VDD 30"), + PINCTRL_PIN(320, "P PAD GND 30"), + PINCTRL_PIN(321, "P PAD VSSIO 44"), + PINCTRL_PIN(322, "P PAD VDDIO 44"), + PINCTRL_PIN(323, "PO ETM TRACE PKT3"), + PINCTRL_PIN(324, "PO ETM TRACE PKT4"), + PINCTRL_PIN(325, "PO ETM TRACE PKT5"), + PINCTRL_PIN(326, "PO ETM TRACE PKT6"), + PINCTRL_PIN(327, "PO ETM TRACE PKT7"), + PINCTRL_PIN(328, "PO ETM PIPE STAT0"), + PINCTRL_PIN(329, "P PAD VDD 26"), + PINCTRL_PIN(330, "P PAD GND 26"), + PINCTRL_PIN(331, "P PAD VSSIO 40"), + PINCTRL_PIN(332, "P PAD VDDIO 40"), + PINCTRL_PIN(333, "PO ETM PIPE STAT1"), + PINCTRL_PIN(334, "PO ETM PIPE STAT2"), + PINCTRL_PIN(335, "PO ETM TRACE CLK"), + PINCTRL_PIN(336, "PO ETM TRACE SYNC"), + PINCTRL_PIN(337, "PIO ACC GPIO 33"), + PINCTRL_PIN(338, "PIO ACC GPIO 32"), + PINCTRL_PIN(339, "PIO ACC GPIO 30"), + PINCTRL_PIN(340, "PIO ACC GPIO 29"), + PINCTRL_PIN(341, "P PAD VDDIO 17"), + PINCTRL_PIN(342, "P PAD VSSIO 17"), + PINCTRL_PIN(343, "P PAD GND 15"), + PINCTRL_PIN(344, "P PAD VDD 15"), + PINCTRL_PIN(345, "PIO ACC GPIO 28"), + PINCTRL_PIN(346, "PIO ACC GPIO 27"), + PINCTRL_PIN(347, "PIO ACC GPIO 16"), + PINCTRL_PIN(348, "PI TAP TMS"), + PINCTRL_PIN(349, "PI TAP TDI"), + PINCTRL_PIN(350, "PO TAP TDO"), + PINCTRL_PIN(351, "PI TAP RST N"), + /* Pads along the left edge of the chip */ + PINCTRL_PIN(352, "PI EMU MODE 0"), + PINCTRL_PIN(353, "PO TAP RET CLK"), + PINCTRL_PIN(354, "PI TAP CLK"), + PINCTRL_PIN(355, "PO EMIF 0 SD CS N"), + PINCTRL_PIN(356, "PO EMIF 0 SD CAS N"), + PINCTRL_PIN(357, "PO EMIF 0 SD WE N"), + PINCTRL_PIN(358, "P PAD VDDIO 1"), + PINCTRL_PIN(359, "P PAD VSSIO 1"), + PINCTRL_PIN(360, "P PAD GND 1"), + PINCTRL_PIN(361, "P PAD VDD 1"), + PINCTRL_PIN(362, "PO EMIF 0 SD CKE"), + PINCTRL_PIN(363, "PO EMIF 0 SD DQML"), + PINCTRL_PIN(364, "PO EMIF 0 SD DQMU"), + PINCTRL_PIN(365, "PO EMIF 0 SD RAS N"), + PINCTRL_PIN(366, "PIO EMIF 0 D15"), + PINCTRL_PIN(367, "PO EMIF 0 A15"), + PINCTRL_PIN(368, "PIO EMIF 0 D14"), + PINCTRL_PIN(369, "PO EMIF 0 A14"), + PINCTRL_PIN(370, "PIO EMIF 0 D13"), + PINCTRL_PIN(371, "PO EMIF 0 A13"), + PINCTRL_PIN(372, "P PAD VDDIO 2"), + PINCTRL_PIN(373, "P PAD VSSIO 2"), + PINCTRL_PIN(374, "P PAD GND 2"), + PINCTRL_PIN(375, "P PAD VDD 2"), + PINCTRL_PIN(376, "PIO EMIF 0 D12"), + PINCTRL_PIN(377, "PO EMIF 0 A12"), + PINCTRL_PIN(378, "PIO EMIF 0 D11"), + PINCTRL_PIN(379, "PO EMIF 0 A11"), + PINCTRL_PIN(380, "PIO EMIF 0 D10"), + PINCTRL_PIN(381, "PO EMIF 0 A10"), + PINCTRL_PIN(382, "PIO EMIF 0 D09"), + PINCTRL_PIN(383, "PO EMIF 0 A09"), + PINCTRL_PIN(384, "PIO EMIF 0 D08"), + PINCTRL_PIN(385, "PO EMIF 0 A08"), + PINCTRL_PIN(386, "PIO EMIF 0 D07"), + PINCTRL_PIN(387, "PO EMIF 0 A07"), + PINCTRL_PIN(388, "P PAD VDDIO 3"), + PINCTRL_PIN(389, "P PAD VSSIO 3"), + PINCTRL_PIN(390, "P PAD GND 3"), + PINCTRL_PIN(391, "P PAD VDD 3"), + PINCTRL_PIN(392, "PO EFUSE RDOUT1"), + PINCTRL_PIN(393, "PIO EMIF 0 D06"), + PINCTRL_PIN(394, "PO EMIF 0 A06"), + PINCTRL_PIN(395, "PIO EMIF 0 D05"), + PINCTRL_PIN(396, "PO EMIF 0 A05"), + PINCTRL_PIN(397, "PIO EMIF 0 D04"), + PINCTRL_PIN(398, "PO EMIF 0 A04"), + PINCTRL_PIN(399, "A PADS/A VDDCO1v82v5 GND 80U SF LIN VDDCO AF"), + PINCTRL_PIN(400, "PWR VDDCO AF"), + PINCTRL_PIN(401, "PWR EFUSE HV1"), + PINCTRL_PIN(402, "P PAD VSSIO 4"), + PINCTRL_PIN(403, "P PAD VDDIO 4"), + PINCTRL_PIN(404, "P PAD GND 4"), + PINCTRL_PIN(405, "P PAD VDD 4"), + PINCTRL_PIN(406, "PIO EMIF 0 D03"), + PINCTRL_PIN(407, "PO EMIF 0 A03"), + PINCTRL_PIN(408, "PWR EFUSE HV2"), + PINCTRL_PIN(409, "PWR EFUSE HV3"), + PINCTRL_PIN(410, "PIO EMIF 0 D02"), + PINCTRL_PIN(411, "PO EMIF 0 A02"), + PINCTRL_PIN(412, "PIO EMIF 0 D01"), + PINCTRL_PIN(413, "P PAD VDDIO 5"), + PINCTRL_PIN(414, "P PAD VSSIO 5"), + PINCTRL_PIN(415, "P PAD GND 5"), + PINCTRL_PIN(416, "P PAD VDD 5"), + PINCTRL_PIN(417, "PO EMIF 0 A01"), + PINCTRL_PIN(418, "PIO EMIF 0 D00"), + PINCTRL_PIN(419, "IF 0 SD CLK"), + PINCTRL_PIN(420, "APP SPI CLK"), + PINCTRL_PIN(421, "APP SPI DO"), + PINCTRL_PIN(422, "APP SPI DI"), + PINCTRL_PIN(423, "APP SPI CS0"), + PINCTRL_PIN(424, "APP SPI CS1"), + PINCTRL_PIN(425, "APP SPI CS2"), + PINCTRL_PIN(426, "PIO APP GPIO 10"), + PINCTRL_PIN(427, "P PAD VDDIO 41"), + PINCTRL_PIN(428, "P PAD VSSIO 41"), + PINCTRL_PIN(429, "P PAD GND 6"), + PINCTRL_PIN(430, "P PAD VDD 6"), + PINCTRL_PIN(431, "PIO ACC SDIO0 CMD"), + PINCTRL_PIN(432, "PIO ACC SDIO0 CK"), + PINCTRL_PIN(433, "PIO ACC SDIO0 D3"), + PINCTRL_PIN(434, "PIO ACC SDIO0 D2"), + PINCTRL_PIN(435, "PIO ACC SDIO0 D1"), + PINCTRL_PIN(436, "PIO ACC SDIO0 D0"), + PINCTRL_PIN(437, "PIO USB PU"), + PINCTRL_PIN(438, "PIO USB SP"), + PINCTRL_PIN(439, "PIO USB DAT VP"), + PINCTRL_PIN(440, "PIO USB SE0 VM"), + PINCTRL_PIN(441, "PIO USB OE"), + PINCTRL_PIN(442, "PIO USB SUSP"), + PINCTRL_PIN(443, "P PAD VSSIO 6"), + PINCTRL_PIN(444, "P PAD VDDIO 6"), + PINCTRL_PIN(445, "PIO USB PUEN"), + PINCTRL_PIN(446, "PIO ACC UART0 RX"), + PINCTRL_PIN(447, "PIO ACC UART0 TX"), + PINCTRL_PIN(448, "PIO ACC UART0 CTS"), + PINCTRL_PIN(449, "PIO ACC UART0 RTS"), + PINCTRL_PIN(450, "PIO ACC UART3 RX"), + PINCTRL_PIN(451, "PIO ACC UART3 TX"), + PINCTRL_PIN(452, "PIO ACC UART3 CTS"), + PINCTRL_PIN(453, "PIO ACC UART3 RTS"), + PINCTRL_PIN(454, "PIO ACC IRDA TX"), + PINCTRL_PIN(455, "P PAD VDDIO 7"), + PINCTRL_PIN(456, "P PAD VSSIO 7"), + PINCTRL_PIN(457, "P PAD GND 7"), + PINCTRL_PIN(458, "P PAD VDD 7"), + PINCTRL_PIN(459, "PIO ACC IRDA RX"), + PINCTRL_PIN(460, "PIO ACC PCM I2S CLK"), + PINCTRL_PIN(461, "PIO ACC PCM I2S WS"), + PINCTRL_PIN(462, "PIO ACC PCM I2S DATA A"), + PINCTRL_PIN(463, "PIO ACC PCM I2S DATA B"), + PINCTRL_PIN(464, "PO SIM CLK"), + PINCTRL_PIN(465, "PIO ACC IRDA SD"), + PINCTRL_PIN(466, "PIO SIM DATA"), +}; + +/** + * @dev: a pointer back to containing device + * @virtbase: the offset to the controller in virtual memory + */ +struct u300_pmx { + struct device *dev; + struct pinctrl_dev *pctl; + u32 phybase; + u32 physize; + void __iomem *virtbase; +}; + +/** + * u300_pmx_registers - the array of registers read/written for each pinmux + * shunt setting + */ +const u32 u300_pmx_registers[] = { + U300_SYSCON_PMC1LR, + U300_SYSCON_PMC1HR, + U300_SYSCON_PMC2R, + U300_SYSCON_PMC3R, + U300_SYSCON_PMC4R, +}; + +/** + * struct u300_pin_group - describes a U300 pin group + * @name: the name of this specific pin group + * @pins: an array of discrete physical pins used in this group, taken + * from the driver-local pin enumeration space + * @num_pins: the number of pins in this group array, i.e. the number of + * elements in .pins so we can iterate over that array + */ +struct u300_pin_group { + const char *name; + const unsigned int *pins; + const unsigned num_pins; +}; + +/** + * struct pmx_onmask - mask bits to enable/disable padmux + * @mask: mask bits to disable + * @val: mask bits to enable + * + * onmask lazy dog: + * onmask = { + * {"PMC1LR" mask, "PMC1LR" value}, + * {"PMC1HR" mask, "PMC1HR" value}, + * {"PMC2R" mask, "PMC2R" value}, + * {"PMC3R" mask, "PMC3R" value}, + * {"PMC4R" mask, "PMC4R" value} + * } + */ +struct u300_pmx_mask { + u16 mask; + u16 bits; +}; + +/* The chip power pins are VDD, GND, VDDIO and VSSIO */ +static const unsigned power_pins[] = { 0, 1, 3, 31, 46, 47, 49, 50, 61, 62, 63, + 64, 78, 79, 80, 81, 92, 93, 94, 95, 101, 102, 103, 104, 115, 116, 117, + 118, 130, 131, 132, 133, 145, 146, 147, 148, 159, 160, 172, 173, 174, + 175, 187, 188, 189, 190, 201, 202, 211, 212, 213, 214, 215, 218, 223, + 224, 225, 226, 231, 232, 237, 238, 239, 240, 245, 246, 251, 252, 256, + 257, 258, 259, 264, 265, 270, 271, 276, 277, 278, 279, 284, 285, 290, + 291, 295, 296, 299, 300, 301, 302, 303, 309, 310, 311, 312, 319, 320, + 321, 322, 329, 330, 331, 332, 341, 342, 343, 344, 358, 359, 360, 361, + 372, 373, 374, 375, 388, 389, 390, 391, 402, 403, 404, 405, 413, 414, + 415, 416, 427, 428, 429, 430, 443, 444, 455, 456, 457, 458 }; +static const unsigned emif0_pins[] = { 355, 356, 357, 362, 363, 364, 365, 366, + 367, 368, 369, 370, 371, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 387, 393, 394, 395, 396, 397, 398, 406, 407, 410, 411, 412, + 417, 418 }; +static const unsigned emif1_pins[] = { 216, 217, 219, 220, 221, 222, 227, 228, + 229, 230, 233, 234, 235, 236, 241, 242, 243, 244, 247, 248, 249, 250, + 253, 254, 255, 260, 261, 262, 263, 266, 267, 268, 269, 272, 273, 274, + 275, 280, 281, 282, 283, 286, 287, 288, 289, 292, 293, 294, 297, 298, + 304, 305, 306, 307, 308, 313, 314, 315 }; +static const unsigned uart0_pins[] = { 134, 135, 136, 137 }; +static const unsigned mmc0_pins[] = { 166, 167, 168, 169, 170, 171, 176, 177 }; +static const unsigned spi0_pins[] = { 420, 421, 422, 423, 424, 425 }; + +static const struct u300_pmx_mask emif0_mask[] = { + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, +}; + +static const struct u300_pmx_mask emif1_mask[] = { + /* + * This connects the SDRAM to CS2 and a NAND flash to + * CS0 on the EMIF. + */ + { + U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK | + U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK | + U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK | + U300_SYSCON_PMC1LR_EMIF_1_MASK, + U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM | + U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC | + U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF | + U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 + }, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, +}; + +static const struct u300_pmx_mask uart0_mask[] = { + {0, 0}, + { + U300_SYSCON_PMC1HR_APP_UART0_1_MASK | + U300_SYSCON_PMC1HR_APP_UART0_2_MASK, + U300_SYSCON_PMC1HR_APP_UART0_1_UART0 | + U300_SYSCON_PMC1HR_APP_UART0_2_UART0 + }, + {0, 0}, + {0, 0}, + {0, 0}, +}; + +static const struct u300_pmx_mask mmc0_mask[] = { + { U300_SYSCON_PMC1LR_MMCSD_MASK, U300_SYSCON_PMC1LR_MMCSD_MMCSD}, + {0, 0}, + {0, 0}, + {0, 0}, + { U300_SYSCON_PMC4R_APP_MISC_12_MASK, + U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO } +}; + +static const struct u300_pmx_mask spi0_mask[] = { + {0, 0}, + { + U300_SYSCON_PMC1HR_APP_SPI_2_MASK | + U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK | + U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK, + U300_SYSCON_PMC1HR_APP_SPI_2_SPI | + U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI | + U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI + }, + {0, 0}, + {0, 0}, + {0, 0} +}; + +static const struct u300_pin_group u300_pin_groups[] = { + { + .name = "powergrp", + .pins = power_pins, + .num_pins = ARRAY_SIZE(power_pins), + }, + { + .name = "emif0grp", + .pins = emif0_pins, + .num_pins = ARRAY_SIZE(emif0_pins), + }, + { + .name = "emif1grp", + .pins = emif1_pins, + .num_pins = ARRAY_SIZE(emif1_pins), + }, + { + .name = "uart0grp", + .pins = uart0_pins, + .num_pins = ARRAY_SIZE(uart0_pins), + }, + { + .name = "mmc0grp", + .pins = mmc0_pins, + .num_pins = ARRAY_SIZE(mmc0_pins), + }, + { + .name = "spi0grp", + .pins = spi0_pins, + .num_pins = ARRAY_SIZE(spi0_pins), + }, +}; + +static int u300_list_groups(struct pinctrl_dev *pctldev, unsigned selector) +{ + if (selector >= ARRAY_SIZE(u300_pin_groups)) + return -EINVAL; + return 0; +} + +static const char *u300_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + if (selector >= ARRAY_SIZE(u300_pin_groups)) + return NULL; + return u300_pin_groups[selector].name; +} + +static int u300_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, + unsigned ** const pins, + unsigned * const num_pins) +{ + if (selector >= ARRAY_SIZE(u300_pin_groups)) + return -EINVAL; + *pins = (unsigned *) u300_pin_groups[selector].pins; + *num_pins = u300_pin_groups[selector].num_pins; + return 0; +} + +static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, + unsigned offset) +{ + seq_printf(s, " " DRIVER_NAME); +} + +static struct pinctrl_ops u300_pctrl_ops = { + .list_groups = u300_list_groups, + .get_group_name = u300_get_group_name, + .get_group_pins = u300_get_group_pins, + .pin_dbg_show = u300_pin_dbg_show, +}; + +/* + * Here we define the available functions and their corresponding pin groups + */ + +/** + * struct u300_pmx_func - describes U300 pinmux functions + * @name: the name of this specific function + * @groups: corresponding pin groups + * @onmask: bits to set to enable this when doing pin muxing + */ +struct u300_pmx_func { + const char *name; + const char * const *groups; + const unsigned num_groups; + const struct u300_pmx_mask *mask; +}; + +static const char * const powergrps[] = { "powergrp" }; +static const char * const emif0grps[] = { "emif0grp" }; +static const char * const emif1grps[] = { "emif1grp" }; +static const char * const uart0grps[] = { "uart0grp" }; +static const char * const mmc0grps[] = { "mmc0grp" }; +static const char * const spi0grps[] = { "spi0grp" }; + +static const struct u300_pmx_func u300_pmx_functions[] = { + { + .name = "power", + .groups = powergrps, + .num_groups = ARRAY_SIZE(powergrps), + /* Mask is N/A */ + }, + { + .name = "emif0", + .groups = emif0grps, + .num_groups = ARRAY_SIZE(emif0grps), + .mask = emif0_mask, + }, + { + .name = "emif1", + .groups = emif1grps, + .num_groups = ARRAY_SIZE(emif1grps), + .mask = emif1_mask, + }, + { + .name = "uart0", + .groups = uart0grps, + .num_groups = ARRAY_SIZE(uart0grps), + .mask = uart0_mask, + }, + { + .name = "mmc0", + .groups = mmc0grps, + .num_groups = ARRAY_SIZE(mmc0grps), + .mask = mmc0_mask, + }, + { + .name = "spi0", + .groups = spi0grps, + .num_groups = ARRAY_SIZE(spi0grps), + .mask = spi0_mask, + }, +}; + +static void u300_pmx_endisable(struct u300_pmx *upmx, unsigned selector, + bool enable) +{ + u16 regval, val, mask; + int i; + + for (i = 0; i < ARRAY_SIZE(u300_pmx_registers); i++) { + if (enable) + val = u300_pmx_functions[selector].mask->bits; + else + val = 0; + + mask = u300_pmx_functions[selector].mask->mask; + if (mask != 0) { + regval = readw(upmx->virtbase + u300_pmx_registers[i]); + regval &= ~mask; + regval |= val; + writew(regval, upmx->virtbase + u300_pmx_registers[i]); + } + } +} + +static int u300_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + struct u300_pmx *upmx; + + /* There is nothing to do with the power pins */ + if (selector == 0) + return 0; + + upmx = pinctrl_dev_get_drvdata(pctldev); + u300_pmx_endisable(upmx, selector, true); + + return 0; +} + +static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector, + unsigned group) +{ + struct u300_pmx *upmx; + + /* There is nothing to do with the power pins */ + if (selector == 0) + return; + + upmx = pinctrl_dev_get_drvdata(pctldev); + u300_pmx_endisable(upmx, selector, false); +} + +static int u300_pmx_list_funcs(struct pinctrl_dev *pctldev, unsigned selector) +{ + if (selector >= ARRAY_SIZE(u300_pmx_functions)) + return -EINVAL; + return 0; +} + +static const char *u300_pmx_get_func_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + return u300_pmx_functions[selector].name; +} + +static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector, + const char * const **groups, + unsigned * const num_groups) +{ + *groups = u300_pmx_functions[selector].groups; + *num_groups = u300_pmx_functions[selector].num_groups; + return 0; +} + +static struct pinmux_ops u300_pmx_ops = { + .list_functions = u300_pmx_list_funcs, + .get_function_name = u300_pmx_get_func_name, + .get_function_groups = u300_pmx_get_groups, + .enable = u300_pmx_enable, + .disable = u300_pmx_disable, +}; + +/* + * FIXME: this will be set to sane values as this driver engulfs + * drivers/gpio/gpio-u300.c and we really know this stuff. + */ +static struct pinctrl_gpio_range u300_gpio_range = { + .name = "COH901*", + .id = 0, + .base = 0, + .npins = 64, +}; + +static struct pinctrl_desc u300_pmx_desc = { + .name = DRIVER_NAME, + .pins = u300_pads, + .npins = ARRAY_SIZE(u300_pads), + .maxpin = U300_NUM_PADS-1, + .pctlops = &u300_pctrl_ops, + .pmxops = &u300_pmx_ops, + .owner = THIS_MODULE, +}; + +static int __init u300_pmx_probe(struct platform_device *pdev) +{ + int ret; + struct u300_pmx *upmx; + struct resource *res; + + /* Create state holders etc for this driver */ + upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL); + if (!upmx) + return -ENOMEM; + + upmx->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + ret = -ENOENT; + goto out_no_resource; + } + upmx->phybase = res->start; + upmx->physize = resource_size(res); + + if (request_mem_region(upmx->phybase, upmx->physize, + DRIVER_NAME) == NULL) { + ret = -ENOMEM; + goto out_no_memregion; + } + + upmx->virtbase = ioremap(upmx->phybase, upmx->physize); + if (!upmx->virtbase) { + ret = -ENOMEM; + goto out_no_remap; + } + + upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx); + if (!upmx->pctl) { + dev_err(&pdev->dev, "could not register U300 pinmux driver\n"); + ret = -EINVAL; + goto out_no_pmx; + } + + /* We will handle a range of GPIO pins */ + pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_range); + + platform_set_drvdata(pdev, upmx); + + dev_info(&pdev->dev, "initialized U300 pinmux driver\n"); + + return 0; + +out_no_pmx: + iounmap(upmx->virtbase); +out_no_remap: + platform_set_drvdata(pdev, NULL); +out_no_memregion: + release_mem_region(upmx->phybase, upmx->physize); +out_no_resource: + devm_kfree(&pdev->dev, upmx); + return ret; +} + +static int __exit u300_pmx_remove(struct platform_device *pdev) +{ + struct u300_pmx *upmx = platform_get_drvdata(pdev); + + pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_range); + pinctrl_unregister(upmx->pctl); + iounmap(upmx->virtbase); + release_mem_region(upmx->phybase, upmx->physize); + platform_set_drvdata(pdev, NULL); + devm_kfree(&pdev->dev, upmx); + + return 0; +} + +static struct platform_driver u300_pmx_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .remove = __exit_p(u300_pmx_remove), +}; + +static int __init u300_pmx_init(void) +{ + return platform_driver_probe(&u300_pmx_driver, u300_pmx_probe); +} +arch_initcall(u300_pmx_init); + +static void __exit u300_pmx_exit(void) +{ + platform_driver_unregister(&u300_pmx_driver); +} +module_exit(u300_pmx_exit); + +MODULE_AUTHOR("Linus Walleij "); +MODULE_DESCRIPTION("U300 pin control driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3