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 <peter.ujfalusi@ti.com>
Link: https://lore.kernel.org/r/20200717120903.8774-3-peter.ujfalusi@ti.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Peter Ujfalusi 2020-07-17 15:09:03 +03:00 committed by Vinod Koul
parent 44385c4171
commit daf4ad0499
2 changed files with 30 additions and 29 deletions

View File

@ -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),

View File

@ -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)