>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
