1 /*******************************************************************************
2  * Copyright 2019-2020 Microchip FPGA Embedded Systems Solutions.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * PoalrFire SoC Microprocessor Subsystem PDMA bare metal driver implementation.
7  */
8 
9 #include "mpfs_hal/mss_hal.h"
10 #include "mss_pdma.h"
11 
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 
16 /* MACRO to set the correct channel memory offset for the memory mapped
17  * configuration register.
18  */
19 #define MSS_PDMA_REG_OFFSET(x)  \
20                     (uint64_t)(PDMA_REG_BASE + (PDMA_CHL_REG_OFFSET * (x)))
21 
22 /* Default is maximum transaction size for both write_size and read_size. */
23 uint8_t g_channel_nextcfg_wsize[MSS_PDMA_lAST_CHANNEL] =
24                                                 { 0x0Fu, 0x0Fu, 0x0Fu, 0x0Fu };
25 uint8_t g_channel_nextcfg_rsize[MSS_PDMA_lAST_CHANNEL] =
26                                                 { 0x0Fu, 0x0Fu, 0x0Fu, 0x0Fu };
27 /*-------------------------------------------------------------------------*//**
28  * MSS_PDMA_init()
29  * See pse_pdma.h for description of this function.
30  */
31 void
MSS_PDMA_init(void)32 MSS_PDMA_init
33 (
34     void
35 )
36 {
37     ;
38 }
39 
40 /*-------------------------------------------------------------------------*//**
41  * MSS_PDMA_setup_transfer()
42  * See pse_pdma.h for description of this function.
43  */
44 mss_pdma_error_id_t
MSS_PDMA_setup_transfer(mss_pdma_channel_id_t channel_id,mss_pdma_channel_config_t * channel_config)45 MSS_PDMA_setup_transfer
46 (
47     mss_pdma_channel_id_t channel_id,
48     mss_pdma_channel_config_t *channel_config
49 )
50 {
51     if (channel_id > MSS_PDMA_CHANNEL_3)
52     {
53         return MSS_PDMA_ERROR_INVALID_CHANNEL_ID;
54     }
55 
56     /* Set the register structure pointer for the PDMA channel. */
57     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
58 
59     /* Basic House Keeping, return if errors exist. */
60     if (channel_config->src_addr == 0u)
61     {
62         return MSS_PDMA_ERROR_INVALID_SRC_ADDR;
63     }
64 
65     if (channel_config->dest_addr == 0u)
66     {
67         return MSS_PDMA_ERROR_INVALID_DEST_ADDR;
68     }
69 
70     /* If a run transaction is in progress, return error.
71      * Channel can only be claimed when run is low */
72     if (pdmareg->control_reg & MASK_PDMA_CONTROL_RUN)
73     {
74         return MSS_PDMA_ERROR_TRANSACTION_IN_PROGRESS;
75     }
76 
77     /* Set or clear the interrupts for the transfer. */
78     if (channel_config->enable_done_int)
79     {
80         pdmareg->control_reg |= ((uint32_t)MASK_PDMA_ENABLE_DONE_INT);
81     }
82     else
83     {
84         pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_DONE_INT);
85     }
86 
87     if (channel_config->enable_err_int)
88     {
89         pdmareg->control_reg |= ((uint32_t)MASK_PDMA_ENABLE_ERR_INT);
90     }
91     else
92     {
93         pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_ERR_INT);
94     }
95 
96     /* clear Next registers. */
97     pdmareg->control_reg |= (uint32_t)MASK_CLAIM_PDMA_CHANNEL;
98 
99     /* Setup the source and destination addresses.*/
100     pdmareg->next_destination = channel_config->dest_addr;
101     pdmareg->next_source      = channel_config->src_addr;
102 
103     /* Set the transfer size. */
104     pdmareg->next_bytes       = channel_config->num_bytes;
105 
106     /* Setup repeat and force order requirements. */
107     if (channel_config->repeat)
108     {
109         pdmareg->next_config |= MASK_REPEAT_TRANSCTION;
110     }
111     else
112     {
113         pdmareg->next_config &= ~((uint32_t)MASK_REPEAT_TRANSCTION);
114     }
115 
116     if (channel_config->force_order)
117     {
118         pdmareg->next_config |= ((uint32_t)MASK_FORCE_ORDERING);
119     }
120     else
121     {
122         pdmareg->next_config &= ~((uint32_t)MASK_FORCE_ORDERING);
123     }
124 
125     /* PDMA transaction size.. set to maximum. */
126     pdmareg->next_config |=
127             (g_channel_nextcfg_wsize[channel_id] << SHIFT_CH_CONFIG_WSIZE);
128     pdmareg->next_config |=
129             (g_channel_nextcfg_rsize[channel_id] << SHIFT_CH_CONFIG_RSIZE);
130 
131     return MSS_PDMA_OK;
132 }
133 
134 /***************************************************************************//**
135  * See pse_pdma.h for description of this function.
136  */
137 mss_pdma_error_id_t
MSS_PDMA_set_transction_size(mss_pdma_channel_id_t channel_id,uint8_t write_size,uint8_t read_size)138 MSS_PDMA_set_transction_size
139 (
140     mss_pdma_channel_id_t channel_id,
141     uint8_t write_size,
142     uint8_t read_size
143 )
144 {
145     uint8_t value;
146 
147     if (channel_id > MSS_PDMA_CHANNEL_3)
148     {
149         return MSS_PDMA_ERROR_INVALID_CHANNEL_ID;
150     }
151 
152     if (write_size > 0x0Fu)
153     {
154         return MSS_PDMA_ERROR_INVALID_NEXTCFG_WSIZE;
155     }
156 
157     if (read_size > 0x0Fu)
158     {
159         return MSS_PDMA_ERROR_INVALID_NEXTCFG_RSIZE;
160     }
161 
162     g_channel_nextcfg_wsize[channel_id] = write_size;
163     g_channel_nextcfg_rsize[channel_id] = read_size;
164 
165     return MSS_PDMA_OK;
166 }
167 
168 /***************************************************************************//**
169  * See pse_pdma.h for description of this function.
170  */
171 mss_pdma_error_id_t
MSS_PDMA_start_transfer(mss_pdma_channel_id_t channel_id)172 MSS_PDMA_start_transfer
173 (
174     mss_pdma_channel_id_t channel_id
175 )
176 {
177     if (channel_id > MSS_PDMA_CHANNEL_3)
178     {
179         return MSS_PDMA_ERROR_INVALID_CHANNEL_ID;
180     }
181 
182     /* Set the register structure pointer for the PDMA channel. */
183     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
184 
185     /* If a run transaction is in progress, return error.
186      * Channel can only be claimed when run is low */
187     pdmareg->control_reg |= ((uint32_t)MASK_PDMA_CONTROL_RUN);
188 
189     return MSS_PDMA_OK;
190 }
191 
192 /***************************************************************************//**
193  * See pse_pdma.h for description of this function.
194  */
195 uint32_t
MSS_PDMA_get_active_transfer_type(mss_pdma_channel_id_t channel_id)196 MSS_PDMA_get_active_transfer_type
197 (
198     mss_pdma_channel_id_t channel_id
199 )
200 {
201     if (channel_id > MSS_PDMA_CHANNEL_3)
202     {
203         return 0u;
204     }
205 
206     /* Set the register structure pointer for the PDMA channel. */
207     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
208 
209     return pdmareg->exec_config;
210 }
211 
212 /***************************************************************************//**
213  * See pse_pdma.h for description of this function.
214  */
215 uint64_t
MSS_PDMA_get_number_bytes_remaining(mss_pdma_channel_id_t channel_id)216 MSS_PDMA_get_number_bytes_remaining
217 (
218     mss_pdma_channel_id_t channel_id
219 )
220 {
221     if (channel_id > MSS_PDMA_CHANNEL_3)
222     {
223         return 0u;
224     }
225 
226     /* Set the register structure pointer for the PDMA channel. */
227     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
228 
229     return pdmareg->exec_bytes;
230 }
231 
232 /***************************************************************************//**
233  * See pse_pdma.h for description of this function.
234  */
235 uint64_t
MSS_PDMA_get_destination_current_addr(mss_pdma_channel_id_t channel_id)236 MSS_PDMA_get_destination_current_addr
237 (
238     mss_pdma_channel_id_t channel_id
239 )
240 {
241     if (channel_id > MSS_PDMA_CHANNEL_3)
242     {
243         return 0u;
244     }
245 
246     /* Set the register structure pointer for the PDMA channel. */
247     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
248 
249     return pdmareg->exec_destination;
250 }
251 
252 /***************************************************************************//**
253  * See pse_pdma.h for description of this function.
254  */
255 uint64_t
MSS_PDMA_get_source_current_addr(mss_pdma_channel_id_t channel_id)256 MSS_PDMA_get_source_current_addr
257 (
258     mss_pdma_channel_id_t channel_id
259 )
260 {
261     if (channel_id > MSS_PDMA_CHANNEL_3)
262     {
263         return 0u;
264     }
265 
266     /* Set the register structure pointer for the PDMA channel. */
267     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
268 
269     return pdmareg->exec_source;
270 }
271 
272 /***************************************************************************//**
273  * See pse_pdma.h for description of this function.
274  */
275 uint8_t
MSS_PDMA_get_transfer_complete_status(mss_pdma_channel_id_t channel_id)276 MSS_PDMA_get_transfer_complete_status
277 (
278     mss_pdma_channel_id_t channel_id
279 )
280 {
281     if (channel_id > MSS_PDMA_CHANNEL_3)
282     {
283         return 0u;
284     }
285 
286     /* Set the register structure pointer for the PDMA channel. */
287     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
288 
289     if (pdmareg->control_reg & MASK_PDMA_TRANSFER_DONE)
290     {
291         return 1u;
292     }
293     else
294     {
295         return 0u;
296     }
297 }
298 
299 /***************************************************************************//**
300  * See pse_pdma.h for description of this function.
301  */
302 uint8_t
MSS_PDMA_get_transfer_error_status(mss_pdma_channel_id_t channel_id)303 MSS_PDMA_get_transfer_error_status
304 (
305     mss_pdma_channel_id_t channel_id
306 )
307 {
308     if (channel_id > MSS_PDMA_CHANNEL_3)
309     {
310         return 0u;
311     }
312 
313     /* Set the register structure pointer for the PDMA channel. */
314     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
315 
316     if (pdmareg->control_reg & MASK_PDMA_TRANSFER_ERROR)
317     {
318         return 1u;
319     }
320     else
321     {
322         return 0u;
323     }
324 }
325 
326 /***************************************************************************//**
327  * See pse_pdma.h for description of this function.
328  */
329 uint8_t
MSS_PDMA_clear_transfer_complete_status(mss_pdma_channel_id_t channel_id)330 MSS_PDMA_clear_transfer_complete_status
331 (
332     mss_pdma_channel_id_t channel_id
333 )
334 {
335     uint8_t intStatus = 0u;
336 
337     if (channel_id > MSS_PDMA_CHANNEL_3)
338     {
339         return 0u;
340     }
341 
342     /* Set the register structure pointer for the PDMA channel. */
343     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
344 
345     if (pdmareg->control_reg & MASK_PDMA_TRANSFER_DONE)
346     {
347         intStatus = 1u;
348         pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_TRANSFER_DONE);
349     }
350 
351     return intStatus;
352 }
353 
354 /***************************************************************************//**
355  * See pse_pdma.h for description of this function.
356  */
357 uint8_t
MSS_PDMA_clear_transfer_error_status(mss_pdma_channel_id_t channel_id)358 MSS_PDMA_clear_transfer_error_status
359 (
360     mss_pdma_channel_id_t channel_id
361 )
362 {
363     uint8_t intStatus = 0u;
364 
365     if (channel_id > MSS_PDMA_CHANNEL_3)
366     {
367         return 0u;
368     }
369 
370     /* Set the register structure pointer for the PDMA channel. */
371     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET(channel_id);
372 
373     if (pdmareg->control_reg & MASK_PDMA_TRANSFER_ERROR)
374     {
375         intStatus = 1u;
376         pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_TRANSFER_ERROR);
377     }
378 
379     return intStatus;
380 }
381 
382 /***************************************************************************//**
383  * Each DMA channel has two interrupts, one for transfer complete
384  * and the other for the transfer error.
385  */
386 uint8_t
dma_ch0_DONE_IRQHandler(void)387 dma_ch0_DONE_IRQHandler
388 (
389     void
390 )
391 {
392     /* Clear the interrupt enable bit. */
393     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET
394                                                 (MSS_PDMA_CHANNEL_0);
395 
396     pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_DONE_INT);
397 
398     return 0u;
399 }
400 
401 uint8_t
dma_ch0_ERR_IRQHandler(void)402 dma_ch0_ERR_IRQHandler
403 (
404     void
405 )
406 {
407     /* Clear the interrupt enable bit. */
408     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET
409                                                 (MSS_PDMA_CHANNEL_0);
410 
411     pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_ERR_INT);
412 
413     return 0u;
414 }
415 
416 uint8_t
dma_ch1_DONE_IRQHandler(void)417 dma_ch1_DONE_IRQHandler
418 (
419     void
420 )
421 {
422     /* Clear the interrupt enable bit. */
423     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET
424                                                 (MSS_PDMA_CHANNEL_1);
425 
426     pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_DONE_INT);
427 
428     return 0u;
429 }
430 
431 uint8_t
dma_ch1_ERR_IRQHandler(void)432 dma_ch1_ERR_IRQHandler
433 (
434     void
435 )
436 {
437     /* Clear the interrupt enable bit. */
438     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET
439                                                 (MSS_PDMA_CHANNEL_1);
440 
441     pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_ERR_INT);
442 
443     return 0u;
444 }
445 
446 
447 uint8_t
dma_ch2_DONE_IRQHandler(void)448 dma_ch2_DONE_IRQHandler
449 (
450     void
451 )
452 {
453     /* Clear the interrupt enable bit. */
454     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET
455                                                 (MSS_PDMA_CHANNEL_2);
456 
457     pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_DONE_INT);
458 
459     return 0u;
460 }
461 
462 uint8_t
dma_ch2_ERR_IRQHandler(void)463 dma_ch2_ERR_IRQHandler
464 (
465     void
466 )
467 {
468     /* Clear the interrupt enable bit. */
469     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET
470                                                 (MSS_PDMA_CHANNEL_2);
471 
472     pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_ERR_INT);
473 
474     return 0u;
475 }
476 
477 uint8_t
dma_ch3_DONE_IRQHandler(void)478 dma_ch3_DONE_IRQHandler
479 (
480     void
481 )
482 {
483     /* Clear the interrupt enable bit. */
484     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET
485                                                 (MSS_PDMA_CHANNEL_3);
486 
487     pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_DONE_INT);
488 
489     return 0u;
490 }
491 
492 uint8_t
dma_ch3_ERR_IRQHandler(void)493 dma_ch3_ERR_IRQHandler
494 (
495     void
496 )
497 {
498     /* Clear the interrupt enable bit. */
499     volatile mss_pdma_t *pdmareg = (mss_pdma_t *)MSS_PDMA_REG_OFFSET
500                                                 (MSS_PDMA_CHANNEL_3);
501 
502     pdmareg->control_reg &= ~((uint32_t)MASK_PDMA_ENABLE_ERR_INT);
503 
504     return 0u;
505 }
506 
507 #ifdef __cplusplus
508 }
509 #endif