diff options
Diffstat (limited to 'drivers/ata/pata_arasan_cf.c')
| -rw-r--r-- | drivers/ata/pata_arasan_cf.c | 85 |
1 files changed, 46 insertions, 39 deletions
diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 848ed3254ddd..514d549286b5 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -4,7 +4,7 @@ * Arasan Compact Flash host controller source file * * Copyright (C) 2011 ST Microelectronics - * Viresh Kumar <viresh.linux@gmail.com> + * Viresh Kumar <vireshk@kernel.org> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -39,6 +39,7 @@ #include <linux/spinlock.h> #include <linux/types.h> #include <linux/workqueue.h> +#include <trace/events/libata.h> #define DRIVER_NAME "arasan_cf" #define TIMEOUT msecs_to_jiffies(3000) @@ -217,9 +218,8 @@ struct arasan_cf_dev { struct ata_queued_cmd *qc; }; -static struct scsi_host_template arasan_cf_sht = { +static const struct scsi_host_template arasan_cf_sht = { ATA_BASE_SHT(DRIVER_NAME), - .sg_tablesize = SG_NONE, .dma_boundary = 0xFFFFFFFFUL, }; @@ -319,6 +319,7 @@ static int cf_init(struct arasan_cf_dev *acdev) ret = clk_set_rate(acdev->clk, 166000000); if (ret) { dev_warn(acdev->host->dev, "clock set rate failed"); + clk_disable_unprepare(acdev->clk); return ret; } @@ -355,7 +356,7 @@ static void cf_exit(struct arasan_cf_dev *acdev) static void dma_callback(void *dev) { - struct arasan_cf_dev *acdev = (struct arasan_cf_dev *) dev; + struct arasan_cf_dev *acdev = dev; complete(&acdev->dma_completion); } @@ -396,8 +397,7 @@ dma_xfer(struct arasan_cf_dev *acdev, dma_addr_t src, dma_addr_t dest, u32 len) struct dma_async_tx_descriptor *tx; struct dma_chan *chan = acdev->dma_chan; dma_cookie_t cookie; - unsigned long flags = DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP | - DMA_COMPL_SKIP_DEST_UNMAP; + unsigned long flags = DMA_PREP_INTERRUPT; int ret = 0; tx = chan->device->device_prep_dma_memcpy(chan, dest, src, len, flags); @@ -420,7 +420,7 @@ dma_xfer(struct arasan_cf_dev *acdev, dma_addr_t src, dma_addr_t dest, u32 len) /* Wait for DMA to complete */ if (!wait_for_completion_timeout(&acdev->dma_completion, TIMEOUT)) { - chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + dmaengine_terminate_all(chan); dev_err(acdev->host->dev, "wait_for_completion_timeout\n"); return -ETIMEDOUT; } @@ -527,9 +527,11 @@ static void data_xfer(struct work_struct *work) /* request dma channels */ /* dma_request_channel may sleep, so calling from process context */ - acdev->dma_chan = dma_request_slave_channel(acdev->host->dev, "data"); - if (!acdev->dma_chan) { - dev_err(acdev->host->dev, "Unable to get dma_chan\n"); + acdev->dma_chan = dma_request_chan(acdev->host->dev, "data"); + if (IS_ERR(acdev->dma_chan)) { + dev_err_probe(acdev->host->dev, PTR_ERR(acdev->dma_chan), + "Unable to get dma_chan\n"); + acdev->dma_chan = NULL; goto chan_request_fail; } @@ -540,6 +542,7 @@ static void data_xfer(struct work_struct *work) } dma_release_channel(acdev->dma_chan); + acdev->dma_chan = NULL; /* data xferred successfully */ if (!ret) { @@ -565,7 +568,7 @@ chan_request_fail: qc->ap->hsm_task_state = HSM_ST_ERR; cf_ctrl_reset(acdev); - spin_unlock_irqrestore(qc->ap->lock, flags); + spin_unlock_irqrestore(&acdev->host->lock, flags); sff_intr: dma_complete(acdev); } @@ -654,7 +657,7 @@ static void arasan_cf_freeze(struct ata_port *ap) ata_sff_freeze(ap); } -void arasan_cf_error_handler(struct ata_port *ap) +static void arasan_cf_error_handler(struct ata_port *ap) { struct arasan_cf_dev *acdev = ap->host->private_data; @@ -683,7 +686,7 @@ static void arasan_cf_dma_start(struct arasan_cf_dev *acdev) ata_sff_queue_work(&acdev->work); } -unsigned int arasan_cf_qc_issue(struct ata_queued_cmd *qc) +static unsigned int arasan_cf_qc_issue(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; struct arasan_cf_dev *acdev = ap->host->private_data; @@ -702,9 +705,11 @@ unsigned int arasan_cf_qc_issue(struct ata_queued_cmd *qc) case ATA_PROT_DMA: WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING); + trace_ata_tf_load(ap, &qc->tf); ap->ops->sff_tf_load(ap, &qc->tf); acdev->dma_status = 0; acdev->qc = qc; + trace_ata_bmdma_start(ap, &qc->tf, qc->tag); arasan_cf_dma_start(acdev); ap->hsm_task_state = HSM_ST_LAST; break; @@ -796,7 +801,7 @@ static int arasan_cf_probe(struct platform_device *pdev) struct resource *res; u32 quirk; irq_handler_t irq_handler = NULL; - int ret = 0; + int ret; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -809,32 +814,37 @@ static int arasan_cf_probe(struct platform_device *pdev) } acdev = devm_kzalloc(&pdev->dev, sizeof(*acdev), GFP_KERNEL); - if (!acdev) { - dev_warn(&pdev->dev, "kzalloc fail\n"); + if (!acdev) return -ENOMEM; - } if (pdata) quirk = pdata->quirk; else quirk = CF_BROKEN_UDMA; /* as it is on spear1340 */ - /* if irq is 0, support only PIO */ - acdev->irq = platform_get_irq(pdev, 0); - if (acdev->irq) + /* + * If there's an error getting IRQ (or we do get IRQ0), + * support only PIO + */ + ret = platform_get_irq(pdev, 0); + if (ret > 0) { + acdev->irq = ret; irq_handler = arasan_cf_interrupt; - else + } else if (ret == -EPROBE_DEFER) { + return ret; + } else { quirk |= CF_BROKEN_MWDMA | CF_BROKEN_UDMA; + } acdev->pbase = res->start; - acdev->vbase = devm_ioremap_nocache(&pdev->dev, res->start, + acdev->vbase = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!acdev->vbase) { dev_warn(&pdev->dev, "ioremap fail\n"); return -ENOMEM; } - acdev->clk = clk_get(&pdev->dev, NULL); + acdev->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(acdev->clk)) { dev_warn(&pdev->dev, "Clock not found\n"); return PTR_ERR(acdev->clk); @@ -843,9 +853,8 @@ static int arasan_cf_probe(struct platform_device *pdev) /* allocate host */ host = ata_host_alloc(&pdev->dev, 1); if (!host) { - ret = -ENOMEM; dev_warn(&pdev->dev, "alloc host fail\n"); - goto free_clk; + return -ENOMEM; } ap = host->ports[0]; @@ -894,28 +903,27 @@ static int arasan_cf_probe(struct platform_device *pdev) ret = cf_init(acdev); if (ret) - goto free_clk; + return ret; cf_card_detect(acdev, 0); - return ata_host_activate(host, acdev->irq, irq_handler, 0, - &arasan_cf_sht); + ret = ata_host_activate(host, acdev->irq, irq_handler, 0, + &arasan_cf_sht); + if (!ret) + return 0; + + cf_exit(acdev); -free_clk: - clk_put(acdev->clk); return ret; } -static int arasan_cf_remove(struct platform_device *pdev) +static void arasan_cf_remove(struct platform_device *pdev) { struct ata_host *host = platform_get_drvdata(pdev); struct arasan_cf_dev *acdev = host->ports[0]->private_data; ata_host_detach(host); cf_exit(acdev); - clk_put(acdev->clk); - - return 0; } #ifdef CONFIG_PM_SLEEP @@ -925,11 +933,11 @@ static int arasan_cf_suspend(struct device *dev) struct arasan_cf_dev *acdev = host->ports[0]->private_data; if (acdev->dma_chan) - acdev->dma_chan->device->device_control(acdev->dma_chan, - DMA_TERMINATE_ALL, 0); + dmaengine_terminate_all(acdev->dma_chan); cf_exit(acdev); - return ata_host_suspend(host, PMSG_SUSPEND); + ata_host_suspend(host, PMSG_SUSPEND); + return 0; } static int arasan_cf_resume(struct device *dev) @@ -959,7 +967,6 @@ static struct platform_driver arasan_cf_driver = { .remove = arasan_cf_remove, .driver = { .name = DRIVER_NAME, - .owner = THIS_MODULE, .pm = &arasan_cf_pm_ops, .of_match_table = of_match_ptr(arasan_cf_id_table), }, @@ -967,7 +974,7 @@ static struct platform_driver arasan_cf_driver = { module_platform_driver(arasan_cf_driver); -MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>"); +MODULE_AUTHOR("Viresh Kumar <vireshk@kernel.org>"); MODULE_DESCRIPTION("Arasan ATA Compact Flash driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:" DRIVER_NAME); |
