[RFC] sdhc-pxa : mmp2 : Send 74 clocks when device powers up

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

 



Resent -- now plain text

MMC spec calls for the host to send 74 clocks to the card
during initialization, right after voltage stabilization.
the mmp2 controller does not start the clock when the clock
is enabled but does provide a way to generate the clocks by
programming the hardware.

Turning ON the clock does NOT do ensure this happens on MMP2 - Aspen (pxa168) - Tavor. 
Turning on the clock only ensure that when the first cmd is sent that the clock will 
be turned on.


Submitted as a RFC as I do not have a way to test this code using mmc-next.  
Code tested in marvell mmp2 linux environment.

Signed-off-by: Philip Rakity <prakity@xxxxxxxxxxx>

diff --git a/drivers/mmc/host/sdhci-pxa.c b/drivers/mmc/host/sdhci-pxa.c
index 5a61208..bc83075 100644
--- a/drivers/mmc/host/sdhci-pxa.c
+++ b/drivers/mmc/host/sdhci-pxa.c
@@ -25,13 +25,21 @@
#include <linux/io.h>
#include <linux/err.h>
#include <plat/sdhci.h>
+#include <mach/cputype.h>
#include "sdhci.h"

#define DRIVER_NAME	"sdhci-pxa"

+#define SD_CFG_FIFO_PARAM	0x100
+#define  SDCFG_GEN_PAD_CLK_ON	(1<<6)
+
#define SD_FIFO_PARAM		0x104
#define DIS_PAD_SD_CLK_GATE	0x400

+#define SD_CE_ATA_2		0x10E
+#define  SDCE_MISC_INT_EN	(1<<1)
+#define  SDCE_MISC_INT		(1<<2)
+
struct sdhci_pxa {
	struct sdhci_host		*host;
	struct sdhci_pxa_platdata	*pdata;
@@ -39,6 +47,11 @@ struct sdhci_pxa {
	struct resource			*res;

	u8 clk_enable;
+	u8 power_mode;
+};
+
+static struct sdhci_ops sdhci_mmc_ops = {
+	.platform_send_init_74_clocks = NULL,
};

/*****************************************************************************\
@@ -73,6 +86,60 @@ static struct sdhci_ops sdhci_pxa_ops = {
	.set_clock = set_clock,
};

+/*
+ * MMC spec calls for the host to send 74 clocks to the card
+ * during initialization, right after voltage stabilization.
+ * the mmp2 controller does not start the clock when the clock
+ * is enabled but does provide a way to generate the clocks by
+ * programming the hardware.
+ */
+static void generate_init_clocks_mmp2(struct sdhci_host *host, u8 power_mode)
+{
+	struct sdhci_pxa *pxa = sdhci_priv(host);
+	u16 tmp;
+	int count;
+
+	if (pxa->power_mode == MMC_POWER_UP
+	&& power_mode == MMC_POWER_ON) {
+
+		/*
+		 * set we want notice of when 74 clocks are sent
+		 * (NOT an interrupt -- just a h/w flag that flips)
+		 */
+		tmp = readw(host->ioaddr + SD_CE_ATA_2);
+		tmp |= SDCE_MISC_INT_EN;
+		writew(tmp, host->ioaddr + SD_CE_ATA_2);
+
+		/* start sending the 74 clocks */
+		tmp = readw(host->ioaddr + SD_CFG_FIFO_PARAM);
+		tmp |= SDCFG_GEN_PAD_CLK_ON;
+		writew(tmp, host->ioaddr + SD_CFG_FIFO_PARAM);
+
+		/* slowest speed is about 100KHz or 10usec per clock */
+		udelay (740);
+		count = 0;
+#define MAX_WAIT_COUNT	5
+		while (count++ < MAX_WAIT_COUNT)
+		{
+			/* check if hardware has indicated clocks sent */
+			if ((readw(host->ioaddr + SD_CE_ATA_2) & SDCE_MISC_INT) == 0)
+				break;
+			udelay(10);
+		}
+
+		/* keep going if error -- could be okay */
+		if (count == MAX_WAIT_COUNT)
+			printk (KERN_WARNING "%s: %s: 74 clock interrupt not"
+				"cleared\n",
+				__func__,
+				mmc_hostname(host->mmc));
+		/* clear the interrupt bit if posted */
+		tmp = readw(host->ioaddr + SD_CE_ATA_2);
+		tmp |= SDCE_MISC_INT;
+		writew(tmp, host->ioaddr + SD_CE_ATA_2);
+	}
+	pxa->power_mode = power_mode;
+}
/*****************************************************************************\
 *                                                                           *
 * Device probing/removal                                                    *
@@ -145,6 +212,10 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
	if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
		host->mmc->caps |= MMC_CAP_8_BIT_DATA;

+	if (cpu_is_mmp2())
+		sdhci_mmc_ops.platform_send_init_74_clocks =
+			generate_init_clocks_mmp2;
+
	ret = sdhci_add_host(host);
	if (ret) {
		dev_err(&pdev->dev, "failed to add host\n");--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux