mmc: sdhci-pci: add platform data
authorAdrian Hunter <adrian.hunter@intel.com>
Tue, 27 Dec 2011 13:48:43 +0000 (15:48 +0200)
committerChris Ball <cjb@laptop.org>
Thu, 12 Jan 2012 04:58:47 +0000 (23:58 -0500)
Add a means of getting platform data for the SDHCI PCI
devices.  The data is stored against the slot not the
device in order to support multi-slot devices.

The data allows platform-specific setup (such as getting
GPIO numbers from firmware or setting up wl12xx for SDIO)
to be done in platform support files instead of the
sdhci-pci driver.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
drivers/Makefile
drivers/mmc/Makefile
drivers/mmc/host/Makefile
drivers/mmc/host/sdhci-pci-data.c [new file with mode: 0644]
drivers/mmc/host/sdhci-pci.c
include/linux/mmc/sdhci-pci-data.h [new file with mode: 0644]

index 1b3142127bf5f7308f3e7fc9fb83ff88a4730f2e..c07be024b962aa9ad8cce1ef635f37acd0a18fae 100644 (file)
@@ -97,7 +97,7 @@ obj-$(CONFIG_EISA)            += eisa/
 obj-y                          += lguest/
 obj-$(CONFIG_CPU_FREQ)         += cpufreq/
 obj-$(CONFIG_CPU_IDLE)         += cpuidle/
-obj-$(CONFIG_MMC)              += mmc/
+obj-y                          += mmc/
 obj-$(CONFIG_MEMSTICK)         += memstick/
 obj-y                          += leds/
 obj-$(CONFIG_INFINIBAND)       += infiniband/
index 12eef393e2160103ac3e63dadcefd5817e99a6a9..400756ec7c492dfd527dc5154b6601ae0ef1060d 100644 (file)
@@ -6,5 +6,4 @@ subdir-ccflags-$(CONFIG_MMC_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_MMC)              += core/
 obj-$(CONFIG_MMC)              += card/
-obj-$(CONFIG_MMC)              += host/
-
+obj-$(subst m,y,$(CONFIG_MMC)) += host/
index b4b83f302e325f52a9d138884644cf8c9eb52819..745f8fce251986278b408951fd1d5b4a12015893 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXC)           += mxcmmc.o
 obj-$(CONFIG_MMC_MXS)          += mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)                += sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)    += sdhci-pci.o
+obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI))       += sdhci-pci-data.o
 obj-$(CONFIG_MMC_SDHCI_PXAV3)  += sdhci-pxav3.o
 obj-$(CONFIG_MMC_SDHCI_PXAV2)  += sdhci-pxav2.o
 obj-$(CONFIG_MMC_SDHCI_S3C)    += sdhci-s3c.o
diff --git a/drivers/mmc/host/sdhci-pci-data.c b/drivers/mmc/host/sdhci-pci-data.c
new file mode 100644 (file)
index 0000000..a611217
--- /dev/null
@@ -0,0 +1,5 @@
+#include <linux/module.h>
+#include <linux/mmc/sdhci-pci-data.h>
+
+struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno);
+EXPORT_SYMBOL_GPL(sdhci_pci_get_data);
index d2e77fb21b26247e7cb0fda103114b7e9d42dda7..4e8f324e2c846fc62170ee7d100f62c73eb341b9 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/sfi.h>
 #include <linux/pm_runtime.h>
+#include <linux/mmc/sdhci-pci-data.h>
 
 #include "sdhci.h"
 
@@ -61,6 +62,7 @@ struct sdhci_pci_fixes {
 struct sdhci_pci_slot {
        struct sdhci_pci_chip   *chip;
        struct sdhci_host       *host;
+       struct sdhci_pci_data   *data;
 
        int                     pci_bar;
        int                     rst_n_gpio;
@@ -1188,11 +1190,12 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
 \*****************************************************************************/
 
 static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
-       struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar)
+       struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
+       int slotno)
 {
        struct sdhci_pci_slot *slot;
        struct sdhci_host *host;
-       int ret;
+       int ret, bar = first_bar + slotno;
 
        if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
                dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar);
@@ -1227,6 +1230,20 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
        slot->pci_bar = bar;
        slot->rst_n_gpio = -EINVAL;
 
+       /* Retrieve platform data if there is any */
+       if (*sdhci_pci_get_data)
+               slot->data = sdhci_pci_get_data(pdev, slotno);
+
+       if (slot->data) {
+               if (slot->data->setup) {
+                       ret = slot->data->setup(slot->data);
+                       if (ret) {
+                               dev_err(&pdev->dev, "platform setup failed\n");
+                               goto free;
+                       }
+               }
+       }
+
        host->hw_name = "PCI";
        host->ops = &sdhci_pci_ops;
        host->quirks = chip->quirks;
@@ -1236,7 +1253,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
        ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
        if (ret) {
                dev_err(&pdev->dev, "cannot request region\n");
-               goto free;
+               goto cleanup;
        }
 
        host->ioaddr = pci_ioremap_bar(pdev, bar);
@@ -1270,6 +1287,10 @@ unmap:
 release:
        pci_release_region(pdev, bar);
 
+cleanup:
+       if (slot->data && slot->data->cleanup)
+               slot->data->cleanup(slot->data);
+
 free:
        sdhci_free_host(host);
 
@@ -1291,6 +1312,9 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
        if (slot->chip->fixes && slot->chip->fixes->remove_slot)
                slot->chip->fixes->remove_slot(slot, dead);
 
+       if (slot->data && slot->data->cleanup)
+               slot->data->cleanup(slot->data);
+
        pci_release_region(slot->chip->pdev, slot->pci_bar);
 
        sdhci_free_host(slot->host);
@@ -1377,7 +1401,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
        slots = chip->num_slots;        /* Quirk may have changed this */
 
        for (i = 0; i < slots; i++) {
-               slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i);
+               slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i);
                if (IS_ERR(slot)) {
                        for (i--; i >= 0; i--)
                                sdhci_pci_remove_slot(chip->slots[i]);
diff --git a/include/linux/mmc/sdhci-pci-data.h b/include/linux/mmc/sdhci-pci-data.h
new file mode 100644 (file)
index 0000000..8959604
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef LINUX_MMC_SDHCI_PCI_DATA_H
+#define LINUX_MMC_SDHCI_PCI_DATA_H
+
+struct pci_dev;
+
+struct sdhci_pci_data {
+       struct pci_dev  *pdev;
+       int             slotno;
+       int             rst_n_gpio; /* Set to -EINVAL if unused */
+       int             cd_gpio;    /* Set to -EINVAL if unused */
+       int             (*setup)(struct sdhci_pci_data *data);
+       void            (*cleanup)(struct sdhci_pci_data *data);
+};
+
+extern struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev,
+                               int slotno);
+
+#endif