Skip to content

Commit fcc8a89

Browse files
Akhil Rwsakernel
authored andcommitted
i2c: tegra: Share same DMA channel for RX and TX
Allocate only one DMA channel for I2C and share it for both TX and RX instead of using two different DMA hardware channels with the same slave ID. Since I2C supports only half duplex, there is no impact on perf with this. Signed-off-by: Akhil R <akhilrajeev@nvidia.com> Acked-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
1 parent bcfc2ab commit fcc8a89

File tree

1 file changed

+20
-49
lines changed

1 file changed

+20
-49
lines changed

drivers/i2c/busses/i2c-tegra.c

Lines changed: 20 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,7 @@ struct tegra_i2c_hw_feature {
249249
* @msg_read: indicates that the transfer is a read access
250250
* @timings: i2c timings information like bus frequency
251251
* @multimaster_mode: indicates that I2C controller is in multi-master mode
252-
* @tx_dma_chan: DMA transmit channel
253-
* @rx_dma_chan: DMA receive channel
252+
* @dma_chan: DMA channel
254253
* @dma_phys: handle to DMA resources
255254
* @dma_buf: pointer to allocated DMA buffer
256255
* @dma_buf_size: DMA buffer size
@@ -283,8 +282,7 @@ struct tegra_i2c_dev {
283282
u8 *msg_buf;
284283

285284
struct completion dma_complete;
286-
struct dma_chan *tx_dma_chan;
287-
struct dma_chan *rx_dma_chan;
285+
struct dma_chan *dma_chan;
288286
unsigned int dma_buf_size;
289287
struct device *dma_dev;
290288
dma_addr_t dma_phys;
@@ -393,16 +391,14 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len)
393391
{
394392
struct dma_async_tx_descriptor *dma_desc;
395393
enum dma_transfer_direction dir;
396-
struct dma_chan *chan;
397394

398395
dev_dbg(i2c_dev->dev, "starting DMA for length: %zu\n", len);
399396

400397
reinit_completion(&i2c_dev->dma_complete);
401398

402399
dir = i2c_dev->msg_read ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
403-
chan = i2c_dev->msg_read ? i2c_dev->rx_dma_chan : i2c_dev->tx_dma_chan;
404400

405-
dma_desc = dmaengine_prep_slave_single(chan, i2c_dev->dma_phys,
401+
dma_desc = dmaengine_prep_slave_single(i2c_dev->dma_chan, i2c_dev->dma_phys,
406402
len, dir, DMA_PREP_INTERRUPT |
407403
DMA_CTRL_ACK);
408404
if (!dma_desc) {
@@ -415,7 +411,7 @@ static int tegra_i2c_dma_submit(struct tegra_i2c_dev *i2c_dev, size_t len)
415411
dma_desc->callback_param = i2c_dev;
416412

417413
dmaengine_submit(dma_desc);
418-
dma_async_issue_pending(chan);
414+
dma_async_issue_pending(i2c_dev->dma_chan);
419415

420416
return 0;
421417
}
@@ -428,20 +424,14 @@ static void tegra_i2c_release_dma(struct tegra_i2c_dev *i2c_dev)
428424
i2c_dev->dma_buf = NULL;
429425
}
430426

431-
if (i2c_dev->tx_dma_chan) {
432-
dma_release_channel(i2c_dev->tx_dma_chan);
433-
i2c_dev->tx_dma_chan = NULL;
434-
}
435-
436-
if (i2c_dev->rx_dma_chan) {
437-
dma_release_channel(i2c_dev->rx_dma_chan);
438-
i2c_dev->rx_dma_chan = NULL;
427+
if (i2c_dev->dma_chan) {
428+
dma_release_channel(i2c_dev->dma_chan);
429+
i2c_dev->dma_chan = NULL;
439430
}
440431
}
441432

442433
static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
443434
{
444-
struct dma_chan *chan;
445435
dma_addr_t dma_phys;
446436
u32 *dma_buf;
447437
int err;
@@ -459,25 +449,18 @@ static int tegra_i2c_init_dma(struct tegra_i2c_dev *i2c_dev)
459449
return 0;
460450
}
461451

462-
chan = dma_request_chan(i2c_dev->dev, "rx");
463-
if (IS_ERR(chan)) {
464-
err = PTR_ERR(chan);
465-
goto err_out;
466-
}
467-
468-
i2c_dev->rx_dma_chan = chan;
469-
470-
chan = dma_request_chan(i2c_dev->dev, "tx");
471-
if (IS_ERR(chan)) {
472-
err = PTR_ERR(chan);
452+
/*
453+
* The same channel will be used for both RX and TX.
454+
* Keeping the name as "tx" for backward compatibility
455+
* with existing devicetrees.
456+
*/
457+
i2c_dev->dma_chan = dma_request_chan(i2c_dev->dev, "tx");
458+
if (IS_ERR(i2c_dev->dma_chan)) {
459+
err = PTR_ERR(i2c_dev->dma_chan);
473460
goto err_out;
474461
}
475462

476-
i2c_dev->tx_dma_chan = chan;
477-
478-
WARN_ON(i2c_dev->tx_dma_chan->device != i2c_dev->rx_dma_chan->device);
479-
i2c_dev->dma_dev = chan->device->dev;
480-
463+
i2c_dev->dma_dev = i2c_dev->dma_chan->device->dev;
481464
i2c_dev->dma_buf_size = i2c_dev->hw->quirks->max_write_len +
482465
I2C_PACKET_HEADER_SIZE;
483466

@@ -976,11 +959,7 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
976959
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
977960

978961
if (i2c_dev->dma_mode) {
979-
if (i2c_dev->msg_read)
980-
dmaengine_terminate_async(i2c_dev->rx_dma_chan);
981-
else
982-
dmaengine_terminate_async(i2c_dev->tx_dma_chan);
983-
962+
dmaengine_terminate_async(i2c_dev->dma_chan);
984963
complete(&i2c_dev->dma_complete);
985964
}
986965

@@ -994,7 +973,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
994973
{
995974
struct dma_slave_config slv_config = {0};
996975
u32 val, reg, dma_burst, reg_offset;
997-
struct dma_chan *chan;
998976
int err;
999977

1000978
if (i2c_dev->hw->has_mst_fifo)
@@ -1011,7 +989,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
1011989
dma_burst = 8;
1012990

1013991
if (i2c_dev->msg_read) {
1014-
chan = i2c_dev->rx_dma_chan;
1015992
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_RX_FIFO);
1016993

1017994
slv_config.src_addr = i2c_dev->base_phys + reg_offset;
@@ -1023,7 +1000,6 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
10231000
else
10241001
val = I2C_FIFO_CONTROL_RX_TRIG(dma_burst);
10251002
} else {
1026-
chan = i2c_dev->tx_dma_chan;
10271003
reg_offset = tegra_i2c_reg_addr(i2c_dev, I2C_TX_FIFO);
10281004

10291005
slv_config.dst_addr = i2c_dev->base_phys + reg_offset;
@@ -1037,7 +1013,7 @@ static void tegra_i2c_config_fifo_trig(struct tegra_i2c_dev *i2c_dev,
10371013
}
10381014

10391015
slv_config.device_fc = true;
1040-
err = dmaengine_slave_config(chan, &slv_config);
1016+
err = dmaengine_slave_config(i2c_dev->dma_chan, &slv_config);
10411017
if (err) {
10421018
dev_err(i2c_dev->dev, "DMA config failed: %d\n", err);
10431019
dev_err(i2c_dev->dev, "falling back to PIO\n");
@@ -1347,13 +1323,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
13471323
* performs synchronization after the transfer's termination
13481324
* and we want to get a completion if transfer succeeded.
13491325
*/
1350-
dmaengine_synchronize(i2c_dev->msg_read ?
1351-
i2c_dev->rx_dma_chan :
1352-
i2c_dev->tx_dma_chan);
1353-
1354-
dmaengine_terminate_sync(i2c_dev->msg_read ?
1355-
i2c_dev->rx_dma_chan :
1356-
i2c_dev->tx_dma_chan);
1326+
dmaengine_synchronize(i2c_dev->dma_chan);
1327+
dmaengine_terminate_sync(i2c_dev->dma_chan);
13571328

13581329
if (!time_left && !completion_done(&i2c_dev->dma_complete)) {
13591330
dev_err(i2c_dev->dev, "DMA transfer timed out\n");

0 commit comments

Comments
 (0)