Merge branch 'driver-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / arm / mach-ux500 / board-mop500-sdi.c
index bac9956..4b99667 100644 (file)
 #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,
@@ -49,6 +63,55 @@ static pin_cfg_t mop500_sdi2_pins[] = {
        GPIO138_MC2_DAT7,
 };
 
+/*
+ * SDI 0 (MicroSD slot)
+ */
+
+/* MMCIPOWER bits */
+#define MCI_DATA2DIREN         (1 << 2)
+#define MCI_CMDDIREN           (1 << 3)
+#define MCI_DATA0DIREN         (1 << 4)
+#define MCI_DATA31DIREN                (1 << 5)
+#define MCI_FBCLKEN            (1 << 7)
+
+static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
+                                  unsigned char power_mode)
+{
+       if (power_mode == MMC_POWER_UP)
+               gpio_set_value_cansleep(GPIO_SDMMC_EN, 1);
+       else if (power_mode == MMC_POWER_OFF)
+               gpio_set_value_cansleep(GPIO_SDMMC_EN, 0);
+
+       return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
+              MCI_DATA2DIREN | MCI_DATA31DIREN;
+}
+
+static struct mmci_platform_data mop500_sdi0_data = {
+       .vdd_handler    = mop500_sdi0_vdd_handler,
+       .ocr_mask       = MMC_VDD_29_30,
+       .f_max          = 100000000,
+       .capabilities   = MMC_CAP_4_BIT_DATA,
+       .gpio_cd        = GPIO_SDMMC_CD,
+       .gpio_wp        = -1,
+};
+
+void mop500_sdi_tc35892_init(void)
+{
+       int ret;
+
+       ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN");
+       if (!ret)
+               ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL,
+                                  "GPIO_SDMMC_1V8_3V_SEL");
+       if (ret)
+               return;
+
+       gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1);
+       gpio_direction_output(GPIO_SDMMC_EN, 0);
+
+       db8500_add_sdi0(&mop500_sdi0_data);
+}
+
 /*
  * SDI 2 (POP eMMC, not on DB8500ed)
  */
@@ -74,18 +137,24 @@ static struct mmci_platform_data mop500_sdi4_data = {
        .gpio_wp        = -1,
 };
 
-void mop500_sdi_init(void)
+void __init mop500_sdi_init(void)
 {
        nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
 
-       u8500_sdi2_device.dev.platform_data = &mop500_sdi2_data;
-       u8500_sdi4_device.dev.platform_data = &mop500_sdi4_data;
+       /*
+        * sdi0 will finally be added when the TC35892 initializes and calls
+        * mop500_sdi_tc35892_init() above.
+        */
 
+       /* PoP:ed eMMC */
        if (!cpu_is_u8500ed()) {
                nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
-               amba_device_register(&u8500_sdi2_device, &iomem_resource);
+               /* 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 */
-       amba_device_register(&u8500_sdi4_device, &iomem_resource);
+       db8500_add_sdi4(&mop500_sdi4_data);
 }