>From 23a82bace793f82a61c010b7341e4dc1ece07f04 Mon Sep 17 00:00:00 2001
From: Chuanxiao Dong <[email protected]>
Date: Thu, 4 Nov 2010 15:34:44 +0800
Subject: [PATCH 3/3] mmc: implemented the real reset eMMC card in sdhci HC 
driver

Hardware reset need host controller to trigger a RST_n signal,
and driver needs to pull up/down the relavent GPIO to implement
this

Signed-off-by: Chuanxiao Dong <[email protected]>
---
 drivers/mmc/host/sdhci-pci.c |   64 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 7bdbd9c..41b69da 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -18,6 +18,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/gpio.h>
 
 #include <linux/mmc/host.h>
 
@@ -633,8 +634,41 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)
        return 0;
 }
 
+/*
+ * HW reset eMMC4.4 card callback
+ * In this function, driver need to trigger RST_n signal
+ * as eMMC4.4 standard says.
+ * 0: reset emmc successfully
+ * 1: reset emmc failed
+ */
+static int sdhci_pci_reset_emmc(struct sdhci_host *host)
+{
+       /* trigger a RST_n signal */
+       struct sdhci_pci_slot *slot;
+       struct pci_dev *pdev;
+       unsigned gpio;
+       int ret = 1;
+
+       slot = sdhci_priv(host);
+       pdev = slot->chip->pdev;
+
+       if (pdev->device == PCI_DEVICE_ID_INTEL_MFD_EMMC0)
+               gpio = 117;
+       else if (pdev->device == PCI_DEVICE_ID_INTEL_MFD_EMMC1)
+               gpio = 118;
+       else
+               return ret;
+
+       __gpio_set_value(gpio, 1);
+       udelay(300);
+       __gpio_set_value(gpio, 0);
+
+       return 0;
+}
+
 static struct sdhci_ops sdhci_pci_ops = {
        .enable_dma     = sdhci_pci_enable_dma,
+       .reset_emmc = sdhci_pci_reset_emmc,
 };
 
 /*****************************************************************************\
@@ -817,6 +851,20 @@ static struct sdhci_pci_slot * __devinit 
sdhci_pci_probe_slot(
        if (ret)
                goto remove;
 
+       if (pdev->device == PCI_DEVICE_ID_INTEL_MFD_EMMC0) {
+               /* request gp_core_21 for eMMC0 */
+               gpio_request(117, "eMMC0");
+               /* set to be output and to be low state */
+               gpio_direction_output(117, 0);
+       }
+
+       if (pdev->device == PCI_DEVICE_ID_INTEL_MFD_EMMC1) {
+               /* request gp_core_22 for eMMC1 */
+               gpio_request(118, "eMMC1");
+               /* set to be output and to be low state */
+               gpio_direction_output(118, 0);
+       }
+
        return slot;
 
 remove:
@@ -839,12 +887,28 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot 
*slot)
 {
        int dead;
        u32 scratch;
+       struct pci_dev *pdev;
 
        dead = 0;
        scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
        if (scratch == (u32)-1)
                dead = 1;
 
+       pdev = slot->chip->pdev;
+       if (pdev->device == PCI_DEVICE_ID_INTEL_MFD_EMMC0) {
+               /* set to be output and to be low state */
+               gpio_direction_output(117, 0);
+               /* free gp_core_21 for eMMC0 */
+               gpio_free(117);
+       }
+
+       if (pdev->device == PCI_DEVICE_ID_INTEL_MFD_EMMC1) {
+               /* set to be output and to be low state */
+               gpio_direction_output(118, 0);
+               /* free gp_core_22 for eMMC1 */
+               gpio_free(118);
+       }
+
        sdhci_remove_host(slot->host, dead);
 
        if (slot->chip->fixes && slot->chip->fixes->remove_slot)
-- 
1.6.6.1

_______________________________________________
MeeGo-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to