Skip to content

Commit 76a0966

Browse files
pcercueivinodkoul
authored andcommitted
dmaengine: jz4780: Support bidirectional I/O on one channel
For some devices with only half-duplex capabilities, it doesn't make much sense to use one DMA channel per direction, as both channels will never be active at the same time. Add support for bidirectional I/O on DMA channels. The client drivers can then request a "tx-rx" DMA channel which will be used for both directions. Signed-off-by: Paul Cercueil <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent c8c0cda commit 76a0966

File tree

1 file changed

+32
-16
lines changed

1 file changed

+32
-16
lines changed

drivers/dma/dma-jz4780.c

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ struct jz4780_dma_desc {
122122
dma_addr_t desc_phys;
123123
unsigned int count;
124124
enum dma_transaction_type type;
125+
u32 transfer_type;
125126
u32 status;
126127
};
127128

@@ -130,7 +131,7 @@ struct jz4780_dma_chan {
130131
unsigned int id;
131132
struct dma_pool *desc_pool;
132133

133-
u32 transfer_type;
134+
u32 transfer_type_tx, transfer_type_rx;
134135
u32 transfer_shift;
135136
struct dma_slave_config config;
136137

@@ -157,7 +158,7 @@ struct jz4780_dma_dev {
157158
};
158159

159160
struct jz4780_dma_filter_data {
160-
u32 transfer_type;
161+
u32 transfer_type_tx, transfer_type_rx;
161162
int channel;
162163
};
163164

@@ -226,9 +227,10 @@ static inline void jz4780_dma_chan_disable(struct jz4780_dma_dev *jzdma,
226227
jz4780_dma_ctrl_writel(jzdma, JZ_DMA_REG_DCKEC, BIT(chn));
227228
}
228229

229-
static struct jz4780_dma_desc *jz4780_dma_desc_alloc(
230-
struct jz4780_dma_chan *jzchan, unsigned int count,
231-
enum dma_transaction_type type)
230+
static struct jz4780_dma_desc *
231+
jz4780_dma_desc_alloc(struct jz4780_dma_chan *jzchan, unsigned int count,
232+
enum dma_transaction_type type,
233+
enum dma_transfer_direction direction)
232234
{
233235
struct jz4780_dma_desc *desc;
234236

@@ -248,6 +250,12 @@ static struct jz4780_dma_desc *jz4780_dma_desc_alloc(
248250

249251
desc->count = count;
250252
desc->type = type;
253+
254+
if (direction == DMA_DEV_TO_MEM)
255+
desc->transfer_type = jzchan->transfer_type_rx;
256+
else
257+
desc->transfer_type = jzchan->transfer_type_tx;
258+
251259
return desc;
252260
}
253261

@@ -361,7 +369,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
361369
unsigned int i;
362370
int err;
363371

364-
desc = jz4780_dma_desc_alloc(jzchan, sg_len, DMA_SLAVE);
372+
desc = jz4780_dma_desc_alloc(jzchan, sg_len, DMA_SLAVE, direction);
365373
if (!desc)
366374
return NULL;
367375

@@ -410,7 +418,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_dma_cyclic(
410418

411419
periods = buf_len / period_len;
412420

413-
desc = jz4780_dma_desc_alloc(jzchan, periods, DMA_CYCLIC);
421+
desc = jz4780_dma_desc_alloc(jzchan, periods, DMA_CYCLIC, direction);
414422
if (!desc)
415423
return NULL;
416424

@@ -455,14 +463,14 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_dma_memcpy(
455463
struct jz4780_dma_desc *desc;
456464
u32 tsz;
457465

458-
desc = jz4780_dma_desc_alloc(jzchan, 1, DMA_MEMCPY);
466+
desc = jz4780_dma_desc_alloc(jzchan, 1, DMA_MEMCPY, 0);
459467
if (!desc)
460468
return NULL;
461469

462470
tsz = jz4780_dma_transfer_size(jzchan, dest | src | len,
463471
&jzchan->transfer_shift);
464472

465-
jzchan->transfer_type = JZ_DMA_DRT_AUTO;
473+
desc->transfer_type = JZ_DMA_DRT_AUTO;
466474

467475
desc->desc[0].dsa = src;
468476
desc->desc[0].dta = dest;
@@ -528,7 +536,7 @@ static void jz4780_dma_begin(struct jz4780_dma_chan *jzchan)
528536

529537
/* Set transfer type. */
530538
jz4780_dma_chn_writel(jzdma, jzchan->id, JZ_DMA_REG_DRT,
531-
jzchan->transfer_type);
539+
jzchan->desc->transfer_type);
532540

533541
/*
534542
* Set the transfer count. This is redundant for a descriptor-driven
@@ -788,7 +796,8 @@ static bool jz4780_dma_filter_fn(struct dma_chan *chan, void *param)
788796
return false;
789797
}
790798

791-
jzchan->transfer_type = data->transfer_type;
799+
jzchan->transfer_type_tx = data->transfer_type_tx;
800+
jzchan->transfer_type_rx = data->transfer_type_rx;
792801

793802
return true;
794803
}
@@ -800,11 +809,17 @@ static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
800809
dma_cap_mask_t mask = jzdma->dma_device.cap_mask;
801810
struct jz4780_dma_filter_data data;
802811

803-
if (dma_spec->args_count != 2)
812+
if (dma_spec->args_count == 2) {
813+
data.transfer_type_tx = dma_spec->args[0];
814+
data.transfer_type_rx = dma_spec->args[0];
815+
data.channel = dma_spec->args[1];
816+
} else if (dma_spec->args_count == 3) {
817+
data.transfer_type_tx = dma_spec->args[0];
818+
data.transfer_type_rx = dma_spec->args[1];
819+
data.channel = dma_spec->args[2];
820+
} else {
804821
return NULL;
805-
806-
data.transfer_type = dma_spec->args[0];
807-
data.channel = dma_spec->args[1];
822+
}
808823

809824
if (data.channel > -1) {
810825
if (data.channel >= jzdma->soc_data->nb_channels) {
@@ -822,7 +837,8 @@ static struct dma_chan *jz4780_of_dma_xlate(struct of_phandle_args *dma_spec,
822837
return NULL;
823838
}
824839

825-
jzdma->chan[data.channel].transfer_type = data.transfer_type;
840+
jzdma->chan[data.channel].transfer_type_tx = data.transfer_type_tx;
841+
jzdma->chan[data.channel].transfer_type_rx = data.transfer_type_rx;
826842

827843
return dma_get_slave_channel(
828844
&jzdma->chan[data.channel].vchan.chan);

0 commit comments

Comments
 (0)