Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20211206174259.68133-7-paul@crapouillou.net
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Paul Cercueil and committed by
Vinod Koul
76a09663 c8c0cda8

+32 -16
+32 -16
drivers/dma/dma-jz4780.c
··· 122 122 dma_addr_t desc_phys; 123 123 unsigned int count; 124 124 enum dma_transaction_type type; 125 + u32 transfer_type; 125 126 u32 status; 126 127 }; 127 128 ··· 131 130 unsigned int id; 132 131 struct dma_pool *desc_pool; 133 132 134 - u32 transfer_type; 133 + u32 transfer_type_tx, transfer_type_rx; 135 134 u32 transfer_shift; 136 135 struct dma_slave_config config; 137 136 ··· 158 157 }; 159 158 160 159 struct jz4780_dma_filter_data { 161 - u32 transfer_type; 160 + u32 transfer_type_tx, transfer_type_rx; 162 161 int channel; 163 162 }; 164 163 ··· 227 226 jz4780_dma_ctrl_writel(jzdma, JZ_DMA_REG_DCKEC, BIT(chn)); 228 227 } 229 228 230 - static struct jz4780_dma_desc *jz4780_dma_desc_alloc( 231 - struct jz4780_dma_chan *jzchan, unsigned int count, 232 - enum dma_transaction_type type) 229 + static struct jz4780_dma_desc * 230 + jz4780_dma_desc_alloc(struct jz4780_dma_chan *jzchan, unsigned int count, 231 + enum dma_transaction_type type, 232 + enum dma_transfer_direction direction) 233 233 { 234 234 struct jz4780_dma_desc *desc; 235 235 ··· 250 248 251 249 desc->count = count; 252 250 desc->type = type; 251 + 252 + if (direction == DMA_DEV_TO_MEM) 253 + desc->transfer_type = jzchan->transfer_type_rx; 254 + else 255 + desc->transfer_type = jzchan->transfer_type_tx; 256 + 253 257 return desc; 254 258 } 255 259 ··· 369 361 unsigned int i; 370 362 int err; 371 363 372 - desc = jz4780_dma_desc_alloc(jzchan, sg_len, DMA_SLAVE); 364 + desc = jz4780_dma_desc_alloc(jzchan, sg_len, DMA_SLAVE, direction); 373 365 if (!desc) 374 366 return NULL; 375 367 ··· 418 410 419 411 periods = buf_len / period_len; 420 412 421 - desc = jz4780_dma_desc_alloc(jzchan, periods, DMA_CYCLIC); 413 + desc = jz4780_dma_desc_alloc(jzchan, periods, DMA_CYCLIC, direction); 422 414 if (!desc) 423 415 return NULL; 424 416 ··· 463 455 struct jz4780_dma_desc *desc; 464 456 u32 tsz; 465 457 466 - desc = jz4780_dma_desc_alloc(jzchan, 1, DMA_MEMCPY); 458 + desc = jz4780_dma_desc_alloc(jzchan, 1, DMA_MEMCPY, 0); 467 459 if (!desc) 468 460 return NULL; 469 461 470 462 tsz = jz4780_dma_transfer_size(jzchan, dest | src | len, 471 463 &jzchan->transfer_shift); 472 464 473 - jzchan->transfer_type = JZ_DMA_DRT_AUTO; 465 + desc->transfer_type = JZ_DMA_DRT_AUTO; 474 466 475 467 desc->desc[0].dsa = src; 476 468 desc->desc[0].dta = dest; ··· 536 528 537 529 /* Set transfer type. */ 538 530 jz4780_dma_chn_writel(jzdma, jzchan->id, JZ_DMA_REG_DRT, 539 - jzchan->transfer_type); 531 + jzchan->desc->transfer_type); 540 532 541 533 /* 542 534 * Set the transfer count. This is redundant for a descriptor-driven ··· 796 788 return false; 797 789 } 798 790 799 - jzchan->transfer_type = data->transfer_type; 791 + jzchan->transfer_type_tx = data->transfer_type_tx; 792 + jzchan->transfer_type_rx = data->transfer_type_rx; 800 793 801 794 return true; 802 795 } ··· 809 800 dma_cap_mask_t mask = jzdma->dma_device.cap_mask; 810 801 struct jz4780_dma_filter_data data; 811 802 812 - if (dma_spec->args_count != 2) 803 + if (dma_spec->args_count == 2) { 804 + data.transfer_type_tx = dma_spec->args[0]; 805 + data.transfer_type_rx = dma_spec->args[0]; 806 + data.channel = dma_spec->args[1]; 807 + } else if (dma_spec->args_count == 3) { 808 + data.transfer_type_tx = dma_spec->args[0]; 809 + data.transfer_type_rx = dma_spec->args[1]; 810 + data.channel = dma_spec->args[2]; 811 + } else { 813 812 return NULL; 814 - 815 - data.transfer_type = dma_spec->args[0]; 816 - data.channel = dma_spec->args[1]; 813 + } 817 814 818 815 if (data.channel > -1) { 819 816 if (data.channel >= jzdma->soc_data->nb_channels) { ··· 837 822 return NULL; 838 823 } 839 824 840 - jzdma->chan[data.channel].transfer_type = data.transfer_type; 825 + jzdma->chan[data.channel].transfer_type_tx = data.transfer_type_tx; 826 + jzdma->chan[data.channel].transfer_type_rx = data.transfer_type_rx; 841 827 842 828 return dma_get_slave_channel( 843 829 &jzdma->chan[data.channel].vchan.chan);