summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/board-mop500-sdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ux500/board-mop500-sdi.c')
-rw-r--r--arch/arm/mach-ux500/board-mop500-sdi.c137
1 files changed, 97 insertions, 40 deletions
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 4657c0073ab..ee49e5f7f33 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -11,6 +11,7 @@
#include <linux/amba/mmci.h>
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <asm/mach-types.h>
#include <plat/ste_dma40.h>
@@ -25,21 +26,13 @@
* 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)
-
/* GPIO pins used by the sdi0 level shifter */
static int sdi0_en = -1;
static int sdi0_vsel = -1;
-static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
- unsigned char power_mode)
+static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios)
{
- switch (power_mode) {
+ switch (ios->power_mode) {
case MMC_POWER_UP:
case MMC_POWER_ON:
/*
@@ -52,6 +45,7 @@ static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
*/
gpio_direction_output(sdi0_vsel, 0);
gpio_direction_output(sdi0_en, 1);
+ udelay(100);
break;
case MMC_POWER_OFF:
gpio_direction_output(sdi0_vsel, 0);
@@ -59,68 +53,122 @@ static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd,
break;
}
- return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN |
- MCI_DATA2DIREN | MCI_DATA31DIREN;
+ return 0;
}
+#ifdef MMC_SUSPEND_WORKAROUND
#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,
+ .src_dev_type = DB8500_DMA_DEV1_SD_MMC0_RX,
.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
.src_info.data_width = STEDMA40_WORD_WIDTH,
.dst_info.data_width = STEDMA40_WORD_WIDTH,
+ .use_fixed_channel = true,
+ .phy_channel = 0,
};
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,
+ .dst_dev_type = DB8500_DMA_DEV1_SD_MMC0_TX,
.src_info.data_width = STEDMA40_WORD_WIDTH,
.dst_info.data_width = STEDMA40_WORD_WIDTH,
+ .use_fixed_channel = true,
+ .phy_channel = 0,
};
#endif
+#endif
static struct mmci_platform_data mop500_sdi0_data = {
- .vdd_handler = mop500_sdi0_vdd_handler,
+ .ios_handler = mop500_sdi0_ios_handler,
.ocr_mask = MMC_VDD_29_30,
.f_max = 50000000,
.capabilities = MMC_CAP_4_BIT_DATA |
MMC_CAP_SD_HIGHSPEED |
MMC_CAP_MMC_HIGHSPEED,
.gpio_wp = -1,
+ .sigdir = MCI_ST_FBCLKEN |
+ MCI_ST_CMDDIREN |
+ MCI_ST_DATA0DIREN |
+ MCI_ST_DATA2DIREN,
+#ifdef MMC_SUSPEND_WORKAROUND
#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
+#endif
+};
+
+/*
+ * SDI1 (SDIO WLAN)
+ */
+#ifdef SDIO_DMA_ON
+#ifdef CONFIG_STE_DMA40
+static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
+ .mode = STEDMA40_MODE_LOGICAL,
+ .dir = STEDMA40_PERIPH_TO_MEM,
+ .src_dev_type = DB8500_DMA_DEV32_SD_MM1_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 sdi1_dma_cfg_tx = {
+ .mode = STEDMA40_MODE_LOGICAL,
+ .dir = STEDMA40_MEM_TO_PERIPH,
+ .src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+ .dst_dev_type = DB8500_DMA_DEV32_SD_MM1_TX,
+ .src_info.data_width = STEDMA40_WORD_WIDTH,
+ .dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+#endif
+
+static struct mmci_platform_data mop500_sdi1_data = {
+ .ocr_mask = MMC_VDD_29_30,
+ .f_max = 50000000,
+ .capabilities = MMC_CAP_4_BIT_DATA,
+ .gpio_cd = -1,
+ .gpio_wp = -1,
+#ifdef SDIO_DMA_ON
+#ifdef CONFIG_STE_DMA40
+ .dma_filter = stedma40_filter,
+ .dma_rx_param = &sdi1_dma_cfg_rx,
+ .dma_tx_param = &sdi1_dma_cfg_tx,
+#endif
+#endif
};
-static void sdi0_configure(void)
+static void sdi0_sdi1_configure(void)
{
- int ret;
+ int ret;
+ u32 periphid = 0;
- ret = gpio_request(sdi0_en, "level shifter enable");
- 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;
- }
+ ret = gpio_request(sdi0_en, "level shifter enable");
+ 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;
+ }
- /* Select the default 2.9V and enable level shifter */
- gpio_direction_output(sdi0_vsel, 0);
- gpio_direction_output(sdi0_en, 1);
+ /* Select the default 2.9V and enable level shifter */
+ gpio_direction_output(sdi0_vsel, 0);
+ gpio_direction_output(sdi0_en, 1);
- /* Add the device, force v2 to subrevision 1 */
- if (cpu_is_u8500v2())
- db8500_add_sdi0(&mop500_sdi0_data, 0x10480180);
- else
- db8500_add_sdi0(&mop500_sdi0_data, 0);
+ /* v2 has a new version of this block that need to be forced */
+ if (cpu_is_u8500v20_or_later())
+ periphid = 0x10480180;
+
+ db8500_add_sdi0(&mop500_sdi0_data, periphid);
+ db8500_add_sdi1(&mop500_sdi1_data, periphid);
}
void mop500_sdi_tc35892_init(void)
@@ -128,13 +176,13 @@ 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();
+ sdi0_sdi1_configure();
}
/*
* SDI 2 (POP eMMC, not on DB8500ed)
*/
-
+#ifdef MMC_SUSPEND_WORKAROUND
#ifdef CONFIG_STE_DMA40
struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
.mode = STEDMA40_MODE_LOGICAL,
@@ -154,24 +202,29 @@ static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
.dst_info.data_width = STEDMA40_WORD_WIDTH,
};
#endif
+#endif
static struct mmci_platform_data mop500_sdi2_data = {
.ocr_mask = MMC_VDD_165_195,
.f_max = 50000000,
- .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA,
.gpio_cd = -1,
.gpio_wp = -1,
+#ifdef MMC_SUSPEND_WORKAROUND
#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
+#endif
};
/*
* SDI 4 (on-board eMMC)
*/
+#ifdef MMC_SUSPEND_WORKAROUND
#ifdef CONFIG_STE_DMA40
struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
.mode = STEDMA40_MODE_LOGICAL,
@@ -191,19 +244,23 @@ static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
.dst_info.data_width = STEDMA40_WORD_WIDTH,
};
#endif
+#endif
static struct mmci_platform_data mop500_sdi4_data = {
.ocr_mask = MMC_VDD_29_30,
.f_max = 50000000,
- .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
- MMC_CAP_MMC_HIGHSPEED,
+ .capabilities = MMC_CAP_4_BIT_DATA |
+ MMC_CAP_8_BIT_DATA |
+ MMC_CAP_MMC_HIGHSPEED,
.gpio_cd = -1,
.gpio_wp = -1,
+#ifdef MMC_SUSPEND_WORKAROUND
#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
+#endif
};
void __init mop500_sdi_init(void)
@@ -236,11 +293,11 @@ void __init mop500_sdi_init(void)
sdi0_en = SNOWBALL_SDMMC_EN_GPIO;
sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO;
}
- sdi0_configure();
+ sdi0_sdi1_configure();
}
/*
- * On boards with the TC35892 GPIO expander, sdi0 will finally
+ * On boards with the TC35892 GPIO expander, sdi0 and sdi1 will finally
* be added when the TC35892 initializes and calls
* mop500_sdi_tc35892_init() above.
*/