diff options
Diffstat (limited to 'drivers/mmc/host/jz4740_mmc.c')
| -rw-r--r-- | drivers/mmc/host/jz4740_mmc.c | 225 |
1 files changed, 59 insertions, 166 deletions
diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index b3a0ab0e4c2..537d6c7a5ae 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -14,6 +14,8 @@ */ #include <linux/mmc/host.h> +#include <linux/mmc/slot-gpio.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/interrupt.h> @@ -119,7 +121,6 @@ struct jz4740_mmc_host { int irq; int card_detect_irq; - struct resource *mem; void __iomem *base; struct mmc_request *req; struct mmc_command *cmd; @@ -230,6 +231,14 @@ static void jz4740_mmc_transfer_check_state(struct jz4740_mmc_host *host, host->req->cmd->error = -EIO; data->error = -EIO; } + } else if (status & JZ_MMC_STATUS_READ_ERROR_MASK) { + if (status & (JZ_MMC_STATUS_TIMEOUT_READ)) { + host->req->cmd->error = -ETIMEDOUT; + data->error = -ETIMEDOUT; + } else { + host->req->cmd->error = -EIO; + data->error = -EIO; + } } } @@ -506,10 +515,13 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) jz4740_mmc_send_command(host, req->stop); - timeout = jz4740_mmc_poll_irq(host, JZ_MMC_IRQ_PRG_DONE); - if (timeout) { - host->state = JZ4740_MMC_STATE_DONE; - break; + if (mmc_resp_type(req->stop) & MMC_RSP_BUSY) { + timeout = jz4740_mmc_poll_irq(host, + JZ_MMC_IRQ_PRG_DONE); + if (timeout) { + host->state = JZ4740_MMC_STATE_DONE; + break; + } } case JZ4740_MMC_STATE_DONE: break; @@ -559,11 +571,6 @@ static irqreturn_t jz_mmc_irq(int irq, void *devid) if (cmd->data) cmd->data->error = -EIO; cmd->error = -EIO; - } else if (status & (JZ_MMC_STATUS_CRC_READ_ERROR | - JZ_MMC_STATUS_CRC_WRITE_ERROR)) { - if (cmd->data) - cmd->data->error = -EIO; - cmd->error = -EIO; } jz4740_mmc_set_irq_enabled(host, irq_reg, false); @@ -625,7 +632,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) gpio_set_value(host->pdata->gpio_power, !host->pdata->power_active_low); host->cmdat |= JZ_MMC_CMDAT_INIT; - clk_enable(host->clk); + clk_prepare_enable(host->clk); break; case MMC_POWER_ON: break; @@ -633,7 +640,7 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (gpio_is_valid(host->pdata->gpio_power)) gpio_set_value(host->pdata->gpio_power, host->pdata->power_active_low); - clk_disable(host->clk); + clk_disable_unprepare(host->clk); break; } @@ -649,35 +656,6 @@ static void jz4740_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } -static int jz4740_mmc_get_ro(struct mmc_host *mmc) -{ - struct jz4740_mmc_host *host = mmc_priv(mmc); - if (!gpio_is_valid(host->pdata->gpio_read_only)) - return -ENOSYS; - - return gpio_get_value(host->pdata->gpio_read_only) ^ - host->pdata->read_only_active_low; -} - -static int jz4740_mmc_get_cd(struct mmc_host *mmc) -{ - struct jz4740_mmc_host *host = mmc_priv(mmc); - if (!gpio_is_valid(host->pdata->gpio_card_detect)) - return -ENOSYS; - - return gpio_get_value(host->pdata->gpio_card_detect) ^ - host->pdata->card_detect_active_low; -} - -static irqreturn_t jz4740_mmc_card_detect_irq(int irq, void *devid) -{ - struct jz4740_mmc_host *host = devid; - - mmc_detect_change(host->mmc, HZ / 2); - - return IRQ_HANDLED; -} - static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct jz4740_mmc_host *host = mmc_priv(mmc); @@ -687,8 +665,8 @@ static void jz4740_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) static const struct mmc_host_ops jz4740_mmc_ops = { .request = jz4740_mmc_request, .set_ios = jz4740_mmc_set_ios, - .get_ro = jz4740_mmc_get_ro, - .get_cd = jz4740_mmc_get_cd, + .get_ro = mmc_gpio_get_ro, + .get_cd = mmc_gpio_get_cd, .enable_sdio_irq = jz4740_mmc_enable_sdio_irq, }; @@ -701,7 +679,7 @@ static const struct jz_gpio_bulk_request jz4740_mmc_pins[] = { JZ_GPIO_BULK_PIN(MSC_DATA3), }; -static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio, +static int jz4740_mmc_request_gpio(struct device *dev, int gpio, const char *name, bool output, int value) { int ret; @@ -723,58 +701,34 @@ static int __devinit jz4740_mmc_request_gpio(struct device *dev, int gpio, return 0; } -static int __devinit jz4740_mmc_request_gpios(struct platform_device *pdev) +static int jz4740_mmc_request_gpios(struct mmc_host *mmc, + struct platform_device *pdev) { - int ret; struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + int ret = 0; if (!pdata) return 0; - ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_card_detect, - "MMC detect change", false, 0); - if (ret) - goto err; - - ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_read_only, - "MMC read only", false, 0); - if (ret) - goto err_free_gpio_card_detect; - - ret = jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, - "MMC read only", true, pdata->power_active_low); - if (ret) - goto err_free_gpio_read_only; - - return 0; - -err_free_gpio_read_only: - if (gpio_is_valid(pdata->gpio_read_only)) - gpio_free(pdata->gpio_read_only); -err_free_gpio_card_detect: - if (gpio_is_valid(pdata->gpio_card_detect)) - gpio_free(pdata->gpio_card_detect); -err: - return ret; -} - -static int __devinit jz4740_mmc_request_cd_irq(struct platform_device *pdev, - struct jz4740_mmc_host *host) -{ - struct jz4740_mmc_platform_data *pdata = pdev->dev.platform_data; + if (!pdata->card_detect_active_low) + mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; + if (!pdata->read_only_active_low) + mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; - if (!gpio_is_valid(pdata->gpio_card_detect)) - return 0; + if (gpio_is_valid(pdata->gpio_card_detect)) { + ret = mmc_gpio_request_cd(mmc, pdata->gpio_card_detect, 0); + if (ret) + return ret; + } - host->card_detect_irq = gpio_to_irq(pdata->gpio_card_detect); - if (host->card_detect_irq < 0) { - dev_warn(&pdev->dev, "Failed to get card detect irq\n"); - return 0; + if (gpio_is_valid(pdata->gpio_read_only)) { + ret = mmc_gpio_request_ro(mmc, pdata->gpio_read_only); + if (ret) + return ret; } - return request_irq(host->card_detect_irq, jz4740_mmc_card_detect_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "MMC card detect", host); + return jz4740_mmc_request_gpio(&pdev->dev, pdata->gpio_power, + "MMC read only", true, pdata->power_active_low); } static void jz4740_mmc_free_gpios(struct platform_device *pdev) @@ -786,10 +740,6 @@ static void jz4740_mmc_free_gpios(struct platform_device *pdev) if (gpio_is_valid(pdata->gpio_power)) gpio_free(pdata->gpio_power); - if (gpio_is_valid(pdata->gpio_read_only)) - gpio_free(pdata->gpio_read_only); - if (gpio_is_valid(pdata->gpio_card_detect)) - gpio_free(pdata->gpio_card_detect); } static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) @@ -801,12 +751,13 @@ static inline size_t jz4740_mmc_num_pins(struct jz4740_mmc_host *host) return num_pins; } -static int __devinit jz4740_mmc_probe(struct platform_device* pdev) +static int jz4740_mmc_probe(struct platform_device* pdev) { int ret; struct mmc_host *mmc; struct jz4740_mmc_host *host; struct jz4740_mmc_platform_data *pdata; + struct resource *res; pdata = pdev->dev.platform_data; @@ -826,42 +777,27 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) goto err_free_host; } - host->clk = clk_get(&pdev->dev, "mmc"); - if (!host->clk) { - ret = -ENOENT; + host->clk = devm_clk_get(&pdev->dev, "mmc"); + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); dev_err(&pdev->dev, "Failed to get mmc clock\n"); goto err_free_host; } - host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!host->mem) { - ret = -ENOENT; - dev_err(&pdev->dev, "Failed to get base platform memory\n"); - goto err_clk_put; - } - - host->mem = request_mem_region(host->mem->start, - resource_size(host->mem), pdev->name); - if (!host->mem) { - ret = -EBUSY; - dev_err(&pdev->dev, "Failed to request base memory region\n"); - goto err_clk_put; - } - - host->base = ioremap_nocache(host->mem->start, resource_size(host->mem)); - if (!host->base) { - ret = -EBUSY; - dev_err(&pdev->dev, "Failed to ioremap base memory\n"); - goto err_release_mem_region; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + host->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(host->base)) { + ret = PTR_ERR(host->base); + goto err_free_host; } ret = jz_gpio_bulk_request(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); if (ret) { dev_err(&pdev->dev, "Failed to request mmc pins: %d\n", ret); - goto err_iounmap; + goto err_free_host; } - ret = jz4740_mmc_request_gpios(pdev); + ret = jz4740_mmc_request_gpios(mmc, pdev); if (ret) goto err_gpio_bulk_free; @@ -884,17 +820,11 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) spin_lock_init(&host->lock); host->irq_mask = 0xffff; - ret = jz4740_mmc_request_cd_irq(pdev, host); - if (ret) { - dev_err(&pdev->dev, "Failed to request card detect irq\n"); - goto err_free_gpios; - } - ret = request_threaded_irq(host->irq, jz_mmc_irq, jz_mmc_irq_worker, 0, dev_name(&pdev->dev), host); if (ret) { dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); - goto err_free_card_detect_irq; + goto err_free_gpios; } jz4740_mmc_reset(host); @@ -917,27 +847,17 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) err_free_irq: free_irq(host->irq, host); -err_free_card_detect_irq: - if (host->card_detect_irq >= 0) - free_irq(host->card_detect_irq, host); err_free_gpios: jz4740_mmc_free_gpios(pdev); err_gpio_bulk_free: jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); -err_iounmap: - iounmap(host->base); -err_release_mem_region: - release_mem_region(host->mem->start, resource_size(host->mem)); -err_clk_put: - clk_put(host->clk); err_free_host: - platform_set_drvdata(pdev, NULL); mmc_free_host(mmc); return ret; } -static int __devexit jz4740_mmc_remove(struct platform_device *pdev) +static int jz4740_mmc_remove(struct platform_device *pdev) { struct jz4740_mmc_host *host = platform_get_drvdata(pdev); @@ -948,31 +868,21 @@ static int __devexit jz4740_mmc_remove(struct platform_device *pdev) mmc_remove_host(host->mmc); free_irq(host->irq, host); - if (host->card_detect_irq >= 0) - free_irq(host->card_detect_irq, host); jz4740_mmc_free_gpios(pdev); jz_gpio_bulk_free(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); - iounmap(host->base); - release_mem_region(host->mem->start, resource_size(host->mem)); - - clk_put(host->clk); - - platform_set_drvdata(pdev, NULL); mmc_free_host(host->mmc); return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int jz4740_mmc_suspend(struct device *dev) { struct jz4740_mmc_host *host = dev_get_drvdata(dev); - mmc_suspend_host(host->mmc); - jz_gpio_bulk_suspend(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); return 0; @@ -984,18 +894,11 @@ static int jz4740_mmc_resume(struct device *dev) jz_gpio_bulk_resume(jz4740_mmc_pins, jz4740_mmc_num_pins(host)); - mmc_resume_host(host->mmc); - return 0; } -const struct dev_pm_ops jz4740_mmc_pm_ops = { - .suspend = jz4740_mmc_suspend, - .resume = jz4740_mmc_resume, - .poweroff = jz4740_mmc_suspend, - .restore = jz4740_mmc_resume, -}; - +static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend, + jz4740_mmc_resume); #define JZ4740_MMC_PM_OPS (&jz4740_mmc_pm_ops) #else #define JZ4740_MMC_PM_OPS NULL @@ -1003,7 +906,7 @@ const struct dev_pm_ops jz4740_mmc_pm_ops = { static struct platform_driver jz4740_mmc_driver = { .probe = jz4740_mmc_probe, - .remove = __devexit_p(jz4740_mmc_remove), + .remove = jz4740_mmc_remove, .driver = { .name = "jz4740-mmc", .owner = THIS_MODULE, @@ -1011,17 +914,7 @@ static struct platform_driver jz4740_mmc_driver = { }, }; -static int __init jz4740_mmc_init(void) -{ - return platform_driver_register(&jz4740_mmc_driver); -} -module_init(jz4740_mmc_init); - -static void __exit jz4740_mmc_exit(void) -{ - platform_driver_unregister(&jz4740_mmc_driver); -} -module_exit(jz4740_mmc_exit); +module_platform_driver(jz4740_mmc_driver); MODULE_DESCRIPTION("JZ4740 SD/MMC controller driver"); MODULE_LICENSE("GPL"); |
