Re: OMAP MMC multiport support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Mar 19, 2008 at 08:53:48PM +0200, Keppler Alecrim wrote:
> What about DMA channel? Isn't it necessary?
> 
> diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
> index 3d4a7d1..262d846 100644
> --- a/drivers/mmc/host/omap_hsmmc.c
> +++ b/drivers/mmc/host/omap_hsmmc.c
> @@ -514,10 +514,18 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host
> *host, struct mmc_request *req)
> 
>  	if (!(data->flags & MMC_DATA_WRITE)) {
>  		host->dma_dir = DMA_FROM_DEVICE;
> -		sync_dev = OMAP24XX_DMA_MMC1_RX;
> +		if (host->id == OMAP_MMC1_DEVID)
> +			sync_dev = OMAP24XX_DMA_MMC1_RX;
> +		else
> +			sync_dev = OMAP24XX_DMA_MMC2_RX;
> +
>  	} else {
>  		host->dma_dir = DMA_TO_DEVICE;
> -		sync_dev = OMAP24XX_DMA_MMC1_TX;
> +		if (host->id == OMAP_MMC1_DEVID)
> +			sync_dev = OMAP24XX_DMA_MMC1_TX;
> +		else
> +			sync_dev = OMAP24XX_DMA_MMC2_TX;
> +
>  	}

Indeed.  The kernel I'm working with already had this though.

Okay, I checked other differences between in the omap_hsmmc.c that I'm working
with and didn't find anything necessary for MMC2.  I've incorporated this into
the patch below, which I think is everything needed to get MMC2 working.  This
should emphasize the point that someone needs to test with this patch, as I am
unable to test it myself.

I would also like someone familiar with both OMAP 2430 and 2420 to look at the
pin-muxing changes in the patch.  I found that some pins were being set up in
the MMC1 configuration with the same configuration register offsets as those
for MMC2.  I assumed that those were for the 2420 and modified the MMC1
initialization accordingly.  If these changes are correct I will break them
out into a separate patch before I submit.

Cheers,
Seth


diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c
index fb639f5..48704b2 100644
--- a/arch/arm/mach-omap2/mux.c
+++ b/arch/arm/mach-omap2/mux.c
@@ -210,6 +210,14 @@ MUX_CFG_24XX("AC10_2430_MCBSP2_FSX_OFF",0x012E,	0,	0,	0,	1)
 MUX_CFG_24XX("AD16_2430_MCBSP2_CLX_OFF",0x012F,	0,	0,	0,	1)
 MUX_CFG_24XX("AE13_2430_MCBSP2_DX_OFF",	0x0130,	0,	0,	0,	1)
 MUX_CFG_24XX("AD13_2430_MCBSP2_DR_OFF",	0x0131,	0,	0,	0,	1)
+
+/* MMC2 */
+MUX_CFG_24XX("V26_2430_MMC2_CLKO",	0x0f9,	0,	0,	0,	1)
+MUX_CFG_24XX("V24_2430_MMC2_DAT3",	0x0fa,	0,	0,	0,	1)
+MUX_CFG_24XX("W20_2430_MMC2_CMD",	0x0fb,	0,	0,	0,	1)
+MUX_CFG_24XX("V23_2430_MMC2_DAT0",	0x0fc,	0,	0,	0,	1)
+MUX_CFG_24XX("V25_2430_MMC2_DAT2",	0x0fd,	0,	0,	0,	1)
+MUX_CFG_24XX("Y24_2430_MMC2_DAT1",	0x0fe,	0,	0,	0,	1)
 };
 
 #define OMAP24XX_PINS_SZ	ARRAY_SIZE(omap24xx_pins)
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c
index ec9a999..1859ed4 100644
--- a/arch/arm/plat-omap/devices.c
+++ b/arch/arm/plat-omap/devices.c
@@ -161,7 +161,17 @@ static inline void omap_init_kp(void) {}
 #define	OMAP_MMC1_BASE		0xfffb7800
 #define OMAP_MMC1_INT		INT_MMC
 #endif
-#define	OMAP_MMC2_BASE		0xfffb7c00	/* omap16xx only */
+
+#if defined(CONFIG_ARCH_OMAP16XX)
+#define	OMAP_MMC2_BASE		0xfffb7c00
+#define	OMAP_MMC2_INT		INT_1610_MMC2
+#elif defined(CONFIG_ARCH_OMAP2430)
+#define	OMAP_MMC2_BASE		0x480b4000
+#define	OMAP_MMC2_INT		INT_24XX_MMC2_IRQ
+#endif
+
+#define OMAP_MMC2_SUPPORT \
+	(defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2430))
 
 static struct omap_mmc_platform_data mmc1_data;
 
