From: zonque@gmail.com (Daniel Mack)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 10/20] net: irda: pxaficp_ir: switch to dmaengine
Date: Wed, 7 Aug 2013 17:33:59 +0200 [thread overview]
Message-ID: <1375889649-14638-11-git-send-email-zonque@gmail.com> (raw)
In-Reply-To: <1375889649-14638-1-git-send-email-zonque@gmail.com>
This was only compile-tested.
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
drivers/net/irda/pxaficp_ir.c | 242 ++++++++++++++++++++++++++----------------
1 file changed, 151 insertions(+), 91 deletions(-)
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 964b116..d77a342 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -21,13 +21,15 @@
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/mmp-pdma.h>
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#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>
#include <mach/regs-uart.h>
@@ -99,6 +101,9 @@
IrSR_RCVEIR_UART_MODE | \
IrSR_XMITIR_IR_MODE)
+/* FIXME */
+extern void pxa2xx_transceiver_mode(struct device *dev, int mode);
+
struct pxa_irda {
int speed;
int newspeed;
@@ -109,8 +114,10 @@ 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 dma_rx_cookie;
+ dma_cookie_t dma_tx_cookie;
int uart_irq;
int icp_irq;
@@ -122,6 +129,7 @@ struct pxa_irda {
iobuff_t rx_buff;
struct device *dev;
+ struct net_device *net_dev;
struct pxaficp_platform_data *pdata;
struct clk *fir_clk;
struct clk *sir_clk;
@@ -147,26 +155,121 @@ static inline void pxa_irda_enable_sirclk(struct pxa_irda *si)
clk_prepare_enable(si->sir_clk);
}
-
#define IS_FIR(si) ((si)->speed >= 4000000)
#define IRDA_FRAME_SIZE_LIMIT 2047
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;
+ struct dma_slave_config config;
+ struct dma_device *dma_dev;
+ int ret;
+
+ dma_dev = si->rxdma->device;
+
+ memset(&config, 0, sizeof(config));
+ config.src_maxburst = 32;
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ config.direction = DMA_DEV_TO_MEM;
+
+ ret = dmaengine_slave_config(si->rxdma, &config);
+ if (ret < 0) {
+ dev_err(si->dev, "dmaengine_slave_config() failed: %d\n", ret);
+ return;
+ }
+
+ tx = dma_dev->device_prep_dma_memcpy(si->rxdma, __PREG(ICDR),
+ si->dma_rx_buff_phy,
+ IRDA_FRAME_SIZE_LIMIT, 0);
+ if (!tx) {
+ dev_err(si->dev, "device_prep_dma_memcpy() failed: %d\n", ret);
+ return;
+ }
+
+ si->dma_rx_cookie = dmaengine_submit(tx);
+ dma_async_issue_pending(si->rxdma);
+}
+
+static int pxa_irda_set_speed(struct pxa_irda *si, int speed);
+
+/* FIR Transmit DMA interrupt handler */
+static void pxa_irda_fir_dma_tx_irq(void *param)
+{
+ struct net_device *dev = param;
+ struct pxa_irda *si = netdev_priv(dev);
+ struct dma_tx_state tx_state;
+ enum dma_status status;
+
+ status = dmaengine_tx_status(si->txdma, si->dma_tx_cookie, &tx_state);
+ if (status == DMA_ERROR) {
+ dev->stats.tx_errors++;
+ } else {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += si->dma_tx_buff_len;
+ }
+
+ while (ICSR1 & ICSR1_TBY)
+ cpu_relax();
+ si->last_oscr = readl_relaxed(OSCR);
+
+ /*
+ * HACK: It looks like the TBY bit is dropped too soon.
+ * Without this delay things break.
+ */
+ udelay(120);
+
+ if (si->newspeed) {
+ pxa_irda_set_speed(si, si->newspeed);
+ si->newspeed = 0;
+ } else {
+ int i = 64;
+
+ ICCR0 = 0;
+ pxa_irda_fir_dma_rx_start(si);
+ while ((ICSR1 & ICSR1_RNE) && i--)
+ (void)ICDR;
+ ICCR0 = ICCR0_ITR | ICCR0_RXE;
+
+ if (i < 0)
+ printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
+ }
+ netif_wake_queue(dev);
}
+
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;
+ struct dma_slave_config config;
+ struct dma_device *dma_dev;
+ int ret;
+
+ dma_dev = si->txdma->device;
+
+ memset(&config, 0, sizeof(config));
+ config.dst_maxburst = 32;
+ config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ config.direction = DMA_MEM_TO_DEV;
+
+ ret = dmaengine_slave_config(si->txdma, &config);
+ if (ret < 0) {
+ dev_err(si->dev, "dmaengine_slave_config() failed: %d\n", ret);
+ return;
+ }
+
+ tx = dma_dev->device_prep_dma_memcpy(si->txdma, __PREG(ICDR),
+ si->dma_tx_buff_phy,
+ si->dma_tx_buff_len, 0);
+ if (!tx) {
+ dev_err(si->dev, "device_prep_dma_memcpy() failed: %d\n", ret);
+ return;
+ }
+
+ tx->callback = pxa_irda_fir_dma_tx_irq;
+ tx->callback_param = si->net_dev;
+
+ si->dma_tx_cookie = dmaengine_submit(tx);
+ dma_async_issue_pending(si->txdma);
}
/*
@@ -205,7 +308,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 */
ICCR0 = 0;
pxa_irda_disable_clk(si);
@@ -344,68 +447,18 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-/* 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)
-{
- 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) {
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += si->dma_tx_buff_len;
- } else {
- dev->stats.tx_errors++;
- }
-
- while (ICSR1 & ICSR1_TBY)
- cpu_relax();
- si->last_oscr = readl_relaxed(OSCR);
-
- /*
- * HACK: It looks like the TBY bit is dropped too soon.
- * Without this delay things break.
- */
- udelay(120);
-
- if (si->newspeed) {
- pxa_irda_set_speed(si, si->newspeed);
- si->newspeed = 0;
- } else {
- int i = 64;
-
- ICCR0 = 0;
- pxa_irda_fir_dma_rx_start(si);
- while ((ICSR1 & ICSR1_RNE) && i--)
- (void)ICDR;
- ICCR0 = ICCR0_ITR | ICCR0_RXE;
-
- if (i < 0)
- printk(KERN_ERR "pxa_ir: cannot clear Rx FIFO!\n");
- }
- netif_wake_queue(dev);
-}
-
/* EIF(Error in FIFO/End in Frame) handler for FIR */
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 tx_state;
+ enum dma_status status;
+
+ status = dmaengine_tx_status(si->rxdma, si->dma_rx_cookie,
+ &tx_state);
/* Get the current data position. */
- len = DTADR(si->rxdma) - si->dma_rx_buff_phy;
+ len = IRDA_FRAME_SIZE_LIMIT - tx_state.residue;
do {
/* Read Status, and then Data. */
@@ -472,7 +525,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_oscr = readl_relaxed(OSCR);
icsr0 = ICSR0;
@@ -553,7 +606,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);
ICCR0 = 0;
pxa_irda_fir_dma_tx_start(si);
@@ -626,10 +679,6 @@ static void pxa_irda_startup(struct pxa_irda *si)
/* configure FICP ICCR2 */
ICCR2 = ICCR2_TXP | ICCR2_TRIG_32;
- /* 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);
@@ -649,17 +698,15 @@ static void pxa_irda_shutdown(struct pxa_irda *si)
STISR = 0;
/* 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;
/* 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,7 +718,8 @@ 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);
- int err;
+ dma_cap_mask_t mask;
+ int drcmr, err;
si->speed = 9600;
@@ -689,13 +737,21 @@ static int pxa_irda_start(struct net_device *dev)
disable_irq(si->uart_irq);
disable_irq(si->icp_irq);
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
err = -EBUSY;
- si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev);
- if (si->rxdma < 0)
+
+ drcmr = 17;
+ si->rxdma = dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+ &drcmr, si->dev, "rx");
+ if (si->rxdma == NULL)
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)
+ drcmr = 18;
+ si->rxdma = dma_request_slave_channel_compat(mask, mmp_pdma_filter_fn,
+ &drcmr, si->dev, "rx");
+ if (si->txdma == NULL)
goto err_tx_dma;
err = -ENOMEM;
@@ -737,9 +793,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 +822,11 @@ 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);
@@ -855,6 +914,7 @@ static int pxa_irda_probe(struct platform_device *pdev)
si = netdev_priv(dev);
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
+ si->net_dev = dev;
si->uart_irq = platform_get_irq(pdev, 0);
si->icp_irq = platform_get_irq(pdev, 1);
--
1.8.3.1
next prev parent reply other threads:[~2013-08-07 15:33 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-07 15:33 [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine Daniel Mack
2013-08-07 15:33 ` [PATCH 01/20] mtd: pxa3xx-nand: replace pxa_request_dma with dmaengine Daniel Mack
2013-08-07 17:46 ` Ezequiel Garcia
2013-08-08 6:42 ` Daniel Mack
2013-08-08 10:12 ` Ezequiel Garcia
2013-08-08 10:14 ` Daniel Mack
2013-08-07 15:33 ` [PATCH 02/20] mtd: pxa3xx-nand: use mmp_pdma_filter_fn and dma_request_slave_channel_compat Daniel Mack
2013-08-07 15:33 ` [PATCH 03/20] ARM: pxa: ssp: add shortcut for &pdev->dev Daniel Mack
2013-08-08 7:32 ` Brian Norris
2013-08-08 7:52 ` Artem Bityutskiy
2013-08-08 8:20 ` Daniel Mack
2013-08-07 15:33 ` [PATCH 04/20] ARM: pxa: ssp: add DT bindings Daniel Mack
2013-08-07 15:54 ` Arnd Bergmann
2013-08-07 15:33 ` [PATCH 05/20] ARM: pxa: ssp: use devm_ functions Daniel Mack
2013-08-07 15:33 ` [PATCH 06/20] tty: serial: pxa: remove old cruft Daniel Mack
2013-08-12 8:19 ` Daniel Mack
2013-08-12 18:08 ` Greg KH
2013-08-07 15:33 ` [PATCH 07/20] spi: spi-pxa2xx: remove legacy PXA DMA bits Daniel Mack
2013-08-07 15:55 ` Mark Brown
2013-08-07 15:59 ` Daniel Mack
2013-08-07 16:41 ` Mark Brown
2013-08-07 15:33 ` [PATCH 08/20] mmc: host: pxamci: switch over to dmaengine use Daniel Mack
2014-10-15 18:32 ` Vasily Khoruzhick
2014-10-16 17:57 ` Vasily Khoruzhick
2013-08-07 15:33 ` [PATCH 09/20] ata: pdata_pxa: migrate over to dmaengine usage Daniel Mack
2013-08-07 15:59 ` Arnd Bergmann
2013-08-07 15:33 ` Daniel Mack [this message]
2013-08-07 15:34 ` [PATCH 11/20] net: smc91x.c: switch to generic buf-to-buf DMA offload Daniel Mack
2013-08-07 15:34 ` [PATCH 12/20] net: smc911x.c: switch to dmaengine API Daniel Mack
2013-08-07 15:34 ` [PATCH 13/20] ASoC: pxa: pxa-ssp: add DT bindings Daniel Mack
2013-08-07 16:40 ` Mark Brown
2013-08-08 9:39 ` Daniel Mack
2013-08-08 13:20 ` Mark Brown
2013-08-09 13:03 ` Daniel Mack
2013-08-07 15:34 ` [PATCH 14/20] ASoC: pxa: use snd_dmaengine_dai_dma_data Daniel Mack
2013-08-07 15:57 ` Mark Brown
2013-08-07 15:34 ` [PATCH 15/20] ASoC: pxa: pxa-ssp: set dma filter data from startup hook Daniel Mack
2013-08-07 15:58 ` Mark Brown
2013-08-07 15:34 ` [PATCH 16/20] ASoC: pxa: add DT bindings for pxa2xx-pcm Daniel Mack
2013-08-07 16:06 ` Mark Brown
2013-08-07 15:34 ` [PATCH 17/20] ASoC: pxa: pxa-pcm-lib: switch over to snd-soc-dmaengine-pcm Daniel Mack
2013-08-07 16:07 ` Mark Brown
2013-08-07 16:10 ` Daniel Mack
2013-08-07 16:32 ` Mark Brown
2013-08-08 8:18 ` Daniel Mack
2013-08-08 8:44 ` Lars-Peter Clausen
2013-08-08 9:03 ` Daniel Mack
2013-08-08 9:36 ` Mark Brown
2013-08-08 9:43 ` Daniel Mack
2013-08-08 10:35 ` Mark Brown
2013-08-08 10:39 ` Daniel Mack
2013-08-08 11:03 ` Mark Brown
2013-08-08 10:25 ` Russell King - ARM Linux
2013-08-07 15:34 ` [PATCH 18/20] ARM: pxa: register static mmp_pdma device Daniel Mack
2013-08-07 15:34 ` [PATCH 19/20] ARM: mmp: " Daniel Mack
2013-08-07 15:34 ` [PATCH 20/20] ARM: pxa: remove old DMA implementation Daniel Mack
2013-08-07 16:08 ` [PATCH 00/20] ARM: pxa: move core and drivers to dmaengine Arnd Bergmann
2013-08-09 22:50 ` Robert Jarzmik
2013-08-10 10:56 ` Daniel Mack
2013-08-11 20:05 ` Robert Jarzmik
2013-08-14 10:00 ` Vinod Koul
2013-08-15 15:22 ` Robert Jarzmik
2013-08-15 15:30 ` Daniel Mack
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1375889649-14638-11-git-send-email-zonque@gmail.com \
--to=zonque@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).