From daf4ad0499aa4f75c6f32493829acdbe48110b32 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 17 Jul 2020 15:09:03 +0300 Subject: [PATCH] dmaengine: ti: k3-udma: Query throughput level information from hardware The CAP3 register contains information about the number of HCHAN (High Capacity) and UCHAN (Ultra High Capacity) channels in UDMAP. Based on this information the start indexes of the levels can be calculated without a need of a table in the match data. On am654 the CAP3 does not contain information about the number different channels. Set up the tpl information based on the available documentation. This change will allow to use the same compatible for different SoCs where the only difference is the number of channel types. Signed-off-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20200717120903.8774-3-peter.ujfalusi@ti.com Signed-off-by: Vinod Koul --- drivers/dma/ti/k3-udma.c | 57 ++++++++++++++++++++-------------------- drivers/dma/ti/k3-udma.h | 2 ++ 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index e1b7cde793e3..8fa26e25ddba 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -92,9 +92,6 @@ struct udma_match_data { u32 flags; u32 statictr_z_mask; u32 rchan_oes_offset; - - u8 tpl_levels; - u32 level_start_idx[]; }; struct udma_hwdesc { @@ -121,6 +118,9 @@ struct udma_dev { void __iomem *mmrs[MMR_LAST]; const struct udma_match_data *match_data; + u8 tpl_levels; + u32 tpl_start_idx[3]; + size_t desc_align; /* alignment to use for descriptors */ struct udma_tisci_rm tisci_rm; @@ -1210,10 +1210,10 @@ static struct udma_##res *__udma_reserve_##res(struct udma_dev *ud, \ } else { \ int start; \ \ - if (tpl >= ud->match_data->tpl_levels) \ - tpl = ud->match_data->tpl_levels - 1; \ + if (tpl >= ud->tpl_levels) \ + tpl = ud->tpl_levels - 1; \ \ - start = ud->match_data->level_start_idx[tpl]; \ + start = ud->tpl_start_idx[tpl]; \ \ id = find_next_zero_bit(ud->res##_map, ud->res##_cnt, \ start); \ @@ -1262,7 +1262,6 @@ static int udma_get_rchan(struct udma_chan *uc) static int udma_get_chan_pair(struct udma_chan *uc) { struct udma_dev *ud = uc->ud; - const struct udma_match_data *match_data = ud->match_data; int chan_id, end; if ((uc->tchan && uc->rchan) && uc->tchan->id == uc->rchan->id) { @@ -1284,7 +1283,7 @@ static int udma_get_chan_pair(struct udma_chan *uc) /* Can be optimized, but let's have it like this for now */ end = min(ud->tchan_cnt, ud->rchan_cnt); /* Try to use the highest TPL channel pair for MEM_TO_MEM channels */ - chan_id = match_data->level_start_idx[match_data->tpl_levels - 1]; + chan_id = ud->tpl_start_idx[ud->tpl_levels - 1]; for (; chan_id < end; chan_id++) { if (!test_bit(chan_id, ud->tchan_map) && !test_bit(chan_id, ud->rchan_map)) @@ -3117,11 +3116,6 @@ static struct udma_match_data am654_main_data = { .enable_memcpy_support = true, .statictr_z_mask = GENMASK(11, 0), .rchan_oes_offset = 0x2000, - .tpl_levels = 2, - .level_start_idx = { - [0] = 8, /* Normal channels */ - [1] = 0, /* High Throughput channels */ - }, }; static struct udma_match_data am654_mcu_data = { @@ -3129,11 +3123,6 @@ static struct udma_match_data am654_mcu_data = { .enable_memcpy_support = false, .statictr_z_mask = GENMASK(11, 0), .rchan_oes_offset = 0x2000, - .tpl_levels = 2, - .level_start_idx = { - [0] = 2, /* Normal channels */ - [1] = 0, /* High Throughput channels */ - }, }; static struct udma_match_data j721e_main_data = { @@ -3142,12 +3131,6 @@ static struct udma_match_data j721e_main_data = { .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST, .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 = { @@ -3156,11 +3139,6 @@ static struct udma_match_data j721e_mcu_data = { .flags = UDMA_FLAG_PDMA_ACC32 | UDMA_FLAG_PDMA_BURST, .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 of_device_id udma_of_match[] = { @@ -3218,6 +3196,27 @@ static int udma_setup_resources(struct udma_dev *ud) ud->rchan_cnt = UDMA_CAP2_RCHAN_CNT(cap2); ch_count = ud->tchan_cnt + ud->rchan_cnt; + /* Set up the throughput level start indexes */ + if (of_device_is_compatible(dev->of_node, + "ti,am654-navss-main-udmap")) { + ud->tpl_levels = 2; + ud->tpl_start_idx[0] = 8; + } else if (of_device_is_compatible(dev->of_node, + "ti,am654-navss-mcu-udmap")) { + ud->tpl_levels = 2; + ud->tpl_start_idx[0] = 2; + } else if (UDMA_CAP3_UCHAN_CNT(cap3)) { + ud->tpl_levels = 3; + ud->tpl_start_idx[1] = UDMA_CAP3_UCHAN_CNT(cap3); + ud->tpl_start_idx[0] = ud->tpl_start_idx[1] + + UDMA_CAP3_HCHAN_CNT(cap3); + } else if (UDMA_CAP3_HCHAN_CNT(cap3)) { + ud->tpl_levels = 2; + ud->tpl_start_idx[0] = UDMA_CAP3_HCHAN_CNT(cap3); + } else { + ud->tpl_levels = 1; + } + ud->tchan_map = devm_kmalloc_array(dev, BITS_TO_LONGS(ud->tchan_cnt), sizeof(unsigned long), GFP_KERNEL); ud->tchans = devm_kcalloc(dev, ud->tchan_cnt, sizeof(*ud->tchans), diff --git a/drivers/dma/ti/k3-udma.h b/drivers/dma/ti/k3-udma.h index 9534f0ca29f4..09c4529e013d 100644 --- a/drivers/dma/ti/k3-udma.h +++ b/drivers/dma/ti/k3-udma.h @@ -42,6 +42,8 @@ #define UDMA_CAP2_ECHAN_CNT(val) (((val) >> 9) & 0x1ff) #define UDMA_CAP2_RCHAN_CNT(val) (((val) >> 18) & 0x1ff) #define UDMA_CAP3_RFLOW_CNT(val) ((val) & 0x3fff) +#define UDMA_CAP3_HCHAN_CNT(val) (((val) >> 14) & 0x1ff) +#define UDMA_CAP3_UCHAN_CNT(val) (((val) >> 23) & 0x1ff) /* UDMA_CHAN_RT_CTL_REG */ #define UDMA_CHAN_RT_CTL_EN BIT(31)