1
0
Fork 0

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: Robert Jarzmik <robert.jarzmik@free.fr>
Tested-by: Petr Cvek <petr.cvek@tul.cz>
Signed-off-by: David S. Miller <davem@davemloft.net>
steinar/wifi_calib_4_9_kernel
Robert Jarzmik 2015-09-26 20:49:20 +02:00 committed by David S. Miller
parent 89fa57244a
commit 1273bc573a
1 changed files with 106 additions and 51 deletions

View File

@ -19,6 +19,9 @@
#include <linux/etherdevice.h>
#include <linux/platform_device.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/slab.h>
@ -27,7 +30,6 @@
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
#include <mach/dma.h>
#include <linux/platform_data/irda-pxaficp.h>
#undef __REG
#define __REG(x) ((x) & 0xffff)
@ -146,8 +148,12 @@ struct pxa_irda {
dma_addr_t dma_rx_buff_phy;
dma_addr_t dma_tx_buff_phy;
unsigned int dma_tx_buff_len;
int txdma;
int rxdma;
struct dma_chan *txdma;
struct dma_chan *rxdma;
dma_cookie_t rx_cookie;
dma_cookie_t tx_cookie;
int drcmr_rx;
int drcmr_tx;
int uart_irq;
int icp_irq;
@ -165,6 +171,8 @@ struct pxa_irda {
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)
{
if (si->cur_clk)
@ -188,22 +196,41 @@ static inline void pxa_irda_enable_sirclk(struct pxa_irda *si)
#define IS_FIR(si) ((si)->speed >= 4000000)
#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)
{
DCSR(si->rxdma) = DCSR_NODESC;
DSADR(si->rxdma) = (unsigned long)si->irda_base + ICDR;
DTADR(si->rxdma) = si->dma_rx_buff_phy;
DCMD(si->rxdma) = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_WIDTH1 | DCMD_BURST32 | IRDA_FRAME_SIZE_LIMIT;
DCSR(si->rxdma) |= DCSR_RUN;
struct dma_async_tx_descriptor *tx;
tx = dmaengine_prep_slave_single(si->rxdma, si->dma_rx_buff_phy,
IRDA_FRAME_SIZE_LIMIT, DMA_FROM_DEVICE,
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)
{
DCSR(si->txdma) = DCSR_NODESC;
DSADR(si->txdma) = si->dma_tx_buff_phy;
DTADR(si->txdma) = (unsigned long)si->irda_base + ICDR;
DCMD(si->txdma) = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_ENDIRQEN | DCMD_WIDTH1 | DCMD_BURST32 | si->dma_tx_buff_len;
DCSR(si->txdma) |= DCSR_RUN;
struct dma_async_tx_descriptor *tx;
tx = dmaengine_prep_slave_single(si->txdma, si->dma_tx_buff_phy,
si->dma_tx_buff_len, DMA_TO_DEVICE,
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)
if (IS_FIR(si)) {
/* stop RX DMA */
DCSR(si->rxdma) &= ~DCSR_RUN;
dmaengine_terminate_all(si->rxdma);
/* disable FICP */
ficp_writel(si, 0, ICCR0);
pxa_irda_disable_clk(si);
@ -388,30 +415,27 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
}
/* FIR Receive DMA interrupt handler */
static void pxa_irda_fir_dma_rx_irq(int channel, void *data)
{
int dcsr = DCSR(channel);
DCSR(channel) = dcsr & ~DCSR_RUN;
printk(KERN_DEBUG "pxa_ir: fir rx dma bus error %#x\n", dcsr);
}
/* FIR Transmit DMA interrupt handler */
static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
static void pxa_irda_fir_dma_rx_irq(void *data)
{
struct net_device *dev = data;
struct pxa_irda *si = netdev_priv(dev);
int dcsr;
dcsr = DCSR(channel);
DCSR(channel) = dcsr & ~DCSR_RUN;
dmaengine_terminate_all(si->rxdma);
netdev_dbg(dev, "pxa_ir: fir rx dma bus error\n");
}
if (dcsr & DCSR_ENDINTR) {
/* FIR Transmit DMA interrupt handler */
static void pxa_irda_fir_dma_tx_irq(void *data)
{
struct net_device *dev = data;
struct pxa_irda *si = netdev_priv(dev);
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_bytes += si->dma_tx_buff_len;
} else {
dev->stats.tx_errors++;
}
while (ficp_readl(si, ICSR1) & ICSR1_TBY)
@ -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)
{
unsigned int len, stat, data;
struct dma_tx_state state;
/* 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 {
/* Read Status, and then Data. */
@ -515,7 +542,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
int icsr0, i = 64;
/* stop RX DMA */
DCSR(si->rxdma) &= ~DCSR_RUN;
dmaengine_terminate_all(si->rxdma);
si->last_clk = sched_clock();
icsr0 = ficp_readl(si, ICSR0);
@ -597,7 +624,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
cpu_relax();
/* stop RX DMA, disable FICP */
DCSR(si->rxdma) &= ~DCSR_RUN;
dmaengine_terminate_all(si->rxdma);
ficp_writel(si, 0, ICCR0);
pxa_irda_fir_dma_tx_start(si);
@ -670,10 +697,6 @@ static void pxa_irda_startup(struct pxa_irda *si)
/* configure FICP 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 */
si->speed = 4000000;
pxa_irda_set_speed(si, 9600);
@ -693,17 +716,14 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
stuart_writel(si, 0, STISR);
/* disable DMA */
DCSR(si->txdma) &= ~DCSR_RUN;
DCSR(si->rxdma) &= ~DCSR_RUN;
dmaengine_terminate_all(si->rxdma);
dmaengine_terminate_all(si->txdma);
/* disable FICP */
ficp_writel(si, 0, ICCR0);
/* disable the STUART or FICP clocks */
pxa_irda_disable_clk(si);
DRCMR(17) = 0;
DRCMR(18) = 0;
local_irq_restore(flags);
/* power off board transceiver */
@ -715,6 +735,9 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
static int pxa_irda_start(struct net_device *dev)
{
struct pxa_irda *si = netdev_priv(dev);
dma_cap_mask_t mask;
struct dma_slave_config config;
struct pxad_param param;
int err;
si->speed = 9600;
@ -734,14 +757,37 @@ static int pxa_irda_start(struct net_device *dev)
disable_irq(si->icp_irq);
err = -EBUSY;
si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
if (si->rxdma < 0)
dma_cap_zero(mask);
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;
si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev);
if (si->txdma < 0)
param.drcmr = si->drcmr_tx;
si->txdma = dma_request_slave_channel_compat(mask, pxad_filter_fn,
&param, &dev->dev, "tx");
if (!si->txdma)
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;
si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT,
&si->dma_rx_buff_phy, GFP_KERNEL);
@ -781,9 +827,9 @@ err_irlap:
err_dma_tx_buff:
dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy);
err_dma_rx_buff:
pxa_free_dma(si->txdma);
dma_release_channel(si->txdma);
err_tx_dma:
pxa_free_dma(si->rxdma);
dma_release_channel(si->rxdma);
err_rx_dma:
free_irq(si->icp_irq, dev);
err_irq2:
@ -810,8 +856,10 @@ static int pxa_irda_stop(struct net_device *dev)
free_irq(si->uart_irq, dev);
free_irq(si->icp_irq, dev);
pxa_free_dma(si->rxdma);
pxa_free_dma(si->txdma);
dmaengine_terminate_all(si->rxdma);
dmaengine_terminate_all(si->txdma);
dma_release_channel(si->rxdma);
dma_release_channel(si->txdma);
if (si->dma_rx_buff)
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)
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
*/