Commit 52c506f0bc72530fb786838e7ffd4f158a2e5c3a

Authored by Adrian Hunter
Committed by Chris Ball
1 parent c79396c191

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>

Showing 6 changed files with 54 additions and 7 deletions Side-by-side Diff

... ... @@ -97,7 +97,7 @@
97 97 obj-y += lguest/
98 98 obj-$(CONFIG_CPU_FREQ) += cpufreq/
99 99 obj-$(CONFIG_CPU_IDLE) += cpuidle/
100   -obj-$(CONFIG_MMC) += mmc/
  100 +obj-y += mmc/
101 101 obj-$(CONFIG_MEMSTICK) += memstick/
102 102 obj-y += leds/
103 103 obj-$(CONFIG_INFINIBAND) += infiniband/
drivers/mmc/Makefile
... ... @@ -6,5 +6,5 @@
6 6  
7 7 obj-$(CONFIG_MMC) += core/
8 8 obj-$(CONFIG_MMC) += card/
9   -obj-$(CONFIG_MMC) += host/
  9 +obj-$(subst m,y,$(CONFIG_MMC)) += host/
drivers/mmc/host/Makefile
... ... @@ -9,6 +9,7 @@
9 9 obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
10 10 obj-$(CONFIG_MMC_SDHCI) += sdhci.o
11 11 obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
  12 +obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o
12 13 obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
13 14 obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o
14 15 obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
drivers/mmc/host/sdhci-pci-data.c
  1 +#include <linux/module.h>
  2 +#include <linux/mmc/sdhci-pci-data.h>
  3 +
  4 +struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno);
  5 +EXPORT_SYMBOL_GPL(sdhci_pci_get_data);
drivers/mmc/host/sdhci-pci.c
... ... @@ -25,6 +25,7 @@
25 25 #include <linux/gpio.h>
26 26 #include <linux/sfi.h>
27 27 #include <linux/pm_runtime.h>
  28 +#include <linux/mmc/sdhci-pci-data.h>
28 29  
29 30 #include "sdhci.h"
30 31  
... ... @@ -61,6 +62,7 @@
61 62 struct sdhci_pci_slot {
62 63 struct sdhci_pci_chip *chip;
63 64 struct sdhci_host *host;
  65 + struct sdhci_pci_data *data;
64 66  
65 67 int pci_bar;
66 68 int rst_n_gpio;
67 69  
... ... @@ -1188,11 +1190,12 @@
1188 1190 \*****************************************************************************/
1189 1191  
1190 1192 static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
1191   - struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar)
  1193 + struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
  1194 + int slotno)
1192 1195 {
1193 1196 struct sdhci_pci_slot *slot;
1194 1197 struct sdhci_host *host;
1195   - int ret;
  1198 + int ret, bar = first_bar + slotno;
1196 1199  
1197 1200 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
1198 1201 dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar);
... ... @@ -1227,6 +1230,20 @@
1227 1230 slot->pci_bar = bar;
1228 1231 slot->rst_n_gpio = -EINVAL;
1229 1232  
  1233 + /* Retrieve platform data if there is any */
  1234 + if (*sdhci_pci_get_data)
  1235 + slot->data = sdhci_pci_get_data(pdev, slotno);
  1236 +
  1237 + if (slot->data) {
  1238 + if (slot->data->setup) {
  1239 + ret = slot->data->setup(slot->data);
  1240 + if (ret) {
  1241 + dev_err(&pdev->dev, "platform setup failed\n");
  1242 + goto free;
  1243 + }
  1244 + }
  1245 + }
  1246 +
1230 1247 host->hw_name = "PCI";
1231 1248 host->ops = &sdhci_pci_ops;
1232 1249 host->quirks = chip->quirks;
... ... @@ -1236,7 +1253,7 @@
1236 1253 ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
1237 1254 if (ret) {
1238 1255 dev_err(&pdev->dev, "cannot request region\n");
1239   - goto free;
  1256 + goto cleanup;
1240 1257 }
1241 1258  
1242 1259 host->ioaddr = pci_ioremap_bar(pdev, bar);
... ... @@ -1270,6 +1287,10 @@
1270 1287 release:
1271 1288 pci_release_region(pdev, bar);
1272 1289  
  1290 +cleanup:
  1291 + if (slot->data && slot->data->cleanup)
  1292 + slot->data->cleanup(slot->data);
  1293 +
1273 1294 free:
1274 1295 sdhci_free_host(host);
1275 1296  
... ... @@ -1291,6 +1312,9 @@
1291 1312 if (slot->chip->fixes && slot->chip->fixes->remove_slot)
1292 1313 slot->chip->fixes->remove_slot(slot, dead);
1293 1314  
  1315 + if (slot->data && slot->data->cleanup)
  1316 + slot->data->cleanup(slot->data);
  1317 +
1294 1318 pci_release_region(slot->chip->pdev, slot->pci_bar);
1295 1319  
1296 1320 sdhci_free_host(slot->host);
... ... @@ -1377,7 +1401,7 @@
1377 1401 slots = chip->num_slots; /* Quirk may have changed this */
1378 1402  
1379 1403 for (i = 0; i < slots; i++) {
1380   - slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i);
  1404 + slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i);
1381 1405 if (IS_ERR(slot)) {
1382 1406 for (i--; i >= 0; i--)
1383 1407 sdhci_pci_remove_slot(chip->slots[i]);
include/linux/mmc/sdhci-pci-data.h
  1 +#ifndef LINUX_MMC_SDHCI_PCI_DATA_H
  2 +#define LINUX_MMC_SDHCI_PCI_DATA_H
  3 +
  4 +struct pci_dev;
  5 +
  6 +struct sdhci_pci_data {
  7 + struct pci_dev *pdev;
  8 + int slotno;
  9 + int rst_n_gpio; /* Set to -EINVAL if unused */
  10 + int cd_gpio; /* Set to -EINVAL if unused */
  11 + int (*setup)(struct sdhci_pci_data *data);
  12 + void (*cleanup)(struct sdhci_pci_data *data);
  13 +};
  14 +
  15 +extern struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev,
  16 + int slotno);
  17 +
  18 +#endif