From b8410a150fbc4e61a28032637dc0ae7e8609131d Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 9 Aug 2010 19:18:17 +0530 Subject: [PATCH 01/35] ux500: mop500: add TC35892 and MicroSD slot support Acked-by: Linus Walleij Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-sdi.c | 63 +++++++++++++++++++ arch/arm/mach-ux500/board-mop500.c | 34 ++++++++++ arch/arm/mach-ux500/board-mop500.h | 8 +++ .../include/mach/irqs-board-mop500.h | 14 ++++- 4 files changed, 118 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index bac995665b58..f0095ffee438 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -20,6 +20,19 @@ #include "board-mop500.h" static pin_cfg_t mop500_sdi_pins[] = { + /* SDI0 (MicroSD slot) */ + GPIO18_MC0_CMDDIR, + GPIO19_MC0_DAT0DIR, + GPIO20_MC0_DAT2DIR, + GPIO21_MC0_DAT31DIR, + GPIO22_MC0_FBCLK, + GPIO23_MC0_CLK, + GPIO24_MC0_CMD, + GPIO25_MC0_DAT0, + GPIO26_MC0_DAT1, + GPIO27_MC0_DAT2, + GPIO28_MC0_DAT3, + /* SDI4 (on-board eMMC) */ GPIO197_MC4_DAT3, GPIO198_MC4_DAT2, @@ -49,6 +62,55 @@ static pin_cfg_t mop500_sdi2_pins[] = { GPIO138_MC2_DAT7, }; +/* + * SDI 0 (MicroSD slot) + */ + +/* MMCIPOWER bits */ +#define MCI_DATA2DIREN (1 << 2) +#define MCI_CMDDIREN (1 << 3) +#define MCI_DATA0DIREN (1 << 4) +#define MCI_DATA31DIREN (1 << 5) +#define MCI_FBCLKEN (1 << 7) + +static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd, + unsigned char power_mode) +{ + if (power_mode == MMC_POWER_UP) + gpio_set_value(GPIO_SDMMC_EN, 1); + else if (power_mode == MMC_POWER_OFF) + gpio_set_value(GPIO_SDMMC_EN, 0); + + return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN | + MCI_DATA2DIREN | MCI_DATA31DIREN; +} + +static struct mmci_platform_data mop500_sdi0_data = { + .vdd_handler = mop500_sdi0_vdd_handler, + .ocr_mask = MMC_VDD_29_30, + .f_max = 100000000, + .capabilities = MMC_CAP_4_BIT_DATA, + .gpio_cd = GPIO_SDMMC_CD, + .gpio_wp = -1, +}; + +void mop500_sdi_tc35892_init(void) +{ + int ret; + + ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN"); + if (!ret) + ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL, + "GPIO_SDMMC_1V8_3V_SEL"); + if (ret) + return; + + gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1); + gpio_direction_output(GPIO_SDMMC_EN, 0); + + amba_device_register(&u8500_sdi0_device, &iomem_resource); +} + /* * SDI 2 (POP eMMC, not on DB8500ed) */ @@ -78,6 +140,7 @@ void mop500_sdi_init(void) { nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins)); + u8500_sdi0_device.dev.platform_data = &mop500_sdi0_data; u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data; u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data; diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index cac83a694880..9aeefc403f35 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -13,11 +13,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -69,6 +71,8 @@ static pin_cfg_t mop500_pins[] = { GPIO166_KP_O2, GPIO167_KP_O1, GPIO168_KP_O0, + + GPIO217_GPIO, /* GPIO_EXP_INT */ }; static void ab4500_spi_cs_control(u32 command) @@ -132,6 +136,33 @@ static struct pl022_ssp_controller ssp0_platform_data = { .num_chipselect = 5, }; +/* + * TC35892 + */ + +static void mop500_tc35892_init(struct tc35892 *tc35892, unsigned int base) +{ + mop500_sdi_tc35892_init(); +} + +static struct tc35892_gpio_platform_data mop500_tc35892_gpio_data = { + .gpio_base = MOP500_EGPIO(0), + .setup = mop500_tc35892_init, +}; + +static struct tc35892_platform_data mop500_tc35892_data = { + .gpio = &mop500_tc35892_gpio_data, + .irq_base = MOP500_EGPIO_IRQ_BASE, +}; + +static struct i2c_board_info mop500_i2c0_devices[] = { + { + I2C_BOARD_INFO("tc35892", 0x42), + .irq = NOMADIK_GPIO_TO_IRQ(217), + .platform_data = &mop500_tc35892_data, + }, +}; + #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ static struct nmk_i2c_controller u8500_i2c##id##_data = { \ /* \ @@ -314,6 +345,9 @@ static void __init u8500_init_machine(void) ARRAY_SIZE(ab8500_spi_devices)); else /* If HW is v.1.1 or later use I2C to access AB8500 */ platform_device_register(&ab8500_device); + + i2c_register_board_info(0, mop500_i2c0_devices, + ARRAY_SIZE(mop500_i2c0_devices)); } MACHINE_START(U8500, "ST-Ericsson MOP500 platform") diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index 2d240322fa6f..3a338e6850a4 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -7,6 +7,14 @@ #ifndef __BOARD_MOP500_H #define __BOARD_MOP500_H +#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x)) + +/* GPIOs on the TC35892 expander */ +#define GPIO_SDMMC_CD MOP500_EGPIO(3) +#define GPIO_SDMMC_EN MOP500_EGPIO(17) +#define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18) + extern void mop500_sdi_init(void); +extern void mop500_sdi_tc35892_init(void); #endif diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h index cca4f705601e..7ee8aaae66a4 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h @@ -13,7 +13,19 @@ #define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START #define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ + AB8500_NR_IRQS) -#define MOP500_IRQ_END MOP500_AB8500_IRQ_END + +#define TC35892_NR_INTERNAL_IRQS 8 +#define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x)) +#define TC35892_NR_GPIOS 24 +#define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS) + +#define MOP500_EGPIO_NR_IRQS TC35892_NR_IRQS + +#define MOP500_EGPIO_IRQ_BASE MOP500_AB8500_IRQ_END +#define MOP500_EGPIO_IRQ_END (MOP500_EGPIO_IRQ_BASE \ + + MOP500_EGPIO_NR_IRQS) + +#define MOP500_IRQ_END MOP500_EGPIO_IRQ_END #if MOP500_IRQ_END > IRQ_BOARD_END #undef IRQ_BOARD_END From 1bde668c8afa279d81b8f26b2120b906f38f7822 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 9 Sep 2010 22:29:34 +0200 Subject: [PATCH 02/35] ux500: use _cansleep GPIO functions Similar to the patch to MMCI this silences similar messages from the platform code. Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-sdi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index f0095ffee438..2fbaa2013fdb 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -77,9 +77,9 @@ static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd, unsigned char power_mode) { if (power_mode == MMC_POWER_UP) - gpio_set_value(GPIO_SDMMC_EN, 1); + gpio_set_value_cansleep(GPIO_SDMMC_EN, 1); else if (power_mode == MMC_POWER_OFF) - gpio_set_value(GPIO_SDMMC_EN, 0); + gpio_set_value_cansleep(GPIO_SDMMC_EN, 0); return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN | MCI_DATA2DIREN | MCI_DATA31DIREN; From fbf1eadf950da1f5f5ed2e454d2f191f90fe1ebe Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 29 Sep 2010 19:46:32 +0530 Subject: [PATCH 03/35] ux500: rework device registration Change the Ux500 devices to be dynamically allocated and added by calling functions instead of referencing structures, thereby allowing 5500 and other derivatives' support to be added without having to duplicate structures, use fixup functions, or use compile-time macros. Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/board-mop500-sdi.c | 11 +- arch/arm/mach-ux500/board-mop500.c | 46 ++++---- arch/arm/mach-ux500/board-u5500.c | 16 ++- arch/arm/mach-ux500/cpu-db5500.c | 5 +- arch/arm/mach-ux500/cpu-db8500.c | 7 +- arch/arm/mach-ux500/cpu.c | 10 -- arch/arm/mach-ux500/devices-common.c | 107 +++++++++++++++++ arch/arm/mach-ux500/devices-common.h | 77 ++++++++++++ arch/arm/mach-ux500/devices-db5500.h | 66 +++++++++++ arch/arm/mach-ux500/devices-db8500.c | 131 --------------------- arch/arm/mach-ux500/devices-db8500.h | 98 +++++++++++++++ arch/arm/mach-ux500/devices.c | 63 ---------- arch/arm/mach-ux500/include/mach/devices.h | 17 --- arch/arm/mach-ux500/include/mach/setup.h | 2 +- 15 files changed, 395 insertions(+), 263 deletions(-) create mode 100644 arch/arm/mach-ux500/devices-common.c create mode 100644 arch/arm/mach-ux500/devices-common.h create mode 100644 arch/arm/mach-ux500/devices-db5500.h create mode 100644 arch/arm/mach-ux500/devices-db8500.h diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 9e27a84433cb..061201388dac 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel, U8500 machine. # -obj-y := clock.o cpu.o devices.o +obj-y := clock.o cpu.o devices.o devices-common.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 2fbaa2013fdb..be5e8ccb97cc 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -16,6 +16,7 @@ #include #include +#include "devices-db8500.h" #include "pins-db8500.h" #include "board-mop500.h" @@ -108,7 +109,7 @@ void mop500_sdi_tc35892_init(void) gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1); gpio_direction_output(GPIO_SDMMC_EN, 0); - amba_device_register(&u8500_sdi0_device, &iomem_resource); + db8500_add_sdi0(&mop500_sdi0_data); } /* @@ -140,15 +141,11 @@ void mop500_sdi_init(void) { nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins)); - u8500_sdi0_device.dev.platform_data = &mop500_sdi0_data; - u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data; - u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data; - if (!cpu_is_u8500ed()) { nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins)); - amba_device_register(&u8500_sdi2_device, &iomem_resource); + db8500_add_sdi2(&mop500_sdi2_data); } /* On-board eMMC */ - amba_device_register(&u8500_sdi4_device, &iomem_resource); + db8500_add_sdi4(&mop500_sdi4_data); } diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 9aeefc403f35..8edc27f41f0d 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -34,6 +34,7 @@ #include #include +#include "devices-db8500.h" #include "pins-db8500.h" #include "board-mop500.h" @@ -192,12 +193,13 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(2, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); U8500_I2C_CONTROLLER(3, 0xe, 1, 1, 100000, I2C_FREQ_MODE_STANDARD); -static struct amba_device *amba_devs[] __initdata = { - &ux500_uart0_device, - &ux500_uart1_device, - &ux500_uart2_device, - &u8500_ssp0_device, -}; +static void __init mop500_i2c_init(void) +{ + db8500_add_i2c0(&u8500_i2c0_data); + db8500_add_i2c1(&u8500_i2c1_data); + db8500_add_i2c2(&u8500_i2c2_data); + db8500_add_i2c3(&u8500_i2c3_data); +} static const unsigned int ux500_keymap[] = { KEY(2, 5, KEY_END), @@ -308,36 +310,34 @@ static struct ske_keypad_platform_data ske_keypad_board = { /* add any platform devices here - TODO */ static struct platform_device *platform_devs[] __initdata = { - &u8500_i2c0_device, - &ux500_i2c1_device, - &ux500_i2c2_device, - &ux500_i2c3_device, &ux500_ske_keypad_device, }; +static void __init mop500_spi_init(void) +{ + db8500_add_ssp0(&ssp0_platform_data); +} + +static void __init mop500_uart_init(void) +{ + db8500_add_uart0(); + db8500_add_uart1(); + db8500_add_uart2(); +} + static void __init u8500_init_machine(void) { - int i; - u8500_init_devices(); nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins)); - u8500_i2c0_device.dev.platform_data = &u8500_i2c0_data; - ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data; - ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data; - ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data; ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board; - - u8500_ssp0_device.dev.platform_data = &ssp0_platform_data; - - /* Register the active AMBA devices on this board */ - for (i = 0; i < ARRAY_SIZE(amba_devs); i++) - amba_device_register(amba_devs[i], &iomem_resource); - platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); + mop500_i2c_init(); mop500_sdi_init(); + mop500_spi_init(); + mop500_uart_init(); /* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */ if (cpu_is_u8500ed() || cpu_is_u8500v10()) diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 1ca094a45e71..9a5db956deba 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -17,17 +18,20 @@ #include #include -static struct amba_device *amba_board_devs[] __initdata = { - &ux500_uart0_device, - &ux500_uart1_device, - &ux500_uart2_device, -}; +#include "devices-db5500.h" + +static void __init u5500_uart_init(void) +{ + db5500_add_uart0(); + db5500_add_uart1(); + db5500_add_uart2(); +} static void __init u5500_init_machine(void) { u5500_init_devices(); - amba_add_devices(amba_board_devs, ARRAY_SIZE(amba_board_devs)); + u5500_uart_init(); } MACHINE_START(U8500, "ST-Ericsson U5500 Platform") diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 2f87075e9d6f..bcc0fd4fdc29 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -16,6 +17,8 @@ #include #include +#include "devices-db5500.h" + static struct map_desc u5500_io_desc[] __initdata = { __IO_DEV_DESC(U5500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U5500_GPIO1_BASE, SZ_4K), @@ -132,7 +135,7 @@ void __init u5500_map_io(void) void __init u5500_init_devices(void) { - ux500_init_devices(); + db5500_add_rtc(); platform_add_devices(u5500_platform_devs, ARRAY_SIZE(u5500_platform_devs)); diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 4acab7544b3c..5966f353890f 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -22,6 +22,8 @@ #include #include +#include "devices-db8500.h" + static struct platform_device *platform_devs[] __initdata = { &u8500_gpio_devs[0], &u8500_gpio_devs[1], @@ -152,12 +154,11 @@ void __init u8500_init_devices(void) else pr_warning("ASIC: UNKNOWN SILICON VERSION!\n"); - ux500_init_devices(); - if (cpu_is_u8500ed()) dma40_u8500ed_fixup(); - /* Register the platform devices */ + db8500_add_rtc(); + platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); return ; diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 608a1372b172..2bc0efbac584 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -6,7 +6,6 @@ */ #include -#include #include #include @@ -45,20 +44,11 @@ static struct map_desc ux500_io_desc[] __initdata = { __IO_DEV_DESC(UX500_BACKUPRAM0_BASE, SZ_8K), }; -static struct amba_device *ux500_amba_devs[] __initdata = { - &ux500_pl031_device, -}; - void __init ux500_map_io(void) { iotable_init(ux500_io_desc, ARRAY_SIZE(ux500_io_desc)); } -void __init ux500_init_devices(void) -{ - amba_add_devices(ux500_amba_devs, ARRAY_SIZE(ux500_amba_devs)); -} - void __init ux500_init_irq(void) { gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29); diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c new file mode 100644 index 000000000000..9376a246f862 --- /dev/null +++ b/arch/arm/mach-ux500/devices-common.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "devices-common.h" + +struct amba_device * +dbx500_add_amba_device(const char *name, resource_size_t base, + int irq, void *pdata, unsigned int periphid) +{ + struct amba_device *dev; + int ret; + + dev = kzalloc(sizeof *dev, GFP_KERNEL); + if (!dev) + return ERR_PTR(-ENOMEM); + + dev->dev.init_name = name; + + dev->res.start = base; + dev->res.end = base + SZ_4K - 1; + dev->res.flags = IORESOURCE_MEM; + + dev->dma_mask = DMA_BIT_MASK(32); + dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + + dev->irq[0] = irq; + dev->irq[1] = NO_IRQ; + + dev->periphid = periphid; + + dev->dev.platform_data = pdata; + + ret = amba_device_register(dev, &iomem_resource); + if (ret) { + kfree(dev); + return ERR_PTR(ret); + } + + return dev; +} + +static struct platform_device * +dbx500_add_platform_device(const char *name, int id, void *pdata, + struct resource *res, int resnum) +{ + struct platform_device *dev; + int ret; + + dev = platform_device_alloc(name, id); + if (!dev) + return ERR_PTR(-ENOMEM); + + dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + dev->dev.dma_mask = &dev->dev.coherent_dma_mask; + + ret = platform_device_add_resources(dev, res, resnum); + if (ret) + goto out_free; + + dev->dev.platform_data = pdata; + + ret = platform_device_add(dev); + if (ret) + goto out_free; + + return dev; + +out_free: + platform_device_put(dev); + return ERR_PTR(ret); +} + +struct platform_device * +dbx500_add_platform_device_4k1irq(const char *name, int id, + resource_size_t base, + int irq, void *pdata) +{ + struct resource resources[] = { + [0] = { + .start = base, + .end = base + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = irq, + .end = irq, + .flags = IORESOURCE_IRQ, + } + }; + + return dbx500_add_platform_device(name, id, pdata, resources, + ARRAY_SIZE(resources)); +} diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h new file mode 100644 index 000000000000..2e1de0e19717 --- /dev/null +++ b/arch/arm/mach-ux500/devices-common.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef __DEVICES_COMMON_H +#define __DEVICES_COMMON_H + +extern struct amba_device * +dbx500_add_amba_device(const char *name, resource_size_t base, + int irq, void *pdata, unsigned int periphid); + +extern struct platform_device * +dbx500_add_platform_device_4k1irq(const char *name, int id, + resource_size_t base, + int irq, void *pdata); + +struct spi_master_cntlr; + +static inline struct amba_device * +dbx500_add_msp_spi(const char *name, resource_size_t base, int irq, + struct spi_master_cntlr *pdata) +{ + return dbx500_add_amba_device(name, base, irq, pdata, 0); +} + +static inline struct amba_device * +dbx500_add_spi(const char *name, resource_size_t base, int irq, + struct spi_master_cntlr *pdata) +{ + return dbx500_add_amba_device(name, base, irq, pdata, 0); +} + +struct mmci_platform_data; + +static inline struct amba_device * +dbx500_add_sdi(const char *name, resource_size_t base, int irq, + struct mmci_platform_data *pdata) +{ + return dbx500_add_amba_device(name, base, irq, pdata, 0); +} + +static inline struct amba_device * +dbx500_add_uart(const char *name, resource_size_t base, int irq) +{ + return dbx500_add_amba_device(name, base, irq, NULL, 0); +} + +struct nmk_i2c_controller; + +static inline struct platform_device * +dbx500_add_i2c(int id, resource_size_t base, int irq, + struct nmk_i2c_controller *pdata) +{ + return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq, + pdata); +} + +struct msp_i2s_platform_data; + +static inline struct platform_device * +dbx500_add_msp_i2s(int id, resource_size_t base, int irq, + struct msp_i2s_platform_data *pdata) +{ + return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq, + pdata); +} + +static inline struct amba_device * +dbx500_add_rtc(resource_size_t base, int irq) +{ + return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0); +} + +#endif diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h new file mode 100644 index 000000000000..c8d7901c1f2d --- /dev/null +++ b/arch/arm/mach-ux500/devices-db5500.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef __DEVICES_DB5500_H +#define __DEVICES_DB5500_H + +#include "devices-common.h" + +#define db5500_add_i2c1(pdata) \ + dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata) +#define db5500_add_i2c2(pdata) \ + dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata) +#define db5500_add_i2c3(pdata) \ + dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata) + +#define db5500_add_msp0_i2s(pdata) \ + dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata) +#define db5500_add_msp1_i2s(pdata) \ + dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata) +#define db5500_add_msp2_i2s(pdata) \ + dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata) + +#define db5500_add_msp0_spi(pdata) \ + dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata) +#define db5500_add_msp1_spi(pdata) \ + dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata) +#define db5500_add_msp2_spi(pdata) \ + dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata) + +#define db5500_add_rtc() \ + dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC); + +#define db5500_add_sdi0(pdata) \ + dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata) +#define db5500_add_sdi1(pdata) \ + dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata) +#define db5500_add_sdi2(pdata) \ + dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata) +#define db5500_add_sdi3(pdata) \ + dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata) +#define db5500_add_sdi4(pdata) \ + dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata) + +#define db5500_add_spi0(pdata) \ + dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata) +#define db5500_add_spi1(pdata) \ + dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata) +#define db5500_add_spi2(pdata) \ + dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata) +#define db5500_add_spi3(pdata) \ + dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata) + +#define db5500_add_uart0() \ + dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0) +#define db5500_add_uart1() \ + dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1) +#define db5500_add_uart2() \ + dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2) +#define db5500_add_uart3() \ + dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3) + +#endif diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 4a94be3304b9..1edcf82299fa 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -55,137 +55,6 @@ struct platform_device u8500_gpio_devs[] = { GPIO_DEVICE(8), }; -struct amba_device u8500_ssp0_device = { - .dev = { - .coherent_dma_mask = ~0, - .init_name = "ssp0", - }, - .res = { - .start = U8500_SSP0_BASE, - .end = U8500_SSP0_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_DB8500_SSP0, NO_IRQ }, - /* ST-Ericsson modified id */ - .periphid = SSP_PER_ID, -}; - -static struct resource u8500_i2c0_resources[] = { - [0] = { - .start = U8500_I2C0_BASE, - .end = U8500_I2C0_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_DB8500_I2C0, - .end = IRQ_DB8500_I2C0, - .flags = IORESOURCE_IRQ, - } -}; - -struct platform_device u8500_i2c0_device = { - .name = "nmk-i2c", - .id = 0, - .resource = u8500_i2c0_resources, - .num_resources = ARRAY_SIZE(u8500_i2c0_resources), -}; - -static struct resource u8500_i2c4_resources[] = { - [0] = { - .start = U8500_I2C4_BASE, - .end = U8500_I2C4_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = IRQ_DB8500_I2C4, - .end = IRQ_DB8500_I2C4, - .flags = IORESOURCE_IRQ, - } -}; - -struct platform_device u8500_i2c4_device = { - .name = "nmk-i2c", - .id = 4, - .resource = u8500_i2c4_resources, - .num_resources = ARRAY_SIZE(u8500_i2c4_resources), -}; - -/* - * SD/MMC - */ - -struct amba_device u8500_sdi0_device = { - .dev = { - .init_name = "sdi0", - }, - .res = { - .start = U8500_SDI0_BASE, - .end = U8500_SDI0_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_DB8500_SDMMC0, NO_IRQ}, -}; - -struct amba_device u8500_sdi1_device = { - .dev = { - .init_name = "sdi1", - }, - .res = { - .start = U8500_SDI1_BASE, - .end = U8500_SDI1_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_DB8500_SDMMC1, NO_IRQ}, -}; - -struct amba_device u8500_sdi2_device = { - .dev = { - .init_name = "sdi2", - }, - .res = { - .start = U8500_SDI2_BASE, - .end = U8500_SDI2_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_DB8500_SDMMC2, NO_IRQ}, -}; - -struct amba_device u8500_sdi3_device = { - .dev = { - .init_name = "sdi3", - }, - .res = { - .start = U8500_SDI3_BASE, - .end = U8500_SDI3_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_DB8500_SDMMC3, NO_IRQ}, -}; - -struct amba_device u8500_sdi4_device = { - .dev = { - .init_name = "sdi4", - }, - .res = { - .start = U8500_SDI4_BASE, - .end = U8500_SDI4_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_DB8500_SDMMC4, NO_IRQ}, -}; - -struct amba_device u8500_sdi5_device = { - .dev = { - .init_name = "sdi5", - }, - .res = { - .start = U8500_SDI5_BASE, - .end = U8500_SDI5_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_DB8500_SDMMC5, NO_IRQ}, -}; - static struct resource dma40_resources[] = { [0] = { .start = U8500_DMA_BASE, diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h new file mode 100644 index 000000000000..3a770c756979 --- /dev/null +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef __DEVICES_DB8500_H +#define __DEVICES_DB8500_H + +#include "devices-common.h" + +struct ske_keypad_platform_data; +struct pl022_ssp_controller; + +static inline struct platform_device * +db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata) +{ + return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1, + U8500_SKE_BASE, + IRQ_DB8500_KB, pdata); +} + +static inline struct amba_device * +db8500_add_ssp(const char *name, resource_size_t base, int irq, + struct pl022_ssp_controller *pdata) +{ + return dbx500_add_amba_device(name, base, irq, pdata, SSP_PER_ID); +} + + +#define db8500_add_i2c0(pdata) \ + dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata) +#define db8500_add_i2c1(pdata) \ + dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata) +#define db8500_add_i2c2(pdata) \ + dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata) +#define db8500_add_i2c3(pdata) \ + dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata) +#define db8500_add_i2c4(pdata) \ + dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata) + +#define db8500_add_msp0_i2s(pdata) \ + dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) +#define db8500_add_msp1_i2s(pdata) \ + dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) +#define db8500_add_msp2_i2s(pdata) \ + dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) +#define db8500_add_msp3_i2s(pdata) \ + dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) + +#define db8500_add_msp0_spi(pdata) \ + dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) +#define db8500_add_msp1_spi(pdata) \ + dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) +#define db8500_add_msp2_spi(pdata) \ + dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) +#define db8500_add_msp3_spi(pdata) \ + dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) + +#define db8500_add_rtc() \ + dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC); + +#define db8500_add_sdi0(pdata) \ + dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata) +#define db8500_add_sdi1(pdata) \ + dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata) +#define db8500_add_sdi2(pdata) \ + dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata) +#define db8500_add_sdi3(pdata) \ + dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata) +#define db8500_add_sdi4(pdata) \ + dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata) +#define db8500_add_sdi5(pdata) \ + dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata) + +#define db8500_add_ssp0(pdata) \ + db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata) +#define db8500_add_ssp1(pdata) \ + db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata) + +#define db8500_add_spi0(pdata) \ + dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata) +#define db8500_add_spi1(pdata) \ + dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata) +#define db8500_add_spi2(pdata) \ + dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata) +#define db8500_add_spi3(pdata) \ + dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata) + +#define db8500_add_uart0() \ + dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0) +#define db8500_add_uart1() \ + dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1) +#define db8500_add_uart2() \ + dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2) + +#endif diff --git a/arch/arm/mach-ux500/devices.c b/arch/arm/mach-ux500/devices.c index 8a268893cb7f..ea0a2f92ca70 100644 --- a/arch/arm/mach-ux500/devices.c +++ b/arch/arm/mach-ux500/devices.c @@ -14,69 +14,6 @@ #include #include -#define __MEM_4K_RESOURCE(x) \ - .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM} - -struct amba_device ux500_pl031_device = { - .dev = { - .init_name = "pl031", - }, - .res = { - .start = UX500_RTC_BASE, - .end = UX500_RTC_BASE + SZ_4K - 1, - .flags = IORESOURCE_MEM, - }, - .irq = {IRQ_RTC_RTT, NO_IRQ}, -}; - -struct amba_device ux500_uart0_device = { - .dev = { .init_name = "uart0" }, - __MEM_4K_RESOURCE(UX500_UART0_BASE), - .irq = {IRQ_UART0, NO_IRQ}, -}; - -struct amba_device ux500_uart1_device = { - .dev = { .init_name = "uart1" }, - __MEM_4K_RESOURCE(UX500_UART1_BASE), - .irq = {IRQ_UART1, NO_IRQ}, -}; - -struct amba_device ux500_uart2_device = { - .dev = { .init_name = "uart2" }, - __MEM_4K_RESOURCE(UX500_UART2_BASE), - .irq = {IRQ_UART2, NO_IRQ}, -}; - -#define UX500_I2C_RESOURCES(id, size) \ -static struct resource ux500_i2c##id##_resources[] = { \ - [0] = { \ - .start = UX500_I2C##id##_BASE, \ - .end = UX500_I2C##id##_BASE + size - 1, \ - .flags = IORESOURCE_MEM, \ - }, \ - [1] = { \ - .start = IRQ_I2C##id, \ - .end = IRQ_I2C##id, \ - .flags = IORESOURCE_IRQ \ - } \ -} - -UX500_I2C_RESOURCES(1, SZ_4K); -UX500_I2C_RESOURCES(2, SZ_4K); -UX500_I2C_RESOURCES(3, SZ_4K); - -#define UX500_I2C_PDEVICE(cid) \ -struct platform_device ux500_i2c##cid##_device = { \ - .name = "nmk-i2c", \ - .id = cid, \ - .num_resources = 2, \ - .resource = ux500_i2c##cid##_resources, \ -} - -UX500_I2C_PDEVICE(1); -UX500_I2C_PDEVICE(2); -UX500_I2C_PDEVICE(3); - void __init amba_add_devices(struct amba_device *devs[], int num) { int i; diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h index b91a4d1211a2..020b6369a30a 100644 --- a/arch/arm/mach-ux500/include/mach/devices.h +++ b/arch/arm/mach-ux500/include/mach/devices.h @@ -14,27 +14,10 @@ extern struct platform_device u5500_gpio_devs[]; extern struct platform_device u8500_gpio_devs[]; extern struct amba_device ux500_pl031_device; -extern struct amba_device u8500_ssp0_device; -extern struct amba_device ux500_uart0_device; -extern struct amba_device ux500_uart1_device; -extern struct amba_device ux500_uart2_device; -extern struct platform_device ux500_i2c1_device; -extern struct platform_device ux500_i2c2_device; -extern struct platform_device ux500_i2c3_device; - -extern struct platform_device u8500_i2c0_device; -extern struct platform_device u8500_i2c4_device; extern struct platform_device u8500_dma40_device; extern struct platform_device ux500_ske_keypad_device; -extern struct amba_device u8500_sdi0_device; -extern struct amba_device u8500_sdi1_device; -extern struct amba_device u8500_sdi2_device; -extern struct amba_device u8500_sdi3_device; -extern struct amba_device u8500_sdi4_device; -extern struct amba_device u8500_sdi5_device; - void dma40_u8500ed_fixup(void); #endif diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 54bbe648bf58..322a1c1f2bae 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -18,7 +18,6 @@ extern void __init ux500_map_io(void); extern void __init u5500_map_io(void); extern void __init u8500_map_io(void); -extern void __init ux500_init_devices(void); extern void __init u5500_init_devices(void); extern void __init u8500_init_devices(void); @@ -26,6 +25,7 @@ extern void __init ux500_init_irq(void); /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); +struct amba_device; extern void __init amba_add_devices(struct amba_device *devs[], int num); struct sys_timer; From fcbd458e95316fe5031f1b8eaf5e66ce8f3c3146 Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Thu, 2 Dec 2010 16:20:42 +0100 Subject: [PATCH 04/35] ARM: ux500: prcmu db8500 v2 support This patch adds support for db8500 chip version 2. The TCDM memory address of the PRCMU is changed and dynamic detection of that is added. Signed-off-by: Mattias Wallin Acked-by: Linus Walleij --- arch/arm/mach-ux500/cpu-db8500.c | 18 ++++++++----- arch/arm/mach-ux500/cpu.c | 2 ++ .../arm/mach-ux500/include/mach/db8500-regs.h | 3 ++- arch/arm/mach-ux500/include/mach/prcmu.h | 1 + arch/arm/mach-ux500/prcmu.c | 25 +++++++++++++++---- 5 files changed, 37 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 5966f353890f..b78970c08ebc 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -40,7 +40,6 @@ static struct platform_device *platform_devs[] __initdata = { /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_io_desc[] __initdata = { __IO_DEV_DESC(U8500_PRCMU_BASE, SZ_4K), - __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO0_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO1_BASE, SZ_4K), __IO_DEV_DESC(U8500_GPIO2_BASE, SZ_4K), @@ -48,13 +47,18 @@ static struct map_desc u8500_io_desc[] __initdata = { __MEM_DEV_DESC(U8500_BOOT_ROM_BASE, SZ_1M), }; -static struct map_desc u8500ed_io_desc[] __initdata = { +static struct map_desc u8500_ed_io_desc[] __initdata = { __IO_DEV_DESC(U8500_MTU0_BASE_ED, SZ_4K), __IO_DEV_DESC(U8500_CLKRST7_BASE_ED, SZ_8K), }; -static struct map_desc u8500v1_io_desc[] __initdata = { +static struct map_desc u8500_v1_io_desc[] __initdata = { __IO_DEV_DESC(U8500_MTU0_BASE, SZ_4K), + __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE_V1, SZ_4K), +}; + +static struct map_desc u8500_v2_io_desc[] __initdata = { + __IO_DEV_DESC(U8500_PRCMU_TCDM_BASE, SZ_4K), }; /* @@ -127,9 +131,11 @@ void __init u8500_map_io(void) iotable_init(u8500_io_desc, ARRAY_SIZE(u8500_io_desc)); if (cpu_is_u8500ed()) - iotable_init(u8500ed_io_desc, ARRAY_SIZE(u8500ed_io_desc)); - else - iotable_init(u8500v1_io_desc, ARRAY_SIZE(u8500v1_io_desc)); + iotable_init(u8500_ed_io_desc, ARRAY_SIZE(u8500_ed_io_desc)); + else if (cpu_is_u8500v1()) + iotable_init(u8500_v1_io_desc, ARRAY_SIZE(u8500_v1_io_desc)); + else if (cpu_is_u8500v2()) + iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc)); /* Read out the ASIC ID as early as we can */ get_db8500_asic_id(); diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 2bc0efbac584..46c372fb806d 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "clock.h" @@ -58,6 +59,7 @@ void __init ux500_init_irq(void) * Init clocks here so that they are available for system timer * initialization. */ + prcmu_early_init(); clk_init(); } diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index f07d0986409d..0fefb34c11e4 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h @@ -92,7 +92,8 @@ #define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000) #define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000) #define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000) -#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x0f000) +#define U8500_PRCMU_TCDM_BASE_V1 (U8500_PER4_BASE + 0x0f000) +#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000) /* per3 base addresses */ #define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000) diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h index 549843ff6dbe..daa9d3ab7e0c 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu.h +++ b/arch/arm/mach-ux500/include/mach/prcmu.h @@ -9,6 +9,7 @@ #ifndef __MACH_PRCMU_H #define __MACH_PRCMU_H +void __init prcmu_early_init(void); int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c index 293274d1342a..3ba3e3298b89 100644 --- a/arch/arm/mach-ux500/prcmu.c +++ b/arch/arm/mach-ux500/prcmu.c @@ -20,10 +20,11 @@ #include #include -#define PRCMU_TCDM_BASE __io_address(U8500_PRCMU_TCDM_BASE) +/* Global var to runtime determine TCDM base for v2 or v1 */ +static __iomem void *tcdm_base; -#define REQ_MB5 (PRCMU_TCDM_BASE + 0xE44) -#define ACK_MB5 (PRCMU_TCDM_BASE + 0xDF4) +#define REQ_MB5 (tcdm_base + 0xE44) +#define ACK_MB5 (tcdm_base + 0xDF4) #define REQ_MB5_I2C_SLAVE_OP (REQ_MB5) #define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1) @@ -33,8 +34,10 @@ #define ACK_MB5_I2C_STATUS (ACK_MB5 + 1) #define ACK_MB5_I2C_VAL (ACK_MB5 + 3) -#define I2C_WRITE(slave) ((slave) << 1) -#define I2C_READ(slave) (((slave) << 1) | BIT(0)) +#define I2C_WRITE(slave) \ + (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0)) +#define I2C_READ(slave) \ + (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0)) #define I2C_STOP_EN BIT(3) enum ack_mb5_status { @@ -217,6 +220,18 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data) return IRQ_HANDLED; } +void __init prcmu_early_init(void) +{ + if (cpu_is_u8500v11() || cpu_is_u8500ed()) { + tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE_V1); + } else if (cpu_is_u8500v2()) { + tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); + } else { + pr_err("prcmu: Unsupported chip version\n"); + BUG(); + } +} + static int __init prcmu_init(void) { mutex_init(&mb5_transfer.lock); From a5de3dc240eb4e58f02b199ed529c17b65f9adfb Mon Sep 17 00:00:00 2001 From: Mattias Wallin Date: Thu, 2 Dec 2010 13:46:00 +0100 Subject: [PATCH 05/35] mach-ux500: AB8500 irqs is taken from header file This patch removes the dublicated define for number of interrupts and instead include the needed header file. Signed-off-by: Mattias Wallin Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/include/mach/irqs-board-mop500.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h index 7ee8aaae66a4..4a91bbdb973e 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h @@ -8,7 +8,8 @@ #ifndef __MACH_IRQS_BOARD_MOP500_H #define __MACH_IRQS_BOARD_MOP500_H -#define AB8500_NR_IRQS 104 +/* Number of AB8500 irqs is taken from header file */ +#include #define MOP500_AB8500_IRQ_BASE IRQ_BOARD_START #define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ From edaa86a4142474c99e4741efb6a916067978a1ee Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 2 Dec 2010 12:05:18 +0100 Subject: [PATCH 06/35] ux500: minor revision to the eMMC/SD config A small fixup for the v1(.0) ASIC. Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-sdi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index be5e8ccb97cc..4b996676594e 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -137,12 +137,21 @@ static struct mmci_platform_data mop500_sdi4_data = { .gpio_wp = -1, }; -void mop500_sdi_init(void) +void __init mop500_sdi_init(void) { nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins)); + /* + * sdi0 will finally be added when the TC35892 initializes and calls + * mop500_sdi_tc35892_init() above. + */ + + /* PoP:ed eMMC */ if (!cpu_is_u8500ed()) { nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins)); + /* POP eMMC on v1.0 has problems with high speed */ + if (!cpu_is_u8500v10()) + mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED; db8500_add_sdi2(&mop500_sdi2_data); } From dacdc96cd33dee876c704aaed78f41515abe8a81 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 3 Dec 2010 20:35:37 +0530 Subject: [PATCH 07/35] nomadik-gpio: allow sleep mode dir/pull to differ from normal mode In the nomadik GPIO pin configuration, allow the sleep mode direction and pull configurations to differ from the ones for the normal state. PIN_SLPM_PULL_*, PIN_SLPM_INPUT, PIN_SLPM_OUTPUT* macros are provided for this. Since the hardware does not allow seperate configurations for sleep mode and normal mode, this is implemented by having software remux the configurations as necessary. Reviewed-by: Srinidhi KASAGAR Signed-off-by: Rabin Vincent Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 50 +++++++++++++-- arch/arm/plat-nomadik/include/plat/pincfg.h | 70 ++++++++++++++++----- 2 files changed, 99 insertions(+), 21 deletions(-) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 85e6fd212a41..5fc8e4d8cd2a 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -119,7 +119,7 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, } static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, - pin_cfg_t cfg) + pin_cfg_t cfg, bool sleep) { static const char *afnames[] = { [NMK_GPIO_ALT_GPIO] = "GPIO", @@ -145,11 +145,34 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, int output = PIN_DIR(cfg); int val = PIN_VAL(cfg); - dev_dbg(nmk_chip->chip.dev, "pin %d: af %s, pull %s, slpm %s (%s%s)\n", - pin, afnames[af], pullnames[pull], slpmnames[slpm], + dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n", + pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm], output ? "output " : "input", output ? (val ? "high" : "low") : ""); + if (sleep) { + int slpm_pull = PIN_SLPM_PULL(cfg); + int slpm_output = PIN_SLPM_DIR(cfg); + int slpm_val = PIN_SLPM_VAL(cfg); + + /* + * The SLPM_* values are normal values + 1 to allow zero to + * mean "same as normal". + */ + if (slpm_pull) + pull = slpm_pull - 1; + if (slpm_output) + output = slpm_output - 1; + if (slpm_val) + val = slpm_val - 1; + + dev_dbg(nmk_chip->chip.dev, "pin %d: sleep pull %s, dir %s, val %s\n", + pin, + slpm_pull ? pullnames[pull] : "same", + slpm_output ? (output ? "output" : "input") : "same", + slpm_val ? (val ? "high" : "low") : "same"); + } + if (output) __nmk_gpio_make_output(nmk_chip, offset, val); else { @@ -175,7 +198,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, * side-effects. The gpio can be manipulated later using standard GPIO API * calls. */ -int nmk_config_pin(pin_cfg_t cfg) +int nmk_config_pin(pin_cfg_t cfg, bool sleep) { struct nmk_gpio_chip *nmk_chip; int gpio = PIN_NUM(cfg); @@ -186,7 +209,7 @@ int nmk_config_pin(pin_cfg_t cfg) return -EINVAL; spin_lock_irqsave(&nmk_chip->lock, flags); - __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg); + __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep); spin_unlock_irqrestore(&nmk_chip->lock, flags); return 0; @@ -207,7 +230,7 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num) int i; for (i = 0; i < num; i++) { - int ret = nmk_config_pin(cfgs[i]); + ret = nmk_config_pin(cfgs[i], false); if (ret) break; } @@ -216,6 +239,21 @@ int nmk_config_pins(pin_cfg_t *cfgs, int num) } EXPORT_SYMBOL(nmk_config_pins); +int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num) +{ + int ret = 0; + int i; + + for (i = 0; i < num; i++) { + ret = nmk_config_pin(cfgs[i], true); + if (ret) + break; + } + + return ret; +} +EXPORT_SYMBOL(nmk_config_pins_sleep); + /** * nmk_gpio_set_slpm() - configure the sleep mode of a pin * @gpio: pin number diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/arch/arm/plat-nomadik/include/plat/pincfg.h index 8c5ae3f2acf8..05a3936ae6d1 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/arch/arm/plat-nomadik/include/plat/pincfg.h @@ -19,16 +19,22 @@ * bit 9..10 - Alternate Function Selection * bit 11..12 - Pull up/down state * bit 13 - Sleep mode behaviour - * bit 14 - (sleep mode) Direction - * bit 15 - (sleep mode) Value (if output) + * bit 14 - Direction + * bit 15 - Value (if output) + * bit 16..18 - SLPM pull up/down state + * bit 19..20 - SLPM direction + * bit 21..22 - SLPM Value (if output) * * to facilitate the definition, the following macros are provided * * PIN_CFG_DEFAULT - default config (0): * pull up/down = disabled * sleep mode = input/wakeup - * (sleep mode) direction = input - * (sleep mode) value = low + * direction = input + * value = low + * SLPM direction = same as normal + * SLPM pull = same as normal + * SLPM value = same as normal * * PIN_CFG - default config with alternate function * PIN_CFG_PULL - default config with alternate function and pull up/down @@ -75,30 +81,64 @@ typedef unsigned long pin_cfg_t; #define PIN_VAL_LOW (0 << PIN_VAL_SHIFT) #define PIN_VAL_HIGH (1 << PIN_VAL_SHIFT) -/* Shortcuts. Use these instead of separate DIR and VAL. */ -#define PIN_INPUT PIN_DIR_INPUT +#define PIN_SLPM_PULL_SHIFT 16 +#define PIN_SLPM_PULL_MASK (0x7 << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL(x) \ + (((x) & PIN_SLPM_PULL_MASK) >> PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_NONE \ + ((1 + NMK_GPIO_PULL_NONE) << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_UP \ + ((1 + NMK_GPIO_PULL_UP) << PIN_SLPM_PULL_SHIFT) +#define PIN_SLPM_PULL_DOWN \ + ((1 + NMK_GPIO_PULL_DOWN) << PIN_SLPM_PULL_SHIFT) + +#define PIN_SLPM_DIR_SHIFT 19 +#define PIN_SLPM_DIR_MASK (0x3 << PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR(x) \ + (((x) & PIN_SLPM_DIR_MASK) >> PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR_INPUT ((1 + 0) << PIN_SLPM_DIR_SHIFT) +#define PIN_SLPM_DIR_OUTPUT ((1 + 1) << PIN_SLPM_DIR_SHIFT) + +#define PIN_SLPM_VAL_SHIFT 21 +#define PIN_SLPM_VAL_MASK (0x3 << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL(x) \ + (((x) & PIN_SLPM_VAL_MASK) >> PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL_LOW ((1 + 0) << PIN_SLPM_VAL_SHIFT) +#define PIN_SLPM_VAL_HIGH ((1 + 1) << PIN_SLPM_VAL_SHIFT) + +/* Shortcuts. Use these instead of separate DIR, PULL, and VAL. */ +#define PIN_INPUT_PULLDOWN (PIN_DIR_INPUT | PIN_PULL_DOWN) +#define PIN_INPUT_PULLUP (PIN_DIR_INPUT | PIN_PULL_UP) +#define PIN_INPUT_NOPULL (PIN_DIR_INPUT | PIN_PULL_NONE) #define PIN_OUTPUT_LOW (PIN_DIR_OUTPUT | PIN_VAL_LOW) #define PIN_OUTPUT_HIGH (PIN_DIR_OUTPUT | PIN_VAL_HIGH) -/* - * These are the same as the ones above, but should make more sense to the - * reader when seen along with a setting a pin to AF mode. - */ -#define PIN_SLPM_INPUT PIN_INPUT -#define PIN_SLPM_OUTPUT_LOW PIN_OUTPUT_LOW -#define PIN_SLPM_OUTPUT_HIGH PIN_OUTPUT_HIGH +#define PIN_SLPM_INPUT_PULLDOWN (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_DOWN) +#define PIN_SLPM_INPUT_PULLUP (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_UP) +#define PIN_SLPM_INPUT_NOPULL (PIN_SLPM_DIR_INPUT | PIN_SLPM_PULL_NONE) +#define PIN_SLPM_OUTPUT_LOW (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_LOW) +#define PIN_SLPM_OUTPUT_HIGH (PIN_SLPM_DIR_OUTPUT | PIN_SLPM_VAL_HIGH) -#define PIN_CFG_DEFAULT (PIN_PULL_NONE | PIN_SLPM_INPUT) +#define PIN_CFG_DEFAULT (0) #define PIN_CFG(num, alt) \ (PIN_CFG_DEFAULT |\ (PIN_NUM(num) | PIN_##alt)) +#define PIN_CFG_INPUT(num, alt, pull) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt | PIN_INPUT_##pull)) + +#define PIN_CFG_OUTPUT(num, alt, val) \ + (PIN_CFG_DEFAULT |\ + (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) + #define PIN_CFG_PULL(num, alt, pull) \ ((PIN_CFG_DEFAULT & ~PIN_PULL_MASK) |\ (PIN_NUM(num) | PIN_##alt | PIN_PULL_##pull)) -extern int nmk_config_pin(pin_cfg_t cfg); +extern int nmk_config_pin(pin_cfg_t cfg, bool sleep); extern int nmk_config_pins(pin_cfg_t *cfgs, int num); +extern int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num); #endif From f306954c9b69aa21bd26724c59ac8c98b7d6e003 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Fri, 3 Dec 2010 20:35:51 +0530 Subject: [PATCH 08/35] mach-ux500: explicit enable MTU TCR in the kernel PRCM_TCR enables the various timers in the system. This must be achieved before any of the MTUs are usable for kernel usage. Explicit enabling of this in the kernel makes it independent of bootloader actions. Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/clock.c | 49 +++++++------------------------------ 1 file changed, 9 insertions(+), 40 deletions(-) diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 1675047daf20..a7cd0d55828e 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -133,7 +133,7 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) { void __iomem *addr = __io_address(UX500_PRCMU_BASE) + PRCM_TCR; - u32 tcr = readl(addr); + u32 tcr; int mtu = (int) clk->data; /* * One of these is selected eventually @@ -144,6 +144,14 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) unsigned long mturate; unsigned long retclk; + /* + * On a startup, always conifgure the TCR to the doze mode; + * bootloaders do it for us. Do this in the kernel too. + */ + writel(PRCM_TCR_DOZE_MODE, addr); + + tcr = readl(addr); + /* Get the rate from the parent as a default */ if (clk->parent_periph) mturate = clk_get_rate(clk->parent_periph); @@ -153,45 +161,6 @@ static unsigned long clk_mtu_get_rate(struct clk *clk) /* We need to be connected SOMEWHERE */ BUG(); - /* - * Are we in doze mode? - * In this mode the parent peripheral or the fixed 32768 Hz - * clock is fed into the block. - */ - if (!(tcr & PRCM_TCR_DOZE_MODE)) { - /* - * Here we're using the clock input from the APE ULP - * clock domain. But first: are the timers stopped? - */ - if (tcr & PRCM_TCR_STOPPED) { - clk32k = 0; - mturate = 0; - } else { - /* Else default mode: 0 and 2.4 MHz */ - clk32k = 0; - if (cpu_is_u5500()) - /* DB5500 divides by 8 */ - mturate /= 8; - else if (cpu_is_u8500ed()) { - /* - * This clocking setting must not be used - * in the ED chip, it is simply not - * connected anywhere! - */ - mturate = 0; - BUG(); - } else - /* - * In this mode the ulp38m4 clock is divided - * by a factor 16, on the DB8500 typically - * 38400000 / 16 ~ 2.4 MHz. - * TODO: Replace the constant with a reference - * to the ULP source once this is modeled. - */ - mturate = 38400000 / 16; - } - } - /* Return the clock selected for this MTU */ if (tcr & (1 << mtu)) retclk = clk32k; From 592b2f254d68b6eb8665658cc7d8fc3cd61ebc94 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Fri, 3 Dec 2010 20:35:52 +0530 Subject: [PATCH 09/35] mach-ux500: clean up checkpatch spits Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/clock.c | 118 ++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index a7cd0d55828e..3d4e8eb403ba 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -335,92 +335,92 @@ static DEFINE_PRCMU_CLK(uiccclk, 0x4, 1, UICCCLK); /* v1 */ */ /* Peripheral Cluster #1 */ -static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, i2c4, 10, 9, &clk_i2cclk); static DEFINE_PRCC_CLK(1, gpio0, 9, -1, NULL); -static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); -static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL); -static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL); -static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, slimbus0, 8, 8, &clk_slimclk); +static DEFINE_PRCC_CLK(1, spi3_ed, 7, 7, NULL); +static DEFINE_PRCC_CLK(1, spi3_v1, 7, -1, NULL); +static DEFINE_PRCC_CLK(1, i2c2, 6, 6, &clk_i2cclk); static DEFINE_PRCC_CLK(1, sdi0, 5, 5, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk); -static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk); -static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk); -static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk); -static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk); -static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk); +static DEFINE_PRCC_CLK(1, msp1_ed, 4, 4, &clk_msp02clk); +static DEFINE_PRCC_CLK(1, msp1_v1, 4, 4, &clk_msp1clk); +static DEFINE_PRCC_CLK(1, msp0, 3, 3, &clk_msp02clk); +static DEFINE_PRCC_CLK(1, i2c1, 2, 2, &clk_i2cclk); +static DEFINE_PRCC_CLK(1, uart1, 1, 1, &clk_uartclk); +static DEFINE_PRCC_CLK(1, uart0, 0, 0, &clk_uartclk); /* Peripheral Cluster #2 */ static DEFINE_PRCC_CLK(2, gpio1_ed, 12, -1, NULL); -static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL); -static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL); -static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL); -static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk); -static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, ssitx_ed, 11, -1, NULL); +static DEFINE_PRCC_CLK(2, ssirx_ed, 10, -1, NULL); +static DEFINE_PRCC_CLK(2, spi0_ed, 9, -1, NULL); +static DEFINE_PRCC_CLK(2, sdi3_ed, 8, 6, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, sdi1_ed, 7, 5, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, msp2_ed, 6, 4, &clk_msp02clk); +static DEFINE_PRCC_CLK(2, sdi4_ed, 4, 2, &clk_sdmmcclk); static DEFINE_PRCC_CLK(2, pwl_ed, 3, 1, NULL); -static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL); -static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL); -static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk); +static DEFINE_PRCC_CLK(2, spi1_ed, 2, -1, NULL); +static DEFINE_PRCC_CLK(2, spi2_ed, 1, -1, NULL); +static DEFINE_PRCC_CLK(2, i2c3_ed, 0, 0, &clk_i2cclk); static DEFINE_PRCC_CLK(2, gpio1_v1, 11, -1, NULL); -static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL); -static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL); -static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL); -static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk); -static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, ssitx_v1, 10, 7, NULL); +static DEFINE_PRCC_CLK(2, ssirx_v1, 9, 6, NULL); +static DEFINE_PRCC_CLK(2, spi0_v1, 8, -1, NULL); +static DEFINE_PRCC_CLK(2, sdi3_v1, 7, 5, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, sdi1_v1, 6, 4, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(2, msp2_v1, 5, 3, &clk_msp02clk); +static DEFINE_PRCC_CLK(2, sdi4_v1, 4, 2, &clk_sdmmcclk); static DEFINE_PRCC_CLK(2, pwl_v1, 3, 1, NULL); -static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL); -static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL); -static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk); +static DEFINE_PRCC_CLK(2, spi1_v1, 2, -1, NULL); +static DEFINE_PRCC_CLK(2, spi2_v1, 1, -1, NULL); +static DEFINE_PRCC_CLK(2, i2c3_v1, 0, 0, &clk_i2cclk); /* Peripheral Cluster #3 */ -static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL); -static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk); -static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz); -static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk); -static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk); -static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk); -static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk); -static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk); -static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk); -static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL); +static DEFINE_PRCC_CLK(3, gpio2, 8, -1, NULL); +static DEFINE_PRCC_CLK(3, sdi5, 7, 7, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(3, uart2, 6, 6, &clk_uartclk); +static DEFINE_PRCC_CLK(3, ske, 5, 5, &clk_32khz); +static DEFINE_PRCC_CLK(3, sdi2, 4, 4, &clk_sdmmcclk); +static DEFINE_PRCC_CLK(3, i2c0, 3, 3, &clk_i2cclk); +static DEFINE_PRCC_CLK(3, ssp1_ed, 2, 2, &clk_i2cclk); +static DEFINE_PRCC_CLK(3, ssp0_ed, 1, 1, &clk_i2cclk); +static DEFINE_PRCC_CLK(3, ssp1_v1, 2, 2, &clk_sspclk); +static DEFINE_PRCC_CLK(3, ssp0_v1, 1, 1, &clk_sspclk); +static DEFINE_PRCC_CLK(3, fsmc, 0, -1, NULL); /* Peripheral Cluster #4 is in the always on domain */ /* Peripheral Cluster #5 */ -static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL); -static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk); -static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL); +static DEFINE_PRCC_CLK(5, gpio3, 1, -1, NULL); +static DEFINE_PRCC_CLK(5, usb_ed, 0, 0, &clk_i2cclk); +static DEFINE_PRCC_CLK(5, usb_v1, 0, 0, NULL); /* Peripheral Cluster #6 */ /* MTU ID in data */ static DEFINE_PRCC_CLK_CUSTOM(6, mtu1_v1, 8, -1, NULL, clk_mtu_get_rate, 1); static DEFINE_PRCC_CLK_CUSTOM(6, mtu0_v1, 7, -1, NULL, clk_mtu_get_rate, 0); -static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL); -static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL); -static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); -static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk); -static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL); -static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL); -static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL); -static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL); -static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk); -static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk); +static DEFINE_PRCC_CLK(6, cfgreg_v1, 6, 6, NULL); +static DEFINE_PRCC_CLK(6, dmc_ed, 6, 6, NULL); +static DEFINE_PRCC_CLK(6, hash1, 5, -1, NULL); +static DEFINE_PRCC_CLK(6, unipro_v1, 4, 1, &clk_uniproclk); +static DEFINE_PRCC_CLK(6, cryp1_ed, 4, -1, NULL); +static DEFINE_PRCC_CLK(6, pka, 3, -1, NULL); +static DEFINE_PRCC_CLK(6, hash0, 2, -1, NULL); +static DEFINE_PRCC_CLK(6, cryp0, 1, -1, NULL); +static DEFINE_PRCC_CLK(6, rng_ed, 0, 0, &clk_i2cclk); +static DEFINE_PRCC_CLK(6, rng_v1, 0, 0, &clk_rngclk); /* Peripheral Cluster #7 */ -static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL); +static DEFINE_PRCC_CLK(7, tzpc0_ed, 4, -1, NULL); /* MTU ID in data */ static DEFINE_PRCC_CLK_CUSTOM(7, mtu1_ed, 3, -1, NULL, clk_mtu_get_rate, 1); static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0); -static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); -static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); +static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); +static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); static struct clk clk_dummy_apb_pclk; @@ -523,7 +523,7 @@ static struct clk_lookup u8500_ed_clks[] = { static struct clk_lookup u8500_v1_clks[] = { /* Peripheral Cluster #1 */ - CLK(i2c4, "nmk-i2c.4", NULL), + CLK(i2c4, "nmk-i2c.4", NULL), CLK(spi3_v1, "spi3", NULL), CLK(msp1_v1, "msp1", NULL), From 9b04f8b9070e60fe9d335613ec538223c159a5c9 Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Sun, 5 Dec 2010 12:27:05 +0100 Subject: [PATCH 10/35] ux500: Call prmcu_init only for u8500 PRCMU driver only supports u8500. Don't initialize prcmu if running on u5500. Signed-off-by: Per Forlin Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index 46c372fb806d..a3700bc374d3 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c @@ -59,7 +59,8 @@ void __init ux500_init_irq(void) * Init clocks here so that they are available for system timer * initialization. */ - prcmu_early_init(); + if (cpu_is_u8500()) + prcmu_early_init(); clk_init(); } From bab263e0ce624b05bdcf568e83a9ca4ce71f5e3d Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Sun, 5 Dec 2010 12:49:03 +0100 Subject: [PATCH 11/35] ux500: Add eMMC support in U5500. U5500 now boots from sdi0 (onboard eMMC). Change machine type to U5500. Adjust uart and sdi0 clock rates for u5500. All necessary clocks must be enabled before Linux starts because there is no clock tree support in u5500 yet. Signed-off-by: Per Forlin Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/board-u5500-sdi.c | 49 ++++++++++++++++++++++++ arch/arm/mach-ux500/board-u5500.c | 3 +- arch/arm/mach-ux500/clock.c | 2 + arch/arm/mach-ux500/include/mach/setup.h | 3 ++ 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-ux500/board-u5500-sdi.c diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 061201388dac..fb65e598bffb 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -6,7 +6,7 @@ obj-y := clock.o cpu.o devices.o devices-common.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o -obj-$(CONFIG_MACH_U5500) += board-u5500.o +obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c new file mode 100644 index 000000000000..54712acc0394 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-sdi.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Hanumath Prasad + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include + +#include +#include +#include + +#include "pins-db5500.h" +#include "devices-db5500.h" +#include "ste-dma40-db5500.h" + +static pin_cfg_t u5500_sdi_pins[] = { + /* SDI0 (POP eMMC) */ + GPIO5_MC0_DAT0 | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO6_MC0_DAT1 | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO7_MC0_DAT2 | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO8_MC0_DAT3 | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO9_MC0_DAT4 | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO10_MC0_DAT5 | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO11_MC0_DAT6 | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO12_MC0_DAT7 | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO13_MC0_CMD | PIN_DIR_INPUT | PIN_PULL_UP, + GPIO14_MC0_CLK | PIN_DIR_OUTPUT | PIN_VAL_LOW, +}; + +static struct mmci_platform_data u5500_sdi0_data = { + .ocr_mask = MMC_VDD_165_195, + .f_max = 50000000, + .capabilities = MMC_CAP_4_BIT_DATA | + MMC_CAP_8_BIT_DATA | + MMC_CAP_MMC_HIGHSPEED, + .gpio_cd = -1, + .gpio_wp = -1, +}; + +void __init u5500_sdi_init(void) +{ + nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins)); + + db5500_add_sdi0(&u5500_sdi0_data); +} diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 9a5db956deba..39d370c1f3b4 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -31,10 +31,11 @@ static void __init u5500_init_machine(void) { u5500_init_devices(); + u5500_sdi_init(); u5500_uart_init(); } -MACHINE_START(U8500, "ST-Ericsson U5500 Platform") +MACHINE_START(U5500, "ST-Ericsson U5500 Platform") .boot_params = 0x00000100, .map_io = u5500_map_io, .init_irq = ux500_init_irq, diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 3d4e8eb403ba..598902da31d8 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -579,6 +579,8 @@ int __init clk_init(void) clk_prcc_ops.enable = clk_prcc_ops.disable = NULL; clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL; clk_per6clk.rate = 26000000; + clk_uartclk.rate = 36360000; + clk_sdmmcclk.rate = 99900000; } clkdev_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 322a1c1f2bae..22788a7d35dc 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -22,6 +22,9 @@ extern void __init u5500_init_devices(void); extern void __init u8500_init_devices(void); extern void __init ux500_init_irq(void); + +extern void __init u5500_sdi_init(void); + /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); From e8b1cc3a341684dfc02fd02f52308752b031668c Mon Sep 17 00:00:00 2001 From: Per Forlin Date: Sun, 5 Dec 2010 13:35:12 +0100 Subject: [PATCH 12/35] ux500: Add DMA support for U5500 Add basic DMA configuration for u5500 supporting memcpy. Make way for SDI0 dma support by setting SDI0 to -1, indicating it will be configured in runtime. Signed-off-by: Per Forlin Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/cpu-db5500.c | 2 + arch/arm/mach-ux500/dma-db5500.c | 120 ++++++++++++++++++ .../arm/mach-ux500/include/mach/db5500-regs.h | 4 + arch/arm/mach-ux500/include/mach/setup.h | 2 + 5 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-ux500/dma-db5500.c diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index fb65e598bffb..9720e4284429 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -3,7 +3,7 @@ # obj-y := clock.o cpu.o devices.o devices-common.o -obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o +obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o dma-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index bcc0fd4fdc29..8816844d7e48 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -135,6 +135,8 @@ void __init u5500_map_io(void) void __init u5500_init_devices(void) { + db5500_dma_init(); + db5500_add_rtc(); platform_add_devices(u5500_platform_devs, diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c new file mode 100644 index 000000000000..32a061f8a95b --- /dev/null +++ b/arch/arm/mach-ux500/dma-db5500.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Per Forlin for ST-Ericsson + * Author: Jonas Aaberg for ST-Ericsson + * Author: Rabin Vincent for ST-Ericsson + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include +#include + +#include +#include +#include + +#include "ste-dma40-db5500.h" + +static struct resource dma40_resources[] = { + [0] = { + .start = U5500_DMA_BASE, + .end = U5500_DMA_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + .name = "base", + }, + [1] = { + .start = U5500_DMA_LCPA_BASE, + .end = U5500_DMA_LCPA_BASE + 2 * SZ_1K - 1, + .flags = IORESOURCE_MEM, + .name = "lcpa", + }, + [2] = { + .start = IRQ_DB5500_DMA, + .end = IRQ_DB5500_DMA, + .flags = IORESOURCE_IRQ + } +}; + +/* Default configuration for physical memcpy */ +static struct stedma40_chan_cfg dma40_memcpy_conf_phy = { + .mode = STEDMA40_MODE_PHYSICAL, + .dir = STEDMA40_MEM_TO_MEM, + + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .src_info.psize = STEDMA40_PSIZE_PHY_1, + .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + + .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.psize = STEDMA40_PSIZE_PHY_1, + .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +}; + +/* Default configuration for logical memcpy */ +static struct stedma40_chan_cfg dma40_memcpy_conf_log = { + .dir = STEDMA40_MEM_TO_MEM, + + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .src_info.psize = STEDMA40_PSIZE_LOG_1, + .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, + + .dst_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.psize = STEDMA40_PSIZE_LOG_1, + .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, +}; + +/* + * Mapping between soruce event lines and physical device address This was + * created assuming that the event line is tied to a device and therefore the + * address is constant, however this is not true for at least USB, and the + * values are just placeholders for USB. This table is preserved and used for + * now. + */ +static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = { + [DB5500_DMA_DEV24_SDMMC0_RX] = -1, +}; + +/* Mapping between destination event lines and physical device address */ +static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = { + [DB5500_DMA_DEV24_SDMMC0_TX] = -1, +}; + +static int dma40_memcpy_event[] = { + DB5500_DMA_MEMCPY_TX_1, + DB5500_DMA_MEMCPY_TX_2, + DB5500_DMA_MEMCPY_TX_3, + DB5500_DMA_MEMCPY_TX_4, + DB5500_DMA_MEMCPY_TX_5, +}; + +static struct stedma40_platform_data dma40_plat_data = { + .dev_len = ARRAY_SIZE(dma40_rx_map), + .dev_rx = dma40_rx_map, + .dev_tx = dma40_tx_map, + .memcpy = dma40_memcpy_event, + .memcpy_len = ARRAY_SIZE(dma40_memcpy_event), + .memcpy_conf_phy = &dma40_memcpy_conf_phy, + .memcpy_conf_log = &dma40_memcpy_conf_log, + .disabled_channels = {-1}, +}; + +static struct platform_device dma40_device = { + .dev = { + .platform_data = &dma40_plat_data, + }, + .name = "dma40", + .id = 0, + .num_resources = ARRAY_SIZE(dma40_resources), + .resource = dma40_resources +}; + +void __init db5500_dma_init(void) +{ + int ret; + + ret = platform_device_register(&dma40_device); + if (ret) + dev_err(&dma40_device.dev, "unable to register device: %d\n", ret); + +} diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h index 3eafc0e24ba5..bd88c1e74060 100644 --- a/arch/arm/mach-ux500/include/mach/db5500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h @@ -114,4 +114,8 @@ #define U5500_MBOX2_LOCAL_START (U5500_MBOX_BASE + 0x20) #define U5500_MBOX2_LOCAL_END (U5500_MBOX_BASE + 0x3F) +#define U5500_ESRAM_BASE 0x40000000 +#define U5500_ESRAM_DMA_LCPA_OFFSET 0x10000 +#define U5500_DMA_LCPA_BASE (U5500_ESRAM_BASE + U5500_ESRAM_DMA_LCPA_OFFSET) + #endif diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index 22788a7d35dc..469877e0de90 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h @@ -25,6 +25,8 @@ extern void __init ux500_init_irq(void); extern void __init u5500_sdi_init(void); +extern void __init db5500_dma_init(void); + /* We re-use nomadik_timer for this platform */ extern void nmdk_timer_init(void); From ec4a637d35d4e05d1f43a68d647fb2453891379a Mon Sep 17 00:00:00 2001 From: Carl-Johan Irekvist Date: Wed, 8 Dec 2010 11:07:53 +0530 Subject: [PATCH 13/35] ux500: fix uncompressor UART address for U5500 The uncompress code for zImage uses the UART to print status messages, this was hard coded to use UART2 for the U8500 platform. This patch checks at run time which platform it is run on. U5500 uses UART0 as console UART. Signed-off-by: Carl-Johan Irekvist Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/include/mach/uncompress.h | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h index 0271ca0a83df..9a6614c6808e 100644 --- a/arch/arm/mach-ux500/include/mach/uncompress.h +++ b/arch/arm/mach-ux500/include/mach/uncompress.h @@ -19,38 +19,43 @@ #define __ASM_ARCH_UNCOMPRESS_H #include +#include #include +#include #include -#define U8500_UART_DR 0x80007000 -#define U8500_UART_LCRH 0x8000702c -#define U8500_UART_CR 0x80007030 -#define U8500_UART_FR 0x80007018 +static u32 ux500_uart_base; static void putc(const char c) { /* Do nothing if the UART is not enabled. */ - if (!(__raw_readb(U8500_UART_CR) & 0x1)) + if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1)) return; if (c == '\n') putc('\r'); - while (__raw_readb(U8500_UART_FR) & (1 << 5)) + while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 5)) barrier(); - __raw_writeb(c, U8500_UART_DR); + __raw_writeb(c, ux500_uart_base + UART01x_DR); } static void flush(void) { - if (!(__raw_readb(U8500_UART_CR) & 0x1)) + if (!(__raw_readb(ux500_uart_base + UART011_CR) & 0x1)) return; - while (__raw_readb(U8500_UART_FR) & (1 << 3)) + while (__raw_readb(ux500_uart_base + UART01x_FR) & (1 << 3)) barrier(); } static inline void arch_decomp_setup(void) { + if (machine_is_u8500()) + ux500_uart_base = U8500_UART2_BASE; + else if (machine_is_u5500()) + ux500_uart_base = U5500_UART0_BASE; + else /* not much can be done to help here */ + ux500_uart_base = U8500_UART2_BASE; } #define arch_decomp_wdog() /* nothing to do here */ From 8d568ae5362c00c5b0b8e61bceb1829c8051002e Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 8 Dec 2010 11:07:54 +0530 Subject: [PATCH 14/35] nomadik-gpio: use dev name if no name is specified Platforms may choose not to provide an additional name for the GPIO block. Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 5fc8e4d8cd2a..eda4e3a11a3d 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -672,7 +672,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) chip = &nmk_chip->chip; chip->base = pdata->first_gpio; - chip->label = pdata->name; + chip->label = pdata->name ?: dev_name(&dev->dev); chip->dev = &dev->dev; chip->owner = THIS_MODULE; From 01afdd1353ca83904f430be4f6202d1a20912f4d Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 8 Dec 2010 11:07:55 +0530 Subject: [PATCH 15/35] ux500: rework gpio registration Rework gpio registration to remove build-time changing macros. Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/cpu-db5500.c | 33 +++++++++++---- arch/arm/mach-ux500/cpu-db8500.c | 32 ++++++++++---- arch/arm/mach-ux500/devices-common.c | 38 +++++++++++++++++ arch/arm/mach-ux500/devices-common.h | 5 +++ arch/arm/mach-ux500/devices-db5500.c | 46 --------------------- arch/arm/mach-ux500/devices-db8500.c | 36 ---------------- arch/arm/mach-ux500/include/mach/gpio.h | 38 ----------------- arch/arm/mach-ux500/include/mach/hardware.h | 2 + 9 files changed, 93 insertions(+), 139 deletions(-) delete mode 100644 arch/arm/mach-ux500/devices-db5500.c diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 9720e4284429..93b0cf162017 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -3,7 +3,7 @@ # obj-y := clock.o cpu.o devices.o devices-common.o -obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o devices-db5500.o dma-db5500.o +obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 8816844d7e48..acc841e48de4 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -12,6 +12,8 @@ #include +#include + #include #include #include @@ -113,19 +115,32 @@ static struct platform_device mbox2_device = { }; static struct platform_device *u5500_platform_devs[] __initdata = { - &u5500_gpio_devs[0], - &u5500_gpio_devs[1], - &u5500_gpio_devs[2], - &u5500_gpio_devs[3], - &u5500_gpio_devs[4], - &u5500_gpio_devs[5], - &u5500_gpio_devs[6], - &u5500_gpio_devs[7], &mbox0_device, &mbox1_device, &mbox2_device, }; +static resource_size_t __initdata db5500_gpio_base[] = { + U5500_GPIOBANK0_BASE, + U5500_GPIOBANK1_BASE, + U5500_GPIOBANK2_BASE, + U5500_GPIOBANK3_BASE, + U5500_GPIOBANK4_BASE, + U5500_GPIOBANK5_BASE, + U5500_GPIOBANK6_BASE, + U5500_GPIOBANK7_BASE, +}; + +static void __init db5500_add_gpios(void) +{ + struct nmk_gpio_platform_data pdata = { + /* No custom data yet */ + }; + + dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base), + IRQ_DB5500_GPIO0, &pdata); +} + void __init u5500_map_io(void) { ux500_map_io(); @@ -135,8 +150,8 @@ void __init u5500_map_io(void) void __init u5500_init_devices(void) { + db5500_add_gpios(); db5500_dma_init(); - db5500_add_rtc(); platform_add_devices(u5500_platform_devs, diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index b78970c08ebc..658384c86933 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -25,15 +25,6 @@ #include "devices-db8500.h" static struct platform_device *platform_devs[] __initdata = { - &u8500_gpio_devs[0], - &u8500_gpio_devs[1], - &u8500_gpio_devs[2], - &u8500_gpio_devs[3], - &u8500_gpio_devs[4], - &u8500_gpio_devs[5], - &u8500_gpio_devs[6], - &u8500_gpio_devs[7], - &u8500_gpio_devs[8], &u8500_dma40_device, }; @@ -141,6 +132,28 @@ void __init u8500_map_io(void) get_db8500_asic_id(); } +static resource_size_t __initdata db8500_gpio_base[] = { + U8500_GPIOBANK0_BASE, + U8500_GPIOBANK1_BASE, + U8500_GPIOBANK2_BASE, + U8500_GPIOBANK3_BASE, + U8500_GPIOBANK4_BASE, + U8500_GPIOBANK5_BASE, + U8500_GPIOBANK6_BASE, + U8500_GPIOBANK7_BASE, + U8500_GPIOBANK8_BASE, +}; + +static void __init db8500_add_gpios(void) +{ + struct nmk_gpio_platform_data pdata = { + /* No custom data yet */ + }; + + dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), + IRQ_DB8500_GPIO0, &pdata); +} + /* * This function is called from the board init */ @@ -164,6 +177,7 @@ void __init u8500_init_devices(void) dma40_u8500ed_fixup(); db8500_add_rtc(); + db8500_add_gpios(); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index 9376a246f862..fe69f5fac1bb 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -13,6 +13,8 @@ #include #include +#include + #include #include "devices-common.h" @@ -105,3 +107,39 @@ dbx500_add_platform_device_4k1irq(const char *name, int id, return dbx500_add_platform_device(name, id, pdata, resources, ARRAY_SIZE(resources)); } + +static struct platform_device * +dbx500_add_gpio(int id, resource_size_t addr, int irq, + struct nmk_gpio_platform_data *pdata) +{ + struct resource resources[] = { + { + .start = addr, + .end = addr + 127, + .flags = IORESOURCE_MEM, + }, + { + .start = irq, + .end = irq, + .flags = IORESOURCE_IRQ, + } + }; + + return platform_device_register_resndata(NULL, "gpio", id, + resources, ARRAY_SIZE(resources), + pdata, sizeof(*pdata)); +} + +void dbx500_add_gpios(resource_size_t *base, int num, int irq, + struct nmk_gpio_platform_data *pdata) +{ + int first = 0; + int i; + + for (i = 0; i < num; i++, first += 32, irq++) { + pdata->first_gpio = first; + pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first); + + dbx500_add_gpio(i, base[i], irq, pdata); + } +} diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 2e1de0e19717..cbadc117d2db 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -74,4 +74,9 @@ dbx500_add_rtc(resource_size_t base, int irq) return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0); } +struct nmk_gpio_platform_data; + +void dbx500_add_gpios(resource_size_t *base, int num, int irq, + struct nmk_gpio_platform_data *pdata); + #endif diff --git a/arch/arm/mach-ux500/devices-db5500.c b/arch/arm/mach-ux500/devices-db5500.c deleted file mode 100644 index 33e5b56bebb6..000000000000 --- a/arch/arm/mach-ux500/devices-db5500.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * - * Author: Rabin Vincent for ST-Ericsson - * License terms: GNU General Public License (GPL) version 2 - */ - -#include -#include -#include - -#include -#include - -static struct nmk_gpio_platform_data u5500_gpio_data[] = { - GPIO_DATA("GPIO-0-31", 0), - GPIO_DATA("GPIO-32-63", 32), /* 36..63 not routed to pin */ - GPIO_DATA("GPIO-64-95", 64), /* 83..95 not routed to pin */ - GPIO_DATA("GPIO-96-127", 96), /* 102..127 not routed to pin */ - GPIO_DATA("GPIO-128-159", 128), /* 149..159 not routed to pin */ - GPIO_DATA("GPIO-160-191", 160), - GPIO_DATA("GPIO-192-223", 192), - GPIO_DATA("GPIO-224-255", 224), /* 228..255 not routed to pin */ -}; - -static struct resource u5500_gpio_resources[] = { - GPIO_RESOURCE(0), - GPIO_RESOURCE(1), - GPIO_RESOURCE(2), - GPIO_RESOURCE(3), - GPIO_RESOURCE(4), - GPIO_RESOURCE(5), - GPIO_RESOURCE(6), - GPIO_RESOURCE(7), -}; - -struct platform_device u5500_gpio_devs[] = { - GPIO_DEVICE(0), - GPIO_DEVICE(1), - GPIO_DEVICE(2), - GPIO_DEVICE(3), - GPIO_DEVICE(4), - GPIO_DEVICE(5), - GPIO_DEVICE(6), - GPIO_DEVICE(7), -}; diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 1edcf82299fa..a7b0a183c037 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -19,42 +19,6 @@ #include "ste-dma40-db8500.h" -static struct nmk_gpio_platform_data u8500_gpio_data[] = { - GPIO_DATA("GPIO-0-31", 0), - GPIO_DATA("GPIO-32-63", 32), /* 37..63 not routed to pin */ - GPIO_DATA("GPIO-64-95", 64), - GPIO_DATA("GPIO-96-127", 96), /* 98..127 not routed to pin */ - GPIO_DATA("GPIO-128-159", 128), - GPIO_DATA("GPIO-160-191", 160), /* 172..191 not routed to pin */ - GPIO_DATA("GPIO-192-223", 192), - GPIO_DATA("GPIO-224-255", 224), /* 231..255 not routed to pin */ - GPIO_DATA("GPIO-256-288", 256), /* 268..288 not routed to pin */ -}; - -static struct resource u8500_gpio_resources[] = { - GPIO_RESOURCE(0), - GPIO_RESOURCE(1), - GPIO_RESOURCE(2), - GPIO_RESOURCE(3), - GPIO_RESOURCE(4), - GPIO_RESOURCE(5), - GPIO_RESOURCE(6), - GPIO_RESOURCE(7), - GPIO_RESOURCE(8), -}; - -struct platform_device u8500_gpio_devs[] = { - GPIO_DEVICE(0), - GPIO_DEVICE(1), - GPIO_DEVICE(2), - GPIO_DEVICE(3), - GPIO_DEVICE(4), - GPIO_DEVICE(5), - GPIO_DEVICE(6), - GPIO_DEVICE(7), - GPIO_DEVICE(8), -}; - static struct resource dma40_resources[] = { [0] = { .start = U8500_DMA_BASE, diff --git a/arch/arm/mach-ux500/include/mach/gpio.h b/arch/arm/mach-ux500/include/mach/gpio.h index d548a622e7d2..3c4cd31ad9f7 100644 --- a/arch/arm/mach-ux500/include/mach/gpio.h +++ b/arch/arm/mach-ux500/include/mach/gpio.h @@ -9,42 +9,4 @@ #include -#define __GPIO_RESOURCE(soc, block) \ - { \ - .start = soc##_GPIOBANK##block##_BASE, \ - .end = soc##_GPIOBANK##block##_BASE + 127, \ - .flags = IORESOURCE_MEM, \ - }, \ - { \ - .start = IRQ_GPIO##block, \ - .end = IRQ_GPIO##block, \ - .flags = IORESOURCE_IRQ, \ - } - -#define __GPIO_DEVICE(soc, block) \ - { \ - .name = "gpio", \ - .id = block, \ - .num_resources = 2, \ - .resource = &soc##_gpio_resources[block * 2], \ - .dev = { \ - .platform_data = &soc##_gpio_data[block], \ - }, \ - } - -#define GPIO_DATA(_name, first) \ - { \ - .name = _name, \ - .first_gpio = first, \ - .first_irq = NOMADIK_GPIO_TO_IRQ(first), \ - } - -#ifdef CONFIG_UX500_SOC_DB8500 -#define GPIO_RESOURCE(block) __GPIO_RESOURCE(U8500, block) -#define GPIO_DEVICE(block) __GPIO_DEVICE(u8500, block) -#elif defined(CONFIG_UX500_SOC_DB5500) -#define GPIO_RESOURCE(block) __GPIO_RESOURCE(U5500, block) -#define GPIO_DEVICE(block) __GPIO_DEVICE(u5500, block) -#endif - #endif /* __ASM_ARCH_GPIO_H */ diff --git a/arch/arm/mach-ux500/include/mach/hardware.h b/arch/arm/mach-ux500/include/mach/hardware.h index 32e883a8f2a2..6295cc581355 100644 --- a/arch/arm/mach-ux500/include/mach/hardware.h +++ b/arch/arm/mach-ux500/include/mach/hardware.h @@ -142,6 +142,8 @@ static inline bool cpu_is_u5500(void) #endif } +#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x) + #endif #endif /* __MACH_HARDWARE_H */ From 22039b7cc54a636f80434e9b149fcdec148c4cb9 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 8 Dec 2010 11:07:56 +0530 Subject: [PATCH 16/35] ux500: remove ambiguous irq macros Remove the irq number macros which don't specify which SoC they're for. Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 6 ++-- arch/arm/mach-ux500/include/mach/irqs.h | 44 ------------------------- arch/arm/mach-ux500/prcmu.c | 3 +- 3 files changed, 5 insertions(+), 48 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 8edc27f41f0d..287956cebe8b 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -98,9 +98,9 @@ static struct ab8500_platform_data ab8500_platdata = { static struct resource ab8500_resources[] = { [0] = { - .start = IRQ_AB8500, - .end = IRQ_AB8500, - .flags = IORESOURCE_IRQ + .start = IRQ_DB8500_AB8500, + .end = IRQ_DB8500_AB8500, + .flags = IORESOURCE_IRQ } }; diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h index 693aa57de88d..880ae45bc235 100644 --- a/arch/arm/mach-ux500/include/mach/irqs.h +++ b/arch/arm/mach-ux500/include/mach/irqs.h @@ -21,50 +21,6 @@ /* Interrupt numbers generic for shared peripheral */ #define IRQ_MTU0 (IRQ_SHPI_START + 4) -#define IRQ_SPI2 (IRQ_SHPI_START + 6) -#define IRQ_SPI0 (IRQ_SHPI_START + 8) -#define IRQ_UART0 (IRQ_SHPI_START + 11) -#define IRQ_I2C3 (IRQ_SHPI_START + 12) -#define IRQ_SSP0 (IRQ_SHPI_START + 14) -#define IRQ_MTU1 (IRQ_SHPI_START + 17) -#define IRQ_RTC_RTT (IRQ_SHPI_START + 18) -#define IRQ_UART1 (IRQ_SHPI_START + 19) -#define IRQ_I2C0 (IRQ_SHPI_START + 21) -#define IRQ_I2C1 (IRQ_SHPI_START + 22) -#define IRQ_USBOTG (IRQ_SHPI_START + 23) -#define IRQ_DMA (IRQ_SHPI_START + 25) -#define IRQ_UART2 (IRQ_SHPI_START + 26) -#define IRQ_HSIR_EXCEP (IRQ_SHPI_START + 29) -#define IRQ_MSP0 (IRQ_SHPI_START + 31) -#define IRQ_HSIR_CH0_OVRRUN (IRQ_SHPI_START + 32) -#define IRQ_HSIR_CH1_OVRRUN (IRQ_SHPI_START + 33) -#define IRQ_HSIR_CH2_OVRRUN (IRQ_SHPI_START + 34) -#define IRQ_HSIR_CH3_OVRRUN (IRQ_SHPI_START + 35) -#define IRQ_AB8500 (IRQ_SHPI_START + 40) -#define IRQ_PRCMU (IRQ_SHPI_START + 47) -#define IRQ_DISP (IRQ_SHPI_START + 48) -#define IRQ_SiPI3 (IRQ_SHPI_START + 49) -#define IRQ_I2C4 (IRQ_SHPI_START + 51) -#define IRQ_SSP1 (IRQ_SHPI_START + 52) -#define IRQ_I2C2 (IRQ_SHPI_START + 55) -#define IRQ_SDMMC0 (IRQ_SHPI_START + 60) -#define IRQ_MSP1 (IRQ_SHPI_START + 62) -#define IRQ_SPI1 (IRQ_SHPI_START + 96) -#define IRQ_MSP2 (IRQ_SHPI_START + 98) -#define IRQ_SDMMC4 (IRQ_SHPI_START + 99) -#define IRQ_HSIRD0 (IRQ_SHPI_START + 104) -#define IRQ_HSIRD1 (IRQ_SHPI_START + 105) -#define IRQ_HSITD0 (IRQ_SHPI_START + 106) -#define IRQ_HSITD1 (IRQ_SHPI_START + 107) -#define IRQ_GPIO0 (IRQ_SHPI_START + 119) -#define IRQ_GPIO1 (IRQ_SHPI_START + 120) -#define IRQ_GPIO2 (IRQ_SHPI_START + 121) -#define IRQ_GPIO3 (IRQ_SHPI_START + 122) -#define IRQ_GPIO4 (IRQ_SHPI_START + 123) -#define IRQ_GPIO5 (IRQ_SHPI_START + 124) -#define IRQ_GPIO6 (IRQ_SHPI_START + 125) -#define IRQ_GPIO7 (IRQ_SHPI_START + 126) -#define IRQ_GPIO8 (IRQ_SHPI_START + 127) /* There are 128 shared peripheral interrupts assigned to * INTID[160:32]. The first 32 interrupts are reserved. diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c index 3ba3e3298b89..07d5f13d2a4e 100644 --- a/arch/arm/mach-ux500/prcmu.c +++ b/arch/arm/mach-ux500/prcmu.c @@ -240,7 +240,8 @@ static int __init prcmu_init(void) /* Clean up the mailbox interrupts after pre-kernel code. */ writel((MBOX_BIT(NUM_MBOX) - 1), PRCM_ARM_IT1_CLEAR); - return request_irq(IRQ_PRCMU, prcmu_irq_handler, 0, "prcmu", NULL); + return request_irq(IRQ_DB8500_PRCMU1, prcmu_irq_handler, 0, + "prcmu", NULL); } arch_initcall(prcmu_init); From 20e218a77fc0b0576817b6b204fe5b9391a5b209 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 8 Dec 2010 17:18:46 +0530 Subject: [PATCH 17/35] ux500: fix 5500 PER6 clock rate The DB5500 PER6 clock rate is the same as the DB8500 one, i.e. 133.33 MHz. Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/clock.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 598902da31d8..00e9ab304ca7 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -578,7 +578,6 @@ int __init clk_init(void) /* Clock tree for U5500 not implemented yet */ clk_prcc_ops.enable = clk_prcc_ops.disable = NULL; clk_prcmu_ops.enable = clk_prcmu_ops.disable = NULL; - clk_per6clk.rate = 26000000; clk_uartclk.rate = 36360000; clk_sdmmcclk.rate = 99900000; } From e0befb23dfed4d4d0de9d97dac936ccc0bbec093 Mon Sep 17 00:00:00 2001 From: Martin Persson Date: Wed, 8 Dec 2010 15:13:28 +0100 Subject: [PATCH 18/35] ux500: Add prcmu support for operating points Adds support in PRCMU driver to handle CPU and APE operating points. Signed-off-by: Martin Persson Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/include/mach/prcmu-defs.h | 30 ++++ arch/arm/mach-ux500/include/mach/prcmu-regs.h | 15 +- arch/arm/mach-ux500/include/mach/prcmu.h | 14 +- arch/arm/mach-ux500/prcmu.c | 151 +++++++++++++++++- 4 files changed, 202 insertions(+), 8 deletions(-) create mode 100644 arch/arm/mach-ux500/include/mach/prcmu-defs.h diff --git a/arch/arm/mach-ux500/include/mach/prcmu-defs.h b/arch/arm/mach-ux500/include/mach/prcmu-defs.h new file mode 100644 index 000000000000..848ba64b561f --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/prcmu-defs.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Sundar Iyer + * Author: Martin Persson + * + * License Terms: GNU General Public License v2 + * + * PRCM Unit definitions + */ + +#ifndef __MACH_PRCMU_DEFS_H +#define __MACH_PRCMU_DEFS_H + +enum prcmu_cpu_opp { + CPU_OPP_INIT = 0x00, + CPU_OPP_NO_CHANGE = 0x01, + CPU_OPP_100 = 0x02, + CPU_OPP_50 = 0x03, + CPU_OPP_MAX = 0x04, + CPU_OPP_EXT_CLK = 0x07 +}; +enum prcmu_ape_opp { + APE_OPP_NO_CHANGE = 0x00, + APE_OPP_100 = 0x02, + APE_OPP_50 = 0x03, +}; + +#endif /* __MACH_PRCMU_DEFS_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h index 8885f39a6421..455467e88791 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h +++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h @@ -1,10 +1,15 @@ /* - * Copyright (c) 2009 ST-Ericsson SA + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. + * Author: Kumar Sanghvi + * Author: Sundar Iyer + * + * License Terms: GNU General Public License v2 + * + * PRCM Unit registers */ + #ifndef __MACH_PRCMU_REGS_H #define __MACH_PRCMU_REGS_H @@ -88,4 +93,4 @@ /* Miscellaneous unit registers */ #define PRCM_DSI_SW_RESET (_PRCMU_BASE + 0x324) -#endif /* __MACH_PRCMU__REGS_H */ +#endif /* __MACH_PRCMU_REGS_H */ diff --git a/arch/arm/mach-ux500/include/mach/prcmu.h b/arch/arm/mach-ux500/include/mach/prcmu.h index daa9d3ab7e0c..c49e456162ef 100644 --- a/arch/arm/mach-ux500/include/mach/prcmu.h +++ b/arch/arm/mach-ux500/include/mach/prcmu.h @@ -2,15 +2,27 @@ * Copyright (C) STMicroelectronics 2009 * Copyright (C) ST-Ericsson SA 2010 * + * Author: Kumar Sanghvi + * Author: Sundar Iyer + * Author: Mattias Nilsson + * * License Terms: GNU General Public License v2 * - * PRCMU f/w APIs + * PRCM Unit f/w API */ #ifndef __MACH_PRCMU_H #define __MACH_PRCMU_H +#include void __init prcmu_early_init(void); int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size); int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size); +int prcmu_set_ape_opp(enum prcmu_ape_opp opp); +int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp); +int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp, + enum prcmu_cpu_opp cpu_opp); +int prcmu_get_ape_opp(void); +int prcmu_get_cpu_opp(void); +bool prcmu_has_arm_maxopp(void); #endif /* __MACH_PRCMU_H */ diff --git a/arch/arm/mach-ux500/prcmu.c b/arch/arm/mach-ux500/prcmu.c index 07d5f13d2a4e..c522d26ef348 100644 --- a/arch/arm/mach-ux500/prcmu.c +++ b/arch/arm/mach-ux500/prcmu.c @@ -1,10 +1,14 @@ /* - * Copyright (C) ST Ericsson SA 2010 + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 * * License Terms: GNU General Public License v2 + * Author: Kumar Sanghvi + * Author: Sundar Iyer * Author: Mattias Nilsson * - * U8500 PRCMU driver. + * U8500 PRCM Unit interface driver + * */ #include #include @@ -19,13 +23,27 @@ #include #include +#include /* Global var to runtime determine TCDM base for v2 or v1 */ static __iomem void *tcdm_base; +#define _MBOX_HEADER (tcdm_base + 0xFE8) +#define MBOX_HEADER_REQ_MB0 (_MBOX_HEADER + 0x0) + +#define REQ_MB1 (tcdm_base + 0xFD0) #define REQ_MB5 (tcdm_base + 0xE44) + +#define REQ_MB1_ARMOPP (REQ_MB1 + 0x0) +#define REQ_MB1_APEOPP (REQ_MB1 + 0x1) +#define REQ_MB1_BOOSTOPP (REQ_MB1 + 0x2) + +#define ACK_MB1 (tcdm_base + 0xE04) #define ACK_MB5 (tcdm_base + 0xDF4) +#define ACK_MB1_CURR_ARMOPP (ACK_MB1 + 0x0) +#define ACK_MB1_CURR_APEOPP (ACK_MB1 + 0x1) + #define REQ_MB5_I2C_SLAVE_OP (REQ_MB5) #define REQ_MB5_I2C_HW_BITS (REQ_MB5 + 1) #define REQ_MB5_I2C_REG (REQ_MB5 + 2) @@ -34,12 +52,33 @@ static __iomem void *tcdm_base; #define ACK_MB5_I2C_STATUS (ACK_MB5 + 1) #define ACK_MB5_I2C_VAL (ACK_MB5 + 3) +#define PRCM_AVS_VARM_MAX_OPP (tcdm_base + 0x2E4) +#define PRCM_AVS_ISMODEENABLE 7 +#define PRCM_AVS_ISMODEENABLE_MASK (1 << PRCM_AVS_ISMODEENABLE) + #define I2C_WRITE(slave) \ (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0)) #define I2C_READ(slave) \ (((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0) | BIT(0)) #define I2C_STOP_EN BIT(3) +enum mb1_h { + MB1H_ARM_OPP = 1, + MB1H_APE_OPP, + MB1H_ARM_APE_OPP, +}; + +static struct { + struct mutex lock; + struct completion work; + struct { + u8 arm_opp; + u8 ape_opp; + u8 arm_status; + u8 ape_status; + } ack; +} mb1_transfer; + enum ack_mb5_status { I2C_WR_OK = 0x01, I2C_RD_OK = 0x02, @@ -148,6 +187,104 @@ unlock_and_return: } EXPORT_SYMBOL(prcmu_abb_write); +static int set_ape_cpu_opps(u8 header, enum prcmu_ape_opp ape_opp, + enum prcmu_cpu_opp cpu_opp) +{ + bool do_ape; + bool do_arm; + int err = 0; + + do_ape = ((header == MB1H_APE_OPP) || (header == MB1H_ARM_APE_OPP)); + do_arm = ((header == MB1H_ARM_OPP) || (header == MB1H_ARM_APE_OPP)); + + mutex_lock(&mb1_transfer.lock); + + while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1)) + cpu_relax(); + + writeb(0, MBOX_HEADER_REQ_MB0); + writeb(cpu_opp, REQ_MB1_ARMOPP); + writeb(ape_opp, REQ_MB1_APEOPP); + writeb(0, REQ_MB1_BOOSTOPP); + writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET); + wait_for_completion(&mb1_transfer.work); + if ((do_ape) && (mb1_transfer.ack.ape_status != 0)) + err = -EIO; + if ((do_arm) && (mb1_transfer.ack.arm_status != 0)) + err = -EIO; + + mutex_unlock(&mb1_transfer.lock); + + return err; +} + +/** + * prcmu_set_ape_opp() - Set the OPP of the APE. + * @opp: The OPP to set. + * + * This function sets the OPP of the APE. + */ +int prcmu_set_ape_opp(enum prcmu_ape_opp opp) +{ + return set_ape_cpu_opps(MB1H_APE_OPP, opp, APE_OPP_NO_CHANGE); +} +EXPORT_SYMBOL(prcmu_set_ape_opp); + +/** + * prcmu_set_cpu_opp() - Set the OPP of the CPU. + * @opp: The OPP to set. + * + * This function sets the OPP of the CPU. + */ +int prcmu_set_cpu_opp(enum prcmu_cpu_opp opp) +{ + return set_ape_cpu_opps(MB1H_ARM_OPP, CPU_OPP_NO_CHANGE, opp); +} +EXPORT_SYMBOL(prcmu_set_cpu_opp); + +/** + * prcmu_set_ape_cpu_opps() - Set the OPPs of the APE and the CPU. + * @ape_opp: The APE OPP to set. + * @cpu_opp: The CPU OPP to set. + * + * This function sets the OPPs of the APE and the CPU. + */ +int prcmu_set_ape_cpu_opps(enum prcmu_ape_opp ape_opp, + enum prcmu_cpu_opp cpu_opp) +{ + return set_ape_cpu_opps(MB1H_ARM_APE_OPP, ape_opp, cpu_opp); +} +EXPORT_SYMBOL(prcmu_set_ape_cpu_opps); + +/** + * prcmu_get_ape_opp() - Get the OPP of the APE. + * + * This function gets the OPP of the APE. + */ +enum prcmu_ape_opp prcmu_get_ape_opp(void) +{ + return readb(ACK_MB1_CURR_APEOPP); +} +EXPORT_SYMBOL(prcmu_get_ape_opp); + +/** + * prcmu_get_cpu_opp() - Get the OPP of the CPU. + * + * This function gets the OPP of the CPU. The OPP is specified in %%. + * PRCMU_OPP_EXT is a special OPP value, not specified in %%. + */ +int prcmu_get_cpu_opp(void) +{ + return readb(ACK_MB1_CURR_ARMOPP); +} +EXPORT_SYMBOL(prcmu_get_cpu_opp); + +bool prcmu_has_arm_maxopp(void) +{ + return (readb(PRCM_AVS_VARM_MAX_OPP) & PRCM_AVS_ISMODEENABLE_MASK) + == PRCM_AVS_ISMODEENABLE_MASK; +} + static void read_mailbox_0(void) { writel(MBOX_BIT(0), PRCM_ARM_IT1_CLEAR); @@ -155,6 +292,9 @@ static void read_mailbox_0(void) static void read_mailbox_1(void) { + mb1_transfer.ack.arm_opp = readb(ACK_MB1_CURR_ARMOPP); + mb1_transfer.ack.ape_opp = readb(ACK_MB1_CURR_APEOPP); + complete(&mb1_transfer.work); writel(MBOX_BIT(1), PRCM_ARM_IT1_CLEAR); } @@ -234,6 +374,13 @@ void __init prcmu_early_init(void) static int __init prcmu_init(void) { + if (cpu_is_u8500ed()) { + pr_err("prcmu: Unsupported chip version\n"); + return 0; + } + + mutex_init(&mb1_transfer.lock); + init_completion(&mb1_transfer.work); mutex_init(&mb5_transfer.lock); init_completion(&mb5_transfer.work); From 7c1a70e99819d723cde610d83de48a8ab01ec609 Mon Sep 17 00:00:00 2001 From: Martin Persson Date: Wed, 8 Dec 2010 15:13:42 +0100 Subject: [PATCH 19/35] ux500: Add cpufreq support for u8500 Signed-off-by: Martin Persson Signed-off-by: Linus Walleij --- arch/arm/Kconfig | 1 + arch/arm/mach-ux500/Makefile | 1 + arch/arm/mach-ux500/cpu-db8500.c | 1 + arch/arm/mach-ux500/cpufreq.c | 211 +++++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 arch/arm/mach-ux500/cpufreq.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db524e75c4a2..c8d035afcac7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -797,6 +797,7 @@ config ARCH_U8500 select GENERIC_CLOCKEVENTS select COMMON_CLKDEV select ARCH_REQUIRE_GPIOLIB + select ARCH_HAS_CPUFREQ help Support for ST-Ericsson's Ux500 architecture diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 93b0cf162017..841118335607 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem_irq.o obj-$(CONFIG_U5500_MBOX) += mbox.o +obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 658384c86933..c0f34a404c53 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -179,6 +179,7 @@ void __init u8500_init_devices(void) db8500_add_rtc(); db8500_add_gpios(); + platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); return ; diff --git a/arch/arm/mach-ux500/cpufreq.c b/arch/arm/mach-ux500/cpufreq.c new file mode 100644 index 000000000000..5c5b747f134d --- /dev/null +++ b/arch/arm/mach-ux500/cpufreq.c @@ -0,0 +1,211 @@ +/* + * CPU frequency scaling for u8500 + * Inspired by linux/arch/arm/mach-davinci/cpufreq.c + * + * Copyright (C) STMicroelectronics 2009 + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * + * Author: Sundar Iyer + * Author: Martin Persson + * Author: Jonas Aaberg + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#define DRIVER_NAME "cpufreq-u8500" +#define CPUFREQ_NAME "u8500" + +static struct device *dev; + +static struct cpufreq_frequency_table freq_table[] = { + [0] = { + .index = 0, + .frequency = 200000, + }, + [1] = { + .index = 1, + .frequency = 300000, + }, + [2] = { + .index = 2, + .frequency = 600000, + }, + [3] = { + /* Used for CPU_OPP_MAX, if available */ + .index = 3, + .frequency = CPUFREQ_TABLE_END, + }, + [4] = { + .index = 4, + .frequency = CPUFREQ_TABLE_END, + }, +}; + +static enum prcmu_cpu_opp index2opp[] = { + CPU_OPP_EXT_CLK, + CPU_OPP_50, + CPU_OPP_100, + CPU_OPP_MAX +}; + +static int u8500_cpufreq_verify_speed(struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, freq_table); +} + +static int u8500_cpufreq_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_freqs freqs; + unsigned int index; + int ret = 0; + + /* + * Ensure desired rate is within allowed range. Some govenors + * (ondemand) will just pass target_freq=0 to get the minimum. + */ + if (target_freq < policy->cpuinfo.min_freq) + target_freq = policy->cpuinfo.min_freq; + if (target_freq > policy->cpuinfo.max_freq) + target_freq = policy->cpuinfo.max_freq; + + ret = cpufreq_frequency_table_target(policy, freq_table, + target_freq, relation, &index); + if (ret < 0) { + dev_err(dev, "Could not look up next frequency\n"); + return ret; + } + + freqs.old = policy->cur; + freqs.new = freq_table[index].frequency; + freqs.cpu = policy->cpu; + + if (freqs.old == freqs.new) { + dev_dbg(dev, "Current and target frequencies are equal\n"); + return 0; + } + + dev_dbg(dev, "transition: %u --> %u\n", freqs.old, freqs.new); + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + ret = prcmu_set_cpu_opp(index2opp[index]); + if (ret < 0) { + dev_err(dev, "Failed to set OPP level\n"); + return ret; + } + + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return ret; +} + +static unsigned int u8500_cpufreq_getspeed(unsigned int cpu) +{ + int i; + + for (i = 0; prcmu_get_cpu_opp() != index2opp[i]; i++) + ; + return freq_table[i].frequency; +} + +static int __cpuinit u8500_cpu_init(struct cpufreq_policy *policy) +{ + int res; + + BUILD_BUG_ON(ARRAY_SIZE(index2opp) + 1 != ARRAY_SIZE(freq_table)); + + if (cpu_is_u8500v2()) { + freq_table[1].frequency = 400000; + freq_table[2].frequency = 800000; + if (prcmu_has_arm_maxopp()) + freq_table[3].frequency = 1000000; + } + + /* get policy fields based on the table */ + res = cpufreq_frequency_table_cpuinfo(policy, freq_table); + if (!res) + cpufreq_frequency_table_get_attr(freq_table, policy->cpu); + else { + dev_err(dev, "u8500-cpufreq : Failed to read policy table\n"); + return res; + } + + policy->min = policy->cpuinfo.min_freq; + policy->max = policy->cpuinfo.max_freq; + policy->cur = u8500_cpufreq_getspeed(policy->cpu); + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + /* + * FIXME : Need to take time measurement across the target() + * function with no/some/all drivers in the notification + * list. + */ + policy->cpuinfo.transition_latency = 200 * 1000; /* in ns */ + + /* policy sharing between dual CPUs */ + cpumask_copy(policy->cpus, &cpu_present_map); + + policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; + + return res; +} + +static struct freq_attr *u8500_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; +static int u8500_cpu_exit(struct cpufreq_policy *policy) +{ + cpufreq_frequency_table_put_attr(policy->cpu); + return 0; +} + +static struct cpufreq_driver u8500_driver = { + .owner = THIS_MODULE, + .flags = CPUFREQ_STICKY, + .verify = u8500_cpufreq_verify_speed, + .target = u8500_cpufreq_target, + .get = u8500_cpufreq_getspeed, + .init = u8500_cpu_init, + .exit = u8500_cpu_exit, + .name = CPUFREQ_NAME, + .attr = u8500_cpufreq_attr, +}; + +static int __init u8500_cpufreq_probe(struct platform_device *pdev) +{ + dev = &pdev->dev; + return cpufreq_register_driver(&u8500_driver); +} + +static int __exit u8500_cpufreq_remove(struct platform_device *pdev) +{ + return cpufreq_unregister_driver(&u8500_driver); +} + +static struct platform_driver u8500_cpufreq_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, + .remove = __exit_p(u8500_cpufreq_remove), +}; + +static int __init u8500_cpufreq_init(void) +{ + return platform_driver_probe(&u8500_cpufreq_driver, + &u8500_cpufreq_probe); +} + +device_initcall(u8500_cpufreq_init); From d5d228158e77998a1659c1783fb204f275fab93b Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Mon, 13 Dec 2010 09:33:11 +0530 Subject: [PATCH 20/35] mach-ux500: deprecate spi support for ab8500 Acked-by: Samuel Ortiz Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 36 +----------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 287956cebe8b..a8220c5a6a69 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -76,22 +76,6 @@ static pin_cfg_t mop500_pins[] = { GPIO217_GPIO, /* GPIO_EXP_INT */ }; -static void ab4500_spi_cs_control(u32 command) -{ - /* set the FRM signal, which is CS - TODO */ -} - -struct pl022_config_chip ab4500_chip_info = { - .com_mode = INTERRUPT_TRANSFER, - .iface = SSP_INTERFACE_MOTOROLA_SPI, - /* we can act as master only */ - .hierarchy = SSP_MASTER, - .slave_tx_disable = 0, - .rx_lev_trig = SSP_RX_1_OR_MORE_ELEM, - .tx_lev_trig = SSP_TX_1_OR_MORE_EMPTY_LOC, - .cs_control = ab4500_spi_cs_control, -}; - static struct ab8500_platform_data ab8500_platdata = { .irq_base = MOP500_AB8500_IRQ_BASE, }; @@ -114,19 +98,6 @@ struct platform_device ab8500_device = { .resource = ab8500_resources, }; -static struct spi_board_info ab8500_spi_devices[] = { - { - .modalias = "ab8500-spi", - .controller_data = &ab4500_chip_info, - .platform_data = &ab8500_platdata, - .max_speed_hz = 12000000, - .bus_num = 0, - .chip_select = 0, - .mode = SPI_MODE_3, - .irq = IRQ_DB8500_AB8500, - }, -}; - static struct pl022_ssp_controller ssp0_platform_data = { .bus_id = 0, /* pl022 not yet supports dma */ @@ -339,12 +310,7 @@ static void __init u8500_init_machine(void) mop500_spi_init(); mop500_uart_init(); - /* If HW is early drop (ED) or V1.0 then use SPI to access AB8500 */ - if (cpu_is_u8500ed() || cpu_is_u8500v10()) - spi_register_board_info(ab8500_spi_devices, - ARRAY_SIZE(ab8500_spi_devices)); - else /* If HW is v.1.1 or later use I2C to access AB8500 */ - platform_device_register(&ab8500_device); + platform_device_register(&ab8500_device); i2c_register_board_info(0, mop500_i2c0_devices, ARRAY_SIZE(mop500_i2c0_devices)); From c6eda6c5eeb357ff231121619fb49d2bc0605faf Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Mon, 13 Dec 2010 09:33:12 +0530 Subject: [PATCH 21/35] mfd/tc35892: rename tc35892 header to tc3589x Rename the header file to include further variants within the same mfd core driver Acked-by: Samuel Ortiz Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- drivers/gpio/tc35892-gpio.c | 2 +- drivers/mfd/tc35892.c | 2 +- include/linux/mfd/{tc35892.h => tc3589x.h} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename include/linux/mfd/{tc35892.h => tc3589x.h} (100%) diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c index 7e10c935a047..027b857c18ff 100644 --- a/drivers/gpio/tc35892-gpio.c +++ b/drivers/gpio/tc35892-gpio.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include /* * These registers are modified under the irq bus lock and cached to avoid diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index e619e2a55997..f230235c3765 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include /** * tc35892_reg_read() - read a single TC35892 register diff --git a/include/linux/mfd/tc35892.h b/include/linux/mfd/tc3589x.h similarity index 100% rename from include/linux/mfd/tc35892.h rename to include/linux/mfd/tc3589x.h From f4e8afdc7ab1b5a0962be02a9dd15d29a81f4c53 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Mon, 13 Dec 2010 09:33:13 +0530 Subject: [PATCH 22/35] mfd/tc35892: rename tc35892 core driver to tc3589x Rename the tc35892 core/gpio drivers to tc3589x to include new variants in the same mfd core Acked-by: Samuel Ortiz Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- drivers/gpio/Kconfig | 8 ++++---- drivers/gpio/Makefile | 2 +- drivers/gpio/{tc35892-gpio.c => tc3589x-gpio.c} | 0 drivers/mfd/Kconfig | 6 +++--- drivers/mfd/Makefile | 2 +- drivers/mfd/{tc35892.c => tc3589x.c} | 0 6 files changed, 9 insertions(+), 9 deletions(-) rename drivers/gpio/{tc35892-gpio.c => tc3589x-gpio.c} (100%) rename drivers/mfd/{tc35892.c => tc3589x.c} (100%) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3143ac795eb0..082495bb08a7 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -230,11 +230,11 @@ config GPIO_STMPE This enables support for the GPIOs found on the STMPE I/O Expanders. -config GPIO_TC35892 - bool "TC35892 GPIOs" - depends on MFD_TC35892 +config GPIO_TC3589X + bool "TC3589X GPIOs" + depends on MFD_TC3589X help - This enables support for the GPIOs found on the TC35892 + This enables support for the GPIOs found on the TC3589X I/O Expander. config GPIO_TWL4030 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index bdf3ddec0652..39bfd7a37650 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o obj-$(CONFIG_GPIO_PCH) += pch_gpio.o obj-$(CONFIG_GPIO_PL061) += pl061.o obj-$(CONFIG_GPIO_STMPE) += stmpe-gpio.o -obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o +obj-$(CONFIG_GPIO_TC3589X) += tc3589x-gpio.o obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc3589x-gpio.c similarity index 100% rename from drivers/gpio/tc35892-gpio.c rename to drivers/gpio/tc3589x-gpio.c diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3a1493b8b5e5..e8e704f52746 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -218,12 +218,12 @@ config MFD_STMPE Keypad: stmpe-keypad Touchscreen: stmpe-ts -config MFD_TC35892 - bool "Support Toshiba TC35892" +config MFD_TC3589X + bool "Support Toshiba TC35892 and variants" depends on I2C=y && GENERIC_HARDIRQS select MFD_CORE help - Support for the Toshiba TC35892 I/O Expander. + Support for the Toshiba TC35892 and variants I/O Expander. This driver provides common support for accessing the device, additional drivers must be enabled in order to use the diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f54b3659abbb..e590d1e44cf0 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o obj-$(CONFIG_MFD_STMPE) += stmpe.o -obj-$(CONFIG_MFD_TC35892) += tc35892.o +obj-$(CONFIG_MFD_TC3589X) += tc3589x.o obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc3589x.c similarity index 100% rename from drivers/mfd/tc35892.c rename to drivers/mfd/tc3589x.c From 20406ebff4a298e6e3abbc1717a90bb3e55dc820 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Mon, 13 Dec 2010 09:33:14 +0530 Subject: [PATCH 23/35] mfd/tc3589x: rename tc35892 structs/registers to tc359x Most of the register layout, client IRQ numbers on the TC35892 is shared also by other variants. Make this generic as tc3589x Acked-by: Samuel Ortiz Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 12 +- drivers/gpio/tc3589x-gpio.c | 268 ++++++++++++++--------------- drivers/mfd/tc3589x.c | 222 ++++++++++++------------ include/linux/mfd/tc3589x.h | 176 +++++++++---------- 4 files changed, 338 insertions(+), 340 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index a8220c5a6a69..5c950261968e 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -19,8 +19,7 @@ #include #include #include -#include -#include +#include #include #include @@ -112,24 +111,24 @@ static struct pl022_ssp_controller ssp0_platform_data = { * TC35892 */ -static void mop500_tc35892_init(struct tc35892 *tc35892, unsigned int base) +static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base) { mop500_sdi_tc35892_init(); } -static struct tc35892_gpio_platform_data mop500_tc35892_gpio_data = { +static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = { .gpio_base = MOP500_EGPIO(0), .setup = mop500_tc35892_init, }; -static struct tc35892_platform_data mop500_tc35892_data = { +static struct tc3589x_platform_data mop500_tc35892_data = { .gpio = &mop500_tc35892_gpio_data, .irq_base = MOP500_EGPIO_IRQ_BASE, }; static struct i2c_board_info mop500_i2c0_devices[] = { { - I2C_BOARD_INFO("tc35892", 0x42), + I2C_BOARD_INFO("tc3589x", 0x42), .irq = NOMADIK_GPIO_TO_IRQ(217), .platform_data = &mop500_tc35892_data, }, @@ -302,7 +301,6 @@ static void __init u8500_init_machine(void) nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins)); - ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board; platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); mop500_i2c_init(); diff --git a/drivers/gpio/tc3589x-gpio.c b/drivers/gpio/tc3589x-gpio.c index 027b857c18ff..180d584454fb 100644 --- a/drivers/gpio/tc3589x-gpio.c +++ b/drivers/gpio/tc3589x-gpio.c @@ -24,9 +24,9 @@ enum { REG_IBE, REG_IEV, REG_IS, REG_IE }; #define CACHE_NR_REGS 4 #define CACHE_NR_BANKS 3 -struct tc35892_gpio { +struct tc3589x_gpio { struct gpio_chip chip; - struct tc35892 *tc35892; + struct tc3589x *tc3589x; struct device *dev; struct mutex irq_lock; @@ -37,179 +37,179 @@ struct tc35892_gpio { u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; }; -static inline struct tc35892_gpio *to_tc35892_gpio(struct gpio_chip *chip) +static inline struct tc3589x_gpio *to_tc3589x_gpio(struct gpio_chip *chip) { - return container_of(chip, struct tc35892_gpio, chip); + return container_of(chip, struct tc3589x_gpio, chip); } -static int tc35892_gpio_get(struct gpio_chip *chip, unsigned offset) +static int tc3589x_gpio_get(struct gpio_chip *chip, unsigned offset) { - struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); - struct tc35892 *tc35892 = tc35892_gpio->tc35892; - u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2; + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; + u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; u8 mask = 1 << (offset % 8); int ret; - ret = tc35892_reg_read(tc35892, reg); + ret = tc3589x_reg_read(tc3589x, reg); if (ret < 0) return ret; return ret & mask; } -static void tc35892_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +static void tc3589x_gpio_set(struct gpio_chip *chip, unsigned offset, int val) { - struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); - struct tc35892 *tc35892 = tc35892_gpio->tc35892; - u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2; + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; + u8 reg = TC3589x_GPIODATA0 + (offset / 8) * 2; unsigned pos = offset % 8; u8 data[] = {!!val << pos, 1 << pos}; - tc35892_block_write(tc35892, reg, ARRAY_SIZE(data), data); + tc3589x_block_write(tc3589x, reg, ARRAY_SIZE(data), data); } -static int tc35892_gpio_direction_output(struct gpio_chip *chip, +static int tc3589x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int val) { - struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); - struct tc35892 *tc35892 = tc35892_gpio->tc35892; - u8 reg = TC35892_GPIODIR0 + offset / 8; + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; + u8 reg = TC3589x_GPIODIR0 + offset / 8; unsigned pos = offset % 8; - tc35892_gpio_set(chip, offset, val); + tc3589x_gpio_set(chip, offset, val); - return tc35892_set_bits(tc35892, reg, 1 << pos, 1 << pos); + return tc3589x_set_bits(tc3589x, reg, 1 << pos, 1 << pos); } -static int tc35892_gpio_direction_input(struct gpio_chip *chip, +static int tc3589x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) { - struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); - struct tc35892 *tc35892 = tc35892_gpio->tc35892; - u8 reg = TC35892_GPIODIR0 + offset / 8; + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; + u8 reg = TC3589x_GPIODIR0 + offset / 8; unsigned pos = offset % 8; - return tc35892_set_bits(tc35892, reg, 1 << pos, 0); + return tc3589x_set_bits(tc3589x, reg, 1 << pos, 0); } -static int tc35892_gpio_to_irq(struct gpio_chip *chip, unsigned offset) +static int tc3589x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) { - struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); + struct tc3589x_gpio *tc3589x_gpio = to_tc3589x_gpio(chip); - return tc35892_gpio->irq_base + offset; + return tc3589x_gpio->irq_base + offset; } static struct gpio_chip template_chip = { - .label = "tc35892", + .label = "tc3589x", .owner = THIS_MODULE, - .direction_input = tc35892_gpio_direction_input, - .get = tc35892_gpio_get, - .direction_output = tc35892_gpio_direction_output, - .set = tc35892_gpio_set, - .to_irq = tc35892_gpio_to_irq, + .direction_input = tc3589x_gpio_direction_input, + .get = tc3589x_gpio_get, + .direction_output = tc3589x_gpio_direction_output, + .set = tc3589x_gpio_set, + .to_irq = tc3589x_gpio_to_irq, .can_sleep = 1, }; -static int tc35892_gpio_irq_set_type(unsigned int irq, unsigned int type) +static int tc3589x_gpio_irq_set_type(unsigned int irq, unsigned int type) { - struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); - int offset = irq - tc35892_gpio->irq_base; + struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); + int offset = irq - tc3589x_gpio->irq_base; int regoffset = offset / 8; int mask = 1 << (offset % 8); if (type == IRQ_TYPE_EDGE_BOTH) { - tc35892_gpio->regs[REG_IBE][regoffset] |= mask; + tc3589x_gpio->regs[REG_IBE][regoffset] |= mask; return 0; } - tc35892_gpio->regs[REG_IBE][regoffset] &= ~mask; + tc3589x_gpio->regs[REG_IBE][regoffset] &= ~mask; if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) - tc35892_gpio->regs[REG_IS][regoffset] |= mask; + tc3589x_gpio->regs[REG_IS][regoffset] |= mask; else - tc35892_gpio->regs[REG_IS][regoffset] &= ~mask; + tc3589x_gpio->regs[REG_IS][regoffset] &= ~mask; if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) - tc35892_gpio->regs[REG_IEV][regoffset] |= mask; + tc3589x_gpio->regs[REG_IEV][regoffset] |= mask; else - tc35892_gpio->regs[REG_IEV][regoffset] &= ~mask; + tc3589x_gpio->regs[REG_IEV][regoffset] &= ~mask; return 0; } -static void tc35892_gpio_irq_lock(unsigned int irq) +static void tc3589x_gpio_irq_lock(unsigned int irq) { - struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); + struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); - mutex_lock(&tc35892_gpio->irq_lock); + mutex_lock(&tc3589x_gpio->irq_lock); } -static void tc35892_gpio_irq_sync_unlock(unsigned int irq) +static void tc3589x_gpio_irq_sync_unlock(unsigned int irq) { - struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); - struct tc35892 *tc35892 = tc35892_gpio->tc35892; + struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; static const u8 regmap[] = { - [REG_IBE] = TC35892_GPIOIBE0, - [REG_IEV] = TC35892_GPIOIEV0, - [REG_IS] = TC35892_GPIOIS0, - [REG_IE] = TC35892_GPIOIE0, + [REG_IBE] = TC3589x_GPIOIBE0, + [REG_IEV] = TC3589x_GPIOIEV0, + [REG_IS] = TC3589x_GPIOIS0, + [REG_IE] = TC3589x_GPIOIE0, }; int i, j; for (i = 0; i < CACHE_NR_REGS; i++) { for (j = 0; j < CACHE_NR_BANKS; j++) { - u8 old = tc35892_gpio->oldregs[i][j]; - u8 new = tc35892_gpio->regs[i][j]; + u8 old = tc3589x_gpio->oldregs[i][j]; + u8 new = tc3589x_gpio->regs[i][j]; if (new == old) continue; - tc35892_gpio->oldregs[i][j] = new; - tc35892_reg_write(tc35892, regmap[i] + j * 8, new); + tc3589x_gpio->oldregs[i][j] = new; + tc3589x_reg_write(tc3589x, regmap[i] + j * 8, new); } } - mutex_unlock(&tc35892_gpio->irq_lock); + mutex_unlock(&tc3589x_gpio->irq_lock); } -static void tc35892_gpio_irq_mask(unsigned int irq) +static void tc3589x_gpio_irq_mask(unsigned int irq) { - struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); - int offset = irq - tc35892_gpio->irq_base; + struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); + int offset = irq - tc3589x_gpio->irq_base; int regoffset = offset / 8; int mask = 1 << (offset % 8); - tc35892_gpio->regs[REG_IE][regoffset] &= ~mask; + tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask; } -static void tc35892_gpio_irq_unmask(unsigned int irq) +static void tc3589x_gpio_irq_unmask(unsigned int irq) { - struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); - int offset = irq - tc35892_gpio->irq_base; + struct tc3589x_gpio *tc3589x_gpio = get_irq_chip_data(irq); + int offset = irq - tc3589x_gpio->irq_base; int regoffset = offset / 8; int mask = 1 << (offset % 8); - tc35892_gpio->regs[REG_IE][regoffset] |= mask; + tc3589x_gpio->regs[REG_IE][regoffset] |= mask; } -static struct irq_chip tc35892_gpio_irq_chip = { - .name = "tc35892-gpio", - .bus_lock = tc35892_gpio_irq_lock, - .bus_sync_unlock = tc35892_gpio_irq_sync_unlock, - .mask = tc35892_gpio_irq_mask, - .unmask = tc35892_gpio_irq_unmask, - .set_type = tc35892_gpio_irq_set_type, +static struct irq_chip tc3589x_gpio_irq_chip = { + .name = "tc3589x-gpio", + .bus_lock = tc3589x_gpio_irq_lock, + .bus_sync_unlock = tc3589x_gpio_irq_sync_unlock, + .mask = tc3589x_gpio_irq_mask, + .unmask = tc3589x_gpio_irq_unmask, + .set_type = tc3589x_gpio_irq_set_type, }; -static irqreturn_t tc35892_gpio_irq(int irq, void *dev) +static irqreturn_t tc3589x_gpio_irq(int irq, void *dev) { - struct tc35892_gpio *tc35892_gpio = dev; - struct tc35892 *tc35892 = tc35892_gpio->tc35892; + struct tc3589x_gpio *tc3589x_gpio = dev; + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; u8 status[CACHE_NR_BANKS]; int ret; int i; - ret = tc35892_block_read(tc35892, TC35892_GPIOMIS0, + ret = tc3589x_block_read(tc3589x, TC3589x_GPIOMIS0, ARRAY_SIZE(status), status); if (ret < 0) return IRQ_NONE; @@ -223,24 +223,24 @@ static irqreturn_t tc35892_gpio_irq(int irq, void *dev) int bit = __ffs(stat); int line = i * 8 + bit; - handle_nested_irq(tc35892_gpio->irq_base + line); + handle_nested_irq(tc3589x_gpio->irq_base + line); stat &= ~(1 << bit); } - tc35892_reg_write(tc35892, TC35892_GPIOIC0 + i, status[i]); + tc3589x_reg_write(tc3589x, TC3589x_GPIOIC0 + i, status[i]); } return IRQ_HANDLED; } -static int tc35892_gpio_irq_init(struct tc35892_gpio *tc35892_gpio) +static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio) { - int base = tc35892_gpio->irq_base; + int base = tc3589x_gpio->irq_base; int irq; - for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) { - set_irq_chip_data(irq, tc35892_gpio); - set_irq_chip_and_handler(irq, &tc35892_gpio_irq_chip, + for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { + set_irq_chip_data(irq, tc3589x_gpio); + set_irq_chip_and_handler(irq, &tc3589x_gpio_irq_chip, handle_simple_irq); set_irq_nested_thread(irq, 1); #ifdef CONFIG_ARM @@ -253,12 +253,12 @@ static int tc35892_gpio_irq_init(struct tc35892_gpio *tc35892_gpio) return 0; } -static void tc35892_gpio_irq_remove(struct tc35892_gpio *tc35892_gpio) +static void tc3589x_gpio_irq_remove(struct tc3589x_gpio *tc3589x_gpio) { - int base = tc35892_gpio->irq_base; + int base = tc3589x_gpio->irq_base; int irq; - for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) { + for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) { #ifdef CONFIG_ARM set_irq_flags(irq, 0); #endif @@ -267,15 +267,15 @@ static void tc35892_gpio_irq_remove(struct tc35892_gpio *tc35892_gpio) } } -static int __devinit tc35892_gpio_probe(struct platform_device *pdev) +static int __devinit tc3589x_gpio_probe(struct platform_device *pdev) { - struct tc35892 *tc35892 = dev_get_drvdata(pdev->dev.parent); - struct tc35892_gpio_platform_data *pdata; - struct tc35892_gpio *tc35892_gpio; + struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); + struct tc3589x_gpio_platform_data *pdata; + struct tc3589x_gpio *tc3589x_gpio; int ret; int irq; - pdata = tc35892->pdata->gpio; + pdata = tc3589x->pdata->gpio; if (!pdata) return -ENODEV; @@ -283,107 +283,107 @@ static int __devinit tc35892_gpio_probe(struct platform_device *pdev) if (irq < 0) return irq; - tc35892_gpio = kzalloc(sizeof(struct tc35892_gpio), GFP_KERNEL); - if (!tc35892_gpio) + tc3589x_gpio = kzalloc(sizeof(struct tc3589x_gpio), GFP_KERNEL); + if (!tc3589x_gpio) return -ENOMEM; - mutex_init(&tc35892_gpio->irq_lock); + mutex_init(&tc3589x_gpio->irq_lock); - tc35892_gpio->dev = &pdev->dev; - tc35892_gpio->tc35892 = tc35892; + tc3589x_gpio->dev = &pdev->dev; + tc3589x_gpio->tc3589x = tc3589x; - tc35892_gpio->chip = template_chip; - tc35892_gpio->chip.ngpio = tc35892->num_gpio; - tc35892_gpio->chip.dev = &pdev->dev; - tc35892_gpio->chip.base = pdata->gpio_base; + tc3589x_gpio->chip = template_chip; + tc3589x_gpio->chip.ngpio = tc3589x->num_gpio; + tc3589x_gpio->chip.dev = &pdev->dev; + tc3589x_gpio->chip.base = pdata->gpio_base; - tc35892_gpio->irq_base = tc35892->irq_base + TC35892_INT_GPIO(0); + tc3589x_gpio->irq_base = tc3589x->irq_base + TC3589x_INT_GPIO(0); /* Bring the GPIO module out of reset */ - ret = tc35892_set_bits(tc35892, TC35892_RSTCTRL, - TC35892_RSTCTRL_GPIRST, 0); + ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, + TC3589x_RSTCTRL_GPIRST, 0); if (ret < 0) goto out_free; - ret = tc35892_gpio_irq_init(tc35892_gpio); + ret = tc3589x_gpio_irq_init(tc3589x_gpio); if (ret) goto out_free; - ret = request_threaded_irq(irq, NULL, tc35892_gpio_irq, IRQF_ONESHOT, - "tc35892-gpio", tc35892_gpio); + ret = request_threaded_irq(irq, NULL, tc3589x_gpio_irq, IRQF_ONESHOT, + "tc3589x-gpio", tc3589x_gpio); if (ret) { dev_err(&pdev->dev, "unable to get irq: %d\n", ret); goto out_removeirq; } - ret = gpiochip_add(&tc35892_gpio->chip); + ret = gpiochip_add(&tc3589x_gpio->chip); if (ret) { dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); goto out_freeirq; } if (pdata->setup) - pdata->setup(tc35892, tc35892_gpio->chip.base); + pdata->setup(tc3589x, tc3589x_gpio->chip.base); - platform_set_drvdata(pdev, tc35892_gpio); + platform_set_drvdata(pdev, tc3589x_gpio); return 0; out_freeirq: - free_irq(irq, tc35892_gpio); + free_irq(irq, tc3589x_gpio); out_removeirq: - tc35892_gpio_irq_remove(tc35892_gpio); + tc3589x_gpio_irq_remove(tc3589x_gpio); out_free: - kfree(tc35892_gpio); + kfree(tc3589x_gpio); return ret; } -static int __devexit tc35892_gpio_remove(struct platform_device *pdev) +static int __devexit tc3589x_gpio_remove(struct platform_device *pdev) { - struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev); - struct tc35892 *tc35892 = tc35892_gpio->tc35892; - struct tc35892_gpio_platform_data *pdata = tc35892->pdata->gpio; + struct tc3589x_gpio *tc3589x_gpio = platform_get_drvdata(pdev); + struct tc3589x *tc3589x = tc3589x_gpio->tc3589x; + struct tc3589x_gpio_platform_data *pdata = tc3589x->pdata->gpio; int irq = platform_get_irq(pdev, 0); int ret; if (pdata->remove) - pdata->remove(tc35892, tc35892_gpio->chip.base); + pdata->remove(tc3589x, tc3589x_gpio->chip.base); - ret = gpiochip_remove(&tc35892_gpio->chip); + ret = gpiochip_remove(&tc3589x_gpio->chip); if (ret < 0) { - dev_err(tc35892_gpio->dev, + dev_err(tc3589x_gpio->dev, "unable to remove gpiochip: %d\n", ret); return ret; } - free_irq(irq, tc35892_gpio); - tc35892_gpio_irq_remove(tc35892_gpio); + free_irq(irq, tc3589x_gpio); + tc3589x_gpio_irq_remove(tc3589x_gpio); platform_set_drvdata(pdev, NULL); - kfree(tc35892_gpio); + kfree(tc3589x_gpio); return 0; } -static struct platform_driver tc35892_gpio_driver = { - .driver.name = "tc35892-gpio", +static struct platform_driver tc3589x_gpio_driver = { + .driver.name = "tc3589x-gpio", .driver.owner = THIS_MODULE, - .probe = tc35892_gpio_probe, - .remove = __devexit_p(tc35892_gpio_remove), + .probe = tc3589x_gpio_probe, + .remove = __devexit_p(tc3589x_gpio_remove), }; -static int __init tc35892_gpio_init(void) +static int __init tc3589x_gpio_init(void) { - return platform_driver_register(&tc35892_gpio_driver); + return platform_driver_register(&tc3589x_gpio_driver); } -subsys_initcall(tc35892_gpio_init); +subsys_initcall(tc3589x_gpio_init); -static void __exit tc35892_gpio_exit(void) +static void __exit tc3589x_gpio_exit(void) { - platform_driver_unregister(&tc35892_gpio_driver); + platform_driver_unregister(&tc3589x_gpio_driver); } -module_exit(tc35892_gpio_exit); +module_exit(tc3589x_gpio_exit); MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("TC35892 GPIO driver"); +MODULE_DESCRIPTION("TC3589x GPIO driver"); MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index f230235c3765..7deff53181d1 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -15,141 +15,141 @@ #include /** - * tc35892_reg_read() - read a single TC35892 register - * @tc35892: Device to read from + * tc3589x_reg_read() - read a single TC3589x register + * @tc3589x: Device to read from * @reg: Register to read */ -int tc35892_reg_read(struct tc35892 *tc35892, u8 reg) +int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg) { int ret; - ret = i2c_smbus_read_byte_data(tc35892->i2c, reg); + ret = i2c_smbus_read_byte_data(tc3589x->i2c, reg); if (ret < 0) - dev_err(tc35892->dev, "failed to read reg %#x: %d\n", + dev_err(tc3589x->dev, "failed to read reg %#x: %d\n", reg, ret); return ret; } -EXPORT_SYMBOL_GPL(tc35892_reg_read); +EXPORT_SYMBOL_GPL(tc3589x_reg_read); /** - * tc35892_reg_read() - write a single TC35892 register - * @tc35892: Device to write to + * tc3589x_reg_read() - write a single TC3589x register + * @tc3589x: Device to write to * @reg: Register to read * @data: Value to write */ -int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data) +int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data) { int ret; - ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data); + ret = i2c_smbus_write_byte_data(tc3589x->i2c, reg, data); if (ret < 0) - dev_err(tc35892->dev, "failed to write reg %#x: %d\n", + dev_err(tc3589x->dev, "failed to write reg %#x: %d\n", reg, ret); return ret; } -EXPORT_SYMBOL_GPL(tc35892_reg_write); +EXPORT_SYMBOL_GPL(tc3589x_reg_write); /** - * tc35892_block_read() - read multiple TC35892 registers - * @tc35892: Device to read from + * tc3589x_block_read() - read multiple TC3589x registers + * @tc3589x: Device to read from * @reg: First register * @length: Number of registers * @values: Buffer to write to */ -int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values) +int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values) { int ret; - ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values); + ret = i2c_smbus_read_i2c_block_data(tc3589x->i2c, reg, length, values); if (ret < 0) - dev_err(tc35892->dev, "failed to read regs %#x: %d\n", + dev_err(tc3589x->dev, "failed to read regs %#x: %d\n", reg, ret); return ret; } -EXPORT_SYMBOL_GPL(tc35892_block_read); +EXPORT_SYMBOL_GPL(tc3589x_block_read); /** - * tc35892_block_write() - write multiple TC35892 registers - * @tc35892: Device to write to + * tc3589x_block_write() - write multiple TC3589x registers + * @tc3589x: Device to write to * @reg: First register * @length: Number of registers * @values: Values to write */ -int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length, +int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, const u8 *values) { int ret; - ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length, + ret = i2c_smbus_write_i2c_block_data(tc3589x->i2c, reg, length, values); if (ret < 0) - dev_err(tc35892->dev, "failed to write regs %#x: %d\n", + dev_err(tc3589x->dev, "failed to write regs %#x: %d\n", reg, ret); return ret; } -EXPORT_SYMBOL_GPL(tc35892_block_write); +EXPORT_SYMBOL_GPL(tc3589x_block_write); /** - * tc35892_set_bits() - set the value of a bitfield in a TC35892 register - * @tc35892: Device to write to + * tc3589x_set_bits() - set the value of a bitfield in a TC3589x register + * @tc3589x: Device to write to * @reg: Register to write * @mask: Mask of bits to set * @values: Value to set */ -int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val) +int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val) { int ret; - mutex_lock(&tc35892->lock); + mutex_lock(&tc3589x->lock); - ret = tc35892_reg_read(tc35892, reg); + ret = tc3589x_reg_read(tc3589x, reg); if (ret < 0) goto out; ret &= ~mask; ret |= val; - ret = tc35892_reg_write(tc35892, reg, ret); + ret = tc3589x_reg_write(tc3589x, reg, ret); out: - mutex_unlock(&tc35892->lock); + mutex_unlock(&tc3589x->lock); return ret; } -EXPORT_SYMBOL_GPL(tc35892_set_bits); +EXPORT_SYMBOL_GPL(tc3589x_set_bits); static struct resource gpio_resources[] = { { - .start = TC35892_INT_GPIIRQ, - .end = TC35892_INT_GPIIRQ, + .start = TC3589x_INT_GPIIRQ, + .end = TC3589x_INT_GPIIRQ, .flags = IORESOURCE_IRQ, }, }; -static struct mfd_cell tc35892_devs[] = { +static struct mfd_cell tc3589x_devs[] = { { - .name = "tc35892-gpio", + .name = "tc3589x-gpio", .num_resources = ARRAY_SIZE(gpio_resources), .resources = &gpio_resources[0], }, }; -static irqreturn_t tc35892_irq(int irq, void *data) +static irqreturn_t tc3589x_irq(int irq, void *data) { - struct tc35892 *tc35892 = data; + struct tc3589x *tc3589x = data; int status; - status = tc35892_reg_read(tc35892, TC35892_IRQST); + status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); if (status < 0) return IRQ_NONE; while (status) { int bit = __ffs(status); - handle_nested_irq(tc35892->irq_base + bit); + handle_nested_irq(tc3589x->irq_base + bit); status &= ~(1 << bit); } @@ -158,30 +158,30 @@ static irqreturn_t tc35892_irq(int irq, void *data) * have the last interrupt clear (for example, GPIO IC write) take * effect. */ - tc35892_reg_read(tc35892, TC35892_IRQST); + tc3589x_reg_read(tc3589x, TC3589x_IRQST); return IRQ_HANDLED; } -static void tc35892_irq_dummy(unsigned int irq) +static void tc3589x_irq_dummy(unsigned int irq) { /* No mask/unmask at this level */ } -static struct irq_chip tc35892_irq_chip = { - .name = "tc35892", - .mask = tc35892_irq_dummy, - .unmask = tc35892_irq_dummy, +static struct irq_chip tc3589x_irq_chip = { + .name = "tc3589x", + .mask = tc3589x_irq_dummy, + .unmask = tc3589x_irq_dummy, }; -static int tc35892_irq_init(struct tc35892 *tc35892) +static int tc3589x_irq_init(struct tc3589x *tc3589x) { - int base = tc35892->irq_base; + int base = tc3589x->irq_base; int irq; - for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { - set_irq_chip_data(irq, tc35892); - set_irq_chip_and_handler(irq, &tc35892_irq_chip, + for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { + set_irq_chip_data(irq, tc3589x); + set_irq_chip_and_handler(irq, &tc3589x_irq_chip, handle_edge_irq); set_irq_nested_thread(irq, 1); #ifdef CONFIG_ARM @@ -194,12 +194,12 @@ static int tc35892_irq_init(struct tc35892 *tc35892) return 0; } -static void tc35892_irq_remove(struct tc35892 *tc35892) +static void tc3589x_irq_remove(struct tc3589x *tc3589x) { - int base = tc35892->irq_base; + int base = tc3589x->irq_base; int irq; - for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { + for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { #ifdef CONFIG_ARM set_irq_flags(irq, 0); #endif @@ -208,138 +208,138 @@ static void tc35892_irq_remove(struct tc35892 *tc35892) } } -static int tc35892_chip_init(struct tc35892 *tc35892) +static int tc3589x_chip_init(struct tc3589x *tc3589x) { int manf, ver, ret; - manf = tc35892_reg_read(tc35892, TC35892_MANFCODE); + manf = tc3589x_reg_read(tc3589x, TC3589x_MANFCODE); if (manf < 0) return manf; - ver = tc35892_reg_read(tc35892, TC35892_VERSION); + ver = tc3589x_reg_read(tc3589x, TC3589x_VERSION); if (ver < 0) return ver; - if (manf != TC35892_MANFCODE_MAGIC) { - dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf); + if (manf != TC3589x_MANFCODE_MAGIC) { + dev_err(tc3589x->dev, "unknown manufacturer: %#x\n", manf); return -EINVAL; } - dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver); + dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver); /* Put everything except the IRQ module into reset */ - ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL, - TC35892_RSTCTRL_TIMRST - | TC35892_RSTCTRL_ROTRST - | TC35892_RSTCTRL_KBDRST - | TC35892_RSTCTRL_GPIRST); + ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL, + TC3589x_RSTCTRL_TIMRST + | TC3589x_RSTCTRL_ROTRST + | TC3589x_RSTCTRL_KBDRST + | TC3589x_RSTCTRL_GPIRST); if (ret < 0) return ret; /* Clear the reset interrupt. */ - return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1); + return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1); } -static int __devinit tc35892_probe(struct i2c_client *i2c, +static int __devinit tc3589x_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct tc35892_platform_data *pdata = i2c->dev.platform_data; - struct tc35892 *tc35892; + struct tc3589x_platform_data *pdata = i2c->dev.platform_data; + struct tc3589x *tc3589x; int ret; if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) return -EIO; - tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL); - if (!tc35892) + tc3589x = kzalloc(sizeof(struct tc3589x), GFP_KERNEL); + if (!tc3589x) return -ENOMEM; - mutex_init(&tc35892->lock); + mutex_init(&tc3589x->lock); - tc35892->dev = &i2c->dev; - tc35892->i2c = i2c; - tc35892->pdata = pdata; - tc35892->irq_base = pdata->irq_base; - tc35892->num_gpio = id->driver_data; + tc3589x->dev = &i2c->dev; + tc3589x->i2c = i2c; + tc3589x->pdata = pdata; + tc3589x->irq_base = pdata->irq_base; + tc3589x->num_gpio = id->driver_data; - i2c_set_clientdata(i2c, tc35892); + i2c_set_clientdata(i2c, tc3589x); - ret = tc35892_chip_init(tc35892); + ret = tc3589x_chip_init(tc3589x); if (ret) goto out_free; - ret = tc35892_irq_init(tc35892); + ret = tc3589x_irq_init(tc3589x); if (ret) goto out_free; - ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq, + ret = request_threaded_irq(tc3589x->i2c->irq, NULL, tc3589x_irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "tc35892", tc35892); + "tc3589x", tc3589x); if (ret) { - dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret); + dev_err(tc3589x->dev, "failed to request IRQ: %d\n", ret); goto out_removeirq; } - ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs, - ARRAY_SIZE(tc35892_devs), NULL, - tc35892->irq_base); + ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_devs, + ARRAY_SIZE(tc3589x_devs), NULL, + tc3589x->irq_base); if (ret) { - dev_err(tc35892->dev, "failed to add children\n"); + dev_err(tc3589x->dev, "failed to add children\n"); goto out_freeirq; } return 0; out_freeirq: - free_irq(tc35892->i2c->irq, tc35892); + free_irq(tc3589x->i2c->irq, tc3589x); out_removeirq: - tc35892_irq_remove(tc35892); + tc3589x_irq_remove(tc3589x); out_free: - kfree(tc35892); + kfree(tc3589x); return ret; } -static int __devexit tc35892_remove(struct i2c_client *client) +static int __devexit tc3589x_remove(struct i2c_client *client) { - struct tc35892 *tc35892 = i2c_get_clientdata(client); + struct tc3589x *tc3589x = i2c_get_clientdata(client); - mfd_remove_devices(tc35892->dev); + mfd_remove_devices(tc3589x->dev); - free_irq(tc35892->i2c->irq, tc35892); - tc35892_irq_remove(tc35892); + free_irq(tc3589x->i2c->irq, tc3589x); + tc3589x_irq_remove(tc3589x); - kfree(tc35892); + kfree(tc3589x); return 0; } -static const struct i2c_device_id tc35892_id[] = { - { "tc35892", 24 }, +static const struct i2c_device_id tc3589x_id[] = { + { "tc3589x", 24 }, { } }; -MODULE_DEVICE_TABLE(i2c, tc35892_id); +MODULE_DEVICE_TABLE(i2c, tc3589x_id); -static struct i2c_driver tc35892_driver = { - .driver.name = "tc35892", +static struct i2c_driver tc3589x_driver = { + .driver.name = "tc3589x", .driver.owner = THIS_MODULE, - .probe = tc35892_probe, - .remove = __devexit_p(tc35892_remove), - .id_table = tc35892_id, + .probe = tc3589x_probe, + .remove = __devexit_p(tc3589x_remove), + .id_table = tc3589x_id, }; -static int __init tc35892_init(void) +static int __init tc3589x_init(void) { - return i2c_add_driver(&tc35892_driver); + return i2c_add_driver(&tc3589x_driver); } -subsys_initcall(tc35892_init); +subsys_initcall(tc3589x_init); -static void __exit tc35892_exit(void) +static void __exit tc3589x_exit(void) { - i2c_del_driver(&tc35892_driver); + i2c_del_driver(&tc3589x_driver); } -module_exit(tc35892_exit); +module_exit(tc3589x_exit); MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("TC35892 MFD core driver"); +MODULE_DESCRIPTION("TC3589x MFD core driver"); MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h index eff3094ca84e..ea1918896f5b 100644 --- a/include/linux/mfd/tc3589x.h +++ b/include/linux/mfd/tc3589x.h @@ -4,133 +4,133 @@ * License Terms: GNU General Public License, version 2 */ -#ifndef __LINUX_MFD_TC35892_H -#define __LINUX_MFD_TC35892_H +#ifndef __LINUX_MFD_TC3589x_H +#define __LINUX_MFD_TC3589x_H #include -#define TC35892_RSTCTRL_IRQRST (1 << 4) -#define TC35892_RSTCTRL_TIMRST (1 << 3) -#define TC35892_RSTCTRL_ROTRST (1 << 2) -#define TC35892_RSTCTRL_KBDRST (1 << 1) -#define TC35892_RSTCTRL_GPIRST (1 << 0) +#define TC3589x_RSTCTRL_IRQRST (1 << 4) +#define TC3589x_RSTCTRL_TIMRST (1 << 3) +#define TC3589x_RSTCTRL_ROTRST (1 << 2) +#define TC3589x_RSTCTRL_KBDRST (1 << 1) +#define TC3589x_RSTCTRL_GPIRST (1 << 0) -#define TC35892_IRQST 0x91 +#define TC3589x_IRQST 0x91 -#define TC35892_MANFCODE_MAGIC 0x03 -#define TC35892_MANFCODE 0x80 -#define TC35892_VERSION 0x81 -#define TC35892_IOCFG 0xA7 +#define TC3589x_MANFCODE_MAGIC 0x03 +#define TC3589x_MANFCODE 0x80 +#define TC3589x_VERSION 0x81 +#define TC3589x_IOCFG 0xA7 -#define TC35892_CLKMODE 0x88 -#define TC35892_CLKCFG 0x89 -#define TC35892_CLKEN 0x8A +#define TC3589x_CLKMODE 0x88 +#define TC3589x_CLKCFG 0x89 +#define TC3589x_CLKEN 0x8A -#define TC35892_RSTCTRL 0x82 -#define TC35892_EXTRSTN 0x83 -#define TC35892_RSTINTCLR 0x84 +#define TC3589x_RSTCTRL 0x82 +#define TC3589x_EXTRSTN 0x83 +#define TC3589x_RSTINTCLR 0x84 -#define TC35892_GPIOIS0 0xC9 -#define TC35892_GPIOIS1 0xCA -#define TC35892_GPIOIS2 0xCB -#define TC35892_GPIOIBE0 0xCC -#define TC35892_GPIOIBE1 0xCD -#define TC35892_GPIOIBE2 0xCE -#define TC35892_GPIOIEV0 0xCF -#define TC35892_GPIOIEV1 0xD0 -#define TC35892_GPIOIEV2 0xD1 -#define TC35892_GPIOIE0 0xD2 -#define TC35892_GPIOIE1 0xD3 -#define TC35892_GPIOIE2 0xD4 -#define TC35892_GPIORIS0 0xD6 -#define TC35892_GPIORIS1 0xD7 -#define TC35892_GPIORIS2 0xD8 -#define TC35892_GPIOMIS0 0xD9 -#define TC35892_GPIOMIS1 0xDA -#define TC35892_GPIOMIS2 0xDB -#define TC35892_GPIOIC0 0xDC -#define TC35892_GPIOIC1 0xDD -#define TC35892_GPIOIC2 0xDE +#define TC3589x_GPIOIS0 0xC9 +#define TC3589x_GPIOIS1 0xCA +#define TC3589x_GPIOIS2 0xCB +#define TC3589x_GPIOIBE0 0xCC +#define TC3589x_GPIOIBE1 0xCD +#define TC3589x_GPIOIBE2 0xCE +#define TC3589x_GPIOIEV0 0xCF +#define TC3589x_GPIOIEV1 0xD0 +#define TC3589x_GPIOIEV2 0xD1 +#define TC3589x_GPIOIE0 0xD2 +#define TC3589x_GPIOIE1 0xD3 +#define TC3589x_GPIOIE2 0xD4 +#define TC3589x_GPIORIS0 0xD6 +#define TC3589x_GPIORIS1 0xD7 +#define TC3589x_GPIORIS2 0xD8 +#define TC3589x_GPIOMIS0 0xD9 +#define TC3589x_GPIOMIS1 0xDA +#define TC3589x_GPIOMIS2 0xDB +#define TC3589x_GPIOIC0 0xDC +#define TC3589x_GPIOIC1 0xDD +#define TC3589x_GPIOIC2 0xDE -#define TC35892_GPIODATA0 0xC0 -#define TC35892_GPIOMASK0 0xc1 -#define TC35892_GPIODATA1 0xC2 -#define TC35892_GPIOMASK1 0xc3 -#define TC35892_GPIODATA2 0xC4 -#define TC35892_GPIOMASK2 0xC5 +#define TC3589x_GPIODATA0 0xC0 +#define TC3589x_GPIOMASK0 0xc1 +#define TC3589x_GPIODATA1 0xC2 +#define TC3589x_GPIOMASK1 0xc3 +#define TC3589x_GPIODATA2 0xC4 +#define TC3589x_GPIOMASK2 0xC5 -#define TC35892_GPIODIR0 0xC6 -#define TC35892_GPIODIR1 0xC7 -#define TC35892_GPIODIR2 0xC8 +#define TC3589x_GPIODIR0 0xC6 +#define TC3589x_GPIODIR1 0xC7 +#define TC3589x_GPIODIR2 0xC8 -#define TC35892_GPIOSYNC0 0xE6 -#define TC35892_GPIOSYNC1 0xE7 -#define TC35892_GPIOSYNC2 0xE8 +#define TC3589x_GPIOSYNC0 0xE6 +#define TC3589x_GPIOSYNC1 0xE7 +#define TC3589x_GPIOSYNC2 0xE8 -#define TC35892_GPIOWAKE0 0xE9 -#define TC35892_GPIOWAKE1 0xEA -#define TC35892_GPIOWAKE2 0xEB +#define TC3589x_GPIOWAKE0 0xE9 +#define TC3589x_GPIOWAKE1 0xEA +#define TC3589x_GPIOWAKE2 0xEB -#define TC35892_GPIOODM0 0xE0 -#define TC35892_GPIOODE0 0xE1 -#define TC35892_GPIOODM1 0xE2 -#define TC35892_GPIOODE1 0xE3 -#define TC35892_GPIOODM2 0xE4 -#define TC35892_GPIOODE2 0xE5 +#define TC3589x_GPIOODM0 0xE0 +#define TC3589x_GPIOODE0 0xE1 +#define TC3589x_GPIOODM1 0xE2 +#define TC3589x_GPIOODE1 0xE3 +#define TC3589x_GPIOODM2 0xE4 +#define TC3589x_GPIOODE2 0xE5 -#define TC35892_INT_GPIIRQ 0 -#define TC35892_INT_TI0IRQ 1 -#define TC35892_INT_TI1IRQ 2 -#define TC35892_INT_TI2IRQ 3 -#define TC35892_INT_ROTIRQ 5 -#define TC35892_INT_KBDIRQ 6 -#define TC35892_INT_PORIRQ 7 +#define TC3589x_INT_GPIIRQ 0 +#define TC3589x_INT_TI0IRQ 1 +#define TC3589x_INT_TI1IRQ 2 +#define TC3589x_INT_TI2IRQ 3 +#define TC3589x_INT_ROTIRQ 5 +#define TC3589x_INT_KBDIRQ 6 +#define TC3589x_INT_PORIRQ 7 -#define TC35892_NR_INTERNAL_IRQS 8 -#define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x)) +#define TC3589x_NR_INTERNAL_IRQS 8 +#define TC3589x_INT_GPIO(x) (TC3589x_NR_INTERNAL_IRQS + (x)) -struct tc35892 { +struct tc3589x { struct mutex lock; struct device *dev; struct i2c_client *i2c; int irq_base; int num_gpio; - struct tc35892_platform_data *pdata; + struct tc3589x_platform_data *pdata; }; -extern int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data); -extern int tc35892_reg_read(struct tc35892 *tc35892, u8 reg); -extern int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, +extern int tc3589x_reg_write(struct tc3589x *tc3589x, u8 reg, u8 data); +extern int tc3589x_reg_read(struct tc3589x *tc3589x, u8 reg); +extern int tc3589x_block_read(struct tc3589x *tc3589x, u8 reg, u8 length, u8 *values); -extern int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length, +extern int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, const u8 *values); -extern int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val); +extern int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val); /** - * struct tc35892_gpio_platform_data - TC35892 GPIO platform data - * @gpio_base: first gpio number assigned to TC35892. A maximum of - * %TC35892_NR_GPIOS GPIOs will be allocated. + * struct tc3589x_gpio_platform_data - TC3589x GPIO platform data + * @gpio_base: first gpio number assigned to TC3589x. A maximum of + * %TC3589x_NR_GPIOS GPIOs will be allocated. * @setup: callback for board-specific initialization * @remove: callback for board-specific teardown */ -struct tc35892_gpio_platform_data { +struct tc3589x_gpio_platform_data { int gpio_base; - void (*setup)(struct tc35892 *tc35892, unsigned gpio_base); - void (*remove)(struct tc35892 *tc35892, unsigned gpio_base); + void (*setup)(struct tc3589x *tc3589x, unsigned gpio_base); + void (*remove)(struct tc3589x *tc3589x, unsigned gpio_base); }; /** - * struct tc35892_platform_data - TC35892 platform data - * @irq_base: base IRQ number. %TC35892_NR_IRQS irqs will be used. + * struct tc3589x_platform_data - TC3589x platform data + * @irq_base: base IRQ number. %TC3589x_NR_IRQS irqs will be used. * @gpio: GPIO-specific platform data */ -struct tc35892_platform_data { +struct tc3589x_platform_data { int irq_base; - struct tc35892_gpio_platform_data *gpio; + struct tc3589x_gpio_platform_data *gpio; }; -#define TC35892_NR_GPIOS 24 -#define TC35892_NR_IRQS TC35892_INT_GPIO(TC35892_NR_GPIOS) +#define TC3589x_NR_GPIOS 24 +#define TC3589x_NR_IRQS TC3589x_INT_GPIO(TC3589x_NR_GPIOS) #endif From 611b7590afa6e6c6b0942b1d3efef17fbb348ef5 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Mon, 13 Dec 2010 09:33:15 +0530 Subject: [PATCH 24/35] mfd/tc3589x: add block identifier for multiple child devices Add block identifier to be able to add multiple mfd clients to the mfd core Acked-by: Samuel Ortiz Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 1 + drivers/mfd/tc3589x.c | 28 +++++++++++++++++++++++----- include/linux/mfd/tc3589x.h | 7 +++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 5c950261968e..060b23aab8e4 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -122,6 +122,7 @@ static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = { }; static struct tc3589x_platform_data mop500_tc35892_data = { + .block = TC3589x_BLOCK_GPIO, .gpio = &mop500_tc35892_gpio_data, .irq_base = MOP500_EGPIO_IRQ_BASE, }; diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 7deff53181d1..0ed9669d95fa 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -129,7 +129,7 @@ static struct resource gpio_resources[] = { }, }; -static struct mfd_cell tc3589x_devs[] = { +static struct mfd_cell tc3589x_dev_gpio[] = { { .name = "tc3589x-gpio", .num_resources = ARRAY_SIZE(gpio_resources), @@ -240,6 +240,26 @@ static int tc3589x_chip_init(struct tc3589x *tc3589x) return tc3589x_reg_write(tc3589x, TC3589x_RSTINTCLR, 0x1); } +static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) +{ + int ret = 0; + unsigned int blocks = tc3589x->pdata->block; + + if (blocks & TC3589x_BLOCK_GPIO) { + ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio, + ARRAY_SIZE(tc3589x_dev_gpio), NULL, + tc3589x->irq_base); + if (ret) { + dev_err(tc3589x->dev, "failed to add gpio child\n"); + return ret; + } + dev_info(tc3589x->dev, "added gpio block\n"); + } + + return ret; + +} + static int __devinit tc3589x_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -281,11 +301,9 @@ static int __devinit tc3589x_probe(struct i2c_client *i2c, goto out_removeirq; } - ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_devs, - ARRAY_SIZE(tc3589x_devs), NULL, - tc3589x->irq_base); + ret = tc3589x_device_init(tc3589x); if (ret) { - dev_err(tc3589x->dev, "failed to add children\n"); + dev_err(tc3589x->dev, "failed to add child devices\n"); goto out_freeirq; } diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h index ea1918896f5b..da00958b12d9 100644 --- a/include/linux/mfd/tc3589x.h +++ b/include/linux/mfd/tc3589x.h @@ -9,6 +9,11 @@ #include +enum tx3589x_block { + TC3589x_BLOCK_GPIO = 1 << 0, + TC3589x_BLOCK_KEYPAD = 1 << 1, +}; + #define TC3589x_RSTCTRL_IRQRST (1 << 4) #define TC3589x_RSTCTRL_TIMRST (1 << 3) #define TC3589x_RSTCTRL_ROTRST (1 << 2) @@ -122,10 +127,12 @@ struct tc3589x_gpio_platform_data { /** * struct tc3589x_platform_data - TC3589x platform data + * @block: bitmask of blocks to enable (use TC3589x_BLOCK_*) * @irq_base: base IRQ number. %TC3589x_NR_IRQS irqs will be used. * @gpio: GPIO-specific platform data */ struct tc3589x_platform_data { + unsigned int block; int irq_base; struct tc3589x_gpio_platform_data *gpio; }; From bd77efd0cea80865d4cfcc1e4b62789c51a74b2d Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Mon, 13 Dec 2010 09:33:16 +0530 Subject: [PATCH 25/35] mfd/tc3589x: fix random interrupt misses On the TC35892, a random delayed interrupt clear (GPIO IC) write locks up the child interrupts. In such a case, the original interrupt is active and not yet acknowledged. Re-check the IRQST bit for any pending interrupts and handle those. Acked-by: Samuel Ortiz Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- drivers/mfd/tc3589x.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 0ed9669d95fa..708349a5c0e3 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -142,6 +142,7 @@ static irqreturn_t tc3589x_irq(int irq, void *data) struct tc3589x *tc3589x = data; int status; +again: status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); if (status < 0) return IRQ_NONE; @@ -156,9 +157,12 @@ static irqreturn_t tc3589x_irq(int irq, void *data) /* * A dummy read or write (to any register) appears to be necessary to * have the last interrupt clear (for example, GPIO IC write) take - * effect. + * effect. In such a case, recheck for any interrupt which is still + * pending. */ - tc3589x_reg_read(tc3589x, TC3589x_IRQST); + status = tc3589x_reg_read(tc3589x, TC3589x_IRQST); + if (status) + goto again; return IRQ_HANDLED; } From 523bc3820f023169671e9726b8dc075669d14bec Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Mon, 13 Dec 2010 09:33:17 +0530 Subject: [PATCH 26/35] mfd/tc3589x: undo gpio module reset during chip init Skip putting the GPIO module into a reset during the chip init. This makes sure to preserve any existing GPIO configurations done by pre-kernel boot code. Acked-by: Samuel Ortiz Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- drivers/mfd/tc3589x.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 708349a5c0e3..f000d2ed23e0 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -231,12 +231,15 @@ static int tc3589x_chip_init(struct tc3589x *tc3589x) dev_info(tc3589x->dev, "manufacturer: %#x, version: %#x\n", manf, ver); - /* Put everything except the IRQ module into reset */ + /* + * Put everything except the IRQ module into reset; + * also spare the GPIO module for any pin initialization + * done during pre-kernel boot + */ ret = tc3589x_reg_write(tc3589x, TC3589x_RSTCTRL, TC3589x_RSTCTRL_TIMRST | TC3589x_RSTCTRL_ROTRST - | TC3589x_RSTCTRL_KBDRST - | TC3589x_RSTCTRL_GPIRST); + | TC3589x_RSTCTRL_KBDRST); if (ret < 0) return ret; From 593e9d70fb0f1ece1cf2a61c701dec35d8e41f8d Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Mon, 13 Dec 2010 09:33:18 +0530 Subject: [PATCH 27/35] mfd/tc3589x: add suspend/resume support Acked-by: Samuel Ortiz Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- drivers/mfd/tc3589x.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index f000d2ed23e0..32291fe4151c 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -14,6 +14,9 @@ #include #include +#define TC3589x_CLKMODE_MODCTL_SLEEP 0x0 +#define TC3589x_CLKMODE_MODCTL_OPERATION (1 << 0) + /** * tc3589x_reg_read() - read a single TC3589x register * @tc3589x: Device to read from @@ -339,6 +342,37 @@ static int __devexit tc3589x_remove(struct i2c_client *client) return 0; } +static int tc3589x_suspend(struct device *dev) +{ + struct tc3589x *tc3589x = dev_get_drvdata(dev); + struct i2c_client *client = tc3589x->i2c; + int ret = 0; + + /* put the system to sleep mode */ + if (!device_may_wakeup(&client->dev)) + ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, + TC3589x_CLKMODE_MODCTL_SLEEP); + + return ret; +} + +static int tc3589x_resume(struct device *dev) +{ + struct tc3589x *tc3589x = dev_get_drvdata(dev); + struct i2c_client *client = tc3589x->i2c; + int ret = 0; + + /* enable the system into operation */ + if (!device_may_wakeup(&client->dev)) + ret = tc3589x_reg_write(tc3589x, TC3589x_CLKMODE, + TC3589x_CLKMODE_MODCTL_OPERATION); + + return ret; +} + +static const SIMPLE_DEV_PM_OPS(tc3589x_dev_pm_ops, tc3589x_suspend, + tc3589x_resume); + static const struct i2c_device_id tc3589x_id[] = { { "tc3589x", 24 }, { } @@ -348,6 +382,9 @@ MODULE_DEVICE_TABLE(i2c, tc3589x_id); static struct i2c_driver tc3589x_driver = { .driver.name = "tc3589x", .driver.owner = THIS_MODULE, +#ifdef CONFIG_PM + .driver.pm = &tc3589x_dev_pm_ops, +#endif .probe = tc3589x_probe, .remove = __devexit_p(tc3589x_remove), .id_table = tc3589x_id, From e43abe6f98641e40460d74a002f09c7751db48f9 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Fri, 3 Dec 2010 20:35:36 +0530 Subject: [PATCH 28/35] mach-ux500: move keymaps to new file Move keylayouts to a dedicated file and plug these keylayouts for input platform data. This will make addition of new and custom keylayouts localized. Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 3 +- arch/arm/mach-ux500/board-mop500-keypads.c | 134 +++++++++++++++++++++ arch/arm/mach-ux500/board-mop500.c | 111 +---------------- arch/arm/mach-ux500/board-mop500.h | 1 + arch/arm/mach-ux500/devices-db8500.c | 2 +- 5 files changed, 140 insertions(+), 111 deletions(-) create mode 100644 arch/arm/mach-ux500/board-mop500-keypads.c diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 841118335607..3d2c6a510a87 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -5,7 +5,8 @@ obj-y := clock.o cpu.o devices.o devices-common.o obj-$(CONFIG_UX500_SOC_DB5500) += cpu-db5500.o dma-db5500.o obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o -obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o +obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o board-mop500-sdi.o \ + board-mop500-keypads.o obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c new file mode 100644 index 000000000000..b634615b1381 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-keypads.c @@ -0,0 +1,134 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * + * Keypad layouts for various boards + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "devices-db8500.h" +#include "board-mop500.h" + +/* STMPE/SKE keypad use this key layout */ +static const unsigned int mop500_keymap[] = { + KEY(2, 5, KEY_END), + KEY(4, 1, KEY_POWER), + KEY(3, 5, KEY_VOLUMEDOWN), + KEY(1, 3, KEY_3), + KEY(5, 2, KEY_RIGHT), + KEY(5, 0, KEY_9), + + KEY(0, 5, KEY_MENU), + KEY(7, 6, KEY_ENTER), + KEY(4, 5, KEY_0), + KEY(6, 7, KEY_2), + KEY(3, 4, KEY_UP), + KEY(3, 3, KEY_DOWN), + + KEY(6, 4, KEY_SEND), + KEY(6, 2, KEY_BACK), + KEY(4, 2, KEY_VOLUMEUP), + KEY(5, 5, KEY_1), + KEY(4, 3, KEY_LEFT), + KEY(3, 2, KEY_7), +}; + +static const struct matrix_keymap_data mop500_keymap_data = { + .keymap = mop500_keymap, + .keymap_size = ARRAY_SIZE(mop500_keymap), +}; + +/* + * Nomadik SKE keypad + */ +#define ROW_PIN_I0 164 +#define ROW_PIN_I1 163 +#define ROW_PIN_I2 162 +#define ROW_PIN_I3 161 +#define ROW_PIN_I4 156 +#define ROW_PIN_I5 155 +#define ROW_PIN_I6 154 +#define ROW_PIN_I7 153 +#define COL_PIN_O0 168 +#define COL_PIN_O1 167 +#define COL_PIN_O2 166 +#define COL_PIN_O3 165 +#define COL_PIN_O4 160 +#define COL_PIN_O5 159 +#define COL_PIN_O6 158 +#define COL_PIN_O7 157 + +#define SKE_KPD_MAX_ROWS 8 +#define SKE_KPD_MAX_COLS 8 + +static int ske_kp_rows[] = { + ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3, + ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7, +}; + +/* + * ske_set_gpio_row: request and set gpio rows + */ +static int ske_set_gpio_row(int gpio) +{ + int ret; + + ret = gpio_request(gpio, "ske-kp"); + if (ret < 0) { + pr_err("ske_set_gpio_row: gpio request failed\n"); + return ret; + } + + ret = gpio_direction_output(gpio, 1); + if (ret < 0) { + pr_err("ske_set_gpio_row: gpio direction failed\n"); + gpio_free(gpio); + } + + return ret; +} + +/* + * ske_kp_init - enable the gpio configuration + */ +static int ske_kp_init(void) +{ + int ret, i; + + for (i = 0; i < SKE_KPD_MAX_ROWS; i++) { + ret = ske_set_gpio_row(ske_kp_rows[i]); + if (ret < 0) { + pr_err("ske_kp_init: failed init\n"); + return ret; + } + } + + return 0; +} + +static struct ske_keypad_platform_data ske_keypad_board = { + .init = ske_kp_init, + .keymap_data = &mop500_keymap_data, + .no_autorepeat = true, + .krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */ + .kcol = SKE_KPD_MAX_COLS, + .debounce_ms = 40, /* in millisecs */ +}; + +void mop500_keypad_init(void) +{ + db8500_add_ske_keypad(&ske_keypad_board); +} diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 060b23aab8e4..0bc0aa311de1 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -26,7 +26,6 @@ #include #include -#include #include #include @@ -172,116 +171,8 @@ static void __init mop500_i2c_init(void) db8500_add_i2c3(&u8500_i2c3_data); } -static const unsigned int ux500_keymap[] = { - KEY(2, 5, KEY_END), - KEY(4, 1, KEY_POWER), - KEY(3, 5, KEY_VOLUMEDOWN), - KEY(1, 3, KEY_3), - KEY(5, 2, KEY_RIGHT), - KEY(5, 0, KEY_9), - - KEY(0, 5, KEY_MENU), - KEY(7, 6, KEY_ENTER), - KEY(4, 5, KEY_0), - KEY(6, 7, KEY_2), - KEY(3, 4, KEY_UP), - KEY(3, 3, KEY_DOWN), - - KEY(6, 4, KEY_SEND), - KEY(6, 2, KEY_BACK), - KEY(4, 2, KEY_VOLUMEUP), - KEY(5, 5, KEY_1), - KEY(4, 3, KEY_LEFT), - KEY(3, 2, KEY_7), -}; - -static const struct matrix_keymap_data ux500_keymap_data = { - .keymap = ux500_keymap, - .keymap_size = ARRAY_SIZE(ux500_keymap), -}; - -/* - * Nomadik SKE keypad - */ -#define ROW_PIN_I0 164 -#define ROW_PIN_I1 163 -#define ROW_PIN_I2 162 -#define ROW_PIN_I3 161 -#define ROW_PIN_I4 156 -#define ROW_PIN_I5 155 -#define ROW_PIN_I6 154 -#define ROW_PIN_I7 153 -#define COL_PIN_O0 168 -#define COL_PIN_O1 167 -#define COL_PIN_O2 166 -#define COL_PIN_O3 165 -#define COL_PIN_O4 160 -#define COL_PIN_O5 159 -#define COL_PIN_O6 158 -#define COL_PIN_O7 157 - -#define SKE_KPD_MAX_ROWS 8 -#define SKE_KPD_MAX_COLS 8 - -static int ske_kp_rows[] = { - ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3, - ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7, -}; - -/* - * ske_set_gpio_row: request and set gpio rows - */ -static int ske_set_gpio_row(int gpio) -{ - int ret; - - ret = gpio_request(gpio, "ske-kp"); - if (ret < 0) { - pr_err("ske_set_gpio_row: gpio request failed\n"); - return ret; - } - - ret = gpio_direction_output(gpio, 1); - if (ret < 0) { - pr_err("ske_set_gpio_row: gpio direction failed\n"); - gpio_free(gpio); - } - - return ret; -} - -/* - * ske_kp_init - enable the gpio configuration - */ -static int ske_kp_init(void) -{ - int ret, i; - - for (i = 0; i < SKE_KPD_MAX_ROWS; i++) { - ret = ske_set_gpio_row(ske_kp_rows[i]); - if (ret < 0) { - pr_err("ske_kp_init: failed init\n"); - return ret; - } - } - - return 0; -} - -static struct ske_keypad_platform_data ske_keypad_board = { - .init = ske_kp_init, - .keymap_data = &ux500_keymap_data, - .no_autorepeat = true, - .krow = SKE_KPD_MAX_ROWS, /* 8x8 matrix */ - .kcol = SKE_KPD_MAX_COLS, - .debounce_ms = 40, /* in millsecs */ -}; - - - /* add any platform devices here - TODO */ static struct platform_device *platform_devs[] __initdata = { - &ux500_ske_keypad_device, }; static void __init mop500_spi_init(void) @@ -309,6 +200,8 @@ static void __init u8500_init_machine(void) mop500_spi_init(); mop500_uart_init(); + mop500_keypad_init(); + platform_device_register(&ab8500_device); i2c_register_board_info(0, mop500_i2c0_devices, diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index 3a338e6850a4..3104ae2a02c2 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -16,5 +16,6 @@ extern void mop500_sdi_init(void); extern void mop500_sdi_tc35892_init(void); +extern void mop500_keypad_init(void); #endif diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index a7b0a183c037..23c695d54977 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -128,7 +128,7 @@ struct resource keypad_resources[] = { }, }; -struct platform_device ux500_ske_keypad_device = { +struct platform_device u8500_ske_keypad_device = { .name = "nmk-ske-keypad", .id = -1, .num_resources = ARRAY_SIZE(keypad_resources), From 556fb03869ad4d14e5336093a7a8565456a26c21 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Fri, 3 Dec 2010 20:35:38 +0530 Subject: [PATCH 29/35] mach-ux500: add STMPE1601 platform data Signed-off-by: Sundar Iyer [Minor fixups to GPIO enumerators] Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-keypads.c | 32 +++++++++++++++++++ arch/arm/mach-ux500/board-mop500.c | 6 +++- .../include/mach/irqs-board-mop500.h | 13 +++++++- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c index b634615b1381..8dbba03eb6c1 100644 --- a/arch/arm/mach-ux500/board-mop500-keypads.c +++ b/arch/arm/mach-ux500/board-mop500-keypads.c @@ -128,7 +128,39 @@ static struct ske_keypad_platform_data ske_keypad_board = { .debounce_ms = 40, /* in millisecs */ }; +/* + * STMPE1601 + */ +static struct stmpe_keypad_platform_data stmpe1601_keypad_data = { + .debounce_ms = 64, + .scan_count = 8, + .no_autorepeat = true, + .keymap_data = &mop500_keymap_data, +}; + +static struct stmpe_platform_data stmpe1601_data = { + .id = 1, + .blocks = STMPE_BLOCK_KEYPAD, + .irq_trigger = IRQF_TRIGGER_FALLING, + .irq_base = MOP500_STMPE1601_IRQ(0), + .keypad = &stmpe1601_keypad_data, + .autosleep = true, + .autosleep_timeout = 1024, +}; + +static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = { + { + I2C_BOARD_INFO("stmpe1601", 0x40), + .irq = NOMADIK_GPIO_TO_IRQ(218), + .platform_data = &stmpe1601_data, + .flags = I2C_CLIENT_WAKE, + }, +}; + void mop500_keypad_init(void) { db8500_add_ske_keypad(&ske_keypad_board); + + i2c_register_board_info(0, mop500_i2c0_devices_stuib, + ARRAY_SIZE(mop500_i2c0_devices_stuib)); } diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 0bc0aa311de1..a1c9ea1a66df 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -71,7 +71,11 @@ static pin_cfg_t mop500_pins[] = { GPIO167_KP_O1, GPIO168_KP_O0, - GPIO217_GPIO, /* GPIO_EXP_INT */ + /* GPIO_EXP_INT */ + GPIO217_GPIO, + + /* STMPE1601 IRQ */ + GPIO218_GPIO | PIN_INPUT_PULLUP, }; static struct ab8500_platform_data ab8500_platdata = { diff --git a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h index 4a91bbdb973e..7cdeb2af0ebb 100644 --- a/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h +++ b/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h @@ -15,6 +15,7 @@ #define MOP500_AB8500_IRQ_END (MOP500_AB8500_IRQ_BASE \ + AB8500_NR_IRQS) +/* TC35892 */ #define TC35892_NR_INTERNAL_IRQS 8 #define TC35892_INT_GPIO(x) (TC35892_NR_INTERNAL_IRQS + (x)) #define TC35892_NR_GPIOS 24 @@ -25,8 +26,18 @@ #define MOP500_EGPIO_IRQ_BASE MOP500_AB8500_IRQ_END #define MOP500_EGPIO_IRQ_END (MOP500_EGPIO_IRQ_BASE \ + MOP500_EGPIO_NR_IRQS) +/* STMPE1601 irqs */ +#define STMPE_NR_INTERNAL_IRQS 9 +#define STMPE_INT_GPIO(x) (STMPE_NR_INTERNAL_IRQS + (x)) +#define STMPE_NR_GPIOS 24 +#define STMPE_NR_IRQS STMPE_INT_GPIO(STMPE_NR_GPIOS) -#define MOP500_IRQ_END MOP500_EGPIO_IRQ_END +#define MOP500_STMPE1601_IRQBASE MOP500_EGPIO_IRQ_END +#define MOP500_STMPE1601_IRQ(x) (MOP500_STMPE1601_IRQBASE + (x)) + +#define MOP500_NR_IRQS MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS) + +#define MOP500_IRQ_END MOP500_NR_IRQS #if MOP500_IRQ_END > IRQ_BOARD_END #undef IRQ_BOARD_END From 3c5728edbeb44819dba25a3c1b56702c87c9e419 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 15 Dec 2010 08:36:02 +0100 Subject: [PATCH 30/35] ux500: platsmp: Fix section mismatch Signed-off-by: Jonas Aaberg Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/platsmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index 9e4c678de785..ade2e17f253c 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -26,7 +26,7 @@ * control for which core is the next to come out of the secondary * boot "holding pen" */ -volatile int __cpuinitdata pen_release = -1; +volatile int pen_release = -1; static unsigned int __init get_core_count(void) { From abda3a24a99998279fe890ea8a789ebe4d605d78 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 20 Dec 2010 13:01:30 +0100 Subject: [PATCH 31/35] mfd: Use dummy_irq_chip for tc3589x This also converts tc3589x to the new irq API. Cc: Rabin Vincent Signed-off-by: Samuel Ortiz Signed-off-by: Linus Walleij --- drivers/mfd/tc3589x.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 32291fe4151c..112efd3c4940 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -170,17 +170,6 @@ again: return IRQ_HANDLED; } -static void tc3589x_irq_dummy(unsigned int irq) -{ - /* No mask/unmask at this level */ -} - -static struct irq_chip tc3589x_irq_chip = { - .name = "tc3589x", - .mask = tc3589x_irq_dummy, - .unmask = tc3589x_irq_dummy, -}; - static int tc3589x_irq_init(struct tc3589x *tc3589x) { int base = tc3589x->irq_base; @@ -188,7 +177,7 @@ static int tc3589x_irq_init(struct tc3589x *tc3589x) for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) { set_irq_chip_data(irq, tc3589x); - set_irq_chip_and_handler(irq, &tc3589x_irq_chip, + set_irq_chip_and_handler(irq, &dummy_irq_chip, handle_edge_irq); set_irq_nested_thread(irq, 1); #ifdef CONFIG_ARM From 763eef8b5b64dbbfc0f6273af9a57024069785a9 Mon Sep 17 00:00:00 2001 From: Vincent Guittot Date: Fri, 3 Dec 2010 18:18:39 +0100 Subject: [PATCH 32/35] ux500: add debugfs support for powerdebug Signed-off-by: Vincent Guittot Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/clock.c | 195 +++++++++++++++++++++++++++++++++++- arch/arm/mach-ux500/clock.h | 4 + 2 files changed, 198 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 00e9ab304ca7..912d1cc18c57 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -20,6 +20,12 @@ #include #include "clock.h" +#ifdef CONFIG_DEBUG_FS +#include +#include /* for copy_from_user */ +static LIST_HEAD(clk_list); +#endif + #define PRCC_PCKEN 0x00 #define PRCC_PCKDIS 0x04 #define PRCC_KCKEN 0x08 @@ -286,6 +292,7 @@ static struct clkops clk_prcc_ops = { }; static struct clk clk_32khz = { + .name = "clk_32khz", .rate = 32000, }; @@ -422,7 +429,9 @@ static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0); static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL); static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL); -static struct clk clk_dummy_apb_pclk; +static struct clk clk_dummy_apb_pclk = { + .name = "apb_pclk", +}; static struct clk_lookup u8500_common_clks[] = { CLK(dummy_apb_pclk, NULL, "apb_pclk"), @@ -568,6 +577,183 @@ static struct clk_lookup u8500_v1_clks[] = { CLK(uiccclk, "uicc", NULL), }; +#ifdef CONFIG_DEBUG_FS +/* + * debugfs support to trace clock tree hierarchy and attributes with + * powerdebug + */ +static struct dentry *clk_debugfs_root; + +void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num) +{ + while (num--) { + /* Check that the clock has not been already registered */ + if (!(cl->clk->list.prev != cl->clk->list.next)) + list_add_tail(&cl->clk->list, &clk_list); + + cl++; + } +} + +static ssize_t usecount_dbg_read(struct file *file, char __user *buf, + size_t size, loff_t *off) +{ + struct clk *clk = file->f_dentry->d_inode->i_private; + char cusecount[128]; + unsigned int len; + + len = sprintf(cusecount, "%u\n", clk->enabled); + return simple_read_from_buffer(buf, size, off, cusecount, len); +} + +static ssize_t rate_dbg_read(struct file *file, char __user *buf, + size_t size, loff_t *off) +{ + struct clk *clk = file->f_dentry->d_inode->i_private; + char crate[128]; + unsigned int rate; + unsigned int len; + + rate = clk_get_rate(clk); + len = sprintf(crate, "%u\n", rate); + return simple_read_from_buffer(buf, size, off, crate, len); +} + +static const struct file_operations usecount_fops = { + .read = usecount_dbg_read, +}; + +static const struct file_operations set_rate_fops = { + .read = rate_dbg_read, +}; + +static struct dentry *clk_debugfs_register_dir(struct clk *c, + struct dentry *p_dentry) +{ + struct dentry *d, *clk_d, *child, *child_tmp; + char s[255]; + char *p = s; + + if (c->name == NULL) + p += sprintf(p, "BUG"); + else + p += sprintf(p, "%s", c->name); + + clk_d = debugfs_create_dir(s, p_dentry); + if (!clk_d) + return NULL; + + d = debugfs_create_file("usecount", S_IRUGO, + clk_d, c, &usecount_fops); + if (!d) + goto err_out; + d = debugfs_create_file("rate", S_IRUGO, + clk_d, c, &set_rate_fops); + if (!d) + goto err_out; + /* + * TODO : not currently available in ux500 + * d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags); + * if (!d) + * goto err_out; + */ + + return clk_d; + +err_out: + d = clk_d; + list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(clk_d); + return NULL; +} + +static void clk_debugfs_remove_dir(struct dentry *cdentry) +{ + struct dentry *d, *child, *child_tmp; + + d = cdentry; + list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) + debugfs_remove(child); + debugfs_remove(cdentry); + return ; +} + +static int clk_debugfs_register_one(struct clk *c) +{ + struct clk *pa = c->parent_periph; + struct clk *bpa = c->parent_cluster; + + if (!(bpa && !pa)) { + c->dent = clk_debugfs_register_dir(c, + pa ? pa->dent : clk_debugfs_root); + if (!c->dent) + return -ENOMEM; + } + + if (bpa) { + c->dent_bus = clk_debugfs_register_dir(c, + bpa->dent_bus ? bpa->dent_bus : bpa->dent); + if ((!c->dent_bus) && (c->dent)) { + clk_debugfs_remove_dir(c->dent); + c->dent = NULL; + return -ENOMEM; + } + } + return 0; +} + +static int clk_debugfs_register(struct clk *c) +{ + int err; + struct clk *pa = c->parent_periph; + struct clk *bpa = c->parent_cluster; + + if (pa && (!pa->dent && !pa->dent_bus)) { + err = clk_debugfs_register(pa); + if (err) + return err; + } + + if (bpa && (!bpa->dent && !bpa->dent_bus)) { + err = clk_debugfs_register(bpa); + if (err) + return err; + } + + if ((!c->dent) && (!c->dent_bus)) { + err = clk_debugfs_register_one(c); + if (err) + return err; + } + return 0; +} + +static int __init clk_debugfs_init(void) +{ + struct clk *c; + struct dentry *d; + int err; + + d = debugfs_create_dir("clock", NULL); + if (!d) + return -ENOMEM; + clk_debugfs_root = d; + + list_for_each_entry(c, &clk_list, list) { + err = clk_debugfs_register(c); + if (err) + goto err_out; + } + return 0; +err_out: + debugfs_remove_recursive(clk_debugfs_root); + return err; +} + +late_initcall(clk_debugfs_init); +#endif /* defined(CONFIG_DEBUG_FS) */ + int __init clk_init(void) { if (cpu_is_u8500ed()) { @@ -588,5 +774,12 @@ int __init clk_init(void) else clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); +#ifdef CONFIG_DEBUG_FS + clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks)); + if (cpu_is_u8500ed()) + clk_debugfs_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks)); + else + clk_debugfs_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks)); +#endif return 0; } diff --git a/arch/arm/mach-ux500/clock.h b/arch/arm/mach-ux500/clock.h index a05802501527..074490705229 100644 --- a/arch/arm/mach-ux500/clock.h +++ b/arch/arm/mach-ux500/clock.h @@ -90,6 +90,10 @@ struct clk { struct clk *parent_cluster; struct clk *parent_periph; +#if defined(CONFIG_DEBUG_FS) + struct dentry *dent; /* For visible tree hierarchy */ + struct dentry *dent_bus; /* For visible tree hierarchy */ +#endif }; #define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \ From 11c8ea81cc639c2ea56f94a9cdaa6242ff13a3af Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 17 Dec 2010 21:16:23 +0100 Subject: [PATCH 33/35] ux500: rename modem IRQ and MBOX files Suffix the U5500 modem IRQ and MBOX files with *-db5500* so that we clearly know the SoC they belong to, in line with the rest of the files in mach-ux500. Cc: Stefan Nilsson Cc: Martin Persson Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 4 ++-- arch/arm/mach-ux500/include/mach/{mbox.h => mbox-db5500.h} | 0 arch/arm/mach-ux500/{mbox.c => mbox-db5500.c} | 2 +- arch/arm/mach-ux500/{modem_irq.c => modem-irq-db5500.c} | 0 drivers/net/caif/caif_shm_u5500.c | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename arch/arm/mach-ux500/include/mach/{mbox.h => mbox-db5500.h} (100%) rename arch/arm/mach-ux500/{mbox.c => mbox-db5500.c} (99%) rename arch/arm/mach-ux500/{modem_irq.c => modem-irq-db5500.c} (100%) diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 3d2c6a510a87..12052e8e064c 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -12,6 +12,6 @@ obj-$(CONFIG_SMP) += platsmp.o headsmp.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o -obj-$(CONFIG_U5500_MODEM_IRQ) += modem_irq.o -obj-$(CONFIG_U5500_MBOX) += mbox.o +obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o +obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o diff --git a/arch/arm/mach-ux500/include/mach/mbox.h b/arch/arm/mach-ux500/include/mach/mbox-db5500.h similarity index 100% rename from arch/arm/mach-ux500/include/mach/mbox.h rename to arch/arm/mach-ux500/include/mach/mbox-db5500.h diff --git a/arch/arm/mach-ux500/mbox.c b/arch/arm/mach-ux500/mbox-db5500.c similarity index 99% rename from arch/arm/mach-ux500/mbox.c rename to arch/arm/mach-ux500/mbox-db5500.c index 63435389c544..cbf15718fc3c 100644 --- a/arch/arm/mach-ux500/mbox.c +++ b/arch/arm/mach-ux500/mbox-db5500.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #define MBOX_NAME "mbox" diff --git a/arch/arm/mach-ux500/modem_irq.c b/arch/arm/mach-ux500/modem-irq-db5500.c similarity index 100% rename from arch/arm/mach-ux500/modem_irq.c rename to arch/arm/mach-ux500/modem-irq-db5500.c diff --git a/drivers/net/caif/caif_shm_u5500.c b/drivers/net/caif/caif_shm_u5500.c index 1cd90da86f13..13fa5353816e 100644 --- a/drivers/net/caif/caif_shm_u5500.c +++ b/drivers/net/caif/caif_shm_u5500.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include MODULE_LICENSE("GPL"); From 09c730a488c32c2cadb31cdb8dcc4df528441197 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Tue, 21 Dec 2010 15:53:31 +0530 Subject: [PATCH 34/35] input/tc3589x: add tc3589x keypad support Add support for the keypad controller module found on the TC3589X devices. This driver default adds the support for TC35893 device. Signed-off-by: Sundar Iyer Acked-by: Dmitry Torokhov [Some minor fixups for compilation] Signed-off-by: Linus Walleij --- drivers/input/keyboard/Kconfig | 10 + drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/tc3589x-keypad.c | 472 ++++++++++++++++++++++++ drivers/mfd/tc3589x.c | 28 +- include/linux/mfd/tc3589x.h | 52 +++ 5 files changed, 562 insertions(+), 1 deletion(-) create mode 100644 drivers/input/keyboard/tc3589x-keypad.c diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b8c51b9781db..85af3c3f7bcb 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -443,6 +443,16 @@ config KEYBOARD_OMAP4 To compile this driver as a module, choose M here: the module will be called omap4-keypad. +config KEYBOARD_TC3589X + tristate "TC3589X Keypad support" + depends on MFD_TC3589X + help + Say Y here if you want to use the keypad controller on + TC35892/3 I/O expander. + + To compile this driver as a module, choose M here: the + module will be called tc3589x-keypad. + config KEYBOARD_TNETV107X tristate "TI TNETV107X keypad support" depends on ARCH_DAVINCI_TNETV107X diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index a34452e8ebe2..4411c70db3b5 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o obj-$(CONFIG_KEYBOARD_STMPE) += stmpe-keypad.o obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o +obj-$(CONFIG_KEYBOARD_TC3589X) += tc3589x-keypad.o obj-$(CONFIG_KEYBOARD_TNETV107X) += tnetv107x-keypad.o obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c new file mode 100644 index 000000000000..69dc0cb20a00 --- /dev/null +++ b/drivers/input/keyboard/tc3589x-keypad.c @@ -0,0 +1,472 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Jayeeta Banerjee + * Author: Sundar Iyer + * + * License Terms: GNU General Public License, version 2 + * + * TC35893 MFD Keypad Controller driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Maximum supported keypad matrix row/columns size */ +#define TC3589x_MAX_KPROW 8 +#define TC3589x_MAX_KPCOL 12 + +/* keypad related Constants */ +#define TC3589x_MAX_DEBOUNCE_SETTLE 0xFF +#define DEDICATED_KEY_VAL 0xFF + +/* Pull up/down masks */ +#define TC3589x_NO_PULL_MASK 0x0 +#define TC3589x_PULL_DOWN_MASK 0x1 +#define TC3589x_PULL_UP_MASK 0x2 +#define TC3589x_PULLUP_ALL_MASK 0xAA +#define TC3589x_IO_PULL_VAL(index, mask) ((mask)<<((index)%4)*2)) + +/* Bit masks for IOCFG register */ +#define IOCFG_BALLCFG 0x01 +#define IOCFG_IG 0x08 + +#define KP_EVCODE_COL_MASK 0x0F +#define KP_EVCODE_ROW_MASK 0x70 +#define KP_RELEASE_EVT_MASK 0x80 + +#define KP_ROW_SHIFT 4 + +#define KP_NO_VALID_KEY_MASK 0x7F + +/* bit masks for RESTCTRL register */ +#define TC3589x_KBDRST 0x2 +#define TC3589x_IRQRST 0x10 +#define TC3589x_RESET_ALL 0x1B + +/* KBDMFS register bit mask */ +#define TC3589x_KBDMFS_EN 0x1 + +/* CLKEN register bitmask */ +#define KPD_CLK_EN 0x1 + +/* RSTINTCLR register bit mask */ +#define IRQ_CLEAR 0x1 + +/* bit masks for keyboard interrupts*/ +#define TC3589x_EVT_LOSS_INT 0x8 +#define TC3589x_EVT_INT 0x4 +#define TC3589x_KBD_LOSS_INT 0x2 +#define TC3589x_KBD_INT 0x1 + +/* bit masks for keyboard interrupt clear*/ +#define TC3589x_EVT_INT_CLR 0x2 +#define TC3589x_KBD_INT_CLR 0x1 + +#define TC3589x_KBD_KEYMAP_SIZE 64 + +/** + * struct tc_keypad - data structure used by keypad driver + * @input: pointer to input device object + * @board: keypad platform device + * @krow: number of rows + * @kcol: number of coloumns + * @keymap: matrix scan code table for keycodes + */ +struct tc_keypad { + struct tc3589x *tc3589x; + struct input_dev *input; + const struct tc3589x_keypad_platform_data *board; + unsigned int krow; + unsigned int kcol; + unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE]; + bool keypad_stopped; +}; + +static int __devinit tc3589x_keypad_init_key_hardware(struct tc_keypad *keypad) +{ + int ret; + struct tc3589x *tc3589x = keypad->tc3589x; + u8 settle_time = keypad->board->settle_time; + u8 dbounce_period = keypad->board->debounce_period; + u8 rows = keypad->board->krow & 0xf; /* mask out the nibble */ + u8 column = keypad->board->kcol & 0xf; /* mask out the nibble */ + + /* validate platform configurations */ + if (keypad->board->kcol > TC3589x_MAX_KPCOL || + keypad->board->krow > TC3589x_MAX_KPROW || + keypad->board->debounce_period > TC3589x_MAX_DEBOUNCE_SETTLE || + keypad->board->settle_time > TC3589x_MAX_DEBOUNCE_SETTLE) + return -EINVAL; + + /* configure KBDSIZE 4 LSbits for cols and 4 MSbits for rows */ + ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSIZE, + (rows << KP_ROW_SHIFT) | column); + if (ret < 0) + return ret; + + /* configure dedicated key config, no dedicated key selected */ + ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_LSB, DEDICATED_KEY_VAL); + if (ret < 0) + return ret; + + ret = tc3589x_reg_write(tc3589x, TC3589x_KBCFG_MSB, DEDICATED_KEY_VAL); + if (ret < 0) + return ret; + + /* Configure settle time */ + ret = tc3589x_reg_write(tc3589x, TC3589x_KBDSETTLE_REG, settle_time); + if (ret < 0) + return ret; + + /* Configure debounce time */ + ret = tc3589x_reg_write(tc3589x, TC3589x_KBDBOUNCE, dbounce_period); + if (ret < 0) + return ret; + + /* Start of initialise keypad GPIOs */ + ret = tc3589x_set_bits(tc3589x, TC3589x_IOCFG, 0x0, IOCFG_IG); + if (ret < 0) + return ret; + + /* Configure pull-up resistors for all row GPIOs */ + ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_LSB, + TC3589x_PULLUP_ALL_MASK); + if (ret < 0) + return ret; + + ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG0_MSB, + TC3589x_PULLUP_ALL_MASK); + if (ret < 0) + return ret; + + /* Configure pull-up resistors for all column GPIOs */ + ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_LSB, + TC3589x_PULLUP_ALL_MASK); + if (ret < 0) + return ret; + + ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG1_MSB, + TC3589x_PULLUP_ALL_MASK); + if (ret < 0) + return ret; + + ret = tc3589x_reg_write(tc3589x, TC3589x_IOPULLCFG2_LSB, + TC3589x_PULLUP_ALL_MASK); + + return ret; +} + +#define TC35893_DATA_REGS 4 +#define TC35893_KEYCODE_FIFO_EMPTY 0x7f +#define TC35893_KEYCODE_FIFO_CLEAR 0xff +#define TC35893_KEYPAD_ROW_SHIFT 0x3 + +static irqreturn_t tc3589x_keypad_irq(int irq, void *dev) +{ + struct tc_keypad *keypad = dev; + struct tc3589x *tc3589x = keypad->tc3589x; + u8 i, row_index, col_index, kbd_code, up; + u8 code; + + for (i = 0; i < TC35893_DATA_REGS * 2; i++) { + kbd_code = tc3589x_reg_read(tc3589x, TC3589x_EVTCODE_FIFO); + + /* loop till fifo is empty and no more keys are pressed */ + if (kbd_code == TC35893_KEYCODE_FIFO_EMPTY || + kbd_code == TC35893_KEYCODE_FIFO_CLEAR) + continue; + + /* valid key is found */ + col_index = kbd_code & KP_EVCODE_COL_MASK; + row_index = (kbd_code & KP_EVCODE_ROW_MASK) >> KP_ROW_SHIFT; + code = MATRIX_SCAN_CODE(row_index, col_index, + TC35893_KEYPAD_ROW_SHIFT); + up = kbd_code & KP_RELEASE_EVT_MASK; + + input_event(keypad->input, EV_MSC, MSC_SCAN, code); + input_report_key(keypad->input, keypad->keymap[code], !up); + input_sync(keypad->input); + } + + /* clear IRQ */ + tc3589x_set_bits(tc3589x, TC3589x_KBDIC, + 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); + /* enable IRQ */ + tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, + 0x0, TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); + + return IRQ_HANDLED; +} + +static int tc3589x_keypad_enable(struct tc_keypad *keypad) +{ + struct tc3589x *tc3589x = keypad->tc3589x; + int ret; + + /* pull the keypad module out of reset */ + ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x0); + if (ret < 0) + return ret; + + /* configure KBDMFS */ + ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMFS, 0x0, TC3589x_KBDMFS_EN); + if (ret < 0) + return ret; + + /* enable the keypad clock */ + ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x0, KPD_CLK_EN); + if (ret < 0) + return ret; + + /* clear pending IRQs */ + ret = tc3589x_set_bits(tc3589x, TC3589x_RSTINTCLR, 0x0, 0x1); + if (ret < 0) + return ret; + + /* enable the IRQs */ + ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, 0x0, + TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT); + if (ret < 0) + return ret; + + keypad->keypad_stopped = false; + + return ret; +} + +static int tc3589x_keypad_disable(struct tc_keypad *keypad) +{ + struct tc3589x *tc3589x = keypad->tc3589x; + int ret; + + /* clear IRQ */ + ret = tc3589x_set_bits(tc3589x, TC3589x_KBDIC, + 0x0, TC3589x_EVT_INT_CLR | TC3589x_KBD_INT_CLR); + if (ret < 0) + return ret; + + /* disable all interrupts */ + ret = tc3589x_set_bits(tc3589x, TC3589x_KBDMSK, + ~(TC3589x_EVT_LOSS_INT | TC3589x_EVT_INT), 0x0); + if (ret < 0) + return ret; + + /* disable the keypad module */ + ret = tc3589x_set_bits(tc3589x, TC3589x_CLKEN, 0x1, 0x0); + if (ret < 0) + return ret; + + /* put the keypad module into reset */ + ret = tc3589x_set_bits(tc3589x, TC3589x_RSTCTRL, TC3589x_KBDRST, 0x1); + + keypad->keypad_stopped = true; + + return ret; +} + +static int tc3589x_keypad_open(struct input_dev *input) +{ + int error; + struct tc_keypad *keypad = input_get_drvdata(input); + + /* enable the keypad module */ + error = tc3589x_keypad_enable(keypad); + if (error < 0) { + dev_err(&input->dev, "failed to enable keypad module\n"); + return error; + } + + error = tc3589x_keypad_init_key_hardware(keypad); + if (error < 0) { + dev_err(&input->dev, "failed to configure keypad module\n"); + return error; + } + + return 0; +} + +static void tc3589x_keypad_close(struct input_dev *input) +{ + struct tc_keypad *keypad = input_get_drvdata(input); + + /* disable the keypad module */ + tc3589x_keypad_disable(keypad); +} + +static int __devinit tc3589x_keypad_probe(struct platform_device *pdev) +{ + struct tc3589x *tc3589x = dev_get_drvdata(pdev->dev.parent); + struct tc_keypad *keypad; + struct input_dev *input; + const struct tc3589x_keypad_platform_data *plat; + int error, irq; + + plat = tc3589x->pdata->keypad; + if (!plat) { + dev_err(&pdev->dev, "invalid keypad platform data\n"); + return -EINVAL; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + keypad = kzalloc(sizeof(struct tc_keypad), GFP_KERNEL); + input = input_allocate_device(); + if (!keypad || !input) { + dev_err(&pdev->dev, "failed to allocate keypad memory\n"); + error = -ENOMEM; + goto err_free_mem; + } + + keypad->board = plat; + keypad->input = input; + keypad->tc3589x = tc3589x; + + input->id.bustype = BUS_I2C; + input->name = pdev->name; + input->dev.parent = &pdev->dev; + + input->keycode = keypad->keymap; + input->keycodesize = sizeof(keypad->keymap[0]); + input->keycodemax = ARRAY_SIZE(keypad->keymap); + + input->open = tc3589x_keypad_open; + input->close = tc3589x_keypad_close; + + input_set_drvdata(input, keypad); + + input_set_capability(input, EV_MSC, MSC_SCAN); + + __set_bit(EV_KEY, input->evbit); + if (!plat->no_autorepeat) + __set_bit(EV_REP, input->evbit); + + matrix_keypad_build_keymap(plat->keymap_data, 0x3, + input->keycode, input->keybit); + + error = request_threaded_irq(irq, NULL, + tc3589x_keypad_irq, plat->irqtype, + "tc3589x-keypad", keypad); + if (error < 0) { + dev_err(&pdev->dev, + "Could not allocate irq %d,error %d\n", + irq, error); + goto err_free_mem; + } + + error = input_register_device(input); + if (error) { + dev_err(&pdev->dev, "Could not register input device\n"); + goto err_free_irq; + } + + /* let platform decide if keypad is a wakeup source or not */ + device_init_wakeup(&pdev->dev, plat->enable_wakeup); + device_set_wakeup_capable(&pdev->dev, plat->enable_wakeup); + + platform_set_drvdata(pdev, keypad); + + return 0; + +err_free_irq: + free_irq(irq, keypad); +err_free_mem: + input_free_device(input); + kfree(keypad); + return error; +} + +static int __devexit tc3589x_keypad_remove(struct platform_device *pdev) +{ + struct tc_keypad *keypad = platform_get_drvdata(pdev); + int irq = platform_get_irq(pdev, 0); + + if (!keypad->keypad_stopped) + tc3589x_keypad_disable(keypad); + + free_irq(irq, keypad); + + input_unregister_device(keypad->input); + + kfree(keypad); + + return 0; +} + +#ifdef CONFIG_PM +static int tc3589x_keypad_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct tc_keypad *keypad = platform_get_drvdata(pdev); + int irq = platform_get_irq(pdev, 0); + + /* keypad is already off; we do nothing */ + if (keypad->keypad_stopped) + return 0; + + /* if device is not a wakeup source, disable it for powersave */ + if (!device_may_wakeup(&pdev->dev)) + tc3589x_keypad_disable(keypad); + else + enable_irq_wake(irq); + + return 0; +} + +static int tc3589x_keypad_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct tc_keypad *keypad = platform_get_drvdata(pdev); + int irq = platform_get_irq(pdev, 0); + + if (!keypad->keypad_stopped) + return 0; + + /* enable the device to resume normal operations */ + if (!device_may_wakeup(&pdev->dev)) + tc3589x_keypad_enable(keypad); + else + disable_irq_wake(irq); + + return 0; +} + +static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops, + tc3589x_keypad_suspend, tc3589x_keypad_resume); +#endif + +static struct platform_driver tc3589x_keypad_driver = { + .driver.name = "tc3589x-keypad", + .driver.owner = THIS_MODULE, +#ifdef CONFIG_PM + .driver.pm = &tc3589x_keypad_dev_pm_ops, +#endif + .probe = tc3589x_keypad_probe, + .remove = __devexit_p(tc3589x_keypad_remove), +}; + +static int __init tc3589x_keypad_init(void) +{ + return platform_driver_register(&tc3589x_keypad_driver); +} +module_init(tc3589x_keypad_init); + +static void __exit tc3589x_keypad_exit(void) +{ + return platform_driver_unregister(&tc3589x_keypad_driver); +} +module_exit(tc3589x_keypad_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Jayeeta Banerjee/Sundar Iyer"); +MODULE_DESCRIPTION("TC35893 Keypad Driver"); +MODULE_ALIAS("platform:tc3589x-keypad") diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index 112efd3c4940..729dbeed2ce0 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c @@ -132,6 +132,14 @@ static struct resource gpio_resources[] = { }, }; +static struct resource keypad_resources[] = { + { + .start = TC3589x_INT_KBDIRQ, + .end = TC3589x_INT_KBDIRQ, + .flags = IORESOURCE_IRQ, + }, +}; + static struct mfd_cell tc3589x_dev_gpio[] = { { .name = "tc3589x-gpio", @@ -140,6 +148,14 @@ static struct mfd_cell tc3589x_dev_gpio[] = { }, }; +static struct mfd_cell tc3589x_dev_keypad[] = { + { + .name = "tc3589x-keypad", + .num_resources = ARRAY_SIZE(keypad_resources), + .resources = &keypad_resources[0], + }, +}; + static irqreturn_t tc3589x_irq(int irq, void *data) { struct tc3589x *tc3589x = data; @@ -255,8 +271,18 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x) dev_info(tc3589x->dev, "added gpio block\n"); } - return ret; + if (blocks & TC3589x_BLOCK_KEYPAD) { + ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad, + ARRAY_SIZE(tc3589x_dev_keypad), NULL, + tc3589x->irq_base); + if (ret) { + dev_err(tc3589x->dev, "failed to keypad child\n"); + return ret; + } + dev_info(tc3589x->dev, "added keypad block\n"); + } + return ret; } static int __devinit tc3589x_probe(struct i2c_client *i2c, diff --git a/include/linux/mfd/tc3589x.h b/include/linux/mfd/tc3589x.h index da00958b12d9..16c76e124f9c 100644 --- a/include/linux/mfd/tc3589x.h +++ b/include/linux/mfd/tc3589x.h @@ -20,6 +20,17 @@ enum tx3589x_block { #define TC3589x_RSTCTRL_KBDRST (1 << 1) #define TC3589x_RSTCTRL_GPIRST (1 << 0) +/* Keyboard Configuration Registers */ +#define TC3589x_KBDSETTLE_REG 0x01 +#define TC3589x_KBDBOUNCE 0x02 +#define TC3589x_KBDSIZE 0x03 +#define TC3589x_KBCFG_LSB 0x04 +#define TC3589x_KBCFG_MSB 0x05 +#define TC3589x_KBDIC 0x08 +#define TC3589x_KBDMSK 0x09 +#define TC3589x_EVTCODE_FIFO 0x10 +#define TC3589x_KBDMFS 0x8F + #define TC3589x_IRQST 0x91 #define TC3589x_MANFCODE_MAGIC 0x03 @@ -35,6 +46,14 @@ enum tx3589x_block { #define TC3589x_EXTRSTN 0x83 #define TC3589x_RSTINTCLR 0x84 +/* Pull up/down configuration registers */ +#define TC3589x_IOCFG 0xA7 +#define TC3589x_IOPULLCFG0_LSB 0xAA +#define TC3589x_IOPULLCFG0_MSB 0xAB +#define TC3589x_IOPULLCFG1_LSB 0xAC +#define TC3589x_IOPULLCFG1_MSB 0xAD +#define TC3589x_IOPULLCFG2_LSB 0xAE + #define TC3589x_GPIOIS0 0xC9 #define TC3589x_GPIOIS1 0xCA #define TC3589x_GPIOIS2 0xCB @@ -112,6 +131,37 @@ extern int tc3589x_block_write(struct tc3589x *tc3589x, u8 reg, u8 length, const u8 *values); extern int tc3589x_set_bits(struct tc3589x *tc3589x, u8 reg, u8 mask, u8 val); +/* + * Keypad related platform specific constants + * These values may be modified for fine tuning + */ +#define TC_KPD_ROWS 0x8 +#define TC_KPD_COLUMNS 0x8 +#define TC_KPD_DEBOUNCE_PERIOD 0xA3 +#define TC_KPD_SETTLE_TIME 0xA3 + +/** + * struct tc35893_platform_data - data structure for platform specific data + * @keymap_data: matrix scan code table for keycodes + * @krow: mask for available rows, value is 0xFF + * @kcol: mask for available columns, value is 0xFF + * @debounce_period: platform specific debounce time + * @settle_time: platform specific settle down time + * @irqtype: type of interrupt, falling or rising edge + * @enable_wakeup: specifies if keypad event can wake up system from sleep + * @no_autorepeat: flag for auto repetition + */ +struct tc3589x_keypad_platform_data { + const struct matrix_keymap_data *keymap_data; + u8 krow; + u8 kcol; + u8 debounce_period; + u8 settle_time; + unsigned long irqtype; + bool enable_wakeup; + bool no_autorepeat; +}; + /** * struct tc3589x_gpio_platform_data - TC3589x GPIO platform data * @gpio_base: first gpio number assigned to TC3589x. A maximum of @@ -130,11 +180,13 @@ struct tc3589x_gpio_platform_data { * @block: bitmask of blocks to enable (use TC3589x_BLOCK_*) * @irq_base: base IRQ number. %TC3589x_NR_IRQS irqs will be used. * @gpio: GPIO-specific platform data + * @keypad: keypad-specific platform data */ struct tc3589x_platform_data { unsigned int block; int irq_base; struct tc3589x_gpio_platform_data *gpio; + const struct tc3589x_keypad_platform_data *keypad; }; #define TC3589x_NR_GPIOS 24 From 60ebe1568fd15b7ffa101acc645069e27d546ed6 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Fri, 3 Dec 2010 20:35:50 +0530 Subject: [PATCH 35/35] ux500: add TC35893 keypad platform data Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-keypads.c | 65 +++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c index 8dbba03eb6c1..70318c354d32 100644 --- a/arch/arm/mach-ux500/board-mop500-keypads.c +++ b/arch/arm/mach-ux500/board-mop500-keypads.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -148,7 +149,7 @@ static struct stmpe_platform_data stmpe1601_data = { .autosleep_timeout = 1024, }; -static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = { +static struct i2c_board_info mop500_i2c0_devices_stuib[] = { { I2C_BOARD_INFO("stmpe1601", 0x40), .irq = NOMADIK_GPIO_TO_IRQ(218), @@ -157,10 +158,72 @@ static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = { }, }; +/* + * TC35893 + */ + +static const unsigned int uib_keymap[] = { + KEY(3, 1, KEY_END), + KEY(4, 1, KEY_POWER), + KEY(6, 4, KEY_VOLUMEDOWN), + KEY(4, 2, KEY_EMAIL), + KEY(3, 3, KEY_RIGHT), + KEY(2, 5, KEY_BACKSPACE), + + KEY(6, 7, KEY_MENU), + KEY(5, 0, KEY_ENTER), + KEY(4, 3, KEY_0), + KEY(3, 4, KEY_DOT), + KEY(5, 2, KEY_UP), + KEY(3, 5, KEY_DOWN), + + KEY(4, 5, KEY_SEND), + KEY(0, 5, KEY_BACK), + KEY(6, 2, KEY_VOLUMEUP), + KEY(1, 3, KEY_SPACE), + KEY(7, 6, KEY_LEFT), + KEY(5, 5, KEY_SEARCH), +}; + +static struct matrix_keymap_data uib_keymap_data = { + .keymap = uib_keymap, + .keymap_size = ARRAY_SIZE(uib_keymap), +}; + +static struct tc3589x_keypad_platform_data tc35893_data = { + .krow = TC_KPD_ROWS, + .kcol = TC_KPD_COLUMNS, + .debounce_period = TC_KPD_DEBOUNCE_PERIOD, + .settle_time = TC_KPD_SETTLE_TIME, + .irqtype = IRQF_TRIGGER_FALLING, + .enable_wakeup = true, + .keymap_data = &uib_keymap_data, + .no_autorepeat = true, +}; + +static struct tc3589x_platform_data tc3589x_keypad_data = { + .block = TC3589x_BLOCK_KEYPAD, + .keypad = &tc35893_data, + .irq_base = MOP500_EGPIO_IRQ_BASE, +}; + +static struct i2c_board_info mop500_i2c0_devices_uib[] = { + { + I2C_BOARD_INFO("tc3589x", 0x44), + .platform_data = &tc3589x_keypad_data, + .irq = NOMADIK_GPIO_TO_IRQ(218), + .flags = I2C_CLIENT_WAKE, + }, +}; + void mop500_keypad_init(void) { db8500_add_ske_keypad(&ske_keypad_board); i2c_register_board_info(0, mop500_i2c0_devices_stuib, ARRAY_SIZE(mop500_i2c0_devices_stuib)); + + i2c_register_board_info(0, mop500_i2c0_devices_uib, + ARRAY_SIZE(mop500_i2c0_devices_uib)); + }