diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-25 08:23:32 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-25 08:23:32 -0700 |
commit | 92bf3d09410531a06e06504957271e3978f937e2 (patch) | |
tree | e638413049deb010103bc65e2650d1315dbaa748 /drivers/mmc/host/mmci.c | |
parent | 603d6637aeb9a14cd0087d7c24c3777bfa51fcbf (diff) | |
parent | 0caaa9539adcff38ce12e99f0ab25645e7eb3eea (diff) |
Merge tag 'mmc-merge-for-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC changes from Chris Ball
- at91-mci: This driver will be replaced by atmel-mci in 3.7.
- atmel-mci: Add support for old at91-mci hardware.
- dw_mmc: Allow multiple controllers; this previously caused
corruption.
- imxmmc: Remove this driver, replaced by mxcmmc.
- mmci: Add device tree support.
- omap: Allow multiple controllers.
- omap_hsmmc: Auto CMD12, DDR support.
- tegra: Support SD 3.0 spec.
Fix up the usual trivial conflicts in feature-removal-schedule.txt
* tag 'mmc-merge-for-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (38 commits)
mmc: at91-mci: this driver is now deprecated
mmc: omap_hsmmc: pass IRQF_ONESHOT to request_threaded_irq
mmc: block: Allow disabling 512B sector size emulation
mmc: atmel-mci: add debug logs
mmc: atmel-mci: add support for version lower than v2xx
mmc: atmel-mci: change the state machine for compatibility with old IP
mmc: atmel-mci: the r/w proof capability lack was not well managed
mmc: dw_mmc: Fixed sdio interrupt mask bit setting bug
mmc: omap: convert to module_platform_driver
mmc: omap: make it behave well as a module
mmc: omap: convert to per instance workqueue
mmc: core: Remove dead code
mmc: card: Avoid null pointer dereference
mmc: core: Prevent eMMC VCC supply to be cut from late init
mmc: dw_mmc: make multiple instances of dw_mci_card_workqueue
mmc: queue: remove redundant memsets
mmc: queue: rename mmc_request function
mmc: core: skip card initialization if power class selection fails
mmc: core: fix the signaling 1.8V for HS200
mmc: core: fix the decision of HS200/DDR card-type
...
Diffstat (limited to 'drivers/mmc/host/mmci.c')
-rw-r--r-- | drivers/mmc/host/mmci.c | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index b6f38421d541..f0fcce40cd8d 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -15,6 +15,7 @@ #include <linux/device.h> #include <linux/interrupt.h> #include <linux/kernel.h> +#include <linux/slab.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/highmem.h> @@ -25,6 +26,7 @@ #include <linux/clk.h> #include <linux/scatterlist.h> #include <linux/gpio.h> +#include <linux/of_gpio.h> #include <linux/regulator/consumer.h> #include <linux/dmaengine.h> #include <linux/dma-mapping.h> @@ -1207,21 +1209,76 @@ static const struct mmc_host_ops mmci_ops = { .get_cd = mmci_get_cd, }; +#ifdef CONFIG_OF +static void mmci_dt_populate_generic_pdata(struct device_node *np, + struct mmci_platform_data *pdata) +{ + int bus_width = 0; + + pdata->gpio_wp = of_get_named_gpio(np, "wp-gpios", 0); + if (!pdata->gpio_wp) + pdata->gpio_wp = -1; + + pdata->gpio_cd = of_get_named_gpio(np, "cd-gpios", 0); + if (!pdata->gpio_cd) + pdata->gpio_cd = -1; + + if (of_get_property(np, "cd-inverted", NULL)) + pdata->cd_invert = true; + else + pdata->cd_invert = false; + + of_property_read_u32(np, "max-frequency", &pdata->f_max); + if (!pdata->f_max) + pr_warn("%s has no 'max-frequency' property\n", np->full_name); + + if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL)) + pdata->capabilities |= MMC_CAP_MMC_HIGHSPEED; + if (of_get_property(np, "mmc-cap-sd-highspeed", NULL)) + pdata->capabilities |= MMC_CAP_SD_HIGHSPEED; + + of_property_read_u32(np, "bus-width", &bus_width); + switch (bus_width) { + case 0 : + /* No bus-width supplied. */ + break; + case 4 : + pdata->capabilities |= MMC_CAP_4_BIT_DATA; + break; + case 8 : + pdata->capabilities |= MMC_CAP_8_BIT_DATA; + break; + default : + pr_warn("%s: Unsupported bus width\n", np->full_name); + } +} +#else +static void mmci_dt_populate_generic_pdata(struct device_node *np, + struct mmci_platform_data *pdata) +{ + return; +} +#endif + static int __devinit mmci_probe(struct amba_device *dev, const struct amba_id *id) { struct mmci_platform_data *plat = dev->dev.platform_data; + struct device_node *np = dev->dev.of_node; struct variant_data *variant = id->data; struct mmci_host *host; struct mmc_host *mmc; int ret; - /* must have platform data */ - if (!plat) { - ret = -EINVAL; - goto out; + /* Must have platform data or Device Tree. */ + if (!plat && !np) { + dev_err(&dev->dev, "No plat data or DT found\n"); + return -EINVAL; } + if (np) + mmci_dt_populate_generic_pdata(np, plat); + ret = amba_request_regions(dev, DRIVER_NAME); if (ret) goto out; |