summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2009-01-06 11:38:16 -0700
committerDan Williams <dan.j.williams@intel.com>2009-01-06 11:38:16 -0700
commit74465b4ff9ac1da503025c0a0042e023bfa6505c (patch)
treece63f4a4b055b65cae1edaddd334931bf512c76e /drivers
parent33df8ca068123457db56c316946a3c0e4ef787d6 (diff)
atmel-mci: convert to dma_request_channel and down-level dma_slave
dma_request_channel provides an exclusive channel, so we no longer need to pass slave data through dmaengine. Cc: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> Reviewed-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/dmaengine.c8
-rw-r--r--drivers/dma/dw_dmac.c25
-rw-r--r--drivers/mmc/host/atmel-mci.c98
3 files changed, 33 insertions, 98 deletions
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 7a0594f24a3f..90aca505a1df 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -234,10 +234,6 @@ static void dma_client_chan_alloc(struct dma_client *client)
list_for_each_entry(device, &dma_device_list, global_node) {
if (dma_has_cap(DMA_PRIVATE, device->cap_mask))
continue;
- /* Does the client require a specific DMA controller? */
- if (client->slave && client->slave->dma_dev
- && client->slave->dma_dev != device->dev)
- continue;
if (!dma_device_satisfies_mask(device, client->cap_mask))
continue;
@@ -613,10 +609,6 @@ void dma_async_client_register(struct dma_client *client)
struct dma_chan *chan;
int err;
- /* validate client data */
- BUG_ON(dma_has_cap(DMA_SLAVE, client->cap_mask) &&
- !client->slave);
-
mutex_lock(&dma_list_mutex);
dmaengine_ref_count++;
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 377dafa37a20..dbd50804e5d2 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -567,7 +567,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
if (unlikely(!dws || !sg_len))
return NULL;
- reg_width = dws->slave.reg_width;
+ reg_width = dws->reg_width;
prev = first = NULL;
sg_len = dma_map_sg(chan->dev.parent, sgl, sg_len, direction);
@@ -579,7 +579,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
| DWC_CTLL_DST_FIX
| DWC_CTLL_SRC_INC
| DWC_CTLL_FC_M2P);
- reg = dws->slave.tx_reg;
+ reg = dws->tx_reg;
for_each_sg(sgl, sg, sg_len, i) {
struct dw_desc *desc;
u32 len;
@@ -625,7 +625,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
| DWC_CTLL_SRC_FIX
| DWC_CTLL_FC_P2M);
- reg = dws->slave.rx_reg;
+ reg = dws->rx_reg;
for_each_sg(sgl, sg, sg_len, i) {
struct dw_desc *desc;
u32 len;
@@ -764,7 +764,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan,
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
struct dw_dma *dw = to_dw_dma(chan->device);
struct dw_desc *desc;
- struct dma_slave *slave;
struct dw_dma_slave *dws;
int i;
u32 cfghi;
@@ -772,12 +771,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan,
dev_vdbg(&chan->dev, "alloc_chan_resources\n");
- /* Channels doing slave DMA can only handle one client. */
- if (dwc->dws || (client && client->slave)) {
- if (chan->client_count)
- return -EBUSY;
- }
-
/* ASSERT: channel is idle */
if (dma_readl(dw, CH_EN) & dwc->mask) {
dev_dbg(&chan->dev, "DMA channel not idle?\n");
@@ -789,23 +782,17 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan,
cfghi = DWC_CFGH_FIFO_MODE;
cfglo = 0;
- slave = client->slave;
- if (slave) {
+ dws = dwc->dws;
+ if (dws) {
/*
* We need controller-specific data to set up slave
* transfers.
*/
- BUG_ON(!slave->dma_dev || slave->dma_dev != dw->dma.dev);
-
- dws = container_of(slave, struct dw_dma_slave, slave);
+ BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
- dwc->dws = dws;
cfghi = dws->cfg_hi;
cfglo = dws->cfg_lo;
- } else {
- dwc->dws = NULL;
}
-
channel_writel(dwc, CFG_LO, cfglo);
channel_writel(dwc, CFG_HI, cfghi);
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 6c11f4d4c4e9..7a34118507db 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -1441,60 +1441,6 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-#ifdef CONFIG_MMC_ATMELMCI_DMA
-
-static inline struct atmel_mci *
-dma_client_to_atmel_mci(struct dma_client *client)
-{
- return container_of(client, struct atmel_mci, dma.client);
-}
-
-static enum dma_state_client atmci_dma_event(struct dma_client *client,
- struct dma_chan *chan, enum dma_state state)
-{
- struct atmel_mci *host;
- enum dma_state_client ret = DMA_NAK;
-
- host = dma_client_to_atmel_mci(client);
-
- switch (state) {
- case DMA_RESOURCE_AVAILABLE:
- spin_lock_bh(&host->lock);
- if (!host->dma.chan) {
- host->dma.chan = chan;
- ret = DMA_ACK;
- }
- spin_unlock_bh(&host->lock);
-
- if (ret == DMA_ACK)
- dev_info(&host->pdev->dev,
- "Using %s for DMA transfers\n",
- chan->dev.bus_id);
- break;
-
- case DMA_RESOURCE_REMOVED:
- spin_lock_bh(&host->lock);
- if (host->dma.chan == chan) {
- host->dma.chan = NULL;
- ret = DMA_ACK;
- }
- spin_unlock_bh(&host->lock);
-
- if (ret == DMA_ACK)
- dev_info(&host->pdev->dev,
- "Lost %s, falling back to PIO\n",
- chan->dev.bus_id);
- break;
-
- default:
- break;
- }
-
-
- return ret;
-}
-#endif /* CONFIG_MMC_ATMELMCI_DMA */
-
static int __init atmci_init_slot(struct atmel_mci *host,
struct mci_slot_pdata *slot_data, unsigned int id,
u32 sdc_reg)
@@ -1598,6 +1544,18 @@ static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot,
mmc_free_host(slot->mmc);
}
+#ifdef CONFIG_MMC_ATMELMCI_DMA
+static enum dma_state_client filter(struct dma_chan *chan, void *slave)
+{
+ struct dw_dma_slave *dws = slave;
+
+ if (dws->dma_dev == chan->device->dev)
+ return DMA_ACK;
+ else
+ return DMA_DUP;
+}
+#endif
+
static int __init atmci_probe(struct platform_device *pdev)
{
struct mci_platform_data *pdata;
@@ -1650,22 +1608,20 @@ static int __init atmci_probe(struct platform_device *pdev)
goto err_request_irq;
#ifdef CONFIG_MMC_ATMELMCI_DMA
- if (pdata->dma_slave) {
- struct dma_slave *slave = pdata->dma_slave;
+ if (pdata->dma_slave.dma_dev) {
+ struct dw_dma_slave *dws = &pdata->dma_slave;
+ dma_cap_mask_t mask;
- slave->tx_reg = regs->start + MCI_TDR;
- slave->rx_reg = regs->start + MCI_RDR;
+ dws->tx_reg = regs->start + MCI_TDR;
+ dws->rx_reg = regs->start + MCI_RDR;
/* Try to grab a DMA channel */
- host->dma.client.event_callback = atmci_dma_event;
- dma_cap_set(DMA_SLAVE, host->dma.client.cap_mask);
- host->dma.client.slave = slave;
-
- dma_async_client_register(&host->dma.client);
- dma_async_client_chan_request(&host->dma.client);
- } else {
- dev_notice(&pdev->dev, "DMA not available, using PIO\n");
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ host->dma.chan = dma_request_channel(mask, filter, dws);
}
+ if (!host->dma.chan)
+ dev_notice(&pdev->dev, "DMA not available, using PIO\n");
#endif /* CONFIG_MMC_ATMELMCI_DMA */
platform_set_drvdata(pdev, host);
@@ -1697,8 +1653,8 @@ static int __init atmci_probe(struct platform_device *pdev)
err_init_slot:
#ifdef CONFIG_MMC_ATMELMCI_DMA
- if (pdata->dma_slave)
- dma_async_client_unregister(&host->dma.client);
+ if (host->dma.chan)
+ dma_release_channel(host->dma.chan);
#endif
free_irq(irq, host);
err_request_irq:
@@ -1729,8 +1685,8 @@ static int __exit atmci_remove(struct platform_device *pdev)
clk_disable(host->mck);
#ifdef CONFIG_MMC_ATMELMCI_DMA
- if (host->dma.client.slave)
- dma_async_client_unregister(&host->dma.client);
+ if (host->dma.chan)
+ dma_release_channel(host->dma.chan);
#endif
free_irq(platform_get_irq(pdev, 0), host);
@@ -1759,7 +1715,7 @@ static void __exit atmci_exit(void)
platform_driver_unregister(&atmci_driver);
}
-module_init(atmci_init);
+late_initcall(atmci_init); /* try to load after dma driver when built-in */
module_exit(atmci_exit);
MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver");