Merge branch 'for-rmk-devel-stable' of git://git.kernel.org/pub/scm/linux/kernel...
authorRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 14 Mar 2011 22:27:03 +0000 (22:27 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Mon, 14 Mar 2011 22:27:03 +0000 (22:27 +0000)
30 files changed:
arch/arm/mach-u300/core.c
arch/arm/mach-u300/include/mach/coh901318.h
arch/arm/mach-u300/mmc.c
arch/arm/mach-u300/spi.c
arch/arm/mach-ux500/Makefile
arch/arm/mach-ux500/board-mop500-keypads.c [deleted file]
arch/arm/mach-ux500/board-mop500-pins.c [new file with mode: 0644]
arch/arm/mach-ux500/board-mop500-regulators.c
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/board-mop500-stuib.c [new file with mode: 0644]
arch/arm/mach-ux500/board-mop500-u8500uib.c [new file with mode: 0644]
arch/arm/mach-ux500/board-mop500-uib.c [new file with mode: 0644]
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/board-u5500-sdi.c
arch/arm/mach-ux500/board-u5500.c
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/cpu-db5500.c
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/devices-common.c
arch/arm/mach-ux500/devices-common.h
arch/arm/mach-ux500/devices-db5500.h
arch/arm/mach-ux500/devices-db8500.c
arch/arm/mach-ux500/devices-db8500.h
arch/arm/mach-ux500/dma-db5500.c
arch/arm/mach-ux500/include/mach/uncompress.h
arch/arm/mach-ux500/include/mach/usb.h [new file with mode: 0644]
arch/arm/mach-ux500/usb.c [new file with mode: 0644]
arch/arm/plat-nomadik/gpio.c
arch/arm/plat-nomadik/include/plat/gpio.h

index aa53ee2..513d6ab 100644 (file)
@@ -3,7 +3,7 @@
  * arch/arm/mach-u300/core.c
  *
  *
- * Copyright (C) 2007-2010 ST-Ericsson AB
+ * Copyright (C) 2007-2010 ST-Ericsson SA
  * License terms: GNU General Public License (GPL) version 2
  * Core platform support, IRQ handling and device definitions.
  * Author: Linus Walleij <linus.walleij@stericsson.com>
@@ -16,7 +16,9 @@
 #include <linux/device.h>
 #include <linux/mm.h>
 #include <linux/termios.h>
+#include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
@@ -96,10 +98,20 @@ void __init u300_map_io(void)
  * Declaration of devices found on the U300 board and
  * their respective memory locations.
  */
+
+static struct amba_pl011_data uart0_plat_data = {
+#ifdef CONFIG_COH901318
+       .dma_filter = coh901318_filter_id,
+       .dma_rx_param = (void *) U300_DMA_UART0_RX,
+       .dma_tx_param = (void *) U300_DMA_UART0_TX,
+#endif
+};
+
 static struct amba_device uart0_device = {
        .dev = {
+               .coherent_dma_mask = ~0,
                .init_name = "uart0", /* Slow device at 0x3000 offset */
-               .platform_data = NULL,
+               .platform_data = &uart0_plat_data,
        },
        .res = {
                .start = U300_UART0_BASE,
@@ -111,10 +123,19 @@ static struct amba_device uart0_device = {
 
 /* The U335 have an additional UART1 on the APP CPU */
 #ifdef CONFIG_MACH_U300_BS335
+static struct amba_pl011_data uart1_plat_data = {
+#ifdef CONFIG_COH901318
+       .dma_filter = coh901318_filter_id,
+       .dma_rx_param = (void *) U300_DMA_UART1_RX,
+       .dma_tx_param = (void *) U300_DMA_UART1_TX,
+#endif
+};
+
 static struct amba_device uart1_device = {
        .dev = {
+               .coherent_dma_mask = ~0,
                .init_name = "uart1", /* Fast device at 0x7000 offset */
-               .platform_data = NULL,
+               .platform_data = &uart1_plat_data,
        },
        .res = {
                .start = U300_UART1_BASE,
@@ -960,42 +981,37 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
                .priority_high = 0,
                .dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220,
        },
+       /*
+        * Don't set up device address, burst count or size of src
+        * or dst bus for this peripheral - handled by PrimeCell
+        * DMA extension.
+        */
        {
                .number = U300_DMA_MMCSD_RX_TX,
                .name = "MMCSD RX TX",
                .priority_high = 0,
-               .dev_addr =  U300_MMCSD_BASE + 0x080,
                .param.config = COH901318_CX_CFG_CH_DISABLE |
                                COH901318_CX_CFG_LCR_DISABLE |
                                COH901318_CX_CFG_TC_IRQ_ENABLE |
                                COH901318_CX_CFG_BE_IRQ_ENABLE,
                .param.ctrl_lli_chained = 0 |
                                COH901318_CX_CTRL_TC_ENABLE |
-                               COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-                               COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-                               COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
                                COH901318_CX_CTRL_MASTER_MODE_M1RW |
                                COH901318_CX_CTRL_TCP_ENABLE |
-                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_DISABLE |
                                COH901318_CX_CTRL_HSP_ENABLE |
                                COH901318_CX_CTRL_HSS_DISABLE |
                                COH901318_CX_CTRL_DDMA_LEGACY,
                .param.ctrl_lli = 0 |
                                COH901318_CX_CTRL_TC_ENABLE |
-                               COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-                               COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-                               COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
                                COH901318_CX_CTRL_MASTER_MODE_M1RW |
                                COH901318_CX_CTRL_TCP_ENABLE |
-                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_DISABLE |
                                COH901318_CX_CTRL_HSP_ENABLE |
                                COH901318_CX_CTRL_HSS_DISABLE |
                                COH901318_CX_CTRL_DDMA_LEGACY,
                .param.ctrl_lli_last = 0 |
                                COH901318_CX_CTRL_TC_ENABLE |
-                               COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-                               COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-                               COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
                                COH901318_CX_CTRL_MASTER_MODE_M1RW |
                                COH901318_CX_CTRL_TCP_DISABLE |
                                COH901318_CX_CTRL_TC_IRQ_ENABLE |
@@ -1014,15 +1030,76 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
                .name = "MSPRO RX",
                .priority_high = 0,
        },
+       /*
+        * Don't set up device address, burst count or size of src
+        * or dst bus for this peripheral - handled by PrimeCell
+        * DMA extension.
+        */
        {
                .number = U300_DMA_UART0_TX,
                .name = "UART0 TX",
                .priority_high = 0,
+               .param.config = COH901318_CX_CFG_CH_DISABLE |
+                               COH901318_CX_CFG_LCR_DISABLE |
+                               COH901318_CX_CFG_TC_IRQ_ENABLE |
+                               COH901318_CX_CFG_BE_IRQ_ENABLE,
+               .param.ctrl_lli_chained = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_DISABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+               .param.ctrl_lli = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+               .param.ctrl_lli_last = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
        },
        {
                .number = U300_DMA_UART0_RX,
                .name = "UART0 RX",
                .priority_high = 0,
+               .param.config = COH901318_CX_CFG_CH_DISABLE |
+                               COH901318_CX_CFG_LCR_DISABLE |
+                               COH901318_CX_CFG_TC_IRQ_ENABLE |
+                               COH901318_CX_CFG_BE_IRQ_ENABLE,
+               .param.ctrl_lli_chained = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_DISABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+               .param.ctrl_lli = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+               .param.ctrl_lli_last = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
        },
        {
                .number = U300_DMA_APEX_TX,
@@ -1080,7 +1157,7 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
                                COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
                                COH901318_CX_CTRL_MASTER_MODE_M1RW |
                                COH901318_CX_CTRL_TCP_ENABLE |
-                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_TC_IRQ_DISABLE |
                                COH901318_CX_CTRL_HSP_ENABLE |
                                COH901318_CX_CTRL_HSS_DISABLE |
                                COH901318_CX_CTRL_DDMA_LEGACY |
@@ -1252,15 +1329,77 @@ const struct coh_dma_channel chan_config[U300_DMA_CHANNELS] = {
                .name = "XGAM PDI",
                .priority_high = 0,
        },
+       /*
+        * Don't set up device address, burst count or size of src
+        * or dst bus for this peripheral - handled by PrimeCell
+        * DMA extension.
+        */
        {
                .number = U300_DMA_SPI_TX,
                .name = "SPI TX",
                .priority_high = 0,
+               .param.config = COH901318_CX_CFG_CH_DISABLE |
+                               COH901318_CX_CFG_LCR_DISABLE |
+                               COH901318_CX_CFG_TC_IRQ_ENABLE |
+                               COH901318_CX_CFG_BE_IRQ_ENABLE,
+               .param.ctrl_lli_chained = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_DISABLE |
+                               COH901318_CX_CTRL_TC_IRQ_DISABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+               .param.ctrl_lli = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_DISABLE |
+                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+               .param.ctrl_lli_last = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_DISABLE |
+                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
        },
        {
                .number = U300_DMA_SPI_RX,
                .name = "SPI RX",
                .priority_high = 0,
+               .param.config = COH901318_CX_CFG_CH_DISABLE |
+                               COH901318_CX_CFG_LCR_DISABLE |
+                               COH901318_CX_CFG_TC_IRQ_ENABLE |
+                               COH901318_CX_CFG_BE_IRQ_ENABLE,
+               .param.ctrl_lli_chained = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_DISABLE |
+                               COH901318_CX_CTRL_TC_IRQ_DISABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+               .param.ctrl_lli = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_DISABLE |
+                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+               .param.ctrl_lli_last = 0 |
+                               COH901318_CX_CTRL_TC_ENABLE |
+                               COH901318_CX_CTRL_MASTER_MODE_M1RW |
+                               COH901318_CX_CTRL_TCP_DISABLE |
+                               COH901318_CX_CTRL_TC_IRQ_ENABLE |
+                               COH901318_CX_CTRL_HSP_ENABLE |
+                               COH901318_CX_CTRL_HSS_DISABLE |
+                               COH901318_CX_CTRL_DDMA_LEGACY,
+
        },
        {
                .number = U300_DMA_GENERAL_PURPOSE_0,
@@ -1617,7 +1756,7 @@ static void __init u300_init_check_chip(void)
 #endif
 #ifdef CONFIG_MACH_U300_BS335
        if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
-               printk(KERN_ERR "Platform configured for BS365 " \
+               printk(KERN_ERR "Platform configured for BS335 " \
                       " with DB3350 but %s detected, expect problems!",
                       chipname);
        }
@@ -1692,12 +1831,12 @@ void __init u300_init_devices(void)
        /* Register subdevices on the I2C buses */
        u300_i2c_register_board_devices();
 
-       /* Register subdevices on the SPI bus */
-       u300_spi_register_board_devices();
-
        /* Register the platform devices */
        platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
+       /* Register subdevices on the SPI bus */
+       u300_spi_register_board_devices();
+
 #ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
        /*
         * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
index 6193aaa..7c3b2b2 100644 (file)
@@ -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.
index de1ac9a..677ccef 100644 (file)
  * arch/arm/mach-u300/mmc.c
  *
  *
- * Copyright (C) 2009 ST-Ericsson AB
+ * Copyright (C) 2009 ST-Ericsson SA
  * License terms: GNU General Public License (GPL) version 2
  *
  * Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Johan Lundin <johan.lundin@stericsson.com>
+ * Author: Johan Lundin
  * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
  */
 #include <linux/device.h>
 #include <linux/amba/bus.h>
 #include <linux/mmc/host.h>
-#include <linux/input.h>
-#include <linux/workqueue.h>
-#include <linux/delay.h>
-#include <linux/regulator/consumer.h>
-#include <linux/regulator/machine.h>
 #include <linux/gpio.h>
+#include <linux/dmaengine.h>
 #include <linux/amba/mmci.h>
 #include <linux/slab.h>
+#include <mach/coh901318.h>
+#include <mach/dma_channels.h>
 
 #include "mmc.h"
 #include "padmux.h"
 
-struct mmci_card_event {
-       struct input_dev *mmc_input;
-       int mmc_inserted;
-       struct work_struct workq;
-       struct mmci_platform_data mmc0_plat_data;
+static struct mmci_platform_data mmc0_plat_data = {
+       /*
+        * Do not set ocr_mask or voltage translation function,
+        * we have a regulator we can control instead.
+        */
+       /* Nominally 2.85V on our platform */
+       .f_max = 24000000,
+       .gpio_wp = -1,
+       .gpio_cd = U300_GPIO_PIN_MMC_CD,
+       .cd_invert = true,
+       .capabilities = MMC_CAP_MMC_HIGHSPEED |
+       MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+#ifdef CONFIG_COH901318
+       .dma_filter = coh901318_filter_id,
+       .dma_rx_param = (void *) U300_DMA_MMCSD_RX_TX,
+       /* Don't specify a TX channel, this RX channel is bidirectional */
+#endif
 };
 
-static unsigned int mmc_status(struct device *dev)
-{
-       struct mmci_card_event *mmci_card = container_of(
-               dev->platform_data,
-               struct mmci_card_event, mmc0_plat_data);
-
-       return mmci_card->mmc_inserted;
-}
-
-static int mmci_callback(void *data)
-{
-       struct mmci_card_event *mmci_card = data;
-
-       disable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD);
-       schedule_work(&mmci_card->workq);
-
-       return 0;
-}
-
-
-static ssize_t gpio_show(struct device *dev, struct device_attribute *attr,
-                 char *buf)
-{
-       struct mmci_card_event *mmci_card = container_of(
-               dev->platform_data,
-               struct mmci_card_event, mmc0_plat_data);
-
-
-       return sprintf(buf, "%d\n", !mmci_card->mmc_inserted);
-}
-
-static DEVICE_ATTR(mmc_inserted, S_IRUGO, gpio_show, NULL);
-
-static void _mmci_callback(struct work_struct *ws)
-{
-
-       struct mmci_card_event *mmci_card = container_of(
-               ws,
-               struct mmci_card_event, workq);
-
-       mdelay(20);
-
-       mmci_card->mmc_inserted = !gpio_get_value(U300_GPIO_PIN_MMC_CD);
-
-       input_report_switch(mmci_card->mmc_input, KEY_INSERT,
-                           mmci_card->mmc_inserted);
-       input_sync(mmci_card->mmc_input);
-
-       pr_debug("MMC/SD card was %s\n",
-                mmci_card->mmc_inserted ? "inserted" : "removed");
-
-       enable_irq_on_gpio_pin(U300_GPIO_PIN_MMC_CD, mmci_card->mmc_inserted);
-}
-
 int __devinit mmc_init(struct amba_device *adev)
 {
-       struct mmci_card_event *mmci_card;
        struct device *mmcsd_device = &adev->dev;
        struct pmx *pmx;
        int ret = 0;
 
-       mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL);
-       if (!mmci_card)
-               return -ENOMEM;
-
-       /*
-        * Do not set ocr_mask or voltage translation function,
-        * we have a regulator we can control instead.
-        */
-       /* Nominally 2.85V on our platform */
-       mmci_card->mmc0_plat_data.f_max = 24000000;
-       mmci_card->mmc0_plat_data.status = mmc_status;
-       mmci_card->mmc0_plat_data.gpio_wp = -1;
-       mmci_card->mmc0_plat_data.gpio_cd = -1;
-       mmci_card->mmc0_plat_data.capabilities = MMC_CAP_MMC_HIGHSPEED |
-               MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-
-       mmcsd_device->platform_data = (void *) &mmci_card->mmc0_plat_data;
-
-       INIT_WORK(&mmci_card->workq, _mmci_callback);
-
-       ret = gpio_request(U300_GPIO_PIN_MMC_CD, "MMC card detection");
-       if (ret) {
-               printk(KERN_CRIT "Could not allocate MMC card detection " \
-                      "GPIO pin\n");
-               goto out;
-       }
-
-       ret = gpio_direction_input(U300_GPIO_PIN_MMC_CD);
-       if (ret) {
-               printk(KERN_CRIT "Invalid GPIO pin requested\n");
-               goto out;
-       }
-
-       ret = sysfs_create_file(&mmcsd_device->kobj,
-                              &dev_attr_mmc_inserted.attr);
-       if (ret)
-               goto out;
-
-       mmci_card->mmc_input = input_allocate_device();
-       if (!mmci_card->mmc_input) {
-               printk(KERN_CRIT "Could not allocate MMC input device\n");
-               return -ENOMEM;
-       }
-
-       mmci_card->mmc_input->name = "MMC insert notification";
-       mmci_card->mmc_input->id.bustype = BUS_HOST;
-       mmci_card->mmc_input->id.vendor = 0;
-       mmci_card->mmc_input->id.product = 0;
-       mmci_card->mmc_input->id.version = 0x0100;
-       mmci_card->mmc_input->dev.parent = mmcsd_device;
-       input_set_capability(mmci_card->mmc_input, EV_SW, KEY_INSERT);
-
-       /*
-        * Since this must always be compiled into the kernel, this input
-        * is never unregistered or free:ed.
-        */
-       ret = input_register_device(mmci_card->mmc_input);
-       if (ret) {
-               input_free_device(mmci_card->mmc_input);
-               goto out;
-       }
-
-       input_set_drvdata(mmci_card->mmc_input, mmci_card);
+       mmcsd_device->platform_data = &mmc0_plat_data;
 
        /*
         * Setup padmuxing for MMC. Since this must always be
@@ -171,12 +64,5 @@ int __devinit mmc_init(struct amba_device *adev)
                        pr_warning("Could not activate padmuxing\n");
        }
 
-       ret = gpio_register_callback(U300_GPIO_PIN_MMC_CD, mmci_callback,
-                                    mmci_card);
-
-       schedule_work(&mmci_card->workq);
-
-       printk(KERN_INFO "Registered MMC insert/remove notification\n");
-out:
        return ret;
 }
index 00869de..5767208 100644 (file)
@@ -11,6 +11,9 @@
 #include <linux/spi/spi.h>
 #include <linux/amba/pl022.h>
 #include <linux/err.h>
+#include <mach/coh901318.h>
+#include <mach/dma_channels.h>
+
 #include "padmux.h"
 
 /*
@@ -30,11 +33,8 @@ static void select_dummy_chip(u32 chipselect)
 }
 
 struct pl022_config_chip dummy_chip_info = {
-       /*
-        * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
-        * DMA_TRANSFER does not work
-        */
-       .com_mode = INTERRUPT_TRANSFER,
+       /* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */
+       .com_mode = DMA_TRANSFER,
        .iface = SSP_INTERFACE_MOTOROLA_SPI,
        /* We can only act as master but SSP_SLAVE is possible in theory */
        .hierarchy = SSP_MASTER,
@@ -75,8 +75,6 @@ static struct spi_board_info u300_spi_devices[] = {
 static struct pl022_ssp_controller ssp_platform_data = {
        /* If you have several SPI buses this varies, we have only bus 0 */
        .bus_id = 0,
-       /* Set this to 1 when we think we got DMA working */
-       .enable_dma = 0,
        /*
         * On the APP CPU GPIO 4, 5 and 6 are connected as generic
         * chip selects for SPI. (Same on U330, U335 and U365.)
@@ -84,6 +82,14 @@ static struct pl022_ssp_controller ssp_platform_data = {
         * and do padmuxing accordingly too.
         */
        .num_chipselect = 3,
+#ifdef CONFIG_COH901318
+       .enable_dma = 1,
+       .dma_filter = coh901318_filter_id,
+       .dma_rx_param = (void *) U300_DMA_SPI_RX,
+       .dma_tx_param = (void *) U300_DMA_SPI_TX,
+#else
+       .enable_dma = 0,
+#endif
 };
 
 
@@ -109,6 +115,7 @@ void __init u300_spi_init(struct amba_device *adev)
        }
 
 }
+
 void __init u300_spi_register_board_devices(void)
 {
        /* Register any SPI devices */
index 53ebb42..b549a8f 100644 (file)
@@ -3,16 +3,18 @@
 #
 
 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 \
-                               board-mop500-keypads.o
+                               board-mop500-regulators.o \
+                               board-mop500-uib.o board-mop500-stuib.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
 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
diff --git a/arch/arm/mach-ux500/board-mop500-keypads.c b/arch/arm/mach-ux500/board-mop500-keypads.c
deleted file mode 100644 (file)
index 70318c3..0000000
+++ /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 <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/stmpe.h>
-#include <linux/mfd/tc3589x.h>
-#include <linux/input/matrix_keypad.h>
-
-#include <plat/pincfg.h>
-#include <plat/ske.h>
-
-#include <mach/devices.h>
-#include <mach/hardware.h>
-
-#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));
-
-}
diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
new file mode 100644 (file)
index 0000000..fd4cf1c
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <plat/pincfg.h>
+#include <mach/hardware.h>
+
+#include "pins-db8500.h"
+
+static pin_cfg_t mop500_pins_common[] = {
+       /* 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,
+
+       /* 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,
+       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,
+
+       /* 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,
+
+       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,
+
+
+};
+
+void __init mop500_pins_init(void)
+{
+       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));
+}
index 533967c..875c91b 100644 (file)
 #include <linux/kernel.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/ab8500.h>
+#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,
        },
 };
index 4b99667..bf0b024 100644 (file)
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 
-#include <plat/pincfg.h>
+#include <asm/mach-types.h>
+#include <plat/ste_dma40.h>
 #include <mach/devices.h>
 #include <mach/hardware.h>
 
 #include "devices-db8500.h"
-#include "pins-db8500.h"
 #include "board-mop500.h"
-
-static pin_cfg_t mop500_sdi_pins[] = {
-       /* SDI0 (MicroSD slot) */
-       GPIO18_MC0_CMDDIR,
-       GPIO19_MC0_DAT0DIR,
-       GPIO20_MC0_DAT2DIR,
-       GPIO21_MC0_DAT31DIR,
-       GPIO22_MC0_FBCLK,
-       GPIO23_MC0_CLK,
-       GPIO24_MC0_CMD,
-       GPIO25_MC0_DAT0,
-       GPIO26_MC0_DAT1,
-       GPIO27_MC0_DAT2,
-       GPIO28_MC0_DAT3,
-
-       /* SDI4 (on-board eMMC) */
-       GPIO197_MC4_DAT3,
-       GPIO198_MC4_DAT2,
-       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,
-};
+#include "ste-dma40-db8500.h"
 
 /*
  * SDI 0 (MicroSD slot)
@@ -86,48 +44,134 @@ 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,
        .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,
+       .dma_rx_param   = &mop500_sdi0_dma_cfg_rx,
+       .dma_tx_param   = &mop500_sdi0_dma_cfg_tx,
+#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, 1);
-       gpio_direction_output(GPIO_SDMMC_EN, 0);
+       /* 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)
  */
 
+#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,26 +179,32 @@ 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)
 {
-       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);
 
+       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.
         */
-
-       /* 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);
 }
diff --git a/arch/arm/mach-ux500/board-mop500-stuib.c b/arch/arm/mach-ux500/board-mop500-stuib.c
new file mode 100644 (file)
index 0000000..8c97977
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/input/bu21013.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/input/matrix_keypad.h>
+#include <asm/mach-types.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),
+};
+/*
+ * 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),
+       .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),
+       .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)
+{
+       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));
+
+       mop500_uib_i2c_add(3, u8500_i2c3_devices_stuib,
+                       ARRAY_SIZE(u8500_i2c3_devices_stuib));
+}
diff --git a/arch/arm/mach-ux500/board-mop500-u8500uib.c b/arch/arm/mach-ux500/board-mop500-u8500uib.c
new file mode 100644 (file)
index 0000000..d8a8734
--- /dev/null
@@ -0,0 +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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tc3589x.h>
+#include <linux/input/matrix_keypad.h>
+#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h>
+
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+
+#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-uib.c b/arch/arm/mach-ux500/board-mop500-uib.c
new file mode 100644 (file)
index 0000000..69cce41
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#define pr_fmt(fmt)    "mop500-uib: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#include <mach/hardware.h>
+#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);
index a393f57..8790d98 100644 (file)
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
+#include <linux/amba/serial.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
 #include <linux/mfd/tc3589x.h>
+#include <linux/leds-lp5521.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <plat/pincfg.h>
 #include <plat/i2c.h>
+#include <plat/ste_dma40.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
 #include <mach/irqs.h>
 
+#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,
-};
-
 static struct ab8500_platform_data ab8500_platdata = {
        .irq_base       = MOP500_AB8500_IRQ_BASE,
        .regulator      = ab8500_regulators,
@@ -103,16 +65,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
  */
@@ -133,14 +85,81 @@ 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,
+       },
+       {
+               /* Light sensor Rohm BH1780GLI */
+               I2C_BOARD_INFO("bh1780", 0x29),
+       },
+};
+
 #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
 static struct nmk_i2c_controller u8500_i2c##id##_data = { \
        /*                              \
@@ -178,8 +197,93 @@ 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,
+               .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,
+};
+
+#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)
@@ -187,18 +291,108 @@ 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)
+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();
 
-       nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins));
+       mop500_pins_init();
 
        platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
@@ -207,12 +401,12 @@ 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,
                                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")
@@ -222,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
index 3104ae2..56722f4 100644 (file)
@@ -7,15 +7,36 @@
 #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)
 #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 __init mop500_pins_init(void);
+
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
+               unsigned n);
 
 #endif
index 54712ac..739fb4c 100644 (file)
@@ -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)
index 39d370c..44fd3b5 100644 (file)
@@ -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)
index b2b0a3b..32ce908 100644 (file)
@@ -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);
@@ -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),
index af04e08..c9dc2ef 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/irq.h>
 
 #include <asm/mach/map.h>
+#include <asm/pmu.h>
 
 #include <plat/gpio.h>
 
 #include <mach/devices.h>
 #include <mach/setup.h>
 #include <mach/irqs.h>
+#include <mach/usb.h>
 
 #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),
@@ -43,6 +46,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 +150,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,
@@ -166,12 +190,35 @@ 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(u5500_platform_devs,
-                            ARRAY_SIZE(u5500_platform_devs));
+       platform_add_devices(db5500_platform_devs,
+                            ARRAY_SIZE(db5500_platform_devs));
 }
index 5c0fabf..516126c 100644 (file)
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
+#include <mach/usb.h>
 
 #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));
index fe69f5f..13a4ce0 100644 (file)
@@ -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);
        }
index cbadc11..c719b5a 100644 (file)
@@ -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;
index c8d7901..94627f7 100644 (file)
@@ -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) \
 #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
index 23c695d..73b1740 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
+#include <linux/amba/pl022.h>
 
 #include <plat/ste_dma40.h>
 
@@ -67,12 +68,72 @@ 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];
+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,
+       /* 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 */
-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,
+       /* 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 */
 static int dma40_memcpy_event[] = {
index 3a770c7..9cc6f8f 100644 (file)
@@ -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) \
@@ -88,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
index 32a061f..1cfab68 100644 (file)
@@ -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[] = {
index 9a6614c..ab0fe14 100644 (file)
@@ -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;
diff --git a/arch/arm/mach-ux500/include/mach/usb.h b/arch/arm/mach-ux500/include/mach/usb.h
new file mode 100644 (file)
index 0000000..d3739d4
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __ASM_ARCH_USB_H
+#define __ASM_ARCH_USB_H
+
+#include <linux/dmaengine.h>
+
+#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 (file)
index 0000000..82e5359
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#include <linux/platform_device.h>
+#include <linux/usb/musb.h>
+#include <plat/ste_dma40.h>
+#include <mach/hardware.h>
+#include <mach/usb.h>
+
+#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);
+}
index 1e88ecb..7062042 100644 (file)
 /*
  * 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"
  */
 
-#define NMK_GPIO_PER_CHIP 32
+#define NMK_GPIO_PER_CHIP      32
+
 struct nmk_gpio_chip {
        struct gpio_chip chip;
        void __iomem *addr;
        struct clk *clk;
+       unsigned int bank;
        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;
        u32 edge_falling;
+       u32 real_wake;
+       u32 rwimsc;
+       u32 fwimsc;
+       u32 slpm;
 };
 
+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)
 {
@@ -118,8 +134,35 @@ 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 = 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);
+
+               /* 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",
@@ -144,6 +187,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],
@@ -155,6 +199,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".
@@ -180,8 +226,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;
 }
 
 /**
@@ -200,19 +354,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);
 
@@ -226,31 +368,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);
 
@@ -277,9 +401,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;
 }
@@ -314,6 +442,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;
@@ -401,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;
@@ -415,44 +564,58 @@ 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_chip->lock, flags);
-#ifdef CONFIG_ARCH_U8500
-       if (cpu_is_u8500v2()) {
-               __nmk_gpio_set_slpm(nmk_chip, gpio,
-                                   on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
-                                      : NMK_GPIO_SLPM_WAKEUP_DISABLE);
-       }
-#endif
-       __nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
-       spin_unlock_irqrestore(&nmk_chip->lock, flags);
+       spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+       spin_lock(&nmk_chip->lock);
+
+       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);
 
        return 0;
 }
@@ -483,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;
@@ -497,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);
@@ -514,12 +677,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,29 +694,56 @@ 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;
        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);
                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;
 }
 
@@ -605,6 +794,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 <linux/seq_file.h>
+
+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,
@@ -612,10 +892,64 @@ 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,
+       .dbg_show               = nmk_gpio_dbg_show,
        .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;
@@ -623,6 +957,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;
 
@@ -641,6 +976,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;
@@ -664,14 +1005,19 @@ 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;
+       nmk_chip->set_ioforce = pdata->set_ioforce;
        spin_lock_init(&nmk_chip->lock);
 
        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;
@@ -680,6 +1026,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);
@@ -705,10 +1054,8 @@ static struct platform_driver nmk_gpio_driver = {
        .driver = {
                .owner = THIS_MODULE,
                .name = "gpio",
-               },
+       },
        .probe = nmk_gpio_probe,
-       .suspend = NULL, /* to be done */
-       .resume = NULL,
 };
 
 static int __init nmk_gpio_init(void)
index 67b113d..1b9f6f0 100644 (file)
@@ -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.
  */
@@ -82,6 +85,9 @@ struct nmk_gpio_platform_data {
        char *name;
        int first_gpio;
        int first_irq;
+       int num_gpio;
+       u32 (*get_secondary_status)(unsigned int bank);
+       void (*set_ioforce)(bool enable);
 };
 
 #endif /* __ASM_PLAT_GPIO_H */