summaryrefslogtreecommitdiff
path: root/drivers/dma
diff options
context:
space:
mode:
authorVignesh Raghavendra <vigneshr@ti.com>2019-12-04 22:17:21 +0530
committerJoe Hershberger <joe.hershberger@ni.com>2019-12-09 09:47:43 -0600
commit5e6d9ccde9cf700e19e0d783f1f671a1eb4a60fb (patch)
tree1dda58fd65d436618231818ec63a34b28b9f17d8 /drivers/dma
parentb8a4dd28f3b719d176fed5dc8d23a898463b072c (diff)
dma: ti: k3-udma: Implement dma_get_cfg() interface
Implement dma_get_cfg() interface to pass flow id information for DMA clients to use. This is needed because on K3 SoCs, CPSW (ethernet) and UDMA (DMA provider) support "flows" within a given RX DMA channel. This allows different network packets to be segregated while using same RX DMA channel. In order for basic ethernet to work, CPSW slave must be aware of the flow ID allocated for the RX channel by the DMA driver. This interface allows CPSW to query flow ID from DMA provider and configure it in CPSW HW. Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com> Acked-by: Joe Hershberger <joe.hershberger@ni.com> Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/ti/k3-udma.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index 2e64d338ca..f90ca53e90 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -104,6 +104,8 @@ struct udma_chan {
struct udma_rchan *rchan;
struct udma_rflow *rflow;
+ struct ti_udma_drv_chan_cfg_data cfg_data;
+
u32 bcnt; /* number of bytes completed since the start of the channel */
bool pkt_mode; /* TR or packet */
@@ -1407,6 +1409,11 @@ static int udma_request(struct dma *dma)
uc->desc_rx_cur = 0;
uc->num_rx_bufs = 0;
+ if (uc->dir == DMA_DEV_TO_MEM) {
+ uc->cfg_data.flow_id_base = uc->rflow->id;
+ uc->cfg_data.flow_id_cnt = 1;
+ }
+
return 0;
}
@@ -1689,6 +1696,26 @@ int udma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size)
return 0;
}
+static int udma_get_cfg(struct dma *dma, u32 id, void **data)
+{
+ struct udma_dev *ud = dev_get_priv(dma->dev);
+ struct udma_chan *uc;
+
+ if (dma->id >= (ud->rchan_cnt + ud->tchan_cnt)) {
+ dev_err(dma->dev, "invalid dma ch_id %lu\n", dma->id);
+ return -EINVAL;
+ }
+
+ switch (id) {
+ case TI_UDMA_CHAN_PRIV_INFO:
+ uc = &ud->channels[dma->id];
+ *data = &uc->cfg_data;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
static const struct dma_ops udma_ops = {
.transfer = udma_transfer,
.of_xlate = udma_of_xlate,
@@ -1699,6 +1726,7 @@ static const struct dma_ops udma_ops = {
.send = udma_send,
.receive = udma_receive,
.prepare_rcv_buf = udma_prepare_rcv_buf,
+ .get_cfg = udma_get_cfg,
};
static const struct udevice_id udma_ids[] = {