Commit 1273bc57 authored by Robert Jarzmik's avatar Robert Jarzmik Committed by David S. Miller

net: irda: pxaficp_ir: dmaengine conversion

Convert pxaficp_ir to dmaengine. As pxa architecture is shifting from
raw DMA registers access to pxa_dma dmaengine driver, convert this
driver to dmaengine.
Signed-off-by: default avatarRobert Jarzmik <robert.jarzmik@free.fr>
Tested-by: default avatarPetr Cvek <petr.cvek@tul.cz>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 89fa5724
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/dma/pxa-dma.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -27,7 +30,6 @@ ...@@ -27,7 +30,6 @@
#include <net/irda/wrapper.h> #include <net/irda/wrapper.h>
#include <net/irda/irda_device.h> #include <net/irda/irda_device.h>
#include <mach/dma.h>
#include <linux/platform_data/irda-pxaficp.h> #include <linux/platform_data/irda-pxaficp.h>
#undef __REG #undef __REG
#define __REG(x) ((x) & 0xffff) #define __REG(x) ((x) & 0xffff)
...@@ -146,8 +148,12 @@ struct pxa_irda { ...@@ -146,8 +148,12 @@ struct pxa_irda {
dma_addr_t dma_rx_buff_phy; dma_addr_t dma_rx_buff_phy;
dma_addr_t dma_tx_buff_phy; dma_addr_t dma_tx_buff_phy;
unsigned int dma_tx_buff_len; unsigned int dma_tx_buff_len;
int txdma; struct dma_chan *txdma;
int rxdma; struct dma_chan *rxdma;
dma_cookie_t rx_cookie;
dma_cookie_t tx_cookie;
int drcmr_rx;
int drcmr_tx;
int uart_irq; int uart_irq;
int icp_irq; int icp_irq;
...@@ -165,6 +171,8 @@ struct pxa_irda { ...@@ -165,6 +171,8 @@ struct pxa_irda {
struct clk *cur_clk; struct clk *cur_clk;
}; };
static int pxa_irda_set_speed(struct pxa_irda *si, int speed);
static inline void pxa_irda_disable_clk(struct pxa_irda *si) static inline void pxa_irda_disable_clk(struct pxa_irda *si)
{ {
if (si->cur_clk) if (si->cur_clk)
...@@ -188,22 +196,41 @@ static inline void pxa_irda_enable_sirclk(struct pxa_irda *si) ...@@ -188,22 +196,41 @@ static inline void pxa_irda_enable_sirclk(struct pxa_irda *si)
#define IS_FIR(si) ((si)->speed >= 4000000) #define IS_FIR(si) ((si)->speed >= 4000000)
#define IRDA_FRAME_SIZE_LIMIT 2047 #define IRDA_FRAME_SIZE_LIMIT 2047
static void pxa_irda_fir_dma_rx_irq(void *data);
static void pxa_irda_fir_dma_tx_irq(void *data);
inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si) inline static void pxa_irda_fir_dma_rx_start(struct pxa_irda *si)
{ {
DCSR(si->rxdma) = DCSR_NODESC; struct dma_async_tx_descriptor *tx;
DSADR(si->rxdma) = (unsigned long)si->irda_base + ICDR;
DTADR(si->rxdma) = si->dma_rx_buff_phy; tx = dmaengine_prep_slave_single(si->rxdma, si->dma_rx_buff_phy,
DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT; IRDA_FRAME_SIZE_LIMIT, DMA_FROM_DEVICE,
DCSR(si->rxdma) |= DCSR_RUN; DMA_PREP_INTERRUPT);
if (!tx) {
dev_err(si->dev, "prep_slave_sg() failed\n");
return;
}
tx->callback = pxa_irda_fir_dma_rx_irq;
tx->callback_param = si;
si->rx_cookie = dmaengine_submit(tx);
dma_async_issue_pending(si->rxdma);
} }
inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si) inline static void pxa_irda_fir_dma_tx_start(struct pxa_irda *si)
{ {
DCSR(si->txdma) = DCSR_NODESC; struct dma_async_tx_descriptor *tx;
DSADR(si->txdma) = si->dma_tx_buff_phy;
DTADR(si->txdma) = (unsigned long)si->irda_base + ICDR; tx = dmaengine_prep_slave_single(si->txdma, si->dma_tx_buff_phy,
DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len; si->dma_tx_buff_len, DMA_TO_DEVICE,
DCSR(si->txdma) |= DCSR_RUN; DMA_PREP_INTERRUPT);
if (!tx) {
dev_err(si->dev, "prep_slave_sg() failed\n");
return;
}
tx->callback = pxa_irda_fir_dma_tx_irq;
tx->callback_param = si;
si->tx_cookie = dmaengine_submit(tx);
dma_async_issue_pending(si->rxdma);
} }
/* /*
...@@ -242,7 +269,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed) ...@@ -242,7 +269,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
if (IS_FIR(si)) { if (IS_FIR(si)) {
/* stop RX DMA */ /* stop RX DMA */
DCSR(si->rxdma) &= ~DCSR_RUN; dmaengine_terminate_all(si->rxdma);
/* disable FICP */ /* disable FICP */
ficp_writel(si, 0, ICCR0); ficp_writel(si, 0, ICCR0);
pxa_irda_disable_clk(si); pxa_irda_disable_clk(si);
...@@ -388,30 +415,27 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) ...@@ -388,30 +415,27 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
} }
/* FIR Receive DMA interrupt handler */ /* FIR Receive DMA interrupt handler */
static void pxa_irda_fir_dma_rx_irq(int channel, void *data) static void pxa_irda_fir_dma_rx_irq(void *data)
{ {
int dcsr = DCSR(channel); struct net_device *dev = data;
struct pxa_irda *si = netdev_priv(dev);
DCSR(channel) = dcsr & ~DCSR_RUN;
printk(KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n", dcsr); dmaengine_terminate_all(si->rxdma);
netdev_dbg(dev, "pxa_ir: fir rx dma bus error\n");
} }
/* FIR Transmit DMA interrupt handler */ /* FIR Transmit DMA interrupt handler */
static void pxa_irda_fir_dma_tx_irq(int channel, void *data) static void pxa_irda_fir_dma_tx_irq(void *data)
{ {
struct net_device *dev = data; struct net_device *dev = data;
struct pxa_irda *si = netdev_priv(dev); struct pxa_irda *si = netdev_priv(dev);
int dcsr;
dcsr = DCSR(channel);
DCSR(channel) = dcsr & ~DCSR_RUN;
if (dcsr & DCSR_ENDINTR) { dmaengine_terminate_all(si->txdma);
if (dmaengine_tx_status(si->txdma, si->tx_cookie, NULL) == DMA_ERROR) {
dev->stats.tx_errors++;
} else {
dev->stats.tx_packets++; dev->stats.tx_packets++;
dev->stats.tx_bytes += si->dma_tx_buff_len; dev->stats.tx_bytes += si->dma_tx_buff_len;
} else {
dev->stats.tx_errors++;
} }
while (ficp_readl(si, ICSR1) & ICSR1_TBY) while (ficp_readl(si, ICSR1) & ICSR1_TBY)
...@@ -446,9 +470,12 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) ...@@ -446,9 +470,12 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0) static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, int icsr0)
{ {
unsigned int len, stat, data; unsigned int len, stat, data;
struct dma_tx_state state;
/* Get the current data position. */ /* Get the current data position. */
len = DTADR(si->rxdma) - si->dma_rx_buff_phy;
dmaengine_tx_status(si->rxdma, si->rx_cookie, &state);
len = IRDA_FRAME_SIZE_LIMIT - state.residue;
do { do {
/* Read Status, and then Data. */ /* Read Status, and then Data. */
...@@ -515,7 +542,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) ...@@ -515,7 +542,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
int icsr0, i = 64; int icsr0, i = 64;
/* stop RX DMA */ /* stop RX DMA */
DCSR(si->rxdma) &= ~DCSR_RUN; dmaengine_terminate_all(si->rxdma);
si->last_clk = sched_clock(); si->last_clk = sched_clock();
icsr0 = ficp_readl(si, ICSR0); icsr0 = ficp_readl(si, ICSR0);
...@@ -597,7 +624,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -597,7 +624,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
cpu_relax(); cpu_relax();
/* stop RX DMA, disable FICP */ /* stop RX DMA, disable FICP */
DCSR(si->rxdma) &= ~DCSR_RUN; dmaengine_terminate_all(si->rxdma);
ficp_writel(si, 0, ICCR0); ficp_writel(si, 0, ICCR0);
pxa_irda_fir_dma_tx_start(si); pxa_irda_fir_dma_tx_start(si);
...@@ -670,10 +697,6 @@ static void pxa_irda_startup(struct pxa_irda *si) ...@@ -670,10 +697,6 @@ static void pxa_irda_startup(struct pxa_irda *si)
/* configure FICP ICCR2 */ /* configure FICP ICCR2 */
ficp_writel(si, ICCR2_TXP | ICCR2_TRIG_32, ICCR2); ficp_writel(si, ICCR2_TXP | ICCR2_TRIG_32, ICCR2);
/* configure DMAC */
DRCMR(17) = si->rxdma | DRCMR_MAPVLD;
DRCMR(18) = si->txdma | DRCMR_MAPVLD;
/* force SIR reinitialization */ /* force SIR reinitialization */
si->speed = 4000000; si->speed = 4000000;
pxa_irda_set_speed(si, 9600); pxa_irda_set_speed(si, 9600);
...@@ -693,17 +716,14 @@ static void pxa_irda_shutdown(struct pxa_irda *si) ...@@ -693,17 +716,14 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
stuart_writel(si, 0, STISR); stuart_writel(si, 0, STISR);
/* disable DMA */ /* disable DMA */
DCSR(si->txdma) &= ~DCSR_RUN; dmaengine_terminate_all(si->rxdma);
DCSR(si->rxdma) &= ~DCSR_RUN; dmaengine_terminate_all(si->txdma);
/* disable FICP */ /* disable FICP */
ficp_writel(si, 0, ICCR0); ficp_writel(si, 0, ICCR0);
/* disable the STUART or FICP clocks */ /* disable the STUART or FICP clocks */
pxa_irda_disable_clk(si); pxa_irda_disable_clk(si);
DRCMR(17) = 0;
DRCMR(18) = 0;
local_irq_restore(flags); local_irq_restore(flags);
/* power off board transceiver */ /* power off board transceiver */
...@@ -715,6 +735,9 @@ static void pxa_irda_shutdown(struct pxa_irda *si) ...@@ -715,6 +735,9 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
static int pxa_irda_start(struct net_device *dev) static int pxa_irda_start(struct net_device *dev)
{ {
struct pxa_irda *si = netdev_priv(dev); struct pxa_irda *si = netdev_priv(dev);
dma_cap_mask_t mask;
struct dma_slave_config config;
struct pxad_param param;
int err; int err;
si->speed = 9600; si->speed = 9600;
...@@ -734,14 +757,37 @@ static int pxa_irda_start(struct net_device *dev) ...@@ -734,14 +757,37 @@ static int pxa_irda_start(struct net_device *dev)
disable_irq(si->icp_irq); disable_irq(si->icp_irq);
err = -EBUSY; err = -EBUSY;
si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev); dma_cap_zero(mask);
if (si->rxdma < 0) dma_cap_set(DMA_SLAVE, mask);
param.prio = PXAD_PRIO_LOWEST;
memset(&config, 0, sizeof(config));
config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
config.src_addr = (dma_addr_t)si->irda_base + ICDR;
config.dst_addr = (dma_addr_t)si->irda_base + ICDR;
config.src_maxburst = 32;
config.dst_maxburst = 32;
param.drcmr = si->drcmr_rx;
si->rxdma = dma_request_slave_channel_compat(mask, pxad_filter_fn,
&param, &dev->dev, "rx");
if (!si->rxdma)
goto err_rx_dma; goto err_rx_dma;
si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev); param.drcmr = si->drcmr_tx;
if (si->txdma < 0) si->txdma = dma_request_slave_channel_compat(mask, pxad_filter_fn,
&param, &dev->dev, "tx");
if (!si->txdma)
goto err_tx_dma; goto err_tx_dma;
err = dmaengine_slave_config(si->rxdma, &config);
if (err)
goto err_dma_rx_buff;
err = dmaengine_slave_config(si->txdma, &config);
if (err)
goto err_dma_rx_buff;
err = -ENOMEM; err = -ENOMEM;
si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
&si->dma_rx_buff_phy, GFP_KERNEL); &si->dma_rx_buff_phy, GFP_KERNEL);
...@@ -781,9 +827,9 @@ static int pxa_irda_start(struct net_device *dev) ...@@ -781,9 +827,9 @@ static int pxa_irda_start(struct net_device *dev)
err_dma_tx_buff: err_dma_tx_buff:
dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy); dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
err_dma_rx_buff: err_dma_rx_buff:
pxa_free_dma(si->txdma); dma_release_channel(si->txdma);
err_tx_dma: err_tx_dma:
pxa_free_dma(si->rxdma); dma_release_channel(si->rxdma);
err_rx_dma: err_rx_dma:
free_irq(si->icp_irq, dev); free_irq(si->icp_irq, dev);
err_irq2: err_irq2:
...@@ -810,8 +856,10 @@ static int pxa_irda_stop(struct net_device *dev) ...@@ -810,8 +856,10 @@ static int pxa_irda_stop(struct net_device *dev)
free_irq(si->uart_irq, dev); free_irq(si->uart_irq, dev);
free_irq(si->icp_irq, dev); free_irq(si->icp_irq, dev);
pxa_free_dma(si->rxdma); dmaengine_terminate_all(si->rxdma);
pxa_free_dma(si->txdma); dmaengine_terminate_all(si->txdma);
dma_release_channel(si->rxdma);
dma_release_channel(si->txdma);
if (si->dma_rx_buff) if (si->dma_rx_buff)
dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy); dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy);
...@@ -920,6 +968,13 @@ static int pxa_irda_probe(struct platform_device *pdev) ...@@ -920,6 +968,13 @@ static int pxa_irda_probe(struct platform_device *pdev)
goto err_mem_4; goto err_mem_4;
} }
res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (res)
si->drcmr_rx = res->start;
res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
if (res)
si->drcmr_tx = res->start;
/* /*
* Initialise the SIR buffers * Initialise the SIR buffers
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment