1/*-
2*******************************************************************************
3Copyright (C) 2015 Annapurna Labs Ltd.
4
5This file may be licensed under the terms of the Annapurna Labs Commercial
6License Agreement.
7
8Alternatively, this file can be distributed under the terms of the GNU General
9Public License V2 as published by the Free Software Foundation and can be
10found at http://www.gnu.org/licenses/gpl-2.0.html
11
12Alternatively, redistribution and use in source and binary forms, with or
13without modification, are permitted provided that the following conditions are
14met:
15
16    *     Redistributions of source code must retain the above copyright notice,
17this list of conditions and the following disclaimer.
18
19    *     Redistributions in binary form must reproduce the above copyright
20notice, this list of conditions and the following disclaimer in
21the documentation and/or other materials provided with the
22distribution.
23
24THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35*******************************************************************************/
36
37/**
38 * @file   al_hal_udma_config.c
39 *
40 * @brief  Universal DMA HAL driver for configurations
41 *
42 */
43
44#include <al_hal_common.h>
45#include <al_hal_udma_regs.h>
46#include <al_hal_udma_config.h>
47
48/**************** Misc configurations *********************/
49/** Configure AXI generic configuration */
50int al_udma_axi_set(struct udma_gen_axi *axi_regs,
51					struct al_udma_axi_conf *axi)
52{
53        uint32_t reg;
54
55        al_reg_write32(&axi_regs->cfg_1, axi->axi_timeout);
56
57        reg = al_reg_read32(&axi_regs->cfg_2);
58        reg &= ~UDMA_GEN_AXI_CFG_2_ARB_PROMOTION_MASK;
59        reg |= axi->arb_promotion;
60        al_reg_write32(&axi_regs->cfg_2, reg);
61
62        reg = al_reg_read32(&axi_regs->endian_cfg);
63        if (axi->swap_8_bytes == AL_TRUE)
64                reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_64B_EN;
65        else
66                reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_64B_EN;
67
68        if (axi->swap_s2m_data == AL_TRUE)
69                reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DATA;
70        else
71                reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DATA;
72
73        if (axi->swap_s2m_desc == AL_TRUE)
74                reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DESC;
75        else
76                reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_S2M_DESC;
77
78        if (axi->swap_m2s_data == AL_TRUE)
79                reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DATA;
80        else
81                reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DATA;
82
83        if (axi->swap_m2s_desc == AL_TRUE)
84                reg |= UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DESC;
85        else
86                reg &= ~UDMA_GEN_AXI_ENDIAN_CFG_SWAP_M2S_DESC;
87
88        al_reg_write32(&axi_regs->endian_cfg, reg);
89        return 0;
90}
91
92/* Configure UDMA AXI M2S configuration */
93/** Configure AXI M2S submaster */
94static int al_udma_m2s_axi_sm_set(struct al_udma_axi_submaster *m2s_sm,
95				      uint32_t *cfg_1, uint32_t *cfg_2,
96				      uint32_t *cfg_max_beats)
97{
98	uint32_t reg;
99	reg = al_reg_read32(cfg_1);
100	reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_1_AWID_MASK;
101	reg |= m2s_sm->id & UDMA_AXI_M2S_COMP_WR_CFG_1_AWID_MASK;
102	reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_1_AWCACHE_MASK;
103	reg |= (m2s_sm->cache_type <<
104			UDMA_AXI_M2S_COMP_WR_CFG_1_AWCACHE_SHIFT) &
105		UDMA_AXI_M2S_COMP_WR_CFG_1_AWCACHE_MASK;
106	reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_1_AWBURST_MASK;
107	reg |= (m2s_sm->burst << UDMA_AXI_M2S_COMP_WR_CFG_1_AWBURST_SHIFT) &
108		UDMA_AXI_M2S_COMP_WR_CFG_1_AWBURST_MASK;
109	al_reg_write32(cfg_1, reg);
110
111	reg = al_reg_read32(cfg_2);
112	reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_2_AWUSER_MASK;
113	reg |= m2s_sm->used_ext & UDMA_AXI_M2S_COMP_WR_CFG_2_AWUSER_MASK;
114	reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_2_AWSIZE_MASK;
115	reg |= (m2s_sm->bus_size <<
116			UDMA_AXI_M2S_COMP_WR_CFG_2_AWSIZE_SHIFT) &
117		UDMA_AXI_M2S_COMP_WR_CFG_2_AWSIZE_MASK;
118	reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_2_AWQOS_MASK;
119	reg |= (m2s_sm->qos << UDMA_AXI_M2S_COMP_WR_CFG_2_AWQOS_SHIFT) &
120		UDMA_AXI_M2S_COMP_WR_CFG_2_AWQOS_MASK;
121	reg &= ~UDMA_AXI_M2S_COMP_WR_CFG_2_AWPROT_MASK;
122	reg |= (m2s_sm->prot << UDMA_AXI_M2S_COMP_WR_CFG_2_AWPROT_SHIFT) &
123		UDMA_AXI_M2S_COMP_WR_CFG_2_AWPROT_MASK;
124	al_reg_write32(cfg_2, reg);
125
126	reg = al_reg_read32(cfg_max_beats);
127	reg &= ~UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK;
128	reg |= m2s_sm->max_beats &
129			UDMA_AXI_M2S_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK;
130	al_reg_write32(cfg_max_beats, reg);
131
132	return 0;
133}
134
135/** Configure UDMA AXI M2S configuration */
136int al_udma_m2s_axi_set(struct al_udma *udma,
137					struct al_udma_m2s_axi_conf *axi_m2s)
138{
139	uint32_t reg;
140
141	al_udma_m2s_axi_sm_set(&axi_m2s->comp_write,
142			       &udma->udma_regs->m2s.axi_m2s.comp_wr_cfg_1,
143			       &udma->udma_regs->m2s.axi_m2s.comp_wr_cfg_2,
144			       &udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1);
145
146	al_udma_m2s_axi_sm_set(&axi_m2s->data_read,
147			       &udma->udma_regs->m2s.axi_m2s.data_rd_cfg_1,
148			       &udma->udma_regs->m2s.axi_m2s.data_rd_cfg_2,
149			       &udma->udma_regs->m2s.axi_m2s.data_rd_cfg);
150
151	al_udma_m2s_axi_sm_set(&axi_m2s->desc_read,
152			       &udma->udma_regs->m2s.axi_m2s.desc_rd_cfg_1,
153			       &udma->udma_regs->m2s.axi_m2s.desc_rd_cfg_2,
154			       &udma->udma_regs->m2s.axi_m2s.desc_rd_cfg_3);
155
156	reg = al_reg_read32(&udma->udma_regs->m2s.axi_m2s.data_rd_cfg);
157	if (axi_m2s->break_on_max_boundary == AL_TRUE)
158		reg |= UDMA_AXI_M2S_DATA_RD_CFG_ALWAYS_BREAK_ON_MAX_BOUDRY;
159	else
160		reg &= ~UDMA_AXI_M2S_DATA_RD_CFG_ALWAYS_BREAK_ON_MAX_BOUDRY;
161	al_reg_write32(&udma->udma_regs->m2s.axi_m2s.data_rd_cfg, reg);
162
163	reg = al_reg_read32(&udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1);
164	reg &= ~UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK;
165	reg |= (axi_m2s->min_axi_beats <<
166			UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS_SHIFT) &
167		UDMA_AXI_M2S_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK;
168	al_reg_write32(&udma->udma_regs->m2s.axi_m2s.desc_wr_cfg_1, reg);
169
170	reg = al_reg_read32(&udma->udma_regs->m2s.axi_m2s.ostand_cfg);
171	reg &= ~UDMA_AXI_M2S_OSTAND_CFG_MAX_DATA_RD_MASK;
172	reg |= axi_m2s->ostand_max_data_read &
173			UDMA_AXI_M2S_OSTAND_CFG_MAX_DATA_RD_MASK;
174	reg &= ~UDMA_AXI_M2S_OSTAND_CFG_MAX_DESC_RD_MASK;
175	reg |= (axi_m2s->ostand_max_desc_read <<
176			UDMA_AXI_M2S_OSTAND_CFG_MAX_DESC_RD_SHIFT) &
177		UDMA_AXI_M2S_OSTAND_CFG_MAX_DESC_RD_MASK;
178	reg &= ~UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_REQ_MASK;
179	reg |= (axi_m2s->ostand_max_comp_req <<
180			UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_REQ_SHIFT) &
181		UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_REQ_MASK;
182	reg &= ~UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_DATA_WR_MASK;
183	reg |= (axi_m2s->ostand_max_comp_write <<
184			UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_DATA_WR_SHIFT) &
185		UDMA_AXI_M2S_OSTAND_CFG_MAX_COMP_DATA_WR_MASK;
186	al_reg_write32(&udma->udma_regs->m2s.axi_m2s.ostand_cfg, reg);
187	return 0;
188}
189
190/** Configure AXI S2M submaster */
191static int al_udma_s2m_axi_sm_set(struct al_udma_axi_submaster *s2m_sm,
192				      uint32_t *cfg_1, uint32_t *cfg_2,
193				      uint32_t *cfg_max_beats)
194{
195	uint32_t reg;
196	reg = al_reg_read32(cfg_1);
197	reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_1_AWID_MASK;
198	reg |= s2m_sm->id & UDMA_AXI_S2M_COMP_WR_CFG_1_AWID_MASK;
199	reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_1_AWCACHE_MASK;
200	reg |= (s2m_sm->cache_type <<
201			UDMA_AXI_S2M_COMP_WR_CFG_1_AWCACHE_SHIFT) &
202		UDMA_AXI_S2M_COMP_WR_CFG_1_AWCACHE_MASK;
203	reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_1_AWBURST_MASK;
204	reg |= (s2m_sm->burst << UDMA_AXI_S2M_COMP_WR_CFG_1_AWBURST_SHIFT) &
205		UDMA_AXI_S2M_COMP_WR_CFG_1_AWBURST_MASK;
206	al_reg_write32(cfg_1, reg);
207
208	reg = al_reg_read32(cfg_2);
209	reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_2_AWUSER_MASK;
210	reg |= s2m_sm->used_ext & UDMA_AXI_S2M_COMP_WR_CFG_2_AWUSER_MASK;
211	reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_2_AWSIZE_MASK;
212	reg |= (s2m_sm->bus_size << UDMA_AXI_S2M_COMP_WR_CFG_2_AWSIZE_SHIFT) &
213		UDMA_AXI_S2M_COMP_WR_CFG_2_AWSIZE_MASK;
214	reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_2_AWQOS_MASK;
215	reg |= (s2m_sm->qos << UDMA_AXI_S2M_COMP_WR_CFG_2_AWQOS_SHIFT) &
216		UDMA_AXI_S2M_COMP_WR_CFG_2_AWQOS_MASK;
217	reg &= ~UDMA_AXI_S2M_COMP_WR_CFG_2_AWPROT_MASK;
218	reg |= (s2m_sm->prot << UDMA_AXI_S2M_COMP_WR_CFG_2_AWPROT_SHIFT) &
219		UDMA_AXI_S2M_COMP_WR_CFG_2_AWPROT_MASK;
220	al_reg_write32(cfg_2, reg);
221
222	reg = al_reg_read32(cfg_max_beats);
223	reg &= ~UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK;
224	reg |= s2m_sm->max_beats &
225			UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK;
226	al_reg_write32(cfg_max_beats, reg);
227
228	return 0;
229}
230
231/** Configure UDMA AXI S2M configuration */
232int al_udma_s2m_axi_set(struct al_udma *udma,
233				struct al_udma_s2m_axi_conf *axi_s2m)
234{
235
236	uint32_t reg;
237
238	al_udma_s2m_axi_sm_set(&axi_s2m->data_write,
239			       &udma->udma_regs->s2m.axi_s2m.data_wr_cfg_1,
240			       &udma->udma_regs->s2m.axi_s2m.data_wr_cfg_2,
241			       &udma->udma_regs->s2m.axi_s2m.data_wr_cfg);
242
243	al_udma_s2m_axi_sm_set(&axi_s2m->desc_read,
244			       &udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_4,
245			       &udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_5,
246			       &udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_3);
247
248	al_udma_s2m_axi_sm_set(&axi_s2m->comp_write,
249			       &udma->udma_regs->s2m.axi_s2m.comp_wr_cfg_1,
250			       &udma->udma_regs->s2m.axi_s2m.comp_wr_cfg_2,
251			       &udma->udma_regs->s2m.axi_s2m.desc_wr_cfg_1);
252
253	reg = al_reg_read32(&udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_3);
254	if (axi_s2m->break_on_max_boundary == AL_TRUE)
255		reg |= UDMA_AXI_S2M_DESC_RD_CFG_3_ALWAYS_BREAK_ON_MAX_BOUDRY;
256	else
257		reg &= ~UDMA_AXI_S2M_DESC_RD_CFG_3_ALWAYS_BREAK_ON_MAX_BOUDRY;
258	al_reg_write32(&udma->udma_regs->s2m.axi_s2m.desc_rd_cfg_3, reg);
259
260	reg = al_reg_read32(&udma->udma_regs->s2m.axi_s2m.desc_wr_cfg_1);
261	reg &= ~UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK;
262	reg |= (axi_s2m->min_axi_beats <<
263			UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_SHIFT) &
264		UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK;
265	al_reg_write32(&udma->udma_regs->s2m.axi_s2m.desc_wr_cfg_1, reg);
266
267	reg = al_reg_read32(&udma->udma_regs->s2m.axi_s2m.ostand_cfg_rd);
268	reg &= ~UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_DESC_RD_OSTAND_MASK;
269	reg |= axi_s2m->ostand_max_desc_read &
270			UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_DESC_RD_OSTAND_MASK;
271
272	reg &= ~UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_STREAM_ACK_MASK;
273	reg |= (axi_s2m->ack_fifo_depth <<
274			UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_STREAM_ACK_SHIFT) &
275		UDMA_AXI_S2M_OSTAND_CFG_RD_MAX_STREAM_ACK_MASK;
276
277	al_reg_write32(&udma->udma_regs->s2m.axi_s2m.ostand_cfg_rd, reg);
278
279	reg = al_reg_read32(&udma->udma_regs->s2m.axi_s2m.ostand_cfg_wr);
280	reg &= ~UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_WR_OSTAND_MASK;
281	reg |= axi_s2m->ostand_max_data_req &
282			UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_WR_OSTAND_MASK;
283	reg &= ~UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_BEATS_WR_OSTAND_MASK;
284	reg |= (axi_s2m->ostand_max_data_write <<
285		UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_BEATS_WR_OSTAND_SHIFT) &
286		UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_DATA_BEATS_WR_OSTAND_MASK;
287	reg &= ~UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_REQ_MASK;
288	reg |= (axi_s2m->ostand_max_comp_req <<
289			UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_REQ_SHIFT) &
290		UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_REQ_MASK;
291	reg &= ~UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_DATA_WR_OSTAND_MASK;
292	reg |= (axi_s2m->ostand_max_comp_write <<
293		UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_DATA_WR_OSTAND_SHIFT) &
294		UDMA_AXI_S2M_OSTAND_CFG_WR_MAX_COMP_DATA_WR_OSTAND_MASK;
295	al_reg_write32(&udma->udma_regs->s2m.axi_s2m.ostand_cfg_wr, reg);
296	return 0;
297}
298
299/** M2S packet len configuration */
300int al_udma_m2s_packet_size_cfg_set(struct al_udma *udma,
301				struct al_udma_m2s_pkt_len_conf *conf)
302{
303	uint32_t reg = al_reg_read32(&udma->udma_regs->m2s.m2s.cfg_len);
304	uint32_t max_supported_size = UDMA_M2S_CFG_LEN_MAX_PKT_SIZE_MASK;
305
306	al_assert(udma->type == UDMA_TX);
307
308	if (conf->encode_64k_as_zero == AL_TRUE)
309		max_supported_size += 1;	/* 64K */
310
311	if (conf->max_pkt_size > max_supported_size) {
312		al_err("udma [%s]: requested max_pkt_size (0x%x) exceeds the"
313			"supported limit (0x%x)\n", udma->name,
314			 conf->max_pkt_size, max_supported_size);
315		return -EINVAL;
316	}
317
318	reg &= ~UDMA_M2S_CFG_LEN_ENCODE_64K;
319	if (conf->encode_64k_as_zero == AL_TRUE)
320		reg |= UDMA_M2S_CFG_LEN_ENCODE_64K;
321	else
322		reg &= ~UDMA_M2S_CFG_LEN_ENCODE_64K;
323
324	reg &= ~UDMA_M2S_CFG_LEN_MAX_PKT_SIZE_MASK;
325	reg |= conf->max_pkt_size;
326
327	al_reg_write32(&udma->udma_regs->m2s.m2s.cfg_len, reg);
328	return 0;
329}
330
331/** Report Error - to be used for abort */
332void al_udma_err_report(struct al_udma *udma __attribute__((__unused__)))
333{
334	return;
335}
336
337/** Statistics - TBD */
338void al_udma_stats_get(struct al_udma *udma __attribute__((__unused__)))
339{
340	return;
341}
342
343/** Configure UDMA M2S descriptor prefetch */
344int al_udma_m2s_pref_set(struct al_udma *udma,
345				struct al_udma_m2s_desc_pref_conf *conf)
346{
347	uint32_t reg;
348
349	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_1);
350	reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_1_FIFO_DEPTH_MASK;
351	reg |= conf->desc_fifo_depth;
352	al_reg_write32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_1, reg);
353
354	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_2);
355
356	if (conf->sch_mode == SRR)
357		reg |= UDMA_M2S_RD_DESC_PREF_CFG_2_PREF_FORCE_RR;
358	else if (conf->sch_mode == STRICT)
359		reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_2_PREF_FORCE_RR;
360	else {
361		al_err("udma [%s]: requested descriptor preferch arbiter "
362			"mode (%d) is invalid\n", udma->name, conf->sch_mode);
363		return -EINVAL;
364	}
365	reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK;
366	reg |= conf->max_desc_per_packet &
367		UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK;
368	al_reg_write32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_2, reg);
369
370	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_3);
371	reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK;
372	reg |= conf->min_burst_below_thr &
373		UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK;
374
375	reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK;
376	reg |=(conf->min_burst_above_thr <<
377	       UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT) &
378		UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK;
379
380	reg &= ~UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK;
381	reg |= (conf->pref_thr <<
382			UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT) &
383		UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK;
384
385	al_reg_write32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_3, reg);
386
387	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.data_cfg);
388	reg &= ~UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_MASK;
389	reg |= conf->data_fifo_depth &
390			UDMA_M2S_RD_DATA_CFG_DATA_FIFO_DEPTH_MASK;
391
392	reg &= ~UDMA_M2S_RD_DATA_CFG_MAX_PKT_LIMIT_MASK;
393	reg |= (conf->max_pkt_limit
394			<< UDMA_M2S_RD_DATA_CFG_MAX_PKT_LIMIT_SHIFT) &
395		UDMA_M2S_RD_DATA_CFG_MAX_PKT_LIMIT_MASK;
396	al_reg_write32(&udma->udma_regs->m2s.m2s_rd.data_cfg, reg);
397
398	return 0;
399}
400
401/** Ger the M2S UDMA descriptor prefetch */
402int al_udma_m2s_pref_get(struct al_udma *udma,
403				struct al_udma_m2s_desc_pref_conf *conf)
404{
405	uint32_t reg;
406
407	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_1);
408	conf->desc_fifo_depth =
409	    AL_REG_FIELD_GET(reg, UDMA_M2S_RD_DESC_PREF_CFG_1_FIFO_DEPTH_MASK,
410			UDMA_M2S_RD_DESC_PREF_CFG_1_FIFO_DEPTH_SHIFT);
411
412	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_2);
413	if (reg & UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK)
414		conf->sch_mode = SRR;
415	else
416		conf->sch_mode = STRICT;
417	conf->max_desc_per_packet =
418	    AL_REG_FIELD_GET(reg,
419			UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK,
420			UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_SHIFT);
421
422	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_3);
423
424	conf->min_burst_below_thr =
425	    AL_REG_FIELD_GET(reg,
426			UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK,
427			UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_SHIFT);
428
429	conf->min_burst_above_thr =
430	    AL_REG_FIELD_GET(reg,
431			UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK,
432			UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT);
433
434	conf->pref_thr = AL_REG_FIELD_GET(reg,
435				UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK,
436				UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT);
437	return 0;
438}
439
440/* set max descriptors */
441int al_udma_m2s_max_descs_set(struct al_udma *udma, uint8_t max_descs)
442{
443	uint32_t pref_thr = max_descs;
444	uint32_t min_burst_above_thr = 4;
445	al_assert(max_descs <= AL_UDMA_M2S_MAX_ALLOWED_DESCS_PER_PACKET);
446	al_assert(max_descs > 0);
447
448	/* increase min_burst_above_thr so larger burst can be used to fetch
449	 * descriptors */
450	if (pref_thr >= 8)
451		min_burst_above_thr = 8;
452	else {
453	/* don't set prefetch threshold too low so we can have the
454	 * min_burst_above_thr >= 4 */
455		pref_thr = 4;
456	}
457
458	al_reg_write32_masked(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_2,
459			      UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_MASK,
460			      max_descs << UDMA_M2S_RD_DESC_PREF_CFG_2_MAX_DESC_PER_PKT_SHIFT);
461
462	al_reg_write32_masked(&udma->udma_regs->m2s.m2s_rd.desc_pref_cfg_3,
463			      UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_MASK |
464			      UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK,
465			      (pref_thr << UDMA_M2S_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT) |
466			      (min_burst_above_thr << UDMA_M2S_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT));
467
468	return 0;
469}
470
471/* set s2m max descriptors */
472int al_udma_s2m_max_descs_set(struct al_udma *udma, uint8_t max_descs)
473{
474	uint32_t pref_thr = max_descs;
475	uint32_t min_burst_above_thr = 4;
476	al_assert(max_descs <= AL_UDMA_S2M_MAX_ALLOWED_DESCS_PER_PACKET);
477	al_assert(max_descs > 0);
478
479	/* increase min_burst_above_thr so larger burst can be used to fetch
480	 * descriptors */
481	if (pref_thr >= 8)
482		min_burst_above_thr = 8;
483	else
484	/* don't set prefetch threshold too low so we can have the
485	 * min_burst_above_thr >= 4 */
486		pref_thr = 4;
487
488	al_reg_write32_masked(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_3,
489			      UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_MASK |
490			      UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK,
491			      (pref_thr << UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT) |
492			      (min_burst_above_thr << UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT));
493
494	return 0;
495}
496
497int al_udma_s2m_full_line_write_set(struct al_udma *udma, al_bool enable)
498{
499	uint32_t	val = 0;
500
501	if (enable == AL_TRUE) {
502		val = UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE;
503		al_info("udma [%s]: full line write enabled\n", udma->name);
504	}
505
506	al_reg_write32_masked(&udma->udma_regs->s2m.s2m_wr.data_cfg_2,
507			UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE,
508			val);
509	return 0;
510}
511
512/** Configure S2M UDMA descriptor prefetch */
513int al_udma_s2m_pref_set(struct al_udma *udma,
514				struct al_udma_s2m_desc_pref_conf *conf)
515{
516	uint32_t reg;
517
518	reg = al_reg_read32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_1);
519	reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_1_FIFO_DEPTH_MASK;
520	reg |= conf->desc_fifo_depth;
521	al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_1, reg);
522
523	reg = al_reg_read32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_2);
524
525	if (conf->sch_mode == SRR)
526		reg |= UDMA_S2M_RD_DESC_PREF_CFG_2_PREF_FORCE_RR;
527	else if (conf->sch_mode == STRICT)
528		reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_PREF_FORCE_RR;
529	else {
530		al_err("udma [%s]: requested descriptor preferch arbiter "
531			"mode (%d) is invalid\n", udma->name, conf->sch_mode);
532		return -EINVAL;
533	}
534	if (conf->q_promotion == AL_TRUE)
535		reg |= UDMA_S2M_RD_DESC_PREF_CFG_2_Q_PROMOTION;
536	else
537		reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_Q_PROMOTION;
538
539	if (conf->force_promotion == AL_TRUE)
540		reg |= UDMA_S2M_RD_DESC_PREF_CFG_2_FORCE_PROMOTION;
541	else
542		reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_FORCE_PROMOTION;
543
544	if (conf->en_pref_prediction == AL_TRUE)
545		reg |= UDMA_S2M_RD_DESC_PREF_CFG_2_EN_PREF_PREDICTION;
546	else
547		reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_EN_PREF_PREDICTION;
548
549	reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_2_PROMOTION_TH_MASK;
550	reg |= (conf->promotion_th
551			<< UDMA_S2M_RD_DESC_PREF_CFG_2_PROMOTION_TH_SHIFT) &
552		UDMA_S2M_RD_DESC_PREF_CFG_2_PROMOTION_TH_MASK;
553
554	al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_2, reg);
555
556	reg = al_reg_read32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_3);
557	reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_MASK;
558	reg |= (conf->pref_thr << UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_SHIFT) &
559		UDMA_S2M_RD_DESC_PREF_CFG_3_PREF_THR_MASK;
560
561	reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK;
562	reg |= conf->min_burst_below_thr &
563		UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_BELOW_THR_MASK;
564
565	reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK;
566	reg |=(conf->min_burst_above_thr <<
567	       UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_SHIFT) &
568		UDMA_S2M_RD_DESC_PREF_CFG_3_MIN_BURST_ABOVE_THR_MASK;
569
570	al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_3, reg);
571
572	reg = al_reg_read32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_4);
573	reg &= ~UDMA_S2M_RD_DESC_PREF_CFG_4_A_FULL_THR_MASK;
574	reg |= conf->a_full_thr & UDMA_S2M_RD_DESC_PREF_CFG_4_A_FULL_THR_MASK;
575	al_reg_write32(&udma->udma_regs->s2m.s2m_rd.desc_pref_cfg_4, reg);
576
577
578	return 0;
579}
580
581/* Configure S2M UDMA data write */
582int al_udma_s2m_data_write_set(struct al_udma *udma,
583				struct al_udma_s2m_data_write_conf *conf)
584{
585	uint32_t reg;
586
587	reg = al_reg_read32(&udma->udma_regs->s2m.s2m_wr.data_cfg_1);
588	reg &= ~UDMA_S2M_WR_DATA_CFG_1_DATA_FIFO_DEPTH_MASK;
589	reg |= conf->data_fifo_depth &
590			UDMA_S2M_WR_DATA_CFG_1_DATA_FIFO_DEPTH_MASK;
591	reg &= ~UDMA_S2M_WR_DATA_CFG_1_MAX_PKT_LIMIT_MASK;
592	reg |= (conf->max_pkt_limit <<
593				UDMA_S2M_WR_DATA_CFG_1_MAX_PKT_LIMIT_SHIFT) &
594			UDMA_S2M_WR_DATA_CFG_1_MAX_PKT_LIMIT_MASK;
595	reg &= ~UDMA_S2M_WR_DATA_CFG_1_FIFO_MARGIN_MASK;
596	reg |= (conf->fifo_margin <<
597				UDMA_S2M_WR_DATA_CFG_1_FIFO_MARGIN_SHIFT) &
598			UDMA_S2M_WR_DATA_CFG_1_FIFO_MARGIN_MASK;
599	al_reg_write32(&udma->udma_regs->s2m.s2m_wr.data_cfg_1, reg);
600
601	reg = al_reg_read32(&udma->udma_regs->s2m.s2m_wr.data_cfg_2);
602	reg &= ~UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_MASK;
603	reg |= conf->desc_wait_timer &
604			UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_MASK;
605	reg &= ~(UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC |
606		 UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC |
607		 UDMA_S2M_WR_DATA_CFG_2_WAIT_FOR_PREF |
608		 UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE |
609		 UDMA_S2M_WR_DATA_CFG_2_DIRECT_HDR_USE_BUF1);
610	reg |= conf->flags &
611		(UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC |
612		 UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC |
613		 UDMA_S2M_WR_DATA_CFG_2_WAIT_FOR_PREF |
614		 UDMA_S2M_WR_DATA_CFG_2_FULL_LINE_MODE |
615		 UDMA_S2M_WR_DATA_CFG_2_DIRECT_HDR_USE_BUF1);
616	al_reg_write32(&udma->udma_regs->s2m.s2m_wr.data_cfg_2, reg);
617
618	return 0;
619}
620
621/* Configure S2M UDMA completion */
622int al_udma_s2m_completion_set(struct al_udma *udma,
623				struct al_udma_s2m_completion_conf *conf)
624{
625	uint32_t reg = al_reg_read32(&udma->udma_regs->s2m.s2m_comp.cfg_1c);
626	reg &= ~UDMA_S2M_COMP_CFG_1C_DESC_SIZE_MASK;
627	reg |= conf->desc_size & UDMA_S2M_COMP_CFG_1C_DESC_SIZE_MASK;
628	if (conf->cnt_words == AL_TRUE)
629		reg |= UDMA_S2M_COMP_CFG_1C_CNT_WORDS;
630	else
631		reg &= ~UDMA_S2M_COMP_CFG_1C_CNT_WORDS;
632	if (conf->q_promotion == AL_TRUE)
633		reg |= UDMA_S2M_COMP_CFG_1C_Q_PROMOTION;
634	else
635		reg &= ~UDMA_S2M_COMP_CFG_1C_Q_PROMOTION;
636	if (conf->force_rr == AL_TRUE)
637		reg |= UDMA_S2M_COMP_CFG_1C_FORCE_RR;
638	else
639		reg &= ~UDMA_S2M_COMP_CFG_1C_FORCE_RR;
640	reg &= ~UDMA_S2M_COMP_CFG_1C_Q_FREE_MIN_MASK;
641	reg |= (conf->q_free_min << UDMA_S2M_COMP_CFG_1C_Q_FREE_MIN_SHIFT) &
642		UDMA_S2M_COMP_CFG_1C_Q_FREE_MIN_MASK;
643	al_reg_write32(&udma->udma_regs->s2m.s2m_comp.cfg_1c, reg);
644
645	reg = al_reg_read32(&udma->udma_regs->s2m.s2m_comp.cfg_2c);
646	reg &= ~UDMA_S2M_COMP_CFG_2C_COMP_FIFO_DEPTH_MASK;
647	reg |= conf->comp_fifo_depth
648				& UDMA_S2M_COMP_CFG_2C_COMP_FIFO_DEPTH_MASK;
649	reg &= ~UDMA_S2M_COMP_CFG_2C_UNACK_FIFO_DEPTH_MASK;
650	reg |= (conf->unack_fifo_depth
651			<< UDMA_S2M_COMP_CFG_2C_UNACK_FIFO_DEPTH_SHIFT) &
652			UDMA_S2M_COMP_CFG_2C_UNACK_FIFO_DEPTH_MASK;
653	al_reg_write32(&udma->udma_regs->s2m.s2m_comp.cfg_2c, reg);
654
655	al_reg_write32(&udma->udma_regs->s2m.s2m_comp.cfg_application_ack,
656		       conf->timeout);
657	return 0;
658}
659
660/** Configure the M2S UDMA scheduling mode */
661int al_udma_m2s_sc_set(struct al_udma *udma,
662					struct al_udma_m2s_dwrr_conf *sched)
663{
664	uint32_t reg = al_reg_read32(&udma->udma_regs->m2s.m2s_dwrr.cfg_sched);
665
666	if (sched->enable_dwrr == AL_TRUE)
667		reg |= UDMA_M2S_DWRR_CFG_SCHED_EN_DWRR;
668	else
669		reg &= ~UDMA_M2S_DWRR_CFG_SCHED_EN_DWRR;
670
671	if (sched->pkt_mode == AL_TRUE)
672		reg |= UDMA_M2S_DWRR_CFG_SCHED_PKT_MODE_EN;
673	else
674		reg &= ~UDMA_M2S_DWRR_CFG_SCHED_PKT_MODE_EN;
675
676	reg &= ~UDMA_M2S_DWRR_CFG_SCHED_WEIGHT_INC_MASK;
677	reg |= sched->weight << UDMA_M2S_DWRR_CFG_SCHED_WEIGHT_INC_SHIFT;
678	reg &= ~UDMA_M2S_DWRR_CFG_SCHED_INC_FACTOR_MASK;
679	reg |= sched->inc_factor << UDMA_M2S_DWRR_CFG_SCHED_INC_FACTOR_SHIFT;
680	al_reg_write32(&udma->udma_regs->m2s.m2s_dwrr.cfg_sched, reg);
681
682	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_dwrr.ctrl_deficit_cnt);
683	reg &= ~UDMA_M2S_DWRR_CTRL_DEFICIT_CNT_INIT_MASK;
684	reg |= sched->deficit_init_val;
685	al_reg_write32(&udma->udma_regs->m2s.m2s_dwrr.ctrl_deficit_cnt, reg);
686
687	return 0;
688}
689
690/** Configure the M2S UDMA rate limitation */
691int al_udma_m2s_rlimit_set(struct al_udma *udma,
692					struct al_udma_m2s_rlimit_mode *mode)
693{
694	uint32_t reg = al_reg_read32(
695				&udma->udma_regs->m2s.m2s_rate_limiter.gen_cfg);
696
697	if (mode->pkt_mode_en == AL_TRUE)
698		reg |= UDMA_M2S_RATE_LIMITER_GEN_CFG_PKT_MODE_EN;
699	else
700		reg &= ~UDMA_M2S_RATE_LIMITER_GEN_CFG_PKT_MODE_EN;
701	reg &= ~UDMA_M2S_RATE_LIMITER_GEN_CFG_SHORT_CYCLE_SIZE_MASK;
702	reg |= mode->short_cycle_sz &
703	    UDMA_M2S_RATE_LIMITER_GEN_CFG_SHORT_CYCLE_SIZE_MASK;
704	al_reg_write32(&udma->udma_regs->m2s.m2s_rate_limiter.gen_cfg, reg);
705
706	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_rate_limiter.ctrl_token);
707	reg &= ~UDMA_M2S_RATE_LIMITER_CTRL_TOKEN_RST_MASK;
708	reg |= mode->token_init_val &
709			UDMA_M2S_RATE_LIMITER_CTRL_TOKEN_RST_MASK;
710	al_reg_write32(&udma->udma_regs->m2s.m2s_rate_limiter.ctrl_token, reg);
711
712	return 0;
713}
714
715int al_udma_m2s_rlimit_reset(struct al_udma *udma)
716{
717	uint32_t reg = al_reg_read32(
718			&udma->udma_regs->m2s.m2s_rate_limiter.ctrl_cycle_cnt);
719	reg |= UDMA_M2S_RATE_LIMITER_CTRL_CYCLE_CNT_RST;
720	al_reg_write32(&udma->udma_regs->m2s.m2s_rate_limiter.ctrl_cycle_cnt,
721						reg);
722	return 0;
723}
724
725/** Configure the Stream/Q rate limitation */
726static int al_udma_common_rlimit_set(struct udma_rlimit_common *regs,
727					  struct al_udma_m2s_rlimit_cfg *conf)
728{
729	uint32_t reg = al_reg_read32(&regs->cfg_1s);
730	/* mask max burst size, and enable/pause control bits */
731	reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_MAX_BURST_SIZE_MASK;
732	reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_EN;
733	reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_PAUSE;
734	reg |= conf->max_burst_sz &
735		UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_MAX_BURST_SIZE_MASK;
736	al_reg_write32(&regs->cfg_1s, reg);
737
738	reg = al_reg_read32(&regs->cfg_cycle);
739	reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_CYCLE_LONG_CYCLE_SIZE_MASK;
740	reg |= conf->long_cycle_sz &
741		UDMA_M2S_STREAM_RATE_LIMITER_CFG_CYCLE_LONG_CYCLE_SIZE_MASK;
742	al_reg_write32(&regs->cfg_cycle, reg);
743
744	reg = al_reg_read32(&regs->cfg_token_size_1);
745	reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_1_LONG_CYCLE_MASK;
746	reg |= conf->long_cycle &
747		UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_1_LONG_CYCLE_MASK;
748	al_reg_write32(&regs->cfg_token_size_1, reg);
749
750	reg = al_reg_read32(&regs->cfg_token_size_2);
751	reg &= ~UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_2_SHORT_CYCLE_MASK;
752	reg |= conf->short_cycle &
753		UDMA_M2S_STREAM_RATE_LIMITER_CFG_TOKEN_SIZE_2_SHORT_CYCLE_MASK;
754	al_reg_write32(&regs->cfg_token_size_2, reg);
755
756	reg = al_reg_read32(&regs->mask);
757	reg &= ~0xf;		/* only bits 0-3 defined */
758	reg |= conf->mask & 0xf;
759	al_reg_write32(&regs->mask, reg);
760
761	return 0;
762}
763
764static int al_udma_common_rlimit_act(struct udma_rlimit_common *regs,
765					  enum al_udma_m2s_rlimit_action act)
766{
767	uint32_t reg;
768
769	switch (act) {
770	case AL_UDMA_STRM_RLIMIT_ENABLE:
771		reg = al_reg_read32(&regs->cfg_1s);
772		reg |= UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_EN;
773		al_reg_write32(&regs->cfg_1s, reg);
774		break;
775	case AL_UDMA_STRM_RLIMIT_PAUSE:
776		reg = al_reg_read32(&regs->cfg_1s);
777		reg |= UDMA_M2S_STREAM_RATE_LIMITER_CFG_1S_PAUSE;
778		al_reg_write32(&regs->cfg_1s, reg);
779		break;
780	case AL_UDMA_STRM_RLIMIT_RESET:
781		reg = al_reg_read32(&regs->sw_ctrl);
782		reg |= UDMA_M2S_STREAM_RATE_LIMITER_SW_CTRL_RST_TOKEN_CNT;
783		al_reg_write32(&regs->sw_ctrl, reg);
784		break;
785	default:
786		return -EINVAL;
787	}
788	return 0;
789}
790
791/** Configure the M2S Stream rate limitation */
792int al_udma_m2s_strm_rlimit_set(struct al_udma *udma,
793				struct al_udma_m2s_rlimit_cfg *conf)
794{
795	struct udma_rlimit_common *rlimit_regs =
796	    &udma->udma_regs->m2s.m2s_stream_rate_limiter.rlimit;
797
798	return al_udma_common_rlimit_set(rlimit_regs, conf);
799}
800
801int al_udma_m2s_strm_rlimit_act(struct al_udma *udma,
802				enum al_udma_m2s_rlimit_action act)
803{
804	struct udma_rlimit_common *rlimit_regs =
805	    &udma->udma_regs->m2s.m2s_stream_rate_limiter.rlimit;
806
807	if (al_udma_common_rlimit_act(rlimit_regs, act) == -EINVAL) {
808		al_err("udma [%s]: udma stream rate limit invalid action "
809			"(%d)\n", udma->name, act);
810		return -EINVAL;
811	}
812	return 0;
813}
814
815/** Configure the M2S UDMA Q rate limitation */
816int al_udma_m2s_q_rlimit_set(struct al_udma_q *udma_q,
817				struct al_udma_m2s_rlimit_cfg *conf)
818{
819	struct udma_rlimit_common *rlimit_regs = &udma_q->q_regs->m2s_q.rlimit;
820
821	return al_udma_common_rlimit_set(rlimit_regs, conf);
822}
823
824int al_udma_m2s_q_rlimit_act(struct al_udma_q *udma_q,
825				enum al_udma_m2s_rlimit_action act)
826{
827	struct udma_rlimit_common *rlimit_regs = &udma_q->q_regs->m2s_q.rlimit;
828
829	if (al_udma_common_rlimit_act(rlimit_regs, act) == -EINVAL) {
830		al_err("udma [%s %d]: udma stream rate limit invalid action "
831				"(%d)\n",
832				udma_q->udma->name, udma_q->qid, act);
833		return -EINVAL;
834	}
835	return 0;
836}
837
838/** Configure the M2S UDMA Q scheduling mode */
839int al_udma_m2s_q_sc_set(struct al_udma_q *udma_q,
840					struct al_udma_m2s_q_dwrr_conf *conf)
841{
842	uint32_t reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_cfg_1);
843
844	reg &= ~UDMA_M2S_Q_DWRR_CFG_1_MAX_DEFICIT_CNT_SIZE_MASK;
845	reg |= conf->max_deficit_cnt_sz &
846		UDMA_M2S_Q_DWRR_CFG_1_MAX_DEFICIT_CNT_SIZE_MASK;
847	if (conf->strict == AL_TRUE)
848		reg |= UDMA_M2S_Q_DWRR_CFG_1_STRICT;
849	else
850		reg &= ~UDMA_M2S_Q_DWRR_CFG_1_STRICT;
851	al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_cfg_1, reg);
852
853	reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_cfg_2);
854	reg &= ~UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK;
855	reg |= (conf->axi_qos << UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_SHIFT) &
856	    UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK;
857	reg &= ~UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK;
858	reg |= conf->q_qos & UDMA_M2S_Q_DWRR_CFG_2_Q_QOS_MASK;
859	al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_cfg_2, reg);
860
861	reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_cfg_3);
862	reg &= ~UDMA_M2S_Q_DWRR_CFG_3_WEIGHT_MASK;
863	reg |= conf->weight & UDMA_M2S_Q_DWRR_CFG_3_WEIGHT_MASK;
864	al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_cfg_3, reg);
865
866	return 0;
867}
868
869int al_udma_m2s_q_sc_pause(struct al_udma_q *udma_q, al_bool set)
870{
871	uint32_t reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_cfg_1);
872
873	if (set == AL_TRUE)
874		reg |= UDMA_M2S_Q_DWRR_CFG_1_PAUSE;
875	else
876		reg &= ~UDMA_M2S_Q_DWRR_CFG_1_PAUSE;
877	al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_cfg_1, reg);
878
879	return 0;
880}
881
882int al_udma_m2s_q_sc_reset(struct al_udma_q *udma_q)
883{
884	uint32_t reg = al_reg_read32(&udma_q->q_regs->m2s_q.dwrr_sw_ctrl);
885
886	reg |= UDMA_M2S_Q_DWRR_SW_CTRL_RST_CNT;
887	al_reg_write32(&udma_q->q_regs->m2s_q.dwrr_sw_ctrl, reg);
888
889	return 0;
890}
891
892/** M2S UDMA completion and application timeouts */
893int al_udma_m2s_comp_timeouts_set(struct al_udma *udma,
894				struct al_udma_m2s_comp_timeouts *conf)
895{
896	uint32_t reg = al_reg_read32(&udma->udma_regs->m2s.m2s_comp.cfg_1c);
897
898	if (conf->sch_mode == SRR)
899		reg |= UDMA_M2S_COMP_CFG_1C_FORCE_RR;
900	else if (conf->sch_mode == STRICT)
901		reg &= ~UDMA_M2S_COMP_CFG_1C_FORCE_RR;
902	else {
903		al_err("udma [%s]: requested completion descriptor preferch "
904				"arbiter mode (%d) is invalid\n",
905				udma->name, conf->sch_mode);
906		return -EINVAL;
907	}
908	if (conf->enable_q_promotion == AL_TRUE)
909		reg |= UDMA_M2S_COMP_CFG_1C_Q_PROMOTION;
910	else
911		reg &= ~UDMA_M2S_COMP_CFG_1C_Q_PROMOTION;
912	reg &= ~UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_MASK;
913	reg |=
914	    conf->comp_fifo_depth << UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_SHIFT;
915
916	reg &= ~UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_MASK;
917	reg |= conf->unack_fifo_depth
918				<< UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_SHIFT;
919	al_reg_write32(&udma->udma_regs->m2s.m2s_comp.cfg_1c, reg);
920
921	al_reg_write32(&udma->udma_regs->m2s.m2s_comp.cfg_coal
922							, conf->coal_timeout);
923
924	reg = al_reg_read32(&udma->udma_regs->m2s.m2s_comp.cfg_application_ack);
925	reg &= ~UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_MASK;
926	reg |= conf->app_timeout << UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_SHIFT;
927	al_reg_write32(&udma->udma_regs->m2s.m2s_comp.cfg_application_ack, reg);
928	return 0;
929}
930
931int al_udma_m2s_comp_timeouts_get(struct al_udma *udma,
932					struct al_udma_m2s_comp_timeouts *conf)
933{
934	uint32_t reg = al_reg_read32(&udma->udma_regs->m2s.m2s_comp.cfg_1c);
935
936	if (reg & UDMA_M2S_COMP_CFG_1C_FORCE_RR)
937		conf->sch_mode = SRR;
938	else
939		conf->sch_mode = STRICT;
940
941	if (reg & UDMA_M2S_COMP_CFG_1C_Q_PROMOTION)
942		conf->enable_q_promotion = AL_TRUE;
943	else
944		conf->enable_q_promotion = AL_FALSE;
945
946	conf->comp_fifo_depth =
947	    AL_REG_FIELD_GET(reg,
948			     UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_MASK,
949			     UDMA_M2S_COMP_CFG_1C_COMP_FIFO_DEPTH_SHIFT);
950	conf->unack_fifo_depth =
951	    AL_REG_FIELD_GET(reg,
952			     UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_MASK,
953			     UDMA_M2S_COMP_CFG_1C_UNACK_FIFO_DEPTH_SHIFT);
954
955	conf->coal_timeout = al_reg_read32(
956				&udma->udma_regs->m2s.m2s_comp.cfg_coal);
957
958	reg = al_reg_read32(
959			&udma->udma_regs->m2s.m2s_comp.cfg_application_ack);
960
961	conf->app_timeout =
962	    AL_REG_FIELD_GET(reg,
963			     UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_MASK,
964			     UDMA_M2S_COMP_CFG_APPLICATION_ACK_TOUT_SHIFT);
965
966	return 0;
967}
968
969/**
970 * S2M UDMA configure no descriptors behaviour
971 */
972int al_udma_s2m_no_desc_cfg_set(struct al_udma *udma, al_bool drop_packet, al_bool gen_interrupt, uint32_t wait_for_desc_timeout)
973{
974	uint32_t reg;
975
976	reg = al_reg_read32(&udma->udma_regs->s2m.s2m_wr.data_cfg_2);
977
978	if ((drop_packet == AL_TRUE) && (wait_for_desc_timeout == 0)) {
979		al_err("udam [%s]: setting timeout to 0 will cause the udma to wait forever instead of dropping the packet", udma->name);
980		return -EINVAL;
981	}
982
983	if (drop_packet == AL_TRUE)
984		reg |= UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC;
985	else
986		reg &= ~UDMA_S2M_WR_DATA_CFG_2_DROP_IF_NO_DESC;
987
988	if (gen_interrupt == AL_TRUE)
989		reg |= UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC;
990	else
991		reg &= ~UDMA_S2M_WR_DATA_CFG_2_HINT_IF_NO_DESC;
992
993	AL_REG_FIELD_SET(reg, UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_MASK, UDMA_S2M_WR_DATA_CFG_2_DESC_WAIT_TIMER_SHIFT, wait_for_desc_timeout);
994
995	al_reg_write32(&udma->udma_regs->s2m.s2m_wr.data_cfg_2, reg);
996
997	return 0;
998}
999
1000/* S2M UDMA configure a queue's completion update */
1001int al_udma_s2m_q_compl_updade_config(struct al_udma_q *udma_q, al_bool enable)
1002{
1003	uint32_t reg = al_reg_read32(&udma_q->q_regs->s2m_q.comp_cfg);
1004
1005	if (enable == AL_TRUE)
1006		reg |= UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE;
1007	else
1008		reg &= ~UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE;
1009
1010	al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg, reg);
1011
1012	return 0;
1013}
1014
1015/* S2M UDMA configure a queue's completion descriptors coalescing */
1016int al_udma_s2m_q_compl_coal_config(struct al_udma_q *udma_q, al_bool enable, uint32_t
1017		coal_timeout)
1018{
1019	uint32_t reg = al_reg_read32(&udma_q->q_regs->s2m_q.comp_cfg);
1020
1021	if (enable == AL_TRUE)
1022		reg &= ~UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL;
1023	else
1024		reg |= UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL;
1025
1026	al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg, reg);
1027
1028	al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg_2, coal_timeout);
1029	return 0;
1030}
1031
1032/* S2M UDMA configure completion descriptors write burst parameters */
1033int al_udma_s2m_compl_desc_burst_config(struct al_udma *udma, uint16_t
1034		burst_size)
1035{
1036	if ((burst_size != 64) && (burst_size != 128) && (burst_size != 256)) {
1037		al_err("%s: invalid burst_size value (%d)\n", __func__,
1038				burst_size);
1039		return -EINVAL;
1040	}
1041
1042	/* convert burst size from bytes to beats (16 byte) */
1043	burst_size = burst_size / 16;
1044	al_reg_write32_masked(&udma->udma_regs->s2m.axi_s2m.desc_wr_cfg_1,
1045			UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_MASK |
1046			UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_MASK,
1047			burst_size << UDMA_AXI_S2M_DESC_WR_CFG_1_MIN_AXI_BEATS_SHIFT |
1048			burst_size << UDMA_AXI_S2M_DESC_WR_CFG_1_MAX_AXI_BEATS_SHIFT);
1049	return 0;
1050}
1051
1052/* S2M UDMA configure a queue's completion descriptors header split */
1053int al_udma_s2m_q_compl_hdr_split_config(struct al_udma_q *udma_q, al_bool enable,
1054					 al_bool force_hdr_split, uint32_t hdr_len)
1055{
1056	uint32_t reg = al_reg_read32(&udma_q->q_regs->s2m_q.pkt_cfg);
1057
1058	reg &= ~UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK;
1059	reg &= ~UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT;
1060	reg &= ~UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT;
1061
1062	if (enable == AL_TRUE) {
1063		reg |= hdr_len & UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK;
1064		reg |= UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT;
1065
1066		if (force_hdr_split == AL_TRUE)
1067			reg |= UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT;
1068	}
1069
1070	al_reg_write32(&udma_q->q_regs->s2m_q.pkt_cfg, reg);
1071
1072	return 0;
1073}
1074
1075/* S2M UDMA per queue completion configuration */
1076int al_udma_s2m_q_comp_set(struct al_udma_q *udma_q,
1077					struct al_udma_s2m_q_comp_conf *conf)
1078{
1079	uint32_t reg = al_reg_read32(&udma_q->q_regs->s2m_q.comp_cfg);
1080	if (conf->en_comp_ring_update == AL_TRUE)
1081		reg |= UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE;
1082	else
1083		reg &= ~UDMA_S2M_Q_COMP_CFG_EN_COMP_RING_UPDATE;
1084
1085	if (conf->dis_comp_coal == AL_TRUE)
1086		reg |= UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL;
1087	else
1088		reg &= ~UDMA_S2M_Q_COMP_CFG_DIS_COMP_COAL;
1089
1090	al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg, reg);
1091
1092	al_reg_write32(&udma_q->q_regs->s2m_q.comp_cfg_2, conf->comp_timer);
1093
1094	reg = al_reg_read32(&udma_q->q_regs->s2m_q.pkt_cfg);
1095
1096	reg &= ~UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK;
1097	reg |= conf->hdr_split_size & UDMA_S2M_Q_PKT_CFG_HDR_SPLIT_SIZE_MASK;
1098	if (conf->force_hdr_split == AL_TRUE)
1099		reg |= UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT;
1100	else
1101		reg &= ~UDMA_S2M_Q_PKT_CFG_FORCE_HDR_SPLIT;
1102	if (conf->en_hdr_split == AL_TRUE)
1103		reg |= UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT;
1104	else
1105		reg &= ~UDMA_S2M_Q_PKT_CFG_EN_HDR_SPLIT;
1106
1107	al_reg_write32(&udma_q->q_regs->s2m_q.pkt_cfg, reg);
1108
1109	reg = al_reg_read32(&udma_q->q_regs->s2m_q.qos_cfg);
1110	reg &= ~UDMA_S2M_QOS_CFG_Q_QOS_MASK;
1111	reg |= conf->q_qos & UDMA_S2M_QOS_CFG_Q_QOS_MASK;
1112	al_reg_write32(&udma_q->q_regs->s2m_q.qos_cfg, reg);
1113
1114	return 0;
1115}
1116
1117/* UDMA Target-ID control configuration per queue */
1118void al_udma_gen_tgtid_conf_queue_set(
1119	struct unit_regs		*unit_regs,
1120	struct al_udma_gen_tgtid_conf	*conf,
1121	uint32_t qid)
1122{
1123	uint32_t *tx_tgtid_reg, *rx_tgtid_reg, *tx_tgtaddr_reg, *rx_tgtaddr_reg;
1124	unsigned int rev_id;
1125
1126	al_assert(qid < DMA_MAX_Q);
1127	rev_id = al_udma_get_revision(unit_regs);
1128
1129	/* Target-ID TX DESC EN */
1130	al_reg_write32_masked(&unit_regs->gen.tgtid.cfg_tgtid_0,
1131			(conf->tx_q_conf[qid].desc_en << qid) <<
1132			UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_DESC_EN_SHIFT,
1133			(conf->tx_q_conf[qid].desc_en << qid) <<
1134			UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_DESC_EN_SHIFT);
1135
1136	/* Target-ID TX QUEUE EN */
1137	al_reg_write32_masked(&unit_regs->gen.tgtid.cfg_tgtid_0,
1138			(conf->tx_q_conf[qid].queue_en << qid) <<
1139			UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_QUEUE_EN_SHIFT,
1140			(conf->tx_q_conf[qid].queue_en << qid) <<
1141			UDMA_GEN_TGTID_CFG_TGTID_0_TX_Q_TGTID_QUEUE_EN_SHIFT);
1142
1143	/* Target-ID RX DESC EN */
1144	al_reg_write32_masked(&unit_regs->gen.tgtid.cfg_tgtid_0,
1145			(conf->rx_q_conf[qid].desc_en << qid) <<
1146			UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_DESC_EN_SHIFT,
1147			(conf->rx_q_conf[qid].desc_en << qid) <<
1148			UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_DESC_EN_SHIFT);
1149
1150	/* Target-ID RX QUEUE EN */
1151	al_reg_write32_masked(&unit_regs->gen.tgtid.cfg_tgtid_0,
1152			(conf->rx_q_conf[qid].queue_en << qid) <<
1153			UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_QUEUE_EN_SHIFT,
1154			(conf->rx_q_conf[qid].queue_en << qid) <<
1155			UDMA_GEN_TGTID_CFG_TGTID_0_RX_Q_TGTID_QUEUE_EN_SHIFT);
1156
1157	switch (qid) {
1158	case 0:
1159	case 1:
1160		tx_tgtid_reg = &unit_regs->gen.tgtid.cfg_tgtid_1;
1161		rx_tgtid_reg = &unit_regs->gen.tgtid.cfg_tgtid_3;
1162		tx_tgtaddr_reg = &unit_regs->gen.tgtaddr.cfg_tgtaddr_0;
1163		rx_tgtaddr_reg = &unit_regs->gen.tgtaddr.cfg_tgtaddr_2;
1164		break;
1165	case 2:
1166	case 3:
1167		tx_tgtid_reg = &unit_regs->gen.tgtid.cfg_tgtid_2;
1168		rx_tgtid_reg = &unit_regs->gen.tgtid.cfg_tgtid_4;
1169		tx_tgtaddr_reg = &unit_regs->gen.tgtaddr.cfg_tgtaddr_1;
1170		rx_tgtaddr_reg = &unit_regs->gen.tgtaddr.cfg_tgtaddr_3;
1171		break;
1172	default:
1173		al_assert(AL_FALSE);
1174		return;
1175	}
1176
1177	al_reg_write32_masked(tx_tgtid_reg,
1178		UDMA_GEN_TGTID_CFG_TGTID_MASK(qid),
1179		conf->tx_q_conf[qid].tgtid << UDMA_GEN_TGTID_CFG_TGTID_SHIFT(qid));
1180
1181	al_reg_write32_masked(rx_tgtid_reg,
1182		UDMA_GEN_TGTID_CFG_TGTID_MASK(qid),
1183		conf->rx_q_conf[qid].tgtid << UDMA_GEN_TGTID_CFG_TGTID_SHIFT(qid));
1184
1185	if (rev_id >= AL_UDMA_REV_ID_REV2) {
1186		al_reg_write32_masked(tx_tgtaddr_reg,
1187			UDMA_GEN_TGTADDR_CFG_MASK(qid),
1188			conf->tx_q_conf[qid].tgtaddr << UDMA_GEN_TGTADDR_CFG_SHIFT(qid));
1189
1190		al_reg_write32_masked(rx_tgtaddr_reg,
1191			UDMA_GEN_TGTADDR_CFG_MASK(qid),
1192			conf->rx_q_conf[qid].tgtaddr << UDMA_GEN_TGTADDR_CFG_SHIFT(qid));
1193	}
1194}
1195
1196/* UDMA Target-ID control configuration */
1197void al_udma_gen_tgtid_conf_set(
1198	struct unit_regs		*unit_regs,
1199	struct al_udma_gen_tgtid_conf	*conf)
1200{
1201	int i;
1202
1203	for (i = 0; i < DMA_MAX_Q; i++)
1204		al_udma_gen_tgtid_conf_queue_set(unit_regs, conf, i);
1205}
1206
1207/* UDMA Target-ID MSIX control configuration */
1208void al_udma_gen_tgtid_msix_conf_set(
1209	struct unit_regs			*unit_regs,
1210	struct al_udma_gen_tgtid_msix_conf	*conf)
1211{
1212	al_reg_write32_masked(
1213		&unit_regs->gen.tgtid.cfg_tgtid_0,
1214		UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_ACCESS_EN |
1215		UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_SEL,
1216		(conf->access_en ? UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_ACCESS_EN : 0) |
1217		(conf->sel ? UDMA_GEN_TGTID_CFG_TGTID_0_MSIX_TGTID_SEL : 0));
1218}
1219