Skip to content

Commit 73e8b05

Browse files
Niklas SöderlundWolfram Sang
authored andcommitted
i2c: rcar: add DMA support
Make it possible to transfer i2c message buffers via DMA. Start/Stop/Sending_Slave_Address and some data is still handled using the old state machine, it is sending the bulk of the data that is done via DMA. The first byte of a transmission and the last two bytes of reception are sent/received using PIO. This is needed for the HW to have access to the first byte before DMA transmit and to be able to set the STOP condition for DMA reception. Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> Acked-by: Rob Herring <robh@kernel.org> Tested-by: Wolfram Sang <wsa+renesas@sang-engineering.com> [wsa: fixed a checkpatch warning] Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
1 parent 40027b2 commit 73e8b05

File tree

2 files changed

+232
-4
lines changed

2 files changed

+232
-4
lines changed

Documentation/devicetree/bindings/i2c/i2c-rcar.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ Optional properties:
1919
- clock-frequency: desired I2C bus clock frequency in Hz. The absence of this
2020
property indicates the default frequency 100 kHz.
2121
- clocks: clock specifier.
22+
- dmas: Must contain a list of two references to DMA specifiers, one for
23+
transmission, and one for reception.
24+
- dma-names: Must contain a list of two DMA names, "tx" and "rx".
2225

2326
- i2c-scl-falling-time-ns: see i2c.txt
2427
- i2c-scl-internal-delay-ns: see i2c.txt

drivers/i2c/busses/i2c-rcar.c

Lines changed: 229 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
*/
2222
#include <linux/clk.h>
2323
#include <linux/delay.h>
24+
#include <linux/dmaengine.h>
25+
#include <linux/dma-mapping.h>
2426
#include <linux/err.h>
2527
#include <linux/interrupt.h>
2628
#include <linux/io.h>
@@ -43,6 +45,8 @@
4345
#define ICSAR 0x1C /* slave address */
4446
#define ICMAR 0x20 /* master address */
4547
#define ICRXTX 0x24 /* data port */
48+
#define ICDMAER 0x3c /* DMA enable */
49+
#define ICFBSCR 0x38 /* first bit setup cycle */
4650

4751
/* ICSCR */
4852
#define SDBS (1 << 3) /* slave data buffer select */
@@ -78,6 +82,16 @@
7882
#define MDR (1 << 1)
7983
#define MAT (1 << 0) /* slave addr xfer done */
8084

85+
/* ICDMAER */
86+
#define RSDMAE (1 << 3) /* DMA Slave Received Enable */
87+
#define TSDMAE (1 << 2) /* DMA Slave Transmitted Enable */
88+
#define RMDMAE (1 << 1) /* DMA Master Received Enable */
89+
#define TMDMAE (1 << 0) /* DMA Master Transmitted Enable */
90+
91+
/* ICFBSCR */
92+
#define TCYC06 0x04 /* 6*Tcyc delay 1st bit between SDA and SCL */
93+
#define TCYC17 0x0f /* 17*Tcyc delay 1st bit between SDA and SCL */
94+
8195

8296
#define RCAR_BUS_PHASE_START (MDBS | MIE | ESG)
8397
#define RCAR_BUS_PHASE_DATA (MDBS | MIE)
@@ -120,6 +134,12 @@ struct rcar_i2c_priv {
120134
u32 flags;
121135
enum rcar_i2c_type devtype;
122136
struct i2c_client *slave;
137+
138+
struct resource *res;
139+
struct dma_chan *dma_tx;
140+
struct dma_chan *dma_rx;
141+
struct scatterlist sg;
142+
enum dma_data_direction dma_direction;
123143
};
124144

