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:
parent
c79396c191
commit
52c506f0bc
6 changed files with 54 additions and 7 deletions
|
@ -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/
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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
|
||||
|
|
5
drivers/mmc/host/sdhci-pci-data.c
Normal file
5
drivers/mmc/host/sdhci-pci-data.c
Normal 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);
|
|
@ -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 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
|
|||
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]);
|
||||
|
|
18
include/linux/mmc/sdhci-pci-data.h
Normal file
18
include/linux/mmc/sdhci-pci-data.h
Normal 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
|
Loading…
Reference in a new issue