summaryrefslogtreecommitdiff
path: root/drivers/ata/pata_arasan_cf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/pata_arasan_cf.c')
-rw-r--r--drivers/ata/pata_arasan_cf.c85
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);