Skip to content

Commit 03de6b2

Browse files
arndbvinodkoul
authored andcommitted
dmaengine: qcom-adm: stop abusing slave_id config
The slave_id was previously used to pick one DMA slave instead of another, but this is now done through the DMA descriptors in device tree. For the qcom_adm driver, the configuration is documented in the DT binding to contain a tuple of device identifier and a "crci" field, but the implementation ends up using only a single cell for identifying the slave, with the crci getting passed in nonstandard properties of the device, and passed through the dma driver using the old slave_id field. Part of the problem apparently is that the nand driver ends up using only a single DMA request ID, but requires distinct values for "crci" depending on the type of transfer. Change both the dmaengine driver and the two slave drivers to allow the documented binding to work in addition to the ad-hoc passing of crci values. In order to no longer abuse the slave_id field, pass the data using the "peripheral_config" mechanism instead. Signed-off-by: Arnd Bergmann <[email protected]> Acked-by: Mark Brown <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 722d6d2 commit 03de6b2

File tree

4 files changed

+86
-11
lines changed

4 files changed

+86
-11
lines changed

drivers/dma/qcom/qcom_adm.c

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/device.h>
99
#include <linux/dmaengine.h>
1010
#include <linux/dma-mapping.h>
11+
#include <linux/dma/qcom_adm.h>
1112
#include <linux/init.h>
1213
#include <linux/interrupt.h>
1314
#include <linux/io.h>
@@ -140,6 +141,8 @@ struct adm_chan {
140141

141142
struct adm_async_desc *curr_txd;
142143
struct dma_slave_config slave;
144+
u32 crci;
145+
u32 mux;
143146
struct list_head node;
144147

145148
int error;
@@ -379,8 +382,8 @@ static struct dma_async_tx_descriptor *adm_prep_slave_sg(struct dma_chan *chan,
379382
return ERR_PTR(-EINVAL);
380383
}
381384

382-
crci = achan->slave.slave_id & 0xf;
383-
if (!crci || achan->slave.slave_id > 0x1f) {
385+
crci = achan->crci & 0xf;
386+
if (!crci || achan->crci > 0x1f) {
384387
dev_err(adev->dev, "invalid crci value\n");
385388
return ERR_PTR(-EINVAL);
386389
}
@@ -403,9 +406,7 @@ static struct dma_async_tx_descriptor *adm_prep_slave_sg(struct dma_chan *chan,
403406
if (!async_desc)
404407
return ERR_PTR(-ENOMEM);
405408

406-
if (crci)
407-
async_desc->mux = achan->slave.slave_id & ADM_CRCI_MUX_SEL ?
408-
ADM_CRCI_CTL_MUX_SEL : 0;
409+
async_desc->mux = achan->mux ? ADM_CRCI_CTL_MUX_SEL : 0;
409410
async_desc->crci = crci;
410411
async_desc->blk_size = blk_size;
411412
async_desc->dma_len = single_count * sizeof(struct adm_desc_hw_single) +
@@ -488,10 +489,13 @@ static int adm_terminate_all(struct dma_chan *chan)
488489
static int adm_slave_config(struct dma_chan *chan, struct dma_slave_config *cfg)
489490
{
490491
struct adm_chan *achan = to_adm_chan(chan);
492+
struct qcom_adm_peripheral_config *config = cfg->peripheral_config;
491493
unsigned long flag;
492494

493495
spin_lock_irqsave(&achan->vc.lock, flag);
494496
memcpy(&achan->slave, cfg, sizeof(struct dma_slave_config));
497+
if (cfg->peripheral_size == sizeof(config))
498+
achan->crci = config->crci;
495499
spin_unlock_irqrestore(&achan->vc.lock, flag);
496500

497501
return 0;
@@ -694,6 +698,45 @@ static void adm_channel_init(struct adm_device *adev, struct adm_chan *achan,
694698
achan->vc.desc_free = adm_dma_free_desc;
695699
}
696700

701+
/**
702+
* adm_dma_xlate
703+
* @dma_spec: pointer to DMA specifier as found in the device tree
704+
* @ofdma: pointer to DMA controller data
705+
*
706+
* This can use either 1-cell or 2-cell formats, the first cell
707+
* identifies the slave device, while the optional second cell
708+
* contains the crci value.
709+
*
710+
* Returns pointer to appropriate dma channel on success or NULL on error.
711+
*/
712+
static struct dma_chan *adm_dma_xlate(struct of_phandle_args *dma_spec,
713+
struct of_dma *ofdma)
714+
{
715+
struct dma_device *dev = ofdma->of_dma_data;
716+
struct dma_chan *chan, *candidate = NULL;
717+
struct adm_chan *achan;
718+
719+
if (!dev || dma_spec->args_count > 2)
720+
return NULL;
721+
722+
list_for_each_entry(chan, &dev->channels, device_node)
723+
if (chan->chan_id == dma_spec->args[0]) {
724+
candidate = chan;
725+
break;
726+
}
727+
728+
if (!candidate)
729+
return NULL;
730+
731+
achan = to_adm_chan(candidate);
732+
if (dma_spec->args_count == 2)
733+
achan->crci = dma_spec->args[1];
734+
else
735+
achan->crci = 0;
736+
737+
return dma_get_slave_channel(candidate);
738+
}
739+
697740
static int adm_dma_probe(struct platform_device *pdev)
698741
{
699742
struct adm_device *adev;
@@ -838,8 +881,7 @@ static int adm_dma_probe(struct platform_device *pdev)
838881
goto err_disable_clks;
839882
}
840883

841-
ret = of_dma_controller_register(pdev->dev.of_node,
842-
of_dma_xlate_by_chan_id,
884+
ret = of_dma_controller_register(pdev->dev.of_node, adm_dma_xlate,
843885
&adev->common);
844886
if (ret)
845887
goto err_unregister_dma;

drivers/mtd/nand/raw/qcom_nandc.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/clk.h>
77
#include <linux/slab.h>
88
#include <linux/bitops.h>
9+
#include <linux/dma/qcom_adm.h>
910
#include <linux/dma-mapping.h>
1011
#include <linux/dmaengine.h>
1112
#include <linux/module.h>
@@ -952,6 +953,7 @@ static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
952953
struct dma_async_tx_descriptor *dma_desc;
953954
struct scatterlist *sgl;
954955
struct dma_slave_config slave_conf;
956+
struct qcom_adm_peripheral_config periph_conf = {};
955957
enum dma_transfer_direction dir_eng;
956958
int ret;
957959

@@ -983,11 +985,19 @@ static int prep_adm_dma_desc(struct qcom_nand_controller *nandc, bool read,
983985
if (read) {
984986
slave_conf.src_maxburst = 16;
985987
slave_conf.src_addr = nandc->base_dma + reg_off;
986-
slave_conf.slave_id = nandc->data_crci;
988+
if (nandc->data_crci) {
989+
periph_conf.crci = nandc->data_crci;
990+
slave_conf.peripheral_config = &periph_conf;
991+
slave_conf.peripheral_size = sizeof(periph_conf);
992+
}
987993
} else {
988994
slave_conf.dst_maxburst = 16;
989995
slave_conf.dst_addr = nandc->base_dma + reg_off;
990-
slave_conf.slave_id = nandc->cmd_crci;
996+
if (nandc->cmd_crci) {
997+
periph_conf.crci = nandc->cmd_crci;
998+
slave_conf.peripheral_config = &periph_conf;
999+
slave_conf.peripheral_size = sizeof(periph_conf);
1000+
}
9911001
}
9921002

9931003
ret = dmaengine_slave_config(nandc->chan, &slave_conf);

drivers/tty/serial/msm_serial.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <linux/kernel.h>
1111
#include <linux/atomic.h>
12+
#include <linux/dma/qcom_adm.h>
1213
#include <linux/dma-mapping.h>
1314
#include <linux/dmaengine.h>
1415
#include <linux/module.h>
@@ -290,6 +291,7 @@ static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base)
290291
{
291292
struct device *dev = msm_port->uart.dev;
292293
struct dma_slave_config conf;
294+
struct qcom_adm_peripheral_config periph_conf = {};
293295
struct msm_dma *dma;
294296
u32 crci = 0;
295297
int ret;
@@ -308,7 +310,11 @@ static void msm_request_tx_dma(struct msm_port *msm_port, resource_size_t base)
308310
conf.device_fc = true;
309311
conf.dst_addr = base + UARTDM_TF;
310312
conf.dst_maxburst = UARTDM_BURST_SIZE;
311-
conf.slave_id = crci;
313+
if (crci) {
314+
conf.peripheral_config = &periph_conf;
315+
conf.peripheral_size = sizeof(periph_conf);
316+
periph_conf.crci = crci;
317+
}
312318

313319
ret = dmaengine_slave_config(dma->chan, &conf);
314320
if (ret)
@@ -333,6 +339,7 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
333339
{
334340
struct device *dev = msm_port->uart.dev;
335341
struct dma_slave_config conf;
342+
struct qcom_adm_peripheral_config periph_conf = {};
336343
struct msm_dma *dma;
337344
u32 crci = 0;
338345
int ret;
@@ -355,7 +362,11 @@ static void msm_request_rx_dma(struct msm_port *msm_port, resource_size_t base)
355362
conf.device_fc = true;
356363
conf.src_addr = base + UARTDM_RF;
357364
conf.src_maxburst = UARTDM_BURST_SIZE;
358-
conf.slave_id = crci;
365+
if (crci) {
366+
conf.peripheral_config = &periph_conf;
367+
conf.peripheral_size = sizeof(periph_conf);
368+
periph_conf.crci = crci;
369+
}
359370

360371
ret = dmaengine_slave_config(dma->chan, &conf);
361372
if (ret)

include/linux/dma/qcom_adm.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#ifndef __LINUX_DMA_QCOM_ADM_H
3+
#define __LINUX_DMA_QCOM_ADM_H
4+
5+
#include <linux/types.h>
6+
7+
struct qcom_adm_peripheral_config {
8+
u32 crci;
9+
u32 mux;
10+
};
11+
12+
#endif /* __LINUX_DMA_QCOM_ADM_H */

0 commit comments

Comments
 (0)