forked from mirrors/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>
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
	
	 Adrian Hunter
						Adrian Hunter