Commit 52c506f0bc72530fb786838e7ffd4f158a2e5c3a
Committed by
Chris Ball
1 parent
c79396c191
Exists in
master
and in
38 other branches
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
drivers/Makefile
drivers/mmc/Makefile
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
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 |