diff options
Diffstat (limited to 'drivers/dma/ti/k3-udma.c')
-rw-r--r-- | drivers/dma/ti/k3-udma.c | 402 |
1 files changed, 231 insertions, 171 deletions
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 2ce16c8e27..57d9fbfabb 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -22,7 +22,6 @@ #include <dma.h> #include <dma-uclass.h> #include <linux/delay.h> -#include <dt-bindings/dma/k3-udma.h> #include <linux/bitmap.h> #include <linux/err.h> #include <linux/soc/ti/k3-navss-ringacc.h> @@ -31,12 +30,7 @@ #include <linux/soc/ti/ti_sci_protocol.h> #include "k3-udma-hwdef.h" - -#if BITS_PER_LONG == 64 -#define RINGACC_RING_USE_PROXY (0) -#else -#define RINGACC_RING_USE_PROXY (1) -#endif +#include "k3-psil-priv.h" #define K3_UDMA_MAX_RFLOWS 1024 @@ -65,12 +59,28 @@ struct udma_rchan { void __iomem *reg_rt; int id; - struct k3_nav_ring *fd_ring; /* Free Descriptor ring */ - struct k3_nav_ring *r_ring; /* Receive ring*/ +}; + +#define UDMA_FLAG_PDMA_ACC32 BIT(0) +#define UDMA_FLAG_PDMA_BURST BIT(1) +#define UDMA_FLAG_TDTYPE BIT(2) + +struct udma_match_data { + u32 psil_base; + bool enable_memcpy_support; + u32 flags; + u32 statictr_z_mask; + u32 rchan_oes_offset; + + u8 tpl_levels; + u32 level_start_idx[]; }; struct udma_rflow { int id; + + struct k3_nav_ring *fd_ring; /* Free Descriptor ring */ + struct k3_nav_ring *r_ring; /* Receive ring*/ }; enum udma_rm_range { @@ -114,12 +124,34 @@ struct udma_dev { struct udma_rchan *rchans; struct udma_rflow *rflows; + struct udma_match_data *match_data; + struct udma_chan *channels; u32 psil_base; u32 ch_count; }; +struct udma_chan_config { + u32 psd_size; /* size of Protocol Specific Data */ + u32 metadata_size; /* (needs_epib ? 16:0) + psd_size */ + u32 hdesc_size; /* Size of a packet descriptor in packet mode */ + int remote_thread_id; + u32 atype; + u32 src_thread; + u32 dst_thread; + enum psil_endpoint_type ep_type; + enum udma_tp_level channel_tpl; /* Channel Throughput Level */ + + enum dma_direction dir; + + unsigned int pkt_mode:1; /* TR or packet */ + unsigned int needs_epib:1; /* EPIB is needed for the communication or not */ + unsigned int enable_acc32:1; + unsigned int enable_burst:1; + unsigned int notdpkt:1; /* Suppress sending TDC packet */ +}; + struct udma_chan { struct udma_dev *ud; char name[20]; @@ -132,20 +164,11 @@ struct udma_chan { u32 bcnt; /* number of bytes completed since the start of the channel */ - bool pkt_mode; /* TR or packet */ - bool needs_epib; /* EPIB is needed for the communication or not */ - u32 psd_size; /* size of Protocol Specific Data */ - u32 metadata_size; /* (needs_epib ? 16:0) + psd_size */ - int slave_thread_id; - u32 src_thread; - u32 dst_thread; - u32 static_tr_type; + struct udma_chan_config config; u32 id; - enum dma_direction dir; struct cppi5_host_desc_t *desc_tx; - u32 hdesc_size; bool in_use; void *desc_rx; u32 num_rx_bufs; @@ -271,7 +294,7 @@ static inline bool udma_is_chan_running(struct udma_chan *uc) u32 trt_ctl = 0; u32 rrt_ctl = 0; - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: rrt_ctl = udma_rchanrt_read(uc->rchan, UDMA_RCHAN_RT_CTL_REG); pr_debug("%s: rrt_ctl: 0x%08x (peer: 0x%08x)\n", @@ -305,9 +328,9 @@ static int udma_pop_from_ring(struct udma_chan *uc, dma_addr_t *addr) struct k3_nav_ring *ring = NULL; int ret = -ENOENT; - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: - ring = uc->rchan->r_ring; + ring = uc->rflow->r_ring; break; case DMA_MEM_TO_DEV: ring = uc->tchan->tc_ring; @@ -330,10 +353,10 @@ static void udma_reset_rings(struct udma_chan *uc) struct k3_nav_ring *ring1 = NULL; struct k3_nav_ring *ring2 = NULL; - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: - ring1 = uc->rchan->fd_ring; - ring2 = uc->rchan->r_ring; + ring1 = uc->rflow->fd_ring; + ring2 = uc->rflow->r_ring; break; case DMA_MEM_TO_DEV: ring1 = uc->tchan->t_ring; @@ -392,7 +415,7 @@ static inline int udma_stop_hard(struct udma_chan *uc) { pr_debug("%s: ENTER (chan%d)\n", __func__, uc->id); - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_PEER_RT_EN_REG, 0); udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, 0); @@ -418,9 +441,8 @@ static int udma_start(struct udma_chan *uc) if (udma_is_chan_running(uc)) goto out; - pr_debug("%s: chan:%d dir:%s (static_tr_type: %d)\n", - __func__, uc->id, udma_get_dir_text(uc->dir), - uc->static_tr_type); + pr_debug("%s: chan:%d dir:%s\n", + __func__, uc->id, udma_get_dir_text(uc->config.dir)); /* Make sure that we clear the teardown bit, if it is set */ udma_stop_hard(uc); @@ -428,7 +450,7 @@ static int udma_start(struct udma_chan *uc) /* Reset all counters */ udma_reset_counters(uc); - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: udma_rchanrt_write(uc->rchan, UDMA_RCHAN_RT_CTL_REG, UDMA_CHAN_RT_CTL_EN); @@ -530,10 +552,10 @@ static inline void udma_stop_dev2mem(struct udma_chan *uc, bool sync) static inline int udma_stop(struct udma_chan *uc) { pr_debug("%s: chan:%d dir:%s\n", - __func__, uc->id, udma_get_dir_text(uc->dir)); + __func__, uc->id, udma_get_dir_text(uc->config.dir)); udma_reset_counters(uc); - switch (uc->dir) { + switch (uc->config.dir) { case DMA_DEV_TO_MEM: udma_stop_dev2mem(uc, true); break; @@ -768,21 +790,14 @@ static int udma_alloc_tx_resources(struct udma_chan *uc) if (ret) return ret; - uc->tchan->t_ring = k3_nav_ringacc_request_ring( - ud->ringacc, uc->tchan->id, - RINGACC_RING_USE_PROXY); - if (!uc->tchan->t_ring) { + ret = k3_nav_ringacc_request_rings_pair(ud->ringacc, uc->tchan->id, -1, + &uc->tchan->t_ring, + &uc->tchan->tc_ring); + if (ret) { ret = -EBUSY; goto err_tx_ring; } - uc->tchan->tc_ring = k3_nav_ringacc_request_ring( - ud->ringacc, -1, RINGACC_RING_USE_PROXY); - if (!uc->tchan->tc_ring) { - ret = -EBUSY; - goto err_txc_ring; - } - memset(&ring_cfg, 0, sizeof(ring_cfg)); ring_cfg.size = 16; ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8; @@ -799,7 +814,6 @@ static int udma_alloc_tx_resources(struct udma_chan *uc) err_ringcfg: k3_nav_ringacc_ring_free(uc->tchan->tc_ring); uc->tchan->tc_ring = NULL; -err_txc_ring: k3_nav_ringacc_ring_free(uc->tchan->t_ring); uc->tchan->t_ring = NULL; err_tx_ring: @@ -813,12 +827,15 @@ static void udma_free_rx_resources(struct udma_chan *uc) if (!uc->rchan) return; - k3_nav_ringacc_ring_free(uc->rchan->fd_ring); - k3_nav_ringacc_ring_free(uc->rchan->r_ring); - uc->rchan->fd_ring = NULL; - uc->rchan->r_ring = NULL; + if (uc->rflow) { + k3_nav_ringacc_ring_free(uc->rflow->fd_ring); + k3_nav_ringacc_ring_free(uc->rflow->r_ring); + uc->rflow->fd_ring = NULL; + uc->rflow->r_ring = NULL; + + udma_put_rflow(uc); + } - udma_put_rflow(uc); udma_put_rchan(uc); } @@ -826,6 +843,7 @@ static int udma_alloc_rx_resources(struct udma_chan *uc) { struct k3_nav_ring_cfg ring_cfg; struct udma_dev *ud = uc->ud; + struct udma_rflow *rflow; int fd_ring_id; int ret; @@ -834,7 +852,7 @@ static int udma_alloc_rx_resources(struct udma_chan *uc) return ret; /* For MEM_TO_MEM we don't need rflow or rings */ - if (uc->dir == DMA_MEM_TO_MEM) + if (uc->config.dir == DMA_MEM_TO_MEM) return 0; ret = udma_get_rflow(uc, uc->rchan->id); @@ -845,40 +863,31 @@ static int udma_alloc_rx_resources(struct udma_chan *uc) fd_ring_id = ud->tchan_cnt + ud->echan_cnt + uc->rchan->id; - uc->rchan->fd_ring = k3_nav_ringacc_request_ring( - ud->ringacc, fd_ring_id, - RINGACC_RING_USE_PROXY); - if (!uc->rchan->fd_ring) { + rflow = uc->rflow; + ret = k3_nav_ringacc_request_rings_pair(ud->ringacc, fd_ring_id, -1, + &rflow->fd_ring, &rflow->r_ring); + if (ret) { ret = -EBUSY; goto err_rx_ring; } - uc->rchan->r_ring = k3_nav_ringacc_request_ring( - ud->ringacc, -1, RINGACC_RING_USE_PROXY); - if (!uc->rchan->r_ring) { - ret = -EBUSY; - goto err_rxc_ring; - } - memset(&ring_cfg, 0, sizeof(ring_cfg)); ring_cfg.size = 16; ring_cfg.elm_size = K3_NAV_RINGACC_RING_ELSIZE_8; ring_cfg.mode = K3_NAV_RINGACC_RING_MODE_RING; - ret = k3_nav_ringacc_ring_cfg(uc->rchan->fd_ring, &ring_cfg); - ret |= k3_nav_ringacc_ring_cfg(uc->rchan->r_ring, &ring_cfg); - + ret = k3_nav_ringacc_ring_cfg(rflow->fd_ring, &ring_cfg); + ret |= k3_nav_ringacc_ring_cfg(rflow->r_ring, &ring_cfg); if (ret) goto err_ringcfg; return 0; err_ringcfg: - k3_nav_ringacc_ring_free(uc->rchan->r_ring); - uc->rchan->r_ring = NULL; -err_rxc_ring: - k3_nav_ringacc_ring_free(uc->rchan->fd_ring); - uc->rchan->fd_ring = NULL; + k3_nav_ringacc_ring_free(rflow->r_ring); + rflow->r_ring = NULL; + k3_nav_ringacc_ring_free(rflow->fd_ring); + rflow->fd_ring = NULL; err_rx_ring: udma_put_rflow(uc); err_rflow: @@ -896,7 +905,7 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc) u32 mode; int ret; - if (uc->pkt_mode) + if (uc->config.pkt_mode) mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR; else mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR; @@ -907,11 +916,11 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc) req.nav_id = tisci_rm->tisci_dev_id; req.index = uc->tchan->id; req.tx_chan_type = mode; - if (uc->dir == DMA_MEM_TO_MEM) + if (uc->config.dir == DMA_MEM_TO_MEM) req.tx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2; else - req.tx_fetch_size = cppi5_hdesc_calc_size(uc->needs_epib, - uc->psd_size, + req.tx_fetch_size = cppi5_hdesc_calc_size(uc->config.needs_epib, + uc->config.psd_size, 0) >> 2; req.txcq_qnum = tc_ring; @@ -925,8 +934,8 @@ static int udma_alloc_tchan_sci_req(struct udma_chan *uc) static int udma_alloc_rchan_sci_req(struct udma_chan *uc) { struct udma_dev *ud = uc->ud; - int fd_ring = k3_nav_ringacc_get_ring_id(uc->rchan->fd_ring); - int rx_ring = k3_nav_ringacc_get_ring_id(uc->rchan->r_ring); + int fd_ring = k3_nav_ringacc_get_ring_id(uc->rflow->fd_ring); + int rx_ring = k3_nav_ringacc_get_ring_id(uc->rflow->r_ring); int tc_ring = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring); struct ti_sci_msg_rm_udmap_rx_ch_cfg req = { 0 }; struct ti_sci_msg_rm_udmap_flow_cfg flow_req = { 0 }; @@ -934,7 +943,7 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc) u32 mode; int ret; - if (uc->pkt_mode) + if (uc->config.pkt_mode) mode = TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR; else mode = TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR; @@ -947,16 +956,16 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc) req.nav_id = tisci_rm->tisci_dev_id; req.index = uc->rchan->id; req.rx_chan_type = mode; - if (uc->dir == DMA_MEM_TO_MEM) { + if (uc->config.dir == DMA_MEM_TO_MEM) { req.rx_fetch_size = sizeof(struct cppi5_desc_hdr_t) >> 2; req.rxcq_qnum = tc_ring; } else { - req.rx_fetch_size = cppi5_hdesc_calc_size(uc->needs_epib, - uc->psd_size, + req.rx_fetch_size = cppi5_hdesc_calc_size(uc->config.needs_epib, + uc->config.psd_size, 0) >> 2; req.rxcq_qnum = rx_ring; } - if (uc->rflow->id != uc->rchan->id && uc->dir != DMA_MEM_TO_MEM) { + if (uc->rflow->id != uc->rchan->id && uc->config.dir != DMA_MEM_TO_MEM) { req.flowid_start = uc->rflow->id; req.flowid_cnt = 1; } @@ -967,7 +976,7 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc) uc->rchan->id, ret); return ret; } - if (uc->dir == DMA_MEM_TO_MEM) + if (uc->config.dir == DMA_MEM_TO_MEM) return ret; flow_req.valid_params = @@ -989,12 +998,12 @@ static int udma_alloc_rchan_sci_req(struct udma_chan *uc) flow_req.nav_id = tisci_rm->tisci_dev_id; flow_req.flow_index = uc->rflow->id; - if (uc->needs_epib) + if (uc->config.needs_epib) flow_req.rx_einfo_present = 1; else flow_req.rx_einfo_present = 0; - if (uc->psd_size) + if (uc->config.psd_size) flow_req.rx_psinfo_present = 1; else flow_req.rx_psinfo_present = 0; @@ -1027,11 +1036,12 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) int ret; pr_debug("%s: chan:%d as %s\n", - __func__, uc->id, udma_get_dir_text(uc->dir)); + __func__, uc->id, udma_get_dir_text(uc->config.dir)); - switch (uc->dir) { + switch (uc->config.dir) { case DMA_MEM_TO_MEM: /* Non synchronized - mem to mem type of transfer */ + uc->config.pkt_mode = false; ret = udma_get_chan_pair(uc); if (ret) return ret; @@ -1044,8 +1054,8 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) if (ret) goto err_free_res; - uc->src_thread = ud->psil_base + uc->tchan->id; - uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; + uc->config.src_thread = ud->psil_base + uc->tchan->id; + uc->config.dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; break; case DMA_MEM_TO_DEV: /* Slave transfer synchronized - mem to dev (TX) trasnfer */ @@ -1053,10 +1063,9 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) if (ret) goto err_free_res; - uc->src_thread = ud->psil_base + uc->tchan->id; - uc->dst_thread = uc->slave_thread_id; - if (!(uc->dst_thread & 0x8000)) - uc->dst_thread |= 0x8000; + uc->config.src_thread = ud->psil_base + uc->tchan->id; + uc->config.dst_thread = uc->config.remote_thread_id; + uc->config.dst_thread |= 0x8000; break; case DMA_DEV_TO_MEM: @@ -1065,19 +1074,19 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) if (ret) goto err_free_res; - uc->src_thread = uc->slave_thread_id; - uc->dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; + uc->config.src_thread = uc->config.remote_thread_id; + uc->config.dst_thread = (ud->psil_base + uc->rchan->id) | 0x8000; break; default: /* Can not happen */ pr_debug("%s: chan:%d invalid direction (%u)\n", - __func__, uc->id, uc->dir); + __func__, uc->id, uc->config.dir); return -EINVAL; } /* We have channel indexes and rings */ - if (uc->dir == DMA_MEM_TO_MEM) { + if (uc->config.dir == DMA_MEM_TO_MEM) { ret = udma_alloc_tchan_sci_req(uc); if (ret) goto err_free_res; @@ -1087,7 +1096,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) goto err_free_res; } else { /* Slave transfer */ - if (uc->dir == DMA_MEM_TO_DEV) { + if (uc->config.dir == DMA_MEM_TO_DEV) { ret = udma_alloc_tchan_sci_req(uc); if (ret) goto err_free_res; @@ -1108,7 +1117,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) } /* PSI-L pairing */ - ret = udma_navss_psil_pair(ud, uc->src_thread, uc->dst_thread); + ret = udma_navss_psil_pair(ud, uc->config.src_thread, uc->config.dst_thread); if (ret) { dev_err(ud->dev, "k3_nav_psil_request_link fail\n"); goto err_free_res; @@ -1119,7 +1128,7 @@ static int udma_alloc_chan_resources(struct udma_chan *uc) err_free_res: udma_free_tx_resources(uc); udma_free_rx_resources(uc); - uc->slave_thread_id = -1; + uc->config.remote_thread_id = -1; return ret; } @@ -1128,15 +1137,15 @@ static void udma_free_chan_resources(struct udma_chan *uc) /* Some configuration to UDMA-P channel: disable, reset, whatever */ /* Release PSI-L pairing */ - udma_navss_psil_unpair(uc->ud, uc->src_thread, uc->dst_thread); + udma_navss_psil_unpair(uc->ud, uc->config.src_thread, uc->config.dst_thread); /* Reset the rings for a new start */ udma_reset_rings(uc); udma_free_tx_resources(uc); udma_free_rx_resources(uc); - uc->slave_thread_id = -1; - uc->dir = DMA_MEM_TO_MEM; + uc->config.remote_thread_id = -1; + uc->config.dir = DMA_MEM_TO_MEM; } static int udma_get_mmrs(struct udevice *dev) @@ -1293,12 +1302,8 @@ static int udma_probe(struct udevice *dev) if (IS_ERR(ud->ringacc)) return PTR_ERR(ud->ringacc); - ud->psil_base = dev_read_u32_default(dev, "ti,psil-base", 0); - if (!ud->psil_base) { - dev_info(dev, - "Missing ti,psil-base property, using %d.\n", ret); - return -EINVAL; - } + ud->match_data = (void *)dev_get_driver_data(dev); + ud->psil_base = ud->match_data->psil_base; ret = uclass_get_device_by_phandle(UCLASS_FIRMWARE, dev, "ti,sci", &tisci_dev); @@ -1364,10 +1369,10 @@ static int udma_probe(struct udevice *dev) uc->ud = ud; uc->id = i; - uc->slave_thread_id = -1; + uc->config.remote_thread_id = -1; uc->tchan = NULL; uc->rchan = NULL; - uc->dir = DMA_MEM_TO_MEM; + uc->config.dir = DMA_MEM_TO_MEM; sprintf(uc->name, "UDMA chan%d\n", i); if (!i) uc->in_use = true; @@ -1514,6 +1519,7 @@ static int udma_transfer(struct udevice *dev, int direction, static int udma_request(struct dma *dma) { struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan_config *ucc; struct udma_chan *uc; unsigned long dummy; int ret; @@ -1524,30 +1530,27 @@ static int udma_request(struct dma *dma) } uc = &ud->channels[dma->id]; + ucc = &uc->config; ret = udma_alloc_chan_resources(uc); if (ret) { dev_err(dma->dev, "alloc dma res failed %d\n", ret); return -EINVAL; } - uc->hdesc_size = cppi5_hdesc_calc_size(uc->needs_epib, - uc->psd_size, 0); - uc->hdesc_size = ALIGN(uc->hdesc_size, ARCH_DMA_MINALIGN); - - if (uc->dir == DMA_MEM_TO_DEV) { - uc->desc_tx = dma_alloc_coherent(uc->hdesc_size, &dummy); - memset(uc->desc_tx, 0, uc->hdesc_size); + if (uc->config.dir == DMA_MEM_TO_DEV) { + uc->desc_tx = dma_alloc_coherent(ucc->hdesc_size, &dummy); + memset(uc->desc_tx, 0, ucc->hdesc_size); } else { uc->desc_rx = dma_alloc_coherent( - uc->hdesc_size * UDMA_RX_DESC_NUM, &dummy); - memset(uc->desc_rx, 0, uc->hdesc_size * UDMA_RX_DESC_NUM); + ucc->hdesc_size * UDMA_RX_DESC_NUM, &dummy); + memset(uc->desc_rx, 0, ucc->hdesc_size * UDMA_RX_DESC_NUM); } uc->in_use = true; uc->desc_rx_cur = 0; uc->num_rx_bufs = 0; - if (uc->dir == DMA_DEV_TO_MEM) { + if (uc->config.dir == DMA_DEV_TO_MEM) { uc->cfg_data.flow_id_base = uc->rflow->id; uc->cfg_data.flow_id_cnt = 1; } @@ -1632,7 +1635,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) } uc = &ud->channels[dma->id]; - if (uc->dir != DMA_MEM_TO_DEV) + if (uc->config.dir != DMA_MEM_TO_DEV) return -EINVAL; tc_ring_id = k3_nav_ringacc_get_ring_id(uc->tchan->tc_ring); @@ -1642,8 +1645,8 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) cppi5_hdesc_reset_hbdesc(desc_tx); cppi5_hdesc_init(desc_tx, - uc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, - uc->psd_size); + uc->config.needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, + uc->config.psd_size); cppi5_hdesc_set_pktlen(desc_tx, len); cppi5_hdesc_attach_buf(desc_tx, dma_src, len, dma_src, len); cppi5_desc_set_pktids(&desc_tx->hdr, uc->id, 0x3fff); @@ -1656,7 +1659,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) ALIGN((unsigned long)dma_src + len, ARCH_DMA_MINALIGN)); flush_dcache_range((unsigned long)desc_tx, - ALIGN((unsigned long)desc_tx + uc->hdesc_size, + ALIGN((unsigned long)desc_tx + uc->config.hdesc_size, ARCH_DMA_MINALIGN)); ret = udma_push_to_ring(uc->tchan->t_ring, uc->desc_tx); @@ -1674,6 +1677,7 @@ static int udma_send(struct dma *dma, void *src, size_t len, void *metadata) static int udma_receive(struct dma *dma, void **dst, void *metadata) { struct udma_dev *ud = dev_get_priv(dma->dev); + struct udma_chan_config *ucc; struct cppi5_host_desc_t *desc_rx; dma_addr_t buf_dma; struct udma_chan *uc; @@ -1686,13 +1690,14 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata) return -EINVAL; } uc = &ud->channels[dma->id]; + ucc = &uc->config; - if (uc->dir != DMA_DEV_TO_MEM) + if (uc->config.dir != DMA_DEV_TO_MEM) return -EINVAL; if (!uc->num_rx_bufs) return -EINVAL; - ret = k3_nav_ringacc_ring_pop(uc->rchan->r_ring, &desc_rx); + ret = k3_nav_ringacc_ring_pop(uc->rflow->r_ring, &desc_rx); if (ret && ret != -ENODATA) { dev_err(dma->dev, "rx dma fail ch_id:%lu %d\n", dma->id, ret); return ret; @@ -1702,7 +1707,7 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata) /* invalidate cache data */ invalidate_dcache_range((ulong)desc_rx, - (ulong)(desc_rx + uc->hdesc_size)); + (ulong)(desc_rx + ucc->hdesc_size)); cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len); pkt_len = cppi5_hdesc_get_pktlen(desc_rx); @@ -1721,10 +1726,10 @@ static int udma_receive(struct dma *dma, void **dst, void *metadata) static int udma_of_xlate(struct dma *dma, struct ofnode_phandle_args *args) { + struct udma_chan_config *ucc; struct udma_dev *ud = dev_get_priv(dma->dev); struct udma_chan *uc = &ud->channels[0]; - ofnode chconf_node, slave_node; - char prop[50]; + struct psil_endpoint_config *ep_config; u32 val; for (val = 0; val < ud->ch_count; val++) { @@ -1736,48 +1741,40 @@ static int udma_of_xlate(struct dma *dma, struct ofnode_phandle_args *args) if (val == ud->ch_count) return -EBUSY; - uc->dir = DMA_DEV_TO_MEM; - if (args->args[2] == UDMA_DIR_TX) - uc->dir = DMA_MEM_TO_DEV; - - slave_node = ofnode_get_by_phandle(args->args[0]); - if (!ofnode_valid(slave_node)) { - dev_err(ud->dev, "slave node is missing\n"); - return -EINVAL; - } - - snprintf(prop, sizeof(prop), "ti,psil-config%u", args->args[1]); - chconf_node = ofnode_find_subnode(slave_node, prop); - if (!ofnode_valid(chconf_node)) { - dev_err(ud->dev, "Channel configuration node is missing\n"); - return -EINVAL; - } + ucc = &uc->config; + ucc->remote_thread_id = args->args[0]; + if (ucc->remote_thread_id & K3_PSIL_DST_THREAD_ID_OFFSET) + ucc->dir = DMA_MEM_TO_DEV; + else + ucc->dir = DMA_DEV_TO_MEM; - if (!ofnode_read_u32(chconf_node, "linux,udma-mode", &val)) { - if (val == UDMA_PKT_MODE) - uc->pkt_mode = true; + ep_config = psil_get_ep_config(ucc->remote_thread_id); + if (IS_ERR(ep_config)) { + dev_err(ud->dev, "No configuration for psi-l thread 0x%04x\n", + uc->config.remote_thread_id); + ucc->dir = DMA_MEM_TO_MEM; + ucc->remote_thread_id = -1; + return false; } - if (!ofnode_read_u32(chconf_node, "statictr-type", &val)) - uc->static_tr_type = val; + ucc->pkt_mode = ep_config->pkt_mode; + ucc->channel_tpl = ep_config->channel_tpl; + ucc->notdpkt = ep_config->notdpkt; + ucc->ep_type = ep_config->ep_type; - uc->needs_epib = ofnode_read_bool(chconf_node, "ti,needs-epib"); - if (!ofnode_read_u32(chconf_node, "ti,psd-size", &val)) - uc->psd_size = val; - uc->metadata_size = (uc->needs_epib ? 16 : 0) + uc->psd_size; + ucc->needs_epib = ep_config->needs_epib; + ucc->psd_size = ep_config->psd_size; + ucc->metadata_size = (ucc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_SIZE : 0) + ucc->psd_size; - if (ofnode_read_u32(slave_node, "ti,psil-base", &val)) { - dev_err(ud->dev, "ti,psil-base is missing\n"); - return -EINVAL; - } - - uc->slave_thread_id = val + args->args[1]; + ucc->hdesc_size = cppi5_hdesc_calc_size(ucc->needs_epib, + ucc->psd_size, 0); + ucc->hdesc_size = ALIGN(ucc->hdesc_size, ARCH_DMA_MINALIGN); dma->id = uc->id; pr_debug("Allocated dma chn:%lu epib:%d psdata:%u meta:%u thread_id:%x\n", - dma->id, uc->needs_epib, - uc->psd_size, uc->metadata_size, - uc->slave_thread_id); + dma->id, ucc->needs_epib, + ucc->psd_size, ucc->metadata_size, + ucc->remote_thread_id); return 0; } @@ -1796,29 +1793,29 @@ int udma_prepare_rcv_buf(struct dma *dma, void *dst, size_t size) } uc = &ud->channels[dma->id]; - if (uc->dir != DMA_DEV_TO_MEM) + if (uc->config.dir != DMA_DEV_TO_MEM) return -EINVAL; if (uc->num_rx_bufs >= UDMA_RX_DESC_NUM) return -EINVAL; desc_num = uc->desc_rx_cur % UDMA_RX_DESC_NUM; - desc_rx = uc->desc_rx + (desc_num * uc->hdesc_size); + desc_rx = uc->desc_rx + (desc_num * uc->config.hdesc_size); dma_dst = (dma_addr_t)dst; cppi5_hdesc_reset_hbdesc(desc_rx); cppi5_hdesc_init(desc_rx, - uc->needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, - uc->psd_size); + uc->config.needs_epib ? CPPI5_INFO0_HDESC_EPIB_PRESENT : 0, + uc->config.psd_size); cppi5_hdesc_set_pktlen(desc_rx, size); cppi5_hdesc_attach_buf(desc_rx, dma_dst, size, dma_dst, size); flush_dcache_range((unsigned long)desc_rx, - ALIGN((unsigned long)desc_rx + uc->hdesc_size, + ALIGN((unsigned long)desc_rx + uc->config.hdesc_size, ARCH_DMA_MINALIGN)); - udma_push_to_ring(uc->rchan->fd_ring, desc_rx); + udma_push_to_ring(uc->rflow->fd_ring, desc_rx); uc->num_rx_bufs++; uc->desc_rx_cur++; @@ -1859,10 +1856,73 @@ static const struct dma_ops udma_ops = { .get_cfg = udma_get_cfg, }; +static struct udma_match_data am654_main_data = { + .psil_base = 0x1000, + .enable_memcpy_support = true, + .statictr_z_mask = GENMASK(11, 0), + .rchan_oes_offset = 0x200, + .tpl_levels = 2, + .level_start_idx = { + [0] = 8, /* Normal channels */ + [1] = 0, /* High Throughput channels */ + }, +}; + +static struct udma_match_data am654_mcu_data = { + .psil_base = 0x6000, + .enable_memcpy_support = true, + .statictr_z_mask = GENMASK(11, 0), + .rchan_oes_offset = 0x200, + .tpl_levels = 2, + .level_start_idx = { + [0] = 2, /* Normal channels */ + [1] = 0, /* High Throughput channels */ + }, +}; + +static struct udma_match_data j721e_main_data = { + .psil_base = 0x1000, + .enable_memcpy_support = true, + .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST | UDMA_FLAG_TDTYPE, + .statictr_z_mask = GENMASK(23, 0), + .rchan_oes_offset = 0x400, + .tpl_levels = 3, + .level_start_idx = { + [0] = 16, /* Normal channels */ + [1] = 4, /* High Throughput channels */ + [2] = 0, /* Ultra High Throughput channels */ + }, +}; + +static struct udma_match_data j721e_mcu_data = { + .psil_base = 0x6000, + .enable_memcpy_support = true, + .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST | UDMA_FLAG_TDTYPE, + .statictr_z_mask = GENMASK(23, 0), + .rchan_oes_offset = 0x400, + .tpl_levels = 2, + .level_start_idx = { + [0] = 2, /* Normal channels */ + [1] = 0, /* High Throughput channels */ + }, +}; + static const struct udevice_id udma_ids[] = { - { .compatible = "ti,k3-navss-udmap" }, - { .compatible = "ti,j721e-navss-mcu-udmap" }, - { } + { + .compatible = "ti,am654-navss-main-udmap", + .data = (ulong)&am654_main_data, + }, + { + .compatible = "ti,am654-navss-mcu-udmap", + .data = (ulong)&am654_mcu_data, + }, { + .compatible = "ti,j721e-navss-main-udmap", + .data = (ulong)&j721e_main_data, + }, { + .compatible = "ti,j721e-navss-mcu-udmap", + .data = (ulong)&j721e_mcu_data, + }, + { /* Sentinel */ }, }; U_BOOT_DRIVER(ti_edma3) = { |