From df93f1f4eeb02529c13d1f6be832ab6ff7cd8222 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 21 Jan 2011 09:19:05 +0100 Subject: [PATCH 01/35] mach-ux500: add DB5500 PMU resources This adds the PMU resources necessary to get perf working with the DB5500 ASIC. Acked-by: Will Deacon Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/cpu-db5500.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index af04e0891a78..38a01c361263 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -11,6 +11,7 @@ #include #include +#include #include @@ -43,6 +44,26 @@ static struct map_desc u5500_io_desc[] __initdata = { __IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K), }; +static struct resource db5500_pmu_resources[] = { + [0] = { + .start = IRQ_DB5500_PMU0, + .end = IRQ_DB5500_PMU0, + .flags = IORESOURCE_IRQ, + }, + [1] = { + .start = IRQ_DB5500_PMU1, + .end = IRQ_DB5500_PMU1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device db5500_pmu_device = { + .name = "arm-pmu", + .id = ARM_PMU_DEVICE_CPU, + .num_resources = ARRAY_SIZE(db5500_pmu_resources), + .resource = db5500_pmu_resources, +}; + static struct resource mbox0_resources[] = { { .name = "mbox_peer", @@ -127,7 +148,8 @@ static struct platform_device mbox2_device = { .num_resources = ARRAY_SIZE(mbox2_resources), }; -static struct platform_device *u5500_platform_devs[] __initdata = { +static struct platform_device *db5500_platform_devs[] __initdata = { + &db5500_pmu_device, &mbox0_device, &mbox1_device, &mbox2_device, @@ -172,6 +194,6 @@ void __init u5500_init_devices(void) db5500_dma_init(); db5500_add_rtc(); - platform_add_devices(u5500_platform_devs, - ARRAY_SIZE(u5500_platform_devs)); + platform_add_devices(db5500_platform_devs, + ARRAY_SIZE(db5500_platform_devs)); } From d1de85a23144e922a1f2971be74076020f340090 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 2 Dec 2010 17:10:14 +0100 Subject: [PATCH 02/35] mach-ux500: add a few AB8500 regulator consumers v3 Try to make the regulators a little bit more useful by adding some of the most basic consumers we're going to have in the end. Cc: Mark Brown Cc: Rabin Vincent Cc: Naveen Kumar Gaddipati Cc: Bengt Jonsson Cc: Lee Jones Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-regulators.c | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500-regulators.c b/arch/arm/mach-ux500/board-mop500-regulators.c index 533967c2d095..875c91b2f8a4 100644 --- a/arch/arm/mach-ux500/board-mop500-regulators.c +++ b/arch/arm/mach-ux500/board-mop500-regulators.c @@ -11,6 +11,56 @@ #include #include #include +#include "board-mop500-regulators.h" + +static struct regulator_consumer_supply ab8500_vaux1_consumers[] = { + /* External displays, connector on board 2v5 power supply */ + REGULATOR_SUPPLY("vaux12v5", "mcde.0"), + /* SFH7741 proximity sensor */ + REGULATOR_SUPPLY("vcc", "gpio-keys.0"), + /* BH1780GLS ambient light sensor */ + REGULATOR_SUPPLY("vcc", "2-0029"), + /* lsm303dlh accelerometer */ + REGULATOR_SUPPLY("vdd", "3-0018"), + /* lsm303dlh magnetometer */ + REGULATOR_SUPPLY("vdd", "3-001e"), + /* Rohm BU21013 Touchscreen devices */ + REGULATOR_SUPPLY("avdd", "3-005c"), + REGULATOR_SUPPLY("avdd", "3-005d"), + /* Synaptics RMI4 Touchscreen device */ + REGULATOR_SUPPLY("vdd", "3-004b"), +}; + +static struct regulator_consumer_supply ab8500_vaux2_consumers[] = { + /* On-board eMMC power */ + REGULATOR_SUPPLY("vmmc", "sdi4"), + /* AB8500 audio codec */ + REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"), +}; + +static struct regulator_consumer_supply ab8500_vaux3_consumers[] = { + /* External MMC slot power */ + REGULATOR_SUPPLY("vmmc", "sdi0"), +}; + +static struct regulator_consumer_supply ab8500_vtvout_consumers[] = { + /* TV-out DENC supply */ + REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"), + /* Internal general-purpose ADC */ + REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"), +}; + +static struct regulator_consumer_supply ab8500_vintcore_consumers[] = { + /* SoC core supply, no device */ + REGULATOR_SUPPLY("v-intcore", NULL), + /* USB Transciever */ + REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"), +}; + +static struct regulator_consumer_supply ab8500_vana_consumers[] = { + /* External displays, connector on board, 1v8 power supply */ + REGULATOR_SUPPLY("vsmps2", "mcde.0"), +}; /* AB8500 regulators */ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { @@ -23,6 +73,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers), + .consumer_supplies = ab8500_vaux1_consumers, }, /* supplies to the on-board eMMC */ [AB8500_LDO_AUX2] = { @@ -33,6 +85,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers), + .consumer_supplies = ab8500_vaux2_consumers, }, /* supply for VAUX3, supplies to SDcard slots */ [AB8500_LDO_AUX3] = { @@ -43,6 +97,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers), + .consumer_supplies = ab8500_vaux3_consumers, }, /* supply for tvout, gpadc, TVOUT LDO */ [AB8500_LDO_TVOUT] = { @@ -50,6 +106,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { .name = "V-TVOUT", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers), + .consumer_supplies = ab8500_vtvout_consumers, }, /* supply for ab8500-vaudio, VAUDIO LDO */ [AB8500_LDO_AUDIO] = { @@ -85,6 +143,8 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { .name = "V-INTCORE", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers), + .consumer_supplies = ab8500_vintcore_consumers, }, /* supply for U8500 CSI/DSI, VANA LDO */ [AB8500_LDO_ANA] = { @@ -92,5 +152,7 @@ struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = { .name = "V-CSI/DSI", .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + .num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers), + .consumer_supplies = ab8500_vana_consumers, }, }; From 871056e7dfb6164ffd6c6665752f921f9d5c6a81 Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Fri, 21 Jan 2011 10:56:15 +0530 Subject: [PATCH 03/35] mach-ux500: fix ux500 build error Include ab8500 regulators for DB8500 SoC by default and fix build issues Signed-off-by: Sundar Iyer [Small fixup for changed boardfiles] Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 53ebb429e971..0352272dc600 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -7,12 +7,12 @@ 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) += board-mop500.o board-mop500-sdi.o \ - board-mop500-keypads.o + board-mop500-keypads.o \ + board-mop500-regulators.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 -obj-$(CONFIG_REGULATOR_AB8500) += board-mop500-regulators.o obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o From 705e0984444bc7109c5686c36333b27119d8a888 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 21 Jan 2011 10:56:16 +0530 Subject: [PATCH 04/35] mach-ux500: dynamic UIB (user interface boards) detection Add support for dynamic detection of the UIB used (at the cost of one i2c error on the lesser-used UIB) and also provide an override via a command line parameter if needed. Signed-off-by: Rabin Vincent Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 4 +- arch/arm/mach-ux500/board-mop500-stuib.c | 14 ++ arch/arm/mach-ux500/board-mop500-u8500uib.c | 14 ++ arch/arm/mach-ux500/board-mop500-uib.c | 135 ++++++++++++++++++++ arch/arm/mach-ux500/board-mop500.c | 2 - arch/arm/mach-ux500/board-mop500.h | 8 +- 6 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-ux500/board-mop500-stuib.c create mode 100644 arch/arm/mach-ux500/board-mop500-u8500uib.c create mode 100644 arch/arm/mach-ux500/board-mop500-uib.c diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 0352272dc600..ef67952ed420 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -8,7 +8,9 @@ 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) += board-mop500.o board-mop500-sdi.o \ board-mop500-keypads.o \ - board-mop500-regulators.o + board-mop500-regulators.o \ + board-mop500-uib.o board-mop500-stuib.o \ + board-mop500-u8500uib.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-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c new file mode 100644 index 000000000000..7fa30217cc01 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-stuib.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include +#include + +#include "board-mop500.h" + +void __init mop500_stuib_init(void) +{ +} diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c new file mode 100644 index 000000000000..e81c65b2f721 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL), version 2 + */ + +#include +#include + +#include "board-mop500.h" + +void __init mop500_u8500uib_init(void) +{ +} diff --git a/arch/arm/mach-ux500/board-mop500-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c new file mode 100644 index 000000000000..69cce41f602a --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-uib.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Rabin Vincent for ST-Ericsson + * License terms: GNU General Public License (GPL), version 2 + */ + +#define pr_fmt(fmt) "mop500-uib: " fmt + +#include +#include +#include + +#include +#include "board-mop500.h" + +enum mop500_uib { + STUIB, + U8500UIB, +}; + +struct uib { + const char *name; + const char *option; + void (*init)(void); +}; + +static struct __initdata uib mop500_uibs[] = { + [STUIB] = { + .name = "ST-UIB", + .option = "stuib", + .init = mop500_stuib_init, + }, + [U8500UIB] = { + .name = "U8500-UIB", + .option = "u8500uib", + .init = mop500_u8500uib_init, + }, +}; + +static struct uib *mop500_uib; + +static int __init mop500_uib_setup(char *str) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) { + struct uib *uib = &mop500_uibs[i]; + + if (!strcmp(str, uib->option)) { + mop500_uib = uib; + break; + } + } + + if (i == ARRAY_SIZE(mop500_uibs)) + pr_err("invalid uib= option (%s)\n", str); + + return 1; +} +__setup("uib=", mop500_uib_setup); + +/* + * The UIBs are detected after the I2C host controllers are registered, so + * i2c_register_board_info() can't be used. + */ +void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, + unsigned n) +{ + struct i2c_adapter *adap; + struct i2c_client *client; + int i; + + adap = i2c_get_adapter(busnum); + if (!adap) { + pr_err("failed to get adapter i2c%d\n", busnum); + return; + } + + for (i = 0; i < n; i++) { + client = i2c_new_device(adap, &info[i]); + if (!client) + pr_err("failed to register %s to i2c%d\n", + info[i].type, busnum); + } + + i2c_put_adapter(adap); +} + +static void __init __mop500_uib_init(struct uib *uib, const char *why) +{ + pr_info("%s (%s)\n", uib->name, why); + uib->init(); +} + +/* + * Detect the UIB attached based on the presence or absence of i2c devices. + */ +static int __init mop500_uib_init(void) +{ + struct uib *uib = mop500_uib; + struct i2c_adapter *i2c0; + int ret; + + if (!cpu_is_u8500()) + return -ENODEV; + + if (uib) { + __mop500_uib_init(uib, "from uib= boot argument"); + return 0; + } + + i2c0 = i2c_get_adapter(0); + if (!i2c0) { + __mop500_uib_init(&mop500_uibs[STUIB], + "fallback, could not get i2c0"); + return -ENODEV; + } + + /* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */ + ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0, + I2C_SMBUS_QUICK, NULL); + i2c_put_adapter(i2c0); + + if (ret == 0) + uib = &mop500_uibs[U8500UIB]; + else + uib = &mop500_uibs[STUIB]; + + __mop500_uib_init(uib, "detected"); + + return 0; +} + +module_init(mop500_uib_init); diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index a393f57ed2a8..1a839ccad4f8 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -207,8 +207,6 @@ 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 3104ae2a02c2..cedf8ebaad95 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -14,8 +14,14 @@ #define GPIO_SDMMC_EN MOP500_EGPIO(17) #define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18) +struct i2c_board_info; + extern void mop500_sdi_init(void); extern void mop500_sdi_tc35892_init(void); -extern void mop500_keypad_init(void); +void __init mop500_u8500uib_init(void); +void __init mop500_stuib_init(void); + +void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, + unsigned n); #endif From 0c24352eada58dc3571647593e516b2d5b50014f Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Fri, 21 Jan 2011 10:56:17 +0530 Subject: [PATCH 05/35] mach-ux500: add ST-UIB platform data The ST-UIB contains a matrix keypad interfaced with the STMPE1601 port expander and a ROHM BU2101 touch panel. Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-stuib.c | 183 +++++++++++++++++++++++ arch/arm/mach-ux500/board-mop500.h | 1 + 2 files changed, 184 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c index 7fa30217cc01..8b6323e229ff 100644 --- a/arch/arm/mach-ux500/board-mop500-stuib.c +++ b/arch/arm/mach-ux500/board-mop500-stuib.c @@ -6,9 +6,192 @@ #include #include +#include +#include +#include +#include +#include +#include #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), +}; +/* + * 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, + }, +}; + +/* + * BU21013 ROHM touchscreen interface on the STUIBs + */ + +/* tracks number of bu21013 devices being enabled */ +static int bu21013_devices; + +#define TOUCH_GPIO_PIN 84 + +#define TOUCH_XMAX 384 +#define TOUCH_YMAX 704 + +#define PRCMU_CLOCK_OCR 0x1CC +#define TSC_EXT_CLOCK_9_6MHZ 0x840000 + +/** + * bu21013_gpio_board_init : configures the touch panel. + * @reset_pin: reset pin number + * This function can be used to configures + * the voltage and reset the touch panel controller. + */ +static int bu21013_gpio_board_init(int reset_pin) +{ + int retval = 0; + + bu21013_devices++; + if (bu21013_devices == 1) { + retval = gpio_request(reset_pin, "touchp_reset"); + if (retval) { + printk(KERN_ERR "Unable to request gpio reset_pin"); + return retval; + } + retval = gpio_direction_output(reset_pin, 1); + if (retval < 0) { + printk(KERN_ERR "%s: gpio direction failed\n", + __func__); + return retval; + } + } + + return retval; +} + +/** + * bu21013_gpio_board_exit : deconfigures the touch panel controller + * @reset_pin: reset pin number + * This function can be used to deconfigures the chip selection + * for touch panel controller. + */ +static int bu21013_gpio_board_exit(int reset_pin) +{ + int retval = 0; + + if (bu21013_devices == 1) { + retval = gpio_direction_output(reset_pin, 0); + if (retval < 0) { + printk(KERN_ERR "%s: gpio direction failed\n", + __func__); + return retval; + } + gpio_set_value(reset_pin, 0); + } + bu21013_devices--; + + return retval; +} + +/** + * bu21013_read_pin_val : get the interrupt pin value + * This function can be used to get the interrupt pin value for touch panel + * controller. + */ +static int bu21013_read_pin_val(void) +{ + return gpio_get_value(TOUCH_GPIO_PIN); +} + +static struct bu21013_platform_device tsc_plat_device = { + .cs_en = bu21013_gpio_board_init, + .cs_dis = bu21013_gpio_board_exit, + .irq_read_val = bu21013_read_pin_val, + .irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN), + .cs_pin = GPIO_BU21013_CS, + .touch_x_max = TOUCH_XMAX, + .touch_y_max = TOUCH_YMAX, + .ext_clk = false, + .x_flip = false, + .y_flip = true, +}; + +static struct bu21013_platform_device tsc_plat2_device = { + .cs_en = bu21013_gpio_board_init, + .cs_dis = bu21013_gpio_board_exit, + .irq_read_val = bu21013_read_pin_val, + .irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN), + .cs_pin = GPIO_BU21013_CS, + .touch_x_max = TOUCH_XMAX, + .touch_y_max = TOUCH_YMAX, + .ext_clk = false, + .x_flip = false, + .y_flip = true, +}; + +static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = { + { + I2C_BOARD_INFO("bu21013_tp", 0x5C), + .platform_data = &tsc_plat_device, + }, + { + I2C_BOARD_INFO("bu21013_tp", 0x5D), + .platform_data = &tsc_plat2_device, + }, + +}; + void __init mop500_stuib_init(void) { + mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib, + ARRAY_SIZE(mop500_i2c0_devices_stuib)); + + mop500_uib_i2c_add(3, u8500_i2c3_devices_stuib, + ARRAY_SIZE(u8500_i2c3_devices_stuib)); } diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index cedf8ebaad95..fe22b84f89ea 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -11,6 +11,7 @@ /* GPIOs on the TC35892 expander */ #define GPIO_SDMMC_CD MOP500_EGPIO(3) +#define GPIO_BU21013_CS MOP500_EGPIO(13) #define GPIO_SDMMC_EN MOP500_EGPIO(17) #define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18) From 71f933f4efe8395d4f3da6979cab6a01f2c5411b Mon Sep 17 00:00:00 2001 From: Sundar Iyer Date: Fri, 21 Jan 2011 10:56:18 +0530 Subject: [PATCH 06/35] mach-ux500: add U8500 UIB platform data The U8500 UIB contains a Synaptics RMI touchpanel and a matrix keyboard via the TC35893 port expander device. Signed-off-by: Sundar Iyer Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-u8500uib.c | 97 +++++++++++++++++++++ arch/arm/mach-ux500/board-mop500.c | 3 + 2 files changed, 100 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c index e81c65b2f721..d8a8734a0eba 100644 --- a/arch/arm/mach-ux500/board-mop500-u8500uib.c +++ b/arch/arm/mach-ux500/board-mop500-u8500uib.c @@ -1,14 +1,111 @@ /* * Copyright (C) ST-Ericsson SA 2010 * + * Board data for the U8500 UIB, also known as the New UIB * License terms: GNU General Public License (GPL), version 2 */ #include #include +#include +#include +#include +#include +#include +#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h> + +#include +#include #include "board-mop500.h" +/* + * Synaptics RMI4 touchscreen interface on the U8500 UIB + */ + +/* + * Descriptor structure. + * Describes the number of i2c devices on the bus that speak RMI. + */ +static struct synaptics_rmi4_platform_data rmi4_i2c_dev_platformdata = { + .irq_number = NOMADIK_GPIO_TO_IRQ(84), + .irq_type = (IRQF_TRIGGER_FALLING | IRQF_SHARED), + .x_flip = false, + .y_flip = true, + .regulator_en = false, +}; + +static struct i2c_board_info __initdata mop500_i2c3_devices_u8500[] = { + { + I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B), + .platform_data = &rmi4_i2c_dev_platformdata, + }, +}; + +/* + * TC35893 + */ +static const unsigned int u8500_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 u8500_keymap_data = { + .keymap = u8500_keymap, + .keymap_size = ARRAY_SIZE(u8500_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 = &u8500_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 __initdata mop500_i2c0_devices_u8500[] = { + { + I2C_BOARD_INFO("tc3589x", 0x44), + .platform_data = &tc3589x_keypad_data, + .irq = NOMADIK_GPIO_TO_IRQ(218), + .flags = I2C_CLIENT_WAKE, + }, +}; + + void __init mop500_u8500uib_init(void) { + mop500_uib_i2c_add(3, mop500_i2c3_devices_u8500, + ARRAY_SIZE(mop500_i2c3_devices_u8500)); + + mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500, + ARRAY_SIZE(mop500_i2c0_devices_u8500)); + } diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 1a839ccad4f8..fd6d5090caea 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -77,6 +77,9 @@ static pin_cfg_t mop500_pins[] = { /* STMPE1601 IRQ */ GPIO218_GPIO | PIN_INPUT_PULLUP, + + /* touch screen */ + GPIO84_GPIO | PIN_INPUT_PULLUP, }; static struct ab8500_platform_data ab8500_platdata = { From b3f1f73d35839f3e40bd9dba2c3de53f56a2a880 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 21 Jan 2011 10:50:08 +0100 Subject: [PATCH 07/35] mach-ux500: delete old keypad board file We register keypads per-UIB now, remove this. Cc: Lee Jones Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 1 - arch/arm/mach-ux500/board-mop500-keypads.c | 229 --------------------- 2 files changed, 230 deletions(-) delete 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 ef67952ed420..1cb588efec82 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -7,7 +7,6 @@ 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) += board-mop500.o board-mop500-sdi.o \ - board-mop500-keypads.o \ board-mop500-regulators.o \ board-mop500-uib.o board-mop500-stuib.o \ board-mop500-u8500uib.o diff --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c deleted file mode 100644 index 70318c354d32..000000000000 --- a/arch/arm/mach-ux500/board-mop500-keypads.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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 - -#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 */ -}; - -/* - * 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 mop500_i2c0_devices_stuib[] = { - { - I2C_BOARD_INFO("stmpe1601", 0x40), - .irq = NOMADIK_GPIO_TO_IRQ(218), - .platform_data = &stmpe1601_data, - .flags = I2C_CLIENT_WAKE, - }, -}; - -/* - * 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)); - -} From a71b819b6edfb31d6866d084167583bd92f4ad29 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 14 Jan 2011 10:53:59 +0100 Subject: [PATCH 08/35] mach-ux500: platform data for SFH7741 proximity sensor driver Proximity sensor is managed as an input event (SW_PROXIMITY). Signed-off-by: Philippe Langlais [Named GPIO pin] Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 52 ++++++++++++++++++++++++++++++ arch/arm/mach-ux500/board-mop500.h | 1 + 2 files changed, 53 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index fd6d5090caea..dce68788be39 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -181,8 +183,58 @@ static void __init mop500_i2c_init(void) db8500_add_i2c3(&u8500_i2c3_data); } +static struct gpio_keys_button mop500_gpio_keys[] = { + { + .desc = "SFH7741 Proximity Sensor", + .type = EV_SW, + .code = SW_FRONT_PROXIMITY, + .gpio = GPIO_PROX_SENSOR, + .active_low = 0, + .can_disable = 1, + } +}; + +static struct regulator *prox_regulator; +static int mop500_prox_activate(struct device *dev); +static void mop500_prox_deactivate(struct device *dev); + +static struct gpio_keys_platform_data mop500_gpio_keys_data = { + .buttons = mop500_gpio_keys, + .nbuttons = ARRAY_SIZE(mop500_gpio_keys), + .enable = mop500_prox_activate, + .disable = mop500_prox_deactivate, +}; + +static struct platform_device mop500_gpio_keys_device = { + .name = "gpio-keys", + .id = 0, + .dev = { + .platform_data = &mop500_gpio_keys_data, + }, +}; + +static int mop500_prox_activate(struct device *dev) +{ + prox_regulator = regulator_get(&mop500_gpio_keys_device.dev, + "vcc"); + if (IS_ERR(prox_regulator)) { + dev_err(&mop500_gpio_keys_device.dev, + "no regulator\n"); + return PTR_ERR(prox_regulator); + } + regulator_enable(prox_regulator); + return 0; +} + +static void mop500_prox_deactivate(struct device *dev) +{ + regulator_disable(prox_regulator); + regulator_put(prox_regulator); +} + /* add any platform devices here - TODO */ static struct platform_device *platform_devs[] __initdata = { + &mop500_gpio_keys_device, }; static void __init mop500_spi_init(void) diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index fe22b84f89ea..19b6c270d206 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -11,6 +11,7 @@ /* GPIOs on the TC35892 expander */ #define GPIO_SDMMC_CD MOP500_EGPIO(3) +#define GPIO_PROX_SENSOR MOP500_EGPIO(7) #define GPIO_BU21013_CS MOP500_EGPIO(13) #define GPIO_SDMMC_EN MOP500_EGPIO(17) #define GPIO_SDMMC_1V8_3V_SEL MOP500_EGPIO(18) From dd7b2a055622e23c9354bd9b081973c9a15ac639 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 12 Jan 2011 11:26:20 +0100 Subject: [PATCH 09/35] mach-ux500: platform data for LP5521 leds driver Signed-off-by: Philippe Langlais Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 68 +++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index dce68788be39..daebcb4ba709 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -138,14 +139,77 @@ static struct tc3589x_platform_data mop500_tc35892_data = { .irq_base = MOP500_EGPIO_IRQ_BASE, }; +static struct lp5521_led_config lp5521_pri_led[] = { + [0] = { + .chan_nr = 0, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [1] = { + .chan_nr = 1, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [2] = { + .chan_nr = 2, + .led_current = 0x2f, + .max_current = 0x5f, + }, +}; + +static struct lp5521_platform_data __initdata lp5521_pri_data = { + .label = "lp5521_pri", + .led_config = &lp5521_pri_led[0], + .num_channels = 3, + .clock_mode = LP5521_CLOCK_EXT, +}; + +static struct lp5521_led_config lp5521_sec_led[] = { + [0] = { + .chan_nr = 0, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [1] = { + .chan_nr = 1, + .led_current = 0x2f, + .max_current = 0x5f, + }, + [2] = { + .chan_nr = 2, + .led_current = 0x2f, + .max_current = 0x5f, + }, +}; + +static struct lp5521_platform_data __initdata lp5521_sec_data = { + .label = "lp5521_sec", + .led_config = &lp5521_sec_led[0], + .num_channels = 3, + .clock_mode = LP5521_CLOCK_EXT, +}; + static struct i2c_board_info mop500_i2c0_devices[] = { { I2C_BOARD_INFO("tc3589x", 0x42), - .irq = NOMADIK_GPIO_TO_IRQ(217), + .irq = NOMADIK_GPIO_TO_IRQ(217), .platform_data = &mop500_tc35892_data, }, }; +static struct i2c_board_info __initdata mop500_i2c2_devices[] = { + { + /* lp5521 LED driver, 1st device */ + I2C_BOARD_INFO("lp5521", 0x33), + .platform_data = &lp5521_pri_data, + }, + { + /* lp5521 LED driver, 2st device */ + I2C_BOARD_INFO("lp5521", 0x34), + .platform_data = &lp5521_sec_data, + }, +}; + #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ static struct nmk_i2c_controller u8500_i2c##id##_data = { \ /* \ @@ -266,6 +330,8 @@ static void __init u8500_init_machine(void) i2c_register_board_info(0, mop500_i2c0_devices, ARRAY_SIZE(mop500_i2c0_devices)); + i2c_register_board_info(2, mop500_i2c2_devices, + ARRAY_SIZE(mop500_i2c2_devices)); } MACHINE_START(U8500, "ST-Ericsson MOP500 platform") From bb3b218756e061b1e51c1593684be0261482e399 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Thu, 13 Jan 2011 14:41:22 +0000 Subject: [PATCH 10/35] mach-ux500: Add Rohm BH1780GLI Light Sensor to i2c_board_info Signed-off-by: Lee Jones Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index daebcb4ba709..ffe3cf1451a8 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -208,6 +208,10 @@ static struct i2c_board_info __initdata mop500_i2c2_devices[] = { I2C_BOARD_INFO("lp5521", 0x34), .platform_data = &lp5521_sec_data, }, + { + /* Light sensor Rohm BH1780GLI */ + I2C_BOARD_INFO("bh1780", 0x29), + }, }; #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \ From fbdc6d11ae0594fb03f4c5556cbb8ff46e1971e3 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 27 Jan 2011 14:37:07 +0100 Subject: [PATCH 11/35] mach-ux500: set sd/mmc clock rate to 100MHz The clock speed for the SD/MMC clock was incorrect, rectify it. Signed-off-by: Philippe Langlais Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/clock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index b2b0a3b9be8f..9a0a6ed9cd5d 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -313,7 +313,7 @@ static DEFINE_PRCMU_CLK_RATE(uartclk, 0x0, 5, UARTCLK, 38400000); static DEFINE_PRCMU_CLK(msp02clk, 0x0, 6, MSP02CLK); static DEFINE_PRCMU_CLK(msp1clk, 0x0, 7, MSP1CLK); /* v1 */ static DEFINE_PRCMU_CLK_RATE(i2cclk, 0x0, 8, I2CCLK, 48000000); -static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 50000000); +static DEFINE_PRCMU_CLK_RATE(sdmmcclk, 0x0, 9, SDMMCCLK, 100000000); static DEFINE_PRCMU_CLK(slimclk, 0x0, 10, SLIMCLK); static DEFINE_PRCMU_CLK(per1clk, 0x0, 11, PER1CLK); static DEFINE_PRCMU_CLK(per2clk, 0x0, 12, PER2CLK); From 7863513efc4b2829a9d3768b37fdcd46842ac8e6 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 27 Jan 2011 14:35:37 +0100 Subject: [PATCH 12/35] mach-ux500: fix inverted SD-card GPIO pin The levelshifter pins were set to inverted values, fix this up. Signed-off-by: Philippe Langlais 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 4b996676594e..4ba3d930a06e 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -106,8 +106,8 @@ void mop500_sdi_tc35892_init(void) if (ret) return; - gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1); - gpio_direction_output(GPIO_SDMMC_EN, 0); + gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 0); + gpio_direction_output(GPIO_SDMMC_EN, 1); db8500_add_sdi0(&mop500_sdi0_data); } From 07f201d8a30b077b536a9bbc6788724aa8973e31 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Fri, 21 Jan 2011 17:59:56 +0100 Subject: [PATCH 13/35] mach-ux500: add platform data for musb USB resources and DMA40 configurations are dynamically with the data provided in ux500_add_usb() call. Though only DMA40 configurations differ between U8500 and U5500 (USB resource are common between them). Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 2 +- arch/arm/mach-ux500/include/mach/usb.h | 25 ++++ arch/arm/mach-ux500/usb.c | 160 +++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-ux500/include/mach/usb.h create mode 100644 arch/arm/mach-ux500/usb.c diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 1cb588efec82..eec327906686 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 \ - id.o + id.o usb.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) += board-mop500.o board-mop500-sdi.o \ diff --git a/arch/arm/mach-ux500/include/mach/usb.h b/arch/arm/mach-ux500/include/mach/usb.h new file mode 100644 index 000000000000..d3739d418813 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/usb.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Mian Yousaf Kaukab + * License terms: GNU General Public License (GPL) version 2 + */ +#ifndef __ASM_ARCH_USB_H +#define __ASM_ARCH_USB_H + +#include + +#define UX500_MUSB_DMA_NUM_RX_CHANNELS 8 +#define UX500_MUSB_DMA_NUM_TX_CHANNELS 8 + +struct ux500_musb_board_data { + void **dma_rx_param_array; + void **dma_tx_param_array; + u32 num_rx_channels; + u32 num_tx_channels; + bool (*dma_filter)(struct dma_chan *chan, void *filter_param); +}; + +void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, + int *dma_tx_cfg); +#endif diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c new file mode 100644 index 000000000000..82e535953fd9 --- /dev/null +++ b/arch/arm/mach-ux500/usb.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Mian Yousaf Kaukab + * License terms: GNU General Public License (GPL) version 2 + */ +#include +#include +#include +#include +#include + +#define MUSB_DMA40_RX_CH { \ + .mode = STEDMA40_MODE_LOGICAL, \ + .dir = STEDMA40_PERIPH_TO_MEM, \ + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, \ + .src_info.data_width = STEDMA40_WORD_WIDTH, \ + .dst_info.data_width = STEDMA40_WORD_WIDTH, \ + .src_info.psize = STEDMA40_PSIZE_LOG_16, \ + .dst_info.psize = STEDMA40_PSIZE_LOG_16, \ + } + +#define MUSB_DMA40_TX_CH { \ + .mode = STEDMA40_MODE_LOGICAL, \ + .dir = STEDMA40_MEM_TO_PERIPH, \ + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, \ + .src_info.data_width = STEDMA40_WORD_WIDTH, \ + .dst_info.data_width = STEDMA40_WORD_WIDTH, \ + .src_info.psize = STEDMA40_PSIZE_LOG_16, \ + .dst_info.psize = STEDMA40_PSIZE_LOG_16, \ + } + +static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS] + = { + MUSB_DMA40_RX_CH, + MUSB_DMA40_RX_CH, + MUSB_DMA40_RX_CH, + MUSB_DMA40_RX_CH, + MUSB_DMA40_RX_CH, + MUSB_DMA40_RX_CH, + MUSB_DMA40_RX_CH, + MUSB_DMA40_RX_CH +}; + +static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_TX_CHANNELS] + = { + MUSB_DMA40_TX_CH, + MUSB_DMA40_TX_CH, + MUSB_DMA40_TX_CH, + MUSB_DMA40_TX_CH, + MUSB_DMA40_TX_CH, + MUSB_DMA40_TX_CH, + MUSB_DMA40_TX_CH, + MUSB_DMA40_TX_CH, +}; + +static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_CHANNELS] = { + &musb_dma_rx_ch[0], + &musb_dma_rx_ch[1], + &musb_dma_rx_ch[2], + &musb_dma_rx_ch[3], + &musb_dma_rx_ch[4], + &musb_dma_rx_ch[5], + &musb_dma_rx_ch[6], + &musb_dma_rx_ch[7] +}; + +static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_TX_CHANNELS] = { + &musb_dma_tx_ch[0], + &musb_dma_tx_ch[1], + &musb_dma_tx_ch[2], + &musb_dma_tx_ch[3], + &musb_dma_tx_ch[4], + &musb_dma_tx_ch[5], + &musb_dma_tx_ch[6], + &musb_dma_tx_ch[7] +}; + +static struct ux500_musb_board_data musb_board_data = { + .dma_rx_param_array = ux500_dma_rx_param_array, + .dma_tx_param_array = ux500_dma_tx_param_array, + .num_rx_channels = UX500_MUSB_DMA_NUM_RX_CHANNELS, + .num_tx_channels = UX500_MUSB_DMA_NUM_TX_CHANNELS, + .dma_filter = stedma40_filter, +}; + +static u64 ux500_musb_dmamask = DMA_BIT_MASK(32); + +static struct musb_hdrc_config musb_hdrc_config = { + .multipoint = true, + .dyn_fifo = true, + .num_eps = 16, + .ram_bits = 16, +}; + +static struct musb_hdrc_platform_data musb_platform_data = { +#if defined(CONFIG_USB_MUSB_OTG) + .mode = MUSB_OTG, +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) + .mode = MUSB_PERIPHERAL, +#else /* defined(CONFIG_USB_MUSB_HOST) */ + .mode = MUSB_HOST, +#endif + .config = &musb_hdrc_config, + .board_data = &musb_board_data, +}; + +static struct resource usb_resources[] = { + [0] = { + .name = "usb-mem", + .flags = IORESOURCE_MEM, + }, + + [1] = { + .name = "mc", /* hard-coded in musb */ + .flags = IORESOURCE_IRQ, + }, +}; + +struct platform_device ux500_musb_device = { + .name = "musb-ux500", + .id = 0, + .dev = { + .platform_data = &musb_platform_data, + .dma_mask = &ux500_musb_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(usb_resources), + .resource = usb_resources, +}; + +static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type) +{ + u32 idx; + + for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_CHANNELS; idx++) + musb_dma_rx_ch[idx].src_dev_type = src_dev_type[idx]; +} + +static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type) +{ + u32 idx; + + for (idx = 0; idx < UX500_MUSB_DMA_NUM_TX_CHANNELS; idx++) + musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx]; +} + +void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, + int *dma_tx_cfg) +{ + ux500_musb_device.resource[0].start = base; + ux500_musb_device.resource[0].end = base + SZ_64K - 1; + ux500_musb_device.resource[1].start = irq; + ux500_musb_device.resource[1].end = irq; + + ux500_usb_dma_update_rx_ch_config(dma_rx_cfg); + ux500_usb_dma_update_tx_ch_config(dma_tx_cfg); + + platform_device_register(&ux500_musb_device); +} From 7f0709efe65a1a46f9b0affb6b5d27d31bae450a Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Fri, 21 Jan 2011 18:05:40 +0100 Subject: [PATCH 14/35] mach-ux500: update MUSB clock configurations MUSB driver has been updated to separate out BSP layer from its generic parts, as separate driver. This patch configures the clock with the new platform driver name. Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/clock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/clock.c b/arch/arm/mach-ux500/clock.c index 9a0a6ed9cd5d..32ce90840ee1 100644 --- a/arch/arm/mach-ux500/clock.c +++ b/arch/arm/mach-ux500/clock.c @@ -520,7 +520,7 @@ static struct clk_lookup u8500_ed_clks[] = { CLK(ssp0_ed, "ssp0", NULL), /* Peripheral Cluster #5 */ - CLK(usb_ed, "musb_hdrc.0", "usb"), + CLK(usb_ed, "musb-ux500.0", "usb"), /* Peripheral Cluster #6 */ CLK(dmc_ed, "dmc", NULL), @@ -561,7 +561,7 @@ static struct clk_lookup u8500_v1_clks[] = { CLK(ssp0_v1, "ssp0", NULL), /* Peripheral Cluster #5 */ - CLK(usb_v1, "musb_hdrc.0", "usb"), + CLK(usb_v1, "musb-ux500.0", "usb"), /* Peripheral Cluster #6 */ CLK(mtu1_v1, "mtu1", NULL), From 6f3f3c3f0b5c7b84a99f0aa99658d6c6cee8e700 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Fri, 21 Jan 2011 18:21:50 +0100 Subject: [PATCH 15/35] mach-ux500: add MUSB to db8500 devices - DMA tx and rx maps for usb channels are set to be configured at runtime - GPIO configurations for usb are added - MUSB is enabled with soc specific base address, irq and dma configurations Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500.c | 14 ++++++++++++++ arch/arm/mach-ux500/cpu-db8500.c | 25 +++++++++++++++++++++++++ arch/arm/mach-ux500/devices-db8500.c | 24 ++++++++++++++++++++++-- arch/arm/mach-ux500/devices-db8500.h | 3 +++ 4 files changed, 64 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index ffe3cf1451a8..5babce497415 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -83,6 +83,20 @@ static pin_cfg_t mop500_pins[] = { /* touch screen */ GPIO84_GPIO | PIN_INPUT_PULLUP, + + /* USB OTG */ + GPIO256_USB_NXT | PIN_PULL_DOWN, + GPIO257_USB_STP | PIN_PULL_UP, + GPIO258_USB_XCLK | PIN_PULL_DOWN, + GPIO259_USB_DIR | PIN_PULL_DOWN, + GPIO260_USB_DAT7 | PIN_PULL_DOWN, + GPIO261_USB_DAT6 | PIN_PULL_DOWN, + GPIO262_USB_DAT5 | PIN_PULL_DOWN, + GPIO263_USB_DAT4 | PIN_PULL_DOWN, + GPIO264_USB_DAT3 | PIN_PULL_DOWN, + GPIO265_USB_DAT2 | PIN_PULL_DOWN, + GPIO266_USB_DAT1 | PIN_PULL_DOWN, + GPIO267_USB_DAT0 | PIN_PULL_DOWN, }; static struct ab8500_platform_data ab8500_platdata = { diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 5c0fabf5fa01..516126cb357d 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -23,8 +23,10 @@ #include #include #include +#include #include "devices-db8500.h" +#include "ste-dma40-db8500.h" /* minimum static i/o mapping required to boot U8500 platforms */ static struct map_desc u8500_uart_io_desc[] __initdata = { @@ -154,6 +156,28 @@ static void __init db8500_add_gpios(void) IRQ_DB8500_GPIO0, &pdata); } +static int usb_db8500_rx_dma_cfg[] = { + DB8500_DMA_DEV38_USB_OTG_IEP_1_9, + DB8500_DMA_DEV37_USB_OTG_IEP_2_10, + DB8500_DMA_DEV36_USB_OTG_IEP_3_11, + DB8500_DMA_DEV19_USB_OTG_IEP_4_12, + DB8500_DMA_DEV18_USB_OTG_IEP_5_13, + DB8500_DMA_DEV17_USB_OTG_IEP_6_14, + DB8500_DMA_DEV16_USB_OTG_IEP_7_15, + DB8500_DMA_DEV39_USB_OTG_IEP_8 +}; + +static int usb_db8500_tx_dma_cfg[] = { + DB8500_DMA_DEV38_USB_OTG_OEP_1_9, + DB8500_DMA_DEV37_USB_OTG_OEP_2_10, + DB8500_DMA_DEV36_USB_OTG_OEP_3_11, + DB8500_DMA_DEV19_USB_OTG_OEP_4_12, + DB8500_DMA_DEV18_USB_OTG_OEP_5_13, + DB8500_DMA_DEV17_USB_OTG_OEP_6_14, + DB8500_DMA_DEV16_USB_OTG_OEP_7_15, + DB8500_DMA_DEV39_USB_OTG_OEP_8 +}; + /* * This function is called from the board init */ @@ -164,6 +188,7 @@ void __init u8500_init_devices(void) db8500_add_rtc(); db8500_add_gpios(); + db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index 23c695d54977..f122d4ee3b2d 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -69,10 +69,30 @@ struct stedma40_chan_cfg dma40_memcpy_conf_log = { * Mapping between destination event lines and physical device address. * The event line is tied to a device and therefor the address is constant. */ -static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV]; +static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = { + /* MUSB - these will be runtime-reconfigured */ + [DB8500_DMA_DEV39_USB_OTG_OEP_8] = -1, + [DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = -1, + [DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = -1, + [DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = -1, + [DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = -1, + [DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1, + [DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1, + [DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1, +}; /* Mapping between source event lines and physical device address */ -static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV]; +static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = { + /* MUSB - these will be runtime-reconfigured */ + [DB8500_DMA_DEV39_USB_OTG_IEP_8] = -1, + [DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = -1, + [DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = -1, + [DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = -1, + [DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = -1, + [DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1, + [DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1, + [DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1, +}; /* Reserved event lines for memcpy only */ static int dma40_memcpy_event[] = { diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index 3a770c756979..d1ea4bd03291 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -61,6 +61,9 @@ db8500_add_ssp(const char *name, resource_size_t base, int irq, #define db8500_add_rtc() \ dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC); +#define db8500_add_usb(rx_cfg, tx_cfg) \ + ux500_add_usb(U8500_USBOTG_BASE, IRQ_DB8500_USBOTG, rx_cfg, tx_cfg) + #define db8500_add_sdi0(pdata) \ dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata) #define db8500_add_sdi1(pdata) \ From 741caea4e518f5374cc9ff7cfaabc0e591416420 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Fri, 21 Jan 2011 18:24:19 +0100 Subject: [PATCH 16/35] mach-ux500: add MUSB to db5500 devices - DMA tx and rx maps for usb channels are set to be configured at runtime - MUSB is enabled with soc specific base address, irq and dma configurations Signed-off-by: Mian Yousaf Kaukab Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/cpu-db5500.c | 25 +++++++++++++++++++++++++ arch/arm/mach-ux500/devices-db5500.h | 3 +++ arch/arm/mach-ux500/dma-db5500.c | 16 ++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 38a01c361263..c9dc2eff3cb2 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c @@ -19,8 +19,10 @@ #include #include #include +#include #include "devices-db5500.h" +#include "ste-dma40-db5500.h" static struct map_desc u5500_uart_io_desc[] __initdata = { __IO_DEV_DESC(U5500_UART0_BASE, SZ_4K), @@ -188,11 +190,34 @@ void __init u5500_map_io(void) iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc)); } +static int usb_db5500_rx_dma_cfg[] = { + DB5500_DMA_DEV4_USB_OTG_IEP_1_9, + DB5500_DMA_DEV5_USB_OTG_IEP_2_10, + DB5500_DMA_DEV6_USB_OTG_IEP_3_11, + DB5500_DMA_DEV20_USB_OTG_IEP_4_12, + DB5500_DMA_DEV21_USB_OTG_IEP_5_13, + DB5500_DMA_DEV22_USB_OTG_IEP_6_14, + DB5500_DMA_DEV23_USB_OTG_IEP_7_15, + DB5500_DMA_DEV38_USB_OTG_IEP_8 +}; + +static int usb_db5500_tx_dma_cfg[] = { + DB5500_DMA_DEV4_USB_OTG_OEP_1_9, + DB5500_DMA_DEV5_USB_OTG_OEP_2_10, + DB5500_DMA_DEV6_USB_OTG_OEP_3_11, + DB5500_DMA_DEV20_USB_OTG_OEP_4_12, + DB5500_DMA_DEV21_USB_OTG_OEP_5_13, + DB5500_DMA_DEV22_USB_OTG_OEP_6_14, + DB5500_DMA_DEV23_USB_OTG_OEP_7_15, + DB5500_DMA_DEV38_USB_OTG_OEP_8 +}; + void __init u5500_init_devices(void) { db5500_add_gpios(); db5500_dma_init(); db5500_add_rtc(); + db5500_add_usb(usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg); platform_add_devices(db5500_platform_devs, ARRAY_SIZE(db5500_platform_devs)); diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h index c8d7901c1f2d..481ae5c51206 100644 --- a/arch/arm/mach-ux500/devices-db5500.h +++ b/arch/arm/mach-ux500/devices-db5500.h @@ -34,6 +34,9 @@ #define db5500_add_rtc() \ dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC); +#define db5500_add_usb(rx_cfg, tx_cfg) \ + ux500_add_usb(U5500_USBOTG_BASE, IRQ_DB5500_USBOTG, rx_cfg, tx_cfg) + #define db5500_add_sdi0(pdata) \ dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata) #define db5500_add_sdi1(pdata) \ diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c index 32a061f8a95b..1cfab68ae417 100644 --- a/arch/arm/mach-ux500/dma-db5500.c +++ b/arch/arm/mach-ux500/dma-db5500.c @@ -73,11 +73,27 @@ static struct stedma40_chan_cfg dma40_memcpy_conf_log = { */ static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = { [DB5500_DMA_DEV24_SDMMC0_RX] = -1, + [DB5500_DMA_DEV38_USB_OTG_IEP_8] = -1, + [DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = -1, + [DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = -1, + [DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = -1, + [DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = -1, + [DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = -1, + [DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = -1, + [DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = -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, + [DB5500_DMA_DEV38_USB_OTG_OEP_8] = -1, + [DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = -1, + [DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = -1, + [DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = -1, + [DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = -1, + [DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = -1, + [DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = -1, + [DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = -1, }; static int dma40_memcpy_event[] = { From 1a721859f8e57ddf3f6df2b5094057f9f536b4d0 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 2 Feb 2011 14:41:19 +0100 Subject: [PATCH 17/35] mach-u300: use mmci driver for GPIO card detect The mmci driver can handle a GPIO pin for card detect, using IRQs and all just fine, so switch to using that. Delete the old bogus input device hack, if userspace need to detect MMC cards it should use udev like everyone else. Signed-off-by: Linus Walleij --- arch/arm/mach-u300/mmc.c | 150 ++++----------------------------------- 1 file changed, 14 insertions(+), 136 deletions(-) diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c index de1ac9ad2213..8bb4ef42ab04 100644 --- a/arch/arm/mach-u300/mmc.c +++ b/arch/arm/mach-u300/mmc.c @@ -13,11 +13,6 @@ #include #include #include -#include -#include -#include -#include -#include #include #include #include @@ -25,137 +20,27 @@ #include "mmc.h" #include "padmux.h" -struct mmci_card_event { - struct input_dev *mmc_input; - int mmc_inserted; - struct work_struct workq; - struct mmci_platform_data mmc0_plat_data; -}; - -static unsigned int mmc_status(struct device *dev) -{ - struct mmci_card_event *mmci_card = container_of( - dev->platform_data, - struct mmci_card_event, mmc0_plat_data); - - return mmci_card->mmc_inserted; -} - -static int mmci_callback(void *data) -{ - struct mmci_card_event *mmci_card = data; - - disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD); - schedule_work(&mmci_card->workq); - - return 0; -} - - -static ssize_t gpio_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct mmci_card_event *mmci_card = container_of( - dev->platform_data, - struct mmci_card_event, mmc0_plat_data); - - - return sprintf(buf, "%d\n", !mmci_card->mmc_inserted); -} - -static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL); - -static void _mmci_callback(struct work_struct *ws) -{ - - struct mmci_card_event *mmci_card = container_of( - ws, - struct mmci_card_event, workq); - - mdelay(20); - - mmci_card->mmc_inserted = !gpio_get_value(U300_GPIO_PIN_MMC_CD); - - input_report_switch(mmci_card->mmc_input, KEY_INSERT, - mmci_card->mmc_inserted); - input_sync(mmci_card->mmc_input); - - pr_debug("MMC/SD card was %s\n", - mmci_card->mmc_inserted ? "inserted" : "removed"); - - enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, mmci_card->mmc_inserted); -} - -int __devinit mmc_init(struct amba_device *adev) -{ - struct mmci_card_event *mmci_card; - struct device *mmcsd_device = &adev->dev; - struct pmx *pmx; - int ret = 0; - - mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL); - if (!mmci_card) - return -ENOMEM; - +static struct mmci_platform_data mmc0_plat_data = { /* * Do not set ocr_mask or voltage translation function, * we have a regulator we can control instead. */ /* Nominally 2.85V on our platform */ - mmci_card->mmc0_plat_data.f_max = 24000000; - mmci_card->mmc0_plat_data.status = mmc_status; - mmci_card->mmc0_plat_data.gpio_wp = -1; - mmci_card->mmc0_plat_data.gpio_cd = -1; - mmci_card->mmc0_plat_data.capabilities = MMC_CAP_MMC_HIGHSPEED | - MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; + .f_max = 24000000, + .gpio_wp = -1, + .gpio_cd = U300_GPIO_PIN_MMC_CD, + .cd_invert = true, + .capabilities = MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, +}; - mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data; +int __devinit mmc_init(struct amba_device *adev) +{ + struct device *mmcsd_device = &adev->dev; + struct pmx *pmx; + int ret = 0; - INIT_WORK(&mmci_card->workq, _mmci_callback); - - ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection"); - if (ret) { - printk(KERN_CRIT "Could not allocate MMC card detection " \ - "GPIO pin\n"); - goto out; - } - - ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD); - if (ret) { - printk(KERN_CRIT "Invalid GPIO pin requested\n"); - goto out; - } - - ret = sysfs_create_file(&mmcsd_device->kobj, - &dev_attr_mmc_inserted.attr); - if (ret) - goto out; - - mmci_card->mmc_input = input_allocate_device(); - if (!mmci_card->mmc_input) { - printk(KERN_CRIT "Could not allocate MMC input device\n"); - return -ENOMEM; - } - - mmci_card->mmc_input->name = "MMC insert notification"; - mmci_card->mmc_input->id.bustype = BUS_HOST; - mmci_card->mmc_input->id.vendor = 0; - mmci_card->mmc_input->id.product = 0; - mmci_card->mmc_input->id.version = 0x0100; - mmci_card->mmc_input->dev.parent = mmcsd_device; - input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT); - - /* - * Since this must always be compiled into the kernel, this input - * is never unregistered or free:ed. - */ - ret = input_register_device(mmci_card->mmc_input); - if (ret) { - input_free_device(mmci_card->mmc_input); - goto out; - } - - input_set_drvdata(mmci_card->mmc_input, mmci_card); + mmcsd_device->platform_data = &mmc0_plat_data; /* * Setup padmuxing for MMC. Since this must always be @@ -171,12 +56,5 @@ int __devinit mmc_init(struct amba_device *adev) pr_warning("Could not activate padmuxing\n"); } - ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback, - mmci_card); - - schedule_work(&mmci_card->workq); - - printk(KERN_INFO "Registered MMC insert/remove notification\n"); -out: return ret; } From ec8f12533b4a439a8feb0d1a3bf15516781804be Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 13 Aug 2010 11:31:59 +0200 Subject: [PATCH 18/35] mach-u300: config U300 PL180 PL011 PL022 for DMA This will configure the platform data for the PL180, PL011 and PL022 PrimeCells found in the U300 to use DMA with the generic PrimeCell DMA engine for COH 901 318. Signed-off-by: Linus Walleij --- arch/arm/mach-u300/core.c | 179 +++++++++++++++++++++++++++++++++----- arch/arm/mach-u300/mmc.c | 12 ++- arch/arm/mach-u300/spi.c | 21 +++-- 3 files changed, 183 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c index aa53ee22438f..513d6abec1f5 100644 --- a/arch/arm/mach-u300/core.c +++ b/arch/arm/mach-u300/core.c @@ -3,7 +3,7 @@ * arch/arm/mach-u300/core.c * * - * Copyright (C) 2007-2010 ST-Ericsson AB + * Copyright (C) 2007-2010 ST-Ericsson SA * License terms: GNU General Public License (GPL) version 2 * Core platform support, IRQ handling and device definitions. * Author: Linus Walleij @@ -16,7 +16,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -96,10 +98,20 @@ void __init u300_map_io(void) * Declaration of devices found on the U300 board and * their respective memory locations. */ + +static struct amba_pl011_data uart0_plat_data = { +#ifdef CONFIG_COH901318 + .dma_filter = coh901318_filter_id, + .dma_rx_param = (void *) U300_DMA_UART0_RX, + .dma_tx_param = (void *) U300_DMA_UART0_TX, +#endif +}; + static struct amba_device uart0_device = { .dev = { + .coherent_dma_mask = ~0, .init_name = "uart0", /* Slow device at 0x3000 offset */ - .platform_data = NULL, + .platform_data = &uart0_plat_data, }, .res = { .start = U300_UART0_BASE, @@ -111,10 +123,19 @@ static struct amba_device uart0_device = { /* The U335 have an additional UART1 on the APP CPU */ #ifdef CONFIG_MACH_U300_BS335 +static struct amba_pl011_data uart1_plat_data = { +#ifdef CONFIG_COH901318 + .dma_filter = coh901318_filter_id, + .dma_rx_param = (void *) U300_DMA_UART1_RX, + .dma_tx_param = (void *) U300_DMA_UART1_TX, +#endif +}; + static struct amba_device uart1_device = { .dev = { + .coherent_dma_mask = ~0, .init_name = "uart1", /* Fast device at 0x7000 offset */ - .platform_data = NULL, + .platform_data = &uart1_plat_data, }, .res = { .start = U300_UART1_BASE, @@ -960,42 +981,37 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = { .priority_high = 0, .dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220, }, + /* + * Don't set up device address, burst count or size of src + * or dst bus for this peripheral - handled by PrimeCell + * DMA extension. + */ { .number = U300_DMA_MMCSD_RX_TX, .name = "MMCSD RX TX", .priority_high = 0, - .dev_addr = U300_MMCSD_BASE + 0x080, .param.config = COH901318_CX_CFG_CH_DISABLE | COH901318_CX_CFG_LCR_DISABLE | COH901318_CX_CFG_TC_IRQ_ENABLE | COH901318_CX_CFG_BE_IRQ_ENABLE, .param.ctrl_lli_chained = 0 | COH901318_CX_CTRL_TC_ENABLE | - COH901318_CX_CTRL_BURST_COUNT_32_BYTES | - COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | - COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | COH901318_CX_CTRL_MASTER_MODE_M1RW | COH901318_CX_CTRL_TCP_ENABLE | - COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_TC_IRQ_DISABLE | COH901318_CX_CTRL_HSP_ENABLE | COH901318_CX_CTRL_HSS_DISABLE | COH901318_CX_CTRL_DDMA_LEGACY, .param.ctrl_lli = 0 | COH901318_CX_CTRL_TC_ENABLE | - COH901318_CX_CTRL_BURST_COUNT_32_BYTES | - COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | - COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | COH901318_CX_CTRL_MASTER_MODE_M1RW | COH901318_CX_CTRL_TCP_ENABLE | - COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_TC_IRQ_DISABLE | COH901318_CX_CTRL_HSP_ENABLE | COH901318_CX_CTRL_HSS_DISABLE | COH901318_CX_CTRL_DDMA_LEGACY, .param.ctrl_lli_last = 0 | COH901318_CX_CTRL_TC_ENABLE | - COH901318_CX_CTRL_BURST_COUNT_32_BYTES | - COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS | - COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS | COH901318_CX_CTRL_MASTER_MODE_M1RW | COH901318_CX_CTRL_TCP_DISABLE | COH901318_CX_CTRL_TC_IRQ_ENABLE | @@ -1014,15 +1030,76 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = { .name = "MSPRO RX", .priority_high = 0, }, + /* + * Don't set up device address, burst count or size of src + * or dst bus for this peripheral - handled by PrimeCell + * DMA extension. + */ { .number = U300_DMA_UART0_TX, .name = "UART0 TX", .priority_high = 0, + .param.config = COH901318_CX_CFG_CH_DISABLE | + COH901318_CX_CFG_LCR_DISABLE | + COH901318_CX_CFG_TC_IRQ_ENABLE | + COH901318_CX_CFG_BE_IRQ_ENABLE, + .param.ctrl_lli_chained = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_ENABLE | + COH901318_CX_CTRL_TC_IRQ_DISABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + .param.ctrl_lli = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_ENABLE | + COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + .param.ctrl_lli_last = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_ENABLE | + COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, }, { .number = U300_DMA_UART0_RX, .name = "UART0 RX", .priority_high = 0, + .param.config = COH901318_CX_CFG_CH_DISABLE | + COH901318_CX_CFG_LCR_DISABLE | + COH901318_CX_CFG_TC_IRQ_ENABLE | + COH901318_CX_CFG_BE_IRQ_ENABLE, + .param.ctrl_lli_chained = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_ENABLE | + COH901318_CX_CTRL_TC_IRQ_DISABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + .param.ctrl_lli = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_ENABLE | + COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + .param.ctrl_lli_last = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_ENABLE | + COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, }, { .number = U300_DMA_APEX_TX, @@ -1080,7 +1157,7 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = { COH901318_CX_CTRL_DST_ADDR_INC_DISABLE | COH901318_CX_CTRL_MASTER_MODE_M1RW | COH901318_CX_CTRL_TCP_ENABLE | - COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_TC_IRQ_DISABLE | COH901318_CX_CTRL_HSP_ENABLE | COH901318_CX_CTRL_HSS_DISABLE | COH901318_CX_CTRL_DDMA_LEGACY | @@ -1252,15 +1329,77 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = { .name = "XGAM PDI", .priority_high = 0, }, + /* + * Don't set up device address, burst count or size of src + * or dst bus for this peripheral - handled by PrimeCell + * DMA extension. + */ { .number = U300_DMA_SPI_TX, .name = "SPI TX", .priority_high = 0, + .param.config = COH901318_CX_CFG_CH_DISABLE | + COH901318_CX_CFG_LCR_DISABLE | + COH901318_CX_CFG_TC_IRQ_ENABLE | + COH901318_CX_CFG_BE_IRQ_ENABLE, + .param.ctrl_lli_chained = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_DISABLE | + COH901318_CX_CTRL_TC_IRQ_DISABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + .param.ctrl_lli = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_DISABLE | + COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + .param.ctrl_lli_last = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_DISABLE | + COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, }, { .number = U300_DMA_SPI_RX, .name = "SPI RX", .priority_high = 0, + .param.config = COH901318_CX_CFG_CH_DISABLE | + COH901318_CX_CFG_LCR_DISABLE | + COH901318_CX_CFG_TC_IRQ_ENABLE | + COH901318_CX_CFG_BE_IRQ_ENABLE, + .param.ctrl_lli_chained = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_DISABLE | + COH901318_CX_CTRL_TC_IRQ_DISABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + .param.ctrl_lli = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_DISABLE | + COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + .param.ctrl_lli_last = 0 | + COH901318_CX_CTRL_TC_ENABLE | + COH901318_CX_CTRL_MASTER_MODE_M1RW | + COH901318_CX_CTRL_TCP_DISABLE | + COH901318_CX_CTRL_TC_IRQ_ENABLE | + COH901318_CX_CTRL_HSP_ENABLE | + COH901318_CX_CTRL_HSS_DISABLE | + COH901318_CX_CTRL_DDMA_LEGACY, + }, { .number = U300_DMA_GENERAL_PURPOSE_0, @@ -1617,7 +1756,7 @@ static void __init u300_init_check_chip(void) #endif #ifdef CONFIG_MACH_U300_BS335 if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) { - printk(KERN_ERR "Platform configured for BS365 " \ + printk(KERN_ERR "Platform configured for BS335 " \ " with DB3350 but %s detected, expect problems!", chipname); } @@ -1692,12 +1831,12 @@ void __init u300_init_devices(void) /* Register subdevices on the I2C buses */ u300_i2c_register_board_devices(); - /* Register subdevices on the SPI bus */ - u300_spi_register_board_devices(); - /* Register the platform devices */ platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); + /* Register subdevices on the SPI bus */ + u300_spi_register_board_devices(); + #ifndef CONFIG_MACH_U300_SEMI_IS_SHARED /* * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c index 8bb4ef42ab04..677ccef5cd32 100644 --- a/arch/arm/mach-u300/mmc.c +++ b/arch/arm/mach-u300/mmc.c @@ -3,19 +3,22 @@ * arch/arm/mach-u300/mmc.c * * - * Copyright (C) 2009 ST-Ericsson AB + * Copyright (C) 2009 ST-Ericsson SA * License terms: GNU General Public License (GPL) version 2 * * Author: Linus Walleij - * Author: Johan Lundin + * Author: Johan Lundin * Author: Jonas Aaberg */ #include #include #include #include +#include #include #include +#include +#include #include "mmc.h" #include "padmux.h" @@ -32,6 +35,11 @@ static struct mmci_platform_data mmc0_plat_data = { .cd_invert = true, .capabilities = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, +#ifdef CONFIG_COH901318 + .dma_filter = coh901318_filter_id, + .dma_rx_param = (void *) U300_DMA_MMCSD_RX_TX, + /* Don't specify a TX channel, this RX channel is bidirectional */ +#endif }; int __devinit mmc_init(struct amba_device *adev) diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c index 00869def5420..5767208f1c1d 100644 --- a/arch/arm/mach-u300/spi.c +++ b/arch/arm/mach-u300/spi.c @@ -11,6 +11,9 @@ #include #include #include +#include +#include + #include "padmux.h" /* @@ -30,11 +33,8 @@ static void select_dummy_chip(u32 chipselect) } struct pl022_config_chip dummy_chip_info = { - /* - * available POLLING_TRANSFER and INTERRUPT_TRANSFER, - * DMA_TRANSFER does not work - */ - .com_mode = INTERRUPT_TRANSFER, + /* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */ + .com_mode = DMA_TRANSFER, .iface = SSP_INTERFACE_MOTOROLA_SPI, /* We can only act as master but SSP_SLAVE is possible in theory */ .hierarchy = SSP_MASTER, @@ -75,8 +75,6 @@ static struct spi_board_info u300_spi_devices[] = { static struct pl022_ssp_controller ssp_platform_data = { /* If you have several SPI buses this varies, we have only bus 0 */ .bus_id = 0, - /* Set this to 1 when we think we got DMA working */ - .enable_dma = 0, /* * On the APP CPU GPIO 4, 5 and 6 are connected as generic * chip selects for SPI. (Same on U330, U335 and U365.) @@ -84,6 +82,14 @@ static struct pl022_ssp_controller ssp_platform_data = { * and do padmuxing accordingly too. */ .num_chipselect = 3, +#ifdef CONFIG_COH901318 + .enable_dma = 1, + .dma_filter = coh901318_filter_id, + .dma_rx_param = (void *) U300_DMA_SPI_RX, + .dma_tx_param = (void *) U300_DMA_SPI_TX, +#else + .enable_dma = 0, +#endif }; @@ -109,6 +115,7 @@ void __init u300_spi_init(struct amba_device *adev) } } + void __init u300_spi_register_board_devices(void) { /* Register any SPI devices */ From 5d7b8467e18b14ed44c5781d77993bfdcd8c826b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 14 Oct 2010 13:57:59 +0200 Subject: [PATCH 19/35] mach-ux500: config Ux500 PL011 PL022 PL180 for DMA This will configure the platform data for the PL011, PL022 and PL180 (derivate) PrimeCells found in the Ux500 to use DMA with the generic DMA engine for DMA40. Signed-off-by: Per Forlin Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-sdi.c | 77 ++++++++++++++ arch/arm/mach-ux500/board-mop500.c | 135 ++++++++++++++++++++++--- arch/arm/mach-ux500/board-u5500-sdi.c | 25 +++++ arch/arm/mach-ux500/board-u5500.c | 6 +- arch/arm/mach-ux500/devices-common.h | 7 +- arch/arm/mach-ux500/devices-db5500.h | 16 +-- arch/arm/mach-ux500/devices-db8500.c | 43 +++++++- arch/arm/mach-ux500/devices-db8500.h | 12 +-- 8 files changed, 288 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 4ba3d930a06e..d1ae6a09979d 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -13,12 +13,14 @@ #include #include +#include #include #include #include "devices-db8500.h" #include "pins-db8500.h" #include "board-mop500.h" +#include "ste-dma40-db8500.h" static pin_cfg_t mop500_sdi_pins[] = { /* SDI0 (MicroSD slot) */ @@ -86,6 +88,26 @@ static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd, MCI_DATA2DIREN | MCI_DATA31DIREN; } +#ifdef CONFIG_STE_DMA40 +struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; + +static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; +#endif + static struct mmci_platform_data mop500_sdi0_data = { .vdd_handler = mop500_sdi0_vdd_handler, .ocr_mask = MMC_VDD_29_30, @@ -93,6 +115,11 @@ static struct mmci_platform_data mop500_sdi0_data = { .capabilities = MMC_CAP_4_BIT_DATA, .gpio_cd = GPIO_SDMMC_CD, .gpio_wp = -1, +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &mop500_sdi0_dma_cfg_rx, + .dma_tx_param = &mop500_sdi0_dma_cfg_tx, +#endif }; void mop500_sdi_tc35892_init(void) @@ -116,18 +143,63 @@ void mop500_sdi_tc35892_init(void) * SDI 2 (POP eMMC, not on DB8500ed) */ +#ifdef CONFIG_STE_DMA40 +struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB8500_DMA_DEV28_SD_MM2_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; + +static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; +#endif + static struct mmci_platform_data mop500_sdi2_data = { .ocr_mask = MMC_VDD_165_195, .f_max = 100000000, .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, .gpio_cd = -1, .gpio_wp = -1, +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &mop500_sdi2_dma_cfg_rx, + .dma_tx_param = &mop500_sdi2_dma_cfg_tx, +#endif }; /* * SDI 4 (on-board eMMC) */ +#ifdef CONFIG_STE_DMA40 +struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB8500_DMA_DEV42_SD_MM4_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; + +static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; +#endif + static struct mmci_platform_data mop500_sdi4_data = { .ocr_mask = MMC_VDD_29_30, .f_max = 100000000, @@ -135,6 +207,11 @@ static struct mmci_platform_data mop500_sdi4_data = { MMC_CAP_MMC_HIGHSPEED, .gpio_cd = -1, .gpio_wp = -1, +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &mop500_sdi4_dma_cfg_rx, + .dma_tx_param = &mop500_sdi4_dma_cfg_tx, +#endif }; void __init mop500_sdi_init(void) diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 5babce497415..67d9c634c05d 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -29,12 +30,14 @@ #include #include +#include #include #include #include #include +#include "ste-dma40-db8500.h" #include "devices-db8500.h" #include "pins-db8500.h" #include "board-mop500.h" @@ -123,16 +126,6 @@ struct platform_device ab8500_device = { .resource = ab8500_resources, }; -static struct pl022_ssp_controller ssp0_platform_data = { - .bus_id = 0, - /* pl022 not yet supports dma */ - .enable_dma = 0, - /* on this platform, gpio 31,142,144,214 & - * 224 are connected as chip selects - */ - .num_chipselect = 5, -}; - /* * TC35892 */ @@ -319,16 +312,132 @@ static struct platform_device *platform_devs[] __initdata = { &mop500_gpio_keys_device, }; +#ifdef CONFIG_STE_DMA40 +static struct stedma40_chan_cfg ssp0_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB8500_DMA_DEV8_SSP0_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.data_width = STEDMA40_BYTE_WIDTH, +}; + +static struct stedma40_chan_cfg ssp0_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV8_SSP0_TX, + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.data_width = STEDMA40_BYTE_WIDTH, +}; +#endif + +static struct pl022_ssp_controller ssp0_platform_data = { + .bus_id = 0, +#ifdef CONFIG_STE_DMA40 + .enable_dma = 1, + .dma_filter = stedma40_filter, + .dma_rx_param = &ssp0_dma_cfg_rx, + .dma_tx_param = &ssp0_dma_cfg_tx, +#else + .enable_dma = 0, +#endif + /* on this platform, gpio 31,142,144,214 & + * 224 are connected as chip selects + */ + .num_chipselect = 5, +}; + static void __init mop500_spi_init(void) { db8500_add_ssp0(&ssp0_platform_data); } +#ifdef CONFIG_STE_DMA40 +static struct stedma40_chan_cfg uart0_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB8500_DMA_DEV13_UART0_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.data_width = STEDMA40_BYTE_WIDTH, +}; + +static struct stedma40_chan_cfg uart0_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV13_UART0_TX, + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.data_width = STEDMA40_BYTE_WIDTH, +}; + +static struct stedma40_chan_cfg uart1_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB8500_DMA_DEV12_UART1_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.data_width = STEDMA40_BYTE_WIDTH, +}; + +static struct stedma40_chan_cfg uart1_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV12_UART1_TX, + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.data_width = STEDMA40_BYTE_WIDTH, +}; + +static struct stedma40_chan_cfg uart2_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB8500_DMA_DEV11_UART2_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.data_width = STEDMA40_BYTE_WIDTH, +}; + +static struct stedma40_chan_cfg uart2_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB8500_DMA_DEV11_UART2_TX, + .src_info.data_width = STEDMA40_BYTE_WIDTH, + .dst_info.data_width = STEDMA40_BYTE_WIDTH, +}; +#endif + +static struct amba_pl011_data uart0_plat = { +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &uart0_dma_cfg_rx, + .dma_tx_param = &uart0_dma_cfg_tx, +#endif +}; + +static struct amba_pl011_data uart1_plat = { +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &uart1_dma_cfg_rx, + .dma_tx_param = &uart1_dma_cfg_tx, +#endif +}; + +static struct amba_pl011_data uart2_plat = { +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &uart2_dma_cfg_rx, + .dma_tx_param = &uart2_dma_cfg_tx, +#endif +}; + static void __init mop500_uart_init(void) { - db8500_add_uart0(); - db8500_add_uart1(); - db8500_add_uart2(); + db8500_add_uart0(&uart0_plat); + db8500_add_uart1(&uart1_plat); + db8500_add_uart2(&uart2_plat); } static void __init u8500_init_machine(void) diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c index 54712acc0394..739fb4c5b160 100644 --- a/arch/arm/mach-ux500/board-u5500-sdi.c +++ b/arch/arm/mach-ux500/board-u5500-sdi.c @@ -31,6 +31,26 @@ static pin_cfg_t u5500_sdi_pins[] = { GPIO14_MC0_CLK | PIN_DIR_OUTPUT | PIN_VAL_LOW, }; +#ifdef CONFIG_STE_DMA40 +struct stedma40_chan_cfg u5500_sdi0_dma_cfg_rx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_PERIPH_TO_MEM, + .src_dev_type = DB5500_DMA_DEV24_SDMMC0_RX, + .dst_dev_type = STEDMA40_DEV_DST_MEMORY, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; + +static struct stedma40_chan_cfg u5500_sdi0_dma_cfg_tx = { + .mode = STEDMA40_MODE_LOGICAL, + .dir = STEDMA40_MEM_TO_PERIPH, + .src_dev_type = STEDMA40_DEV_SRC_MEMORY, + .dst_dev_type = DB5500_DMA_DEV24_SDMMC0_TX, + .src_info.data_width = STEDMA40_WORD_WIDTH, + .dst_info.data_width = STEDMA40_WORD_WIDTH, +}; +#endif + static struct mmci_platform_data u5500_sdi0_data = { .ocr_mask = MMC_VDD_165_195, .f_max = 50000000, @@ -39,6 +59,11 @@ static struct mmci_platform_data u5500_sdi0_data = { MMC_CAP_MMC_HIGHSPEED, .gpio_cd = -1, .gpio_wp = -1, +#ifdef CONFIG_STE_DMA40 + .dma_filter = stedma40_filter, + .dma_rx_param = &u5500_sdi0_dma_cfg_rx, + .dma_tx_param = &u5500_sdi0_dma_cfg_tx, +#endif }; void __init u5500_sdi_init(void) diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 39d370c1f3b4..44fd3b5c33ec 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -22,9 +22,9 @@ static void __init u5500_uart_init(void) { - db5500_add_uart0(); - db5500_add_uart1(); - db5500_add_uart2(); + db5500_add_uart0(NULL); + db5500_add_uart1(NULL); + db5500_add_uart2(NULL); } static void __init u5500_init_machine(void) diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index cbadc117d2db..c719b5a1d913 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -42,10 +42,13 @@ dbx500_add_sdi(const char *name, resource_size_t base, int irq, return dbx500_add_amba_device(name, base, irq, pdata, 0); } +struct amba_pl011_data; + static inline struct amba_device * -dbx500_add_uart(const char *name, resource_size_t base, int irq) +dbx500_add_uart(const char *name, resource_size_t base, int irq, + struct amba_pl011_data *pdata) { - return dbx500_add_amba_device(name, base, irq, NULL, 0); + return dbx500_add_amba_device(name, base, irq, pdata, 0); } struct nmk_i2c_controller; diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h index 481ae5c51206..94627f7783b0 100644 --- a/arch/arm/mach-ux500/devices-db5500.h +++ b/arch/arm/mach-ux500/devices-db5500.h @@ -57,13 +57,13 @@ #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) +#define db5500_add_uart0(plat) \ + dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0, plat) +#define db5500_add_uart1(plat) \ + dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1, plat) +#define db5500_add_uart2(plat) \ + dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2, plat) +#define db5500_add_uart3(plat) \ + dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, plat) #endif diff --git a/arch/arm/mach-ux500/devices-db8500.c b/arch/arm/mach-ux500/devices-db8500.c index f122d4ee3b2d..73b17404b194 100644 --- a/arch/arm/mach-ux500/devices-db8500.c +++ b/arch/arm/mach-ux500/devices-db8500.c @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -67,7 +68,9 @@ struct stedma40_chan_cfg dma40_memcpy_conf_log = { /* * Mapping between destination event lines and physical device address. - * The event line is tied to a device and therefor the address is constant. + * The event line is tied to a device and therefore the address is constant. + * When the address comes from a primecell it will be configured in runtime + * and we set the address to -1 as a placeholder. */ static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = { /* MUSB - these will be runtime-reconfigured */ @@ -79,6 +82,25 @@ static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = { [DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1, [DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1, [DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1, + /* PrimeCells - run-time configured */ + [DB8500_DMA_DEV0_SPI0_TX] = -1, + [DB8500_DMA_DEV1_SD_MMC0_TX] = -1, + [DB8500_DMA_DEV2_SD_MMC1_TX] = -1, + [DB8500_DMA_DEV3_SD_MMC2_TX] = -1, + [DB8500_DMA_DEV8_SSP0_TX] = -1, + [DB8500_DMA_DEV9_SSP1_TX] = -1, + [DB8500_DMA_DEV11_UART2_TX] = -1, + [DB8500_DMA_DEV12_UART1_TX] = -1, + [DB8500_DMA_DEV13_UART0_TX] = -1, + [DB8500_DMA_DEV28_SD_MM2_TX] = -1, + [DB8500_DMA_DEV29_SD_MM0_TX] = -1, + [DB8500_DMA_DEV32_SD_MM1_TX] = -1, + [DB8500_DMA_DEV33_SPI2_TX] = -1, + [DB8500_DMA_DEV35_SPI1_TX] = -1, + [DB8500_DMA_DEV40_SPI3_TX] = -1, + [DB8500_DMA_DEV41_SD_MM3_TX] = -1, + [DB8500_DMA_DEV42_SD_MM4_TX] = -1, + [DB8500_DMA_DEV43_SD_MM5_TX] = -1, }; /* Mapping between source event lines and physical device address */ @@ -92,6 +114,25 @@ static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = { [DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1, [DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1, [DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1, + /* PrimeCells */ + [DB8500_DMA_DEV0_SPI0_RX] = -1, + [DB8500_DMA_DEV1_SD_MMC0_RX] = -1, + [DB8500_DMA_DEV2_SD_MMC1_RX] = -1, + [DB8500_DMA_DEV3_SD_MMC2_RX] = -1, + [DB8500_DMA_DEV8_SSP0_RX] = -1, + [DB8500_DMA_DEV9_SSP1_RX] = -1, + [DB8500_DMA_DEV11_UART2_RX] = -1, + [DB8500_DMA_DEV12_UART1_RX] = -1, + [DB8500_DMA_DEV13_UART0_RX] = -1, + [DB8500_DMA_DEV28_SD_MM2_RX] = -1, + [DB8500_DMA_DEV29_SD_MM0_RX] = -1, + [DB8500_DMA_DEV32_SD_MM1_RX] = -1, + [DB8500_DMA_DEV33_SPI2_RX] = -1, + [DB8500_DMA_DEV35_SPI1_RX] = -1, + [DB8500_DMA_DEV40_SPI3_RX] = -1, + [DB8500_DMA_DEV41_SD_MM3_RX] = -1, + [DB8500_DMA_DEV42_SD_MM4_RX] = -1, + [DB8500_DMA_DEV43_SD_MM5_RX] = -1, }; /* Reserved event lines for memcpy only */ diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index d1ea4bd03291..9cc6f8f5d3e6 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h @@ -91,11 +91,11 @@ db8500_add_ssp(const char *name, resource_size_t base, int irq, #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) +#define db8500_add_uart0(pdata) \ + dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0, pdata) +#define db8500_add_uart1(pdata) \ + dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1, pdata) +#define db8500_add_uart2(pdata) \ + dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, pdata) #endif From e493e06fedd86b484d172f961234f105f295d4d4 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 18 Mar 2010 12:35:22 +0530 Subject: [PATCH 20/35] plat-nomadik: support varying number of GPIOs per block Signed-off-by: Rabin Vincent [Added constant 32-pin assignment in platform data] Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/devices-common.c | 1 + arch/arm/plat-nomadik/gpio.c | 5 ++--- arch/arm/plat-nomadik/include/plat/gpio.h | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index fe69f5fac1bb..13a4ce046ae5 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -139,6 +139,7 @@ void dbx500_add_gpios(resource_size_t *base, int num, int irq, for (i = 0; i < num; i++, first += 32, irq++) { pdata->first_gpio = first; pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first); + pdata->num_gpio = 32; dbx500_add_gpio(i, base[i], irq, pdata); } diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 1e88ecb846d1..30bb92a746e1 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -35,7 +35,6 @@ * Symbols in this file are called "nmk_gpio" for "nomadik gpio" */ -#define NMK_GPIO_PER_CHIP 32 struct nmk_gpio_chip { struct gpio_chip chip; void __iomem *addr; @@ -546,7 +545,7 @@ static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) int i; first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); - for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) { + for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) { set_irq_chip(i, &nmk_gpio_irq_chip); set_irq_handler(i, handle_edge_irq); set_irq_flags(i, IRQF_VALID); @@ -612,7 +611,6 @@ static struct gpio_chip nmk_gpio_template = { .direction_output = nmk_gpio_make_output, .set = nmk_gpio_set_output, .to_irq = nmk_gpio_to_irq, - .ngpio = NMK_GPIO_PER_CHIP, .can_sleep = 0, }; @@ -672,6 +670,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) chip = &nmk_chip->chip; chip->base = pdata->first_gpio; + chip->ngpio = pdata->num_gpio; chip->label = pdata->name ?: dev_name(&dev->dev); chip->dev = &dev->dev; chip->owner = THIS_MODULE; diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index 67b113d639d8..d745f3ac0a61 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -82,6 +82,7 @@ struct nmk_gpio_platform_data { char *name; int first_gpio; int first_irq; + int num_gpio; }; #endif /* __ASM_PLAT_GPIO_H */ From d0b543c772af20f576e204cae442ccfd221631a7 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 4 Mar 2010 17:39:05 +0530 Subject: [PATCH 21/35] plat-nomadik: add custom dbg_show for GPIO Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 92 ++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 30bb92a746e1..5b5fd1ee3c04 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -604,6 +604,97 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset; } +#ifdef CONFIG_DEBUG_FS + +#include + +static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + int mode; + unsigned i; + unsigned gpio = chip->base; + int is_out; + struct nmk_gpio_chip *nmk_chip = + container_of(chip, struct nmk_gpio_chip, chip); + const char *modes[] = { + [NMK_GPIO_ALT_GPIO] = "gpio", + [NMK_GPIO_ALT_A] = "altA", + [NMK_GPIO_ALT_B] = "altB", + [NMK_GPIO_ALT_C] = "altC", + }; + + for (i = 0; i < chip->ngpio; i++, gpio++) { + const char *label = gpiochip_is_requested(chip, i); + bool pull; + u32 bit = 1 << i; + + if (!label) + continue; + + is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit; + pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit); + mode = nmk_gpio_get_mode(gpio); + seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s", + gpio, label, + is_out ? "out" : "in ", + chip->get + ? (chip->get(chip, i) ? "hi" : "lo") + : "? ", + (mode < 0) ? "unknown" : modes[mode], + pull ? "pull" : "none"); + + if (!is_out) { + int irq = gpio_to_irq(gpio); + struct irq_desc *desc = irq_to_desc(irq); + + /* This races with request_irq(), set_irq_type(), + * and set_irq_wake() ... but those are "rare". + * + * More significantly, trigger type flags aren't + * currently maintained by genirq. + */ + if (irq >= 0 && desc->action) { + char *trigger; + + switch (desc->status & IRQ_TYPE_SENSE_MASK) { + case IRQ_TYPE_NONE: + trigger = "(default)"; + break; + case IRQ_TYPE_EDGE_FALLING: + trigger = "edge-falling"; + break; + case IRQ_TYPE_EDGE_RISING: + trigger = "edge-rising"; + break; + case IRQ_TYPE_EDGE_BOTH: + trigger = "edge-both"; + break; + case IRQ_TYPE_LEVEL_HIGH: + trigger = "level-high"; + break; + case IRQ_TYPE_LEVEL_LOW: + trigger = "level-low"; + break; + default: + trigger = "?trigger?"; + break; + } + + seq_printf(s, " irq-%d %s%s", + irq, trigger, + (desc->status & IRQ_WAKEUP) + ? " wakeup" : ""); + } + } + + seq_printf(s, "\n"); + } +} + +#else +#define nmk_gpio_dbg_show NULL +#endif + /* This structure is replicated for each GPIO block allocated at probe time */ static struct gpio_chip nmk_gpio_template = { .direction_input = nmk_gpio_make_input, @@ -611,6 +702,7 @@ static struct gpio_chip nmk_gpio_template = { .direction_output = nmk_gpio_make_output, .set = nmk_gpio_set_output, .to_irq = nmk_gpio_to_irq, + .dbg_show = nmk_gpio_dbg_show, .can_sleep = 0, }; From c84c7c08e320acfd10a0b7e55dbb0bc819b6d284 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 17 Mar 2010 15:19:04 +0530 Subject: [PATCH 22/35] plat-nomadik: implement suspend/resume for GPIO Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 51 ++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 5b5fd1ee3c04..46f1af869b7f 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -44,6 +44,7 @@ struct nmk_gpio_chip { /* Keep track of configured edges */ u32 edge_rising; u32 edge_falling; + u32 backup[10]; }; static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, @@ -792,14 +793,60 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) return ret; } +#ifdef CONFIG_PM +static int nmk_gpio_pm(struct platform_device *dev, bool suspend) +{ + struct nmk_gpio_chip *nmk_chip = platform_get_drvdata(dev); + int i; + static const unsigned int regs[] = { + NMK_GPIO_DAT, + NMK_GPIO_PDIS, + NMK_GPIO_DIR, + NMK_GPIO_AFSLA, + NMK_GPIO_AFSLB, + NMK_GPIO_SLPC, + NMK_GPIO_RIMSC, + NMK_GPIO_FIMSC, + NMK_GPIO_RWIMSC, + NMK_GPIO_FWIMSC, + }; + + BUILD_BUG_ON(ARRAY_SIZE(nmk_chip->backup) != ARRAY_SIZE(regs)); + + /* XXX: is this sufficient? what about pull-up/down configuration? */ + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + if (suspend) + nmk_chip->backup[i] = readl(nmk_chip->addr + regs[i]); + else + writel(nmk_chip->backup[i], nmk_chip->addr + regs[i]); + } + + return 0; +} + +static int nmk_gpio_suspend(struct platform_device *dev, pm_message_t state) +{ + return nmk_gpio_pm(dev, true); +} + +static int nmk_gpio_resume(struct platform_device *dev) +{ + return nmk_gpio_pm(dev, false); +} +#else +#define nmk_gpio_suspend NULL +#define nmk_gpio_resume NULL +#endif + static struct platform_driver nmk_gpio_driver = { .driver = { .owner = THIS_MODULE, .name = "gpio", }, .probe = nmk_gpio_probe, - .suspend = NULL, /* to be done */ - .resume = NULL, + .suspend = nmk_gpio_suspend, + .resume = nmk_gpio_resume, }; static int __init nmk_gpio_init(void) From 33b744b35189baaa260f526cf117392095331843 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 14 Oct 2010 10:38:03 +0530 Subject: [PATCH 23/35] plat-nomadik: support secondary GPIO interrupts When GPIOs wake up the system from sleep mode, the normal GPIO interrupt handler does not hit and the normal interrupt status register does not contain the status. Instead the secondary GPIO handler does, and the interrupt status needs to be retrieved from the wakeup status saved by the suspend/resume code. Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 51 ++++++++++++++++++++--- arch/arm/plat-nomadik/include/plat/gpio.h | 1 + 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 46f1af869b7f..971e5d3798e4 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -39,7 +39,10 @@ struct nmk_gpio_chip { struct gpio_chip chip; void __iomem *addr; struct clk *clk; + unsigned int bank; unsigned int parent_irq; + unsigned int secondary_parent_irq; + u32 (*get_secondary_status)(unsigned int bank); spinlock_t lock; /* Keep track of configured edges */ u32 edge_rising; @@ -514,12 +517,11 @@ static struct irq_chip nmk_gpio_irq_chip = { .irq_set_wake = nmk_gpio_irq_set_wake, }; -static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, + u32 status) { struct nmk_gpio_chip *nmk_chip; struct irq_chip *host_chip = get_irq_chip(irq); - unsigned int gpio_irq; - u32 pending; unsigned int first_irq; if (host_chip->irq_mask_ack) @@ -532,14 +534,33 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) nmk_chip = get_irq_data(irq); first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base); - while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) { - gpio_irq = first_irq + __ffs(pending); - generic_handle_irq(gpio_irq); + while (status) { + int bit = __ffs(status); + + generic_handle_irq(first_irq + bit); + status &= ~BIT(bit); } host_chip->irq_unmask(&desc->irq_data); } +static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + struct nmk_gpio_chip *nmk_chip = get_irq_data(irq); + u32 status = readl(nmk_chip->addr + NMK_GPIO_IS); + + __nmk_gpio_irq_handler(irq, desc, status); +} + +static void nmk_gpio_secondary_irq_handler(unsigned int irq, + struct irq_desc *desc) +{ + struct nmk_gpio_chip *nmk_chip = get_irq_data(irq); + u32 status = nmk_chip->get_secondary_status(nmk_chip->bank); + + __nmk_gpio_irq_handler(irq, desc, status); +} + static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) { unsigned int first_irq; @@ -553,8 +574,16 @@ static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip) set_irq_chip_data(i, nmk_chip); set_irq_type(i, IRQ_TYPE_EDGE_FALLING); } + set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler); set_irq_data(nmk_chip->parent_irq, nmk_chip); + + if (nmk_chip->secondary_parent_irq >= 0) { + set_irq_chained_handler(nmk_chip->secondary_parent_irq, + nmk_gpio_secondary_irq_handler); + set_irq_data(nmk_chip->secondary_parent_irq, nmk_chip); + } + return 0; } @@ -714,6 +743,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) struct gpio_chip *chip; struct resource *res; struct clk *clk; + int secondary_irq; int irq; int ret; @@ -732,6 +762,12 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) goto out; } + secondary_irq = platform_get_irq(dev, 1); + if (secondary_irq >= 0 && !pdata->get_secondary_status) { + ret = -EINVAL; + goto out; + } + if (request_mem_region(res->start, resource_size(res), dev_name(&dev->dev)) == NULL) { ret = -EBUSY; @@ -755,10 +791,13 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) * The virt address in nmk_chip->addr is in the nomadik register space, * so we can simply convert the resource address, without remapping */ + nmk_chip->bank = dev->id; nmk_chip->clk = clk; nmk_chip->addr = io_p2v(res->start); nmk_chip->chip = nmk_gpio_template; nmk_chip->parent_irq = irq; + nmk_chip->secondary_parent_irq = secondary_irq; + nmk_chip->get_secondary_status = pdata->get_secondary_status; spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index d745f3ac0a61..d108a326a0ab 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -83,6 +83,7 @@ struct nmk_gpio_platform_data { int first_gpio; int first_irq; int num_gpio; + u32 (*get_secondary_status)(unsigned int bank); }; #endif /* __ASM_PLAT_GPIO_H */ From 9c66ee6f55667c5f7e118135d3175b0100e160b9 Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Wed, 13 Oct 2010 13:14:17 +0200 Subject: [PATCH 24/35] plat-nomadik: pull-up/down settings for GPIO resume Suspend/resume didn't take care of pull-up and pull-down settings and writing back the DAT register at resume can change pull up/down settings, depending on pin input value. Output values are now also restored. Signed-off-by: Jonas Aaberg Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/Kconfig | 6 +++ arch/arm/plat-nomadik/gpio.c | 78 ++++++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig index 187f4e84bb22..ad25c963d437 100644 --- a/arch/arm/plat-nomadik/Kconfig +++ b/arch/arm/plat-nomadik/Kconfig @@ -25,4 +25,10 @@ config NOMADIK_GPIO help Support for the Nomadik GPIO controller. +config NOMADIK_GPIO_PM + bool + depends on NOMADIK_GPIO && PM + help + Support PM for the Nomadik GPIO controller. + endif diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 971e5d3798e4..71682a87a878 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -30,11 +30,23 @@ /* * The GPIO module in the Nomadik family of Systems-on-Chip is an * AMBA device, managing 32 pins and alternate functions. The logic block - * is currently only used in the Nomadik. + * is currently used in the Nomadik and ux500. * * Symbols in this file are called "nmk_gpio" for "nomadik gpio" */ +static const u32 backup_regs[] = { + NMK_GPIO_PDIS, + NMK_GPIO_DIR, + NMK_GPIO_AFSLA, + NMK_GPIO_AFSLB, + NMK_GPIO_SLPC, + NMK_GPIO_RIMSC, + NMK_GPIO_FIMSC, + NMK_GPIO_RWIMSC, + NMK_GPIO_FWIMSC, +}; + struct nmk_gpio_chip { struct gpio_chip chip; void __iomem *addr; @@ -47,7 +59,9 @@ struct nmk_gpio_chip { /* Keep track of configured edges */ u32 edge_rising; u32 edge_falling; - u32 backup[10]; + u32 backup[ARRAY_SIZE(backup_regs)]; + /* Bitmap, 1 = pull up, 0 = pull down */ + u32 pull; }; static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, @@ -93,10 +107,13 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, pdis &= ~bit; writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); - if (pull == NMK_GPIO_PULL_UP) + if (pull == NMK_GPIO_PULL_UP) { + nmk_chip->pull |= bit; writel(bit, nmk_chip->addr + NMK_GPIO_DATS); - else if (pull == NMK_GPIO_PULL_DOWN) + } else if (pull == NMK_GPIO_PULL_DOWN) { + nmk_chip->pull &= ~bit; writel(bit, nmk_chip->addr + NMK_GPIO_DATC); + } } static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, @@ -317,6 +334,15 @@ int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull) } /* Mode functions */ +/** + * nmk_gpio_set_mode() - set the mux mode of a gpio pin + * @gpio: pin number + * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A, + * NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C + * + * Sets the mode of the specified pin to one of the alternate functions or + * plain GPIO. + */ int nmk_gpio_set_mode(int gpio, int gpio_mode) { struct nmk_gpio_chip *nmk_chip; @@ -832,35 +858,39 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) return ret; } -#ifdef CONFIG_PM +#ifdef CONFIG_NOMADIK_GPIO_PM static int nmk_gpio_pm(struct platform_device *dev, bool suspend) { struct nmk_gpio_chip *nmk_chip = platform_get_drvdata(dev); int i; - static const unsigned int regs[] = { - NMK_GPIO_DAT, - NMK_GPIO_PDIS, - NMK_GPIO_DIR, - NMK_GPIO_AFSLA, - NMK_GPIO_AFSLB, - NMK_GPIO_SLPC, - NMK_GPIO_RIMSC, - NMK_GPIO_FIMSC, - NMK_GPIO_RWIMSC, - NMK_GPIO_FWIMSC, - }; + u32 dir; + u32 dat; - BUILD_BUG_ON(ARRAY_SIZE(nmk_chip->backup) != ARRAY_SIZE(regs)); - - /* XXX: is this sufficient? what about pull-up/down configuration? */ - - for (i = 0; i < ARRAY_SIZE(regs); i++) { + for (i = 0; i < ARRAY_SIZE(backup_regs); i++) { if (suspend) - nmk_chip->backup[i] = readl(nmk_chip->addr + regs[i]); + nmk_chip->backup[i] = readl(nmk_chip->addr + + backup_regs[i]); else - writel(nmk_chip->backup[i], nmk_chip->addr + regs[i]); + writel(nmk_chip->backup[i], + nmk_chip->addr + backup_regs[i]); } + if (!suspend) { + /* + * Restore pull-up and pull-down on inputs and + * outputs. + */ + dir = readl(nmk_chip->addr + NMK_GPIO_DIR); + dat = readl(nmk_chip->addr + NMK_GPIO_DAT); + + writel((nmk_chip->pull & ~dir) | + (dat & dir), + nmk_chip->addr + NMK_GPIO_DATS); + + writel((~nmk_chip->pull & ~dir) | + (~dat & dir), + nmk_chip->addr + NMK_GPIO_DATC); + } return 0; } From 2c8bb0eba96f6027ea1e6cf52376e07d18f54ddc Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Thu, 11 Nov 2010 14:10:38 +0530 Subject: [PATCH 25/35] plat-nomadik: type secondary IRQ correctly Coverity found that we were checking an unsigned variable for >= zero. Type it correctly so that the check works as intended. Signed-off-by: Virupax Sadashivpetimath 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 71682a87a878..cc9de5964d89 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -53,7 +53,7 @@ struct nmk_gpio_chip { struct clk *clk; unsigned int bank; unsigned int parent_irq; - unsigned int secondary_parent_irq; + int secondary_parent_irq; u32 (*get_secondary_status)(unsigned int bank); spinlock_t lock; /* Keep track of configured edges */ From 3546d15c5c3f923f7925f92bfe0f8e1cf8bccc1c Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 25 Nov 2010 11:38:27 +0530 Subject: [PATCH 26/35] plat-nomadik: set altfunc to GPIO when enabling the sleep config Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index cc9de5964d89..bf299cf34594 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -175,6 +175,8 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, int slpm_output = PIN_SLPM_DIR(cfg); int slpm_val = PIN_SLPM_VAL(cfg); + af = NMK_GPIO_ALT_GPIO; + /* * The SLPM_* values are normal values + 1 to allow zero to * mean "same as normal". From 01727e61f0967dd18fadd9dfcee5cf1246e6d8a6 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Mon, 13 Dec 2010 12:02:40 +0530 Subject: [PATCH 27/35] plat-nomadik: implement safe switch sequence for Alt-C Setting pinmux alternative C for a GPIO pin is actually not so easy since it ivolves setting value "1" in two registers, and since the combined result will take effect for intermediate values (01 or 10) this will cause glitches while you wrote one register but have not yet written the other. This patch implements a series of kludges including an optional machine-specific callback to avoid glitches when changing pin mux mode to alternative C. Signed-off-by: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 211 ++++++++++++++++++---- arch/arm/plat-nomadik/include/plat/gpio.h | 1 + 2 files changed, 172 insertions(+), 40 deletions(-) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index bf299cf34594..9f1b72056270 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -47,6 +47,8 @@ static const u32 backup_regs[] = { NMK_GPIO_FWIMSC, }; +#define NMK_GPIO_PER_CHIP 32 + struct nmk_gpio_chip { struct gpio_chip chip; void __iomem *addr; @@ -55,6 +57,7 @@ struct nmk_gpio_chip { unsigned int parent_irq; int secondary_parent_irq; u32 (*get_secondary_status)(unsigned int bank); + void (*set_ioforce)(bool enable); spinlock_t lock; /* Keep track of configured edges */ u32 edge_rising; @@ -64,6 +67,13 @@ struct nmk_gpio_chip { u32 pull; }; +static struct nmk_gpio_chip * +nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)]; + +static DEFINE_SPINLOCK(nmk_gpio_slpm_lock); + +#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips) + static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip, unsigned offset, int gpio_mode) { @@ -138,8 +148,38 @@ static void __nmk_gpio_make_output(struct nmk_gpio_chip *nmk_chip, __nmk_gpio_set_output(nmk_chip, offset, val); } +static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip, + unsigned offset, int gpio_mode, + bool glitch) +{ + u32 rwimsc; + u32 fwimsc; + + if (glitch && nmk_chip->set_ioforce) { + u32 bit = BIT(offset); + + rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); + + /* Prevent spurious wakeups */ + writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC); + writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC); + + nmk_chip->set_ioforce(true); + } + + __nmk_gpio_set_mode(nmk_chip, offset, gpio_mode); + + if (glitch && nmk_chip->set_ioforce) { + nmk_chip->set_ioforce(false); + + writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC); + writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC); + } +} + static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, - pin_cfg_t cfg, bool sleep) + pin_cfg_t cfg, bool sleep, unsigned int *slpmregs) { static const char *afnames[] = { [NMK_GPIO_ALT_GPIO] = "GPIO", @@ -164,6 +204,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, int slpm = PIN_SLPM(cfg); int output = PIN_DIR(cfg); int val = PIN_VAL(cfg); + bool glitch = af == NMK_GPIO_ALT_C; 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], @@ -202,8 +243,116 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, __nmk_gpio_set_pull(nmk_chip, offset, pull); } - __nmk_gpio_set_slpm(nmk_chip, offset, slpm); - __nmk_gpio_set_mode(nmk_chip, offset, af); + /* + * If we've backed up the SLPM registers (glitch workaround), modify + * the backups since they will be restored. + */ + if (slpmregs) { + if (slpm == NMK_GPIO_SLPM_NOCHANGE) + slpmregs[nmk_chip->bank] |= BIT(offset); + else + slpmregs[nmk_chip->bank] &= ~BIT(offset); + } else + __nmk_gpio_set_slpm(nmk_chip, offset, slpm); + + __nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch); +} + +/* + * Safe sequence used to switch IOs between GPIO and Alternate-C mode: + * - Save SLPM registers + * - Set SLPM=0 for the IOs you want to switch and others to 1 + * - Configure the GPIO registers for the IOs that are being switched + * - Set IOFORCE=1 + * - Modify the AFLSA/B registers for the IOs that are being switched + * - Set IOFORCE=0 + * - Restore SLPM registers + * - Any spurious wake up event during switch sequence to be ignored and + * cleared + */ +static void nmk_gpio_glitch_slpm_init(unsigned int *slpm) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + unsigned int temp = slpm[i]; + + if (!chip) + break; + + slpm[i] = readl(chip->addr + NMK_GPIO_SLPC); + writel(temp, chip->addr + NMK_GPIO_SLPC); + } +} + +static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + break; + + writel(slpm[i], chip->addr + NMK_GPIO_SLPC); + } +} + +static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) +{ + static unsigned int slpm[NUM_BANKS]; + unsigned long flags; + bool glitch = false; + int ret = 0; + int i; + + for (i = 0; i < num; i++) { + if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) { + glitch = true; + break; + } + } + + spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); + + if (glitch) { + memset(slpm, 0xff, sizeof(slpm)); + + for (i = 0; i < num; i++) { + int pin = PIN_NUM(cfgs[i]); + int offset = pin % NMK_GPIO_PER_CHIP; + + if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) + slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset); + } + + nmk_gpio_glitch_slpm_init(slpm); + } + + for (i = 0; i < num; i++) { + struct nmk_gpio_chip *nmk_chip; + int pin = PIN_NUM(cfgs[i]); + + nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(pin)); + if (!nmk_chip) { + ret = -EINVAL; + break; + } + + spin_lock(&nmk_chip->lock); + __nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base, + cfgs[i], sleep, glitch ? slpm : NULL); + spin_unlock(&nmk_chip->lock); + } + + if (glitch) + nmk_gpio_glitch_slpm_restore(slpm); + + spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); + + return ret; } /** @@ -222,19 +371,7 @@ static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, */ int nmk_config_pin(pin_cfg_t cfg, bool sleep) { - struct nmk_gpio_chip *nmk_chip; - int gpio = PIN_NUM(cfg); - unsigned long flags; - - nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio)); - if (!nmk_chip) - return -EINVAL; - - spin_lock_irqsave(&nmk_chip->lock, flags); - __nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep); - spin_unlock_irqrestore(&nmk_chip->lock, flags); - - return 0; + return __nmk_config_pins(&cfg, 1, sleep); } EXPORT_SYMBOL(nmk_config_pin); @@ -248,31 +385,13 @@ EXPORT_SYMBOL(nmk_config_pin); */ int nmk_config_pins(pin_cfg_t *cfgs, int num) { - int ret = 0; - int i; - - for (i = 0; i < num; i++) { - ret = nmk_config_pin(cfgs[i], false); - if (ret) - break; - } - - return ret; + return __nmk_config_pins(cfgs, num, false); } 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; + return __nmk_config_pins(cfgs, num, true); } EXPORT_SYMBOL(nmk_config_pins_sleep); @@ -299,9 +418,13 @@ int nmk_gpio_set_slpm(int gpio, enum nmk_gpio_slpm mode) if (!nmk_chip) return -EINVAL; - spin_lock_irqsave(&nmk_chip->lock, flags); + spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); + spin_lock(&nmk_chip->lock); + __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode); - spin_unlock_irqrestore(&nmk_chip->lock, flags); + + spin_unlock(&nmk_chip->lock); + spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); return 0; } @@ -474,7 +597,9 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) if (!nmk_chip) return -EINVAL; - spin_lock_irqsave(&nmk_chip->lock, flags); + spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); + spin_lock(&nmk_chip->lock); + #ifdef CONFIG_ARCH_U8500 if (cpu_is_u8500v2()) { __nmk_gpio_set_slpm(nmk_chip, gpio, @@ -483,7 +608,9 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) } #endif __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); - spin_unlock_irqrestore(&nmk_chip->lock, flags); + + spin_unlock(&nmk_chip->lock); + spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); return 0; } @@ -826,6 +953,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) nmk_chip->parent_irq = irq; nmk_chip->secondary_parent_irq = secondary_irq; nmk_chip->get_secondary_status = pdata->get_secondary_status; + nmk_chip->set_ioforce = pdata->set_ioforce; spin_lock_init(&nmk_chip->lock); chip = &nmk_chip->chip; @@ -839,6 +967,9 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) if (ret) goto out_free; + BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); + + nmk_gpio_chips[nmk_chip->bank] = nmk_chip; platform_set_drvdata(dev, nmk_chip); nmk_gpio_init_irq(nmk_chip); diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index d108a326a0ab..e3a4837e86f4 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -84,6 +84,7 @@ struct nmk_gpio_platform_data { int first_irq; int num_gpio; u32 (*get_secondary_status)(unsigned int bank); + void (*set_ioforce)(bool enable); }; #endif /* __ASM_PLAT_GPIO_H */ From 8b40eeeadc5837c2c01329aa1294e4bef3b35429 Mon Sep 17 00:00:00 2001 From: Rikard Olsson Date: Mon, 3 Jan 2011 14:30:41 +0100 Subject: [PATCH 28/35] plat-nomadik: change sleep/wakeup setting in GPIO SLPM register This patch fixes a bug when setting SLPM register for DB8500. When calling__nmk_gpio_set_slpm(...) offset to GPIO is now used instead of the GPIO number itself. Signed-off-by: Rikard Olsson 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 9f1b72056270..acc9de213246 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -602,7 +602,7 @@ static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) #ifdef CONFIG_ARCH_U8500 if (cpu_is_u8500v2()) { - __nmk_gpio_set_slpm(nmk_chip, gpio, + __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, on ? NMK_GPIO_SLPM_WAKEUP_ENABLE : NMK_GPIO_SLPM_WAKEUP_DISABLE); } From 5317e4d11d1ce4db949f207aaebe09b7d0d76b5f Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 10 Feb 2011 09:29:53 +0530 Subject: [PATCH 29/35] plat-nomadik: get rid of unused GPIO PM code The NOMADIK_GPIO_PM config option is disabled by default, not user visible, and never selected by any other option: the code is therefore unused. The GPIO registers need not be saved and restored since their values are preserved when vAPE (on DB8500) is powered down. Signed-off-by: Rabin Vincent Reviewed-by: Jonas Aberg Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/Kconfig | 6 --- arch/arm/plat-nomadik/gpio.c | 76 ++--------------------------------- 2 files changed, 3 insertions(+), 79 deletions(-) diff --git a/arch/arm/plat-nomadik/Kconfig b/arch/arm/plat-nomadik/Kconfig index ad25c963d437..187f4e84bb22 100644 --- a/arch/arm/plat-nomadik/Kconfig +++ b/arch/arm/plat-nomadik/Kconfig @@ -25,10 +25,4 @@ config NOMADIK_GPIO help Support for the Nomadik GPIO controller. -config NOMADIK_GPIO_PM - bool - depends on NOMADIK_GPIO && PM - help - Support PM for the Nomadik GPIO controller. - endif diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index acc9de213246..5e6653f63286 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -35,18 +35,6 @@ * Symbols in this file are called "nmk_gpio" for "nomadik gpio" */ -static const u32 backup_regs[] = { - NMK_GPIO_PDIS, - NMK_GPIO_DIR, - NMK_GPIO_AFSLA, - NMK_GPIO_AFSLB, - NMK_GPIO_SLPC, - NMK_GPIO_RIMSC, - NMK_GPIO_FIMSC, - NMK_GPIO_RWIMSC, - NMK_GPIO_FWIMSC, -}; - #define NMK_GPIO_PER_CHIP 32 struct nmk_gpio_chip { @@ -62,9 +50,6 @@ struct nmk_gpio_chip { /* Keep track of configured edges */ u32 edge_rising; u32 edge_falling; - u32 backup[ARRAY_SIZE(backup_regs)]; - /* Bitmap, 1 = pull up, 0 = pull down */ - u32 pull; }; static struct nmk_gpio_chip * @@ -117,13 +102,10 @@ static void __nmk_gpio_set_pull(struct nmk_gpio_chip *nmk_chip, pdis &= ~bit; writel(pdis, nmk_chip->addr + NMK_GPIO_PDIS); - if (pull == NMK_GPIO_PULL_UP) { - nmk_chip->pull |= bit; + if (pull == NMK_GPIO_PULL_UP) writel(bit, nmk_chip->addr + NMK_GPIO_DATS); - } else if (pull == NMK_GPIO_PULL_DOWN) { - nmk_chip->pull &= ~bit; + else if (pull == NMK_GPIO_PULL_DOWN) writel(bit, nmk_chip->addr + NMK_GPIO_DATC); - } } static void __nmk_gpio_make_input(struct nmk_gpio_chip *nmk_chip, @@ -991,64 +973,12 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev) return ret; } -#ifdef CONFIG_NOMADIK_GPIO_PM -static int nmk_gpio_pm(struct platform_device *dev, bool suspend) -{ - struct nmk_gpio_chip *nmk_chip = platform_get_drvdata(dev); - int i; - u32 dir; - u32 dat; - - for (i = 0; i < ARRAY_SIZE(backup_regs); i++) { - if (suspend) - nmk_chip->backup[i] = readl(nmk_chip->addr + - backup_regs[i]); - else - writel(nmk_chip->backup[i], - nmk_chip->addr + backup_regs[i]); - } - - if (!suspend) { - /* - * Restore pull-up and pull-down on inputs and - * outputs. - */ - dir = readl(nmk_chip->addr + NMK_GPIO_DIR); - dat = readl(nmk_chip->addr + NMK_GPIO_DAT); - - writel((nmk_chip->pull & ~dir) | - (dat & dir), - nmk_chip->addr + NMK_GPIO_DATS); - - writel((~nmk_chip->pull & ~dir) | - (~dat & dir), - nmk_chip->addr + NMK_GPIO_DATC); - } - return 0; -} - -static int nmk_gpio_suspend(struct platform_device *dev, pm_message_t state) -{ - return nmk_gpio_pm(dev, true); -} - -static int nmk_gpio_resume(struct platform_device *dev) -{ - return nmk_gpio_pm(dev, false); -} -#else -#define nmk_gpio_suspend NULL -#define nmk_gpio_resume NULL -#endif - static struct platform_driver nmk_gpio_driver = { .driver = { .owner = THIS_MODULE, .name = "gpio", - }, + }, .probe = nmk_gpio_probe, - .suspend = nmk_gpio_suspend, - .resume = nmk_gpio_resume, }; static int __init nmk_gpio_init(void) From 3c4bee04d147f149a167633cf0033f9d25a8d720 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 16 Feb 2011 10:37:52 +0100 Subject: [PATCH 30/35] plat-nomadik: fix compilation warning The compiler warns that [rf]wimsc may be used uninitialized in this function - the warning is actually false since the uses are in identical if()-clauses, but it can't hurt very much to read out the values to be modified early anyway and rid the warning. Cc: Rabin Vincent Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 5e6653f63286..45b1cf95e378 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -134,15 +134,12 @@ static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip, unsigned offset, int gpio_mode, bool glitch) { - u32 rwimsc; - u32 fwimsc; + u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); + u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); if (glitch && nmk_chip->set_ioforce) { u32 bit = BIT(offset); - rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC); - fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC); - /* Prevent spurious wakeups */ writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC); writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC); From fe05203b0c4ba0454ba34a858002b12ae4a72faa Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Fri, 11 Feb 2011 17:07:21 -0700 Subject: [PATCH 31/35] mach-ux500: move MOP500 pins to separate file Split off pin definitions for the MOP500 board family to its own file. Signed-off-by: Rabin Vincent Signed-off-by: Mathieu Poirier Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/Makefile | 3 +- arch/arm/mach-ux500/board-mop500-pins.c | 80 +++++++++++++++++++++++++ arch/arm/mach-ux500/board-mop500.c | 63 +------------------ arch/arm/mach-ux500/board-mop500.h | 1 + 4 files changed, 84 insertions(+), 63 deletions(-) create mode 100644 arch/arm/mach-ux500/board-mop500-pins.c diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index eec327906686..b549a8fb4231 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile @@ -9,7 +9,8 @@ obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o devices-db8500.o prcmu.o obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ board-mop500-regulators.o \ board-mop500-uib.o board-mop500-stuib.o \ - board-mop500-u8500uib.o + board-mop500-u8500uib.o \ + board-mop500-pins.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-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c new file mode 100644 index 000000000000..edd3a6bc3d23 --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include +#include + +#include + +#include + +#include "pins-db8500.h" + +static pin_cfg_t mop500_pins[] = { + /* SSP0 */ + GPIO143_SSP0_CLK, + GPIO144_SSP0_FRM, + GPIO145_SSP0_RXD, + GPIO146_SSP0_TXD, + + /* I2C */ + GPIO147_I2C0_SCL, + GPIO148_I2C0_SDA, + GPIO16_I2C1_SCL, + GPIO17_I2C1_SDA, + GPIO10_I2C2_SDA, + GPIO11_I2C2_SCL, + GPIO229_I2C3_SDA, + GPIO230_I2C3_SCL, + + /* SKE keypad */ + GPIO153_KP_I7, + GPIO154_KP_I6, + GPIO155_KP_I5, + GPIO156_KP_I4, + GPIO157_KP_O7, + GPIO158_KP_O6, + GPIO159_KP_O5, + GPIO160_KP_O4, + GPIO161_KP_I3, + GPIO162_KP_I2, + GPIO163_KP_I1, + GPIO164_KP_I0, + GPIO165_KP_O3, + GPIO166_KP_O2, + GPIO167_KP_O1, + GPIO168_KP_O0, + + /* GPIO_EXP_INT */ + GPIO217_GPIO, + + /* STMPE1601 IRQ */ + GPIO218_GPIO | PIN_INPUT_PULLUP, + + /* touch screen */ + GPIO84_GPIO | PIN_INPUT_PULLUP, + + /* USB OTG */ + GPIO256_USB_NXT | PIN_PULL_DOWN, + GPIO257_USB_STP | PIN_PULL_UP, + GPIO258_USB_XCLK | PIN_PULL_DOWN, + GPIO259_USB_DIR | PIN_PULL_DOWN, + GPIO260_USB_DAT7 | PIN_PULL_DOWN, + GPIO261_USB_DAT6 | PIN_PULL_DOWN, + GPIO262_USB_DAT5 | PIN_PULL_DOWN, + GPIO263_USB_DAT4 | PIN_PULL_DOWN, + GPIO264_USB_DAT3 | PIN_PULL_DOWN, + GPIO265_USB_DAT2 | PIN_PULL_DOWN, + GPIO266_USB_DAT1 | PIN_PULL_DOWN, + GPIO267_USB_DAT0 | PIN_PULL_DOWN, +}; + +void __init mop500_pins_init(void) +{ + nmk_config_pins(mop500_pins, + ARRAY_SIZE(mop500_pins)); +} diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 67d9c634c05d..72448e17260f 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -39,69 +38,9 @@ #include "ste-dma40-db8500.h" #include "devices-db8500.h" -#include "pins-db8500.h" #include "board-mop500.h" #include "board-mop500-regulators.h" -static pin_cfg_t mop500_pins[] = { - /* SSP0 */ - GPIO143_SSP0_CLK, - GPIO144_SSP0_FRM, - GPIO145_SSP0_RXD, - GPIO146_SSP0_TXD, - - /* I2C */ - GPIO147_I2C0_SCL, - GPIO148_I2C0_SDA, - GPIO16_I2C1_SCL, - GPIO17_I2C1_SDA, - GPIO10_I2C2_SDA, - GPIO11_I2C2_SCL, - GPIO229_I2C3_SDA, - GPIO230_I2C3_SCL, - - /* SKE keypad */ - GPIO153_KP_I7, - GPIO154_KP_I6, - GPIO155_KP_I5, - GPIO156_KP_I4, - GPIO157_KP_O7, - GPIO158_KP_O6, - GPIO159_KP_O5, - GPIO160_KP_O4, - GPIO161_KP_I3, - GPIO162_KP_I2, - GPIO163_KP_I1, - GPIO164_KP_I0, - GPIO165_KP_O3, - GPIO166_KP_O2, - GPIO167_KP_O1, - GPIO168_KP_O0, - - /* GPIO_EXP_INT */ - GPIO217_GPIO, - - /* STMPE1601 IRQ */ - GPIO218_GPIO | PIN_INPUT_PULLUP, - - /* touch screen */ - GPIO84_GPIO | PIN_INPUT_PULLUP, - - /* USB OTG */ - GPIO256_USB_NXT | PIN_PULL_DOWN, - GPIO257_USB_STP | PIN_PULL_UP, - GPIO258_USB_XCLK | PIN_PULL_DOWN, - GPIO259_USB_DIR | PIN_PULL_DOWN, - GPIO260_USB_DAT7 | PIN_PULL_DOWN, - GPIO261_USB_DAT6 | PIN_PULL_DOWN, - GPIO262_USB_DAT5 | PIN_PULL_DOWN, - GPIO263_USB_DAT4 | PIN_PULL_DOWN, - GPIO264_USB_DAT3 | PIN_PULL_DOWN, - GPIO265_USB_DAT2 | PIN_PULL_DOWN, - GPIO266_USB_DAT1 | PIN_PULL_DOWN, - GPIO267_USB_DAT0 | PIN_PULL_DOWN, -}; - static struct ab8500_platform_data ab8500_platdata = { .irq_base = MOP500_AB8500_IRQ_BASE, .regulator = ab8500_regulators, @@ -444,7 +383,7 @@ static void __init u8500_init_machine(void) { u8500_init_devices(); - nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins)); + mop500_pins_init(); platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index 19b6c270d206..48abca77335c 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -22,6 +22,7 @@ extern void mop500_sdi_init(void); extern void mop500_sdi_tc35892_init(void); void __init mop500_u8500uib_init(void); void __init mop500_stuib_init(void); +void __init mop500_pins_init(void); void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info, unsigned n); From 4bc3a698c3db6592490cd685e395e27216ed2454 Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Tue, 15 Feb 2011 10:46:59 +0100 Subject: [PATCH 32/35] mach-ux500: add hrefv60 GPIO pins This will centralize all GPIO pin muxing for the different boards in the MOP500 family to a single file. It also kills off the deprecated support for the ED (Early Drop) ASIC, this should never be spotted in the open and ST-Ericsson have internally deprecated this hardware. Signed-off-by: Bibek Basu [Rebasing and kill old ASIC support] Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-pins.c | 219 ++++++++++++++++++++---- arch/arm/mach-ux500/board-mop500-sdi.c | 65 +------ 2 files changed, 197 insertions(+), 87 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index edd3a6bc3d23..fd4cf1ca5efd 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -8,19 +8,13 @@ #include #include +#include #include - #include #include "pins-db8500.h" -static pin_cfg_t mop500_pins[] = { - /* SSP0 */ - GPIO143_SSP0_CLK, - GPIO144_SSP0_FRM, - GPIO145_SSP0_RXD, - GPIO146_SSP0_TXD, - +static pin_cfg_t mop500_pins_common[] = { /* I2C */ GPIO147_I2C0_SCL, GPIO148_I2C0_SDA, @@ -31,6 +25,72 @@ static pin_cfg_t mop500_pins[] = { GPIO229_I2C3_SDA, GPIO230_I2C3_SCL, + /* MSP0 */ + GPIO12_MSP0_TXD, + GPIO13_MSP0_TFS, + GPIO14_MSP0_TCK, + GPIO15_MSP0_RXD, + + /* MSP2: HDMI */ + GPIO193_MSP2_TXD, + GPIO194_MSP2_TCK, + GPIO195_MSP2_TFS, + GPIO196_MSP2_RXD | PIN_OUTPUT_LOW, + + /* Touch screen INTERFACE */ + GPIO84_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT1 */ + + /* STMPE1601/tc35893 keypad IRQ */ + GPIO218_GPIO | PIN_INPUT_PULLUP, + + /* MMC0 (MicroSD card) */ + GPIO18_MC0_CMDDIR | PIN_OUTPUT_HIGH, + GPIO19_MC0_DAT0DIR | PIN_OUTPUT_HIGH, + GPIO20_MC0_DAT2DIR | PIN_OUTPUT_HIGH, + + GPIO22_MC0_FBCLK | PIN_INPUT_NOPULL, + GPIO23_MC0_CLK | PIN_OUTPUT_LOW, + GPIO24_MC0_CMD | PIN_INPUT_PULLUP, + GPIO25_MC0_DAT0 | PIN_INPUT_PULLUP, + GPIO26_MC0_DAT1 | PIN_INPUT_PULLUP, + GPIO27_MC0_DAT2 | PIN_INPUT_PULLUP, + GPIO28_MC0_DAT3 | PIN_INPUT_PULLUP, + + /* SDI1 (SDIO) */ + GPIO208_MC1_CLK | PIN_OUTPUT_LOW, + GPIO209_MC1_FBCLK | PIN_INPUT_NOPULL, + GPIO210_MC1_CMD | PIN_INPUT_PULLUP, + GPIO211_MC1_DAT0 | PIN_INPUT_PULLUP, + GPIO212_MC1_DAT1 | PIN_INPUT_PULLUP, + GPIO213_MC1_DAT2 | PIN_INPUT_PULLUP, + GPIO214_MC1_DAT3 | PIN_INPUT_PULLUP, + + /* MMC2 (On-board DATA INTERFACE eMMC) */ + GPIO128_MC2_CLK | PIN_OUTPUT_LOW, + GPIO129_MC2_CMD | PIN_INPUT_PULLUP, + GPIO130_MC2_FBCLK | PIN_INPUT_NOPULL, + GPIO131_MC2_DAT0 | PIN_INPUT_PULLUP, + GPIO132_MC2_DAT1 | PIN_INPUT_PULLUP, + GPIO133_MC2_DAT2 | PIN_INPUT_PULLUP, + GPIO134_MC2_DAT3 | PIN_INPUT_PULLUP, + GPIO135_MC2_DAT4 | PIN_INPUT_PULLUP, + GPIO136_MC2_DAT5 | PIN_INPUT_PULLUP, + GPIO137_MC2_DAT6 | PIN_INPUT_PULLUP, + GPIO138_MC2_DAT7 | PIN_INPUT_PULLUP, + + /* MMC4 (On-board STORAGE INTERFACE eMMC) */ + GPIO197_MC4_DAT3 | PIN_INPUT_PULLUP, + GPIO198_MC4_DAT2 | PIN_INPUT_PULLUP, + GPIO199_MC4_DAT1 | PIN_INPUT_PULLUP, + GPIO200_MC4_DAT0 | PIN_INPUT_PULLUP, + GPIO201_MC4_CMD | PIN_INPUT_PULLUP, + GPIO202_MC4_FBCLK | PIN_INPUT_NOPULL, + GPIO203_MC4_CLK | PIN_OUTPUT_LOW, + GPIO204_MC4_DAT7 | PIN_INPUT_PULLUP, + GPIO205_MC4_DAT6 | PIN_INPUT_PULLUP, + GPIO206_MC4_DAT5 | PIN_INPUT_PULLUP, + GPIO207_MC4_DAT4 | PIN_INPUT_PULLUP, + /* SKE keypad */ GPIO153_KP_I7, GPIO154_KP_I6, @@ -49,32 +109,133 @@ static pin_cfg_t mop500_pins[] = { GPIO167_KP_O1, GPIO168_KP_O0, - /* GPIO_EXP_INT */ - GPIO217_GPIO, + /* UART */ + GPIO0_U0_CTSn | PIN_INPUT_PULLUP, + GPIO1_U0_RTSn | PIN_OUTPUT_HIGH, + GPIO2_U0_RXD | PIN_INPUT_PULLUP, + GPIO3_U0_TXD | PIN_OUTPUT_HIGH, - /* STMPE1601 IRQ */ - GPIO218_GPIO | PIN_INPUT_PULLUP, + GPIO29_U2_RXD | PIN_INPUT_PULLUP, + GPIO30_U2_TXD | PIN_OUTPUT_HIGH, + GPIO31_U2_CTSn | PIN_INPUT_PULLUP, + GPIO32_U2_RTSn | PIN_OUTPUT_HIGH, + + /* Display & HDMI HW sync */ + GPIO68_LCD_VSI0 | PIN_INPUT_PULLUP, + GPIO69_LCD_VSI1 | PIN_INPUT_PULLUP, +}; + +static pin_cfg_t mop500_pins_default[] = { + /* SSP0 */ + GPIO143_SSP0_CLK, + GPIO144_SSP0_FRM, + GPIO145_SSP0_RXD | PIN_PULL_DOWN, + GPIO146_SSP0_TXD, + + + GPIO217_GPIO | PIN_INPUT_PULLUP, /* TC35892 IRQ */ + + /* SDI0 (MicroSD card) */ + GPIO21_MC0_DAT31DIR | PIN_OUTPUT_HIGH, + + /* UART */ + GPIO4_U1_RXD | PIN_INPUT_PULLUP, + GPIO5_U1_TXD | PIN_OUTPUT_HIGH, + GPIO6_U1_CTSn | PIN_INPUT_PULLUP, + GPIO7_U1_RTSn | PIN_OUTPUT_HIGH, +}; + +static pin_cfg_t mop500_pins_hrefv60[] = { + /* WLAN */ + GPIO4_GPIO | PIN_INPUT_PULLUP,/* WLAN_IRQ */ + GPIO85_GPIO | PIN_OUTPUT_LOW,/* WLAN_ENA */ + + /* XENON Flashgun INTERFACE */ + GPIO6_IP_GPIO0 | PIN_INPUT_PULLUP,/* XENON_FLASH_ID */ + GPIO7_IP_GPIO1 | PIN_INPUT_PULLUP,/* XENON_READY */ + GPIO170_GPIO | PIN_OUTPUT_LOW, /* XENON_CHARGE */ + + /* Assistant LED INTERFACE */ + GPIO21_GPIO | PIN_OUTPUT_LOW, /* XENON_EN1 */ + GPIO64_IP_GPIO4 | PIN_OUTPUT_LOW, /* XENON_EN2 */ + + /* Magnetometer */ + GPIO31_GPIO | PIN_INPUT_PULLUP, /* magnetometer_INT */ + GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */ + + /* Display Interface */ + GPIO65_GPIO | PIN_OUTPUT_LOW, /* DISP1 RST */ + GPIO66_GPIO | PIN_OUTPUT_LOW, /* DISP2 RST */ + + /* Touch screen INTERFACE */ + GPIO143_GPIO | PIN_OUTPUT_LOW,/*TOUCH_RST1 */ + + /* Touch screen INTERFACE 2 */ + GPIO67_GPIO | PIN_INPUT_PULLUP, /* TOUCH_INT2 */ + GPIO146_GPIO | PIN_OUTPUT_LOW,/*TOUCH_RST2 */ + + /* ETM_PTM_TRACE INTERFACE */ + GPIO70_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA23 */ + GPIO71_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA22 */ + GPIO72_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA21 */ + GPIO73_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA20 */ + GPIO74_GPIO | PIN_OUTPUT_LOW,/* ETM_PTM_DATA19 */ + + /* NAHJ INTERFACE */ + GPIO76_GPIO | PIN_OUTPUT_LOW,/* NAHJ_CTRL */ + GPIO216_GPIO | PIN_OUTPUT_HIGH,/* NAHJ_CTRL_INV */ + + /* NFC INTERFACE */ + GPIO77_GPIO | PIN_OUTPUT_LOW, /* NFC_ENA */ + GPIO144_GPIO | PIN_INPUT_PULLDOWN, /* NFC_IRQ */ + GPIO142_GPIO | PIN_OUTPUT_LOW, /* NFC_RESET */ + + /* Keyboard MATRIX INTERFACE */ + GPIO90_MC5_CMD | PIN_OUTPUT_LOW, /* KP_O_1 */ + GPIO87_MC5_DAT1 | PIN_OUTPUT_LOW, /* KP_O_2 */ + GPIO86_MC5_DAT0 | PIN_OUTPUT_LOW, /* KP_O_3 */ + GPIO96_KP_O6 | PIN_OUTPUT_LOW, /* KP_O_6 */ + GPIO94_KP_O7 | PIN_OUTPUT_LOW, /* KP_O_7 */ + GPIO93_MC5_DAT4 | PIN_INPUT_PULLUP, /* KP_I_0 */ + GPIO89_MC5_DAT3 | PIN_INPUT_PULLUP, /* KP_I_2 */ + GPIO88_MC5_DAT2 | PIN_INPUT_PULLUP, /* KP_I_3 */ + GPIO91_GPIO | PIN_INPUT_PULLUP, /* FORCE_SENSING_INT */ + GPIO92_GPIO | PIN_OUTPUT_LOW, /* FORCE_SENSING_RST */ + GPIO97_GPIO | PIN_OUTPUT_LOW, /* FORCE_SENSING_WU */ + + /* DiPro Sensor Interface */ + GPIO139_GPIO | PIN_INPUT_PULLUP, /* DIPRO_INT */ + + /* HAL SWITCH INTERFACE */ + GPIO145_GPIO | PIN_INPUT_PULLDOWN,/* HAL_SW */ + + /* Audio Amplifier Interface */ + GPIO149_GPIO | PIN_OUTPUT_LOW, /* VAUDIO_HF_EN */ + + /* GBF INTERFACE */ + GPIO171_GPIO | PIN_OUTPUT_LOW, /* GBF_ENA_RESET */ + + /* MSP : HDTV INTERFACE */ + GPIO192_GPIO | PIN_INPUT_PULLDOWN, + + /* ACCELEROMETER_INTERFACE */ + GPIO82_GPIO | PIN_INPUT_PULLUP, /* ACC_INT1 */ + GPIO83_GPIO | PIN_INPUT_PULLUP, /* ACC_INT2 */ + + /* Proximity Sensor */ + GPIO217_GPIO | PIN_INPUT_PULLUP, - /* touch screen */ - GPIO84_GPIO | PIN_INPUT_PULLUP, - /* USB OTG */ - GPIO256_USB_NXT | PIN_PULL_DOWN, - GPIO257_USB_STP | PIN_PULL_UP, - GPIO258_USB_XCLK | PIN_PULL_DOWN, - GPIO259_USB_DIR | PIN_PULL_DOWN, - GPIO260_USB_DAT7 | PIN_PULL_DOWN, - GPIO261_USB_DAT6 | PIN_PULL_DOWN, - GPIO262_USB_DAT5 | PIN_PULL_DOWN, - GPIO263_USB_DAT4 | PIN_PULL_DOWN, - GPIO264_USB_DAT3 | PIN_PULL_DOWN, - GPIO265_USB_DAT2 | PIN_PULL_DOWN, - GPIO266_USB_DAT1 | PIN_PULL_DOWN, - GPIO267_USB_DAT0 | PIN_PULL_DOWN, }; void __init mop500_pins_init(void) { - nmk_config_pins(mop500_pins, - ARRAY_SIZE(mop500_pins)); + nmk_config_pins(mop500_pins_common, + ARRAY_SIZE(mop500_pins_common)); + if (machine_is_hrefv60()) + nmk_config_pins(mop500_pins_hrefv60, + ARRAY_SIZE(mop500_pins_hrefv60)); + else + nmk_config_pins(mop500_pins_default, + ARRAY_SIZE(mop500_pins_default)); } diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index d1ae6a09979d..68c8375e45c6 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -12,59 +12,14 @@ #include #include -#include #include #include #include #include "devices-db8500.h" -#include "pins-db8500.h" #include "board-mop500.h" #include "ste-dma40-db8500.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, - GPIO199_MC4_DAT1, - GPIO200_MC4_DAT0, - GPIO201_MC4_CMD, - GPIO202_MC4_FBCLK, - GPIO203_MC4_CLK, - GPIO204_MC4_DAT7, - GPIO205_MC4_DAT6, - GPIO206_MC4_DAT5, - GPIO207_MC4_DAT4, -}; - -static pin_cfg_t mop500_sdi2_pins[] = { - /* SDI2 (POP eMMC) */ - GPIO128_MC2_CLK, - GPIO129_MC2_CMD, - GPIO130_MC2_FBCLK, - GPIO131_MC2_DAT0, - GPIO132_MC2_DAT1, - GPIO133_MC2_DAT2, - GPIO134_MC2_DAT3, - GPIO135_MC2_DAT4, - GPIO136_MC2_DAT5, - GPIO137_MC2_DAT6, - GPIO138_MC2_DAT7, -}; - /* * SDI 0 (MicroSD slot) */ @@ -216,22 +171,16 @@ static struct mmci_platform_data mop500_sdi4_data = { void __init mop500_sdi_init(void) { - nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins)); + /* PoP:ed eMMC on top of DB8500 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); + + /* On-board eMMC */ + db8500_add_sdi4(&mop500_sdi4_data); /* * 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); - } - - /* On-board eMMC */ - db8500_add_sdi4(&mop500_sdi4_data); } From 4b4f757c807375564ce3d4ff1d088d3847c52f6d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 15 Feb 2011 15:01:35 +0100 Subject: [PATCH 33/35] mach-ux500: basic HREFv60 support v2 The HREFv60 variant of the MOP500 family of boards remove the external GPIO expander and route these pins back to some of the readily available internal GPIO pins instead. Based on a patch by Bibek Basu for an internal kernel version. Cc: Bibek Basu Signed-off-by: Linus Walleij --- arch/arm/mach-ux500/board-mop500-sdi.c | 42 +++++++++++++++---- arch/arm/mach-ux500/board-mop500-stuib.c | 12 +++++- arch/arm/mach-ux500/board-mop500.c | 23 ++++++++-- arch/arm/mach-ux500/board-mop500.h | 14 ++++++- arch/arm/mach-ux500/include/mach/uncompress.h | 6 ++- 5 files changed, 81 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 68c8375e45c6..bf0b02414e5b 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -68,7 +69,6 @@ static struct mmci_platform_data mop500_sdi0_data = { .ocr_mask = MMC_VDD_29_30, .f_max = 100000000, .capabilities = MMC_CAP_4_BIT_DATA, - .gpio_cd = GPIO_SDMMC_CD, .gpio_wp = -1, #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, @@ -77,23 +77,40 @@ static struct mmci_platform_data mop500_sdi0_data = { #endif }; -void mop500_sdi_tc35892_init(void) +/* GPIO pins used by the sdi0 level shifter */ +static int sdi0_en = -1; +static int sdi0_vsel = -1; + +static void sdi0_configure(void) { int ret; - ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN"); + ret = gpio_request(sdi0_en, "level shifter enable"); if (!ret) - ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL, - "GPIO_SDMMC_1V8_3V_SEL"); - if (ret) + ret = gpio_request(sdi0_vsel, + "level shifter 1v8-3v select"); + + if (ret) { + pr_warning("unable to config sdi0 gpios for level shifter.\n"); return; + } - gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 0); - gpio_direction_output(GPIO_SDMMC_EN, 1); + /* Select the default 2.9V and enable level shifter */ + gpio_direction_output(sdi0_vsel, 0); + gpio_direction_output(sdi0_en, 1); + /* Add the device */ db8500_add_sdi0(&mop500_sdi0_data); } +void mop500_sdi_tc35892_init(void) +{ + mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD; + sdi0_en = GPIO_SDMMC_EN; + sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL; + sdi0_configure(); +} + /* * SDI 2 (POP eMMC, not on DB8500ed) */ @@ -179,8 +196,15 @@ void __init mop500_sdi_init(void) /* On-board eMMC */ db8500_add_sdi4(&mop500_sdi4_data); + if (machine_is_hrefv60()) { + mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO; + sdi0_en = HREFV60_SDMMC_EN_GPIO; + sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO; + sdi0_configure(); + } /* - * sdi0 will finally be added when the TC35892 initializes and calls + * On boards with the TC35892 GPIO expander, sdi0 will finally + * be added when the TC35892 initializes and calls * mop500_sdi_tc35892_init() above. */ } diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c index 8b6323e229ff..8c979770d872 100644 --- a/arch/arm/mach-ux500/board-mop500-stuib.c +++ b/arch/arm/mach-ux500/board-mop500-stuib.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "board-mop500.h" @@ -154,7 +155,6 @@ static struct bu21013_platform_device tsc_plat_device = { .cs_dis = bu21013_gpio_board_exit, .irq_read_val = bu21013_read_pin_val, .irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN), - .cs_pin = GPIO_BU21013_CS, .touch_x_max = TOUCH_XMAX, .touch_y_max = TOUCH_YMAX, .ext_clk = false, @@ -167,7 +167,6 @@ static struct bu21013_platform_device tsc_plat2_device = { .cs_dis = bu21013_gpio_board_exit, .irq_read_val = bu21013_read_pin_val, .irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN), - .cs_pin = GPIO_BU21013_CS, .touch_x_max = TOUCH_XMAX, .touch_y_max = TOUCH_YMAX, .ext_clk = false, @@ -189,6 +188,15 @@ static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = { void __init mop500_stuib_init(void) { + if (machine_is_hrefv60()) { + tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO; + tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO; + } else { + tsc_plat_device.cs_pin = GPIO_BU21013_CS; + tsc_plat2_device.cs_pin = GPIO_BU21013_CS; + + } + mop500_uib_i2c_add(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 72448e17260f..8790d984cac8 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -202,7 +202,6 @@ static struct gpio_keys_button mop500_gpio_keys[] = { .desc = "SFH7741 Proximity Sensor", .type = EV_SW, .code = SW_FRONT_PROXIMITY, - .gpio = GPIO_PROX_SENSOR, .active_low = 0, .can_disable = 1, } @@ -379,8 +378,18 @@ static void __init mop500_uart_init(void) db8500_add_uart2(&uart2_plat); } -static void __init u8500_init_machine(void) +static void __init mop500_init_machine(void) { + /* + * The HREFv60 board removed a GPIO expander and routed + * all these GPIO pins to the internal GPIO controller + * instead. + */ + if (machine_is_hrefv60()) + mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; + else + mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; + u8500_init_devices(); mop500_pins_init(); @@ -407,5 +416,13 @@ MACHINE_START(U8500, "ST-Ericsson MOP500 platform") .init_irq = ux500_init_irq, /* we re-use nomadik timer here */ .timer = &ux500_timer, - .init_machine = u8500_init_machine, + .init_machine = mop500_init_machine, +MACHINE_END + +MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+") + .boot_params = 0x100, + .map_io = u8500_map_io, + .init_irq = ux500_init_irq, + .timer = &ux500_timer, + .init_machine = mop500_init_machine, MACHINE_END diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index 48abca77335c..56722f4be71b 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h @@ -7,9 +7,21 @@ #ifndef __BOARD_MOP500_H #define __BOARD_MOP500_H -#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x)) +/* HREFv60-specific GPIO assignments, this board has no GPIO expander */ +#define HREFV60_TOUCH_RST_GPIO 143 +#define HREFV60_PROX_SENSE_GPIO 217 +#define HREFV60_HAL_SW_GPIO 145 +#define HREFV60_SDMMC_EN_GPIO 169 +#define HREFV60_SDMMC_1V8_3V_GPIO 5 +#define HREFV60_SDMMC_CD_GPIO 95 +#define HREFV60_ACCEL_INT1_GPIO 82 +#define HREFV60_ACCEL_INT2_GPIO 83 +#define HREFV60_MAGNET_DRDY_GPIO 32 +#define HREFV60_DISP1_RST_GPIO 65 +#define HREFV60_DISP2_RST_GPIO 66 /* GPIOs on the TC35892 expander */ +#define MOP500_EGPIO(x) (NOMADIK_NR_GPIO + (x)) #define GPIO_SDMMC_CD MOP500_EGPIO(3) #define GPIO_PROX_SENSOR MOP500_EGPIO(7) #define GPIO_BU21013_CS MOP500_EGPIO(13) diff --git a/arch/arm/mach-ux500/include/mach/uncompress.h b/arch/arm/mach-ux500/include/mach/uncompress.h index 9a6614c6808e..ab0fe1432fae 100644 --- a/arch/arm/mach-ux500/include/mach/uncompress.h +++ b/arch/arm/mach-ux500/include/mach/uncompress.h @@ -50,7 +50,11 @@ static void flush(void) static inline void arch_decomp_setup(void) { - if (machine_is_u8500()) + /* Check in run time if we run on an U8500 or U5500 */ + if (machine_is_u8500() || + machine_is_svp8500v1() || + machine_is_svp8500v2() || + machine_is_hrefv60()) ux500_uart_base = U8500_UART2_BASE; else if (machine_is_u5500()) ux500_uart_base = U5500_UART0_BASE; From 96cb164bdec6f91eadf09a858c4820701f791b37 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 27 Sep 2010 17:40:22 +0200 Subject: [PATCH 34/35] mach-u300: define a dummy filter function for coh901318 All platform data has to be made conditional on as to avoid cluttering the code with other #ifdef:s. Signed-off-by: Linus Walleij --- arch/arm/mach-u300/include/mach/coh901318.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/mach-u300/include/mach/coh901318.h b/arch/arm/mach-u300/include/mach/coh901318.h index 6193aaa47794..7c3b2b2d25b6 100644 --- a/arch/arm/mach-u300/include/mach/coh901318.h +++ b/arch/arm/mach-u300/include/mach/coh901318.h @@ -102,6 +102,7 @@ struct coh901318_platform { const int max_channels; }; +#ifdef CONFIG_COH901318 /** * coh901318_filter_id() - DMA channel filter function * @chan: dma channel handle @@ -110,6 +111,12 @@ struct coh901318_platform { * In dma_request_channel() it specifies what channel id to be requested */ bool coh901318_filter_id(struct dma_chan *chan, void *chan_id); +#else +static inline bool coh901318_filter_id(struct dma_chan *chan, void *chan_id) +{ + return false; +} +#endif /* * DMA Controller - this access the static mappings of the coh901318 dma. From b9df468d8630c583e3597e24ad8cc4c0318790c1 Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Thu, 10 Feb 2011 11:45:58 +0530 Subject: [PATCH 35/35] plat-nomadik: make GPIO interrupts work with cpuidle ApSleep Enable wakeups by default for any GPIO interrupts and in the suspend/resume path narrow this down to only the the real wakeup interrupts. This approach is based on the assumption that cpuidle ApSleep will be entered more often than system suspend. Signed-off-by: Rabin Vincent Reviewed-by: Srinidhi Kasagar [Fixup for genirq changes to struct irq_data on 2.6.38] Signed-off-by: Linus Walleij --- arch/arm/plat-nomadik/gpio.c | 114 ++++++++++++++++++---- arch/arm/plat-nomadik/include/plat/gpio.h | 3 + 2 files changed, 100 insertions(+), 17 deletions(-) diff --git a/arch/arm/plat-nomadik/gpio.c b/arch/arm/plat-nomadik/gpio.c index 45b1cf95e378..70620426ee55 100644 --- a/arch/arm/plat-nomadik/gpio.c +++ b/arch/arm/plat-nomadik/gpio.c @@ -50,6 +50,10 @@ struct nmk_gpio_chip { /* Keep track of configured edges */ u32 edge_rising; u32 edge_falling; + u32 real_wake; + u32 rwimsc; + u32 fwimsc; + u32 slpm; }; static struct nmk_gpio_chip * @@ -534,8 +538,20 @@ static void __nmk_gpio_irq_modify(struct nmk_gpio_chip *nmk_chip, } } -static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which, - bool enable) +static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip, + int gpio, bool on) +{ +#ifdef CONFIG_ARCH_U8500 + if (cpu_is_u8500v2()) { + __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, + on ? NMK_GPIO_SLPM_WAKEUP_ENABLE + : NMK_GPIO_SLPM_WAKEUP_DISABLE); + } +#endif + __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); +} + +static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable) { int gpio; struct nmk_gpio_chip *nmk_chip; @@ -548,45 +564,55 @@ static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which, if (!nmk_chip) return -EINVAL; - spin_lock_irqsave(&nmk_chip->lock, flags); - __nmk_gpio_irq_modify(nmk_chip, gpio, which, enable); - spin_unlock_irqrestore(&nmk_chip->lock, flags); + spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); + spin_lock(&nmk_chip->lock); + + __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable); + + if (!(nmk_chip->real_wake & bitmask)) + __nmk_gpio_set_wake(nmk_chip, gpio, enable); + + spin_unlock(&nmk_chip->lock); + spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); return 0; } static void nmk_gpio_irq_mask(struct irq_data *d) { - nmk_gpio_irq_modify(d, NORMAL, false); + nmk_gpio_irq_maskunmask(d, false); } static void nmk_gpio_irq_unmask(struct irq_data *d) { - nmk_gpio_irq_modify(d, NORMAL, true); + nmk_gpio_irq_maskunmask(d, true); } static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on) { + struct irq_desc *desc = irq_to_desc(d->irq); + bool enabled = !(desc->status & IRQ_DISABLED); struct nmk_gpio_chip *nmk_chip; unsigned long flags; + u32 bitmask; int gpio; gpio = NOMADIK_IRQ_TO_GPIO(d->irq); nmk_chip = irq_data_get_irq_chip_data(d); if (!nmk_chip) return -EINVAL; + bitmask = nmk_gpio_get_bitmask(gpio); spin_lock_irqsave(&nmk_gpio_slpm_lock, flags); spin_lock(&nmk_chip->lock); -#ifdef CONFIG_ARCH_U8500 - if (cpu_is_u8500v2()) { - __nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, - on ? NMK_GPIO_SLPM_WAKEUP_ENABLE - : NMK_GPIO_SLPM_WAKEUP_DISABLE); - } -#endif - __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on); + if (!enabled) + __nmk_gpio_set_wake(nmk_chip, gpio, on); + + if (on) + nmk_chip->real_wake |= bitmask; + else + nmk_chip->real_wake &= ~bitmask; spin_unlock(&nmk_chip->lock); spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags); @@ -620,7 +646,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) if (enabled) __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false); - if (wake) + if (enabled || wake) __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false); nmk_chip->edge_rising &= ~bitmask; @@ -634,7 +660,7 @@ static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type) if (enabled) __nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true); - if (wake) + if (enabled || wake) __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true); spin_unlock_irqrestore(&nmk_chip->lock, flags); @@ -870,6 +896,60 @@ static struct gpio_chip nmk_gpio_template = { .can_sleep = 0, }; +/* + * Called from the suspend/resume path to only keep the real wakeup interrupts + * (those that have had set_irq_wake() called on them) as wakeup interrupts, + * and not the rest of the interrupts which we needed to have as wakeups for + * cpuidle. + * + * PM ops are not used since this needs to be done at the end, after all the + * other drivers are done with their suspend callbacks. + */ +void nmk_gpio_wakeups_suspend(void) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + break; + + chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC); + chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC); + + writel(chip->rwimsc & chip->real_wake, + chip->addr + NMK_GPIO_RWIMSC); + writel(chip->fwimsc & chip->real_wake, + chip->addr + NMK_GPIO_FWIMSC); + + if (cpu_is_u8500v2()) { + chip->slpm = readl(chip->addr + NMK_GPIO_SLPC); + + /* 0 -> wakeup enable */ + writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC); + } + } +} + +void nmk_gpio_wakeups_resume(void) +{ + int i; + + for (i = 0; i < NUM_BANKS; i++) { + struct nmk_gpio_chip *chip = nmk_gpio_chips[i]; + + if (!chip) + break; + + writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC); + writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC); + + if (cpu_is_u8500v2()) + writel(chip->slpm, chip->addr + NMK_GPIO_SLPC); + } +} + static int __devinit nmk_gpio_probe(struct platform_device *dev) { struct nmk_gpio_platform_data *pdata = dev->dev.platform_data; diff --git a/arch/arm/plat-nomadik/include/plat/gpio.h b/arch/arm/plat-nomadik/include/plat/gpio.h index e3a4837e86f4..1b9f6f0843d1 100644 --- a/arch/arm/plat-nomadik/include/plat/gpio.h +++ b/arch/arm/plat-nomadik/include/plat/gpio.h @@ -75,6 +75,9 @@ extern int nmk_gpio_set_pull(int gpio, enum nmk_gpio_pull pull); extern int nmk_gpio_set_mode(int gpio, int gpio_mode); extern int nmk_gpio_get_mode(int gpio); +extern void nmk_gpio_wakeups_suspend(void); +extern void nmk_gpio_wakeups_resume(void); + /* * Platform data to register a block: only the initial gpio/irq number. */