Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Adrian Hunter and committed by
Chris Ball
52c506f0 c79396c1

+54 -7
+1 -1
drivers/Makefile
··· 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/
+1 -2
drivers/mmc/Makefile
··· 6 6 7 7 obj-$(CONFIG_MMC) += core/ 8 8 obj-$(CONFIG_MMC) += card/ 9 - obj-$(CONFIG_MMC) += host/ 10 - 9 + obj-$(subst m,y,$(CONFIG_MMC)) += host/
+1
drivers/mmc/host/Makefile
··· 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
+5
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);
+28 -4
drivers/mmc/host/sdhci-pci.c
··· 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 ··· 62 61 struct sdhci_pci_slot { 63 62 struct sdhci_pci_chip *chip; 64 63 struct sdhci_host *host; 64 + struct sdhci_pci_data *data; 65 65 66 66 int pci_bar; 67 67 int rst_n_gpio; ··· 1190 1188 \*****************************************************************************/ 1191 1189 1192 1190 static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( 1193 - struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar) 1191 + struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar, 1192 + int slotno) 1194 1193 { 1195 1194 struct sdhci_pci_slot *slot; 1196 1195 struct sdhci_host *host; 1197 - int ret; 1196 + int ret, bar = first_bar + slotno; 1198 1197 1199 1198 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { 1200 1199 dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar); ··· 1230 1227 slot->pci_bar = bar; 1231 1228 slot->rst_n_gpio = -EINVAL; 1232 1229 1230 + /* Retrieve platform data if there is any */ 1231 + if (*sdhci_pci_get_data) 1232 + slot->data = sdhci_pci_get_data(pdev, slotno); 1233 + 1234 + if (slot->data) { 1235 + if (slot->data->setup) { 1236 + ret = slot->data->setup(slot->data); 1237 + if (ret) { 1238 + dev_err(&pdev->dev, "platform setup failed\n"); 1239 + goto free; 1240 + } 1241 + } 1242 + } 1243 + 1233 1244 host->hw_name = "PCI"; 1234 1245 host->ops = &sdhci_pci_ops; 1235 1246 host->quirks = chip->quirks; ··· 1253 1236 ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc)); 1254 1237 if (ret) { 1255 1238 dev_err(&pdev->dev, "cannot request region\n"); 1256 - goto free; 1239 + goto cleanup; 1257 1240 } 1258 1241 1259 1242 host->ioaddr = pci_ioremap_bar(pdev, bar); ··· 1287 1270 release: 1288 1271 pci_release_region(pdev, bar); 1289 1272 1273 + cleanup: 1274 + if (slot->data && slot->data->cleanup) 1275 + slot->data->cleanup(slot->data); 1276 + 1290 1277 free: 1291 1278 sdhci_free_host(host); 1292 1279 ··· 1311 1290 1312 1291 if (slot->chip->fixes && slot->chip->fixes->remove_slot) 1313 1292 slot->chip->fixes->remove_slot(slot, dead); 1293 + 1294 + if (slot->data && slot->data->cleanup) 1295 + slot->data->cleanup(slot->data); 1314 1296 1315 1297 pci_release_region(slot->chip->pdev, slot->pci_bar); 1316 1298 ··· 1401 1377 slots = chip->num_slots; /* Quirk may have changed this */ 1402 1378 1403 1379 for (i = 0; i < slots; i++) { 1404 - slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i); 1380 + slot = sdhci_pci_probe_slot(pdev, chip, first_bar, i); 1405 1381 if (IS_ERR(slot)) { 1406 1382 for (i--; i >= 0; i--) 1407 1383 sdhci_pci_remove_slot(chip->slots[i]);
+18
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