summaryrefslogtreecommitdiff
path: root/drivers/net/irda/pxaficp_ir.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/irda/pxaficp_ir.c')
-rw-r--r--drivers/net/irda/pxaficp_ir.c370
1 files changed, 233 insertions, 137 deletions
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 100454662e4b..6e8f616be48e 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -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,18 +30,17 @@
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
-#include <mach/dma.h>
#include <linux/platform_data/irda-pxaficp.h>
-#include <mach/regs-ost.h>
+#undef __REG
+#define __REG(x) ((x) & 0xffff)
#include <mach/regs-uart.h>
-#define FICP __REG(0x40800000) /* Start of FICP area */
-#define ICCR0 __REG(0x40800000) /* ICP Control Register 0 */
-#define ICCR1 __REG(0x40800004) /* ICP Control Register 1 */
-#define ICCR2 __REG(0x40800008) /* ICP Control Register 2 */
-#define ICDR __REG(0x4080000c) /* ICP Data Register */
-#define ICSR0 __REG(0x40800014) /* ICP Status Register 0 */
-#define ICSR1 __REG(0x40800018) /* ICP Status Register 1 */
+#define ICCR0 0x0000 /* ICP Control Register 0 */
+#define ICCR1 0x0004 /* ICP Control Register 1 */
+#define ICCR2 0x0008 /* ICP Control Register 2 */
+#define ICDR 0x000c /* ICP Data Register */
+#define ICSR0 0x0014 /* ICP Status Register 0 */
+#define ICSR1 0x0018 /* ICP Status Register 1 */
#define ICCR0_AME (1 << 7) /* Address match enable */
#define ICCR0_TIE (1 << 6) /* Transmit FIFO interrupt enable */
@@ -56,9 +58,7 @@
#define ICCR2_TRIG_16 (1 << 0) /* >= 16 bytes */
#define ICCR2_TRIG_32 (2 << 0) /* >= 32 bytes */
-#ifdef CONFIG_PXA27x
#define ICSR0_EOC (1 << 6) /* DMA End of Descriptor Chain */
-#endif
#define ICSR0_FRE (1 << 5) /* Framing error */
#define ICSR0_RFS (1 << 4) /* Receive FIFO service request */
#define ICSR0_TFS (1 << 3) /* Transnit FIFO service request */
@@ -99,18 +99,61 @@
IrSR_RCVEIR_UART_MODE | \
IrSR_XMITIR_IR_MODE)
+/* macros for registers read/write */
+#define ficp_writel(irda, val, off) \
+ do { \
+ dev_vdbg(irda->dev, \
+ "%s():%d ficp_writel(0x%x, %s)\n", \
+ __func__, __LINE__, (val), #off); \
+ writel_relaxed((val), (irda)->irda_base + (off)); \
+ } while (0)
+
+#define ficp_readl(irda, off) \
+ ({ \
+ unsigned int _v; \
+ _v = readl_relaxed((irda)->irda_base + (off)); \
+ dev_vdbg(irda->dev, \
+ "%s():%d ficp_readl(%s): 0x%x\n", \
+ __func__, __LINE__, #off, _v); \
+ _v; \
+ })
+
+#define stuart_writel(irda, val, off) \
+ do { \
+ dev_vdbg(irda->dev, \
+ "%s():%d stuart_writel(0x%x, %s)\n", \
+ __func__, __LINE__, (val), #off); \
+ writel_relaxed((val), (irda)->stuart_base + (off)); \
+ } while (0)
+
+#define stuart_readl(irda, off) \
+ ({ \
+ unsigned int _v; \
+ _v = readl_relaxed((irda)->stuart_base + (off)); \
+ dev_vdbg(irda->dev, \
+ "%s():%d stuart_readl(%s): 0x%x\n", \
+ __func__, __LINE__, #off, _v); \
+ _v; \
+ })
+
struct pxa_irda {
int speed;
int newspeed;
- unsigned long last_oscr;
+ unsigned long long last_clk;
+ void __iomem *stuart_base;
+ void __iomem *irda_base;
unsigned char *dma_rx_buff;
unsigned char *dma_tx_buff;
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;
@@ -128,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)
@@ -151,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) = __PREG(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) = __PREG(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);
}
/*
@@ -205,9 +269,9 @@ 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 */
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
pxa_irda_disable_clk(si);
/* set board transceiver to SIR mode */
@@ -218,17 +282,19 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
}
/* disable STUART first */
- STIER = 0;
+ stuart_writel(si, 0, STIER);
/* access DLL & DLH */
- STLCR |= LCR_DLAB;
- STDLL = divisor & 0xff;
- STDLH = divisor >> 8;
- STLCR &= ~LCR_DLAB;
+ stuart_writel(si, stuart_readl(si, STLCR) | LCR_DLAB, STLCR);
+ stuart_writel(si, divisor & 0xff, STDLL);
+ stuart_writel(si, divisor >> 8, STDLH);
+ stuart_writel(si, stuart_readl(si, STLCR) & ~LCR_DLAB, STLCR);
si->speed = speed;
- STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
- STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+ stuart_writel(si, IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6,
+ STISR);
+ stuart_writel(si, IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE,
+ STIER);
local_irq_restore(flags);
break;
@@ -237,12 +303,12 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
local_irq_save(flags);
/* disable STUART */
- STIER = 0;
- STISR = 0;
+ stuart_writel(si, 0, STIER);
+ stuart_writel(si, 0, STISR);
pxa_irda_disable_clk(si);
/* disable FICP first */
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
/* set board transceiver to FIR mode */
pxa_irda_set_mode(si, IR_FIRMODE);
@@ -252,7 +318,7 @@ static int pxa_irda_set_speed(struct pxa_irda *si, int speed)
si->speed = speed;
pxa_irda_fir_dma_rx_start(si);
- ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0);
local_irq_restore(flags);
break;
@@ -271,13 +337,13 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
struct pxa_irda *si = netdev_priv(dev);
int iir, lsr, data;
- iir = STIIR;
+ iir = stuart_readl(si, STIIR);
switch (iir & 0x0F) {
case 0x06: /* Receiver Line Status */
- lsr = STLSR;
+ lsr = stuart_readl(si, STLSR);
while (lsr & LSR_FIFOE) {
- data = STRBR;
+ data = stuart_readl(si, STRBR);
if (lsr & (LSR_OE | LSR_PE | LSR_FE | LSR_BI)) {
printk(KERN_DEBUG "pxa_ir: sir receiving error\n");
dev->stats.rx_errors++;
@@ -290,9 +356,9 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
async_unwrap_char(dev, &dev->stats,
&si->rx_buff, data);
}
- lsr = STLSR;
+ lsr = stuart_readl(si, STLSR);
}
- si->last_oscr = readl_relaxed(OSCR);
+ si->last_clk = sched_clock();
break;
case 0x04: /* Received Data Available */
@@ -301,14 +367,16 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
case 0x0C: /* Character Timeout Indication */
do {
dev->stats.rx_bytes++;
- async_unwrap_char(dev, &dev->stats, &si->rx_buff, STRBR);
- } while (STLSR & LSR_DR);
- si->last_oscr = readl_relaxed(OSCR);
+ async_unwrap_char(dev, &dev->stats, &si->rx_buff,
+ stuart_readl(si, STRBR));
+ } while (stuart_readl(si, STLSR) & LSR_DR);
+ si->last_clk = sched_clock();
break;
case 0x02: /* Transmit FIFO Data Request */
- while ((si->tx_buff.len) && (STLSR & LSR_TDRQ)) {
- STTHR = *si->tx_buff.data++;
+ while ((si->tx_buff.len) &&
+ (stuart_readl(si, STLSR) & LSR_TDRQ)) {
+ stuart_writel(si, *si->tx_buff.data++, STTHR);
si->tx_buff.len -= 1;
}
@@ -317,9 +385,9 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
dev->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head;
/* We need to ensure that the transmitter has finished. */
- while ((STLSR & LSR_TEMT) == 0)
+ while ((stuart_readl(si, STLSR) & LSR_TEMT) == 0)
cpu_relax();
- si->last_oscr = readl_relaxed(OSCR);
+ si->last_clk = sched_clock();
/*
* Ok, we've finished transmitting. Now enable
@@ -331,9 +399,11 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
si->newspeed = 0;
} else {
/* enable IR Receiver, disable IR Transmitter */
- STISR = IrSR_IR_RECEIVE_ON | IrSR_XMODE_PULSE_1_6;
+ stuart_writel(si, IrSR_IR_RECEIVE_ON |
+ IrSR_XMODE_PULSE_1_6, STISR);
/* enable STUART and receive interrupts */
- STIER = IER_UUE | IER_RLSE | IER_RAVIE | IER_RTIOE;
+ stuart_writel(si, IER_UUE | IER_RLSE |
+ IER_RAVIE | IER_RTIOE, STIER);
}
/* I'm hungry! */
netif_wake_queue(dev);
@@ -345,35 +415,32 @@ 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)
+static void pxa_irda_fir_dma_rx_irq(void *data)
{
- int dcsr = DCSR(channel);
-
- DCSR(channel) = dcsr & ~DCSR_RUN;
+ struct net_device *dev = data;
+ struct pxa_irda *si = netdev_priv(dev);
- 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 */
-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 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_bytes += si->dma_tx_buff_len;
- } else {
- dev->stats.tx_errors++;
}
- while (ICSR1 & ICSR1_TBY)
+ while (ficp_readl(si, ICSR1) & ICSR1_TBY)
cpu_relax();
- si->last_oscr = readl_relaxed(OSCR);
+ si->last_clk = sched_clock();
/*
* HACK: It looks like the TBY bit is dropped too soon.
@@ -387,11 +454,11 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data)
} else {
int i = 64;
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
pxa_irda_fir_dma_rx_start(si);
- while ((ICSR1 & ICSR1_RNE) && i--)
- (void)ICDR;
- ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ while ((ficp_readl(si, ICSR1) & ICSR1_RNE) && i--)
+ ficp_readl(si, ICDR);
+ ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0);
if (i < 0)
printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
@@ -403,15 +470,18 @@ 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. */
- stat = ICSR1;
+ stat = ficp_readl(si, ICSR1);
rmb();
- data = ICDR;
+ data = ficp_readl(si, ICDR);
if (stat & (ICSR1_CRE | ICSR1_ROR)) {
dev->stats.rx_errors++;
@@ -429,7 +499,7 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, in
/* If we hit the end of frame, there's no point in continuing. */
if (stat & ICSR1_EOF)
break;
- } while (ICSR0 & ICSR0_EIF);
+ } while (ficp_readl(si, ICSR0) & ICSR0_EIF);
if (stat & ICSR1_EOF) {
/* end of frame. */
@@ -472,9 +542,9 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
int icsr0, i = 64;
/* stop RX DMA */
- DCSR(si->rxdma) &= ~DCSR_RUN;
- si->last_oscr = readl_relaxed(OSCR);
- icsr0 = ICSR0;
+ dmaengine_terminate_all(si->rxdma);
+ si->last_clk = sched_clock();
+ icsr0 = ficp_readl(si, ICSR0);
if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) {
if (icsr0 & ICSR0_FRE) {
@@ -484,7 +554,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
printk(KERN_DEBUG "pxa_ir: fir receive abort\n");
dev->stats.rx_errors++;
}
- ICSR0 = icsr0 & (ICSR0_FRE | ICSR0_RAB);
+ ficp_writel(si, icsr0 & (ICSR0_FRE | ICSR0_RAB), ICSR0);
}
if (icsr0 & ICSR0_EIF) {
@@ -492,11 +562,11 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id)
pxa_irda_fir_irq_eif(si, dev, icsr0);
}
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
pxa_irda_fir_dma_rx_start(si);
- while ((ICSR1 & ICSR1_RNE) && i--)
- (void)ICDR;
- ICCR0 = ICCR0_ITR | ICCR0_RXE;
+ while ((ficp_readl(si, ICSR1) & ICSR1_RNE) && i--)
+ ficp_readl(si, ICDR);
+ ficp_writel(si, ICCR0_ITR | ICCR0_RXE, ICCR0);
if (i < 0)
printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
@@ -537,11 +607,12 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
si->tx_buff.len = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);
/* Disable STUART interrupts and switch to transmit mode. */
- STIER = 0;
- STISR = IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6;
+ stuart_writel(si, 0, STIER);
+ stuart_writel(si, IrSR_IR_TRANSMIT_ON | IrSR_XMODE_PULSE_1_6,
+ STISR);
/* enable STUART and transmit interrupts */
- STIER = IER_UUE | IER_TIE;
+ stuart_writel(si, IER_UUE | IER_TIE, STIER);
} else {
unsigned long mtt = irda_get_mtt(skb);
@@ -549,15 +620,15 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
skb_copy_from_linear_data(skb, si->dma_tx_buff, skb->len);
if (mtt)
- while ((unsigned)(readl_relaxed(OSCR) - si->last_oscr)/4 < mtt)
+ while ((sched_clock() - si->last_clk) * 1000 < mtt)
cpu_relax();
/* stop RX DMA, disable FICP */
- DCSR(si->rxdma) &= ~DCSR_RUN;
- ICCR0 = 0;
+ dmaengine_terminate_all(si->rxdma);
+ ficp_writel(si, 0, ICCR0);
pxa_irda_fir_dma_tx_start(si);
- ICCR0 = ICCR0_ITR | ICCR0_TXE;
+ ficp_writel(si, ICCR0_ITR | ICCR0_TXE, ICCR0);
}
dev_kfree_skb(skb);
@@ -613,22 +684,18 @@ static int pxa_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
static void pxa_irda_startup(struct pxa_irda *si)
{
/* Disable STUART interrupts */
- STIER = 0;
+ stuart_writel(si, 0, STIER);
/* enable STUART interrupt to the processor */
- STMCR = MCR_OUT2;
+ stuart_writel(si, MCR_OUT2, STMCR);
/* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */
- STLCR = LCR_WLS0 | LCR_WLS1;
+ stuart_writel(si, LCR_WLS0 | LCR_WLS1, STLCR);
/* enable FIFO, we use FIFO to improve performance */
- STFCR = FCR_TRFIFOE | FCR_ITL_32;
+ stuart_writel(si, FCR_TRFIFOE | FCR_ITL_32, STFCR);
/* disable FICP */
- ICCR0 = 0;
+ ficp_writel(si, 0, ICCR0);
/* configure FICP ICCR2 */
- ICCR2 = ICCR2_TXP | ICCR2_TRIG_32;
-
- /* configure DMAC */
- DRCMR(17) = si->rxdma | DRCMR_MAPVLD;
- DRCMR(18) = si->txdma | DRCMR_MAPVLD;
+ ficp_writel(si, ICCR2_TXP | ICCR2_TRIG_32, ICCR2);
/* force SIR reinitialization */
si->speed = 4000000;
@@ -644,22 +711,19 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
local_irq_save(flags);
/* disable STUART and interrupt */
- STIER = 0;
+ stuart_writel(si, 0, STIER);
/* disable STUART SIR mode */
- STISR = 0;
+ 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 */
- ICCR0 = 0;
+ 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 */
@@ -671,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;
@@ -690,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);
@@ -737,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:
@@ -766,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);
@@ -830,25 +922,33 @@ static const struct net_device_ops pxa_irda_netdev_ops = {
static int pxa_irda_probe(struct platform_device *pdev)
{
struct net_device *dev;
+ struct resource *res;
struct pxa_irda *si;
+ void __iomem *ficp, *stuart;
unsigned int baudrate_mask;
int err;
if (!pdev->dev.platform_data)
return -ENODEV;
- err = request_mem_region(__PREG(STUART), 0x24, "IrDA") ? 0 : -EBUSY;
- if (err)
- goto err_mem_1;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ficp = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ficp)) {
+ dev_err(&pdev->dev, "resource ficp not defined\n");
+ return PTR_ERR(ficp);
+ }
- err = request_mem_region(__PREG(FICP), 0x1c, "IrDA") ? 0 : -EBUSY;
- if (err)
- goto err_mem_2;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ stuart = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(stuart)) {
+ dev_err(&pdev->dev, "resource stuart not defined\n");
+ return PTR_ERR(stuart);
+ }
dev = alloc_irdadev(sizeof(struct pxa_irda));
if (!dev) {
err = -ENOMEM;
- goto err_mem_3;
+ goto err_mem_1;
}
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -856,16 +956,25 @@ static int pxa_irda_probe(struct platform_device *pdev)
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
+ si->irda_base = ficp;
+ si->stuart_base = stuart;
si->uart_irq = platform_get_irq(pdev, 0);
si->icp_irq = platform_get_irq(pdev, 1);
- si->sir_clk = clk_get(&pdev->dev, "UARTCLK");
- si->fir_clk = clk_get(&pdev->dev, "FICPCLK");
+ si->sir_clk = devm_clk_get(&pdev->dev, "UARTCLK");
+ si->fir_clk = devm_clk_get(&pdev->dev, "FICPCLK");
if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) {
err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk);
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
*/
@@ -925,15 +1034,7 @@ err_startup:
err_mem_5:
kfree(si->rx_buff.head);
err_mem_4:
- if (si->sir_clk && !IS_ERR(si->sir_clk))
- clk_put(si->sir_clk);
- if (si->fir_clk && !IS_ERR(si->fir_clk))
- clk_put(si->fir_clk);
free_netdev(dev);
-err_mem_3:
- release_mem_region(__PREG(FICP), 0x1c);
-err_mem_2:
- release_mem_region(__PREG(STUART), 0x24);
}
err_mem_1:
return err;
@@ -952,14 +1053,9 @@ static int pxa_irda_remove(struct platform_device *_dev)
si->pdata->shutdown(si->dev);
kfree(si->tx_buff.head);
kfree(si->rx_buff.head);
- clk_put(si->fir_clk);
- clk_put(si->sir_clk);
free_netdev(dev);
}
- release_mem_region(__PREG(STUART), 0x24);
- release_mem_region(__PREG(FICP), 0x1c);
-
return 0;
}