125145
#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
@@ -287,6 +307,118 @@ static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv)
287307
/*
288308
* interrupt functions
289309
*/
310+
static void rcar_i2c_dma_unmap(struct rcar_i2c_priv *priv)
311+
{
312+
struct dma_chan *chan = priv->dma_direction == DMA_FROM_DEVICE
313+
? priv->dma_rx : priv->dma_tx;
314+
315+
/* Disable DMA Master Received/Transmitted */
316+
rcar_i2c_write(priv, ICDMAER, 0);
317+
318+
/* Reset default delay */
319+
rcar_i2c_write(priv, ICFBSCR, TCYC06);
320+
321+
dma_unmap_single(chan->device->dev, sg_dma_address(&priv->sg),
322+
priv->msg->len, priv->dma_direction);
323+
324+
priv->dma_direction = DMA_NONE;
325+
}
326+
327+
static void rcar_i2c_cleanup_dma(struct rcar_i2c_priv *priv)
328+
{
329+
if (priv->dma_direction == DMA_NONE)
330+
return;
331+
else if (priv->dma_direction == DMA_FROM_DEVICE)
332+
dmaengine_terminate_all(priv->dma_rx);
333+
else if (priv->dma_direction == DMA_TO_DEVICE)
334+
dmaengine_terminate_all(priv->dma_tx);
335+
336+
rcar_i2c_dma_unmap(priv);
337+
}
338+
339+
static void rcar_i2c_dma_callback(void *data)
340+
{
341+
struct rcar_i2c_priv *priv = data;
342+
343+
priv->pos += sg_dma_len(&priv->sg);
344+
345+
rcar_i2c_dma_unmap(priv);
346+
}
347+
348+
static void rcar_i2c_dma(struct rcar_i2c_priv *priv)
349+
{
350+
struct device *dev = rcar_i2c_priv_to_dev(priv);
351+
struct i2c_msg *msg = priv->msg;
352+
bool read = msg->flags & I2C_M_RD;
353+
enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
354+
struct dma_chan *chan = read ? priv->dma_rx : priv->dma_tx;
355+
struct dma_async_tx_descriptor *txdesc;
356+
dma_addr_t dma_addr;
357+
dma_cookie_t cookie;
358+
unsigned char *buf;
359+
int len;
360+
361+
/* Do not use DMA if it's not available or for messages < 8 bytes */
362+
if (IS_ERR(chan) || msg->len < 8)
363+
return;
364+
365+
if (read) {
366+
/*
367+
* The last two bytes needs to be fetched using PIO in
368+
* order for the STOP phase to work.
369+
*/
370+
buf = priv->msg->buf;
371+
len = priv->msg->len - 2;
372+
} else {
373+
/*
374+
* First byte in message was sent using PIO.
375+
*/
376+
buf = priv->msg->buf + 1;
377+
len = priv->msg->len - 1;
378+
}
379+
380+
dma_addr = dma_map_single(chan->device->dev, buf, len, dir);
381+
if (dma_mapping_error(dev, dma_addr)) {
382+
dev_dbg(dev, "dma map failed, using PIO\n");
383+
return;
384+
}
385+
386+
sg_dma_len(&priv->sg) = len;
387+
sg_dma_address(&priv->sg) = dma_addr;
388+
389+
priv->dma_direction = dir;
390+
391+
txdesc = dmaengine_prep_slave_sg(chan, &priv->sg, 1,
392+
read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV,
393+
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
394+
if (!txdesc) {
395+
dev_dbg(dev, "dma prep slave sg failed, using PIO\n");
396+
rcar_i2c_cleanup_dma(priv);
397+
return;
398+
}
399+
400+
txdesc->callback = rcar_i2c_dma_callback;
401+
txdesc->callback_param = priv;
402+
403+
cookie = dmaengine_submit(txdesc);
404+
if (dma_submit_error(cookie)) {
405+
dev_dbg(dev, "submitting dma failed, using PIO\n");
406+
rcar_i2c_cleanup_dma(priv);
407+
return;
408+
}
409+
410+
/* Set delay for DMA operations */
411+
rcar_i2c_write(priv, ICFBSCR, TCYC17);
412+
413+
/* Enable DMA Master Received/Transmitted */
414+
if (read)
415+
rcar_i2c_write(priv, ICDMAER, RMDMAE);
416+
else
417+
rcar_i2c_write(priv, ICDMAER, TMDMAE);
418+
419+
dma_async_issue_pending(chan);
420+
}
421+
290422
static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
291423
{
292424
struct i2c_msg *msg = priv->msg;
@@ -306,6 +438,12 @@ static void rcar_i2c_irq_send(struct rcar_i2c_priv *priv, u32 msr)
306438
rcar_i2c_write(priv, ICRXTX, msg->buf[priv->pos]);
307439
priv->pos++;
308440

441+
/*
442+
* Try to use DMA to transmit the rest of the data if
443+
* address transfer pashe just finished.
444+
*/
445+
if (msr & MAT)
446+
rcar_i2c_dma(priv);
309447
} else {
310448
/*
311449
* The last data was pushed to ICRXTX on _PREV_ empty irq.
@@ -340,7 +478,11 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
340478
return;
341479

342480
if (msr & MAT) {
343-
/* Address transfer phase finished, but no data at this point. */
481+
/*
482+
* Address transfer phase finished, but no data at this point.
483+
* Try to use DMA to receive data.
484+
*/
485+
rcar_i2c_dma(priv);
344486
} else if (priv->pos < msg->len) {
345487
/* get received data */
346488
msg->buf[priv->pos] = rcar_i2c_read(priv, ICRXTX);
@@ -472,6 +614,81 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
472614
return IRQ_HANDLED;
473615
}
474616

617+
static struct dma_chan *rcar_i2c_request_dma_chan(struct device *dev,
618+
enum dma_transfer_direction dir,
619+
dma_addr_t port_addr)
620+
{
621+
struct dma_chan *chan;
622+
struct dma_slave_config cfg;
623+
char *chan_name = dir == DMA_MEM_TO_DEV ? "tx" : "rx";
624+
int ret;
625+
626+
chan = dma_request_slave_channel_reason(dev, chan_name);
627+
if (IS_ERR(chan)) {
628+
ret = PTR_ERR(chan);
629+
dev_dbg(dev, "request_channel failed for %s (%d)\n",
630+
chan_name, ret);
631+
return chan;
632+
}
633+
634+
memset(&cfg, 0, sizeof(cfg));
635+
cfg.direction = dir;
636+
if (dir == DMA_MEM_TO_DEV) {
637+
cfg.dst_addr = port_addr;
638+
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
639+
} else {
640+
cfg.src_addr = port_addr;
641+
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
642+
}
643+
644+
ret = dmaengine_slave_config(chan, &cfg);
645+
if (ret) {
646+
dev_dbg(dev, "slave_config failed for %s (%d)\n",
647+
chan_name, ret);
648+
dma_release_channel(chan);
649+
return ERR_PTR(ret);
650+
}
651+
652+
dev_dbg(dev, "got DMA channel for %s\n", chan_name);
653+
return chan;
654+
}
655+
656+
static void rcar_i2c_request_dma(struct rcar_i2c_priv *priv,
657+
struct i2c_msg *msg)
658+
{
659+
struct device *dev = rcar_i2c_priv_to_dev(priv);
660+
bool read;
661+
struct dma_chan *chan;
662+
enum dma_transfer_direction dir;
663+
664+
read = msg->flags & I2C_M_RD;
665+
666+
chan = read ? priv->dma_rx : priv->dma_tx;
667+
if (PTR_ERR(chan) != -EPROBE_DEFER)
668+
return;
669+
670+
dir = read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
671+
chan = rcar_i2c_request_dma_chan(dev, dir, priv->res->start + ICRXTX);
672+
673+
if (read)
674+
priv->dma_rx = chan;
675+
else
676+
priv->dma_tx = chan;
677+
}
678+
679+
static void rcar_i2c_release_dma(struct rcar_i2c_priv *priv)
680+
{
681+
if (!IS_ERR(priv->dma_tx)) {
682+
dma_release_channel(priv->dma_tx);
683+
priv->dma_tx = ERR_PTR(-EPROBE_DEFER);
684+
}
685+
686+
if (!IS_ERR(priv->dma_rx)) {
687+
dma_release_channel(priv->dma_rx);
688+
priv->dma_rx = ERR_PTR(-EPROBE_DEFER);
689+
}
690+
}
691+
475692
static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
476693
struct i2c_msg *msgs,
477694
int num)
@@ -493,6 +710,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
493710
ret = -EOPNOTSUPP;
494711
goto out;
495712
}
713+
rcar_i2c_request_dma(priv, msgs + i);
496714
}
497715

