Skip to content

Commit

Permalink
mmc: sdhci-pci: get gpio numbers from platform data
Browse files Browse the repository at this point in the history
Retrieve the GPIO numbers for hardware reset and
card detect from platform data.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
  • Loading branch information
Adrian Hunter authored and Chris Ball committed Jan 12, 2012
1 parent 52c506f commit c5e027a
Showing 1 changed file with 41 additions and 68 deletions.
109 changes: 41 additions & 68 deletions drivers/mmc/host/sdhci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <linux/scatterlist.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/sfi.h>
#include <linux/pm_runtime.h>
#include <linux/mmc/sdhci-pci-data.h>

Expand Down Expand Up @@ -173,32 +172,9 @@ static int mrst_hc_probe(struct sdhci_pci_chip *chip)
return 0;
}

/* Medfield eMMC hardware reset GPIOs */
static int mfd_emmc0_rst_gpio = -EINVAL;
static int mfd_emmc1_rst_gpio = -EINVAL;

static int mfd_emmc_gpio_parse(struct sfi_table_header *table)
{
struct sfi_table_simple *sb = (struct sfi_table_simple *)table;
struct sfi_gpio_table_entry *entry;
int i, num;

num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
entry = (struct sfi_gpio_table_entry *)sb->pentry;

for (i = 0; i < num; i++, entry++) {
if (!strncmp(entry->pin_name, "emmc0_rst", SFI_NAME_LEN))
mfd_emmc0_rst_gpio = entry->pin_no;
else if (!strncmp(entry->pin_name, "emmc1_rst", SFI_NAME_LEN))
mfd_emmc1_rst_gpio = entry->pin_no;
}

return 0;
}

#ifdef CONFIG_PM_RUNTIME

static irqreturn_t mfd_sd_cd(int irq, void *dev_id)
static irqreturn_t sdhci_pci_sd_cd(int irq, void *dev_id)
{
struct sdhci_pci_slot *slot = dev_id;
struct sdhci_host *host = slot->host;
Expand All @@ -207,15 +183,16 @@ static irqreturn_t mfd_sd_cd(int irq, void *dev_id)
return IRQ_HANDLED;
}

#define MFLD_SD_CD_PIN 69

static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot)
static void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot)
{
int err, irq, gpio = MFLD_SD_CD_PIN;
int err, irq, gpio = slot->cd_gpio;

slot->cd_gpio = -EINVAL;
slot->cd_irq = -EINVAL;

if (!gpio_is_valid(gpio))
return;

err = gpio_request(gpio, "sd_cd");
if (err < 0)
goto out;
Expand All @@ -228,7 +205,7 @@ static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot)
if (irq < 0)
goto out_free;

err = request_irq(irq, mfd_sd_cd, IRQF_TRIGGER_RISING |
err = request_irq(irq, sdhci_pci_sd_cd, IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING, "sd_cd", slot);
if (err)
goto out_free;
Expand All @@ -237,65 +214,41 @@ static int mfd_sd_probe_slot(struct sdhci_pci_slot *slot)
slot->cd_irq = irq;
slot->host->quirks2 |= SDHCI_QUIRK2_OWN_CARD_DETECTION;

return 0;
return;

out_free:
gpio_free(gpio);
out:
dev_warn(&slot->chip->pdev->dev, "failed to setup card detect wake up\n");
return 0;
}

static void mfd_sd_remove_slot(struct sdhci_pci_slot *slot, int dead)
static void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot)
{
if (slot->cd_irq >= 0)
free_irq(slot->cd_irq, slot);
gpio_free(slot->cd_gpio);
if (gpio_is_valid(slot->cd_gpio))
gpio_free(slot->cd_gpio);
}

#else

#define mfd_sd_probe_slot NULL
#define mfd_sd_remove_slot NULL
static inline void sdhci_pci_add_own_cd(struct sdhci_pci_slot *slot)
{
}

static inline void sdhci_pci_remove_own_cd(struct sdhci_pci_slot *slot)
{
}

#endif

static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot)
{
const char *name = NULL;
int gpio = -EINVAL;

sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, mfd_emmc_gpio_parse);

switch (slot->chip->pdev->device) {
case PCI_DEVICE_ID_INTEL_MFD_EMMC0:
gpio = mfd_emmc0_rst_gpio;
name = "eMMC0_reset";
break;
case PCI_DEVICE_ID_INTEL_MFD_EMMC1:
gpio = mfd_emmc1_rst_gpio;
name = "eMMC1_reset";
break;
}

if (!gpio_request(gpio, name)) {
gpio_direction_output(gpio, 1);
slot->rst_n_gpio = gpio;
slot->host->mmc->caps |= MMC_CAP_HW_RESET;
}

slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE;

slot->host->mmc->caps2 = MMC_CAP2_BOOTPART_NOACC;

return 0;
}

static void mfd_emmc_remove_slot(struct sdhci_pci_slot *slot, int dead)
{
gpio_free(slot->rst_n_gpio);
}

static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
.quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
.probe_slot = mrst_hc_probe_slot,
Expand All @@ -309,8 +262,6 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.allow_runtime_pm = true,
.probe_slot = mfd_sd_probe_slot,
.remove_slot = mfd_sd_remove_slot,
};

static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = {
Expand All @@ -322,7 +273,6 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.allow_runtime_pm = true,
.probe_slot = mfd_emmc_probe_slot,
.remove_slot = mfd_emmc_remove_slot,
};

/* O2Micro extra registers */
Expand Down Expand Up @@ -1229,6 +1179,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
slot->host = host;
slot->pci_bar = bar;
slot->rst_n_gpio = -EINVAL;
slot->cd_gpio = -EINVAL;

/* Retrieve platform data if there is any */
if (*sdhci_pci_get_data)
Expand All @@ -1242,6 +1193,8 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
goto free;
}
}
slot->rst_n_gpio = slot->data->rst_n_gpio;
slot->cd_gpio = slot->data->cd_gpio;
}

host->hw_name = "PCI";
Expand Down Expand Up @@ -1269,15 +1222,30 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
goto unmap;
}

if (gpio_is_valid(slot->rst_n_gpio)) {
if (!gpio_request(slot->rst_n_gpio, "eMMC_reset")) {
gpio_direction_output(slot->rst_n_gpio, 1);
slot->host->mmc->caps |= MMC_CAP_HW_RESET;
} else {
dev_warn(&pdev->dev, "failed to request rst_n_gpio\n");
slot->rst_n_gpio = -EINVAL;
}
}

host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;

ret = sdhci_add_host(host);
if (ret)
goto remove;

sdhci_pci_add_own_cd(slot);

return slot;

remove:
if (gpio_is_valid(slot->rst_n_gpio))
gpio_free(slot->rst_n_gpio);

if (chip->fixes && chip->fixes->remove_slot)
chip->fixes->remove_slot(slot, 0);

Expand All @@ -1302,13 +1270,18 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
int dead;
u32 scratch;

sdhci_pci_remove_own_cd(slot);

dead = 0;
scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
if (scratch == (u32)-1)
dead = 1;

sdhci_remove_host(slot->host, dead);

if (gpio_is_valid(slot->rst_n_gpio))
gpio_free(slot->rst_n_gpio);

if (slot->chip->fixes && slot->chip->fixes->remove_slot)
slot->chip->fixes->remove_slot(slot, dead);

Expand Down

0 comments on commit c5e027a

Please sign in to comment.