aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2011-12-27 08:48:43 -0500
committerChris Ball <cjb@laptop.org>2012-01-11 23:58:47 -0500
commit52c506f0bc72530fb786838e7ffd4f158a2e5c3a (patch)
tree2c46fdd2ce9ac582846733ed60f12caea2856196
parentc79396c191bc19703df6eb6bbd0f673ed0df6c9d (diff)
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>
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/mmc/Makefile3
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/sdhci-pci-data.c5
-rw-r--r--drivers/mmc/host/sdhci-pci.c32
-rw-r--r--include/linux/mmc/sdhci-pci-data.h18
6 files changed, 54 insertions, 7 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 1b3142127bf..c07be024b96 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -97,7 +97,7 @@ obj-$(CONFIG_EISA) += eisa/
97obj-y += lguest/ 97obj-y += lguest/
98obj-$(CONFIG_CPU_FREQ) += cpufreq/ 98obj-$(CONFIG_CPU_FREQ) += cpufreq/
99obj-$(CONFIG_CPU_IDLE) += cpuidle/ 99obj-$(CONFIG_CPU_IDLE) += cpuidle/
100obj-$(CONFIG_MMC) += mmc/ 100obj-y += mmc/
101obj-$(CONFIG_MEMSTICK) += memstick/ 101obj-$(CONFIG_MEMSTICK) += memstick/
102obj-y += leds/ 102obj-y += leds/
103obj-$(CONFIG_INFINIBAND) += infiniband/ 103obj-$(CONFIG_INFINIBAND) += infiniband/
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 12eef393e21..400756ec7c4 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -6,5 +6,4 @@ subdir-ccflags-$(CONFIG_MMC_DEBUG) := -DDEBUG
6 6
7obj-$(CONFIG_MMC) += core/ 7obj-$(CONFIG_MMC) += core/
8obj-$(CONFIG_MMC) += card/ 8obj-$(CONFIG_MMC) += card/
9obj-$(CONFIG_MMC) += host/ 9obj-$(subst m,y,$(CONFIG_MMC)) += host/
10
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index b4b83f302e3..745f8fce251 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o
9obj-$(CONFIG_MMC_MXS) += mxs-mmc.o 9obj-$(CONFIG_MMC_MXS) += mxs-mmc.o
10obj-$(CONFIG_MMC_SDHCI) += sdhci.o 10obj-$(CONFIG_MMC_SDHCI) += sdhci.o
11obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o 11obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
12obj-$(subst m,y,$(CONFIG_MMC_SDHCI_PCI)) += sdhci-pci-data.o
12obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o 13obj-$(CONFIG_MMC_SDHCI_PXAV3) += sdhci-pxav3.o
13obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o 14obj-$(CONFIG_MMC_SDHCI_PXAV2) += sdhci-pxav2.o
14obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o 15obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
diff --git a/drivers/mmc/host/sdhci-pci-data.c b/drivers/mmc/host/sdhci-pci-data.c
new file mode 100644
index 00000000000..a611217769f
--- /dev/null
+++ b/drivers/mmc/host/sdhci-pci-data.c
@@ -0,0 +1,5 @@
1#include <linux/module.h>
2#include <linux/mmc/sdhci-pci-data.h>
3
4struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev, int slotno);
5EXPORT_SYMBOL_GPL(sdhci_pci_get_data);
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index d2e77fb21b2..4e8f324e2c8 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -25,6 +25,7 @@
25#include <linux/gpio.h> 25#include <linux/gpio.h>
26#include <linux/sfi.h> 26#include <linux/sfi.h>
27#include <linux/pm_runtime.h> 27#include <linux/pm_runtime.h>
28#include <linux/mmc/sdhci-pci-data.h>
28 29
29#include "sdhci.h" 30#include "sdhci.h"
30 31
@@ -61,6 +62,7 @@ struct sdhci_pci_fixes {
61struct sdhci_pci_slot { 62struct sdhci_pci_slot {
62 struct sdhci_pci_chip *chip; 63 struct sdhci_pci_chip *chip;
63 struct sdhci_host *host; 64 struct sdhci_host *host;
65 struct sdhci_pci_data *data;
64 66
65 int pci_bar; 67 int pci_bar;
66 int rst_n_gpio; 68 int rst_n_gpio;
@@ -1188,11 +1190,12 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
1188\*****************************************************************************/ 1190\*****************************************************************************/
1189 1191
1190static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( 1192static 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 struct sdhci_pci_slot *slot; 1196 struct sdhci_pci_slot *slot;
1194 struct sdhci_host *host; 1197 struct sdhci_host *host;
1195 int ret; 1198 int ret, bar = first_bar + slotno;
1196 1199
1197 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { 1200 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
1198 dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar); 1201 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(
1227 slot->pci_bar = bar; 1230 slot->pci_bar = bar;
1228 slot->rst_n_gpio = -EINVAL; 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 host->hw_name = "PCI"; 1247 host->hw_name = "PCI";
1231 host->ops = &sdhci_pci_ops; 1248 host->ops = &sdhci_pci_ops;
1232 host->quirks = chip->quirks; 1249 host->quirks = chip->quirks;
@@ -1236,7 +1253,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
1236 ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc)); 1253 ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
1237 if (ret) { 1254 if (ret) {
1238 dev_err(&pdev->dev, "cannot request region\n"); 1255 dev_err(&pdev->dev, "cannot request region\n");
1239 goto free; 1256 goto cleanup;
1240 } 1257 }
1241 1258
1242 host->ioaddr = pci_ioremap_bar(pdev, bar); 1259 host->ioaddr = pci_ioremap_bar(pdev, bar);
@@ -1270,6 +1287,10 @@ unmap:
1270release: 1287release:
1271 pci_release_region(pdev, bar); 1288 pci_release_region(pdev, bar);
1272 1289
1290cleanup:
1291 if (slot->data && slot->data->cleanup)
1292 slot->data->cleanup(slot->data);
1293
1273free: 1294free:
1274 sdhci_free_host(host); 1295 sdhci_free_host(host);
1275 1296
@@ -1291,6 +1312,9 @@ static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
1291 if (slot->chip->fixes && slot->chip->fixes->remove_slot) 1312 if (slot->chip->fixes && slot->chip->fixes->remove_slot)
1292 slot->chip->fixes->remove_slot(slot, dead); 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 pci_release_region(slot->chip->pdev, slot->pci_bar); 1318 pci_release_region(slot->chip->pdev, slot->pci_bar);
1295 1319
1296 sdhci_free_host(slot->host); 1320 sdhci_free_host(slot->host);
@@ -1377,7 +1401,7 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
1377 slots = chip->num_slots; /* Quirk may have changed this */ 1401 slots = chip->num_slots; /* Quirk may have changed this */
1378 1402
1379 for (i = 0; i < slots; i++) { 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 if (IS_ERR(slot)) { 1405 if (IS_ERR(slot)) {
1382 for (i--; i >= 0; i--) 1406 for (i--; i >= 0; i--)
1383 sdhci_pci_remove_slot(chip->slots[i]); 1407 sdhci_pci_remove_slot(chip->slots[i]);
diff --git a/include/linux/mmc/sdhci-pci-data.h b/include/linux/mmc/sdhci-pci-data.h
new file mode 100644
index 00000000000..8959604a13d
--- /dev/null
+++ b/include/linux/mmc/sdhci-pci-data.h
@@ -0,0 +1,18 @@
1#ifndef LINUX_MMC_SDHCI_PCI_DATA_H
2#define LINUX_MMC_SDHCI_PCI_DATA_H
3
4struct pci_dev;
5
6struct 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
15extern struct sdhci_pci_data *(*sdhci_pci_get_data)(struct pci_dev *pdev,
16 int slotno);
17
18#endif