diff options
Diffstat (limited to 'drivers/mmc/host/dw_mmc.c')
| -rw-r--r-- | drivers/mmc/host/dw_mmc.c | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index c0667c8af2bd..323c5022c2ca 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -232,7 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | |||
| 232 | { | 232 | { |
| 233 | struct mmc_data *data; | 233 | struct mmc_data *data; |
| 234 | struct dw_mci_slot *slot = mmc_priv(mmc); | 234 | struct dw_mci_slot *slot = mmc_priv(mmc); |
| 235 | struct dw_mci_drv_data *drv_data = slot->host->drv_data; | 235 | const struct dw_mci_drv_data *drv_data = slot->host->drv_data; |
| 236 | u32 cmdr; | 236 | u32 cmdr; |
| 237 | cmd->error = -EINPROGRESS; | 237 | cmd->error = -EINPROGRESS; |
| 238 | 238 | ||
| @@ -617,13 +617,13 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) | |||
| 617 | cmd, arg, cmd_status); | 617 | cmd, arg, cmd_status); |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | static void dw_mci_setup_bus(struct dw_mci_slot *slot) | 620 | static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) |
| 621 | { | 621 | { |
| 622 | struct dw_mci *host = slot->host; | 622 | struct dw_mci *host = slot->host; |
| 623 | u32 div; | 623 | u32 div; |
| 624 | u32 clk_en_a; | 624 | u32 clk_en_a; |
| 625 | 625 | ||
| 626 | if (slot->clock != host->current_speed) { | 626 | if (slot->clock != host->current_speed || force_clkinit) { |
| 627 | div = host->bus_hz / slot->clock; | 627 | div = host->bus_hz / slot->clock; |
| 628 | if (host->bus_hz % slot->clock && host->bus_hz > slot->clock) | 628 | if (host->bus_hz % slot->clock && host->bus_hz > slot->clock) |
| 629 | /* | 629 | /* |
| @@ -683,9 +683,6 @@ static void __dw_mci_start_request(struct dw_mci *host, | |||
| 683 | if (host->pdata->select_slot) | 683 | if (host->pdata->select_slot) |
| 684 | host->pdata->select_slot(slot->id); | 684 | host->pdata->select_slot(slot->id); |
| 685 | 685 | ||
| 686 | /* Slot specific timing and width adjustment */ | ||
| 687 | dw_mci_setup_bus(slot); | ||
| 688 | |||
| 689 | host->cur_slot = slot; | 686 | host->cur_slot = slot; |
| 690 | host->mrq = mrq; | 687 | host->mrq = mrq; |
| 691 | 688 | ||
| @@ -773,22 +770,19 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 773 | static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 770 | static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
| 774 | { | 771 | { |
| 775 | struct dw_mci_slot *slot = mmc_priv(mmc); | 772 | struct dw_mci_slot *slot = mmc_priv(mmc); |
| 776 | struct dw_mci_drv_data *drv_data = slot->host->drv_data; | 773 | const struct dw_mci_drv_data *drv_data = slot->host->drv_data; |
| 777 | u32 regs; | 774 | u32 regs; |
| 778 | 775 | ||
| 779 | /* set default 1 bit mode */ | ||
| 780 | slot->ctype = SDMMC_CTYPE_1BIT; | ||
| 781 | |||
| 782 | switch (ios->bus_width) { | 776 | switch (ios->bus_width) { |
| 783 | case MMC_BUS_WIDTH_1: | ||
| 784 | slot->ctype = SDMMC_CTYPE_1BIT; | ||
| 785 | break; | ||
| 786 | case MMC_BUS_WIDTH_4: | 777 | case MMC_BUS_WIDTH_4: |
| 787 | slot->ctype = SDMMC_CTYPE_4BIT; | 778 | slot->ctype = SDMMC_CTYPE_4BIT; |
| 788 | break; | 779 | break; |
| 789 | case MMC_BUS_WIDTH_8: | 780 | case MMC_BUS_WIDTH_8: |
| 790 | slot->ctype = SDMMC_CTYPE_8BIT; | 781 | slot->ctype = SDMMC_CTYPE_8BIT; |
| 791 | break; | 782 | break; |
| 783 | default: | ||
| 784 | /* set default 1 bit mode */ | ||
| 785 | slot->ctype = SDMMC_CTYPE_1BIT; | ||
| 792 | } | 786 | } |
| 793 | 787 | ||
| 794 | regs = mci_readl(slot->host, UHS_REG); | 788 | regs = mci_readl(slot->host, UHS_REG); |
| @@ -812,6 +806,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 812 | if (drv_data && drv_data->set_ios) | 806 | if (drv_data && drv_data->set_ios) |
| 813 | drv_data->set_ios(slot->host, ios); | 807 | drv_data->set_ios(slot->host, ios); |
| 814 | 808 | ||
| 809 | /* Slot specific timing and width adjustment */ | ||
| 810 | dw_mci_setup_bus(slot, false); | ||
| 811 | |||
| 815 | switch (ios->power_mode) { | 812 | switch (ios->power_mode) { |
| 816 | case MMC_POWER_UP: | 813 | case MMC_POWER_UP: |
| 817 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); | 814 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); |
| @@ -1817,7 +1814,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 1817 | { | 1814 | { |
| 1818 | struct mmc_host *mmc; | 1815 | struct mmc_host *mmc; |
| 1819 | struct dw_mci_slot *slot; | 1816 | struct dw_mci_slot *slot; |
| 1820 | struct dw_mci_drv_data *drv_data = host->drv_data; | 1817 | const struct dw_mci_drv_data *drv_data = host->drv_data; |
| 1821 | int ctrl_id, ret; | 1818 | int ctrl_id, ret; |
| 1822 | u8 bus_width; | 1819 | u8 bus_width; |
| 1823 | 1820 | ||
| @@ -1850,6 +1847,9 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 1850 | if (host->pdata->caps) | 1847 | if (host->pdata->caps) |
| 1851 | mmc->caps = host->pdata->caps; | 1848 | mmc->caps = host->pdata->caps; |
| 1852 | 1849 | ||
| 1850 | if (host->pdata->pm_caps) | ||
| 1851 | mmc->pm_caps = host->pdata->pm_caps; | ||
| 1852 | |||
| 1853 | if (host->dev->of_node) { | 1853 | if (host->dev->of_node) { |
| 1854 | ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); | 1854 | ctrl_id = of_alias_get_id(host->dev->of_node, "mshc"); |
| 1855 | if (ctrl_id < 0) | 1855 | if (ctrl_id < 0) |
| @@ -1911,7 +1911,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
| 1911 | #endif /* CONFIG_MMC_DW_IDMAC */ | 1911 | #endif /* CONFIG_MMC_DW_IDMAC */ |
| 1912 | } | 1912 | } |
| 1913 | 1913 | ||
| 1914 | host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); | 1914 | host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc"); |
| 1915 | if (IS_ERR(host->vmmc)) { | 1915 | if (IS_ERR(host->vmmc)) { |
| 1916 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); | 1916 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); |
| 1917 | host->vmmc = NULL; | 1917 | host->vmmc = NULL; |
| @@ -1960,7 +1960,7 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) | |||
| 1960 | static void dw_mci_init_dma(struct dw_mci *host) | 1960 | static void dw_mci_init_dma(struct dw_mci *host) |
| 1961 | { | 1961 | { |
| 1962 | /* Alloc memory for sg translation */ | 1962 | /* Alloc memory for sg translation */ |
| 1963 | host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE, | 1963 | host->sg_cpu = dmam_alloc_coherent(host->dev, PAGE_SIZE, |
| 1964 | &host->sg_dma, GFP_KERNEL); | 1964 | &host->sg_dma, GFP_KERNEL); |
| 1965 | if (!host->sg_cpu) { | 1965 | if (!host->sg_cpu) { |
| 1966 | dev_err(host->dev, "%s: could not alloc DMA memory\n", | 1966 | dev_err(host->dev, "%s: could not alloc DMA memory\n", |
| @@ -2038,7 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
| 2038 | struct dw_mci_board *pdata; | 2038 | struct dw_mci_board *pdata; |
| 2039 | struct device *dev = host->dev; | 2039 | struct device *dev = host->dev; |
| 2040 | struct device_node *np = dev->of_node; | 2040 | struct device_node *np = dev->of_node; |
| 2041 | struct dw_mci_drv_data *drv_data = host->drv_data; | 2041 | const struct dw_mci_drv_data *drv_data = host->drv_data; |
| 2042 | int idx, ret; | 2042 | int idx, ret; |
| 2043 | 2043 | ||
| 2044 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | 2044 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); |
| @@ -2072,6 +2072,12 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
| 2072 | return ERR_PTR(ret); | 2072 | return ERR_PTR(ret); |
| 2073 | } | 2073 | } |
| 2074 | 2074 | ||
| 2075 | if (of_find_property(np, "keep-power-in-suspend", NULL)) | ||
| 2076 | pdata->pm_caps |= MMC_PM_KEEP_POWER; | ||
| 2077 | |||
| 2078 | if (of_find_property(np, "enable-sdio-wakeup", NULL)) | ||
| 2079 | pdata->pm_caps |= MMC_PM_WAKE_SDIO_IRQ; | ||
| 2080 | |||
| 2075 | return pdata; | 2081 | return pdata; |
| 2076 | } | 2082 | } |
| 2077 | 2083 | ||
| @@ -2084,7 +2090,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) | |||
| 2084 | 2090 | ||
| 2085 | int dw_mci_probe(struct dw_mci *host) | 2091 | int dw_mci_probe(struct dw_mci *host) |
| 2086 | { | 2092 | { |
| 2087 | struct dw_mci_drv_data *drv_data = host->drv_data; | 2093 | const struct dw_mci_drv_data *drv_data = host->drv_data; |
| 2088 | int width, i, ret = 0; | 2094 | int width, i, ret = 0; |
| 2089 | u32 fifo_size; | 2095 | u32 fifo_size; |
| 2090 | int init_slots = 0; | 2096 | int init_slots = 0; |
| @@ -2103,26 +2109,24 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2103 | return -ENODEV; | 2109 | return -ENODEV; |
| 2104 | } | 2110 | } |
| 2105 | 2111 | ||
| 2106 | host->biu_clk = clk_get(host->dev, "biu"); | 2112 | host->biu_clk = devm_clk_get(host->dev, "biu"); |
| 2107 | if (IS_ERR(host->biu_clk)) { | 2113 | if (IS_ERR(host->biu_clk)) { |
| 2108 | dev_dbg(host->dev, "biu clock not available\n"); | 2114 | dev_dbg(host->dev, "biu clock not available\n"); |
| 2109 | } else { | 2115 | } else { |
| 2110 | ret = clk_prepare_enable(host->biu_clk); | 2116 | ret = clk_prepare_enable(host->biu_clk); |
| 2111 | if (ret) { | 2117 | if (ret) { |
| 2112 | dev_err(host->dev, "failed to enable biu clock\n"); | 2118 | dev_err(host->dev, "failed to enable biu clock\n"); |
| 2113 | clk_put(host->biu_clk); | ||
| 2114 | return ret; | 2119 | return ret; |
| 2115 | } | 2120 | } |
| 2116 | } | 2121 | } |
| 2117 | 2122 | ||
| 2118 | host->ciu_clk = clk_get(host->dev, "ciu"); | 2123 | host->ciu_clk = devm_clk_get(host->dev, "ciu"); |
| 2119 | if (IS_ERR(host->ciu_clk)) { | 2124 | if (IS_ERR(host->ciu_clk)) { |
| 2120 | dev_dbg(host->dev, "ciu clock not available\n"); | 2125 | dev_dbg(host->dev, "ciu clock not available\n"); |
| 2121 | } else { | 2126 | } else { |
| 2122 | ret = clk_prepare_enable(host->ciu_clk); | 2127 | ret = clk_prepare_enable(host->ciu_clk); |
| 2123 | if (ret) { | 2128 | if (ret) { |
| 2124 | dev_err(host->dev, "failed to enable ciu clock\n"); | 2129 | dev_err(host->dev, "failed to enable ciu clock\n"); |
| 2125 | clk_put(host->ciu_clk); | ||
| 2126 | goto err_clk_biu; | 2130 | goto err_clk_biu; |
| 2127 | } | 2131 | } |
| 2128 | } | 2132 | } |
| @@ -2224,7 +2228,8 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2224 | if (!host->card_workqueue) | 2228 | if (!host->card_workqueue) |
| 2225 | goto err_dmaunmap; | 2229 | goto err_dmaunmap; |
| 2226 | INIT_WORK(&host->card_work, dw_mci_work_routine_card); | 2230 | INIT_WORK(&host->card_work, dw_mci_work_routine_card); |
| 2227 | ret = request_irq(host->irq, dw_mci_interrupt, host->irq_flags, "dw-mci", host); | 2231 | ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, |
| 2232 | host->irq_flags, "dw-mci", host); | ||
| 2228 | if (ret) | 2233 | if (ret) |
| 2229 | goto err_workqueue; | 2234 | goto err_workqueue; |
| 2230 | 2235 | ||
| @@ -2262,7 +2267,7 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2262 | } else { | 2267 | } else { |
| 2263 | dev_dbg(host->dev, "attempted to initialize %d slots, " | 2268 | dev_dbg(host->dev, "attempted to initialize %d slots, " |
| 2264 | "but failed on all\n", host->num_slots); | 2269 | "but failed on all\n", host->num_slots); |
| 2265 | goto err_init_slot; | 2270 | goto err_workqueue; |
| 2266 | } | 2271 | } |
| 2267 | 2272 | ||
| 2268 | /* | 2273 | /* |
| @@ -2282,33 +2287,24 @@ int dw_mci_probe(struct dw_mci *host) | |||
| 2282 | 2287 | ||
| 2283 | return 0; | 2288 | return 0; |
| 2284 | 2289 | ||
| 2285 | err_init_slot: | ||
| 2286 | free_irq(host->irq, host); | ||
| 2287 | |||
| 2288 | err_workqueue: | 2290 | err_workqueue: |
| 2289 | destroy_workqueue(host->card_workqueue); | 2291 | destroy_workqueue(host->card_workqueue); |
| 2290 | 2292 | ||
| 2291 | err_dmaunmap: | 2293 | err_dmaunmap: |
| 2292 | if (host->use_dma && host->dma_ops->exit) | 2294 | if (host->use_dma && host->dma_ops->exit) |
| 2293 | host->dma_ops->exit(host); | 2295 | host->dma_ops->exit(host); |
| 2294 | dma_free_coherent(host->dev, PAGE_SIZE, | ||
| 2295 | host->sg_cpu, host->sg_dma); | ||
| 2296 | 2296 | ||
| 2297 | if (host->vmmc) { | 2297 | if (host->vmmc) |
| 2298 | regulator_disable(host->vmmc); | 2298 | regulator_disable(host->vmmc); |
| 2299 | regulator_put(host->vmmc); | ||
| 2300 | } | ||
| 2301 | 2299 | ||
| 2302 | err_clk_ciu: | 2300 | err_clk_ciu: |
| 2303 | if (!IS_ERR(host->ciu_clk)) { | 2301 | if (!IS_ERR(host->ciu_clk)) |
| 2304 | clk_disable_unprepare(host->ciu_clk); | 2302 | clk_disable_unprepare(host->ciu_clk); |
| 2305 | clk_put(host->ciu_clk); | 2303 | |
| 2306 | } | ||
| 2307 | err_clk_biu: | 2304 | err_clk_biu: |
| 2308 | if (!IS_ERR(host->biu_clk)) { | 2305 | if (!IS_ERR(host->biu_clk)) |
| 2309 | clk_disable_unprepare(host->biu_clk); | 2306 | clk_disable_unprepare(host->biu_clk); |
| 2310 | clk_put(host->biu_clk); | 2307 | |
| 2311 | } | ||
| 2312 | return ret; | 2308 | return ret; |
| 2313 | } | 2309 | } |
| 2314 | EXPORT_SYMBOL(dw_mci_probe); | 2310 | EXPORT_SYMBOL(dw_mci_probe); |
| @@ -2330,24 +2326,19 @@ void dw_mci_remove(struct dw_mci *host) | |||
| 2330 | mci_writel(host, CLKENA, 0); | 2326 | mci_writel(host, CLKENA, 0); |
| 2331 | mci_writel(host, CLKSRC, 0); | 2327 | mci_writel(host, CLKSRC, 0); |
| 2332 | 2328 | ||
| 2333 | free_irq(host->irq, host); | ||
| 2334 | destroy_workqueue(host->card_workqueue); | 2329 | destroy_workqueue(host->card_workqueue); |
| 2335 | dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); | ||
| 2336 | 2330 | ||
| 2337 | if (host->use_dma && host->dma_ops->exit) | 2331 | if (host->use_dma && host->dma_ops->exit) |
| 2338 | host->dma_ops->exit(host); | 2332 | host->dma_ops->exit(host); |
| 2339 | 2333 | ||
| 2340 | if (host->vmmc) { | 2334 | if (host->vmmc) |
| 2341 | regulator_disable(host->vmmc); | 2335 | regulator_disable(host->vmmc); |
| 2342 | regulator_put(host->vmmc); | ||
| 2343 | } | ||
| 2344 | 2336 | ||
| 2345 | if (!IS_ERR(host->ciu_clk)) | 2337 | if (!IS_ERR(host->ciu_clk)) |
| 2346 | clk_disable_unprepare(host->ciu_clk); | 2338 | clk_disable_unprepare(host->ciu_clk); |
| 2339 | |||
| 2347 | if (!IS_ERR(host->biu_clk)) | 2340 | if (!IS_ERR(host->biu_clk)) |
| 2348 | clk_disable_unprepare(host->biu_clk); | 2341 | clk_disable_unprepare(host->biu_clk); |
| 2349 | clk_put(host->ciu_clk); | ||
| 2350 | clk_put(host->biu_clk); | ||
| 2351 | } | 2342 | } |
| 2352 | EXPORT_SYMBOL(dw_mci_remove); | 2343 | EXPORT_SYMBOL(dw_mci_remove); |
| 2353 | 2344 | ||
| @@ -2411,6 +2402,11 @@ int dw_mci_resume(struct dw_mci *host) | |||
| 2411 | struct dw_mci_slot *slot = host->slot[i]; | 2402 | struct dw_mci_slot *slot = host->slot[i]; |
| 2412 | if (!slot) | 2403 | if (!slot) |
| 2413 | continue; | 2404 | continue; |
| 2405 | if (slot->mmc->pm_flags & MMC_PM_KEEP_POWER) { | ||
| 2406 | dw_mci_set_ios(slot->mmc, &slot->mmc->ios); | ||
| 2407 | dw_mci_setup_bus(slot, true); | ||
| 2408 | } | ||
| 2409 | |||
| 2414 | ret = mmc_resume_host(host->slot[i]->mmc); | 2410 | ret = mmc_resume_host(host->slot[i]->mmc); |
| 2415 | if (ret < 0) | 2411 | if (ret < 0) |
| 2416 | return ret; | 2412 | return ret; |
