dect
/
linux-2.6
Archived
13
0
Fork 0

mmc: sdhci-pci: add platform data

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>
This commit is contained in:
Adrian Hunter 2011-12-27 15:48:43 +02:00 committed by Chris Ball
parent c79396c191
commit 52c506f0bc
6 changed files with 54 additions and 7 deletions

View File

@ -97,7 +97,7 @@ obj-$(CONFIG_EISA) += eisa/
obj-y += lguest/ obj-y += lguest/
obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_CPU_IDLE) += cpuidle/ obj-$(CONFIG_CPU_IDLE) += cpuidle/
obj-$(CONFIG_MMC) += mmc/ obj-y += mmc/
obj-$(CONFIG_MEMSTICK) += memstick/ obj-$(CONFIG_MEMSTICK) += memstick/
obj-y += leds/ obj-y += leds/
obj-$(CONFIG_INFINIBAND) += infiniband/ obj-$(CONFIG_INFINIBAND) += infiniband/

View File

@ -6,5 +6,4 @@ subdir-ccflags-$(CONFIG_MMC_DEBUG) := -DDEBUG
obj-$(CONFIG_MMC) += core/ obj-$(CONFIG_MMC) += core/
obj-$(CONFIG_MMC) += card/ obj-$(CONFIG_MMC) += card/
obj-$(CONFIG_MMC) += host/ obj-$(subst m,y,$(CONFIG_MMC)) += host/

View File

@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_MXS) += mxs-mmc.o obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.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_PXAV3) += sdhci-pxav3.o
obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o

View File

@ -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);

View File

@ -25,6 +25,7 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/sfi.h> #include <linux/sfi.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/mmc/sdhci-pci-data.h>
#include "sdhci.h" #include "sdhci.h"
@ -61,6 +62,7 @@ struct sdhci_pci_fixes {
struct sdhci_pci_slot { struct sdhci_pci_slot {
struct sdhci_pci_chip *chip; struct sdhci_pci_chip *chip;
struct sdhci_host *host; struct sdhci_host *host;
struct sdhci_pci_data *data;
int pci_bar; int pci_bar;
int rst_n_gpio; 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( 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_pci_slot *slot;
struct sdhci_host *host; struct sdhci_host *host;
int ret; int ret, bar = first_bar + slotno;
if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar); 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->pci_bar = bar;
slot->rst_n_gpio = -EINVAL; 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->hw_name = "PCI";
host->ops = &sdhci_pci_ops; host->ops = &sdhci_pci_ops;
host->quirks = chip->quirks; 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)); ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
if (ret) { if (ret) {
dev_err(&pdev->dev, "cannot request region\n"); dev_err(&pdev->dev, "cannot request region\n");
goto free; goto cleanup;
} }
host->ioaddr = pci_ioremap_bar(pdev, bar); host->ioaddr = pci_ioremap_bar(pdev, bar);
@ -1270,6 +1287,10 @@ unmap:
release: release:
pci_release_region(pdev, bar); pci_release_region(pdev, bar);
cleanup:
if (slot->data && slot->data->cleanup)
slot->data->cleanup(slot->data);
free: free:
sdhci_free_host(host); 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) if (slot->chip->fixes && slot->chip->fixes->remove_slot)
slot->chip->fixes->remove_slot(slot, dead); 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); pci_release_region(slot->chip->pdev, slot->pci_bar);
sdhci_free_host(slot->host); 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 */ slots = chip->num_slots; /* Quirk may have changed this */
for (i = 0; i < slots; i++) { 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)) { if (IS_ERR(slot)) {
for (i--; i >= 0; i--) for (i--; i >= 0; i--)
sdhci_pci_remove_slot(chip->slots[i]); sdhci_pci_remove_slot(chip->slots[i]);

View File

@ -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