1 /*
2  * Copyright (c) 2023-2024 Intel Corporation
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "sedi_dma_ann_1p0.h"
8 #include "sedi_driver_pm.h"
9 
10 #include "sedi_soc_regs.h"
11 #include <sedi_driver_dma.h>
12 #include <sedi_driver_ipc.h>
13 #include "sedi_driver_core.h"
14 
15 #define DMA_RS0 0       /* root space for common memory */
16 #define DMA_RS1 1       /* root space for csme memory */
17 #define DMA_RS3 3       /* root space for IMR memory */
18 #define DT_IS_IN_DRAM (1 << 0)
19 #define SR_IS_IN_DRAM (1 << 1)
20 
21 #define DMA_WRITE_ENABLE(i) (BIT(i) | BIT(DMA_CHANNEL_NUM + i))
22 #define DMA_WRITE_DISABLE(i) BIT(DMA_CHANNEL_NUM + i)
23 #define GET_MSB(data64) ((uint32_t)(data64 >> 32))
24 #define GET_LSB(data64) ((uint32_t)(data64))
25 
26 /*driver version*/
27 static const sedi_driver_version_t driver_version = { SEDI_DMA_API_VERSION,
28 						      SEDI_DMA_DRIVER_VERSION };
29 
30 typedef enum {
31 	SEDI_CONFIG_DMA_TRANS_TYPE = SEDI_CONFIG_DMA_CONTROL_ID_MAX,
32 	SEDI_CONFIG_DMA_LL_HEADER
33 } dma_inner_control_code;
34 
35 /*!
36  * DMA Transfer Type, inner usage
37  */
38 typedef enum {
39 	DMA_TYPE_SINGLE,                /**< Single block mode. */
40 	DMA_TYPE_MULTI_CONT,            /**< Contiguous multiblock mode. */
41 	DMA_TYPE_MULTI_LL,              /**< Link list multiblock mode. */
42 	DMA_TYPE_MULTI_LL_CIRCULAR,     /**< Link list multiblock mode with
43 					  cyclic operation. */
44 	DMA_TYPE_MAX
45 } dma_transfer_type_t;
46 
47 /* driver capabilities */
48 static sedi_dma_capabilities_t driver_capabilities[SEDI_DMA_NUM] = { 0 };
49 
50 /* channel config*/
51 typedef struct {
52 	uint8_t config_applied;
53 	uint8_t tf_mode;
54 	uint8_t sr_mem_type;
55 	uint8_t dt_mem_type;
56 	uint8_t sr_msb;
57 	uint8_t dt_msb;
58 	uint8_t burst_length;
59 	uint8_t sr_width;
60 	uint8_t dt_width;
61 	uint8_t direction;
62 	uint8_t handshake_polarity;
63 	uint8_t peripheral_direction;
64 	uint16_t handshake_device_id;
65 	dma_linked_list_item_t *linked_list_header;
66 } channel_config_t;
67 
68 /* dma runtime context information */
69 typedef struct {
70 	channel_config_t channel_config[DMA_CHANNEL_NUM];
71 	sedi_dma_event_cb_t cb_event[DMA_CHANNEL_NUM];  /*event callback*/
72 	void *cb_param[DMA_CHANNEL_NUM];                /*event callback*/
73 	sedi_dma_status_t status[DMA_CHANNEL_NUM];      /*status flags*/
74 	uint32_t done_byte[DMA_CHANNEL_NUM];            /*the transferred byte*/
75 	dma_linked_list_item_t *next_llp[DMA_CHANNEL_NUM];
76 	uint32_t flags[DMA_CHANNEL_NUM];            /*control and state flags*/
77 	uint8_t vnn_status;
78 	uint8_t power_status;
79 	/*other private runtime data*/
80 } dma_context_t;
81 
82 /*resources data structure*/
83 typedef struct {
84 	dma_ann_1p0_regs_t *regs; /* register interface*/
85 	/*other private data can go here,  DMA related information etc. */
86 } dma_resources_t;
87 
88 static dma_context_t dma_context[SEDI_DMA_NUM] = { 0 };
89 
90 static const dma_resources_t resources[SEDI_DMA_NUM] = {
91 	{ .regs = (dma_ann_1p0_regs_t *)SEDI_IREG_BASE(DMA, 0) },
92 };
93 
sedi_dma_get_version(void)94 sedi_driver_version_t sedi_dma_get_version(void)
95 {
96 	return driver_version;
97 }
98 
sedi_dma_get_capabilities(IN sedi_dma_t dma_device,INOUT sedi_dma_capabilities_t * cap)99 int sedi_dma_get_capabilities(IN sedi_dma_t dma_device,
100 			      INOUT sedi_dma_capabilities_t *cap)
101 {
102 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
103 
104 	if (sedi_dev_is_self_owned(SEDI_DEVID_DMA0 + dma_device)) {
105 		driver_capabilities[dma_device].is_available = 1;
106 	} else {
107 		driver_capabilities[dma_device].is_available = 0;
108 	}
109 
110 	*cap = driver_capabilities[dma_device];
111 	return SEDI_DRIVER_OK;
112 }
113 
dma_vnn_req(sedi_dma_t dma_device,int channel_id)114 static inline void dma_vnn_req(sedi_dma_t dma_device, int channel_id)
115 {
116 	unsigned int key = sedi_core_irq_lock();
117 
118 	if (dma_context[dma_device].vnn_status == 0) {
119 		PM_VNN_DRIVER_REQ(VNN_ID_DMA0 + dma_device);
120 	}
121 	dma_context[dma_device].vnn_status |= BIT(channel_id);
122 	sedi_core_irq_unlock(key);
123 }
124 
dma_vnn_dereq(sedi_dma_t dma_device,int channel_id)125 static inline void dma_vnn_dereq(sedi_dma_t dma_device, int channel_id)
126 {
127 	unsigned int key = sedi_core_irq_lock();
128 
129 	if (dma_context[dma_device].vnn_status & (BIT(channel_id))) {
130 		dma_context[dma_device].vnn_status &= (~BIT(channel_id));
131 		if (dma_context[dma_device].vnn_status == 0) {
132 			PM_VNN_DRIVER_DEREQ(VNN_ID_DMA0 + dma_device);
133 		}
134 	}
135 	sedi_core_irq_unlock(key);
136 }
137 
dma_set_default_channel_config(OUT channel_config_t * config)138 static void dma_set_default_channel_config(OUT channel_config_t *config)
139 {
140 	config->tf_mode = DMA_TYPE_MAX;
141 	config->sr_mem_type = DMA_SRAM_MEM;
142 	config->dt_mem_type = DMA_SRAM_MEM;
143 	config->sr_msb = 0;
144 	config->dt_msb = 0;
145 	config->burst_length = DMA_BURST_TRANS_LENGTH_MAX;
146 	config->sr_width = DMA_TRANS_WIDTH_MAX;
147 	config->dt_width = DMA_TRANS_WIDTH_MAX;
148 	config->direction = DMA_DIRECTION_MAX;
149 	config->handshake_device_id = 0;
150 	config->linked_list_header = NULL;
151 	config->config_applied = 0;
152 }
153 
154 /*  mask  channel interrupt */
mask_channel_interrupt(IN sedi_dma_t dma_device,IN int channel_id)155 static void mask_channel_interrupt(IN sedi_dma_t dma_device, IN int channel_id)
156 {
157 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
158 
159 	regs->int_reg.mask_tfr_low = DMA_WRITE_DISABLE(channel_id);
160 	regs->int_reg.mask_block_low = DMA_WRITE_DISABLE(channel_id);
161 	regs->int_reg.mask_src_trans_low = DMA_WRITE_DISABLE(channel_id);
162 	regs->int_reg.mask_dst_trans_low = DMA_WRITE_DISABLE(channel_id);
163 	regs->int_reg.mask_err_low = DMA_WRITE_DISABLE(channel_id);
164 }
165 
166 /* clear channel interrupt */
clear_channel_interrupt(IN sedi_dma_t dma_device,IN int channel_id)167 static void clear_channel_interrupt(IN sedi_dma_t dma_device, IN int channel_id)
168 {
169 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
170 
171 	regs->int_reg.clear_tfr_low = BIT(channel_id);
172 	regs->int_reg.clear_block_low = BIT(channel_id);
173 	regs->int_reg.clear_src_trans_low = BIT(channel_id);
174 	regs->int_reg.clear_dst_trans_low = BIT(channel_id);
175 	regs->int_reg.clear_err_low = BIT(channel_id);
176 }
177 
178 /* enable channel interrupt */
unmask_channel_interrupt(IN sedi_dma_t dma_device,IN int channel_id)179 static void unmask_channel_interrupt(IN sedi_dma_t dma_device,
180 				     IN int channel_id)
181 {
182 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
183 
184 	regs->int_reg.mask_tfr_low = DMA_WRITE_ENABLE(channel_id);
185 	regs->int_reg.mask_err_low = DMA_WRITE_ENABLE(channel_id);
186 }
187 
sedi_dma_init(IN sedi_dma_t dma_device,IN int channel_id,IN sedi_dma_event_cb_t cb,INOUT void * param)188 int32_t sedi_dma_init(IN sedi_dma_t dma_device, IN int channel_id,
189 		      IN sedi_dma_event_cb_t cb, INOUT void *param)
190 {
191 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
192 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
193 
194 	/* init default config context */
195 	channel_config_t *config =
196 		&(dma_context[dma_device].channel_config[channel_id]);
197 	dma_set_default_channel_config(config);
198 	/*add callback*/
199 	dma_context[dma_device].cb_event[channel_id] = cb;
200 	dma_context[dma_device].cb_param[channel_id] = param;
201 
202 	mask_channel_interrupt(dma_device, channel_id);
203 	clear_channel_interrupt(dma_device, channel_id);
204 	dma_context[dma_device].status[channel_id].busy = 0;
205 	dma_context[dma_device].status[channel_id].bus_error = 0;
206 
207 	return SEDI_DRIVER_OK;
208 }
209 
sedi_dma_uninit(IN sedi_dma_t dma_device,IN int channel_id)210 int32_t sedi_dma_uninit(IN sedi_dma_t dma_device, IN int channel_id)
211 {
212 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
213 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
214 
215 	dma_context[dma_device].cb_event[channel_id] = NULL;
216 
217 	mask_channel_interrupt(dma_device, channel_id);
218 	dma_context[dma_device].status[channel_id].busy = 0;
219 	dma_context[dma_device].status[channel_id].bus_error = 0;
220 	return SEDI_DRIVER_OK;
221 }
222 
config_snoop(sedi_dma_t dma_device,int channel_id)223 static void config_snoop(sedi_dma_t dma_device, int channel_id)
224 {
225 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
226 	volatile dma_chan_reg_t *chan_regs = &(regs->chan_reg[channel_id]);
227 	volatile dma_misc_regs_t *misc_regs = &(regs->dev_misc_reg);
228 
229 	/* snoop */
230 	misc_regs->dma_regaccess_chid = channel_id;
231 
232 	SET_BITS(chan_regs->cfg_low, WR_SNP_LOC, WR_SNP_LEN, 0);
233 	SET_BITS(chan_regs->cfg_low, RD_SNP_LOC, RD_SNP_LEN, 0);
234 	SET_BITS(chan_regs->cfg_low, RD_LLP_SNP_LOC, RD_LLP_SNP_LEN, 1);
235 	SET_BITS(chan_regs->cfg_low, RD_STAT_SNP_LOC, RD_STAT_SNP_LEN, 1);
236 	SET_BITS(chan_regs->cfg_low, WR_STAT_SNP_LOC, WR_STAT_SNP_LEN, 1);
237 	SET_BITS(chan_regs->cfg_low, WR_CTLHI_SNP_LOC, WR_CTLHI_SNP_LEN, 1);
238 	SET_BITS(misc_regs->dma_ctl_ch[channel_id], RD_NON_SNOOP_LOC,
239 		 RD_NON_SNOOP_LEN, 1);
240 	SET_BITS(misc_regs->dma_ctl_ch[channel_id], WR_NON_SNOOP_LOC,
241 		 WR_NON_SNOOP_LEN, 1);
242 	SET_BITS(misc_regs->dma_ctl_ch[channel_id], NON_SNOOP_LOC,
243 		 NON_SNOOP_LEN, 1);
244 }
245 
sedi_dma_set_power(IN sedi_dma_t dma_device,IN int channel_id,IN sedi_power_state_t state)246 int32_t sedi_dma_set_power(IN sedi_dma_t dma_device, IN int channel_id,
247 			   IN sedi_power_state_t state)
248 {
249 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
250 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
251 
252 	sedi_devid_t devid = SEDI_DEVID_DMA0 + dma_device;
253 
254 	switch (state) {
255 	case SEDI_POWER_FULL:
256 		if (dma_context[dma_device].power_status == 0) {
257 			sedi_pm_set_device_power(devid, SEDI_POWER_FULL);
258 		}
259 		dma_context[dma_device].power_status |= BIT(channel_id);
260 		config_snoop(dma_device, channel_id);
261 		break;
262 	case SEDI_POWER_LOW:
263 	case SEDI_POWER_SUSPEND:
264 	case SEDI_POWER_FORCE_SUSPEND:
265 		sedi_dma_abort_transfer(dma_device, channel_id);
266 		if (dma_context[dma_device].power_status == 0) {
267 			break;
268 		}
269 		dma_context[dma_device].power_status &= (~BIT(channel_id));
270 		if (dma_context[dma_device].power_status == 0) {
271 			sedi_pm_set_device_power(devid, SEDI_POWER_SUSPEND);
272 		}
273 		break;
274 	case SEDI_POWER_OFF:
275 	default:
276 		return SEDI_DRIVER_ERROR_PARAMETER;
277 	}
278 	return SEDI_DRIVER_OK;
279 }
280 
sedi_dma_control_aux(IN sedi_dma_t dma_device,IN int channel_id,IN uint32_t control_id,IN uint32_t arg)281 static int32_t sedi_dma_control_aux(IN sedi_dma_t dma_device, IN int channel_id,
282 				    IN uint32_t control_id, IN uint32_t arg)
283 {
284 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
285 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
286 
287 	channel_config_t *config =
288 		&(dma_context[dma_device].channel_config[channel_id]);
289 
290 	switch (control_id) {
291 	case SEDI_CONFIG_DMA_TRANS_TYPE:
292 		DBG_CHECK(arg < DMA_TYPE_MAX, SEDI_DRIVER_ERROR_PARAMETER);
293 		config->tf_mode = arg;
294 		break;
295 	case SEDI_CONFIG_DMA_SR_MEM_TYPE:
296 		DBG_CHECK(arg < DMA_MEM_TYPE_MAX, SEDI_DRIVER_ERROR_PARAMETER);
297 		config->sr_mem_type = arg;
298 		break;
299 	case SEDI_CONFIG_DMA_DT_MEM_TYPE:
300 		DBG_CHECK(arg < DMA_MEM_TYPE_MAX, SEDI_DRIVER_ERROR_PARAMETER);
301 		config->dt_mem_type = arg;
302 		break;
303 	case SEDI_CONFIG_DMA_LL_SR_MSB:
304 		config->sr_msb = arg;
305 		break;
306 	case SEDI_CONFIG_DMA_LL_DT_MSB:
307 		config->dt_msb = arg;
308 		break;
309 	case SEDI_CONFIG_DMA_DIRECTION:
310 		DBG_CHECK(arg < DMA_DIRECTION_MAX, SEDI_DRIVER_ERROR_PARAMETER);
311 		config->direction = arg;
312 		break;
313 	case SEDI_CONFIG_DMA_BURST_LENGTH:
314 		DBG_CHECK(arg < DMA_BURST_TRANS_LENGTH_MAX,
315 			  SEDI_DRIVER_ERROR_PARAMETER);
316 		config->burst_length = arg;
317 		break;
318 	case SEDI_CONFIG_DMA_SR_TRANS_WIDTH:
319 		DBG_CHECK(arg < DMA_TRANS_WIDTH_MAX,
320 			  SEDI_DRIVER_ERROR_PARAMETER);
321 		config->sr_width = arg;
322 		break;
323 	case SEDI_CONFIG_DMA_DT_TRANS_WIDTH:
324 		DBG_CHECK(arg < DMA_TRANS_WIDTH_MAX,
325 			  SEDI_DRIVER_ERROR_PARAMETER);
326 		config->dt_width = arg;
327 		break;
328 	case SEDI_CONFIG_DMA_HS_DEVICE_ID:
329 		config->handshake_device_id = arg;
330 		break;
331 	case SEDI_CONFIG_DMA_HS_DEVICE_ID_PER_DIR:
332 		config->peripheral_direction = arg;
333 		break;
334 	case SEDI_CONFIG_DMA_HS_POLARITY:
335 		DBG_CHECK(arg < DMA_HS_PER_RTX_MAX,
336 			  SEDI_DRIVER_ERROR_PARAMETER);
337 		config->handshake_polarity = arg;
338 		break;
339 	case SEDI_CONFIG_DMA_LL_HEADER:
340 		DBG_CHECK((arg), SEDI_DRIVER_ERROR_PARAMETER);
341 		config->linked_list_header = (dma_linked_list_item_t *)arg;
342 		break;
343 	default:
344 		return SEDI_DRIVER_ERROR_PARAMETER;
345 	}
346 	config->config_applied = 0;
347 	return SEDI_DRIVER_OK;
348 }
349 
sedi_dma_control(IN sedi_dma_t dma_device,IN int channel_id,IN uint32_t control_id,IN uint32_t arg)350 int32_t sedi_dma_control(IN sedi_dma_t dma_device, IN int channel_id,
351 			 IN uint32_t control_id, IN uint32_t arg)
352 {
353 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
354 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
355 	DBG_CHECK(control_id < SEDI_CONFIG_DMA_CONTROL_ID_MAX,
356 		  SEDI_DRIVER_ERROR_PARAMETER);
357 
358 	return sedi_dma_control_aux(dma_device, channel_id, control_id, arg);
359 }
360 
sedi_dma_get_status(IN sedi_dma_t dma_device,IN int channel_id,OUT sedi_dma_status_t * status)361 int sedi_dma_get_status(IN sedi_dma_t dma_device, IN int channel_id,
362 			OUT sedi_dma_status_t *status)
363 {
364 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
365 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
366 
367 	*status = dma_context[dma_device].status[channel_id];
368 	return SEDI_DRIVER_OK;
369 }
370 
371 /*config misc and other registers, as an adding for ctrl register*/
dma_apply_other_regs(volatile dma_misc_regs_t * misc_regs,volatile dma_chan_reg_t * chan_regs,channel_config_t * config,int channel_id)372 static int32_t dma_apply_other_regs(volatile dma_misc_regs_t *misc_regs,
373 				    volatile dma_chan_reg_t *chan_regs,
374 				    channel_config_t *config, int channel_id)
375 {
376 	uint8_t sr_rs = DMA_RS0;
377 	uint8_t dt_rs = DMA_RS0;
378 	uint8_t dma_mem_trans_mode = 0;
379 
380 	/* peripheral related registers*/
381 	if (config->direction != DMA_MEMORY_TO_MEMORY) {
382 		/* config check */
383 		DBG_CHECK(config->peripheral_direction < DMA_HS_PER_RTX_MAX,
384 			  SEDI_DRIVER_ERROR_PARAMETER);
385 		DBG_CHECK(config->handshake_polarity < DMA_HS_POLARITY_MAX,
386 			  SEDI_DRIVER_ERROR_PARAMETER);
387 		/* hardware handshake only*/
388 		/* select peripheral rx/tx to link up with dma*/
389 		SET_BITS(misc_regs->dma_xbar_sel[channel_id], RX_TX_LOC,
390 			 RX_TX_LEN, config->peripheral_direction);
391 		/* select peripheral device to connect with dma req wire*/
392 		SET_BITS(misc_regs->dma_xbar_sel[channel_id], DEVID_LOC,
393 			 DEVID_LEN, config->handshake_device_id);
394 		/* set handshaking polarity */
395 		SET_BITS(chan_regs->cfg_low, DST_HS_POL_LOC, DST_HS_POL_LEN,
396 			 config->handshake_polarity);
397 		SET_BITS(chan_regs->cfg_low, SRC_HS_POL_LOC, SRC_HS_POL_LEN,
398 			 config->handshake_polarity);
399 		SET_BITS(chan_regs->cfg_low, HSHAKE_NP_WR_LOC, HSHAKE_NP_WR_LEN,
400 			 1U);
401 		/* fill channel id to DST/SRC_PER reg*/
402 		SET_BITS(chan_regs->cfg_high, SRC_PER_LOC, SRC_PER_LEN,
403 			 channel_id);
404 		SET_BITS(chan_regs->cfg_high, DST_PER_LOC, DST_PER_LEN,
405 			 channel_id);
406 	}
407 	/* memory type related registers config*/
408 	/* source is memory*/
409 	if ((config->direction == DMA_MEMORY_TO_PERIPHERAL) ||
410 	    (config->direction == DMA_MEMORY_TO_MEMORY)) {
411 		DBG_CHECK(config->sr_mem_type < DMA_MEM_TYPE_MAX,
412 			  SEDI_DRIVER_ERROR_PARAMETER);
413 		if (config->sr_mem_type == DMA_UMA_MEM) {
414 			sr_rs = DMA_RS3;
415 		}
416 		if (config->sr_mem_type != DMA_SRAM_MEM) {
417 			dma_mem_trans_mode |= SR_IS_IN_DRAM;
418 		}
419 	}
420 	/* destination is memory*/
421 	if ((config->direction == DMA_PERIPHERAL_TO_MEMORY) ||
422 	    (config->direction == DMA_MEMORY_TO_MEMORY)) {
423 		DBG_CHECK(config->dt_mem_type < DMA_MEM_TYPE_MAX,
424 			  SEDI_DRIVER_ERROR_PARAMETER);
425 		if (config->dt_mem_type == DMA_UMA_MEM) {
426 			dt_rs = DMA_RS3;
427 		}
428 		if (config->dt_mem_type != DMA_SRAM_MEM) {
429 			dma_mem_trans_mode |= DT_IS_IN_DRAM;
430 		}
431 	}
432 	/*set root space and memory type*/
433 	SET_BITS(misc_regs->dma_ctl_ch[channel_id], WR_RS_LOC, WR_RS_LEN,
434 		 dt_rs);
435 	SET_BITS(misc_regs->dma_ctl_ch[channel_id], RD_RS_LOC, RD_RS_LEN,
436 		 sr_rs);
437 	SET_BITS(misc_regs->dma_ctl_ch[channel_id], M2M_TYPE_LOC, M2M_TYPE_LEN,
438 		 dma_mem_trans_mode);
439 
440 	/* fill higher 32bit of 64bit addr */
441 	misc_regs->iosf_addr_fillin_dma_ch[channel_id] = config->sr_msb;
442 	misc_regs->iosf_dest_addr_fillin_dma_ch[channel_id] = config->dt_msb;
443 	return SEDI_DRIVER_OK;
444 }
445 
dma_channel_apply_config(IN sedi_dma_t dma_device,IN int channel_id)446 static int32_t dma_channel_apply_config(IN sedi_dma_t dma_device,
447 					IN int channel_id)
448 {
449 	int32_t ret;
450 	channel_config_t *config =
451 		&(dma_context[dma_device].channel_config[channel_id]);
452 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
453 	volatile dma_chan_reg_t *chan_regs = &(regs->chan_reg[channel_id]);
454 	volatile dma_misc_regs_t *misc_regs = &(regs->dev_misc_reg);
455 
456 	/*return if no need to config*/
457 	if (config->config_applied == 1) {
458 		return SEDI_DRIVER_OK;
459 	}
460 
461 	DBG_CHECK(config->tf_mode < DMA_TYPE_MAX, SEDI_DRIVER_ERROR_PARAMETER);
462 	DBG_CHECK(config->direction < DMA_DIRECTION_MAX,
463 		  SEDI_DRIVER_ERROR_PARAMETER);
464 	misc_regs->dma_regaccess_chid = channel_id;
465 	if (config->tf_mode == DMA_TYPE_SINGLE) {
466 		/* single block mode config, mainly config ctrl_low reg*/
467 		DBG_CHECK(config->burst_length < DMA_BURST_TRANS_LENGTH_MAX,
468 			  SEDI_DRIVER_ERROR_PARAMETER);
469 		DBG_CHECK(config->sr_width < DMA_TRANS_WIDTH_MAX,
470 			  SEDI_DRIVER_ERROR_PARAMETER);
471 		DBG_CHECK(config->dt_width < DMA_TRANS_WIDTH_MAX,
472 			  SEDI_DRIVER_ERROR_PARAMETER);
473 		DBG_CHECK(config->peripheral_direction < DMA_HS_PER_RTX_MAX,
474 			  SEDI_DRIVER_ERROR_PARAMETER);
475 		/*set dest and src burst size */
476 		SET_BITS(chan_regs->ctrl_low, DEST_MSIZE_LOC, SRC_MSIZE_LEN,
477 			 config->burst_length);
478 		SET_BITS(chan_regs->ctrl_low, SRC_MSIZE_LOC, SRC_MSIZE_LEN,
479 			 config->burst_length);
480 		/*source and destination transfer width */
481 		SET_BITS(chan_regs->ctrl_low, DST_TR_WIDTH_LOC,
482 			 DST_TR_WIDTH_LEN, config->dt_width);
483 		SET_BITS(chan_regs->ctrl_low, SRC_TR_WIDTH_LOC,
484 			 SRC_TR_WIDTH_LEN, config->sr_width);
485 
486 		/*transfer  direction */
487 		SET_BITS(chan_regs->ctrl_low, TT_FC_LOC, TT_FC_LEN,
488 			 config->direction);
489 
490 		/* Set increment*/
491 		switch (config->direction) {
492 		case DMA_PERIPHERAL_TO_MEMORY:
493 			SET_BITS(chan_regs->ctrl_low, SINC_LOC, SINC_LEN,
494 				 DMA_INCREMENT_NO_CHANGE);
495 			SET_BITS(chan_regs->ctrl_low, DINC_LOC, DINC_LEN,
496 				 DMA_INCREMENT_INC);
497 			break;
498 		case DMA_MEMORY_TO_MEMORY:
499 			SET_BITS(chan_regs->ctrl_low, SINC_LOC, SINC_LEN,
500 				 DMA_INCREMENT_INC);
501 			SET_BITS(chan_regs->ctrl_low, DINC_LOC, DINC_LEN,
502 				 DMA_INCREMENT_INC);
503 			break;
504 		case DMA_MEMORY_TO_PERIPHERAL:
505 			SET_BITS(chan_regs->ctrl_low, DINC_LOC, DINC_LEN,
506 				 DMA_INCREMENT_NO_CHANGE);
507 			SET_BITS(chan_regs->ctrl_low, SINC_LOC, SINC_LEN,
508 				 DMA_INCREMENT_INC);
509 			break;
510 		case DMA_PERIPHERAL_TO_PERIPHERAL:
511 			SET_BITS(chan_regs->ctrl_low, DINC_LOC, DINC_LEN,
512 				 DMA_INCREMENT_NO_CHANGE);
513 			SET_BITS(chan_regs->ctrl_low, SINC_LOC, SINC_LEN,
514 				 DMA_INCREMENT_NO_CHANGE);
515 			break;
516 		default:
517 			return SEDI_DRIVER_ERROR_PARAMETER;
518 		}
519 		chan_regs->llp_low = 0;
520 	} else if (config->tf_mode == DMA_TYPE_MULTI_LL) {
521 		DBG_CHECK(config->linked_list_header != NULL,
522 			  SEDI_DRIVER_ERROR_PARAMETER);
523 		chan_regs->llp_low = (uint32_t)config->linked_list_header;
524 	}
525 
526 	/*config misc and other registers, as an adding for ctrl register*/
527 	ret = dma_apply_other_regs(misc_regs, chan_regs, config, channel_id);
528 	if (ret != SEDI_DRIVER_OK) {
529 		return ret;
530 	}
531 
532 	if ((config->sr_mem_type != DMA_SRAM_MEM) ||
533 	    (config->dt_mem_type != DMA_SRAM_MEM)) {
534 		dma_vnn_req(dma_device, channel_id);
535 	}
536 
537 	config->config_applied = 1;
538 	return SEDI_DRIVER_OK;
539 }
540 
dma_fill_linkedlist(INOUT dma_linked_list_item_t * ll_p,IN uint32_t src_addr,IN uint32_t dst_addr,IN uint32_t block_size,uint32_t ctrl_low,IN dma_linked_list_item_t * ll_p_next)541 int dma_fill_linkedlist(INOUT dma_linked_list_item_t *ll_p,
542 			IN uint32_t src_addr, IN uint32_t dst_addr,
543 			IN uint32_t block_size, uint32_t ctrl_low,
544 			IN dma_linked_list_item_t *ll_p_next)
545 {
546 	DBG_CHECK(ll_p != NULL, SEDI_DRIVER_ERROR_PARAMETER);
547 	DBG_CHECK(src_addr != 0, SEDI_DRIVER_ERROR_PARAMETER);
548 	DBG_CHECK(dst_addr != 0, SEDI_DRIVER_ERROR_PARAMETER);
549 	DBG_CHECK(block_size <= DMA_MAX_BLOCK_SIZE,
550 		  SEDI_DRIVER_ERROR_PARAMETER);
551 
552 	ll_p->src_addr = src_addr;
553 	ll_p->dst_addr = dst_addr;
554 	ll_p->ctrl_low.raw = ctrl_low;
555 	SET_BITS(ll_p->ctrl_high.raw, BLOCK_TS_LOC, BLOCK_TS_LEN, block_size);
556 	ll_p->next_ll_p = ll_p_next;
557 	return SEDI_DRIVER_OK;
558 }
559 
dma_fill_sc_linkedlist(INOUT dma_linked_list_item_t * llp,IN uint8_t count,IN uint32_t ctrl_reg_low,IN sc_attr_t * attr)560 int dma_fill_sc_linkedlist(INOUT dma_linked_list_item_t *llp,
561 			   IN uint8_t count, IN uint32_t ctrl_reg_low,
562 			   IN sc_attr_t *attr)
563 {
564 	DBG_CHECK(llp != NULL, SEDI_DRIVER_ERROR_PARAMETER);
565 	DBG_CHECK(attr != NULL, SEDI_DRIVER_ERROR_PARAMETER);
566 	DBG_CHECK(count > 0, SEDI_DRIVER_ERROR_PARAMETER);
567 
568 	int ret;
569 	dma_linked_list_item_t *ll_tmp = (dma_linked_list_item_t *)llp;
570 	uint32_t src = attr->src_addr;
571 	uint32_t dst = attr->dst_addr;
572 
573 	for (int i = 0; i < count - 1; i++) {
574 		ret = dma_fill_linkedlist(ll_tmp + i, src, dst,
575 					   attr->block_size,
576 					   ctrl_reg_low, ll_tmp + i + 1);
577 		if (ret != SEDI_DRIVER_OK) {
578 			return ret;
579 		}
580 		if (attr->is_scatter) {
581 			if (attr->need_reload == 0) {
582 				src += attr->block_size;
583 			}
584 			dst += (attr->interval);
585 		} else {
586 			if (attr->need_reload == 0) {
587 				dst += attr->block_size;
588 			}
589 			src += (attr->interval);
590 		}
591 	}
592 	ret = dma_fill_linkedlist(ll_tmp + count - 1, src, dst,
593 				  attr->block_size, ctrl_reg_low, NULL);
594 	return ret;
595 }
596 
sedi_dma_start_transfer_aux(sedi_dma_t dma_device,int channel_id,uint32_t sr_addr,uint32_t dest_addr,uint32_t length)597 static int32_t sedi_dma_start_transfer_aux(sedi_dma_t dma_device,
598 					   int channel_id, uint32_t sr_addr,
599 					   uint32_t dest_addr, uint32_t length)
600 {
601 	int32_t ret;
602 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
603 	volatile dma_chan_reg_t *chan_regs = &(regs->chan_reg[channel_id]);
604 	channel_config_t *config =
605 		&(dma_context[dma_device].channel_config[channel_id]);
606 
607 	if (regs->misc_reg.chan_en_low & BIT(channel_id)) {
608 		return SEDI_DRIVER_ERROR_BUSY;
609 	}
610 	/* channel config*/
611 	ret = dma_channel_apply_config(dma_device, channel_id);
612 	if (ret != SEDI_DRIVER_OK) {
613 		dma_context[dma_device].status[channel_id].busy = 0;
614 		return ret;
615 	}
616 	if (config->tf_mode == DMA_TYPE_SINGLE) {
617 		chan_regs->sar_low = sr_addr;
618 		chan_regs->dar_low = dest_addr;
619 		SET_BITS(chan_regs->ctrl_high, BLOCK_TS_LOC, BLOCK_TS_LEN,
620 			 length);
621 		SET_BITS(chan_regs->ctrl_low, INT_EN_LOC, INT_EN_LEN, 1);
622 	} else if (config->tf_mode == DMA_TYPE_MULTI_LL) {
623 		SET_BITS(chan_regs->ctrl_low, LLP_DST_EN_LOC, LLP_DST_EN_LEN,
624 			 1);
625 		SET_BITS(chan_regs->ctrl_low, LLP_SRC_EN_LOC, LLP_SRC_EN_LEN,
626 			 1);
627 	}
628 
629 	dma_set_default_channel_config(config);
630 	/* enable interrupt */
631 	unmask_channel_interrupt(dma_device, channel_id);
632 
633 	/* enable channel*/
634 	regs->misc_reg.cfg_low = 1;
635 	SET_BITS(chan_regs->cfg_low, CH_DRAIN_LOC, CH_DRAIN_LEN, 0);
636 	SET_BITS(chan_regs->cfg_low, CH_SUSP_LOC, CH_SUSP_LEN, 0);
637 	regs->misc_reg.chan_en_low = DMA_WRITE_ENABLE(channel_id);
638 	return SEDI_DRIVER_OK;
639 }
640 
sedi_dma_start_transfer(IN sedi_dma_t dma_device,IN int channel_id,IN uint64_t sr_addr,IN uint64_t dest_addr,IN uint32_t length)641 int32_t sedi_dma_start_transfer(IN sedi_dma_t dma_device, IN int channel_id,
642 				IN uint64_t sr_addr, IN uint64_t dest_addr,
643 				IN uint32_t length)
644 {
645 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
646 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
647 	DBG_CHECK(sr_addr > 0, SEDI_DRIVER_ERROR_PARAMETER);
648 	DBG_CHECK(dest_addr > 0, SEDI_DRIVER_ERROR_PARAMETER);
649 	DBG_CHECK((length <= DMA_MAX_BLOCK_SIZE) && (length > 0),
650 		  SEDI_DRIVER_ERROR_PARAMETER);
651 
652 	if (dma_context[dma_device].status[channel_id].busy == 1) {
653 		return SEDI_DRIVER_ERROR_BUSY;
654 	}
655 	dma_context[dma_device].status[channel_id].busy = 1;
656 	dma_context[dma_device].status[channel_id].bus_error = 0;
657 
658 	sedi_dma_control_aux(dma_device, channel_id, SEDI_CONFIG_DMA_TRANS_TYPE,
659 			     DMA_TYPE_SINGLE);
660 	/* pass higher 32 bit of address*/
661 	sedi_dma_control_aux(dma_device, channel_id, SEDI_CONFIG_DMA_LL_SR_MSB,
662 			     GET_MSB(sr_addr));
663 	sedi_dma_control_aux(dma_device, channel_id, SEDI_CONFIG_DMA_LL_DT_MSB,
664 			     GET_MSB(dest_addr));
665 
666 	return sedi_dma_start_transfer_aux(dma_device, channel_id,
667 					   GET_LSB(sr_addr), GET_LSB(dest_addr),
668 					   length);
669 }
670 
sedi_dma_start_ll_transfer(IN sedi_dma_t dma_device,IN int channel_id,IN dma_linked_list_item_t * linkedlist_header)671 int32_t sedi_dma_start_ll_transfer(IN sedi_dma_t dma_device, IN int channel_id,
672 				   IN dma_linked_list_item_t *linkedlist_header)
673 {
674 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
675 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
676 	DBG_CHECK(linkedlist_header != NULL, SEDI_DRIVER_ERROR_PARAMETER);
677 	int32_t ret;
678 
679 	if (dma_context[dma_device].status[channel_id].busy == 1) {
680 		return SEDI_DRIVER_ERROR_BUSY;
681 	}
682 	dma_context[dma_device].status[channel_id].busy = 1;
683 	dma_context[dma_device].status[channel_id].bus_error = 0;
684 	/* channel config*/
685 	sedi_dma_control_aux(dma_device, channel_id, SEDI_CONFIG_DMA_TRANS_TYPE,
686 			     DMA_TYPE_MULTI_LL);
687 	sedi_dma_control_aux(dma_device, channel_id, SEDI_CONFIG_DMA_LL_HEADER,
688 			     (uint32_t)linkedlist_header);
689 
690 	ret = sedi_dma_start_transfer_aux(dma_device, channel_id, 0, 0, 0);
691 
692 	return ret;
693 }
694 
dma_transfer_post(sedi_dma_t dma_device,int channel_id)695 static void dma_transfer_post(sedi_dma_t dma_device, int channel_id)
696 {
697 	channel_config_t *config =
698 		&(dma_context[dma_device].channel_config[channel_id]);
699 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
700 	volatile dma_chan_reg_t *chan_regs = &(regs->chan_reg[channel_id]);
701 
702 	/* get status*/
703 	dma_context[dma_device].done_byte[channel_id] =
704 		GET_BITS(chan_regs->ctrl_high, BLOCK_TS_LOC, BLOCK_TS_LEN);
705 	dma_context[dma_device].next_llp[channel_id] =
706 		(dma_linked_list_item_t *)chan_regs->llp_low;
707 
708 	/* disable dma channel*/
709 	regs->misc_reg.chan_en_low = DMA_WRITE_DISABLE(channel_id);
710 	while (regs->misc_reg.chan_en_low & BIT(channel_id)) {
711 	}
712 
713 	/* mask and clear interrupt*/
714 	clear_channel_interrupt(dma_device, channel_id);
715 	mask_channel_interrupt(dma_device, channel_id);
716 
717 	dma_vnn_dereq(dma_device, channel_id);
718 	dma_set_default_channel_config(config);
719 	dma_context[dma_device].status[channel_id].busy = 0;
720 }
721 
722 /* Polling mode is only used in single-block mode */
sedi_dma_start_transfer_polling(IN sedi_dma_t dma_device,IN int channel_id,IN uint64_t sr_addr,IN uint64_t dest_addr,IN uint32_t length)723 int32_t sedi_dma_start_transfer_polling(IN sedi_dma_t dma_device,
724 					IN int channel_id, IN uint64_t sr_addr,
725 					IN uint64_t dest_addr,
726 					IN uint32_t length)
727 {
728 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
729 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
730 	DBG_CHECK(length <= DMA_MAX_BLOCK_SIZE, SEDI_DRIVER_ERROR_PARAMETER);
731 
732 	uint32_t ret;
733 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
734 	volatile dma_chan_reg_t *chan_regs = &(regs->chan_reg[channel_id]);
735 	sedi_dma_event_cb_t cb = dma_context[dma_device].cb_event[channel_id];
736 	void *usr_param = dma_context[dma_device].cb_param[channel_id];
737 
738 	if (dma_context[dma_device].status[channel_id].busy == 1) {
739 		return SEDI_DRIVER_ERROR_BUSY;
740 	}
741 	dma_context[dma_device].status[channel_id].busy = 1;
742 	dma_context[dma_device].status[channel_id].bus_error = 0;
743 
744 	sedi_dma_control_aux(dma_device, channel_id, SEDI_CONFIG_DMA_TRANS_TYPE,
745 			     DMA_TYPE_SINGLE);
746 
747 	/* pass higher 32 bit of address*/
748 	sedi_dma_control_aux(dma_device, channel_id, SEDI_CONFIG_DMA_LL_SR_MSB,
749 			     GET_MSB(sr_addr));
750 	sedi_dma_control_aux(dma_device, channel_id, SEDI_CONFIG_DMA_LL_DT_MSB,
751 			     GET_MSB(dest_addr));
752 
753 	ret = dma_channel_apply_config(dma_device, channel_id);
754 	if (ret != SEDI_DRIVER_OK) {
755 		dma_context[dma_device].status[channel_id].busy = 0;
756 		return ret;
757 	}
758 
759 	chan_regs->sar_low = GET_LSB(sr_addr);
760 	chan_regs->dar_low = GET_LSB(dest_addr);
761 	SET_BITS(chan_regs->ctrl_high, BLOCK_TS_LOC, BLOCK_TS_LEN, length);
762 
763 	/* disable and clear interrupt */
764 	mask_channel_interrupt(dma_device, channel_id);
765 	clear_channel_interrupt(dma_device, channel_id);
766 
767 	/* enable channel*/
768 	regs->misc_reg.cfg_low = 1;
769 	regs->misc_reg.chan_en_low = DMA_WRITE_ENABLE(channel_id);
770 
771 	while (1) {
772 		if (regs->misc_reg.chan_en_low & BIT(channel_id)) {
773 			continue;
774 		}
775 		if (regs->int_reg.raw_err_low & BIT(channel_id)) {
776 			dma_transfer_post(dma_device, channel_id);
777 			dma_context[dma_device].status[channel_id].bus_error =
778 				1;
779 			if (cb != NULL) {
780 				cb(dma_device, channel_id,
781 				   SEDI_DMA_EVENT_BUS_ERROR, usr_param);
782 			}
783 			return SEDI_DRIVER_ERROR_TRANSFER;
784 		} else {
785 			dma_transfer_post(dma_device, channel_id);
786 			if (cb != NULL) {
787 				cb(dma_device, channel_id,
788 				   SEDI_DMA_EVENT_TRANSFER_DONE, usr_param);
789 			}
790 			return SEDI_DRIVER_OK;
791 		}
792 	}
793 	return SEDI_DRIVER_OK;
794 }
795 
sedi_dma_abort_transfer(IN sedi_dma_t dma_device,IN int channel_id)796 int32_t sedi_dma_abort_transfer(IN sedi_dma_t dma_device, IN int channel_id)
797 {
798 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
799 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
800 
801 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
802 	volatile dma_chan_reg_t *chan_regs = &(regs->chan_reg[channel_id]);
803 
804 	if (dma_context[dma_device].status[channel_id].busy == 0) {
805 		return SEDI_DRIVER_OK;
806 	}
807 
808 	SET_BITS(chan_regs->cfg_low, CH_SUSP_LOC, CH_SUSP_LEN, 1);
809 	SET_BITS(chan_regs->cfg_low, CH_DRAIN_LOC, CH_DRAIN_LEN, 1);
810 
811 	while ((chan_regs->cfg_low & BIT(FIFO_EMPTY_LOC)) == 0) {
812 	}
813 
814 	dma_transfer_post(dma_device, channel_id);
815 	return SEDI_DRIVER_OK;
816 }
817 
sedi_dma_get_done_status(IN sedi_dma_t dma_device,IN int channel_id,OUT uint32_t * done_bytes,OUT dma_linked_list_item_t ** next_llp)818 int32_t sedi_dma_get_done_status(IN sedi_dma_t dma_device, IN int channel_id,
819 				 OUT uint32_t *done_bytes,
820 				 OUT dma_linked_list_item_t **next_llp)
821 {
822 	DBG_CHECK(dma_device < SEDI_DMA_NUM, SEDI_DRIVER_ERROR_PARAMETER);
823 	DBG_CHECK(channel_id < DMA_CHANNEL_NUM, SEDI_DRIVER_ERROR_PARAMETER);
824 
825 	if (dma_context[dma_device].status[channel_id].busy == 1) {
826 		return SEDI_DRIVER_ERROR_BUSY;
827 	}
828 
829 	if (done_bytes) {
830 		*done_bytes = dma_context[dma_device].done_byte[channel_id];
831 	}
832 	if (next_llp) {
833 		*next_llp = dma_context[dma_device].next_llp[channel_id];
834 	}
835 	return SEDI_DRIVER_OK;
836 }
837 
dma_isr(IN sedi_dma_t dma_device)838 void dma_isr(IN sedi_dma_t dma_device)
839 {
840 	volatile dma_ann_1p0_regs_t *regs = resources[dma_device].regs;
841 	sedi_dma_event_cb_t cb;
842 	void *usr_param;
843 	uint32_t tfr_status = regs->int_reg.status_tfr_low;
844 	uint32_t err_status = regs->int_reg.status_err_low;
845 
846 	for (int channel_id = 0; channel_id < DMA_CHANNEL_NUM; channel_id++) {
847 		cb = dma_context[dma_device].cb_event[channel_id];
848 		usr_param = dma_context[dma_device].cb_param[channel_id];
849 		if (tfr_status & BIT(channel_id)) {
850 			dma_transfer_post(dma_device, channel_id);
851 			if (cb != NULL) {
852 				cb(dma_device, channel_id,
853 				   SEDI_DMA_EVENT_TRANSFER_DONE, usr_param);
854 			}
855 		}
856 		if (err_status & BIT(channel_id)) {
857 			dma_transfer_post(dma_device, channel_id);
858 			dma_context[dma_device].status[channel_id].bus_error =
859 				1;
860 			if (cb != NULL) {
861 				cb(dma_device, channel_id,
862 				   SEDI_DMA_EVENT_BUS_ERROR, usr_param);
863 			}
864 		}
865 	}
866 }
867