498716
/* init first message */
@@ -504,6 +722,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
504722
time_left = wait_event_timeout(priv->wait, priv->flags & ID_DONE,
505723
num * adap->timeout);
506724
if (!time_left) {
725+
rcar_i2c_cleanup_dma(priv);
507726
rcar_i2c_init(priv);
508727
ret = -ETIMEDOUT;
509728
} else if (priv->flags & ID_NACK) {
@@ -591,7 +810,6 @@ static int rcar_i2c_probe(struct platform_device *pdev)
591810
{
592811
struct rcar_i2c_priv *priv;
593812
struct i2c_adapter *adap;
594-
struct resource *res;
595813
struct device *dev = &pdev->dev;
596814
struct i2c_timings i2c_t;
597815
int irq, ret;
@@ -606,8 +824,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
606824
return PTR_ERR(priv->clk);
607825
}
608826

609-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
610-
priv->io = devm_ioremap_resource(dev, res);
827+
priv->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
828+
829+
priv->io = devm_ioremap_resource(dev, priv->res);
611830
if (IS_ERR(priv->io))
612831
return PTR_ERR(priv->io);
613832

@@ -626,6 +845,11 @@ static int rcar_i2c_probe(struct platform_device *pdev)
626845

627846
i2c_parse_fw_timings(dev, &i2c_t, false);
628847

848+
/* Init DMA */
849+
sg_init_table(&priv->sg, 1);
850+
priv->dma_direction = DMA_NONE;
851+
priv->dma_rx = priv->dma_tx = ERR_PTR(-EPROBE_DEFER);
852+
629853
pm_runtime_enable(dev);
630854
pm_runtime_get_sync(dev);
631855
ret = rcar_i2c_clock_calculate(priv, &i2c_t);
@@ -673,6 +897,7 @@ static int rcar_i2c_remove(struct platform_device *pdev)
673897
struct device *dev = &pdev->dev;
674898

675899
i2c_del_adapter(&priv->adap);
900+
rcar_i2c_release_dma(priv);
676901
if (priv->flags & ID_P_PM_BLOCKED)
677902
pm_runtime_put(dev);
678903
pm_runtime_disable(dev);

0 commit comments

Comments
 (0)