@@ -190,7 +200,7 @@ static struct platform_device mmc_omap_device1 = {
 	.resource	= mmc1_resources,
 };
 
-#ifdef	CONFIG_ARCH_OMAP16XX
+#if OMAP_MMC2_SUPPORT
 
 static struct omap_mmc_platform_data mmc2_data;
 
@@ -204,7 +214,7 @@ static struct resource mmc2_resources[] = {
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= INT_1610_MMC2,
+		.start		= OMAP_MMC2_INT,
 		.flags		= IORESOURCE_IRQ,
 	},
 };
@@ -243,11 +253,13 @@ static void __init omap_init_mmc(void)
 	if (mmc->enabled) {
 		if (cpu_is_omap24xx()) {
 			omap_cfg_reg(H18_24XX_MMC_CMD);
-			omap_cfg_reg(H15_24XX_MMC_CLKI);
 			omap_cfg_reg(G19_24XX_MMC_CLKO);
 			omap_cfg_reg(F20_24XX_MMC_DAT0);
-			omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
-			omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
+			if (cpu_is_omap242x()) {
+				omap_cfg_reg(H15_24XX_MMC_CLKI);
+				omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
+				omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
+			}
 		} else {
 			omap_cfg_reg(MMC_CMD);
 			omap_cfg_reg(MMC_CLK);
@@ -263,9 +275,11 @@ static void __init omap_init_mmc(void)
 				omap_cfg_reg(H14_24XX_MMC_DAT1);
 				omap_cfg_reg(E19_24XX_MMC_DAT2);
 				omap_cfg_reg(D19_24XX_MMC_DAT3);
-				omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
-				omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
-				omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
+				if (cpu_is_omap242x()) {
+					omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
+					omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
+					omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
+				}
 			} else {
 				omap_cfg_reg(MMC_DAT1);
 				/* NOTE:  DAT2 can be on W10 (here) or M15 */
@@ -291,25 +305,39 @@ static void __init omap_init_mmc(void)
 		(void) platform_device_register(&mmc_omap_device1);
 	}
 
-#ifdef	CONFIG_ARCH_OMAP16XX
+#if OMAP_MMC2_SUPPORT
 	/* block 2 is on newer chips, and has many pinout options */
 	mmc = &mmc_conf->mmc[1];
 	if (mmc->enabled) {
 		if (!mmc->nomux) {
-			omap_cfg_reg(Y8_1610_MMC2_CMD);
-			omap_cfg_reg(Y10_1610_MMC2_CLK);
-			omap_cfg_reg(R18_1610_MMC2_CLKIN);
-			omap_cfg_reg(W8_1610_MMC2_DAT0);
+			if (cpu_is_omap243x()) {
+				omap_cfg_reg(V26_2430_MMC2_CLKO);
+				omap_cfg_reg(W20_2430_MMC2_CMD);
+				omap_cfg_reg(V23_2430_MMC2_DAT0);
+			} else {
+				omap_cfg_reg(Y8_1610_MMC2_CMD);
+				omap_cfg_reg(Y10_1610_MMC2_CLK);
+				omap_cfg_reg(R18_1610_MMC2_CLKIN);
+				omap_cfg_reg(W8_1610_MMC2_DAT0);
+			}
 			if (mmc->wire4) {
-				omap_cfg_reg(V8_1610_MMC2_DAT1);
-				omap_cfg_reg(W15_1610_MMC2_DAT2);
-				omap_cfg_reg(R10_1610_MMC2_DAT3);
+				if (cpu_is_omap243x()) {
+					omap_cfg_reg(Y24_2430_MMC2_DAT1);
+					omap_cfg_reg(V25_2430_MMC2_DAT2);
+					omap_cfg_reg(V24_2430_MMC2_DAT3);
+				} else {
+					omap_cfg_reg(V8_1610_MMC2_DAT1);
+					omap_cfg_reg(W15_1610_MMC2_DAT2);
+					omap_cfg_reg(R10_1610_MMC2_DAT3);
+				}
 			}
 
 			/* These are needed for the level shifter */
-			omap_cfg_reg(V9_1610_MMC2_CMDDIR);
-			omap_cfg_reg(V5_1610_MMC2_DATDIR0);
-			omap_cfg_reg(W19_1610_MMC2_DATDIR1);
+			if (cpu_is_omap16xx()) {
+				omap_cfg_reg(V9_1610_MMC2_CMDDIR);
+				omap_cfg_reg(V5_1610_MMC2_DATDIR0);
+				omap_cfg_reg(W19_1610_MMC2_DATDIR1);
+			}
 		}
 
 		/* Feedback clock must be set on OMAP-1710 MMC2 */
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 3d4a7d1..0f1bb9c 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -388,8 +388,12 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
 	 * If a MMC dual voltage card is detected, the set_ios fn calls
 	 * this fn with VDD bit set for 1.8V. Upon card removal from the
 	 * slot, mmc_omap_detect fn sets the VDD back to 3V.
+	 *
+	 * Only MMC1 supports 3.0V.  MMC2 will not function if SDVS30 is
+	 * set in HCTL.
 	 */
-	if (((1 << vdd) == MMC_VDD_32_33) || ((1 << vdd) == MMC_VDD_33_34))
+	if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) ||
+				((1 << vdd) == MMC_VDD_33_34)))
 		reg_val |= SDVS30;
 	if ((1 << vdd) == MMC_VDD_165_195)
 		reg_val |= SDVS18;
