diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 21:58:42 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-09 21:58:42 -0400 |
commit | 943c2acea53784c45fb291498d04d5188fdea891 (patch) | |
tree | 063fac3e584f8f4a5babbc329499f84b3da291d7 /drivers/mmc/host | |
parent | 10f39f04b2cb7a06ba5d4ea0f20bd156d0367bee (diff) | |
parent | e6c085863f97f0a8f009753e1baaf83e4aac7b42 (diff) |
Merge tag 'mmc-merge-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC updates from Chris Ball:
"Core:
- Add DT properties for card detection (broken-cd, cd-gpios,
non-removable)
- Don't poll non-removable devices
- Fixup/rework eMMC sleep mode/"power off notify" feature
- Support eMMC background operations (BKOPS). To set the one-time
programmable fuse that enables bkops on an eMMC that doesn't
already have it set, you can use the "mmc bkops enable" command in:
git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc-utils.git
Drivers:
- atmel-mci, dw_mmc, pxa-mci, dove, s3c, spear: Add device tree
support
- bfin_sdh: Add support for the controller in bf60x
- dw_mmc: Support Samsung Exynos SoCs
- eSDHC: Add ADMA support
- sdhci: Support testing a cd-gpio (from slot-gpio) instead of
presence bit
- sdhci-pltfm: Support broken-cd DT property
- tegra: Convert to only supporting DT (mach-tegra has gone DT-only)"
* tag 'mmc-merge-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (67 commits)
mmc: core: Fixup broken suspend and eMMC4.5 power off notify
mmc: sdhci-spear: Add clk_{un}prepare() support
mmc: sdhci-spear: add device tree bindings
mmc: sdhci-s3c: Add clk_(enable/disable) in runtime suspend/resume
mmc: core: Replace MMC_CAP2_BROKEN_VOLTAGE with test for fixed regulator
mmc: sdhci-pxav3: Use sdhci_get_of_property for parsing DT quirks
mmc: dt: Support "broken-cd" property in sdhci-pltfm
mmc: sdhci-s3c: fix the wrong number of max bus clocks
mmc: sh-mmcif: avoid oops on spurious interrupts
mmc: sh-mmcif: properly handle MMC_WRITE_MULTIPLE_BLOCK completion IRQ
mmc: sdhci-s3c: Fix crash on module insertion for second time
mmc: sdhci-s3c: Enable only required bus clock
mmc: Revert "mmc: dw_mmc: Add check for IDMAC configuration"
mmc: mxcmmc: fix bug that may block a data transfer forever
mmc: omap_hsmmc: Pass on the suspend failure to the PM core
mmc: atmel-mci: AP700x PDC is not connected to MCI
mmc: atmel-mci: DMA can be used with other controllers
mmc: mmci: use clk_prepare_enable and clk_disable_unprepare
mmc: sdhci-s3c: Add device tree support
mmc: dw_mmc: add support for exynos specific implementation of dw-mshc
...
Diffstat (limited to 'drivers/mmc/host')
31 files changed, 1586 insertions, 673 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index aa131b32e3b2..9bf10e7bbfaf 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -540,6 +540,15 @@ config MMC_DW_PLTFM | |||
540 | 540 | ||
541 | If unsure, say Y. | 541 | If unsure, say Y. |
542 | 542 | ||
543 | config MMC_DW_EXYNOS | ||
544 | tristate "Exynos specific extentions for Synopsys DW Memory Card Interface" | ||
545 | depends on MMC_DW | ||
546 | select MMC_DW_PLTFM | ||
547 | help | ||
548 | This selects support for Samsung Exynos SoC specific extensions to the | ||
549 | Synopsys DesignWare Memory Card Interface driver. Select this option | ||
550 | for platforms based on Exynos4 and Exynos5 SoC's. | ||
551 | |||
543 | config MMC_DW_PCI | 552 | config MMC_DW_PCI |
544 | tristate "Synopsys Designware MCI support on PCI bus" | 553 | tristate "Synopsys Designware MCI support on PCI bus" |
545 | depends on MMC_DW && PCI | 554 | depends on MMC_DW && PCI |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 8922b06be925..17ad0a7ba40b 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -39,6 +39,7 @@ obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o | |||
39 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | 39 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o |
40 | obj-$(CONFIG_MMC_DW) += dw_mmc.o | 40 | obj-$(CONFIG_MMC_DW) += dw_mmc.o |
41 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o | 41 | obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o |
42 | obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o | ||
42 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o | 43 | obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o |
43 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 44 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
44 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o | 45 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o |
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index ab56f7db5315..c97001e15227 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h | |||
@@ -140,6 +140,13 @@ | |||
140 | #define atmci_writel(port,reg,value) \ | 140 | #define atmci_writel(port,reg,value) \ |
141 | __raw_writel((value), (port)->regs + reg) | 141 | __raw_writel((value), (port)->regs + reg) |
142 | 142 | ||
143 | /* On AVR chips the Peripheral DMA Controller is not connected to MCI. */ | ||
144 | #ifdef CONFIG_AVR32 | ||
145 | # define ATMCI_PDC_CONNECTED 0 | ||
146 | #else | ||
147 | # define ATMCI_PDC_CONNECTED 1 | ||
148 | #endif | ||
149 | |||
143 | /* | 150 | /* |
144 | * Fix sconfig's burst size according to atmel MCI. We need to convert them as: | 151 | * Fix sconfig's burst size according to atmel MCI. We need to convert them as: |
145 | * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. | 152 | * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 852d5fbda630..ddf096e3803f 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -19,6 +19,9 @@ | |||
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/ioport.h> | 20 | #include <linux/ioport.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
24 | #include <linux/of_gpio.h> | ||
22 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
23 | #include <linux/scatterlist.h> | 26 | #include <linux/scatterlist.h> |
24 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
@@ -71,7 +74,7 @@ enum atmci_pdc_buf { | |||
71 | }; | 74 | }; |
72 | 75 | ||
73 | struct atmel_mci_caps { | 76 | struct atmel_mci_caps { |
74 | bool has_dma; | 77 | bool has_dma_conf_reg; |
75 | bool has_pdc; | 78 | bool has_pdc; |
76 | bool has_cfg_reg; | 79 | bool has_cfg_reg; |
77 | bool has_cstor_reg; | 80 | bool has_cstor_reg; |
@@ -418,7 +421,7 @@ static int atmci_regs_show(struct seq_file *s, void *v) | |||
418 | atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]); | 421 | atmci_show_status_reg(s, "SR", buf[ATMCI_SR / 4]); |
419 | atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]); | 422 | atmci_show_status_reg(s, "IMR", buf[ATMCI_IMR / 4]); |
420 | 423 | ||
421 | if (host->caps.has_dma) { | 424 | if (host->caps.has_dma_conf_reg) { |
422 | u32 val; | 425 | u32 val; |
423 | 426 | ||
424 | val = buf[ATMCI_DMA / 4]; | 427 | val = buf[ATMCI_DMA / 4]; |
@@ -500,6 +503,70 @@ err: | |||
500 | dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); | 503 | dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); |
501 | } | 504 | } |
502 | 505 | ||
506 | #if defined(CONFIG_OF) | ||
507 | static const struct of_device_id atmci_dt_ids[] = { | ||
508 | { .compatible = "atmel,hsmci" }, | ||
509 | { /* sentinel */ } | ||
510 | }; | ||
511 | |||
512 | MODULE_DEVICE_TABLE(of, atmci_dt_ids); | ||
513 | |||
514 | static struct mci_platform_data __devinit* | ||
515 | atmci_of_init(struct platform_device *pdev) | ||
516 | { | ||
517 | struct device_node *np = pdev->dev.of_node; | ||
518 | struct device_node *cnp; | ||
519 | struct mci_platform_data *pdata; | ||
520 | u32 slot_id; | ||
521 | |||
522 | if (!np) { | ||
523 | dev_err(&pdev->dev, "device node not found\n"); | ||
524 | return ERR_PTR(-EINVAL); | ||
525 | } | ||
526 | |||
527 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
528 | if (!pdata) { | ||
529 | dev_err(&pdev->dev, "could not allocate memory for pdata\n"); | ||
530 | return ERR_PTR(-ENOMEM); | ||
531 | } | ||
532 | |||
533 | for_each_child_of_node(np, cnp) { | ||
534 | if (of_property_read_u32(cnp, "reg", &slot_id)) { | ||
535 | dev_warn(&pdev->dev, "reg property is missing for %s\n", | ||
536 | cnp->full_name); | ||
537 | continue; | ||
538 | } | ||
539 | |||
540 | if (slot_id >= ATMCI_MAX_NR_SLOTS) { | ||
541 | dev_warn(&pdev->dev, "can't have more than %d slots\n", | ||
542 | ATMCI_MAX_NR_SLOTS); | ||
543 | break; | ||
544 | } | ||
545 | |||
546 | if (of_property_read_u32(cnp, "bus-width", | ||
547 | &pdata->slot[slot_id].bus_width)) | ||
548 | pdata->slot[slot_id].bus_width = 1; | ||
549 | |||
550 | pdata->slot[slot_id].detect_pin = | ||
551 | of_get_named_gpio(cnp, "cd-gpios", 0); | ||
552 | |||
553 | pdata->slot[slot_id].detect_is_active_high = | ||
554 | of_property_read_bool(cnp, "cd-inverted"); | ||
555 | |||
556 | pdata->slot[slot_id].wp_pin = | ||
557 | of_get_named_gpio(cnp, "wp-gpios", 0); | ||
558 | } | ||
559 | |||
560 | return pdata; | ||
561 | } | ||
562 | #else /* CONFIG_OF */ | ||
563 | static inline struct mci_platform_data* | ||
564 | atmci_of_init(struct platform_device *dev) | ||
565 | { | ||
566 | return ERR_PTR(-EINVAL); | ||
567 | } | ||
568 | #endif | ||
569 | |||
503 | static inline unsigned int atmci_get_version(struct atmel_mci *host) | 570 | static inline unsigned int atmci_get_version(struct atmel_mci *host) |
504 | { | 571 | { |
505 | return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; | 572 | return atmci_readl(host, ATMCI_VERSION) & 0x00000fff; |
@@ -774,7 +841,7 @@ static void atmci_dma_complete(void *arg) | |||
774 | 841 | ||
775 | dev_vdbg(&host->pdev->dev, "DMA complete\n"); | 842 | dev_vdbg(&host->pdev->dev, "DMA complete\n"); |
776 | 843 | ||
777 | if (host->caps.has_dma) | 844 | if (host->caps.has_dma_conf_reg) |
778 | /* Disable DMA hardware handshaking on MCI */ | 845 | /* Disable DMA hardware handshaking on MCI */ |
779 | atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); | 846 | atmci_writel(host, ATMCI_DMA, atmci_readl(host, ATMCI_DMA) & ~ATMCI_DMAEN); |
780 | 847 | ||
@@ -961,7 +1028,9 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data) | |||
961 | maxburst = atmci_convert_chksize(host->dma_conf.dst_maxburst); | 1028 | maxburst = atmci_convert_chksize(host->dma_conf.dst_maxburst); |
962 | } | 1029 | } |
963 | 1030 | ||
964 | atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) | ATMCI_DMAEN); | 1031 | if (host->caps.has_dma_conf_reg) |
1032 | atmci_writel(host, ATMCI_DMA, ATMCI_DMA_CHKSIZE(maxburst) | | ||
1033 | ATMCI_DMAEN); | ||
965 | 1034 | ||
966 | sglen = dma_map_sg(chan->device->dev, data->sg, | 1035 | sglen = dma_map_sg(chan->device->dev, data->sg, |
967 | data->sg_len, direction); | 1036 | data->sg_len, direction); |
@@ -2046,6 +2115,13 @@ static int __init atmci_init_slot(struct atmel_mci *host, | |||
2046 | slot->sdc_reg = sdc_reg; | 2115 | slot->sdc_reg = sdc_reg; |
2047 | slot->sdio_irq = sdio_irq; | 2116 | slot->sdio_irq = sdio_irq; |
2048 | 2117 | ||
2118 | dev_dbg(&mmc->class_dev, | ||
2119 | "slot[%u]: bus_width=%u, detect_pin=%d, " | ||
2120 | "detect_is_active_high=%s, wp_pin=%d\n", | ||
2121 | id, slot_data->bus_width, slot_data->detect_pin, | ||
2122 | slot_data->detect_is_active_high ? "true" : "false", | ||
2123 | slot_data->wp_pin); | ||
2124 | |||
2049 | mmc->ops = &atmci_ops; | 2125 | mmc->ops = &atmci_ops; |
2050 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); | 2126 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); |
2051 | mmc->f_max = host->bus_hz / 2; | 2127 | mmc->f_max = host->bus_hz / 2; |
@@ -2169,7 +2245,10 @@ static bool atmci_configure_dma(struct atmel_mci *host) | |||
2169 | 2245 | ||
2170 | pdata = host->pdev->dev.platform_data; | 2246 | pdata = host->pdev->dev.platform_data; |
2171 | 2247 | ||
2172 | if (pdata && find_slave_dev(pdata->dma_slave)) { | 2248 | if (!pdata) |
2249 | return false; | ||
2250 | |||
2251 | if (pdata->dma_slave && find_slave_dev(pdata->dma_slave)) { | ||
2173 | dma_cap_mask_t mask; | 2252 | dma_cap_mask_t mask; |
2174 | 2253 | ||
2175 | /* Try to grab a DMA channel */ | 2254 | /* Try to grab a DMA channel */ |
@@ -2210,8 +2289,8 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
2210 | dev_info(&host->pdev->dev, | 2289 | dev_info(&host->pdev->dev, |
2211 | "version: 0x%x\n", version); | 2290 | "version: 0x%x\n", version); |
2212 | 2291 | ||
2213 | host->caps.has_dma = 0; | 2292 | host->caps.has_dma_conf_reg = 0; |
2214 | host->caps.has_pdc = 1; | 2293 | host->caps.has_pdc = ATMCI_PDC_CONNECTED; |
2215 | host->caps.has_cfg_reg = 0; | 2294 | host->caps.has_cfg_reg = 0; |
2216 | host->caps.has_cstor_reg = 0; | 2295 | host->caps.has_cstor_reg = 0; |
2217 | host->caps.has_highspeed = 0; | 2296 | host->caps.has_highspeed = 0; |
@@ -2228,12 +2307,7 @@ static void __init atmci_get_cap(struct atmel_mci *host) | |||
2228 | host->caps.has_odd_clk_div = 1; | 2307 | host->caps.has_odd_clk_div = 1; |
2229 | case 0x400: | 2308 | case 0x400: |
2230 | case 0x300: | 2309 | case 0x300: |
2231 | #ifdef CONFIG_AT_HDMAC | 2310 | host->caps.has_dma_conf_reg = 1; |
2232 | host->caps.has_dma = 1; | ||
2233 | #else | ||
2234 | dev_info(&host->pdev->dev, | ||
2235 | "has dma capability but dma engine is not selected, then use pio\n"); | ||
2236 | #endif | ||
2237 | host->caps.has_pdc = 0; | 2311 | host->caps.has_pdc = 0; |
2238 | host->caps.has_cfg_reg = 1; | 2312 | host->caps.has_cfg_reg = 1; |
2239 | host->caps.has_cstor_reg = 1; | 2313 | host->caps.has_cstor_reg = 1; |
@@ -2268,8 +2342,14 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
2268 | if (!regs) | 2342 | if (!regs) |
2269 | return -ENXIO; | 2343 | return -ENXIO; |
2270 | pdata = pdev->dev.platform_data; | 2344 | pdata = pdev->dev.platform_data; |
2271 | if (!pdata) | 2345 | if (!pdata) { |
2272 | return -ENXIO; | 2346 | pdata = atmci_of_init(pdev); |
2347 | if (IS_ERR(pdata)) { | ||
2348 | dev_err(&pdev->dev, "platform data not available\n"); | ||
2349 | return PTR_ERR(pdata); | ||
2350 | } | ||
2351 | } | ||
2352 | |||
2273 | irq = platform_get_irq(pdev, 0); | 2353 | irq = platform_get_irq(pdev, 0); |
2274 | if (irq < 0) | 2354 | if (irq < 0) |
2275 | return irq; | 2355 | return irq; |
@@ -2308,7 +2388,7 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
2308 | 2388 | ||
2309 | /* Get MCI capabilities and set operations according to it */ | 2389 | /* Get MCI capabilities and set operations according to it */ |
2310 | atmci_get_cap(host); | 2390 | atmci_get_cap(host); |
2311 | if (host->caps.has_dma && atmci_configure_dma(host)) { | 2391 | if (atmci_configure_dma(host)) { |
2312 | host->prepare_data = &atmci_prepare_data_dma; | 2392 | host->prepare_data = &atmci_prepare_data_dma; |
2313 | host->submit_data = &atmci_submit_data_dma; | 2393 | host->submit_data = &atmci_submit_data_dma; |
2314 | host->stop_transfer = &atmci_stop_transfer_dma; | 2394 | host->stop_transfer = &atmci_stop_transfer_dma; |
@@ -2487,6 +2567,7 @@ static struct platform_driver atmci_driver = { | |||
2487 | .driver = { | 2567 | .driver = { |
2488 | .name = "atmel_mci", | 2568 | .name = "atmel_mci", |
2489 | .pm = ATMCI_PM_OPS, | 2569 | .pm = ATMCI_PM_OPS, |
2570 | .of_match_table = of_match_ptr(atmci_dt_ids), | ||
2490 | }, | 2571 | }, |
2491 | }; | 2572 | }; |
2492 | 2573 | ||
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index a17dd7363ceb..b9b463eca1ec 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
@@ -24,9 +24,7 @@ | |||
24 | #include <asm/portmux.h> | 24 | #include <asm/portmux.h> |
25 | #include <asm/bfin_sdh.h> | 25 | #include <asm/bfin_sdh.h> |
26 | 26 | ||
27 | #if defined(CONFIG_BF51x) | 27 | #if defined(CONFIG_BF51x) || defined(__ADSPBF60x__) |
28 | #define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CTL | ||
29 | #define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CTL | ||
30 | #define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CTL | 28 | #define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CTL |
31 | #define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CTL | 29 | #define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CTL |
32 | #define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT | 30 | #define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT |
@@ -45,8 +43,16 @@ | |||
45 | #define bfin_write_SDH_E_STATUS bfin_write_RSI_E_STATUS | 43 | #define bfin_write_SDH_E_STATUS bfin_write_RSI_E_STATUS |
46 | #define bfin_read_SDH_STATUS bfin_read_RSI_STATUS | 44 | #define bfin_read_SDH_STATUS bfin_read_RSI_STATUS |
47 | #define bfin_write_SDH_MASK0 bfin_write_RSI_MASK0 | 45 | #define bfin_write_SDH_MASK0 bfin_write_RSI_MASK0 |
46 | #define bfin_write_SDH_E_MASK bfin_write_RSI_E_MASK | ||
48 | #define bfin_read_SDH_CFG bfin_read_RSI_CFG | 47 | #define bfin_read_SDH_CFG bfin_read_RSI_CFG |
49 | #define bfin_write_SDH_CFG bfin_write_RSI_CFG | 48 | #define bfin_write_SDH_CFG bfin_write_RSI_CFG |
49 | # if defined(__ADSPBF60x__) | ||
50 | # define bfin_read_SDH_BLK_SIZE bfin_read_RSI_BLKSZ | ||
51 | # define bfin_write_SDH_BLK_SIZE bfin_write_RSI_BLKSZ | ||
52 | # else | ||
53 | # define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CTL | ||
54 | # define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CTL | ||
55 | # endif | ||
50 | #endif | 56 | #endif |
51 | 57 | ||
52 | struct sdh_host { | 58 | struct sdh_host { |
@@ -62,6 +68,7 @@ struct sdh_host { | |||
62 | dma_addr_t sg_dma; | 68 | dma_addr_t sg_dma; |
63 | int dma_len; | 69 | int dma_len; |
64 | 70 | ||
71 | unsigned long sclk; | ||
65 | unsigned int imask; | 72 | unsigned int imask; |
66 | unsigned int power_mode; | 73 | unsigned int power_mode; |
67 | unsigned int clk_div; | 74 | unsigned int clk_div; |
@@ -127,11 +134,15 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
127 | /* Only supports power-of-2 block size */ | 134 | /* Only supports power-of-2 block size */ |
128 | if (data->blksz & (data->blksz - 1)) | 135 | if (data->blksz & (data->blksz - 1)) |
129 | return -EINVAL; | 136 | return -EINVAL; |
137 | #ifndef RSI_BLKSZ | ||
130 | data_ctl |= ((ffs(data->blksz) - 1) << 4); | 138 | data_ctl |= ((ffs(data->blksz) - 1) << 4); |
139 | #else | ||
140 | bfin_write_SDH_BLK_SIZE(data->blksz); | ||
141 | #endif | ||
131 | 142 | ||
132 | bfin_write_SDH_DATA_CTL(data_ctl); | 143 | bfin_write_SDH_DATA_CTL(data_ctl); |
133 | /* the time of a host clock period in ns */ | 144 | /* the time of a host clock period in ns */ |
134 | cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1))); | 145 | cycle_ns = 1000000000 / (host->sclk / (2 * (host->clk_div + 1))); |
135 | timeout = data->timeout_ns / cycle_ns; | 146 | timeout = data->timeout_ns / cycle_ns; |
136 | timeout += data->timeout_clks; | 147 | timeout += data->timeout_clks; |
137 | bfin_write_SDH_DATA_TIMER(timeout); | 148 | bfin_write_SDH_DATA_TIMER(timeout); |
@@ -145,8 +156,13 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
145 | 156 | ||
146 | sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END)); | 157 | sdh_enable_stat_irq(host, (DAT_CRC_FAIL | DAT_TIME_OUT | DAT_END)); |
147 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); | 158 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, host->dma_dir); |
148 | #if defined(CONFIG_BF54x) | 159 | #if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) |
149 | dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN; | 160 | dma_cfg |= DMAFLOW_ARRAY | RESTART | WDSIZE_32 | DMAEN; |
161 | # ifdef RSI_BLKSZ | ||
162 | dma_cfg |= PSIZE_32 | NDSIZE_3; | ||
163 | # else | ||
164 | dma_cfg |= NDSIZE_5; | ||
165 | # endif | ||
150 | { | 166 | { |
151 | struct scatterlist *sg; | 167 | struct scatterlist *sg; |
152 | int i; | 168 | int i; |
@@ -156,7 +172,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
156 | host->sg_cpu[i].x_count = sg_dma_len(sg) / 4; | 172 | host->sg_cpu[i].x_count = sg_dma_len(sg) / 4; |
157 | host->sg_cpu[i].x_modify = 4; | 173 | host->sg_cpu[i].x_modify = 4; |
158 | dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, " | 174 | dev_dbg(mmc_dev(host->mmc), "%d: start_addr:0x%lx, " |
159 | "cfg:0x%x, x_count:0x%x, x_modify:0x%x\n", | 175 | "cfg:0x%lx, x_count:0x%lx, x_modify:0x%lx\n", |
160 | i, host->sg_cpu[i].start_addr, | 176 | i, host->sg_cpu[i].start_addr, |
161 | host->sg_cpu[i].cfg, host->sg_cpu[i].x_count, | 177 | host->sg_cpu[i].cfg, host->sg_cpu[i].x_count, |
162 | host->sg_cpu[i].x_modify); | 178 | host->sg_cpu[i].x_modify); |
@@ -172,6 +188,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
172 | set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma); | 188 | set_dma_curr_desc_addr(host->dma_ch, (unsigned long *)host->sg_dma); |
173 | set_dma_x_count(host->dma_ch, 0); | 189 | set_dma_x_count(host->dma_ch, 0); |
174 | set_dma_x_modify(host->dma_ch, 0); | 190 | set_dma_x_modify(host->dma_ch, 0); |
191 | SSYNC(); | ||
175 | set_dma_config(host->dma_ch, dma_cfg); | 192 | set_dma_config(host->dma_ch, dma_cfg); |
176 | #elif defined(CONFIG_BF51x) | 193 | #elif defined(CONFIG_BF51x) |
177 | /* RSI DMA doesn't work in array mode */ | 194 | /* RSI DMA doesn't work in array mode */ |
@@ -179,6 +196,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data) | |||
179 | set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0])); | 196 | set_dma_start_addr(host->dma_ch, sg_dma_address(&data->sg[0])); |
180 | set_dma_x_count(host->dma_ch, length / 4); | 197 | set_dma_x_count(host->dma_ch, length / 4); |
181 | set_dma_x_modify(host->dma_ch, 4); | 198 | set_dma_x_modify(host->dma_ch, 4); |
199 | SSYNC(); | ||
182 | set_dma_config(host->dma_ch, dma_cfg); | 200 | set_dma_config(host->dma_ch, dma_cfg); |
183 | #endif | 201 | #endif |
184 | bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); | 202 | bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); |
@@ -296,7 +314,6 @@ static int sdh_data_done(struct sdh_host *host, unsigned int stat) | |||
296 | else | 314 | else |
297 | data->bytes_xfered = 0; | 315 | data->bytes_xfered = 0; |
298 | 316 | ||
299 | sdh_disable_stat_irq(host, DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN); | ||
300 | bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \ | 317 | bfin_write_SDH_STATUS_CLR(DAT_END_STAT | DAT_TIMEOUT_STAT | \ |
301 | DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN); | 318 | DAT_CRC_FAIL_STAT | DAT_BLK_END_STAT | RX_OVERRUN | TX_UNDERRUN); |
302 | bfin_write_SDH_DATA_CTL(0); | 319 | bfin_write_SDH_DATA_CTL(0); |
@@ -321,74 +338,115 @@ static void sdh_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
321 | dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd); | 338 | dev_dbg(mmc_dev(host->mmc), "%s enter, mrp:%p, cmd:%p\n", __func__, mrq, mrq->cmd); |
322 | WARN_ON(host->mrq != NULL); | 339 | WARN_ON(host->mrq != NULL); |
323 | 340 | ||
341 | spin_lock(&host->lock); | ||
324 | host->mrq = mrq; | 342 | host->mrq = mrq; |
325 | host->data = mrq->data; | 343 | host->data = mrq->data; |
326 | 344 | ||
327 | if (mrq->data && mrq->data->flags & MMC_DATA_READ) { | 345 | if (mrq->data && mrq->data->flags & MMC_DATA_READ) { |
328 | ret = sdh_setup_data(host, mrq->data); | 346 | ret = sdh_setup_data(host, mrq->data); |
329 | if (ret) | 347 | if (ret) |
330 | return; | 348 | goto data_err; |
331 | } | 349 | } |
332 | 350 | ||
333 | sdh_start_cmd(host, mrq->cmd); | 351 | sdh_start_cmd(host, mrq->cmd); |
352 | data_err: | ||
353 | spin_unlock(&host->lock); | ||
334 | } | 354 | } |
335 | 355 | ||
336 | static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 356 | static void sdh_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
337 | { | 357 | { |
338 | struct sdh_host *host; | 358 | struct sdh_host *host; |
339 | unsigned long flags; | ||
340 | u16 clk_ctl = 0; | 359 | u16 clk_ctl = 0; |
360 | #ifndef RSI_BLKSZ | ||
341 | u16 pwr_ctl = 0; | 361 | u16 pwr_ctl = 0; |
362 | #endif | ||
342 | u16 cfg; | 363 | u16 cfg; |
343 | host = mmc_priv(mmc); | 364 | host = mmc_priv(mmc); |
344 | 365 | ||
345 | spin_lock_irqsave(&host->lock, flags); | 366 | spin_lock(&host->lock); |
346 | if (ios->clock) { | ||
347 | unsigned long sys_clk, ios_clk; | ||
348 | unsigned char clk_div; | ||
349 | ios_clk = 2 * ios->clock; | ||
350 | sys_clk = get_sclk(); | ||
351 | clk_div = sys_clk / ios_clk; | ||
352 | if (sys_clk % ios_clk == 0) | ||
353 | clk_div -= 1; | ||
354 | clk_div = min_t(unsigned char, clk_div, 0xFF); | ||
355 | clk_ctl |= clk_div; | ||
356 | clk_ctl |= CLK_E; | ||
357 | host->clk_div = clk_div; | ||
358 | } else | ||
359 | sdh_stop_clock(host); | ||
360 | |||
361 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | ||
362 | #ifdef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | ||
363 | pwr_ctl |= ROD_CTL; | ||
364 | #else | ||
365 | pwr_ctl |= SD_CMD_OD | ROD_CTL; | ||
366 | #endif | ||
367 | 367 | ||
368 | if (ios->bus_width == MMC_BUS_WIDTH_4) { | 368 | cfg = bfin_read_SDH_CFG(); |
369 | cfg = bfin_read_SDH_CFG(); | 369 | cfg |= MWE; |
370 | switch (ios->bus_width) { | ||
371 | case MMC_BUS_WIDTH_4: | ||
372 | #ifndef RSI_BLKSZ | ||
370 | cfg &= ~PD_SDDAT3; | 373 | cfg &= ~PD_SDDAT3; |
374 | #endif | ||
371 | cfg |= PUP_SDDAT3; | 375 | cfg |= PUP_SDDAT3; |
372 | /* Enable 4 bit SDIO */ | 376 | /* Enable 4 bit SDIO */ |
373 | cfg |= (SD4E | MWE); | 377 | cfg |= SD4E; |
374 | bfin_write_SDH_CFG(cfg); | 378 | clk_ctl |= WIDE_BUS_4; |
375 | clk_ctl |= WIDE_BUS; | 379 | break; |
376 | } else { | 380 | case MMC_BUS_WIDTH_8: |
377 | cfg = bfin_read_SDH_CFG(); | 381 | #ifndef RSI_BLKSZ |
378 | cfg |= MWE; | 382 | cfg &= ~PD_SDDAT3; |
379 | bfin_write_SDH_CFG(cfg); | 383 | #endif |
384 | cfg |= PUP_SDDAT3; | ||
385 | /* Disable 4 bit SDIO */ | ||
386 | cfg &= ~SD4E; | ||
387 | clk_ctl |= BYTE_BUS_8; | ||
388 | break; | ||
389 | default: | ||
390 | cfg &= ~PUP_SDDAT3; | ||
391 | /* Disable 4 bit SDIO */ | ||
392 | cfg &= ~SD4E; | ||
380 | } | 393 | } |
381 | 394 | ||
382 | bfin_write_SDH_CLK_CTL(clk_ctl); | ||
383 | |||
384 | host->power_mode = ios->power_mode; | 395 | host->power_mode = ios->power_mode; |
385 | if (ios->power_mode == MMC_POWER_ON) | 396 | #ifndef RSI_BLKSZ |
397 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { | ||
398 | pwr_ctl |= ROD_CTL; | ||
399 | # ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | ||
400 | pwr_ctl |= SD_CMD_OD; | ||
401 | # endif | ||
402 | } | ||
403 | |||
404 | if (ios->power_mode != MMC_POWER_OFF) | ||
386 | pwr_ctl |= PWR_ON; | 405 | pwr_ctl |= PWR_ON; |
406 | else | ||
407 | pwr_ctl &= ~PWR_ON; | ||
387 | 408 | ||
388 | bfin_write_SDH_PWR_CTL(pwr_ctl); | 409 | bfin_write_SDH_PWR_CTL(pwr_ctl); |
410 | #else | ||
411 | # ifndef CONFIG_SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | ||
412 | if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) | ||
413 | cfg |= SD_CMD_OD; | ||
414 | else | ||
415 | cfg &= ~SD_CMD_OD; | ||
416 | # endif | ||
417 | |||
418 | |||
419 | if (ios->power_mode != MMC_POWER_OFF) | ||
420 | cfg |= PWR_ON; | ||
421 | else | ||
422 | cfg &= ~PWR_ON; | ||
423 | |||
424 | bfin_write_SDH_CFG(cfg); | ||
425 | #endif | ||
389 | SSYNC(); | 426 | SSYNC(); |
390 | 427 | ||
391 | spin_unlock_irqrestore(&host->lock, flags); | 428 | if (ios->power_mode == MMC_POWER_ON && ios->clock) { |
429 | unsigned char clk_div; | ||
430 | clk_div = (get_sclk() / ios->clock - 1) / 2; | ||
431 | clk_div = min_t(unsigned char, clk_div, 0xFF); | ||
432 | clk_ctl |= clk_div; | ||
433 | clk_ctl |= CLK_E; | ||
434 | host->clk_div = clk_div; | ||
435 | bfin_write_SDH_CLK_CTL(clk_ctl); | ||
436 | |||
437 | } else | ||
438 | sdh_stop_clock(host); | ||
439 | |||
440 | /* set up sdh interrupt mask*/ | ||
441 | if (ios->power_mode == MMC_POWER_ON) | ||
442 | bfin_write_SDH_MASK0(DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | | ||
443 | RX_OVERRUN | TX_UNDERRUN | CMD_SENT | CMD_RESP_END | | ||
444 | CMD_TIME_OUT | CMD_CRC_FAIL); | ||
445 | else | ||
446 | bfin_write_SDH_MASK0(0); | ||
447 | SSYNC(); | ||
448 | |||
449 | spin_unlock(&host->lock); | ||
392 | 450 | ||
393 | dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n", | 451 | dev_dbg(mmc_dev(host->mmc), "SDH: clk_div = 0x%x actual clock:%ld expected clock:%d\n", |
394 | host->clk_div, | 452 | host->clk_div, |
@@ -405,7 +463,7 @@ static irqreturn_t sdh_dma_irq(int irq, void *devid) | |||
405 | { | 463 | { |
406 | struct sdh_host *host = devid; | 464 | struct sdh_host *host = devid; |
407 | 465 | ||
408 | dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04x\n", __func__, | 466 | dev_dbg(mmc_dev(host->mmc), "%s enter, irq_stat: 0x%04lx\n", __func__, |
409 | get_dma_curr_irqstat(host->dma_ch)); | 467 | get_dma_curr_irqstat(host->dma_ch)); |
410 | clear_dma_irqstat(host->dma_ch); | 468 | clear_dma_irqstat(host->dma_ch); |
411 | SSYNC(); | 469 | SSYNC(); |
@@ -420,6 +478,9 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid) | |||
420 | int handled = 0; | 478 | int handled = 0; |
421 | 479 | ||
422 | dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); | 480 | dev_dbg(mmc_dev(host->mmc), "%s enter\n", __func__); |
481 | |||
482 | spin_lock(&host->lock); | ||
483 | |||
423 | status = bfin_read_SDH_E_STATUS(); | 484 | status = bfin_read_SDH_E_STATUS(); |
424 | if (status & SD_CARD_DET) { | 485 | if (status & SD_CARD_DET) { |
425 | mmc_detect_change(host->mmc, 0); | 486 | mmc_detect_change(host->mmc, 0); |
@@ -437,11 +498,30 @@ static irqreturn_t sdh_stat_irq(int irq, void *devid) | |||
437 | if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN)) | 498 | if (status & (DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN | TX_UNDERRUN)) |
438 | handled |= sdh_data_done(host, status); | 499 | handled |= sdh_data_done(host, status); |
439 | 500 | ||
501 | spin_unlock(&host->lock); | ||
502 | |||
440 | dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__); | 503 | dev_dbg(mmc_dev(host->mmc), "%s exit\n\n", __func__); |
441 | 504 | ||
442 | return IRQ_RETVAL(handled); | 505 | return IRQ_RETVAL(handled); |
443 | } | 506 | } |
444 | 507 | ||
508 | static void sdh_reset(void) | ||
509 | { | ||
510 | #if defined(CONFIG_BF54x) | ||
511 | /* Secure Digital Host shares DMA with Nand controller */ | ||
512 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); | ||
513 | #endif | ||
514 | |||
515 | bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); | ||
516 | SSYNC(); | ||
517 | |||
518 | /* Disable card inserting detection pin. set MMC_CAP_NEEDS_POLL, and | ||
519 | * mmc stack will do the detection. | ||
520 | */ | ||
521 | bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); | ||
522 | SSYNC(); | ||
523 | } | ||
524 | |||
445 | static int __devinit sdh_probe(struct platform_device *pdev) | 525 | static int __devinit sdh_probe(struct platform_device *pdev) |
446 | { | 526 | { |
447 | struct mmc_host *mmc; | 527 | struct mmc_host *mmc; |
@@ -462,8 +542,16 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
462 | } | 542 | } |
463 | 543 | ||
464 | mmc->ops = &sdh_ops; | 544 | mmc->ops = &sdh_ops; |
465 | mmc->max_segs = 32; | 545 | #if defined(CONFIG_BF51x) |
546 | mmc->max_segs = 1; | ||
547 | #else | ||
548 | mmc->max_segs = PAGE_SIZE / sizeof(struct dma_desc_array); | ||
549 | #endif | ||
550 | #ifdef RSI_BLKSZ | ||
551 | mmc->max_seg_size = -1; | ||
552 | #else | ||
466 | mmc->max_seg_size = 1 << 16; | 553 | mmc->max_seg_size = 1 << 16; |
554 | #endif | ||
467 | mmc->max_blk_size = 1 << 11; | 555 | mmc->max_blk_size = 1 << 11; |
468 | mmc->max_blk_count = 1 << 11; | 556 | mmc->max_blk_count = 1 << 11; |
469 | mmc->max_req_size = PAGE_SIZE; | 557 | mmc->max_req_size = PAGE_SIZE; |
@@ -473,6 +561,7 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
473 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL; | 561 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_NEEDS_POLL; |
474 | host = mmc_priv(mmc); | 562 | host = mmc_priv(mmc); |
475 | host->mmc = mmc; | 563 | host->mmc = mmc; |
564 | host->sclk = get_sclk(); | ||
476 | 565 | ||
477 | spin_lock_init(&host->lock); | 566 | spin_lock_init(&host->lock); |
478 | host->irq = drv_data->irq_int0; | 567 | host->irq = drv_data->irq_int0; |
@@ -497,7 +586,6 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
497 | } | 586 | } |
498 | 587 | ||
499 | platform_set_drvdata(pdev, mmc); | 588 | platform_set_drvdata(pdev, mmc); |
500 | mmc_add_host(mmc); | ||
501 | 589 | ||
502 | ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host); | 590 | ret = request_irq(host->irq, sdh_stat_irq, 0, "SDH Status IRQ", host); |
503 | if (ret) { | 591 | if (ret) { |
@@ -510,20 +598,10 @@ static int __devinit sdh_probe(struct platform_device *pdev) | |||
510 | dev_err(&pdev->dev, "unable to request peripheral pins\n"); | 598 | dev_err(&pdev->dev, "unable to request peripheral pins\n"); |
511 | goto out4; | 599 | goto out4; |
512 | } | 600 | } |
513 | #if defined(CONFIG_BF54x) | ||
514 | /* Secure Digital Host shares DMA with Nand controller */ | ||
515 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); | ||
516 | #endif | ||
517 | |||
518 | bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); | ||
519 | SSYNC(); | ||
520 | 601 | ||
521 | /* Disable card inserting detection pin. set MMC_CAP_NEES_POLL, and | 602 | sdh_reset(); |
522 | * mmc stack will do the detection. | ||
523 | */ | ||
524 | bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); | ||
525 | SSYNC(); | ||
526 | 603 | ||
604 | mmc_add_host(mmc); | ||
527 | return 0; | 605 | return 0; |
528 | 606 | ||
529 | out4: | 607 | out4: |
@@ -571,7 +649,6 @@ static int sdh_suspend(struct platform_device *dev, pm_message_t state) | |||
571 | if (mmc) | 649 | if (mmc) |
572 | ret = mmc_suspend_host(mmc); | 650 | ret = mmc_suspend_host(mmc); |
573 | 651 | ||
574 | bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON); | ||
575 | peripheral_free_list(drv_data->pin_req); | 652 | peripheral_free_list(drv_data->pin_req); |
576 | 653 | ||
577 | return ret; | 654 | return ret; |
@@ -589,16 +666,7 @@ static int sdh_resume(struct platform_device *dev) | |||
589 | return ret; | 666 | return ret; |
590 | } | 667 | } |
591 | 668 | ||
592 | bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() | PWR_ON); | 669 | sdh_reset(); |
593 | #if defined(CONFIG_BF54x) | ||
594 | /* Secure Digital Host shares DMA with Nand controller */ | ||
595 | bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); | ||
596 | #endif | ||
597 | bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); | ||
598 | SSYNC(); | ||
599 | |||
600 | bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | (PUP_SDDAT | PUP_SDDAT3)); | ||
601 | SSYNC(); | ||
602 | 670 | ||
603 | if (mmc) | 671 | if (mmc) |
604 | ret = mmc_resume_host(mmc); | 672 | ret = mmc_resume_host(mmc); |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 3dfd3473269d..20636772c09b 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
@@ -30,11 +30,12 @@ | |||
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | #include <linux/irq.h> | 31 | #include <linux/irq.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/dmaengine.h> | ||
33 | #include <linux/dma-mapping.h> | 34 | #include <linux/dma-mapping.h> |
35 | #include <linux/edma.h> | ||
34 | #include <linux/mmc/mmc.h> | 36 | #include <linux/mmc/mmc.h> |
35 | 37 | ||
36 | #include <linux/platform_data/mmc-davinci.h> | 38 | #include <linux/platform_data/mmc-davinci.h> |
37 | #include <mach/edma.h> | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * Register Definitions | 41 | * Register Definitions |
@@ -200,21 +201,13 @@ struct mmc_davinci_host { | |||
200 | u32 bytes_left; | 201 | u32 bytes_left; |
201 | 202 | ||
202 | u32 rxdma, txdma; | 203 | u32 rxdma, txdma; |
204 | struct dma_chan *dma_tx; | ||
205 | struct dma_chan *dma_rx; | ||
203 | bool use_dma; | 206 | bool use_dma; |
204 | bool do_dma; | 207 | bool do_dma; |
205 | bool sdio_int; | 208 | bool sdio_int; |
206 | bool active_request; | 209 | bool active_request; |
207 | 210 | ||
208 | /* Scatterlist DMA uses one or more parameter RAM entries: | ||
209 | * the main one (associated with rxdma or txdma) plus zero or | ||
210 | * more links. The entries for a given transfer differ only | ||
211 | * by memory buffer (address, length) and link field. | ||
212 | */ | ||
213 | struct edmacc_param tx_template; | ||
214 | struct edmacc_param rx_template; | ||
215 | unsigned n_link; | ||
216 | u32 links[MAX_NR_SG - 1]; | ||
217 | |||
218 | /* For PIO we walk scatterlists one segment at a time. */ | 211 | /* For PIO we walk scatterlists one segment at a time. */ |
219 | unsigned int sg_len; | 212 | unsigned int sg_len; |
220 | struct scatterlist *sg; | 213 | struct scatterlist *sg; |
@@ -410,153 +403,74 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, | |||
410 | 403 | ||
411 | static void davinci_abort_dma(struct mmc_davinci_host *host) | 404 | static void davinci_abort_dma(struct mmc_davinci_host *host) |
412 | { | 405 | { |
413 | int sync_dev; | 406 | struct dma_chan *sync_dev; |
414 | 407 | ||
415 | if (host->data_dir == DAVINCI_MMC_DATADIR_READ) | 408 | if (host->data_dir == DAVINCI_MMC_DATADIR_READ) |
416 | sync_dev = host->rxdma; | 409 | sync_dev = host->dma_rx; |
417 | else | 410 | else |
418 | sync_dev = host->txdma; | 411 | sync_dev = host->dma_tx; |
419 | |||
420 | edma_stop(sync_dev); | ||
421 | edma_clean_channel(sync_dev); | ||
422 | } | ||
423 | |||
424 | static void | ||
425 | mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data); | ||
426 | |||
427 | static void mmc_davinci_dma_cb(unsigned channel, u16 ch_status, void *data) | ||
428 | { | ||
429 | if (DMA_COMPLETE != ch_status) { | ||
430 | struct mmc_davinci_host *host = data; | ||
431 | |||
432 | /* Currently means: DMA Event Missed, or "null" transfer | ||
433 | * request was seen. In the future, TC errors (like bad | ||
434 | * addresses) might be presented too. | ||
435 | */ | ||
436 | dev_warn(mmc_dev(host->mmc), "DMA %s error\n", | ||
437 | (host->data->flags & MMC_DATA_WRITE) | ||
438 | ? "write" : "read"); | ||
439 | host->data->error = -EIO; | ||
440 | mmc_davinci_xfer_done(host, host->data); | ||
441 | } | ||
442 | } | ||
443 | |||
444 | /* Set up tx or rx template, to be modified and updated later */ | ||
445 | static void __init mmc_davinci_dma_setup(struct mmc_davinci_host *host, | ||
446 | bool tx, struct edmacc_param *template) | ||
447 | { | ||
448 | unsigned sync_dev; | ||
449 | const u16 acnt = 4; | ||
450 | const u16 bcnt = rw_threshold >> 2; | ||
451 | const u16 ccnt = 0; | ||
452 | u32 src_port = 0; | ||
453 | u32 dst_port = 0; | ||
454 | s16 src_bidx, dst_bidx; | ||
455 | s16 src_cidx, dst_cidx; | ||
456 | |||
457 | /* | ||
458 | * A-B Sync transfer: each DMA request is for one "frame" of | ||
459 | * rw_threshold bytes, broken into "acnt"-size chunks repeated | ||
460 | * "bcnt" times. Each segment needs "ccnt" such frames; since | ||
461 | * we tell the block layer our mmc->max_seg_size limit, we can | ||
462 | * trust (later) that it's within bounds. | ||
463 | * | ||
464 | * The FIFOs are read/written in 4-byte chunks (acnt == 4) and | ||
465 | * EDMA will optimize memory operations to use larger bursts. | ||
466 | */ | ||
467 | if (tx) { | ||
468 | sync_dev = host->txdma; | ||
469 | |||
470 | /* src_prt, ccnt, and link to be set up later */ | ||
471 | src_bidx = acnt; | ||
472 | src_cidx = acnt * bcnt; | ||
473 | |||
474 | dst_port = host->mem_res->start + DAVINCI_MMCDXR; | ||
475 | dst_bidx = 0; | ||
476 | dst_cidx = 0; | ||
477 | } else { | ||
478 | sync_dev = host->rxdma; | ||
479 | |||
480 | src_port = host->mem_res->start + DAVINCI_MMCDRR; | ||
481 | src_bidx = 0; | ||
482 | src_cidx = 0; | ||
483 | |||
484 | /* dst_prt, ccnt, and link to be set up later */ | ||
485 | dst_bidx = acnt; | ||
486 | dst_cidx = acnt * bcnt; | ||
487 | } | ||
488 | |||
489 | /* | ||
490 | * We can't use FIFO mode for the FIFOs because MMC FIFO addresses | ||
491 | * are not 256-bit (32-byte) aligned. So we use INCR, and the W8BIT | ||
492 | * parameter is ignored. | ||
493 | */ | ||
494 | edma_set_src(sync_dev, src_port, INCR, W8BIT); | ||
495 | edma_set_dest(sync_dev, dst_port, INCR, W8BIT); | ||
496 | 412 | ||
497 | edma_set_src_index(sync_dev, src_bidx, src_cidx); | 413 | dmaengine_terminate_all(sync_dev); |
498 | edma_set_dest_index(sync_dev, dst_bidx, dst_cidx); | ||
499 | |||
500 | edma_set_transfer_params(sync_dev, acnt, bcnt, ccnt, 8, ABSYNC); | ||
501 | |||
502 | edma_read_slot(sync_dev, template); | ||
503 | |||
504 | /* don't bother with irqs or chaining */ | ||
505 | template->opt |= EDMA_CHAN_SLOT(sync_dev) << 12; | ||
506 | } | 414 | } |
507 | 415 | ||
508 | static void mmc_davinci_send_dma_request(struct mmc_davinci_host *host, | 416 | static int mmc_davinci_send_dma_request(struct mmc_davinci_host *host, |
509 | struct mmc_data *data) | 417 | struct mmc_data *data) |
510 | { | 418 | { |
511 | struct edmacc_param *template; | 419 | struct dma_chan *chan; |
512 | int channel, slot; | 420 | struct dma_async_tx_descriptor *desc; |
513 | unsigned link; | 421 | int ret = 0; |
514 | struct scatterlist *sg; | ||
515 | unsigned sg_len; | ||
516 | unsigned bytes_left = host->bytes_left; | ||
517 | const unsigned shift = ffs(rw_threshold) - 1; | ||
518 | 422 | ||
519 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { | 423 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { |
520 | template = &host->tx_template; | 424 | struct dma_slave_config dma_tx_conf = { |
521 | channel = host->txdma; | 425 | .direction = DMA_MEM_TO_DEV, |
426 | .dst_addr = host->mem_res->start + DAVINCI_MMCDXR, | ||
427 | .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, | ||
428 | .dst_maxburst = | ||
429 | rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES, | ||
430 | }; | ||
431 | chan = host->dma_tx; | ||
432 | dmaengine_slave_config(host->dma_tx, &dma_tx_conf); | ||
433 | |||
434 | desc = dmaengine_prep_slave_sg(host->dma_tx, | ||
435 | data->sg, | ||
436 | host->sg_len, | ||
437 | DMA_MEM_TO_DEV, | ||
438 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
439 | if (!desc) { | ||
440 | dev_dbg(mmc_dev(host->mmc), | ||
441 | "failed to allocate DMA TX descriptor"); | ||
442 | ret = -1; | ||
443 | goto out; | ||
444 | } | ||
522 | } else { | 445 | } else { |
523 | template = &host->rx_template; | 446 | struct dma_slave_config dma_rx_conf = { |
524 | channel = host->rxdma; | 447 | .direction = DMA_DEV_TO_MEM, |
525 | } | 448 | .src_addr = host->mem_res->start + DAVINCI_MMCDRR, |
526 | 449 | .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, | |
527 | /* We know sg_len and ccnt will never be out of range because | 450 | .src_maxburst = |
528 | * we told the mmc layer which in turn tells the block layer | 451 | rw_threshold / DMA_SLAVE_BUSWIDTH_4_BYTES, |
529 | * to ensure that it only hands us one scatterlist segment | 452 | }; |
530 | * per EDMA PARAM entry. Update the PARAM | 453 | chan = host->dma_rx; |
531 | * entries needed for each segment of this scatterlist. | 454 | dmaengine_slave_config(host->dma_rx, &dma_rx_conf); |
532 | */ | 455 | |
533 | for (slot = channel, link = 0, sg = data->sg, sg_len = host->sg_len; | 456 | desc = dmaengine_prep_slave_sg(host->dma_rx, |
534 | sg_len-- != 0 && bytes_left; | 457 | data->sg, |
535 | sg = sg_next(sg), slot = host->links[link++]) { | 458 | host->sg_len, |
536 | u32 buf = sg_dma_address(sg); | 459 | DMA_DEV_TO_MEM, |
537 | unsigned count = sg_dma_len(sg); | 460 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
538 | 461 | if (!desc) { | |
539 | template->link_bcntrld = sg_len | 462 | dev_dbg(mmc_dev(host->mmc), |
540 | ? (EDMA_CHAN_SLOT(host->links[link]) << 5) | 463 | "failed to allocate DMA RX descriptor"); |
541 | : 0xffff; | 464 | ret = -1; |
542 | 465 | goto out; | |
543 | if (count > bytes_left) | 466 | } |
544 | count = bytes_left; | ||
545 | bytes_left -= count; | ||
546 | |||
547 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) | ||
548 | template->src = buf; | ||
549 | else | ||
550 | template->dst = buf; | ||
551 | template->ccnt = count >> shift; | ||
552 | |||
553 | edma_write_slot(slot, template); | ||
554 | } | 467 | } |
555 | 468 | ||
556 | if (host->version == MMC_CTLR_VERSION_2) | 469 | dmaengine_submit(desc); |
557 | edma_clear_event(channel); | 470 | dma_async_issue_pending(chan); |
558 | 471 | ||
559 | edma_start(channel); | 472 | out: |
473 | return ret; | ||
560 | } | 474 | } |
561 | 475 | ||
562 | static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, | 476 | static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, |
@@ -564,6 +478,7 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, | |||
564 | { | 478 | { |
565 | int i; | 479 | int i; |
566 | int mask = rw_threshold - 1; | 480 | int mask = rw_threshold - 1; |
481 | int ret = 0; | ||
567 | 482 | ||
568 | host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, | 483 | host->sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, |
569 | ((data->flags & MMC_DATA_WRITE) | 484 | ((data->flags & MMC_DATA_WRITE) |
@@ -583,70 +498,48 @@ static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host, | |||
583 | } | 498 | } |
584 | 499 | ||
585 | host->do_dma = 1; | 500 | host->do_dma = 1; |
586 | mmc_davinci_send_dma_request(host, data); | 501 | ret = mmc_davinci_send_dma_request(host, data); |
587 | 502 | ||
588 | return 0; | 503 | return ret; |
589 | } | 504 | } |
590 | 505 | ||
591 | static void __init_or_module | 506 | static void __init_or_module |
592 | davinci_release_dma_channels(struct mmc_davinci_host *host) | 507 | davinci_release_dma_channels(struct mmc_davinci_host *host) |
593 | { | 508 | { |
594 | unsigned i; | ||
595 | |||
596 | if (!host->use_dma) | 509 | if (!host->use_dma) |
597 | return; | 510 | return; |
598 | 511 | ||
599 | for (i = 0; i < host->n_link; i++) | 512 | dma_release_channel(host->dma_tx); |
600 | edma_free_slot(host->links[i]); | 513 | dma_release_channel(host->dma_rx); |
601 | |||
602 | edma_free_channel(host->txdma); | ||
603 | edma_free_channel(host->rxdma); | ||
604 | } | 514 | } |
605 | 515 | ||
606 | static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) | 516 | static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) |
607 | { | 517 | { |
608 | u32 link_size; | 518 | int r; |
609 | int r, i; | 519 | dma_cap_mask_t mask; |
610 | 520 | ||
611 | /* Acquire master DMA write channel */ | 521 | dma_cap_zero(mask); |
612 | r = edma_alloc_channel(host->txdma, mmc_davinci_dma_cb, host, | 522 | dma_cap_set(DMA_SLAVE, mask); |
613 | EVENTQ_DEFAULT); | 523 | |
614 | if (r < 0) { | 524 | host->dma_tx = |
615 | dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n", | 525 | dma_request_channel(mask, edma_filter_fn, &host->txdma); |
616 | "tx", r); | 526 | if (!host->dma_tx) { |
617 | return r; | 527 | dev_err(mmc_dev(host->mmc), "Can't get dma_tx channel\n"); |
618 | } | 528 | return -ENODEV; |
619 | mmc_davinci_dma_setup(host, true, &host->tx_template); | ||
620 | |||
621 | /* Acquire master DMA read channel */ | ||
622 | r = edma_alloc_channel(host->rxdma, mmc_davinci_dma_cb, host, | ||
623 | EVENTQ_DEFAULT); | ||
624 | if (r < 0) { | ||
625 | dev_warn(mmc_dev(host->mmc), "alloc %s channel err %d\n", | ||
626 | "rx", r); | ||
627 | goto free_master_write; | ||
628 | } | 529 | } |
629 | mmc_davinci_dma_setup(host, false, &host->rx_template); | ||
630 | 530 | ||
631 | /* Allocate parameter RAM slots, which will later be bound to a | 531 | host->dma_rx = |
632 | * channel as needed to handle a scatterlist. | 532 | dma_request_channel(mask, edma_filter_fn, &host->rxdma); |
633 | */ | 533 | if (!host->dma_rx) { |
634 | link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links)); | 534 | dev_err(mmc_dev(host->mmc), "Can't get dma_rx channel\n"); |
635 | for (i = 0; i < link_size; i++) { | 535 | r = -ENODEV; |
636 | r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); | 536 | goto free_master_write; |
637 | if (r < 0) { | ||
638 | dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n", | ||
639 | r); | ||
640 | break; | ||
641 | } | ||
642 | host->links[i] = r; | ||
643 | } | 537 | } |
644 | host->n_link = i; | ||
645 | 538 | ||
646 | return 0; | 539 | return 0; |
647 | 540 | ||
648 | free_master_write: | 541 | free_master_write: |
649 | edma_free_channel(host->txdma); | 542 | dma_release_channel(host->dma_tx); |
650 | 543 | ||
651 | return r; | 544 | return r; |
652 | } | 545 | } |
@@ -1359,7 +1252,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
1359 | * Each hw_seg uses one EDMA parameter RAM slot, always one | 1252 | * Each hw_seg uses one EDMA parameter RAM slot, always one |
1360 | * channel and then usually some linked slots. | 1253 | * channel and then usually some linked slots. |
1361 | */ | 1254 | */ |
1362 | mmc->max_segs = 1 + host->n_link; | 1255 | mmc->max_segs = MAX_NR_SG; |
1363 | 1256 | ||
1364 | /* EDMA limit per hw segment (one or two MBytes) */ | 1257 | /* EDMA limit per hw segment (one or two MBytes) */ |
1365 | mmc->max_seg_size = MAX_CCNT * rw_threshold; | 1258 | mmc->max_seg_size = MAX_CCNT * rw_threshold; |
diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c new file mode 100644 index 000000000000..660bbc528862 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-exynos.c | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * Exynos Specific Extensions for Synopsys DW Multimedia Card Interface driver | ||
3 | * | ||
4 | * Copyright (C) 2012, Samsung Electronics Co., Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/clk.h> | ||
15 | #include <linux/mmc/host.h> | ||
16 | #include <linux/mmc/dw_mmc.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_gpio.h> | ||
19 | |||
20 | #include "dw_mmc.h" | ||
21 | #include "dw_mmc-pltfm.h" | ||
22 | |||
23 | #define NUM_PINS(x) (x + 2) | ||
24 | |||
25 | #define SDMMC_CLKSEL 0x09C | ||
26 | #define SDMMC_CLKSEL_CCLK_SAMPLE(x) (((x) & 7) << 0) | ||
27 | #define SDMMC_CLKSEL_CCLK_DRIVE(x) (((x) & 7) << 16) | ||
28 | #define SDMMC_CLKSEL_CCLK_DIVIDER(x) (((x) & 7) << 24) | ||
29 | #define SDMMC_CLKSEL_GET_DRV_WD3(x) (((x) >> 16) & 0x7) | ||
30 | #define SDMMC_CLKSEL_TIMING(x, y, z) (SDMMC_CLKSEL_CCLK_SAMPLE(x) | \ | ||
31 | SDMMC_CLKSEL_CCLK_DRIVE(y) | \ | ||
32 | SDMMC_CLKSEL_CCLK_DIVIDER(z)) | ||
33 | |||
34 | #define SDMMC_CMD_USE_HOLD_REG BIT(29) | ||
35 | |||
36 | #define EXYNOS4210_FIXED_CIU_CLK_DIV 2 | ||
37 | #define EXYNOS4412_FIXED_CIU_CLK_DIV 4 | ||
38 | |||
39 | /* Variations in Exynos specific dw-mshc controller */ | ||
40 | enum dw_mci_exynos_type { | ||
41 | DW_MCI_TYPE_EXYNOS4210, | ||
42 | DW_MCI_TYPE_EXYNOS4412, | ||
43 | DW_MCI_TYPE_EXYNOS5250, | ||
44 | }; | ||
45 | |||
46 | /* Exynos implementation specific driver private data */ | ||
47 | struct dw_mci_exynos_priv_data { | ||
48 | enum dw_mci_exynos_type ctrl_type; | ||
49 | u8 ciu_div; | ||
50 | u32 sdr_timing; | ||
51 | u32 ddr_timing; | ||
52 | }; | ||
53 | |||
54 | static struct dw_mci_exynos_compatible { | ||
55 | char *compatible; | ||
56 | enum dw_mci_exynos_type ctrl_type; | ||
57 | } exynos_compat[] = { | ||
58 | { | ||
59 | .compatible = "samsung,exynos4210-dw-mshc", | ||
60 | .ctrl_type = DW_MCI_TYPE_EXYNOS4210, | ||
61 | }, { | ||
62 | .compatible = "samsung,exynos4412-dw-mshc", | ||
63 | .ctrl_type = DW_MCI_TYPE_EXYNOS4412, | ||
64 | }, { | ||
65 | .compatible = "samsung,exynos5250-dw-mshc", | ||
66 | .ctrl_type = DW_MCI_TYPE_EXYNOS5250, | ||
67 | }, | ||
68 | }; | ||
69 | |||
70 | static int dw_mci_exynos_priv_init(struct dw_mci *host) | ||
71 | { | ||
72 | struct dw_mci_exynos_priv_data *priv; | ||
73 | int idx; | ||
74 | |||
75 | priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); | ||
76 | if (!priv) { | ||
77 | dev_err(host->dev, "mem alloc failed for private data\n"); | ||
78 | return -ENOMEM; | ||
79 | } | ||
80 | |||
81 | for (idx = 0; idx < ARRAY_SIZE(exynos_compat); idx++) { | ||
82 | if (of_device_is_compatible(host->dev->of_node, | ||
83 | exynos_compat[idx].compatible)) | ||
84 | priv->ctrl_type = exynos_compat[idx].ctrl_type; | ||
85 | } | ||
86 | |||
87 | host->priv = priv; | ||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int dw_mci_exynos_setup_clock(struct dw_mci *host) | ||
92 | { | ||
93 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
94 | |||
95 | if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS5250) | ||
96 | host->bus_hz /= (priv->ciu_div + 1); | ||
97 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4412) | ||
98 | host->bus_hz /= EXYNOS4412_FIXED_CIU_CLK_DIV; | ||
99 | else if (priv->ctrl_type == DW_MCI_TYPE_EXYNOS4210) | ||
100 | host->bus_hz /= EXYNOS4210_FIXED_CIU_CLK_DIV; | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static void dw_mci_exynos_prepare_command(struct dw_mci *host, u32 *cmdr) | ||
106 | { | ||
107 | /* | ||
108 | * Exynos4412 and Exynos5250 extends the use of CMD register with the | ||
109 | * use of bit 29 (which is reserved on standard MSHC controllers) for | ||
110 | * optionally bypassing the HOLD register for command and data. The | ||
111 | * HOLD register should be bypassed in case there is no phase shift | ||
112 | * applied on CMD/DATA that is sent to the card. | ||
113 | */ | ||
114 | if (SDMMC_CLKSEL_GET_DRV_WD3(mci_readl(host, CLKSEL))) | ||
115 | *cmdr |= SDMMC_CMD_USE_HOLD_REG; | ||
116 | } | ||
117 | |||
118 | static void dw_mci_exynos_set_ios(struct dw_mci *host, struct mmc_ios *ios) | ||
119 | { | ||
120 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
121 | |||
122 | if (ios->timing == MMC_TIMING_UHS_DDR50) | ||
123 | mci_writel(host, CLKSEL, priv->ddr_timing); | ||
124 | else | ||
125 | mci_writel(host, CLKSEL, priv->sdr_timing); | ||
126 | } | ||
127 | |||
128 | static int dw_mci_exynos_parse_dt(struct dw_mci *host) | ||
129 | { | ||
130 | struct dw_mci_exynos_priv_data *priv = host->priv; | ||
131 | struct device_node *np = host->dev->of_node; | ||
132 | u32 timing[2]; | ||
133 | u32 div = 0; | ||
134 | int ret; | ||
135 | |||
136 | of_property_read_u32(np, "samsung,dw-mshc-ciu-div", &div); | ||
137 | priv->ciu_div = div; | ||
138 | |||
139 | ret = of_property_read_u32_array(np, | ||
140 | "samsung,dw-mshc-sdr-timing", timing, 2); | ||
141 | if (ret) | ||
142 | return ret; | ||
143 | |||
144 | priv->sdr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); | ||
145 | |||
146 | ret = of_property_read_u32_array(np, | ||
147 | "samsung,dw-mshc-ddr-timing", timing, 2); | ||
148 | if (ret) | ||
149 | return ret; | ||
150 | |||
151 | priv->ddr_timing = SDMMC_CLKSEL_TIMING(timing[0], timing[1], div); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int dw_mci_exynos_setup_bus(struct dw_mci *host, | ||
156 | struct device_node *slot_np, u8 bus_width) | ||
157 | { | ||
158 | int idx, gpio, ret; | ||
159 | |||
160 | if (!slot_np) | ||
161 | return -EINVAL; | ||
162 | |||
163 | /* cmd + clock + bus-width pins */ | ||
164 | for (idx = 0; idx < NUM_PINS(bus_width); idx++) { | ||
165 | gpio = of_get_gpio(slot_np, idx); | ||
166 | if (!gpio_is_valid(gpio)) { | ||
167 | dev_err(host->dev, "invalid gpio: %d\n", gpio); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus"); | ||
172 | if (ret) { | ||
173 | dev_err(host->dev, "gpio [%d] request failed\n", gpio); | ||
174 | return -EBUSY; | ||
175 | } | ||
176 | } | ||
177 | |||
178 | gpio = of_get_named_gpio(slot_np, "wp-gpios", 0); | ||
179 | if (gpio_is_valid(gpio)) { | ||
180 | if (devm_gpio_request(host->dev, gpio, "dw-mci-wp")) | ||
181 | dev_info(host->dev, "gpio [%d] request failed\n", | ||
182 | gpio); | ||
183 | } else { | ||
184 | dev_info(host->dev, "wp gpio not available"); | ||
185 | host->pdata->quirks |= DW_MCI_QUIRK_NO_WRITE_PROTECT; | ||
186 | } | ||
187 | |||
188 | if (host->pdata->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) | ||
189 | return 0; | ||
190 | |||
191 | gpio = of_get_named_gpio(slot_np, "samsung,cd-pinmux-gpio", 0); | ||
192 | if (gpio_is_valid(gpio)) { | ||
193 | if (devm_gpio_request(host->dev, gpio, "dw-mci-cd")) | ||
194 | dev_err(host->dev, "gpio [%d] request failed\n", gpio); | ||
195 | } else { | ||
196 | dev_info(host->dev, "cd gpio not available"); | ||
197 | } | ||
198 | |||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | /* Exynos5250 controller specific capabilities */ | ||
203 | static unsigned long exynos5250_dwmmc_caps[4] = { | ||
204 | MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR | | ||
205 | MMC_CAP_8_BIT_DATA | MMC_CAP_CMD23, | ||
206 | MMC_CAP_CMD23, | ||
207 | MMC_CAP_CMD23, | ||
208 | MMC_CAP_CMD23, | ||
209 | }; | ||
210 | |||
211 | static struct dw_mci_drv_data exynos5250_drv_data = { | ||
212 | .caps = exynos5250_dwmmc_caps, | ||
213 | .init = dw_mci_exynos_priv_init, | ||
214 | .setup_clock = dw_mci_exynos_setup_clock, | ||
215 | .prepare_command = dw_mci_exynos_prepare_command, | ||
216 | .set_ios = dw_mci_exynos_set_ios, | ||
217 | .parse_dt = dw_mci_exynos_parse_dt, | ||
218 | .setup_bus = dw_mci_exynos_setup_bus, | ||
219 | }; | ||
220 | |||
221 | static const struct of_device_id dw_mci_exynos_match[] = { | ||
222 | { .compatible = "samsung,exynos5250-dw-mshc", | ||
223 | .data = (void *)&exynos5250_drv_data, }, | ||
224 | {}, | ||
225 | }; | ||
226 | MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); | ||
227 | |||
228 | int dw_mci_exynos_probe(struct platform_device *pdev) | ||
229 | { | ||
230 | struct dw_mci_drv_data *drv_data; | ||
231 | const struct of_device_id *match; | ||
232 | |||
233 | match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); | ||
234 | drv_data = match->data; | ||
235 | return dw_mci_pltfm_register(pdev, drv_data); | ||
236 | } | ||
237 | |||
238 | static struct platform_driver dw_mci_exynos_pltfm_driver = { | ||
239 | .probe = dw_mci_exynos_probe, | ||
240 | .remove = __exit_p(dw_mci_pltfm_remove), | ||
241 | .driver = { | ||
242 | .name = "dwmmc_exynos", | ||
243 | .of_match_table = of_match_ptr(dw_mci_exynos_match), | ||
244 | .pm = &dw_mci_pltfm_pmops, | ||
245 | }, | ||
246 | }; | ||
247 | |||
248 | module_platform_driver(dw_mci_exynos_pltfm_driver); | ||
249 | |||
250 | MODULE_DESCRIPTION("Samsung Specific DW-MSHC Driver Extension"); | ||
251 | MODULE_AUTHOR("Thomas Abraham <thomas.ab@samsung.com"); | ||
252 | MODULE_LICENSE("GPL v2"); | ||
253 | MODULE_ALIAS("platform:dwmmc-exynos"); | ||
diff --git a/drivers/mmc/host/dw_mmc-pci.c b/drivers/mmc/host/dw_mmc-pci.c index dc0d25a013e0..edb37e9135ae 100644 --- a/drivers/mmc/host/dw_mmc-pci.c +++ b/drivers/mmc/host/dw_mmc-pci.c | |||
@@ -59,7 +59,7 @@ static int __devinit dw_mci_pci_probe(struct pci_dev *pdev, | |||
59 | 59 | ||
60 | host->irq = pdev->irq; | 60 | host->irq = pdev->irq; |
61 | host->irq_flags = IRQF_SHARED; | 61 | host->irq_flags = IRQF_SHARED; |
62 | host->dev = pdev->dev; | 62 | host->dev = &pdev->dev; |
63 | host->pdata = &pci_board_data; | 63 | host->pdata = &pci_board_data; |
64 | 64 | ||
65 | host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR); | 65 | host->regs = pci_iomap(pdev, PCI_BAR_NO, COMPLETE_BAR); |
@@ -140,18 +140,7 @@ static struct pci_driver dw_mci_pci_driver = { | |||
140 | }, | 140 | }, |
141 | }; | 141 | }; |
142 | 142 | ||
143 | static int __init dw_mci_init(void) | 143 | module_pci_driver(dw_mci_pci_driver); |
144 | { | ||
145 | return pci_register_driver(&dw_mci_pci_driver); | ||
146 | } | ||
147 | |||
148 | static void __exit dw_mci_exit(void) | ||
149 | { | ||
150 | pci_unregister_driver(&dw_mci_pci_driver); | ||
151 | } | ||
152 | |||
153 | module_init(dw_mci_init); | ||
154 | module_exit(dw_mci_exit); | ||
155 | 144 | ||
156 | MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver"); | 145 | MODULE_DESCRIPTION("DW Multimedia Card PCI Interface driver"); |
157 | MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>"); | 146 | MODULE_AUTHOR("Shashidhar Hiremath <shashidharh@vayavyalabs.com>"); |
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 92ec3eb3aae7..c960ca7ffbe6 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c | |||
@@ -19,59 +19,63 @@ | |||
19 | #include <linux/mmc/host.h> | 19 | #include <linux/mmc/host.h> |
20 | #include <linux/mmc/mmc.h> | 20 | #include <linux/mmc/mmc.h> |
21 | #include <linux/mmc/dw_mmc.h> | 21 | #include <linux/mmc/dw_mmc.h> |
22 | #include <linux/of.h> | ||
23 | |||
22 | #include "dw_mmc.h" | 24 | #include "dw_mmc.h" |
23 | 25 | ||
24 | static int dw_mci_pltfm_probe(struct platform_device *pdev) | 26 | int dw_mci_pltfm_register(struct platform_device *pdev, |
27 | struct dw_mci_drv_data *drv_data) | ||
25 | { | 28 | { |
26 | struct dw_mci *host; | 29 | struct dw_mci *host; |
27 | struct resource *regs; | 30 | struct resource *regs; |
28 | int ret; | 31 | int ret; |
29 | 32 | ||
30 | host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL); | 33 | host = devm_kzalloc(&pdev->dev, sizeof(struct dw_mci), GFP_KERNEL); |
31 | if (!host) | 34 | if (!host) |
32 | return -ENOMEM; | 35 | return -ENOMEM; |
33 | 36 | ||
34 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 37 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
35 | if (!regs) { | 38 | if (!regs) |
36 | ret = -ENXIO; | 39 | return -ENXIO; |
37 | goto err_free; | ||
38 | } | ||
39 | 40 | ||
40 | host->irq = platform_get_irq(pdev, 0); | 41 | host->irq = platform_get_irq(pdev, 0); |
41 | if (host->irq < 0) { | 42 | if (host->irq < 0) |
42 | ret = host->irq; | 43 | return host->irq; |
43 | goto err_free; | ||
44 | } | ||
45 | 44 | ||
46 | host->dev = pdev->dev; | 45 | host->drv_data = drv_data; |
46 | host->dev = &pdev->dev; | ||
47 | host->irq_flags = 0; | 47 | host->irq_flags = 0; |
48 | host->pdata = pdev->dev.platform_data; | 48 | host->pdata = pdev->dev.platform_data; |
49 | ret = -ENOMEM; | 49 | host->regs = devm_request_and_ioremap(&pdev->dev, regs); |
50 | host->regs = ioremap(regs->start, resource_size(regs)); | ||
51 | if (!host->regs) | 50 | if (!host->regs) |
52 | goto err_free; | 51 | return -ENOMEM; |
52 | |||
53 | if (host->drv_data->init) { | ||
54 | ret = host->drv_data->init(host); | ||
55 | if (ret) | ||
56 | return ret; | ||
57 | } | ||
58 | |||
53 | platform_set_drvdata(pdev, host); | 59 | platform_set_drvdata(pdev, host); |
54 | ret = dw_mci_probe(host); | 60 | ret = dw_mci_probe(host); |
55 | if (ret) | ||
56 | goto err_out; | ||
57 | return ret; | ||
58 | err_out: | ||
59 | iounmap(host->regs); | ||
60 | err_free: | ||
61 | kfree(host); | ||
62 | return ret; | 61 | return ret; |
63 | } | 62 | } |
63 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_register); | ||
64 | 64 | ||
65 | static int __exit dw_mci_pltfm_remove(struct platform_device *pdev) | 65 | static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev) |
66 | { | ||
67 | return dw_mci_pltfm_register(pdev, NULL); | ||
68 | } | ||
69 | |||
70 | static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev) | ||
66 | { | 71 | { |
67 | struct dw_mci *host = platform_get_drvdata(pdev); | 72 | struct dw_mci *host = platform_get_drvdata(pdev); |
68 | 73 | ||
69 | platform_set_drvdata(pdev, NULL); | 74 | platform_set_drvdata(pdev, NULL); |
70 | dw_mci_remove(host); | 75 | dw_mci_remove(host); |
71 | iounmap(host->regs); | ||
72 | kfree(host); | ||
73 | return 0; | 76 | return 0; |
74 | } | 77 | } |
78 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_remove); | ||
75 | 79 | ||
76 | #ifdef CONFIG_PM_SLEEP | 80 | #ifdef CONFIG_PM_SLEEP |
77 | /* | 81 | /* |
@@ -105,12 +109,20 @@ static int dw_mci_pltfm_resume(struct device *dev) | |||
105 | #define dw_mci_pltfm_resume NULL | 109 | #define dw_mci_pltfm_resume NULL |
106 | #endif /* CONFIG_PM_SLEEP */ | 110 | #endif /* CONFIG_PM_SLEEP */ |
107 | 111 | ||
108 | static SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume); | 112 | SIMPLE_DEV_PM_OPS(dw_mci_pltfm_pmops, dw_mci_pltfm_suspend, dw_mci_pltfm_resume); |
113 | EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops); | ||
114 | |||
115 | static const struct of_device_id dw_mci_pltfm_match[] = { | ||
116 | { .compatible = "snps,dw-mshc", }, | ||
117 | {}, | ||
118 | }; | ||
119 | MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); | ||
109 | 120 | ||
110 | static struct platform_driver dw_mci_pltfm_driver = { | 121 | static struct platform_driver dw_mci_pltfm_driver = { |
111 | .remove = __exit_p(dw_mci_pltfm_remove), | 122 | .remove = __exit_p(dw_mci_pltfm_remove), |
112 | .driver = { | 123 | .driver = { |
113 | .name = "dw_mmc", | 124 | .name = "dw_mmc", |
125 | .of_match_table = of_match_ptr(dw_mci_pltfm_match), | ||
114 | .pm = &dw_mci_pltfm_pmops, | 126 | .pm = &dw_mci_pltfm_pmops, |
115 | }, | 127 | }, |
116 | }; | 128 | }; |
diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h new file mode 100644 index 000000000000..301f24541fc2 --- /dev/null +++ b/drivers/mmc/host/dw_mmc-pltfm.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * Synopsys DesignWare Multimedia Card Interface Platform driver | ||
3 | * | ||
4 | * Copyright (C) 2012, Samsung Electronics Co., Ltd. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _DW_MMC_PLTFM_H_ | ||
13 | #define _DW_MMC_PLTFM_H_ | ||
14 | |||
15 | extern int dw_mci_pltfm_register(struct platform_device *pdev, | ||
16 | struct dw_mci_drv_data *drv_data); | ||
17 | extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev); | ||
18 | extern const struct dev_pm_ops dw_mci_pltfm_pmops; | ||
19 | |||
20 | #endif /* _DW_MMC_PLTFM_H_ */ | ||
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index af40d227bece..c2828f35c3b8 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/bitops.h> | 33 | #include <linux/bitops.h> |
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | #include <linux/workqueue.h> | 35 | #include <linux/workqueue.h> |
36 | #include <linux/of.h> | ||
36 | 37 | ||
37 | #include "dw_mmc.h" | 38 | #include "dw_mmc.h" |
38 | 39 | ||
@@ -230,6 +231,7 @@ static void dw_mci_set_timeout(struct dw_mci *host) | |||
230 | static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | 231 | static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) |
231 | { | 232 | { |
232 | struct mmc_data *data; | 233 | struct mmc_data *data; |
234 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
233 | u32 cmdr; | 235 | u32 cmdr; |
234 | cmd->error = -EINPROGRESS; | 236 | cmd->error = -EINPROGRESS; |
235 | 237 | ||
@@ -259,6 +261,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | |||
259 | cmdr |= SDMMC_CMD_DAT_WR; | 261 | cmdr |= SDMMC_CMD_DAT_WR; |
260 | } | 262 | } |
261 | 263 | ||
264 | if (slot->host->drv_data->prepare_command) | ||
265 | slot->host->drv_data->prepare_command(slot->host, &cmdr); | ||
266 | |||
262 | return cmdr; | 267 | return cmdr; |
263 | } | 268 | } |
264 | 269 | ||
@@ -266,7 +271,7 @@ static void dw_mci_start_command(struct dw_mci *host, | |||
266 | struct mmc_command *cmd, u32 cmd_flags) | 271 | struct mmc_command *cmd, u32 cmd_flags) |
267 | { | 272 | { |
268 | host->cmd = cmd; | 273 | host->cmd = cmd; |
269 | dev_vdbg(&host->dev, | 274 | dev_vdbg(host->dev, |
270 | "start command: ARGR=0x%08x CMDR=0x%08x\n", | 275 | "start command: ARGR=0x%08x CMDR=0x%08x\n", |
271 | cmd->arg, cmd_flags); | 276 | cmd->arg, cmd_flags); |
272 | 277 | ||
@@ -308,7 +313,7 @@ static void dw_mci_dma_cleanup(struct dw_mci *host) | |||
308 | 313 | ||
309 | if (data) | 314 | if (data) |
310 | if (!data->host_cookie) | 315 | if (!data->host_cookie) |
311 | dma_unmap_sg(&host->dev, | 316 | dma_unmap_sg(host->dev, |
312 | data->sg, | 317 | data->sg, |
313 | data->sg_len, | 318 | data->sg_len, |
314 | dw_mci_get_dma_dir(data)); | 319 | dw_mci_get_dma_dir(data)); |
@@ -334,7 +339,7 @@ static void dw_mci_idmac_complete_dma(struct dw_mci *host) | |||
334 | { | 339 | { |
335 | struct mmc_data *data = host->data; | 340 | struct mmc_data *data = host->data; |
336 | 341 | ||
337 | dev_vdbg(&host->dev, "DMA complete\n"); | 342 | dev_vdbg(host->dev, "DMA complete\n"); |
338 | 343 | ||
339 | host->dma_ops->cleanup(host); | 344 | host->dma_ops->cleanup(host); |
340 | 345 | ||
@@ -405,23 +410,11 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) | |||
405 | static int dw_mci_idmac_init(struct dw_mci *host) | 410 | static int dw_mci_idmac_init(struct dw_mci *host) |
406 | { | 411 | { |
407 | struct idmac_desc *p; | 412 | struct idmac_desc *p; |
408 | int i, dma_support; | 413 | int i; |
409 | 414 | ||
410 | /* Number of descriptors in the ring buffer */ | 415 | /* Number of descriptors in the ring buffer */ |
411 | host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); | 416 | host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); |
412 | 417 | ||
413 | /* Check if Hardware Configuration Register has support for DMA */ | ||
414 | dma_support = (mci_readl(host, HCON) >> 16) & 0x3; | ||
415 | |||
416 | if (!dma_support || dma_support > 2) { | ||
417 | dev_err(&host->dev, | ||
418 | "Host Controller does not support IDMA Tx.\n"); | ||
419 | host->dma_ops = NULL; | ||
420 | return -ENODEV; | ||
421 | } | ||
422 | |||
423 | dev_info(&host->dev, "Using internal DMA controller.\n"); | ||
424 | |||
425 | /* Forward link the descriptor list */ | 418 | /* Forward link the descriptor list */ |
426 | for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) | 419 | for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) |
427 | p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); | 420 | p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); |
@@ -476,7 +469,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host, | |||
476 | return -EINVAL; | 469 | return -EINVAL; |
477 | } | 470 | } |
478 | 471 | ||
479 | sg_len = dma_map_sg(&host->dev, | 472 | sg_len = dma_map_sg(host->dev, |
480 | data->sg, | 473 | data->sg, |
481 | data->sg_len, | 474 | data->sg_len, |
482 | dw_mci_get_dma_dir(data)); | 475 | dw_mci_get_dma_dir(data)); |
@@ -519,7 +512,7 @@ static void dw_mci_post_req(struct mmc_host *mmc, | |||
519 | return; | 512 | return; |
520 | 513 | ||
521 | if (data->host_cookie) | 514 | if (data->host_cookie) |
522 | dma_unmap_sg(&slot->host->dev, | 515 | dma_unmap_sg(slot->host->dev, |
523 | data->sg, | 516 | data->sg, |
524 | data->sg_len, | 517 | data->sg_len, |
525 | dw_mci_get_dma_dir(data)); | 518 | dw_mci_get_dma_dir(data)); |
@@ -545,7 +538,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | |||
545 | 538 | ||
546 | host->using_dma = 1; | 539 | host->using_dma = 1; |
547 | 540 | ||
548 | dev_vdbg(&host->dev, | 541 | dev_vdbg(host->dev, |
549 | "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", | 542 | "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", |
550 | (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, | 543 | (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, |
551 | sg_len); | 544 | sg_len); |
@@ -814,6 +807,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
814 | slot->clock = ios->clock; | 807 | slot->clock = ios->clock; |
815 | } | 808 | } |
816 | 809 | ||
810 | if (slot->host->drv_data->set_ios) | ||
811 | slot->host->drv_data->set_ios(slot->host, ios); | ||
812 | |||
817 | switch (ios->power_mode) { | 813 | switch (ios->power_mode) { |
818 | case MMC_POWER_UP: | 814 | case MMC_POWER_UP: |
819 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); | 815 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); |
@@ -830,7 +826,9 @@ static int dw_mci_get_ro(struct mmc_host *mmc) | |||
830 | struct dw_mci_board *brd = slot->host->pdata; | 826 | struct dw_mci_board *brd = slot->host->pdata; |
831 | 827 | ||
832 | /* Use platform get_ro function, else try on board write protect */ | 828 | /* Use platform get_ro function, else try on board write protect */ |
833 | if (brd->get_ro) | 829 | if (brd->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT) |
830 | read_only = 0; | ||
831 | else if (brd->get_ro) | ||
834 | read_only = brd->get_ro(slot->id); | 832 | read_only = brd->get_ro(slot->id); |
835 | else | 833 | else |
836 | read_only = | 834 | read_only = |
@@ -939,12 +937,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | |||
939 | slot = list_entry(host->queue.next, | 937 | slot = list_entry(host->queue.next, |
940 | struct dw_mci_slot, queue_node); | 938 | struct dw_mci_slot, queue_node); |
941 | list_del(&slot->queue_node); | 939 | list_del(&slot->queue_node); |
942 | dev_vdbg(&host->dev, "list not empty: %s is next\n", | 940 | dev_vdbg(host->dev, "list not empty: %s is next\n", |
943 | mmc_hostname(slot->mmc)); | 941 | mmc_hostname(slot->mmc)); |
944 | host->state = STATE_SENDING_CMD; | 942 | host->state = STATE_SENDING_CMD; |
945 | dw_mci_start_request(host, slot); | 943 | dw_mci_start_request(host, slot); |
946 | } else { | 944 | } else { |
947 | dev_vdbg(&host->dev, "list empty\n"); | 945 | dev_vdbg(host->dev, "list empty\n"); |
948 | host->state = STATE_IDLE; | 946 | host->state = STATE_IDLE; |
949 | } | 947 | } |
950 | 948 | ||
@@ -1083,7 +1081,7 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1083 | data->bytes_xfered = 0; | 1081 | data->bytes_xfered = 0; |
1084 | data->error = -ETIMEDOUT; | 1082 | data->error = -ETIMEDOUT; |
1085 | } else { | 1083 | } else { |
1086 | dev_err(&host->dev, | 1084 | dev_err(host->dev, |
1087 | "data FIFO error " | 1085 | "data FIFO error " |
1088 | "(status=%08x)\n", | 1086 | "(status=%08x)\n", |
1089 | status); | 1087 | status); |
@@ -1767,12 +1765,60 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1767 | } | 1765 | } |
1768 | } | 1766 | } |
1769 | 1767 | ||
1770 | static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | 1768 | #ifdef CONFIG_OF |
1769 | /* given a slot id, find out the device node representing that slot */ | ||
1770 | static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) | ||
1771 | { | ||
1772 | struct device_node *np; | ||
1773 | const __be32 *addr; | ||
1774 | int len; | ||
1775 | |||
1776 | if (!dev || !dev->of_node) | ||
1777 | return NULL; | ||
1778 | |||
1779 | for_each_child_of_node(dev->of_node, np) { | ||
1780 | addr = of_get_property(np, "reg", &len); | ||
1781 | if (!addr || (len < sizeof(int))) | ||
1782 | continue; | ||
1783 | if (be32_to_cpup(addr) == slot) | ||
1784 | return np; | ||
1785 | } | ||
1786 | return NULL; | ||
1787 | } | ||
1788 | |||
1789 | /* find out bus-width for a given slot */ | ||
1790 | static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) | ||
1791 | { | ||
1792 | struct device_node *np = dw_mci_of_find_slot_node(dev, slot); | ||
1793 | u32 bus_wd = 1; | ||
1794 | |||
1795 | if (!np) | ||
1796 | return 1; | ||
1797 | |||
1798 | if (of_property_read_u32(np, "bus-width", &bus_wd)) | ||
1799 | dev_err(dev, "bus-width property not found, assuming width" | ||
1800 | " as 1\n"); | ||
1801 | return bus_wd; | ||
1802 | } | ||
1803 | #else /* CONFIG_OF */ | ||
1804 | static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) | ||
1805 | { | ||
1806 | return 1; | ||
1807 | } | ||
1808 | static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) | ||
1809 | { | ||
1810 | return NULL; | ||
1811 | } | ||
1812 | #endif /* CONFIG_OF */ | ||
1813 | |||
1814 | static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | ||
1771 | { | 1815 | { |
1772 | struct mmc_host *mmc; | 1816 | struct mmc_host *mmc; |
1773 | struct dw_mci_slot *slot; | 1817 | struct dw_mci_slot *slot; |
1818 | int ctrl_id, ret; | ||
1819 | u8 bus_width; | ||
1774 | 1820 | ||
1775 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->dev); | 1821 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); |
1776 | if (!mmc) | 1822 | if (!mmc) |
1777 | return -ENOMEM; | 1823 | return -ENOMEM; |
1778 | 1824 | ||
@@ -1780,6 +1826,7 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1780 | slot->id = id; | 1826 | slot->id = id; |
1781 | slot->mmc = mmc; | 1827 | slot->mmc = mmc; |
1782 | slot->host = host; | 1828 | slot->host = host; |
1829 | host->slot[id] = slot; | ||
1783 | 1830 | ||
1784 | mmc->ops = &dw_mci_ops; | 1831 | mmc->ops = &dw_mci_ops; |
1785 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); | 1832 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); |
@@ -1800,21 +1847,44 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1800 | if (host->pdata->caps) | 1847 | if (host->pdata->caps) |
1801 | mmc->caps = host->pdata->caps; | 1848 | mmc->caps = host->pdata->caps; |
1802 | 1849 | ||
1850 | if (host->dev->of_node) { | ||
1851 | ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); | ||
1852 | if (ctrl_id < 0) | ||
1853 | ctrl_id = 0; | ||
1854 | } else { | ||
1855 | ctrl_id = to_platform_device(host->dev)->id; | ||
1856 | } | ||
1857 | if (host->drv_data && host->drv_data->caps) | ||
1858 | mmc->caps |= host->drv_data->caps[ctrl_id]; | ||
1859 | |||
1803 | if (host->pdata->caps2) | 1860 | if (host->pdata->caps2) |
1804 | mmc->caps2 = host->pdata->caps2; | 1861 | mmc->caps2 = host->pdata->caps2; |
1805 | 1862 | ||
1806 | if (host->pdata->get_bus_wd) | 1863 | if (host->pdata->get_bus_wd) |
1807 | if (host->pdata->get_bus_wd(slot->id) >= 4) | 1864 | bus_width = host->pdata->get_bus_wd(slot->id); |
1808 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1865 | else if (host->dev->of_node) |
1866 | bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id); | ||
1867 | else | ||
1868 | bus_width = 1; | ||
1869 | |||
1870 | if (host->drv_data->setup_bus) { | ||
1871 | struct device_node *slot_np; | ||
1872 | slot_np = dw_mci_of_find_slot_node(host->dev, slot->id); | ||
1873 | ret = host->drv_data->setup_bus(host, slot_np, bus_width); | ||
1874 | if (ret) | ||
1875 | goto err_setup_bus; | ||
1876 | } | ||
1877 | |||
1878 | switch (bus_width) { | ||
1879 | case 8: | ||
1880 | mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
1881 | case 4: | ||
1882 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
1883 | } | ||
1809 | 1884 | ||
1810 | if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) | 1885 | if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) |
1811 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | 1886 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; |
1812 | 1887 | ||
1813 | if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY) | ||
1814 | mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT; | ||
1815 | else | ||
1816 | mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE; | ||
1817 | |||
1818 | if (host->pdata->blk_settings) { | 1888 | if (host->pdata->blk_settings) { |
1819 | mmc->max_segs = host->pdata->blk_settings->max_segs; | 1889 | mmc->max_segs = host->pdata->blk_settings->max_segs; |
1820 | mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; | 1890 | mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; |
@@ -1850,7 +1920,6 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1850 | else | 1920 | else |
1851 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | 1921 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); |
1852 | 1922 | ||
1853 | host->slot[id] = slot; | ||
1854 | mmc_add_host(mmc); | 1923 | mmc_add_host(mmc); |
1855 | 1924 | ||
1856 | #if defined(CONFIG_DEBUG_FS) | 1925 | #if defined(CONFIG_DEBUG_FS) |
@@ -1867,6 +1936,10 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1867 | queue_work(host->card_workqueue, &host->card_work); | 1936 | queue_work(host->card_workqueue, &host->card_work); |
1868 | 1937 | ||
1869 | return 0; | 1938 | return 0; |
1939 | |||
1940 | err_setup_bus: | ||
1941 | mmc_free_host(mmc); | ||
1942 | return -EINVAL; | ||
1870 | } | 1943 | } |
1871 | 1944 | ||
1872 | static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) | 1945 | static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) |
@@ -1884,10 +1957,10 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) | |||
1884 | static void dw_mci_init_dma(struct dw_mci *host) | 1957 | static void dw_mci_init_dma(struct dw_mci *host) |
1885 | { | 1958 | { |
1886 | /* Alloc memory for sg translation */ | 1959 | /* Alloc memory for sg translation */ |
1887 | host->sg_cpu = dma_alloc_coherent(&host->dev, PAGE_SIZE, | 1960 | host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE, |
1888 | &host->sg_dma, GFP_KERNEL); | 1961 | &host->sg_dma, GFP_KERNEL); |
1889 | if (!host->sg_cpu) { | 1962 | if (!host->sg_cpu) { |
1890 | dev_err(&host->dev, "%s: could not alloc DMA memory\n", | 1963 | dev_err(host->dev, "%s: could not alloc DMA memory\n", |
1891 | __func__); | 1964 | __func__); |
1892 | goto no_dma; | 1965 | goto no_dma; |
1893 | } | 1966 | } |
@@ -1895,6 +1968,7 @@ static void dw_mci_init_dma(struct dw_mci *host) | |||
1895 | /* Determine which DMA interface to use */ | 1968 | /* Determine which DMA interface to use */ |
1896 | #ifdef CONFIG_MMC_DW_IDMAC | 1969 | #ifdef CONFIG_MMC_DW_IDMAC |
1897 | host->dma_ops = &dw_mci_idmac_ops; | 1970 | host->dma_ops = &dw_mci_idmac_ops; |
1971 | dev_info(&host->dev, "Using internal DMA controller.\n"); | ||
1898 | #endif | 1972 | #endif |
1899 | 1973 | ||
1900 | if (!host->dma_ops) | 1974 | if (!host->dma_ops) |
@@ -1903,12 +1977,12 @@ static void dw_mci_init_dma(struct dw_mci *host) | |||
1903 | if (host->dma_ops->init && host->dma_ops->start && | 1977 | if (host->dma_ops->init && host->dma_ops->start && |
1904 | host->dma_ops->stop && host->dma_ops->cleanup) { | 1978 | host->dma_ops->stop && host->dma_ops->cleanup) { |
1905 | if (host->dma_ops->init(host)) { | 1979 | if (host->dma_ops->init(host)) { |
1906 | dev_err(&host->dev, "%s: Unable to initialize " | 1980 | dev_err(host->dev, "%s: Unable to initialize " |
1907 | "DMA Controller.\n", __func__); | 1981 | "DMA Controller.\n", __func__); |
1908 | goto no_dma; | 1982 | goto no_dma; |
1909 | } | 1983 | } |
1910 | } else { | 1984 | } else { |
1911 | dev_err(&host->dev, "DMA initialization not found.\n"); | 1985 | dev_err(host->dev, "DMA initialization not found.\n"); |
1912 | goto no_dma; | 1986 | goto no_dma; |
1913 | } | 1987 | } |
1914 | 1988 | ||
@@ -1916,7 +1990,7 @@ static void dw_mci_init_dma(struct dw_mci *host) | |||
1916 | return; | 1990 | return; |
1917 | 1991 | ||
1918 | no_dma: | 1992 | no_dma: |
1919 | dev_info(&host->dev, "Using PIO mode.\n"); | 1993 | dev_info(host->dev, "Using PIO mode.\n"); |
1920 | host->use_dma = 0; | 1994 | host->use_dma = 0; |
1921 | return; | 1995 | return; |
1922 | } | 1996 | } |
@@ -1942,30 +2016,133 @@ static bool mci_wait_reset(struct device *dev, struct dw_mci *host) | |||
1942 | return false; | 2016 | return false; |
1943 | } | 2017 | } |
1944 | 2018 | ||
2019 | #ifdef CONFIG_OF | ||
2020 | static struct dw_mci_of_quirks { | ||
2021 | char *quirk; | ||
2022 | int id; | ||
2023 | } of_quirks[] = { | ||
2024 | { | ||
2025 | .quirk = "supports-highspeed", | ||
2026 | .id = DW_MCI_QUIRK_HIGHSPEED, | ||
2027 | }, { | ||
2028 | .quirk = "broken-cd", | ||
2029 | .id = DW_MCI_QUIRK_BROKEN_CARD_DETECTION, | ||
2030 | }, | ||
2031 | }; | ||
2032 | |||
2033 | static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | ||
2034 | { | ||
2035 | struct dw_mci_board *pdata; | ||
2036 | struct device *dev = host->dev; | ||
2037 | struct device_node *np = dev->of_node; | ||
2038 | int idx, ret; | ||
2039 | |||
2040 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
2041 | if (!pdata) { | ||
2042 | dev_err(dev, "could not allocate memory for pdata\n"); | ||
2043 | return ERR_PTR(-ENOMEM); | ||
2044 | } | ||
2045 | |||
2046 | /* find out number of slots supported */ | ||
2047 | if (of_property_read_u32(dev->of_node, "num-slots", | ||
2048 | &pdata->num_slots)) { | ||
2049 | dev_info(dev, "num-slots property not found, " | ||
2050 | "assuming 1 slot is available\n"); | ||
2051 | pdata->num_slots = 1; | ||
2052 | } | ||
2053 | |||
2054 | /* get quirks */ | ||
2055 | for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++) | ||
2056 | if (of_get_property(np, of_quirks[idx].quirk, NULL)) | ||
2057 | pdata->quirks |= of_quirks[idx].id; | ||
2058 | |||
2059 | if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth)) | ||
2060 | dev_info(dev, "fifo-depth property not found, using " | ||
2061 | "value of FIFOTH register as default\n"); | ||
2062 | |||
2063 | of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); | ||
2064 | |||
2065 | if (host->drv_data->parse_dt) { | ||
2066 | ret = host->drv_data->parse_dt(host); | ||
2067 | if (ret) | ||
2068 | return ERR_PTR(ret); | ||
2069 | } | ||
2070 | |||
2071 | return pdata; | ||
2072 | } | ||
2073 | |||
2074 | #else /* CONFIG_OF */ | ||
2075 | static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | ||
2076 | { | ||
2077 | return ERR_PTR(-EINVAL); | ||
2078 | } | ||
2079 | #endif /* CONFIG_OF */ | ||
2080 | |||
1945 | int dw_mci_probe(struct dw_mci *host) | 2081 | int dw_mci_probe(struct dw_mci *host) |
1946 | { | 2082 | { |
1947 | int width, i, ret = 0; | 2083 | int width, i, ret = 0; |
1948 | u32 fifo_size; | 2084 | u32 fifo_size; |
2085 | int init_slots = 0; | ||
1949 | 2086 | ||
1950 | if (!host->pdata || !host->pdata->init) { | 2087 | if (!host->pdata) { |
1951 | dev_err(&host->dev, | 2088 | host->pdata = dw_mci_parse_dt(host); |
1952 | "Platform data must supply init function\n"); | 2089 | if (IS_ERR(host->pdata)) { |
1953 | return -ENODEV; | 2090 | dev_err(host->dev, "platform data not available\n"); |
2091 | return -EINVAL; | ||
2092 | } | ||
1954 | } | 2093 | } |
1955 | 2094 | ||
1956 | if (!host->pdata->select_slot && host->pdata->num_slots > 1) { | 2095 | if (!host->pdata->select_slot && host->pdata->num_slots > 1) { |
1957 | dev_err(&host->dev, | 2096 | dev_err(host->dev, |
1958 | "Platform data must supply select_slot function\n"); | 2097 | "Platform data must supply select_slot function\n"); |
1959 | return -ENODEV; | 2098 | return -ENODEV; |
1960 | } | 2099 | } |
1961 | 2100 | ||
1962 | if (!host->pdata->bus_hz) { | 2101 | host->biu_clk = clk_get(host->dev, "biu"); |
1963 | dev_err(&host->dev, | 2102 | if (IS_ERR(host->biu_clk)) { |
2103 | dev_dbg(host->dev, "biu clock not available\n"); | ||
2104 | } else { | ||
2105 | ret = clk_prepare_enable(host->biu_clk); | ||
2106 | if (ret) { | ||
2107 | dev_err(host->dev, "failed to enable biu clock\n"); | ||
2108 | clk_put(host->biu_clk); | ||
2109 | return ret; | ||
2110 | } | ||
2111 | } | ||
2112 | |||
2113 | host->ciu_clk = clk_get(host->dev, "ciu"); | ||
2114 | if (IS_ERR(host->ciu_clk)) { | ||
2115 | dev_dbg(host->dev, "ciu clock not available\n"); | ||
2116 | } else { | ||
2117 | ret = clk_prepare_enable(host->ciu_clk); | ||
2118 | if (ret) { | ||
2119 | dev_err(host->dev, "failed to enable ciu clock\n"); | ||
2120 | clk_put(host->ciu_clk); | ||
2121 | goto err_clk_biu; | ||
2122 | } | ||
2123 | } | ||
2124 | |||
2125 | if (IS_ERR(host->ciu_clk)) | ||
2126 | host->bus_hz = host->pdata->bus_hz; | ||
2127 | else | ||
2128 | host->bus_hz = clk_get_rate(host->ciu_clk); | ||
2129 | |||
2130 | if (host->drv_data->setup_clock) { | ||
2131 | ret = host->drv_data->setup_clock(host); | ||
2132 | if (ret) { | ||
2133 | dev_err(host->dev, | ||
2134 | "implementation specific clock setup failed\n"); | ||
2135 | goto err_clk_ciu; | ||
2136 | } | ||
2137 | } | ||
2138 | |||
2139 | if (!host->bus_hz) { | ||
2140 | dev_err(host->dev, | ||
1964 | "Platform data must supply bus speed\n"); | 2141 | "Platform data must supply bus speed\n"); |
1965 | return -ENODEV; | 2142 | ret = -ENODEV; |
2143 | goto err_clk_ciu; | ||
1966 | } | 2144 | } |
1967 | 2145 | ||
1968 | host->bus_hz = host->pdata->bus_hz; | ||
1969 | host->quirks = host->pdata->quirks; | 2146 | host->quirks = host->pdata->quirks; |
1970 | 2147 | ||
1971 | spin_lock_init(&host->lock); | 2148 | spin_lock_init(&host->lock); |
@@ -1998,7 +2175,7 @@ int dw_mci_probe(struct dw_mci *host) | |||
1998 | } | 2175 | } |
1999 | 2176 | ||
2000 | /* Reset all blocks */ | 2177 | /* Reset all blocks */ |
2001 | if (!mci_wait_reset(&host->dev, host)) | 2178 | if (!mci_wait_reset(host->dev, host)) |
2002 | return -ENODEV; | 2179 | return -ENODEV; |
2003 | 2180 | ||
2004 | host->dma_ops = host->pdata->dma_ops; | 2181 | host->dma_ops = host->pdata->dma_ops; |
@@ -2054,10 +2231,18 @@ int dw_mci_probe(struct dw_mci *host) | |||
2054 | /* We need at least one slot to succeed */ | 2231 | /* We need at least one slot to succeed */ |
2055 | for (i = 0; i < host->num_slots; i++) { | 2232 | for (i = 0; i < host->num_slots; i++) { |
2056 | ret = dw_mci_init_slot(host, i); | 2233 | ret = dw_mci_init_slot(host, i); |
2057 | if (ret) { | 2234 | if (ret) |
2058 | ret = -ENODEV; | 2235 | dev_dbg(host->dev, "slot %d init failed\n", i); |
2059 | goto err_init_slot; | 2236 | else |
2060 | } | 2237 | init_slots++; |
2238 | } | ||
2239 | |||
2240 | if (init_slots) { | ||
2241 | dev_info(host->dev, "%d slots initialized\n", init_slots); | ||
2242 | } else { | ||
2243 | dev_dbg(host->dev, "attempted to initialize %d slots, " | ||
2244 | "but failed on all\n", host->num_slots); | ||
2245 | goto err_init_slot; | ||
2061 | } | 2246 | } |
2062 | 2247 | ||
2063 | /* | 2248 | /* |
@@ -2065,7 +2250,7 @@ int dw_mci_probe(struct dw_mci *host) | |||
2065 | * Need to check the version-id and set data-offset for DATA register. | 2250 | * Need to check the version-id and set data-offset for DATA register. |
2066 | */ | 2251 | */ |
2067 | host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); | 2252 | host->verid = SDMMC_GET_VERID(mci_readl(host, VERID)); |
2068 | dev_info(&host->dev, "Version ID is %04x\n", host->verid); | 2253 | dev_info(host->dev, "Version ID is %04x\n", host->verid); |
2069 | 2254 | ||
2070 | if (host->verid < DW_MMC_240A) | 2255 | if (host->verid < DW_MMC_240A) |
2071 | host->data_offset = DATA_OFFSET; | 2256 | host->data_offset = DATA_OFFSET; |
@@ -2082,22 +2267,16 @@ int dw_mci_probe(struct dw_mci *host) | |||
2082 | DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); | 2267 | DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); |
2083 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ | 2268 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ |
2084 | 2269 | ||
2085 | dev_info(&host->dev, "DW MMC controller at irq %d, " | 2270 | dev_info(host->dev, "DW MMC controller at irq %d, " |
2086 | "%d bit host data width, " | 2271 | "%d bit host data width, " |
2087 | "%u deep fifo\n", | 2272 | "%u deep fifo\n", |
2088 | host->irq, width, fifo_size); | 2273 | host->irq, width, fifo_size); |
2089 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) | 2274 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) |
2090 | dev_info(&host->dev, "Internal DMAC interrupt fix enabled.\n"); | 2275 | dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); |
2091 | 2276 | ||
2092 | return 0; | 2277 | return 0; |
2093 | 2278 | ||
2094 | err_init_slot: | 2279 | err_init_slot: |
2095 | /* De-init any initialized slots */ | ||
2096 | while (i > 0) { | ||
2097 | if (host->slot[i]) | ||
2098 | dw_mci_cleanup_slot(host->slot[i], i); | ||
2099 | i--; | ||
2100 | } | ||
2101 | free_irq(host->irq, host); | 2280 | free_irq(host->irq, host); |
2102 | 2281 | ||
2103 | err_workqueue: | 2282 | err_workqueue: |
@@ -2106,13 +2285,24 @@ err_workqueue: | |||
2106 | err_dmaunmap: | 2285 | err_dmaunmap: |
2107 | if (host->use_dma && host->dma_ops->exit) | 2286 | if (host->use_dma && host->dma_ops->exit) |
2108 | host->dma_ops->exit(host); | 2287 | host->dma_ops->exit(host); |
2109 | dma_free_coherent(&host->dev, PAGE_SIZE, | 2288 | dma_free_coherent(host->dev, PAGE_SIZE, |
2110 | host->sg_cpu, host->sg_dma); | 2289 | host->sg_cpu, host->sg_dma); |
2111 | 2290 | ||
2112 | if (host->vmmc) { | 2291 | if (host->vmmc) { |
2113 | regulator_disable(host->vmmc); | 2292 | regulator_disable(host->vmmc); |
2114 | regulator_put(host->vmmc); | 2293 | regulator_put(host->vmmc); |
2115 | } | 2294 | } |
2295 | |||
2296 | err_clk_ciu: | ||
2297 | if (!IS_ERR(host->ciu_clk)) { | ||
2298 | clk_disable_unprepare(host->ciu_clk); | ||
2299 | clk_put(host->ciu_clk); | ||
2300 | } | ||
2301 | err_clk_biu: | ||
2302 | if (!IS_ERR(host->biu_clk)) { | ||
2303 | clk_disable_unprepare(host->biu_clk); | ||
2304 | clk_put(host->biu_clk); | ||
2305 | } | ||
2116 | return ret; | 2306 | return ret; |
2117 | } | 2307 | } |
2118 | EXPORT_SYMBOL(dw_mci_probe); | 2308 | EXPORT_SYMBOL(dw_mci_probe); |
@@ -2125,7 +2315,7 @@ void dw_mci_remove(struct dw_mci *host) | |||
2125 | mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ | 2315 | mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ |
2126 | 2316 | ||
2127 | for (i = 0; i < host->num_slots; i++) { | 2317 | for (i = 0; i < host->num_slots; i++) { |
2128 | dev_dbg(&host->dev, "remove slot %d\n", i); | 2318 | dev_dbg(host->dev, "remove slot %d\n", i); |
2129 | if (host->slot[i]) | 2319 | if (host->slot[i]) |
2130 | dw_mci_cleanup_slot(host->slot[i], i); | 2320 | dw_mci_cleanup_slot(host->slot[i], i); |
2131 | } | 2321 | } |
@@ -2136,7 +2326,7 @@ void dw_mci_remove(struct dw_mci *host) | |||
2136 | 2326 | ||
2137 | free_irq(host->irq, host); | 2327 | free_irq(host->irq, host); |
2138 | destroy_workqueue(host->card_workqueue); | 2328 | destroy_workqueue(host->card_workqueue); |
2139 | dma_free_coherent(&host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); | 2329 | dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); |
2140 | 2330 | ||
2141 | if (host->use_dma && host->dma_ops->exit) | 2331 | if (host->use_dma && host->dma_ops->exit) |
2142 | host->dma_ops->exit(host); | 2332 | host->dma_ops->exit(host); |
@@ -2146,6 +2336,12 @@ void dw_mci_remove(struct dw_mci *host) | |||
2146 | regulator_put(host->vmmc); | 2336 | regulator_put(host->vmmc); |
2147 | } | 2337 | } |
2148 | 2338 | ||
2339 | if (!IS_ERR(host->ciu_clk)) | ||
2340 | clk_disable_unprepare(host->ciu_clk); | ||
2341 | if (!IS_ERR(host->biu_clk)) | ||
2342 | clk_disable_unprepare(host->biu_clk); | ||
2343 | clk_put(host->ciu_clk); | ||
2344 | clk_put(host->biu_clk); | ||
2149 | } | 2345 | } |
2150 | EXPORT_SYMBOL(dw_mci_remove); | 2346 | EXPORT_SYMBOL(dw_mci_remove); |
2151 | 2347 | ||
@@ -2188,7 +2384,7 @@ int dw_mci_resume(struct dw_mci *host) | |||
2188 | if (host->vmmc) | 2384 | if (host->vmmc) |
2189 | regulator_enable(host->vmmc); | 2385 | regulator_enable(host->vmmc); |
2190 | 2386 | ||
2191 | if (!mci_wait_reset(&host->dev, host)) { | 2387 | if (!mci_wait_reset(host->dev, host)) { |
2192 | ret = -ENODEV; | 2388 | ret = -ENODEV; |
2193 | return ret; | 2389 | return ret; |
2194 | } | 2390 | } |
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 15c27e17c23f..53b8fd987e47 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h | |||
@@ -182,4 +182,28 @@ extern int dw_mci_suspend(struct dw_mci *host); | |||
182 | extern int dw_mci_resume(struct dw_mci *host); | 182 | extern int dw_mci_resume(struct dw_mci *host); |
183 | #endif | 183 | #endif |
184 | 184 | ||
185 | /** | ||
186 | * dw_mci driver data - dw-mshc implementation specific driver data. | ||
187 | * @caps: mmc subsystem specified capabilities of the controller(s). | ||
188 | * @init: early implementation specific initialization. | ||
189 | * @setup_clock: implementation specific clock configuration. | ||
190 | * @prepare_command: handle CMD register extensions. | ||
191 | * @set_ios: handle bus specific extensions. | ||
192 | * @parse_dt: parse implementation specific device tree properties. | ||
193 | * @setup_bus: initialize io-interface | ||
194 | * | ||
195 | * Provide controller implementation specific extensions. The usage of this | ||
196 | * data structure is fully optional and usage of each member in this structure | ||
197 | * is optional as well. | ||
198 | */ | ||
199 | struct dw_mci_drv_data { | ||
200 | unsigned long *caps; | ||
201 | int (*init)(struct dw_mci *host); | ||
202 | int (*setup_clock)(struct dw_mci *host); | ||
203 | void (*prepare_command)(struct dw_mci *host, u32 *cmdr); | ||
204 | void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); | ||
205 | int (*parse_dt)(struct dw_mci *host); | ||
206 | int (*setup_bus)(struct dw_mci *host, | ||
207 | struct device_node *slot_np, u8 bus_width); | ||
208 | }; | ||
185 | #endif /* _DW_MMC_H_ */ | 209 | #endif /* _DW_MMC_H_ */ |
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 273306c68d58..a600eabbd6c3 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -1532,20 +1532,7 @@ static struct spi_driver mmc_spi_driver = { | |||
1532 | .remove = __devexit_p(mmc_spi_remove), | 1532 | .remove = __devexit_p(mmc_spi_remove), |
1533 | }; | 1533 | }; |
1534 | 1534 | ||
1535 | 1535 | module_spi_driver(mmc_spi_driver); | |
1536 | static int __init mmc_spi_init(void) | ||
1537 | { | ||
1538 | return spi_register_driver(&mmc_spi_driver); | ||
1539 | } | ||
1540 | module_init(mmc_spi_init); | ||
1541 | |||
1542 | |||
1543 | static void __exit mmc_spi_exit(void) | ||
1544 | { | ||
1545 | spi_unregister_driver(&mmc_spi_driver); | ||
1546 | } | ||
1547 | module_exit(mmc_spi_exit); | ||
1548 | |||
1549 | 1536 | ||
1550 | MODULE_AUTHOR("Mike Lavender, David Brownell, " | 1537 | MODULE_AUTHOR("Mike Lavender, David Brownell, " |
1551 | "Hans-Peter Nilsson, Jan Nikitenko"); | 1538 | "Hans-Peter Nilsson, Jan Nikitenko"); |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 50ff19a62368..edc3e9baf0e7 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -1309,14 +1309,10 @@ static int __devinit mmci_probe(struct amba_device *dev, | |||
1309 | goto host_free; | 1309 | goto host_free; |
1310 | } | 1310 | } |
1311 | 1311 | ||
1312 | ret = clk_prepare(host->clk); | 1312 | ret = clk_prepare_enable(host->clk); |
1313 | if (ret) | 1313 | if (ret) |
1314 | goto clk_free; | 1314 | goto clk_free; |
1315 | 1315 | ||
1316 | ret = clk_enable(host->clk); | ||
1317 | if (ret) | ||
1318 | goto clk_unprep; | ||
1319 | |||
1320 | host->plat = plat; | 1316 | host->plat = plat; |
1321 | host->variant = variant; | 1317 | host->variant = variant; |
1322 | host->mclk = clk_get_rate(host->clk); | 1318 | host->mclk = clk_get_rate(host->clk); |
@@ -1515,9 +1511,7 @@ static int __devinit mmci_probe(struct amba_device *dev, | |||
1515 | err_gpio_cd: | 1511 | err_gpio_cd: |
1516 | iounmap(host->base); | 1512 | iounmap(host->base); |
1517 | clk_disable: | 1513 | clk_disable: |
1518 | clk_disable(host->clk); | 1514 | clk_disable_unprepare(host->clk); |
1519 | clk_unprep: | ||
1520 | clk_unprepare(host->clk); | ||
1521 | clk_free: | 1515 | clk_free: |
1522 | clk_put(host->clk); | 1516 | clk_put(host->clk); |
1523 | host_free: | 1517 | host_free: |
@@ -1564,8 +1558,7 @@ static int __devexit mmci_remove(struct amba_device *dev) | |||
1564 | gpio_free(host->gpio_cd); | 1558 | gpio_free(host->gpio_cd); |
1565 | 1559 | ||
1566 | iounmap(host->base); | 1560 | iounmap(host->base); |
1567 | clk_disable(host->clk); | 1561 | clk_disable_unprepare(host->clk); |
1568 | clk_unprepare(host->clk); | ||
1569 | clk_put(host->clk); | 1562 | clk_put(host->clk); |
1570 | 1563 | ||
1571 | if (host->vcc) | 1564 | if (host->vcc) |
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 7b1161de01d6..565c2e4fac75 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <mach/hardware.h> | 44 | #include <mach/hardware.h> |
45 | 45 | ||
46 | #define DRIVER_NAME "mxc-mmc" | 46 | #define DRIVER_NAME "mxc-mmc" |
47 | #define MXCMCI_TIMEOUT_MS 10000 | ||
47 | 48 | ||
48 | #define MMC_REG_STR_STP_CLK 0x00 | 49 | #define MMC_REG_STR_STP_CLK 0x00 |
49 | #define MMC_REG_STATUS 0x04 | 50 | #define MMC_REG_STATUS 0x04 |
@@ -150,6 +151,8 @@ struct mxcmci_host { | |||
150 | int dmareq; | 151 | int dmareq; |
151 | struct dma_slave_config dma_slave_config; | 152 | struct dma_slave_config dma_slave_config; |
152 | struct imx_dma_data dma_data; | 153 | struct imx_dma_data dma_data; |
154 | |||
155 | struct timer_list watchdog; | ||
153 | }; | 156 | }; |
154 | 157 | ||
155 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); | 158 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); |
@@ -271,9 +274,32 @@ static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
271 | dmaengine_submit(host->desc); | 274 | dmaengine_submit(host->desc); |
272 | dma_async_issue_pending(host->dma); | 275 | dma_async_issue_pending(host->dma); |
273 | 276 | ||
277 | mod_timer(&host->watchdog, jiffies + msecs_to_jiffies(MXCMCI_TIMEOUT_MS)); | ||
278 | |||
274 | return 0; | 279 | return 0; |
275 | } | 280 | } |
276 | 281 | ||
282 | static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat); | ||
283 | static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat); | ||
284 | |||
285 | static void mxcmci_dma_callback(void *data) | ||
286 | { | ||
287 | struct mxcmci_host *host = data; | ||
288 | u32 stat; | ||
289 | |||
290 | del_timer(&host->watchdog); | ||
291 | |||
292 | stat = readl(host->base + MMC_REG_STATUS); | ||
293 | writel(stat & ~STATUS_DATA_TRANS_DONE, host->base + MMC_REG_STATUS); | ||
294 | |||
295 | dev_dbg(mmc_dev(host->mmc), "%s: 0x%08x\n", __func__, stat); | ||
296 | |||
297 | if (stat & STATUS_READ_OP_DONE) | ||
298 | writel(STATUS_READ_OP_DONE, host->base + MMC_REG_STATUS); | ||
299 | |||
300 | mxcmci_data_done(host, stat); | ||
301 | } | ||
302 | |||
277 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | 303 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, |
278 | unsigned int cmdat) | 304 | unsigned int cmdat) |
279 | { | 305 | { |
@@ -305,8 +331,14 @@ static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | |||
305 | 331 | ||
306 | int_cntr = INT_END_CMD_RES_EN; | 332 | int_cntr = INT_END_CMD_RES_EN; |
307 | 333 | ||
308 | if (mxcmci_use_dma(host)) | 334 | if (mxcmci_use_dma(host)) { |
309 | int_cntr |= INT_READ_OP_EN | INT_WRITE_OP_DONE_EN; | 335 | if (host->dma_dir == DMA_FROM_DEVICE) { |
336 | host->desc->callback = mxcmci_dma_callback; | ||
337 | host->desc->callback_param = host; | ||
338 | } else { | ||
339 | int_cntr |= INT_WRITE_OP_DONE_EN; | ||
340 | } | ||
341 | } | ||
310 | 342 | ||
311 | spin_lock_irqsave(&host->lock, flags); | 343 | spin_lock_irqsave(&host->lock, flags); |
312 | if (host->use_sdio) | 344 | if (host->use_sdio) |
@@ -345,11 +377,9 @@ static int mxcmci_finish_data(struct mxcmci_host *host, unsigned int stat) | |||
345 | struct mmc_data *data = host->data; | 377 | struct mmc_data *data = host->data; |
346 | int data_error; | 378 | int data_error; |
347 | 379 | ||
348 | if (mxcmci_use_dma(host)) { | 380 | if (mxcmci_use_dma(host)) |
349 | dmaengine_terminate_all(host->dma); | ||
350 | dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, | 381 | dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len, |
351 | host->dma_dir); | 382 | host->dma_dir); |
352 | } | ||
353 | 383 | ||
354 | if (stat & STATUS_ERR_MASK) { | 384 | if (stat & STATUS_ERR_MASK) { |
355 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", | 385 | dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n", |
@@ -624,8 +654,10 @@ static irqreturn_t mxcmci_irq(int irq, void *devid) | |||
624 | mxcmci_cmd_done(host, stat); | 654 | mxcmci_cmd_done(host, stat); |
625 | 655 | ||
626 | if (mxcmci_use_dma(host) && | 656 | if (mxcmci_use_dma(host) && |
627 | (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) | 657 | (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE))) { |
658 | del_timer(&host->watchdog); | ||
628 | mxcmci_data_done(host, stat); | 659 | mxcmci_data_done(host, stat); |
660 | } | ||
629 | 661 | ||
630 | if (host->default_irq_mask && | 662 | if (host->default_irq_mask && |
631 | (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) | 663 | (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL))) |
@@ -836,6 +868,34 @@ static bool filter(struct dma_chan *chan, void *param) | |||
836 | return true; | 868 | return true; |
837 | } | 869 | } |
838 | 870 | ||
871 | static void mxcmci_watchdog(unsigned long data) | ||
872 | { | ||
873 | struct mmc_host *mmc = (struct mmc_host *)data; | ||
874 | struct mxcmci_host *host = mmc_priv(mmc); | ||
875 | struct mmc_request *req = host->req; | ||
876 | unsigned int stat = readl(host->base + MMC_REG_STATUS); | ||
877 | |||
878 | if (host->dma_dir == DMA_FROM_DEVICE) { | ||
879 | dmaengine_terminate_all(host->dma); | ||
880 | dev_err(mmc_dev(host->mmc), | ||
881 | "%s: read time out (status = 0x%08x)\n", | ||
882 | __func__, stat); | ||
883 | } else { | ||
884 | dev_err(mmc_dev(host->mmc), | ||
885 | "%s: write time out (status = 0x%08x)\n", | ||
886 | __func__, stat); | ||
887 | mxcmci_softreset(host); | ||
888 | } | ||
889 | |||
890 | /* Mark transfer as erroneus and inform the upper layers */ | ||
891 | |||
892 | host->data->error = -ETIMEDOUT; | ||
893 | host->req = NULL; | ||
894 | host->cmd = NULL; | ||
895 | host->data = NULL; | ||
896 | mmc_request_done(host->mmc, req); | ||
897 | } | ||
898 | |||
839 | static const struct mmc_host_ops mxcmci_ops = { | 899 | static const struct mmc_host_ops mxcmci_ops = { |
840 | .request = mxcmci_request, | 900 | .request = mxcmci_request, |
841 | .set_ios = mxcmci_set_ios, | 901 | .set_ios = mxcmci_set_ios, |
@@ -968,6 +1028,10 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
968 | 1028 | ||
969 | mmc_add_host(mmc); | 1029 | mmc_add_host(mmc); |
970 | 1030 | ||
1031 | init_timer(&host->watchdog); | ||
1032 | host->watchdog.function = &mxcmci_watchdog; | ||
1033 | host->watchdog.data = (unsigned long)mmc; | ||
1034 | |||
971 | return 0; | 1035 | return 0; |
972 | 1036 | ||
973 | out_free_irq: | 1037 | out_free_irq: |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index c6259a829544..48ad361613ef 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -27,16 +27,10 @@ | |||
27 | #include <linux/mmc/card.h> | 27 | #include <linux/mmc/card.h> |
28 | #include <linux/clk.h> | 28 | #include <linux/clk.h> |
29 | #include <linux/scatterlist.h> | 29 | #include <linux/scatterlist.h> |
30 | #include <linux/i2c/tps65010.h> | ||
31 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
32 | 31 | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/irq.h> | ||
35 | |||
36 | #include <plat/mmc.h> | 32 | #include <plat/mmc.h> |
37 | #include <asm/gpio.h> | ||
38 | #include <plat/dma.h> | 33 | #include <plat/dma.h> |
39 | #include <plat/fpga.h> | ||
40 | 34 | ||
41 | #define OMAP_MMC_REG_CMD 0x00 | 35 | #define OMAP_MMC_REG_CMD 0x00 |
42 | #define OMAP_MMC_REG_ARGL 0x01 | 36 | #define OMAP_MMC_REG_ARGL 0x01 |
@@ -105,7 +99,6 @@ struct mmc_omap_slot { | |||
105 | u16 saved_con; | 99 | u16 saved_con; |
106 | u16 bus_mode; | 100 | u16 bus_mode; |
107 | unsigned int fclk_freq; | 101 | unsigned int fclk_freq; |
108 | unsigned powered:1; | ||
109 | 102 | ||
110 | struct tasklet_struct cover_tasklet; | 103 | struct tasklet_struct cover_tasklet; |
111 | struct timer_list cover_timer; | 104 | struct timer_list cover_timer; |
@@ -137,7 +130,6 @@ struct mmc_omap_host { | |||
137 | unsigned int phys_base; | 130 | unsigned int phys_base; |
138 | int irq; | 131 | int irq; |
139 | unsigned char bus_mode; | 132 | unsigned char bus_mode; |
140 | unsigned char hw_bus_mode; | ||
141 | unsigned int reg_shift; | 133 | unsigned int reg_shift; |
142 | 134 | ||
143 | struct work_struct cmd_abort_work; | 135 | struct work_struct cmd_abort_work; |
@@ -695,22 +687,29 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) | |||
695 | host->buffer += nwords; | 687 | host->buffer += nwords; |
696 | } | 688 | } |
697 | 689 | ||
698 | static inline void mmc_omap_report_irq(u16 status) | 690 | #ifdef CONFIG_MMC_DEBUG |
691 | static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status) | ||
699 | { | 692 | { |
700 | static const char *mmc_omap_status_bits[] = { | 693 | static const char *mmc_omap_status_bits[] = { |
701 | "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO", | 694 | "EOC", "CD", "CB", "BRS", "EOFB", "DTO", "DCRC", "CTO", |
702 | "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR" | 695 | "CCRC", "CRW", "AF", "AE", "OCRB", "CIRQ", "CERR" |
703 | }; | 696 | }; |
704 | int i, c = 0; | 697 | int i; |
698 | char res[64], *buf = res; | ||
699 | |||
700 | buf += sprintf(buf, "MMC IRQ 0x%x:", status); | ||
705 | 701 | ||
706 | for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++) | 702 | for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++) |
707 | if (status & (1 << i)) { | 703 | if (status & (1 << i)) |
708 | if (c) | 704 | buf += sprintf(buf, " %s", mmc_omap_status_bits[i]); |
709 | printk(" "); | 705 | dev_vdbg(mmc_dev(host->mmc), "%s\n", res); |
710 | printk("%s", mmc_omap_status_bits[i]); | ||
711 | c++; | ||
712 | } | ||
713 | } | 706 | } |
707 | #else | ||
708 | static void mmc_omap_report_irq(struct mmc_omap_host *host, u16 status) | ||
709 | { | ||
710 | } | ||
711 | #endif | ||
712 | |||
714 | 713 | ||
715 | static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | 714 | static irqreturn_t mmc_omap_irq(int irq, void *dev_id) |
716 | { | 715 | { |
@@ -744,12 +743,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
744 | cmd = host->cmd->opcode; | 743 | cmd = host->cmd->opcode; |
745 | else | 744 | else |
746 | cmd = -1; | 745 | cmd = -1; |
747 | #ifdef CONFIG_MMC_DEBUG | ||
748 | dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", | 746 | dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", |
749 | status, cmd); | 747 | status, cmd); |
750 | mmc_omap_report_irq(status); | 748 | mmc_omap_report_irq(host, status); |
751 | printk("\n"); | 749 | |
752 | #endif | ||
753 | if (host->total_bytes_left) { | 750 | if (host->total_bytes_left) { |
754 | if ((status & OMAP_MMC_STAT_A_FULL) || | 751 | if ((status & OMAP_MMC_STAT_A_FULL) || |
755 | (status & OMAP_MMC_STAT_END_OF_DATA)) | 752 | (status & OMAP_MMC_STAT_END_OF_DATA)) |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 38adc330c007..54bfd0cc106b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/mmc/core.h> | 35 | #include <linux/mmc/core.h> |
36 | #include <linux/mmc/mmc.h> | 36 | #include <linux/mmc/mmc.h> |
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <linux/semaphore.h> | ||
39 | #include <linux/gpio.h> | 38 | #include <linux/gpio.h> |
40 | #include <linux/regulator/consumer.h> | 39 | #include <linux/regulator/consumer.h> |
41 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
@@ -44,7 +43,6 @@ | |||
44 | #include <plat/cpu.h> | 43 | #include <plat/cpu.h> |
45 | 44 | ||
46 | /* OMAP HSMMC Host Controller Registers */ | 45 | /* OMAP HSMMC Host Controller Registers */ |
47 | #define OMAP_HSMMC_SYSCONFIG 0x0010 | ||
48 | #define OMAP_HSMMC_SYSSTATUS 0x0014 | 46 | #define OMAP_HSMMC_SYSSTATUS 0x0014 |
49 | #define OMAP_HSMMC_CON 0x002C | 47 | #define OMAP_HSMMC_CON 0x002C |
50 | #define OMAP_HSMMC_BLK 0x0104 | 48 | #define OMAP_HSMMC_BLK 0x0104 |
@@ -161,8 +159,6 @@ struct omap_hsmmc_host { | |||
161 | unsigned int dma_sg_idx; | 159 | unsigned int dma_sg_idx; |
162 | unsigned char bus_mode; | 160 | unsigned char bus_mode; |
163 | unsigned char power_mode; | 161 | unsigned char power_mode; |
164 | u32 *buffer; | ||
165 | u32 bytesleft; | ||
166 | int suspended; | 162 | int suspended; |
167 | int irq; | 163 | int irq; |
168 | int use_dma, dma_ch; | 164 | int use_dma, dma_ch; |
@@ -171,7 +167,6 @@ struct omap_hsmmc_host { | |||
171 | int slot_id; | 167 | int slot_id; |
172 | int response_busy; | 168 | int response_busy; |
173 | int context_loss; | 169 | int context_loss; |
174 | int vdd; | ||
175 | int protect_card; | 170 | int protect_card; |
176 | int reqs_blocked; | 171 | int reqs_blocked; |
177 | int use_reg; | 172 | int use_reg; |
@@ -300,12 +295,12 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | |||
300 | struct regulator *reg; | 295 | struct regulator *reg; |
301 | int ocr_value = 0; | 296 | int ocr_value = 0; |
302 | 297 | ||
303 | mmc_slot(host).set_power = omap_hsmmc_set_power; | ||
304 | |||
305 | reg = regulator_get(host->dev, "vmmc"); | 298 | reg = regulator_get(host->dev, "vmmc"); |
306 | if (IS_ERR(reg)) { | 299 | if (IS_ERR(reg)) { |
307 | dev_dbg(host->dev, "vmmc regulator missing\n"); | 300 | dev_dbg(host->dev, "vmmc regulator missing\n"); |
301 | return PTR_ERR(reg); | ||
308 | } else { | 302 | } else { |
303 | mmc_slot(host).set_power = omap_hsmmc_set_power; | ||
309 | host->vcc = reg; | 304 | host->vcc = reg; |
310 | ocr_value = mmc_regulator_get_ocrmask(reg); | 305 | ocr_value = mmc_regulator_get_ocrmask(reg); |
311 | if (!mmc_slot(host).ocr_mask) { | 306 | if (!mmc_slot(host).ocr_mask) { |
@@ -495,7 +490,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) | |||
495 | unsigned long regval; | 490 | unsigned long regval; |
496 | unsigned long timeout; | 491 | unsigned long timeout; |
497 | 492 | ||
498 | dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); | 493 | dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); |
499 | 494 | ||
500 | omap_hsmmc_stop_clock(host); | 495 | omap_hsmmc_stop_clock(host); |
501 | 496 | ||
@@ -579,21 +574,8 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | |||
579 | if (host->context_loss == context_loss) | 574 | if (host->context_loss == context_loss) |
580 | return 1; | 575 | return 1; |
581 | 576 | ||
582 | /* Wait for hardware reset */ | 577 | if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) |
583 | timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); | 578 | return 1; |
584 | while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE | ||
585 | && time_before(jiffies, timeout)) | ||
586 | ; | ||
587 | |||
588 | /* Do software reset */ | ||
589 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, SOFTRESET); | ||
590 | timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); | ||
591 | while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE | ||
592 | && time_before(jiffies, timeout)) | ||
593 | ; | ||
594 | |||
595 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, | ||
596 | OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); | ||
597 | 579 | ||
598 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { | 580 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { |
599 | if (host->power_mode != MMC_POWER_OFF && | 581 | if (host->power_mode != MMC_POWER_OFF && |
@@ -745,7 +727,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | |||
745 | { | 727 | { |
746 | int cmdreg = 0, resptype = 0, cmdtype = 0; | 728 | int cmdreg = 0, resptype = 0, cmdtype = 0; |
747 | 729 | ||
748 | dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", | 730 | dev_vdbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", |
749 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); | 731 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); |
750 | host->cmd = cmd; | 732 | host->cmd = cmd; |
751 | 733 | ||
@@ -934,7 +916,7 @@ static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status) | |||
934 | buf += len; | 916 | buf += len; |
935 | } | 917 | } |
936 | 918 | ||
937 | dev_dbg(mmc_dev(host->mmc), "%s\n", res); | 919 | dev_vdbg(mmc_dev(host->mmc), "%s\n", res); |
938 | } | 920 | } |
939 | #else | 921 | #else |
940 | static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, | 922 | static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, |
@@ -981,72 +963,40 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, | |||
981 | __func__); | 963 | __func__); |
982 | } | 964 | } |
983 | 965 | ||
966 | static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, int err) | ||
967 | { | ||
968 | omap_hsmmc_reset_controller_fsm(host, SRC); | ||
969 | host->cmd->error = err; | ||
970 | |||
971 | if (host->data) { | ||
972 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
973 | omap_hsmmc_dma_cleanup(host, err); | ||
974 | } | ||
975 | |||
976 | } | ||
977 | |||
984 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | 978 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) |
985 | { | 979 | { |
986 | struct mmc_data *data; | 980 | struct mmc_data *data; |
987 | int end_cmd = 0, end_trans = 0; | 981 | int end_cmd = 0, end_trans = 0; |
988 | 982 | ||
989 | if (!host->req_in_progress) { | ||
990 | do { | ||
991 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
992 | /* Flush posted write */ | ||
993 | status = OMAP_HSMMC_READ(host->base, STAT); | ||
994 | } while (status & INT_EN_MASK); | ||
995 | return; | ||
996 | } | ||
997 | |||
998 | data = host->data; | 983 | data = host->data; |
999 | dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); | 984 | dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); |
1000 | 985 | ||
1001 | if (status & ERR) { | 986 | if (status & ERR) { |
1002 | omap_hsmmc_dbg_report_irq(host, status); | 987 | omap_hsmmc_dbg_report_irq(host, status); |
1003 | if ((status & CMD_TIMEOUT) || | 988 | if (status & (CMD_TIMEOUT | DATA_TIMEOUT)) |
1004 | (status & CMD_CRC)) { | 989 | hsmmc_command_incomplete(host, -ETIMEDOUT); |
1005 | if (host->cmd) { | 990 | else if (status & (CMD_CRC | DATA_CRC)) |
1006 | if (status & CMD_TIMEOUT) { | 991 | hsmmc_command_incomplete(host, -EILSEQ); |
1007 | omap_hsmmc_reset_controller_fsm(host, | 992 | |
1008 | SRC); | 993 | end_cmd = 1; |
1009 | host->cmd->error = -ETIMEDOUT; | 994 | if (host->data || host->response_busy) { |
1010 | } else { | 995 | end_trans = 1; |
1011 | host->cmd->error = -EILSEQ; | 996 | host->response_busy = 0; |
1012 | } | ||
1013 | end_cmd = 1; | ||
1014 | } | ||
1015 | if (host->data || host->response_busy) { | ||
1016 | if (host->data) | ||
1017 | omap_hsmmc_dma_cleanup(host, | ||
1018 | -ETIMEDOUT); | ||
1019 | host->response_busy = 0; | ||
1020 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
1021 | } | ||
1022 | } | ||
1023 | if ((status & DATA_TIMEOUT) || | ||
1024 | (status & DATA_CRC)) { | ||
1025 | if (host->data || host->response_busy) { | ||
1026 | int err = (status & DATA_TIMEOUT) ? | ||
1027 | -ETIMEDOUT : -EILSEQ; | ||
1028 | |||
1029 | if (host->data) | ||
1030 | omap_hsmmc_dma_cleanup(host, err); | ||
1031 | else | ||
1032 | host->mrq->cmd->error = err; | ||
1033 | host->response_busy = 0; | ||
1034 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
1035 | end_trans = 1; | ||
1036 | } | ||
1037 | } | ||
1038 | if (status & CARD_ERR) { | ||
1039 | dev_dbg(mmc_dev(host->mmc), | ||
1040 | "Ignoring card err CMD%d\n", host->cmd->opcode); | ||
1041 | if (host->cmd) | ||
1042 | end_cmd = 1; | ||
1043 | if (host->data) | ||
1044 | end_trans = 1; | ||
1045 | } | 997 | } |
1046 | } | 998 | } |
1047 | 999 | ||
1048 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
1049 | |||
1050 | if (end_cmd || ((status & CC) && host->cmd)) | 1000 | if (end_cmd || ((status & CC) && host->cmd)) |
1051 | omap_hsmmc_cmd_done(host, host->cmd); | 1001 | omap_hsmmc_cmd_done(host, host->cmd); |
1052 | if ((end_trans || (status & TC)) && host->mrq) | 1002 | if ((end_trans || (status & TC)) && host->mrq) |
@@ -1062,11 +1012,13 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | |||
1062 | int status; | 1012 | int status; |
1063 | 1013 | ||
1064 | status = OMAP_HSMMC_READ(host->base, STAT); | 1014 | status = OMAP_HSMMC_READ(host->base, STAT); |
1065 | do { | 1015 | while (status & INT_EN_MASK && host->req_in_progress) { |
1066 | omap_hsmmc_do_irq(host, status); | 1016 | omap_hsmmc_do_irq(host, status); |
1017 | |||
1067 | /* Flush posted write */ | 1018 | /* Flush posted write */ |
1019 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
1068 | status = OMAP_HSMMC_READ(host->base, STAT); | 1020 | status = OMAP_HSMMC_READ(host->base, STAT); |
1069 | } while (status & INT_EN_MASK); | 1021 | } |
1070 | 1022 | ||
1071 | return IRQ_HANDLED; | 1023 | return IRQ_HANDLED; |
1072 | } | 1024 | } |
@@ -1501,12 +1453,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1501 | case MMC_POWER_OFF: | 1453 | case MMC_POWER_OFF: |
1502 | mmc_slot(host).set_power(host->dev, host->slot_id, | 1454 | mmc_slot(host).set_power(host->dev, host->slot_id, |
1503 | 0, 0); | 1455 | 0, 0); |
1504 | host->vdd = 0; | ||
1505 | break; | 1456 | break; |
1506 | case MMC_POWER_UP: | 1457 | case MMC_POWER_UP: |
1507 | mmc_slot(host).set_power(host->dev, host->slot_id, | 1458 | mmc_slot(host).set_power(host->dev, host->slot_id, |
1508 | 1, ios->vdd); | 1459 | 1, ios->vdd); |
1509 | host->vdd = ios->vdd; | ||
1510 | break; | 1460 | break; |
1511 | case MMC_POWER_ON: | 1461 | case MMC_POWER_ON: |
1512 | do_send_init_stream = 1; | 1462 | do_send_init_stream = 1; |
@@ -1598,10 +1548,6 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | |||
1598 | value = OMAP_HSMMC_READ(host->base, CAPA); | 1548 | value = OMAP_HSMMC_READ(host->base, CAPA); |
1599 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); | 1549 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); |
1600 | 1550 | ||
1601 | /* Set the controller to AUTO IDLE mode */ | ||
1602 | value = OMAP_HSMMC_READ(host->base, SYSCONFIG); | ||
1603 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE); | ||
1604 | |||
1605 | /* Set SD bus power bit */ | 1551 | /* Set SD bus power bit */ |
1606 | set_sd_bus_power(host); | 1552 | set_sd_bus_power(host); |
1607 | } | 1553 | } |
@@ -1659,8 +1605,6 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) | |||
1659 | 1605 | ||
1660 | pm_runtime_get_sync(host->dev); | 1606 | pm_runtime_get_sync(host->dev); |
1661 | 1607 | ||
1662 | seq_printf(s, "SYSCONFIG:\t0x%08x\n", | ||
1663 | OMAP_HSMMC_READ(host->base, SYSCONFIG)); | ||
1664 | seq_printf(s, "CON:\t\t0x%08x\n", | 1608 | seq_printf(s, "CON:\t\t0x%08x\n", |
1665 | OMAP_HSMMC_READ(host->base, CON)); | 1609 | OMAP_HSMMC_READ(host->base, CON)); |
1666 | seq_printf(s, "HCTL:\t\t0x%08x\n", | 1610 | seq_printf(s, "HCTL:\t\t0x%08x\n", |
@@ -2105,8 +2049,7 @@ static int omap_hsmmc_suspend(struct device *dev) | |||
2105 | if (ret) { | 2049 | if (ret) { |
2106 | host->suspended = 0; | 2050 | host->suspended = 0; |
2107 | if (host->pdata->resume) { | 2051 | if (host->pdata->resume) { |
2108 | ret = host->pdata->resume(dev, host->slot_id); | 2052 | if (host->pdata->resume(dev, host->slot_id)) |
2109 | if (ret) | ||
2110 | dev_dbg(dev, "Unmask interrupt failed\n"); | 2053 | dev_dbg(dev, "Unmask interrupt failed\n"); |
2111 | } | 2054 | } |
2112 | goto err; | 2055 | goto err; |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index ca3915dac03d..3f9d6d577a91 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #include <linux/regulator/consumer.h> | 30 | #include <linux/regulator/consumer.h> |
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/gfp.h> | 32 | #include <linux/gfp.h> |
33 | #include <linux/of.h> | ||
34 | #include <linux/of_gpio.h> | ||
35 | #include <linux/of_device.h> | ||
33 | 36 | ||
34 | #include <asm/sizes.h> | 37 | #include <asm/sizes.h> |
35 | 38 | ||
@@ -573,6 +576,50 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid) | |||
573 | return IRQ_HANDLED; | 576 | return IRQ_HANDLED; |
574 | } | 577 | } |
575 | 578 | ||
579 | #ifdef CONFIG_OF | ||
580 | static const struct of_device_id pxa_mmc_dt_ids[] = { | ||
581 | { .compatible = "marvell,pxa-mmc" }, | ||
582 | { } | ||
583 | }; | ||
584 | |||
585 | MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids); | ||
586 | |||
587 | static int __devinit pxamci_of_init(struct platform_device *pdev) | ||
588 | { | ||
589 | struct device_node *np = pdev->dev.of_node; | ||
590 | struct pxamci_platform_data *pdata; | ||
591 | u32 tmp; | ||
592 | |||
593 | if (!np) | ||
594 | return 0; | ||
595 | |||
596 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
597 | if (!pdata) | ||
598 | return -ENOMEM; | ||
599 | |||
600 | pdata->gpio_card_detect = | ||
601 | of_get_named_gpio(np, "cd-gpios", 0); | ||
602 | pdata->gpio_card_ro = | ||
603 | of_get_named_gpio(np, "wp-gpios", 0); | ||
604 | |||
605 | /* pxa-mmc specific */ | ||
606 | pdata->gpio_power = | ||
607 | of_get_named_gpio(np, "pxa-mmc,gpio-power", 0); | ||
608 | |||
609 | if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0) | ||
610 | pdata->detect_delay_ms = tmp; | ||
611 | |||
612 | pdev->dev.platform_data = pdata; | ||
613 | |||
614 | return 0; | ||
615 | } | ||
616 | #else | ||
617 | static int __devinit pxamci_of_init(struct platform_device *pdev) | ||
618 | { | ||
619 | return 0; | ||
620 | } | ||
621 | #endif | ||
622 | |||
576 | static int pxamci_probe(struct platform_device *pdev) | 623 | static int pxamci_probe(struct platform_device *pdev) |
577 | { | 624 | { |
578 | struct mmc_host *mmc; | 625 | struct mmc_host *mmc; |
@@ -580,6 +627,10 @@ static int pxamci_probe(struct platform_device *pdev) | |||
580 | struct resource *r, *dmarx, *dmatx; | 627 | struct resource *r, *dmarx, *dmatx; |
581 | int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1; | 628 | int ret, irq, gpio_cd = -1, gpio_ro = -1, gpio_power = -1; |
582 | 629 | ||
630 | ret = pxamci_of_init(pdev); | ||
631 | if (ret) | ||
632 | return ret; | ||
633 | |||
583 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 634 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
584 | irq = platform_get_irq(pdev, 0); | 635 | irq = platform_get_irq(pdev, 0); |
585 | if (!r || irq < 0) | 636 | if (!r || irq < 0) |
@@ -866,6 +917,7 @@ static struct platform_driver pxamci_driver = { | |||
866 | .driver = { | 917 | .driver = { |
867 | .name = DRIVER_NAME, | 918 | .name = DRIVER_NAME, |
868 | .owner = THIS_MODULE, | 919 | .owner = THIS_MODULE, |
920 | .of_match_table = of_match_ptr(pxa_mmc_dt_ids), | ||
869 | #ifdef CONFIG_PM | 921 | #ifdef CONFIG_PM |
870 | .pm = &pxamci_pm_ops, | 922 | .pm = &pxamci_pm_ops, |
871 | #endif | 923 | #endif |
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index a6e53a1ebb08..90140eb03e36 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
27 | #include <linux/of.h> | ||
27 | 28 | ||
28 | #include "sdhci-pltfm.h" | 29 | #include "sdhci-pltfm.h" |
29 | 30 | ||
@@ -126,11 +127,18 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev) | |||
126 | return sdhci_pltfm_unregister(pdev); | 127 | return sdhci_pltfm_unregister(pdev); |
127 | } | 128 | } |
128 | 129 | ||
130 | static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { | ||
131 | { .compatible = "marvell,dove-sdhci", }, | ||
132 | {} | ||
133 | }; | ||
134 | MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table); | ||
135 | |||
129 | static struct platform_driver sdhci_dove_driver = { | 136 | static struct platform_driver sdhci_dove_driver = { |
130 | .driver = { | 137 | .driver = { |
131 | .name = "sdhci-dove", | 138 | .name = "sdhci-dove", |
132 | .owner = THIS_MODULE, | 139 | .owner = THIS_MODULE, |
133 | .pm = SDHCI_PLTFM_PMOPS, | 140 | .pm = SDHCI_PLTFM_PMOPS, |
141 | .of_match_table = of_match_ptr(sdhci_dove_of_match_table), | ||
134 | }, | 142 | }, |
135 | .probe = sdhci_dove_probe, | 143 | .probe = sdhci_dove_probe, |
136 | .remove = __devexit_p(sdhci_dove_remove), | 144 | .remove = __devexit_p(sdhci_dove_remove), |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index f8eb1fb0c921..ae5fcbfa1eef 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -21,6 +21,32 @@ | |||
21 | #include "sdhci-pltfm.h" | 21 | #include "sdhci-pltfm.h" |
22 | #include "sdhci-esdhc.h" | 22 | #include "sdhci-esdhc.h" |
23 | 23 | ||
24 | #define VENDOR_V_22 0x12 | ||
25 | static u32 esdhc_readl(struct sdhci_host *host, int reg) | ||
26 | { | ||
27 | u32 ret; | ||
28 | |||
29 | ret = in_be32(host->ioaddr + reg); | ||
30 | /* | ||
31 | * The bit of ADMA flag in eSDHC is not compatible with standard | ||
32 | * SDHC register, so set fake flag SDHCI_CAN_DO_ADMA2 when ADMA is | ||
33 | * supported by eSDHC. | ||
34 | * And for many FSL eSDHC controller, the reset value of field | ||
35 | * SDHCI_CAN_DO_ADMA1 is one, but some of them can't support ADMA, | ||
36 | * only these vendor version is greater than 2.2/0x12 support ADMA. | ||
37 | * For FSL eSDHC, must aligned 4-byte, so use 0xFC to read the | ||
38 | * the verdor version number, oxFE is SDHCI_HOST_VERSION. | ||
39 | */ | ||
40 | if ((reg == SDHCI_CAPABILITIES) && (ret & SDHCI_CAN_DO_ADMA1)) { | ||
41 | u32 tmp = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); | ||
42 | tmp = (tmp & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; | ||
43 | if (tmp > VENDOR_V_22) | ||
44 | ret |= SDHCI_CAN_DO_ADMA2; | ||
45 | } | ||
46 | |||
47 | return ret; | ||
48 | } | ||
49 | |||
24 | static u16 esdhc_readw(struct sdhci_host *host, int reg) | 50 | static u16 esdhc_readw(struct sdhci_host *host, int reg) |
25 | { | 51 | { |
26 | u16 ret; | 52 | u16 ret; |
@@ -144,7 +170,7 @@ static void esdhc_of_resume(struct sdhci_host *host) | |||
144 | #endif | 170 | #endif |
145 | 171 | ||
146 | static struct sdhci_ops sdhci_esdhc_ops = { | 172 | static struct sdhci_ops sdhci_esdhc_ops = { |
147 | .read_l = sdhci_be32bs_readl, | 173 | .read_l = esdhc_readl, |
148 | .read_w = esdhc_readw, | 174 | .read_w = esdhc_readw, |
149 | .read_b = esdhc_readb, | 175 | .read_b = esdhc_readb, |
150 | .write_l = sdhci_be32bs_writel, | 176 | .write_l = sdhci_be32bs_writel, |
@@ -161,9 +187,13 @@ static struct sdhci_ops sdhci_esdhc_ops = { | |||
161 | }; | 187 | }; |
162 | 188 | ||
163 | static struct sdhci_pltfm_data sdhci_esdhc_pdata = { | 189 | static struct sdhci_pltfm_data sdhci_esdhc_pdata = { |
164 | /* card detection could be handled via GPIO */ | 190 | /* |
191 | * card detection could be handled via GPIO | ||
192 | * eSDHC cannot support End Attribute in NOP ADMA descriptor | ||
193 | */ | ||
165 | .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION | 194 | .quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION |
166 | | SDHCI_QUIRK_NO_CARD_NO_RESET, | 195 | | SDHCI_QUIRK_NO_CARD_NO_RESET |
196 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | ||
167 | .ops = &sdhci_esdhc_ops, | 197 | .ops = &sdhci_esdhc_ops, |
168 | }; | 198 | }; |
169 | 199 | ||
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 9722d43d6140..4bb74b042a06 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -1476,24 +1476,7 @@ static struct pci_driver sdhci_driver = { | |||
1476 | }, | 1476 | }, |
1477 | }; | 1477 | }; |
1478 | 1478 | ||
1479 | /*****************************************************************************\ | 1479 | module_pci_driver(sdhci_driver); |
1480 | * * | ||
1481 | * Driver init/exit * | ||
1482 | * * | ||
1483 | \*****************************************************************************/ | ||
1484 | |||
1485 | static int __init sdhci_drv_init(void) | ||
1486 | { | ||
1487 | return pci_register_driver(&sdhci_driver); | ||
1488 | } | ||
1489 | |||
1490 | static void __exit sdhci_drv_exit(void) | ||
1491 | { | ||
1492 | pci_unregister_driver(&sdhci_driver); | ||
1493 | } | ||
1494 | |||
1495 | module_init(sdhci_drv_init); | ||
1496 | module_exit(sdhci_drv_exit); | ||
1497 | 1480 | ||
1498 | MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); | 1481 | MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>"); |
1499 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver"); | 1482 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver"); |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index d9a4ef4f1ed0..65551a9709cc 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -75,6 +75,9 @@ void sdhci_get_of_property(struct platform_device *pdev) | |||
75 | if (sdhci_of_wp_inverted(np)) | 75 | if (sdhci_of_wp_inverted(np)) |
76 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; | 76 | host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; |
77 | 77 | ||
78 | if (of_get_property(np, "broken-cd", NULL)) | ||
79 | host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; | ||
80 | |||
78 | if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) | 81 | if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) |
79 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; | 82 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; |
80 | 83 | ||
diff --git a/drivers/mmc/host/sdhci-pxav2.c b/drivers/mmc/host/sdhci-pxav2.c index b6ee8857e226..8e63a9c04e31 100644 --- a/drivers/mmc/host/sdhci-pxav2.c +++ b/drivers/mmc/host/sdhci-pxav2.c | |||
@@ -197,7 +197,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) | |||
197 | goto err_clk_get; | 197 | goto err_clk_get; |
198 | } | 198 | } |
199 | pltfm_host->clk = clk; | 199 | pltfm_host->clk = clk; |
200 | clk_enable(clk); | 200 | clk_prepare_enable(clk); |
201 | 201 | ||
202 | host->quirks = SDHCI_QUIRK_BROKEN_ADMA | 202 | host->quirks = SDHCI_QUIRK_BROKEN_ADMA |
203 | | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 203 | | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
@@ -239,7 +239,7 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev) | |||
239 | return 0; | 239 | return 0; |
240 | 240 | ||
241 | err_add_host: | 241 | err_add_host: |
242 | clk_disable(clk); | 242 | clk_disable_unprepare(clk); |
243 | clk_put(clk); | 243 | clk_put(clk); |
244 | err_clk_get: | 244 | err_clk_get: |
245 | sdhci_pltfm_free(pdev); | 245 | sdhci_pltfm_free(pdev); |
@@ -255,7 +255,7 @@ static int __devexit sdhci_pxav2_remove(struct platform_device *pdev) | |||
255 | 255 | ||
256 | sdhci_remove_host(host, 1); | 256 | sdhci_remove_host(host, 1); |
257 | 257 | ||
258 | clk_disable(pltfm_host->clk); | 258 | clk_disable_unprepare(pltfm_host->clk); |
259 | clk_put(pltfm_host->clk); | 259 | clk_put(pltfm_host->clk); |
260 | sdhci_pltfm_free(pdev); | 260 | sdhci_pltfm_free(pdev); |
261 | kfree(pxa); | 261 | kfree(pxa); |
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c index 07fe3834fe0b..e918a2bb3af1 100644 --- a/drivers/mmc/host/sdhci-pxav3.c +++ b/drivers/mmc/host/sdhci-pxav3.c | |||
@@ -24,12 +24,14 @@ | |||
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <linux/mmc/card.h> | 25 | #include <linux/mmc/card.h> |
26 | #include <linux/mmc/host.h> | 26 | #include <linux/mmc/host.h> |
27 | #include <linux/mmc/slot-gpio.h> | ||
27 | #include <linux/platform_data/pxa_sdhci.h> | 28 | #include <linux/platform_data/pxa_sdhci.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/module.h> | 31 | #include <linux/module.h> |
31 | #include <linux/of.h> | 32 | #include <linux/of.h> |
32 | #include <linux/of_device.h> | 33 | #include <linux/of_device.h> |
34 | #include <linux/of_gpio.h> | ||
33 | 35 | ||
34 | #include "sdhci.h" | 36 | #include "sdhci.h" |
35 | #include "sdhci-pltfm.h" | 37 | #include "sdhci-pltfm.h" |
@@ -182,6 +184,7 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) | |||
182 | struct device_node *np = dev->of_node; | 184 | struct device_node *np = dev->of_node; |
183 | u32 bus_width; | 185 | u32 bus_width; |
184 | u32 clk_delay_cycles; | 186 | u32 clk_delay_cycles; |
187 | enum of_gpio_flags gpio_flags; | ||
185 | 188 | ||
186 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 189 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
187 | if (!pdata) | 190 | if (!pdata) |
@@ -198,6 +201,10 @@ static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev) | |||
198 | if (clk_delay_cycles > 0) | 201 | if (clk_delay_cycles > 0) |
199 | pdata->clk_delay_cycles = clk_delay_cycles; | 202 | pdata->clk_delay_cycles = clk_delay_cycles; |
200 | 203 | ||
204 | pdata->ext_cd_gpio = of_get_named_gpio_flags(np, "cd-gpios", 0, &gpio_flags); | ||
205 | if (gpio_flags != OF_GPIO_ACTIVE_LOW) | ||
206 | pdata->host_caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; | ||
207 | |||
201 | return pdata; | 208 | return pdata; |
202 | } | 209 | } |
203 | #else | 210 | #else |
@@ -231,14 +238,14 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
231 | pltfm_host = sdhci_priv(host); | 238 | pltfm_host = sdhci_priv(host); |
232 | pltfm_host->priv = pxa; | 239 | pltfm_host->priv = pxa; |
233 | 240 | ||
234 | clk = clk_get(dev, "PXA-SDHCLK"); | 241 | clk = clk_get(dev, NULL); |
235 | if (IS_ERR(clk)) { | 242 | if (IS_ERR(clk)) { |
236 | dev_err(dev, "failed to get io clock\n"); | 243 | dev_err(dev, "failed to get io clock\n"); |
237 | ret = PTR_ERR(clk); | 244 | ret = PTR_ERR(clk); |
238 | goto err_clk_get; | 245 | goto err_clk_get; |
239 | } | 246 | } |
240 | pltfm_host->clk = clk; | 247 | pltfm_host->clk = clk; |
241 | clk_enable(clk); | 248 | clk_prepare_enable(clk); |
242 | 249 | ||
243 | host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 250 | host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
244 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 251 | | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
@@ -266,12 +273,25 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
266 | host->quirks |= pdata->quirks; | 273 | host->quirks |= pdata->quirks; |
267 | if (pdata->host_caps) | 274 | if (pdata->host_caps) |
268 | host->mmc->caps |= pdata->host_caps; | 275 | host->mmc->caps |= pdata->host_caps; |
276 | if (pdata->host_caps2) | ||
277 | host->mmc->caps2 |= pdata->host_caps2; | ||
269 | if (pdata->pm_caps) | 278 | if (pdata->pm_caps) |
270 | host->mmc->pm_caps |= pdata->pm_caps; | 279 | host->mmc->pm_caps |= pdata->pm_caps; |
280 | |||
281 | if (gpio_is_valid(pdata->ext_cd_gpio)) { | ||
282 | ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio); | ||
283 | if (ret) { | ||
284 | dev_err(mmc_dev(host->mmc), | ||
285 | "failed to allocate card detect gpio\n"); | ||
286 | goto err_cd_req; | ||
287 | } | ||
288 | } | ||
271 | } | 289 | } |
272 | 290 | ||
273 | host->ops = &pxav3_sdhci_ops; | 291 | host->ops = &pxav3_sdhci_ops; |
274 | 292 | ||
293 | sdhci_get_of_property(pdev); | ||
294 | |||
275 | ret = sdhci_add_host(host); | 295 | ret = sdhci_add_host(host); |
276 | if (ret) { | 296 | if (ret) { |
277 | dev_err(&pdev->dev, "failed to add host\n"); | 297 | dev_err(&pdev->dev, "failed to add host\n"); |
@@ -283,8 +303,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev) | |||
283 | return 0; | 303 | return 0; |
284 | 304 | ||
285 | err_add_host: | 305 | err_add_host: |
286 | clk_disable(clk); | 306 | clk_disable_unprepare(clk); |
287 | clk_put(clk); | 307 | clk_put(clk); |
308 | mmc_gpio_free_cd(host->mmc); | ||
309 | err_cd_req: | ||
288 | err_clk_get: | 310 | err_clk_get: |
289 | sdhci_pltfm_free(pdev); | 311 | sdhci_pltfm_free(pdev); |
290 | kfree(pxa); | 312 | kfree(pxa); |
@@ -296,11 +318,16 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev) | |||
296 | struct sdhci_host *host = platform_get_drvdata(pdev); | 318 | struct sdhci_host *host = platform_get_drvdata(pdev); |
297 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | 319 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); |
298 | struct sdhci_pxa *pxa = pltfm_host->priv; | 320 | struct sdhci_pxa *pxa = pltfm_host->priv; |
321 | struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; | ||
299 | 322 | ||
300 | sdhci_remove_host(host, 1); | 323 | sdhci_remove_host(host, 1); |
301 | 324 | ||
302 | clk_disable(pltfm_host->clk); | 325 | clk_disable_unprepare(pltfm_host->clk); |
303 | clk_put(pltfm_host->clk); | 326 | clk_put(pltfm_host->clk); |
327 | |||
328 | if (gpio_is_valid(pdata->ext_cd_gpio)) | ||
329 | mmc_gpio_free_cd(host->mmc); | ||
330 | |||
304 | sdhci_pltfm_free(pdev); | 331 | sdhci_pltfm_free(pdev); |
305 | kfree(pxa); | 332 | kfree(pxa); |
306 | 333 | ||
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index a50c205ea208..2903949594c6 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -34,6 +34,9 @@ | |||
34 | 34 | ||
35 | #define MAX_BUS_CLK (4) | 35 | #define MAX_BUS_CLK (4) |
36 | 36 | ||
37 | /* Number of gpio's used is max data bus width + command and clock lines */ | ||
38 | #define NUM_GPIOS(x) (x + 2) | ||
39 | |||
37 | /** | 40 | /** |
38 | * struct sdhci_s3c - S3C SDHCI instance | 41 | * struct sdhci_s3c - S3C SDHCI instance |
39 | * @host: The SDHCI host created | 42 | * @host: The SDHCI host created |
@@ -41,6 +44,7 @@ | |||
41 | * @ioarea: The resource created when we claimed the IO area. | 44 | * @ioarea: The resource created when we claimed the IO area. |
42 | * @pdata: The platform data for this controller. | 45 | * @pdata: The platform data for this controller. |
43 | * @cur_clk: The index of the current bus clock. | 46 | * @cur_clk: The index of the current bus clock. |
47 | * @gpios: List of gpio numbers parsed from device tree. | ||
44 | * @clk_io: The clock for the internal bus interface. | 48 | * @clk_io: The clock for the internal bus interface. |
45 | * @clk_bus: The clocks that are available for the SD/MMC bus clock. | 49 | * @clk_bus: The clocks that are available for the SD/MMC bus clock. |
46 | */ | 50 | */ |
@@ -52,6 +56,7 @@ struct sdhci_s3c { | |||
52 | unsigned int cur_clk; | 56 | unsigned int cur_clk; |
53 | int ext_cd_irq; | 57 | int ext_cd_irq; |
54 | int ext_cd_gpio; | 58 | int ext_cd_gpio; |
59 | int *gpios; | ||
55 | 60 | ||
56 | struct clk *clk_io; | 61 | struct clk *clk_io; |
57 | struct clk *clk_bus[MAX_BUS_CLK]; | 62 | struct clk *clk_bus[MAX_BUS_CLK]; |
@@ -166,7 +171,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, | |||
166 | dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", | 171 | dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n", |
167 | src, rate, wanted, rate / div); | 172 | src, rate, wanted, rate / div); |
168 | 173 | ||
169 | return (wanted - (rate / div)); | 174 | return wanted - (rate / div); |
170 | } | 175 | } |
171 | 176 | ||
172 | /** | 177 | /** |
@@ -203,10 +208,12 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) | |||
203 | best_src, clock, best); | 208 | best_src, clock, best); |
204 | 209 | ||
205 | /* select the new clock source */ | 210 | /* select the new clock source */ |
206 | |||
207 | if (ourhost->cur_clk != best_src) { | 211 | if (ourhost->cur_clk != best_src) { |
208 | struct clk *clk = ourhost->clk_bus[best_src]; | 212 | struct clk *clk = ourhost->clk_bus[best_src]; |
209 | 213 | ||
214 | clk_enable(clk); | ||
215 | clk_disable(ourhost->clk_bus[ourhost->cur_clk]); | ||
216 | |||
210 | /* turn clock off to card before changing clock source */ | 217 | /* turn clock off to card before changing clock source */ |
211 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); | 218 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); |
212 | 219 | ||
@@ -288,6 +295,7 @@ static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host) | |||
288 | static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | 295 | static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) |
289 | { | 296 | { |
290 | struct sdhci_s3c *ourhost = to_s3c(host); | 297 | struct sdhci_s3c *ourhost = to_s3c(host); |
298 | struct device *dev = &ourhost->pdev->dev; | ||
291 | unsigned long timeout; | 299 | unsigned long timeout; |
292 | u16 clk = 0; | 300 | u16 clk = 0; |
293 | 301 | ||
@@ -309,8 +317,8 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | |||
309 | while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) | 317 | while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) |
310 | & SDHCI_CLOCK_INT_STABLE)) { | 318 | & SDHCI_CLOCK_INT_STABLE)) { |
311 | if (timeout == 0) { | 319 | if (timeout == 0) { |
312 | printk(KERN_ERR "%s: Internal clock never " | 320 | dev_err(dev, "%s: Internal clock never stabilised.\n", |
313 | "stabilised.\n", mmc_hostname(host->mmc)); | 321 | mmc_hostname(host->mmc)); |
314 | return; | 322 | return; |
315 | } | 323 | } |
316 | timeout--; | 324 | timeout--; |
@@ -404,7 +412,9 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc) | |||
404 | if (sc->ext_cd_irq && | 412 | if (sc->ext_cd_irq && |
405 | request_threaded_irq(sc->ext_cd_irq, NULL, | 413 | request_threaded_irq(sc->ext_cd_irq, NULL, |
406 | sdhci_s3c_gpio_card_detect_thread, | 414 | sdhci_s3c_gpio_card_detect_thread, |
407 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 415 | IRQF_TRIGGER_RISING | |
416 | IRQF_TRIGGER_FALLING | | ||
417 | IRQF_ONESHOT, | ||
408 | dev_name(dev), sc) == 0) { | 418 | dev_name(dev), sc) == 0) { |
409 | int status = gpio_get_value(sc->ext_cd_gpio); | 419 | int status = gpio_get_value(sc->ext_cd_gpio); |
410 | if (pdata->ext_cd_gpio_invert) | 420 | if (pdata->ext_cd_gpio_invert) |
@@ -419,9 +429,121 @@ static void sdhci_s3c_setup_card_detect_gpio(struct sdhci_s3c *sc) | |||
419 | } | 429 | } |
420 | } | 430 | } |
421 | 431 | ||
432 | #ifdef CONFIG_OF | ||
433 | static int __devinit sdhci_s3c_parse_dt(struct device *dev, | ||
434 | struct sdhci_host *host, struct s3c_sdhci_platdata *pdata) | ||
435 | { | ||
436 | struct device_node *node = dev->of_node; | ||
437 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
438 | u32 max_width; | ||
439 | int gpio, cnt, ret; | ||
440 | |||
441 | /* if the bus-width property is not specified, assume width as 1 */ | ||
442 | if (of_property_read_u32(node, "bus-width", &max_width)) | ||
443 | max_width = 1; | ||
444 | pdata->max_width = max_width; | ||
445 | |||
446 | ourhost->gpios = devm_kzalloc(dev, NUM_GPIOS(pdata->max_width) * | ||
447 | sizeof(int), GFP_KERNEL); | ||
448 | if (!ourhost->gpios) | ||
449 | return -ENOMEM; | ||
450 | |||
451 | /* get the card detection method */ | ||
452 | if (of_get_property(node, "broken-cd", 0)) { | ||
453 | pdata->cd_type = S3C_SDHCI_CD_NONE; | ||
454 | goto setup_bus; | ||
455 | } | ||
456 | |||
457 | if (of_get_property(node, "non-removable", 0)) { | ||
458 | pdata->cd_type = S3C_SDHCI_CD_PERMANENT; | ||
459 | goto setup_bus; | ||
460 | } | ||
461 | |||
462 | gpio = of_get_named_gpio(node, "cd-gpios", 0); | ||
463 | if (gpio_is_valid(gpio)) { | ||
464 | pdata->cd_type = S3C_SDHCI_CD_GPIO; | ||
465 | goto found_cd; | ||
466 | } else if (gpio != -ENOENT) { | ||
467 | dev_err(dev, "invalid card detect gpio specified\n"); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | |||
471 | gpio = of_get_named_gpio(node, "samsung,cd-pinmux-gpio", 0); | ||
472 | if (gpio_is_valid(gpio)) { | ||
473 | pdata->cd_type = S3C_SDHCI_CD_INTERNAL; | ||
474 | goto found_cd; | ||
475 | } else if (gpio != -ENOENT) { | ||
476 | dev_err(dev, "invalid card detect gpio specified\n"); | ||
477 | return -EINVAL; | ||
478 | } | ||
479 | |||
480 | dev_info(dev, "assuming no card detect line available\n"); | ||
481 | pdata->cd_type = S3C_SDHCI_CD_NONE; | ||
482 | |||
483 | found_cd: | ||
484 | if (pdata->cd_type == S3C_SDHCI_CD_GPIO) { | ||
485 | pdata->ext_cd_gpio = gpio; | ||
486 | ourhost->ext_cd_gpio = -1; | ||
487 | if (of_get_property(node, "cd-inverted", NULL)) | ||
488 | pdata->ext_cd_gpio_invert = 1; | ||
489 | } else if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) { | ||
490 | ret = gpio_request(gpio, "sdhci-cd"); | ||
491 | if (ret) { | ||
492 | dev_err(dev, "card detect gpio request failed\n"); | ||
493 | return -EINVAL; | ||
494 | } | ||
495 | ourhost->ext_cd_gpio = gpio; | ||
496 | } | ||
497 | |||
498 | setup_bus: | ||
499 | /* get the gpios for command, clock and data lines */ | ||
500 | for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) { | ||
501 | gpio = of_get_gpio(node, cnt); | ||
502 | if (!gpio_is_valid(gpio)) { | ||
503 | dev_err(dev, "invalid gpio[%d]\n", cnt); | ||
504 | goto err_free_dt_cd_gpio; | ||
505 | } | ||
506 | ourhost->gpios[cnt] = gpio; | ||
507 | } | ||
508 | |||
509 | for (cnt = 0; cnt < NUM_GPIOS(pdata->max_width); cnt++) { | ||
510 | ret = gpio_request(ourhost->gpios[cnt], "sdhci-gpio"); | ||
511 | if (ret) { | ||
512 | dev_err(dev, "gpio[%d] request failed\n", cnt); | ||
513 | goto err_free_dt_gpios; | ||
514 | } | ||
515 | } | ||
516 | |||
517 | return 0; | ||
518 | |||
519 | err_free_dt_gpios: | ||
520 | while (--cnt >= 0) | ||
521 | gpio_free(ourhost->gpios[cnt]); | ||
522 | err_free_dt_cd_gpio: | ||
523 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) | ||
524 | gpio_free(ourhost->ext_cd_gpio); | ||
525 | return -EINVAL; | ||
526 | } | ||
527 | #else | ||
528 | static int __devinit sdhci_s3c_parse_dt(struct device *dev, | ||
529 | struct sdhci_host *host, struct s3c_sdhci_platdata *pdata) | ||
530 | { | ||
531 | return -EINVAL; | ||
532 | } | ||
533 | #endif | ||
534 | |||
535 | static const struct of_device_id sdhci_s3c_dt_match[]; | ||
536 | |||
422 | static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( | 537 | static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( |
423 | struct platform_device *pdev) | 538 | struct platform_device *pdev) |
424 | { | 539 | { |
540 | #ifdef CONFIG_OF | ||
541 | if (pdev->dev.of_node) { | ||
542 | const struct of_device_id *match; | ||
543 | match = of_match_node(sdhci_s3c_dt_match, pdev->dev.of_node); | ||
544 | return (struct sdhci_s3c_drv_data *)match->data; | ||
545 | } | ||
546 | #endif | ||
425 | return (struct sdhci_s3c_drv_data *) | 547 | return (struct sdhci_s3c_drv_data *) |
426 | platform_get_device_id(pdev)->driver_data; | 548 | platform_get_device_id(pdev)->driver_data; |
427 | } | 549 | } |
@@ -436,7 +558,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
436 | struct resource *res; | 558 | struct resource *res; |
437 | int ret, irq, ptr, clks; | 559 | int ret, irq, ptr, clks; |
438 | 560 | ||
439 | if (!pdev->dev.platform_data) { | 561 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { |
440 | dev_err(dev, "no device data specified\n"); | 562 | dev_err(dev, "no device data specified\n"); |
441 | return -ENOENT; | 563 | return -ENOENT; |
442 | } | 564 | } |
@@ -452,21 +574,28 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
452 | dev_err(dev, "sdhci_alloc_host() failed\n"); | 574 | dev_err(dev, "sdhci_alloc_host() failed\n"); |
453 | return PTR_ERR(host); | 575 | return PTR_ERR(host); |
454 | } | 576 | } |
577 | sc = sdhci_priv(host); | ||
455 | 578 | ||
456 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | 579 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); |
457 | if (!pdata) { | 580 | if (!pdata) { |
458 | ret = -ENOMEM; | 581 | ret = -ENOMEM; |
459 | goto err_io_clk; | 582 | goto err_pdata; |
583 | } | ||
584 | |||
585 | if (pdev->dev.of_node) { | ||
586 | ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata); | ||
587 | if (ret) | ||
588 | goto err_pdata; | ||
589 | } else { | ||
590 | memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); | ||
591 | sc->ext_cd_gpio = -1; /* invalid gpio number */ | ||
460 | } | 592 | } |
461 | memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); | ||
462 | 593 | ||
463 | drv_data = sdhci_s3c_get_driver_data(pdev); | 594 | drv_data = sdhci_s3c_get_driver_data(pdev); |
464 | sc = sdhci_priv(host); | ||
465 | 595 | ||
466 | sc->host = host; | 596 | sc->host = host; |
467 | sc->pdev = pdev; | 597 | sc->pdev = pdev; |
468 | sc->pdata = pdata; | 598 | sc->pdata = pdata; |
469 | sc->ext_cd_gpio = -1; /* invalid gpio number */ | ||
470 | 599 | ||
471 | platform_set_drvdata(pdev, host); | 600 | platform_set_drvdata(pdev, host); |
472 | 601 | ||
@@ -486,9 +615,8 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
486 | 615 | ||
487 | snprintf(name, 14, "mmc_busclk.%d", ptr); | 616 | snprintf(name, 14, "mmc_busclk.%d", ptr); |
488 | clk = clk_get(dev, name); | 617 | clk = clk_get(dev, name); |
489 | if (IS_ERR(clk)) { | 618 | if (IS_ERR(clk)) |
490 | continue; | 619 | continue; |
491 | } | ||
492 | 620 | ||
493 | clks++; | 621 | clks++; |
494 | sc->clk_bus[ptr] = clk; | 622 | sc->clk_bus[ptr] = clk; |
@@ -499,8 +627,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
499 | */ | 627 | */ |
500 | sc->cur_clk = ptr; | 628 | sc->cur_clk = ptr; |
501 | 629 | ||
502 | clk_enable(clk); | ||
503 | |||
504 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", | 630 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", |
505 | ptr, name, clk_get_rate(clk)); | 631 | ptr, name, clk_get_rate(clk)); |
506 | } | 632 | } |
@@ -511,6 +637,10 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
511 | goto err_no_busclks; | 637 | goto err_no_busclks; |
512 | } | 638 | } |
513 | 639 | ||
640 | #ifndef CONFIG_PM_RUNTIME | ||
641 | clk_enable(sc->clk_bus[sc->cur_clk]); | ||
642 | #endif | ||
643 | |||
514 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 644 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
515 | host->ioaddr = devm_request_and_ioremap(&pdev->dev, res); | 645 | host->ioaddr = devm_request_and_ioremap(&pdev->dev, res); |
516 | if (!host->ioaddr) { | 646 | if (!host->ioaddr) { |
@@ -616,12 +746,17 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
616 | gpio_is_valid(pdata->ext_cd_gpio)) | 746 | gpio_is_valid(pdata->ext_cd_gpio)) |
617 | sdhci_s3c_setup_card_detect_gpio(sc); | 747 | sdhci_s3c_setup_card_detect_gpio(sc); |
618 | 748 | ||
749 | #ifdef CONFIG_PM_RUNTIME | ||
750 | clk_disable(sc->clk_io); | ||
751 | #endif | ||
619 | return 0; | 752 | return 0; |
620 | 753 | ||
621 | err_req_regs: | 754 | err_req_regs: |
755 | #ifndef CONFIG_PM_RUNTIME | ||
756 | clk_disable(sc->clk_bus[sc->cur_clk]); | ||
757 | #endif | ||
622 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | 758 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { |
623 | if (sc->clk_bus[ptr]) { | 759 | if (sc->clk_bus[ptr]) { |
624 | clk_disable(sc->clk_bus[ptr]); | ||
625 | clk_put(sc->clk_bus[ptr]); | 760 | clk_put(sc->clk_bus[ptr]); |
626 | } | 761 | } |
627 | } | 762 | } |
@@ -631,6 +766,12 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
631 | clk_put(sc->clk_io); | 766 | clk_put(sc->clk_io); |
632 | 767 | ||
633 | err_io_clk: | 768 | err_io_clk: |
769 | for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++) | ||
770 | gpio_free(sc->gpios[ptr]); | ||
771 | if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) | ||
772 | gpio_free(sc->ext_cd_gpio); | ||
773 | |||
774 | err_pdata: | ||
634 | sdhci_free_host(host); | 775 | sdhci_free_host(host); |
635 | 776 | ||
636 | return ret; | 777 | return ret; |
@@ -638,9 +779,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
638 | 779 | ||
639 | static int __devexit sdhci_s3c_remove(struct platform_device *pdev) | 780 | static int __devexit sdhci_s3c_remove(struct platform_device *pdev) |
640 | { | 781 | { |
641 | struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; | ||
642 | struct sdhci_host *host = platform_get_drvdata(pdev); | 782 | struct sdhci_host *host = platform_get_drvdata(pdev); |
643 | struct sdhci_s3c *sc = sdhci_priv(host); | 783 | struct sdhci_s3c *sc = sdhci_priv(host); |
784 | struct s3c_sdhci_platdata *pdata = sc->pdata; | ||
644 | int ptr; | 785 | int ptr; |
645 | 786 | ||
646 | if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) | 787 | if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_cleanup) |
@@ -652,19 +793,30 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) | |||
652 | if (gpio_is_valid(sc->ext_cd_gpio)) | 793 | if (gpio_is_valid(sc->ext_cd_gpio)) |
653 | gpio_free(sc->ext_cd_gpio); | 794 | gpio_free(sc->ext_cd_gpio); |
654 | 795 | ||
796 | #ifdef CONFIG_PM_RUNTIME | ||
797 | clk_enable(sc->clk_io); | ||
798 | #endif | ||
655 | sdhci_remove_host(host, 1); | 799 | sdhci_remove_host(host, 1); |
656 | 800 | ||
801 | pm_runtime_dont_use_autosuspend(&pdev->dev); | ||
657 | pm_runtime_disable(&pdev->dev); | 802 | pm_runtime_disable(&pdev->dev); |
658 | 803 | ||
659 | for (ptr = 0; ptr < 3; ptr++) { | 804 | #ifndef CONFIG_PM_RUNTIME |
805 | clk_disable(sc->clk_bus[sc->cur_clk]); | ||
806 | #endif | ||
807 | for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { | ||
660 | if (sc->clk_bus[ptr]) { | 808 | if (sc->clk_bus[ptr]) { |
661 | clk_disable(sc->clk_bus[ptr]); | ||
662 | clk_put(sc->clk_bus[ptr]); | 809 | clk_put(sc->clk_bus[ptr]); |
663 | } | 810 | } |
664 | } | 811 | } |
665 | clk_disable(sc->clk_io); | 812 | clk_disable(sc->clk_io); |
666 | clk_put(sc->clk_io); | 813 | clk_put(sc->clk_io); |
667 | 814 | ||
815 | if (pdev->dev.of_node) { | ||
816 | for (ptr = 0; ptr < NUM_GPIOS(sc->pdata->max_width); ptr++) | ||
817 | gpio_free(sc->gpios[ptr]); | ||
818 | } | ||
819 | |||
668 | sdhci_free_host(host); | 820 | sdhci_free_host(host); |
669 | platform_set_drvdata(pdev, NULL); | 821 | platform_set_drvdata(pdev, NULL); |
670 | 822 | ||
@@ -691,15 +843,28 @@ static int sdhci_s3c_resume(struct device *dev) | |||
691 | static int sdhci_s3c_runtime_suspend(struct device *dev) | 843 | static int sdhci_s3c_runtime_suspend(struct device *dev) |
692 | { | 844 | { |
693 | struct sdhci_host *host = dev_get_drvdata(dev); | 845 | struct sdhci_host *host = dev_get_drvdata(dev); |
846 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
847 | struct clk *busclk = ourhost->clk_io; | ||
848 | int ret; | ||
849 | |||
850 | ret = sdhci_runtime_suspend_host(host); | ||
694 | 851 | ||
695 | return sdhci_runtime_suspend_host(host); | 852 | clk_disable(ourhost->clk_bus[ourhost->cur_clk]); |
853 | clk_disable(busclk); | ||
854 | return ret; | ||
696 | } | 855 | } |
697 | 856 | ||
698 | static int sdhci_s3c_runtime_resume(struct device *dev) | 857 | static int sdhci_s3c_runtime_resume(struct device *dev) |
699 | { | 858 | { |
700 | struct sdhci_host *host = dev_get_drvdata(dev); | 859 | struct sdhci_host *host = dev_get_drvdata(dev); |
860 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
861 | struct clk *busclk = ourhost->clk_io; | ||
862 | int ret; | ||
701 | 863 | ||
702 | return sdhci_runtime_resume_host(host); | 864 | clk_enable(busclk); |
865 | clk_enable(ourhost->clk_bus[ourhost->cur_clk]); | ||
866 | ret = sdhci_runtime_resume_host(host); | ||
867 | return ret; | ||
703 | } | 868 | } |
704 | #endif | 869 | #endif |
705 | 870 | ||
@@ -737,6 +902,16 @@ static struct platform_device_id sdhci_s3c_driver_ids[] = { | |||
737 | }; | 902 | }; |
738 | MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids); | 903 | MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids); |
739 | 904 | ||
905 | #ifdef CONFIG_OF | ||
906 | static const struct of_device_id sdhci_s3c_dt_match[] = { | ||
907 | { .compatible = "samsung,s3c6410-sdhci", }, | ||
908 | { .compatible = "samsung,exynos4210-sdhci", | ||
909 | .data = (void *)EXYNOS4_SDHCI_DRV_DATA }, | ||
910 | {}, | ||
911 | }; | ||
912 | MODULE_DEVICE_TABLE(of, sdhci_s3c_dt_match); | ||
913 | #endif | ||
914 | |||
740 | static struct platform_driver sdhci_s3c_driver = { | 915 | static struct platform_driver sdhci_s3c_driver = { |
741 | .probe = sdhci_s3c_probe, | 916 | .probe = sdhci_s3c_probe, |
742 | .remove = __devexit_p(sdhci_s3c_remove), | 917 | .remove = __devexit_p(sdhci_s3c_remove), |
@@ -744,6 +919,7 @@ static struct platform_driver sdhci_s3c_driver = { | |||
744 | .driver = { | 919 | .driver = { |
745 | .owner = THIS_MODULE, | 920 | .owner = THIS_MODULE, |
746 | .name = "s3c-sdhci", | 921 | .name = "s3c-sdhci", |
922 | .of_match_table = of_match_ptr(sdhci_s3c_dt_match), | ||
747 | .pm = SDHCI_S3C_PMOPS, | 923 | .pm = SDHCI_S3C_PMOPS, |
748 | }, | 924 | }, |
749 | }; | 925 | }; |
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c index 423da8194cd8..6be89c032deb 100644 --- a/drivers/mmc/host/sdhci-spear.c +++ b/drivers/mmc/host/sdhci-spear.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/of.h> | ||
24 | #include <linux/of_gpio.h> | ||
23 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
24 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
25 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
@@ -68,8 +70,42 @@ static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id) | |||
68 | return IRQ_HANDLED; | 70 | return IRQ_HANDLED; |
69 | } | 71 | } |
70 | 72 | ||
73 | #ifdef CONFIG_OF | ||
74 | static struct sdhci_plat_data * __devinit | ||
75 | sdhci_probe_config_dt(struct platform_device *pdev) | ||
76 | { | ||
77 | struct device_node *np = pdev->dev.of_node; | ||
78 | struct sdhci_plat_data *pdata = NULL; | ||
79 | int cd_gpio; | ||
80 | |||
81 | cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); | ||
82 | if (!gpio_is_valid(cd_gpio)) | ||
83 | cd_gpio = -1; | ||
84 | |||
85 | /* If pdata is required */ | ||
86 | if (cd_gpio != -1) { | ||
87 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
88 | if (!pdata) { | ||
89 | dev_err(&pdev->dev, "DT: kzalloc failed\n"); | ||
90 | return ERR_PTR(-ENOMEM); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | pdata->card_int_gpio = cd_gpio; | ||
95 | |||
96 | return pdata; | ||
97 | } | ||
98 | #else | ||
99 | static struct sdhci_plat_data * __devinit | ||
100 | sdhci_probe_config_dt(struct platform_device *pdev) | ||
101 | { | ||
102 | return ERR_PTR(-ENOSYS); | ||
103 | } | ||
104 | #endif | ||
105 | |||
71 | static int __devinit sdhci_probe(struct platform_device *pdev) | 106 | static int __devinit sdhci_probe(struct platform_device *pdev) |
72 | { | 107 | { |
108 | struct device_node *np = pdev->dev.of_node; | ||
73 | struct sdhci_host *host; | 109 | struct sdhci_host *host; |
74 | struct resource *iomem; | 110 | struct resource *iomem; |
75 | struct spear_sdhci *sdhci; | 111 | struct spear_sdhci *sdhci; |
@@ -104,14 +140,22 @@ static int __devinit sdhci_probe(struct platform_device *pdev) | |||
104 | goto err; | 140 | goto err; |
105 | } | 141 | } |
106 | 142 | ||
107 | ret = clk_enable(sdhci->clk); | 143 | ret = clk_prepare_enable(sdhci->clk); |
108 | if (ret) { | 144 | if (ret) { |
109 | dev_dbg(&pdev->dev, "Error enabling clock\n"); | 145 | dev_dbg(&pdev->dev, "Error enabling clock\n"); |
110 | goto put_clk; | 146 | goto put_clk; |
111 | } | 147 | } |
112 | 148 | ||
113 | /* overwrite platform_data */ | 149 | if (np) { |
114 | sdhci->data = dev_get_platdata(&pdev->dev); | 150 | sdhci->data = sdhci_probe_config_dt(pdev); |
151 | if (IS_ERR(sdhci->data)) { | ||
152 | dev_err(&pdev->dev, "DT: Failed to get pdata\n"); | ||
153 | return -ENODEV; | ||
154 | } | ||
155 | } else { | ||
156 | sdhci->data = dev_get_platdata(&pdev->dev); | ||
157 | } | ||
158 | |||
115 | pdev->dev.platform_data = sdhci; | 159 | pdev->dev.platform_data = sdhci; |
116 | 160 | ||
117 | if (pdev->dev.parent) | 161 | if (pdev->dev.parent) |
@@ -216,7 +260,7 @@ set_drvdata: | |||
216 | free_host: | 260 | free_host: |
217 | sdhci_free_host(host); | 261 | sdhci_free_host(host); |
218 | disable_clk: | 262 | disable_clk: |
219 | clk_disable(sdhci->clk); | 263 | clk_disable_unprepare(sdhci->clk); |
220 | put_clk: | 264 | put_clk: |
221 | clk_put(sdhci->clk); | 265 | clk_put(sdhci->clk); |
222 | err: | 266 | err: |
@@ -238,7 +282,7 @@ static int __devexit sdhci_remove(struct platform_device *pdev) | |||
238 | 282 | ||
239 | sdhci_remove_host(host, dead); | 283 | sdhci_remove_host(host, dead); |
240 | sdhci_free_host(host); | 284 | sdhci_free_host(host); |
241 | clk_disable(sdhci->clk); | 285 | clk_disable_unprepare(sdhci->clk); |
242 | clk_put(sdhci->clk); | 286 | clk_put(sdhci->clk); |
243 | 287 | ||
244 | return 0; | 288 | return 0; |
@@ -253,7 +297,7 @@ static int sdhci_suspend(struct device *dev) | |||
253 | 297 | ||
254 | ret = sdhci_suspend_host(host); | 298 | ret = sdhci_suspend_host(host); |
255 | if (!ret) | 299 | if (!ret) |
256 | clk_disable(sdhci->clk); | 300 | clk_disable_unprepare(sdhci->clk); |
257 | 301 | ||
258 | return ret; | 302 | return ret; |
259 | } | 303 | } |
@@ -264,7 +308,7 @@ static int sdhci_resume(struct device *dev) | |||
264 | struct spear_sdhci *sdhci = dev_get_platdata(dev); | 308 | struct spear_sdhci *sdhci = dev_get_platdata(dev); |
265 | int ret; | 309 | int ret; |
266 | 310 | ||
267 | ret = clk_enable(sdhci->clk); | 311 | ret = clk_prepare_enable(sdhci->clk); |
268 | if (ret) { | 312 | if (ret) { |
269 | dev_dbg(dev, "Resume: Error enabling clock\n"); | 313 | dev_dbg(dev, "Resume: Error enabling clock\n"); |
270 | return ret; | 314 | return ret; |
@@ -276,11 +320,20 @@ static int sdhci_resume(struct device *dev) | |||
276 | 320 | ||
277 | static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume); | 321 | static SIMPLE_DEV_PM_OPS(sdhci_pm_ops, sdhci_suspend, sdhci_resume); |
278 | 322 | ||
323 | #ifdef CONFIG_OF | ||
324 | static const struct of_device_id sdhci_spear_id_table[] = { | ||
325 | { .compatible = "st,spear300-sdhci" }, | ||
326 | {} | ||
327 | }; | ||
328 | MODULE_DEVICE_TABLE(of, sdhci_spear_id_table); | ||
329 | #endif | ||
330 | |||
279 | static struct platform_driver sdhci_driver = { | 331 | static struct platform_driver sdhci_driver = { |
280 | .driver = { | 332 | .driver = { |
281 | .name = "sdhci", | 333 | .name = "sdhci", |
282 | .owner = THIS_MODULE, | 334 | .owner = THIS_MODULE, |
283 | .pm = &sdhci_pm_ops, | 335 | .pm = &sdhci_pm_ops, |
336 | .of_match_table = of_match_ptr(sdhci_spear_id_table), | ||
284 | }, | 337 | }, |
285 | .probe = sdhci_probe, | 338 | .probe = sdhci_probe, |
286 | .remove = __devexit_p(sdhci_remove), | 339 | .remove = __devexit_p(sdhci_remove), |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index d43e7462941f..84e8d0c59ee5 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c | |||
@@ -257,10 +257,9 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev) | |||
257 | int rc; | 257 | int rc; |
258 | 258 | ||
259 | match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); | 259 | match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); |
260 | if (match) | 260 | if (!match) |
261 | soc_data = match->data; | 261 | return -EINVAL; |
262 | else | 262 | soc_data = match->data; |
263 | soc_data = &soc_data_tegra20; | ||
264 | 263 | ||
265 | host = sdhci_pltfm_init(pdev, soc_data->pdata); | 264 | host = sdhci_pltfm_init(pdev, soc_data->pdata); |
266 | if (IS_ERR(host)) | 265 | if (IS_ERR(host)) |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9a11dc39921c..7922adb42386 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/mmc/mmc.h> | 28 | #include <linux/mmc/mmc.h> |
29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
30 | #include <linux/mmc/card.h> | 30 | #include <linux/mmc/card.h> |
31 | #include <linux/mmc/slot-gpio.h> | ||
31 | 32 | ||
32 | #include "sdhci.h" | 33 | #include "sdhci.h" |
33 | 34 | ||
@@ -1293,6 +1294,13 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1293 | present = sdhci_readl(host, SDHCI_PRESENT_STATE) & | 1294 | present = sdhci_readl(host, SDHCI_PRESENT_STATE) & |
1294 | SDHCI_CARD_PRESENT; | 1295 | SDHCI_CARD_PRESENT; |
1295 | 1296 | ||
1297 | /* If we're using a cd-gpio, testing the presence bit might fail. */ | ||
1298 | if (!present) { | ||
1299 | int ret = mmc_gpio_get_cd(host->mmc); | ||
1300 | if (ret > 0) | ||
1301 | present = true; | ||
1302 | } | ||
1303 | |||
1296 | if (!present || host->flags & SDHCI_DEVICE_DEAD) { | 1304 | if (!present || host->flags & SDHCI_DEVICE_DEAD) { |
1297 | host->mrq->cmd->error = -ENOMEDIUM; | 1305 | host->mrq->cmd->error = -ENOMEDIUM; |
1298 | tasklet_schedule(&host->finish_tasklet); | 1306 | tasklet_schedule(&host->finish_tasklet); |
@@ -1597,57 +1605,65 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
1597 | spin_unlock_irqrestore(&host->lock, flags); | 1605 | spin_unlock_irqrestore(&host->lock, flags); |
1598 | } | 1606 | } |
1599 | 1607 | ||
1600 | static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | 1608 | static int sdhci_do_3_3v_signal_voltage_switch(struct sdhci_host *host, |
1601 | struct mmc_ios *ios) | 1609 | u16 ctrl) |
1602 | { | 1610 | { |
1603 | u8 pwr; | 1611 | int ret; |
1604 | u16 clk, ctrl; | ||
1605 | u32 present_state; | ||
1606 | 1612 | ||
1607 | /* | 1613 | /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ |
1608 | * Signal Voltage Switching is only applicable for Host Controllers | 1614 | ctrl &= ~SDHCI_CTRL_VDD_180; |
1609 | * v3.00 and above. | 1615 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
1610 | */ | ||
1611 | if (host->version < SDHCI_SPEC_300) | ||
1612 | return 0; | ||
1613 | 1616 | ||
1614 | /* | 1617 | if (host->vqmmc) { |
1615 | * We first check whether the request is to set signalling voltage | 1618 | ret = regulator_set_voltage(host->vqmmc, 3300000, 3300000); |
1616 | * to 3.3V. If so, we change the voltage to 3.3V and return quickly. | 1619 | if (ret) { |
1617 | */ | 1620 | pr_warning("%s: Switching to 3.3V signalling voltage " |
1621 | " failed\n", mmc_hostname(host->mmc)); | ||
1622 | return -EIO; | ||
1623 | } | ||
1624 | } | ||
1625 | /* Wait for 5ms */ | ||
1626 | usleep_range(5000, 5500); | ||
1627 | |||
1628 | /* 3.3V regulator output should be stable within 5 ms */ | ||
1618 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1629 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
1619 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { | 1630 | if (!(ctrl & SDHCI_CTRL_VDD_180)) |
1620 | /* Set 1.8V Signal Enable in the Host Control2 register to 0 */ | 1631 | return 0; |
1621 | ctrl &= ~SDHCI_CTRL_VDD_180; | ||
1622 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1623 | 1632 | ||
1624 | /* Wait for 5ms */ | 1633 | pr_warning("%s: 3.3V regulator output did not became stable\n", |
1625 | usleep_range(5000, 5500); | 1634 | mmc_hostname(host->mmc)); |
1626 | 1635 | ||
1627 | /* 3.3V regulator output should be stable within 5 ms */ | 1636 | return -EIO; |
1628 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1637 | } |
1629 | if (!(ctrl & SDHCI_CTRL_VDD_180)) | ||
1630 | return 0; | ||
1631 | else { | ||
1632 | pr_info(DRIVER_NAME ": Switching to 3.3V " | ||
1633 | "signalling voltage failed\n"); | ||
1634 | return -EIO; | ||
1635 | } | ||
1636 | } else if (!(ctrl & SDHCI_CTRL_VDD_180) && | ||
1637 | (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) { | ||
1638 | /* Stop SDCLK */ | ||
1639 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | ||
1640 | clk &= ~SDHCI_CLOCK_CARD_EN; | ||
1641 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
1642 | 1638 | ||
1643 | /* Check whether DAT[3:0] is 0000 */ | 1639 | static int sdhci_do_1_8v_signal_voltage_switch(struct sdhci_host *host, |
1644 | present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); | 1640 | u16 ctrl) |
1645 | if (!((present_state & SDHCI_DATA_LVL_MASK) >> | 1641 | { |
1646 | SDHCI_DATA_LVL_SHIFT)) { | 1642 | u8 pwr; |
1647 | /* | 1643 | u16 clk; |
1648 | * Enable 1.8V Signal Enable in the Host Control2 | 1644 | u32 present_state; |
1649 | * register | 1645 | int ret; |
1650 | */ | 1646 | |
1647 | /* Stop SDCLK */ | ||
1648 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | ||
1649 | clk &= ~SDHCI_CLOCK_CARD_EN; | ||
1650 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | ||
1651 | |||
1652 | /* Check whether DAT[3:0] is 0000 */ | ||
1653 | present_state = sdhci_readl(host, SDHCI_PRESENT_STATE); | ||
1654 | if (!((present_state & SDHCI_DATA_LVL_MASK) >> | ||
1655 | SDHCI_DATA_LVL_SHIFT)) { | ||
1656 | /* | ||
1657 | * Enable 1.8V Signal Enable in the Host Control2 | ||
1658 | * register | ||
1659 | */ | ||
1660 | if (host->vqmmc) | ||
1661 | ret = regulator_set_voltage(host->vqmmc, | ||
1662 | 1800000, 1800000); | ||
1663 | else | ||
1664 | ret = 0; | ||
1665 | |||
1666 | if (!ret) { | ||
1651 | ctrl |= SDHCI_CTRL_VDD_180; | 1667 | ctrl |= SDHCI_CTRL_VDD_180; |
1652 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | 1668 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); |
1653 | 1669 | ||
@@ -1656,7 +1672,7 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | |||
1656 | 1672 | ||
1657 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1673 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
1658 | if (ctrl & SDHCI_CTRL_VDD_180) { | 1674 | if (ctrl & SDHCI_CTRL_VDD_180) { |
1659 | /* Provide SDCLK again and wait for 1ms*/ | 1675 | /* Provide SDCLK again and wait for 1ms */ |
1660 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); | 1676 | clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL); |
1661 | clk |= SDHCI_CLOCK_CARD_EN; | 1677 | clk |= SDHCI_CLOCK_CARD_EN; |
1662 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); | 1678 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); |
@@ -1673,29 +1689,55 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | |||
1673 | return 0; | 1689 | return 0; |
1674 | } | 1690 | } |
1675 | } | 1691 | } |
1692 | } | ||
1676 | 1693 | ||
1677 | /* | 1694 | /* |
1678 | * If we are here, that means the switch to 1.8V signaling | 1695 | * If we are here, that means the switch to 1.8V signaling |
1679 | * failed. We power cycle the card, and retry initialization | 1696 | * failed. We power cycle the card, and retry initialization |
1680 | * sequence by setting S18R to 0. | 1697 | * sequence by setting S18R to 0. |
1681 | */ | 1698 | */ |
1682 | pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); | 1699 | pwr = sdhci_readb(host, SDHCI_POWER_CONTROL); |
1683 | pwr &= ~SDHCI_POWER_ON; | 1700 | pwr &= ~SDHCI_POWER_ON; |
1684 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1701 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
1685 | if (host->vmmc) | 1702 | if (host->vmmc) |
1686 | regulator_disable(host->vmmc); | 1703 | regulator_disable(host->vmmc); |
1687 | 1704 | ||
1688 | /* Wait for 1ms as per the spec */ | 1705 | /* Wait for 1ms as per the spec */ |
1689 | usleep_range(1000, 1500); | 1706 | usleep_range(1000, 1500); |
1690 | pwr |= SDHCI_POWER_ON; | 1707 | pwr |= SDHCI_POWER_ON; |
1691 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); | 1708 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
1692 | if (host->vmmc) | 1709 | if (host->vmmc) |
1693 | regulator_enable(host->vmmc); | 1710 | regulator_enable(host->vmmc); |
1694 | 1711 | ||
1695 | pr_info(DRIVER_NAME ": Switching to 1.8V signalling " | 1712 | pr_warning("%s: Switching to 1.8V signalling voltage failed, " |
1696 | "voltage failed, retrying with S18R set to 0\n"); | 1713 | "retrying with S18R set to 0\n", mmc_hostname(host->mmc)); |
1697 | return -EAGAIN; | 1714 | |
1698 | } else | 1715 | return -EAGAIN; |
1716 | } | ||
1717 | |||
1718 | static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, | ||
1719 | struct mmc_ios *ios) | ||
1720 | { | ||
1721 | u16 ctrl; | ||
1722 | |||
1723 | /* | ||
1724 | * Signal Voltage Switching is only applicable for Host Controllers | ||
1725 | * v3.00 and above. | ||
1726 | */ | ||
1727 | if (host->version < SDHCI_SPEC_300) | ||
1728 | return 0; | ||
1729 | |||
1730 | /* | ||
1731 | * We first check whether the request is to set signalling voltage | ||
1732 | * to 3.3V. If so, we change the voltage to 3.3V and return quickly. | ||
1733 | */ | ||
1734 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1735 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) | ||
1736 | return sdhci_do_3_3v_signal_voltage_switch(host, ctrl); | ||
1737 | else if (!(ctrl & SDHCI_CTRL_VDD_180) && | ||
1738 | (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180)) | ||
1739 | return sdhci_do_1_8v_signal_voltage_switch(host, ctrl); | ||
1740 | else | ||
1699 | /* No signal voltage switch required */ | 1741 | /* No signal voltage switch required */ |
1700 | return 0; | 1742 | return 0; |
1701 | } | 1743 | } |
@@ -2802,6 +2844,18 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2802 | !(host->mmc->caps & MMC_CAP_NONREMOVABLE)) | 2844 | !(host->mmc->caps & MMC_CAP_NONREMOVABLE)) |
2803 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 2845 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
2804 | 2846 | ||
2847 | /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ | ||
2848 | host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); | ||
2849 | if (IS_ERR(host->vqmmc)) { | ||
2850 | pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc)); | ||
2851 | host->vqmmc = NULL; | ||
2852 | } | ||
2853 | else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000)) | ||
2854 | regulator_enable(host->vqmmc); | ||
2855 | else | ||
2856 | caps[1] &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | | ||
2857 | SDHCI_SUPPORT_DDR50); | ||
2858 | |||
2805 | /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ | 2859 | /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */ |
2806 | if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | | 2860 | if (caps[1] & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | |
2807 | SDHCI_SUPPORT_DDR50)) | 2861 | SDHCI_SUPPORT_DDR50)) |
@@ -2832,15 +2886,6 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2832 | if (caps[1] & SDHCI_DRIVER_TYPE_D) | 2886 | if (caps[1] & SDHCI_DRIVER_TYPE_D) |
2833 | mmc->caps |= MMC_CAP_DRIVER_TYPE_D; | 2887 | mmc->caps |= MMC_CAP_DRIVER_TYPE_D; |
2834 | 2888 | ||
2835 | /* | ||
2836 | * If Power Off Notify capability is enabled by the host, | ||
2837 | * set notify to short power off notify timeout value. | ||
2838 | */ | ||
2839 | if (mmc->caps2 & MMC_CAP2_POWEROFF_NOTIFY) | ||
2840 | mmc->power_notify_type = MMC_HOST_PW_NOTIFY_SHORT; | ||
2841 | else | ||
2842 | mmc->power_notify_type = MMC_HOST_PW_NOTIFY_NONE; | ||
2843 | |||
2844 | /* Initial value for re-tuning timer count */ | 2889 | /* Initial value for re-tuning timer count */ |
2845 | host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >> | 2890 | host->tuning_count = (caps[1] & SDHCI_RETUNING_TIMER_COUNT_MASK) >> |
2846 | SDHCI_RETUNING_TIMER_COUNT_SHIFT; | 2891 | SDHCI_RETUNING_TIMER_COUNT_SHIFT; |
@@ -2862,7 +2907,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2862 | if (IS_ERR(host->vmmc)) { | 2907 | if (IS_ERR(host->vmmc)) { |
2863 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); | 2908 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); |
2864 | host->vmmc = NULL; | 2909 | host->vmmc = NULL; |
2865 | } | 2910 | } else |
2911 | regulator_enable(host->vmmc); | ||
2866 | 2912 | ||
2867 | #ifdef CONFIG_REGULATOR | 2913 | #ifdef CONFIG_REGULATOR |
2868 | if (host->vmmc) { | 2914 | if (host->vmmc) { |
@@ -3119,8 +3165,15 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) | |||
3119 | tasklet_kill(&host->card_tasklet); | 3165 | tasklet_kill(&host->card_tasklet); |
3120 | tasklet_kill(&host->finish_tasklet); | 3166 | tasklet_kill(&host->finish_tasklet); |
3121 | 3167 | ||
3122 | if (host->vmmc) | 3168 | if (host->vmmc) { |
3169 | regulator_disable(host->vmmc); | ||
3123 | regulator_put(host->vmmc); | 3170 | regulator_put(host->vmmc); |
3171 | } | ||
3172 | |||
3173 | if (host->vqmmc) { | ||
3174 | regulator_disable(host->vqmmc); | ||
3175 | regulator_put(host->vqmmc); | ||
3176 | } | ||
3124 | 3177 | ||
3125 | kfree(host->adma_desc); | 3178 | kfree(host->adma_desc); |
3126 | kfree(host->align_buffer); | 3179 | kfree(host->align_buffer); |
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 5d8142773fac..11d2bc3b51d5 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -1213,7 +1213,9 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
1213 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE); | 1213 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE); |
1214 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); | 1214 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); |
1215 | } else if (state & INT_DTRANE) { | 1215 | } else if (state & INT_DTRANE) { |
1216 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_DTRANE); | 1216 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, |
1217 | ~(INT_CMD12DRE | INT_CMD12RBE | | ||
1218 | INT_CMD12CRE | INT_DTRANE)); | ||
1217 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); | 1219 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); |
1218 | } else if (state & INT_CMD12RBE) { | 1220 | } else if (state & INT_CMD12RBE) { |
1219 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, | 1221 | sh_mmcif_writel(host->addr, MMCIF_CE_INT, |
@@ -1229,6 +1231,10 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | |||
1229 | host->sd_error = true; | 1231 | host->sd_error = true; |
1230 | dev_dbg(&host->pd->dev, "int err state = %08x\n", state); | 1232 | dev_dbg(&host->pd->dev, "int err state = %08x\n", state); |
1231 | } | 1233 | } |
1234 | if (host->state == STATE_IDLE) { | ||
1235 | dev_info(&host->pd->dev, "Spurious IRQ status 0x%x", state); | ||
1236 | return IRQ_HANDLED; | ||
1237 | } | ||
1232 | if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { | 1238 | if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) { |
1233 | if (!host->dma_active) | 1239 | if (!host->dma_active) |
1234 | return IRQ_WAKE_THREAD; | 1240 | return IRQ_WAKE_THREAD; |
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 4b83c43f950d..f18becef156d 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c | |||
@@ -1337,21 +1337,7 @@ static struct pci_driver via_sd_driver = { | |||
1337 | .resume = via_sd_resume, | 1337 | .resume = via_sd_resume, |
1338 | }; | 1338 | }; |
1339 | 1339 | ||
1340 | static int __init via_sd_drv_init(void) | 1340 | module_pci_driver(via_sd_driver); |
1341 | { | ||
1342 | pr_info(DRV_NAME ": VIA SD/MMC Card Reader driver " | ||
1343 | "(C) 2008 VIA Technologies, Inc.\n"); | ||
1344 | |||
1345 | return pci_register_driver(&via_sd_driver); | ||
1346 | } | ||
1347 | |||
1348 | static void __exit via_sd_drv_exit(void) | ||
1349 | { | ||
1350 | pci_unregister_driver(&via_sd_driver); | ||
1351 | } | ||
1352 | |||
1353 | module_init(via_sd_drv_init); | ||
1354 | module_exit(via_sd_drv_exit); | ||
1355 | 1341 | ||
1356 | MODULE_LICENSE("GPL"); | 1342 | MODULE_LICENSE("GPL"); |
1357 | MODULE_AUTHOR("VIA Technologies Inc."); | 1343 | MODULE_AUTHOR("VIA Technologies Inc."); |
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index 58eab9ac1d01..d5655a63eda4 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c | |||
@@ -2358,9 +2358,9 @@ error5: | |||
2358 | * which is contained at the end of struct mmc | 2358 | * which is contained at the end of struct mmc |
2359 | */ | 2359 | */ |
2360 | error4: | 2360 | error4: |
2361 | usb_free_urb(command_out_urb); | ||
2362 | error1: | ||
2363 | usb_free_urb(command_res_urb); | 2361 | usb_free_urb(command_res_urb); |
2362 | error1: | ||
2363 | usb_free_urb(command_out_urb); | ||
2364 | error0: | 2364 | error0: |
2365 | return retval; | 2365 | return retval; |
2366 | } | 2366 | } |