@@ -514,10 +518,16 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req)
 
 	if (!(data->flags & MMC_DATA_WRITE)) {
 		host->dma_dir = DMA_FROM_DEVICE;
-		sync_dev = OMAP24XX_DMA_MMC1_RX;
+		if (host->id == OMAP_MMC1_DEVID)
+			sync_dev = OMAP24XX_DMA_MMC1_RX;
+		else
+			sync_dev = OMAP24XX_DMA_MMC2_RX;
 	} else {
 		host->dma_dir = DMA_TO_DEVICE;
-		sync_dev = OMAP24XX_DMA_MMC1_TX;
+		if (host->id == OMAP_MMC1_DEVID)
+			sync_dev = OMAP24XX_DMA_MMC1_TX;
+		else
+			sync_dev = OMAP24XX_DMA_MMC2_TX;
 	}
 
 	ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb,
@@ -689,6 +699,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 	struct mmc_omap_host *host = NULL;
 	struct resource *res;
 	int ret = 0, irq;
+	u32 hctl, capa;
 
 	if (pdata == NULL) {
 		dev_err(&pdev->dev, "Platform Data is missing\n");
@@ -775,11 +786,20 @@ static int __init omap_mmc_probe(struct platform_device *pdev)
 	if (pdata->conf.wire4)
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+	/* Only MMC1 supports 3.0V */
+	if (host->id == OMAP_MMC1_DEVID) {
+		hctl = SDVS30;
+		capa = VS30 | VS18;
+	} else {
+		hctl = SDVS18;
+		capa = VS18;
+	}
+
 	OMAP_HSMMC_WRITE(host->base, HCTL,
-			OMAP_HSMMC_READ(host->base, HCTL) | SDVS30);
+			OMAP_HSMMC_READ(host->base, HCTL) | hctl);
 
-	OMAP_HSMMC_WRITE(host->base, CAPA, OMAP_HSMMC_READ(host->base,
-							CAPA) | VS30 | VS18);
+	OMAP_HSMMC_WRITE(host->base, CAPA,
+			OMAP_HSMMC_READ(host->base, CAPA) | capa);
 
 	/* Set the controller to AUTO IDLE mode */
 	OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
diff --git a/include/asm-arm/arch-omap/mux.h b/include/asm-arm/arch-omap/mux.h
index f216b4d..c58db03 100644
--- a/include/asm-arm/arch-omap/mux.h
+++ b/include/asm-arm/arch-omap/mux.h
@@ -641,6 +641,14 @@ enum omap24xx_index {
 	AE13_2430_MCBSP2_DX_OFF,
 	AD13_2430_MCBSP2_DR_OFF,
 
+	/* 2430 MMC2 */
+	V26_2430_MMC2_CLKO,
+	V24_2430_MMC2_DAT3,
+	W20_2430_MMC2_CMD,
+	V23_2430_MMC2_DAT0,
+	V25_2430_MMC2_DAT2,
+	Y24_2430_MMC2_DAT1,
+
 };
 
 enum omap34xx_index {
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux