1 /******************************************************************************
2 *                                                                             *
3 * License Agreement                                                           *
4 *                                                                             *
5 * Copyright (c) 2014 Altera Corporation, San Jose, California, USA.           *
6 * All rights reserved.                                                        *
7 *                                                                             *
8 * Permission is hereby granted, free of charge, to any person obtaining a     *
9 * copy of this software and associated documentation files (the "Software"),  *
10 * to deal in the Software without restriction, including without limitation   *
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,    *
12 * and/or sell copies of the Software, and to permit persons to whom the       *
13 * Software is furnished to do so, subject to the following conditions:        *
14 *                                                                             *
15 * The above copyright notice and this permission notice shall be included in  *
16 * all copies or substantial portions of the Software.                         *
17 *                                                                             *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  *
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,    *
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER      *
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING     *
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER         *
24 * DEALINGS IN THE SOFTWARE.                                                   *
25 *                                                                             *
26 *                                                                             *
27 ******************************************************************************/
28 #include <stddef.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include "altera_msgdma_descriptor_regs.h"
33 #include "altera_msgdma_csr_regs.h"
34 #include "altera_msgdma_response_regs.h"
35 #include "io.h"
36 #include "altera_msgdma.h"
37 #include "priv/alt_busy_sleep.h"
38 #include "sys/alt_errno.h"
39 #include "sys/alt_irq.h"
40 #include "sys/alt_stdio.h"
41 
42 
43 
44 
45 /*******************************************************************************
46  *  Private API
47  ******************************************************************************/
48 static int alt_msgdma_write_standard_descriptor (
49 	alt_u32 *csr_base,
50 	alt_u32 *descriptor_base,
51 	alt_msgdma_standard_descriptor *descriptor);
52 static int alt_msgdma_write_extended_descriptor (
53 	alt_u32 *csr_base,
54 	alt_u32 *descriptor_base,
55 	alt_msgdma_extended_descriptor *descriptor);
56 static void alt_msgdma_irq(void *context);
57 static int alt_msgdma_construct_standard_descriptor(
58     	alt_msgdma_dev *dev,
59 	alt_msgdma_standard_descriptor *descriptor,
60 	alt_u32 *read_address,
61 	alt_u32 *write_address,
62 	alt_u32 length,
63 	alt_u32 control);
64 static int alt_msgdma_construct_extended_descriptor(
65     	alt_msgdma_dev *dev,
66 	alt_msgdma_extended_descriptor *descriptor,
67 	alt_u32 *read_address,
68 	alt_u32 *write_address,
69 	alt_u32 length,
70 	alt_u32 control,
71 	alt_u16 sequence_number,
72 	alt_u8 read_burst_count,
73 	alt_u8 write_burst_count,
74 	alt_u16 read_stride,
75 	alt_u16 write_stride);
76 static int alt_msgdma_descriptor_async_transfer (
77 	alt_msgdma_dev *dev,
78 	alt_msgdma_standard_descriptor *standard_desc,
79 	alt_msgdma_extended_descriptor *extended_desc);
80 static int alt_msgdma_descriptor_sync_transfer (
81 	alt_msgdma_dev *dev,
82 	alt_msgdma_standard_descriptor *standard_desc,
83 	alt_msgdma_extended_descriptor *extended_desc);
84 /* The list of registered msgdma components */
85 ALT_LLIST_HEAD(alt_msgdma_list);
86 
87 /*
88  * Functions for writing descriptor structure to the dispatcher.  If you disable
89  * some of the extended features in the hardware then you should pass in 0 for
90  * that particular descriptor element. These disabled elements will not be
91  * buffered by the dispatcher block.
92  *
93  * This function is non-blocking and will return an error code if there is no
94  * room to write another descriptor to the dispatcher. It is recommended to call
95  * 'read_descriptor_buffer_full' and make sure it returns '0' before calling
96  * this function.
97  */
alt_msgdma_write_standard_descriptor(alt_u32 * csr_base,alt_u32 * descriptor_base,alt_msgdma_standard_descriptor * descriptor)98 static int alt_msgdma_write_standard_descriptor (
99 	alt_u32 *csr_base,
100 	alt_u32 *descriptor_base,
101 	alt_msgdma_standard_descriptor *descriptor)
102 {
103     if (0 != (IORD_ALTERA_MSGDMA_CSR_STATUS(csr_base) &
104     	ALTERA_MSGDMA_CSR_DESCRIPTOR_BUFFER_FULL_MASK))
105     {
106       /*at least one descriptor buffer is full, returning so that this function
107 		is non-blocking*/
108         return -ENOSPC;
109     }
110 
111 	IOWR_ALTERA_MSGDMA_DESCRIPTOR_READ_ADDRESS(descriptor_base,
112 		(alt_u32)descriptor->read_address);
113 	IOWR_ALTERA_MSGDMA_DESCRIPTOR_WRITE_ADDRESS(descriptor_base,
114 	(	alt_u32)descriptor->write_address);
115 	IOWR_ALTERA_MSGDMA_DESCRIPTOR_LENGTH(descriptor_base,
116 		descriptor->transfer_length);
117 	IOWR_ALTERA_MSGDMA_DESCRIPTOR_CONTROL_STANDARD(descriptor_base,
118 		descriptor->control);
119         return 0;
120 }
121 
122 /*
123  * This function is used for writing extended descriptors to the dispatcher.
124    It handles only 32-bit descriptors.
125  */
alt_msgdma_write_extended_descriptor(alt_u32 * csr_base,alt_u32 * descriptor_base,alt_msgdma_extended_descriptor * descriptor)126 static int alt_msgdma_write_extended_descriptor (
127 	alt_u32 *csr_base,
128 	alt_u32 *descriptor_base,
129 	alt_msgdma_extended_descriptor *descriptor)
130 {
131     if (0 != (IORD_ALTERA_MSGDMA_CSR_STATUS(csr_base) &
132     	ALTERA_MSGDMA_CSR_DESCRIPTOR_BUFFER_FULL_MASK))
133     {
134       /*at least one descriptor buffer is full, returning so that this function
135 	is non-blocking*/
136         return -ENOSPC;
137     }
138 
139     IOWR_ALTERA_MSGDMA_DESCRIPTOR_READ_ADDRESS(
140 		descriptor_base,
141     	(alt_u32)descriptor->read_address_low);
142     IOWR_ALTERA_MSGDMA_DESCRIPTOR_WRITE_ADDRESS(
143 		descriptor_base,
144 		(alt_u32)descriptor->write_address_low);
145     IOWR_ALTERA_MSGDMA_DESCRIPTOR_LENGTH(
146 		descriptor_base,
147     	descriptor->transfer_length);
148     IOWR_ALTERA_MSGDMA_DESCRIPTOR_SEQUENCE_NUMBER(
149 		descriptor_base,
150     	descriptor->sequence_number);
151     IOWR_ALTERA_MSGDMA_DESCRIPTOR_READ_BURST(
152 		descriptor_base,
153     	descriptor->read_burst_count);
154     IOWR_ALTERA_MSGDMA_DESCRIPTOR_WRITE_BURST(
155 		descriptor_base,
156     	descriptor->write_burst_count);
157     IOWR_ALTERA_MSGDMA_DESCRIPTOR_READ_STRIDE(
158 		descriptor_base,
159     	descriptor->read_stride);
160     IOWR_ALTERA_MSGDMA_DESCRIPTOR_WRITE_STRIDE(
161 		descriptor_base,
162     	descriptor->write_stride);
163     IOWR_ALTERA_MSGDMA_DESCRIPTOR_READ_ADDRESS_HIGH(descriptor_base, 0);
164     IOWR_ALTERA_MSGDMA_DESCRIPTOR_WRITE_ADDRESS_HIGH(descriptor_base, 0);
165     IOWR_ALTERA_MSGDMA_DESCRIPTOR_CONTROL_ENHANCED(
166 		descriptor_base,
167     	descriptor->control);
168     return 0;
169 }
170 
171 /*
172  * alt_msgdma_irq()
173  *
174  * Interrupt handler for the Modular Scatter-Gather DMA controller.
175  */
alt_msgdma_irq(void * context)176 static void alt_msgdma_irq(void *context)
177 {
178     alt_msgdma_dev *dev = (alt_msgdma_dev *) context;
179     alt_irq_context cpu_sr;
180     alt_u32 temporary_control;
181 
182 
183     /* disable global interrupt*/
184     if (dev->prefetcher_enable)
185     {
186         temporary_control =
187         		IORD_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base)
188 				& ALT_MSGDMA_PREFETCHER_CTRL_GLOBAL_INTR_EN_CLR_MASK;
189 
190         IOWR_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base,
191         		temporary_control);
192 
193         /* clear the IRQ status- W1C */
194         IOWR_ALT_MSGDMA_PREFETCHER_STATUS(dev->prefetcher_base,
195         		ALT_MSGDMA_PREFETCHER_STATUS_IRQ_SET_MASK);
196     }
197     else
198     {
199     	temporary_control = IORD_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base)
200     			& (~ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK);
201 
202     	IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, temporary_control);
203     	/* clear the IRQ status */
204     	IOWR_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base,
205     			ALTERA_MSGDMA_CSR_IRQ_SET_MASK);
206     }
207 
208     /*
209     * Other interrupts are explicitly disabled if callbacks
210     * are registered because there is no guarantee that they are
211     * pre-emption-safe. This allows the driver to support
212     * interrupt pre-emption.
213     */
214     if(dev->callback)
215     {
216         cpu_sr = alt_irq_disable_all();
217         dev->callback (dev->callback_context);
218         alt_irq_enable_all(cpu_sr);
219     }
220 
221     /* enable global interrupt */
222     if (dev->prefetcher_enable)
223     {
224     	temporary_control =
225     			IORD_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base)
226 				| ALT_MSGDMA_PREFETCHER_CTRL_GLOBAL_INTR_EN_SET_MASK;
227 
228     	IOWR_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base,
229     			temporary_control);
230     }
231     else
232     {
233     	temporary_control = IORD_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base)
234     			| (ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK);
235 
236     	IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, temporary_control);
237     }
238 
239     return;
240 }
241 /*
242  * Helper functions for constructing mm_to_st, st_to_mm, mm_to_mm standard
243  * descriptors. Unnecessary elements are set to 0 for completeness and will be
244  * ignored by the hardware.
245  * Returns:
246  * - status: return 0 (success)
247  *           return -EINVAL (invalid argument, could be due to argument which
248  *                          has larger value than hardware setting value)
249  */
alt_msgdma_construct_standard_descriptor(alt_msgdma_dev * dev,alt_msgdma_standard_descriptor * descriptor,alt_u32 * read_address,alt_u32 * write_address,alt_u32 length,alt_u32 control)250 static int alt_msgdma_construct_standard_descriptor(
251     	alt_msgdma_dev *dev,
252 	alt_msgdma_standard_descriptor *descriptor,
253 	alt_u32 *read_address,
254 	alt_u32 *write_address,
255 	alt_u32 length,
256 	alt_u32 control)
257 {
258     if(dev->max_byte < length ||
259        dev->enhanced_features != 0
260       )
261     {
262         return -EINVAL;
263     }
264     descriptor->read_address = read_address;
265     descriptor->write_address = write_address;
266     descriptor->transfer_length = length;
267     descriptor->control = control | ALTERA_MSGDMA_DESCRIPTOR_CONTROL_GO_MASK;
268 
269     return 0;
270 }
271 
272 /*
273  * Helper functions for constructing mm_to_st, st_to_mm, mm_to_mm extended
274  * descriptors. Unnecessary elements are set to 0 for completeness and will be
275  * ignored by the hardware.
276  * Returns:
277  * - status: return 0 (success)
278  *           return -EINVAL (invalid argument, could be due to argument which
279  *                          has larger value than hardware setting value)
280  */
alt_msgdma_construct_extended_descriptor(alt_msgdma_dev * dev,alt_msgdma_extended_descriptor * descriptor,alt_u32 * read_address,alt_u32 * write_address,alt_u32 length,alt_u32 control,alt_u16 sequence_number,alt_u8 read_burst_count,alt_u8 write_burst_count,alt_u16 read_stride,alt_u16 write_stride)281 static int alt_msgdma_construct_extended_descriptor(
282     	alt_msgdma_dev *dev,
283 	alt_msgdma_extended_descriptor *descriptor,
284 	alt_u32 *read_address,
285 	alt_u32 *write_address,
286 	alt_u32 length,
287 	alt_u32 control,
288 	alt_u16 sequence_number,
289 	alt_u8 read_burst_count,
290 	alt_u8 write_burst_count,
291 	alt_u16 read_stride,
292 	alt_u16 write_stride)
293 {
294     if(dev->max_byte < length ||
295        dev->max_stride < read_stride ||
296        dev->max_stride < write_stride ||
297        dev->enhanced_features != 1
298       )
299     {
300         return -EINVAL;
301     }
302 
303     descriptor->read_address_low = read_address;
304     descriptor->write_address_low = write_address;
305     descriptor->transfer_length = length;
306     descriptor->sequence_number = sequence_number;
307     descriptor->read_burst_count = read_burst_count;
308     descriptor->write_burst_count = write_burst_count;
309     descriptor->read_stride = read_stride;
310     descriptor->write_stride = write_stride;
311     descriptor->read_address_high = NULL;
312     descriptor->write_address_high = NULL;
313     descriptor->control = control | ALTERA_MSGDMA_DESCRIPTOR_CONTROL_GO_MASK;
314 
315   return 0 ;
316 
317 }
318 
319 /*
320  * Helper functions for descriptor in async transfer.
321  * Arguments:# This driver supports HAL types
322  * - *dev: Pointer to msgdma device (instance) structure.
323  * - *standard_desc: Pointer to single standard descriptor.
324  * - *extended_desc: Pointer to single extended descriptor.
325  *
326  *note: Either one of both *standard_desc and *extended_desc must
327  *      be assigned with NULL, another with proper pointer value.
328  *      Failing to do so can cause the function return with "-EPERM "
329  *
330  * If a callback routine has been previously registered with this
331  * particular msgdma controller, transfer will be set up to enable interrupt
332  * generation. It is the responsibility of the application developer to check
333  * source interruption, status completion and creating suitable interrupt
334  * handling. Note: "stop on error" of CSR control register is always masking
335  * within this function. The CSR control can be set by user through calling
336  * "alt_register_callback" by passing user used defined control setting.
337  *
338  * Returns:
339  * 0 -> success
340  * -ENOSPC -> FIFO descriptor buffer is full
341  * -EPERM -> operation not permitted due to descriptor type conflict
342  * -ETIME -> Time out and skipping the looping after 5 msec.
343  */
alt_msgdma_descriptor_async_transfer(alt_msgdma_dev * dev,alt_msgdma_standard_descriptor * standard_desc,alt_msgdma_extended_descriptor * extended_desc)344 static int alt_msgdma_descriptor_async_transfer (
345 	alt_msgdma_dev *dev,
346 	alt_msgdma_standard_descriptor *standard_desc,
347 	alt_msgdma_extended_descriptor *extended_desc)
348 {
349     alt_u32 control = 0;
350     alt_irq_context context = 0;
351     alt_u16 counter = 0;
352     alt_u32 fifo_read_fill_level = (
353 		IORD_ALTERA_MSGDMA_CSR_DESCRIPTOR_FILL_LEVEL(dev->csr_base) &
354 		ALTERA_MSGDMA_CSR_READ_FILL_LEVEL_MASK) >>
355 		ALTERA_MSGDMA_CSR_READ_FILL_LEVEL_OFFSET;
356     alt_u32 fifo_write_fill_level = (
357 		IORD_ALTERA_MSGDMA_CSR_DESCRIPTOR_FILL_LEVEL(dev->csr_base) &
358 		ALTERA_MSGDMA_CSR_WRITE_FILL_LEVEL_MASK) >>
359 		ALTERA_MSGDMA_CSR_WRITE_FILL_LEVEL_OFFSET;
360 
361 	/* Return with error immediately if one of read/write buffer is full */
362 	if((dev->descriptor_fifo_depth <= fifo_write_fill_level) ||
363 		(dev->descriptor_fifo_depth <= fifo_read_fill_level))
364 	{
365 		/*at least one write or read FIFO descriptor buffer is full,
366 		returning so that this function is non-blocking*/
367 		return -ENOSPC;
368 	}
369 
370 	/*
371 	* When running in a multi threaded environment, obtain the "regs_lock"
372 	* semaphore. This ensures that accessing registers is thread-safe.
373 	*/
374 	ALT_SEM_PEND (dev->regs_lock, 0);
375 
376 	/* Stop the msgdma dispatcher from issuing more descriptors to the
377 	read or write masters  */
378 	/* stop issuing more descriptors */
379 	control = ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK;
380 	/* making sure the read-modify-write below can't be pre-empted */
381 	context = alt_irq_disable_all();
382 	IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, control);
383 	/*
384 	* Clear any (previous) status register information
385 	* that might occlude our error checking later.
386 	*/
387 	IOWR_ALTERA_MSGDMA_CSR_STATUS(
388 		dev->csr_base,
389 		IORD_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base));
390 	alt_irq_enable_all(context);
391 
392     if (NULL != standard_desc && NULL == extended_desc)
393     {
394         /*writing descriptor structure to the dispatcher, wait until descriptor
395 	  write is succeed*/
396         while(0 != alt_msgdma_write_standard_descriptor (
397 		dev->csr_base, dev->descriptor_base, standard_desc))
398         {
399             alt_busy_sleep(1); /* delay 1us */
400             if(5000 <= counter) /* time_out if waiting longer than 5 msec */
401             {
402                 alt_printf("time out after 5 msec while waiting"
403 					" free FIFO buffer for storing standard descriptor\n");
404 
405 				/*
406 				* Now that access to the registers is complete, release the
407 				* registers semaphore so that other threads can access the
408 				* registers.
409 				*/
410 				ALT_SEM_POST (dev->regs_lock);
411 
412                 return -ETIME;
413             }
414             counter++;
415         }
416     }
417     else if (NULL == standard_desc && NULL != extended_desc)
418     {
419         counter = 0; /* reset counter */
420         /*writing descriptor structure to the dispatcher, wait until descriptor
421 	  write is succeed*/
422         while(0 != alt_msgdma_write_extended_descriptor (
423 		dev->csr_base,
424 		dev->descriptor_base,
425 		extended_desc))
426         {
427             alt_busy_sleep(1); /* delay 1us */
428             if(5000 <= counter) /* time_out if waiting longer than 5 msec */
429             {
430                 alt_printf("time out after 5 msec while waiting free FIFO buffer"
431 					" for storing extended descriptor\n");
432 				/*
433 				* Now that access to the registers is complete, release the
434 				* registers semaphore so that other threads can access the
435 				* registers.
436 				*/
437 				ALT_SEM_POST (dev->regs_lock);
438 
439                 return -ETIME;
440             }
441             counter++;
442         }
443     }
444     else
445     {
446 		/*
447 		* Now that access to the registers is complete, release the registers
448 		* semaphore so that other threads can access the registers.
449 		*/
450 		ALT_SEM_POST (dev->regs_lock);
451 
452         /* operation not permitted due to descriptor type conflict */
453         return -EPERM;
454     }
455 
456     /*
457     * If a callback routine has been previously registered which will be
458     * called from the msgdma ISR. Set up controller to:
459     *  - Run
460     *  - Stop on an error with any particular descriptor
461     */
462     if(dev->callback)
463     {
464 
465         control |= (dev->control |
466                     ALTERA_MSGDMA_CSR_STOP_ON_ERROR_MASK |
467                     ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK );
468         control &=  (~ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK);
469     /* making sure the read-modify-write below can't be pre-empted */
470         context = alt_irq_disable_all();
471         IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, control);
472         alt_irq_enable_all(context);
473     }
474     /*
475     * No callback has been registered. Set up controller to:
476     *   - Run
477     *   - Stop on an error with any particular descriptor
478     *   - Disable interrupt generation
479     */
480     else
481     {
482         control |= (dev->control |
483                     ALTERA_MSGDMA_CSR_STOP_ON_ERROR_MASK );
484         control &= (~ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK) &
485                    (~ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK);
486         /* making sure the read-modify-write below can't be pre-empted */
487         context = alt_irq_disable_all();
488         IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, control);
489         alt_irq_enable_all(context);
490     }
491 
492     /*
493 	 * Now that access to the registers is complete, release the registers
494      * semaphore so that other threads can access the registers.
495      */
496     ALT_SEM_POST (dev->regs_lock);
497 
498     return 0;
499 }
500 
501 /*
502  * Helper functions for descriptor in sync transfer.
503  * Arguments:
504  * - *dev: Pointer to msgdma device (instance) structure.
505  * - *standard_desc: Pointer to single standard descriptor.
506  * - *extended_desc: Pointer to single extended descriptor.
507  *
508  * Note: Either one of both *standard_desc and *extended_desc must
509  *      be assigned with NULL, another with proper pointer value.
510  *      Failing to do so can cause the function return with "-EPERM "
511  *
512  * "stop on error" of CSR control register is always being masked and interrupt
513  * is always disabled within this function.
514  * The CSR control can be set by user through calling "alt_register_callback"
515  * with passing user defined control setting.
516  *
517  * Returns:
518  * 0 -> success
519  * error -> errors or conditions causing msgdma stop issuing commands to masters.
520  *          check the bit set in the error with CSR status register.
521  * -EPERM -> operation not permitted due to descriptor type conflict
522  * -ETIME -> Time out and skipping the looping after 5 msec.
523  */
alt_msgdma_descriptor_sync_transfer(alt_msgdma_dev * dev,alt_msgdma_standard_descriptor * standard_desc,alt_msgdma_extended_descriptor * extended_desc)524 static int alt_msgdma_descriptor_sync_transfer (
525 	alt_msgdma_dev *dev,
526 	alt_msgdma_standard_descriptor *standard_desc,
527 	alt_msgdma_extended_descriptor *extended_desc)
528 {
529     alt_u32 control=0;
530     alt_irq_context context=0;
531     alt_u32 csr_status = 0;
532     alt_u16 counter = 0;
533     alt_u32 fifo_read_fill_level = (
534 		IORD_ALTERA_MSGDMA_CSR_DESCRIPTOR_FILL_LEVEL(dev->csr_base) &
535 		ALTERA_MSGDMA_CSR_READ_FILL_LEVEL_MASK) >>
536 		ALTERA_MSGDMA_CSR_READ_FILL_LEVEL_OFFSET;
537     alt_u32 fifo_write_fill_level = (
538 		IORD_ALTERA_MSGDMA_CSR_DESCRIPTOR_FILL_LEVEL(dev->csr_base) &
539 		ALTERA_MSGDMA_CSR_WRITE_FILL_LEVEL_MASK) >>
540 		ALTERA_MSGDMA_CSR_WRITE_FILL_LEVEL_OFFSET;
541     alt_u32 error = ALTERA_MSGDMA_CSR_STOPPED_ON_ERROR_MASK |
542                     ALTERA_MSGDMA_CSR_STOPPED_ON_EARLY_TERMINATION_MASK |
543                     ALTERA_MSGDMA_CSR_STOP_STATE_MASK |
544                     ALTERA_MSGDMA_CSR_RESET_STATE_MASK;
545 
546     /* Wait for available FIFO buffer to store new descriptor*/
547     while ((dev->descriptor_fifo_depth <= fifo_write_fill_level) ||
548     	(dev->descriptor_fifo_depth <= fifo_read_fill_level))
549     {
550         alt_busy_sleep(1); /* delay 1us */
551         if(5000 <= counter) /* time_out if waiting longer than 5 msec */
552         {
553             alt_printf("time out after 5 msec while waiting free FIFO buffer"
554 				" for storing descriptor\n");
555             return -ETIME;
556         }
557         counter++;
558         fifo_read_fill_level = (
559 			IORD_ALTERA_MSGDMA_CSR_DESCRIPTOR_FILL_LEVEL(dev->csr_base) &
560 			ALTERA_MSGDMA_CSR_READ_FILL_LEVEL_MASK) >>
561 			ALTERA_MSGDMA_CSR_READ_FILL_LEVEL_OFFSET;
562         fifo_write_fill_level = (
563 			IORD_ALTERA_MSGDMA_CSR_DESCRIPTOR_FILL_LEVEL(dev->csr_base) &
564 			ALTERA_MSGDMA_CSR_WRITE_FILL_LEVEL_MASK) >>
565 			ALTERA_MSGDMA_CSR_WRITE_FILL_LEVEL_OFFSET;
566     }
567 
568      /*
569      * When running in a multi threaded environment, obtain the "regs_lock"
570      * semaphore. This ensures that accessing registers is thread-safe.
571      */
572 	ALT_SEM_PEND (dev->regs_lock, 0);
573 
574     /* Stop the msgdma dispatcher from issuing more descriptors to the
575     read or write masters  */
576     /* making sure the read-modify-write below can't be pre-empted */
577     context = alt_irq_disable_all();
578     IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base,
579         ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK);
580     /*
581     * Clear any (previous) status register information
582     * that might occlude our error checking later.
583     */
584     IOWR_ALTERA_MSGDMA_CSR_STATUS(
585 		dev->csr_base,
586 		IORD_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base));
587 
588     if (NULL != standard_desc && NULL == extended_desc)
589     {
590         counter = 0; /* reset counter */
591         /*writing descriptor structure to the dispatcher, wait until descriptor
592 	  	write is succeed*/
593         while(0 != alt_msgdma_write_standard_descriptor (
594 			dev->csr_base, dev->descriptor_base, standard_desc))
595         {
596             alt_busy_sleep(1); /* delay 1us */
597             if(5000 <= counter) /* time_out if waiting longer than 5 msec */
598             {
599                 alt_printf("time out after 5 msec while writing standard"
600 					" descriptor to FIFO\n");
601 
602 				/*
603 				* Now that access to the registers is complete, release the
604 				* registers semaphore so that other threads can access the
605 				* registers.
606 				*/
607 				ALT_SEM_POST (dev->regs_lock);
608 
609                 return -ETIME;
610             }
611             counter++;
612         }
613     }
614     else if (NULL == standard_desc && NULL != extended_desc)
615     {
616         counter = 0; /* reset counter */
617         /*writing descriptor structure to the dispatcher, wait until descriptor
618 	  	write is succeed*/
619         while(0 != alt_msgdma_write_extended_descriptor (
620 			dev->csr_base, dev->descriptor_base, extended_desc))
621         {
622             alt_busy_sleep(1); /* delay 1us */
623             if(5000 <= counter) /* time_out if waiting longer than 5 msec */
624             {
625                 alt_printf("time out after 5 msec while writing extended"
626 					" descriptor to FIFO\n");
627 
628 				/*
629 				* Now that access to the registers is complete, release the
630 				* registers semaphore so that other threads can access the
631 				* registers.
632 				*/
633 				ALT_SEM_POST (dev->regs_lock);
634 
635                 return -ETIME;
636             }
637             counter++;
638         }
639     }
640     else
641     {
642 		/*
643 		* Now that access to the registers is complete, release the registers
644 		* semaphore so that other threads can access the registers.
645 		*/
646 		ALT_SEM_POST (dev->regs_lock);
647 
648         /* operation not permitted due to descriptor type conflict */
649         return -EPERM;
650     }
651 
652     /*
653     * Set up msgdma controller to:
654     * - Disable interrupt generation
655     * - Run once a valid descriptor is written to controller
656     * - Stop on an error with any particular descriptor
657     */
658      IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base,
659 		(dev->control |
660 		ALTERA_MSGDMA_CSR_STOP_ON_ERROR_MASK ) &
661 		(~ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK) &
662 		(~ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK)) ;
663 
664 	alt_irq_enable_all(context);
665 
666     counter = 0; /* reset counter */
667 
668 	csr_status = IORD_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base);
669 
670     /* Wait for any pending transfers to complete or checking any errors or
671     conditions causing descriptor to stop dispatching */
672     while (!(csr_status & error) && (csr_status & ALTERA_MSGDMA_CSR_BUSY_MASK))
673     {
674         alt_busy_sleep(1); /* delay 1us */
675         if(5000 <= counter) /* time_out if waiting longer than 5 msec */
676         {
677             alt_printf("time out after 5 msec while waiting for any pending"
678 				" transfer complete\n");
679 
680 			/*
681 			* Now that access to the registers is complete, release the registers
682 			* semaphore so that other threads can access the registers.
683 			*/
684 			ALT_SEM_POST (dev->regs_lock);
685 
686             return -ETIME;
687         }
688         counter++;
689         csr_status = IORD_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base);
690     }
691 
692 
693     /*Errors or conditions causing the dispatcher stopping issuing read/write
694       commands to masters*/
695     if(0 != (csr_status & error))
696     {
697 		/*
698 		* Now that access to the registers is complete, release the registers
699 		* semaphore so that other threads can access the registers.
700 		*/
701 		ALT_SEM_POST (dev->regs_lock);
702 
703         return error;
704     }
705 
706     /* Stop the msgdma dispatcher from issuing more descriptors to the
707     read or write masters  */
708     /* stop issuing more descriptors */
709     control = IORD_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base) |
710 	ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK;
711     /* making sure the read-modify-write below can't be pre-empted */
712     context = alt_irq_disable_all();
713     IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, control);
714     /*
715     * Clear any (previous) status register information
716     * that might occlude our error checking later.
717     */
718     IOWR_ALTERA_MSGDMA_CSR_STATUS(
719 		dev->csr_base,
720 		IORD_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base));
721     	alt_irq_enable_all(context);
722 
723 	/*
724 	* Now that access to the registers is complete, release the registers
725 	* semaphore so that other threads can access the registers.
726 	*/
727     ALT_SEM_POST (dev->regs_lock);
728 
729     return 0;
730 
731 }
732 
733 /*
734  * Functions for constructing standard descriptors.  Unnecessary elements are
735  * set to 0 for completeness and will be ignored by the hardware.
736  * Returns:
737  * - status: return 0 (success)
738  *           return -EINVAL (invalid argument, could be due to argument which
739  *                          has larger value than hardware setting value)
740  */
alt_msgdma_construct_standard_st_to_mm_descriptor(alt_msgdma_dev * dev,alt_msgdma_standard_descriptor * descriptor,alt_u32 * write_address,alt_u32 length,alt_u32 control)741 int alt_msgdma_construct_standard_st_to_mm_descriptor (
742     alt_msgdma_dev *dev,
743 	alt_msgdma_standard_descriptor *descriptor,
744 	alt_u32 *write_address, alt_u32 length, alt_u32 control)
745 {
746     return alt_msgdma_construct_standard_descriptor(dev, descriptor, NULL,
747             write_address, length, control);
748 }
749 
alt_msgdma_construct_standard_mm_to_st_descriptor(alt_msgdma_dev * dev,alt_msgdma_standard_descriptor * descriptor,alt_u32 * read_address,alt_u32 length,alt_u32 control)750 int alt_msgdma_construct_standard_mm_to_st_descriptor (
751     alt_msgdma_dev *dev,
752 	alt_msgdma_standard_descriptor *descriptor,
753 	alt_u32 *read_address,
754 	alt_u32 length,
755 	alt_u32 control)
756 {
757     return alt_msgdma_construct_standard_descriptor(dev, descriptor, read_address,
758             NULL, length, control);
759 
760 }
761 
alt_msgdma_construct_standard_mm_to_mm_descriptor(alt_msgdma_dev * dev,alt_msgdma_standard_descriptor * descriptor,alt_u32 * read_address,alt_u32 * write_address,alt_u32 length,alt_u32 control)762 int alt_msgdma_construct_standard_mm_to_mm_descriptor (
763     alt_msgdma_dev *dev,
764 	alt_msgdma_standard_descriptor *descriptor,
765 	alt_u32 *read_address,
766 	alt_u32 *write_address,
767 	alt_u32 length,
768 	alt_u32 control)
769 {
770     return alt_msgdma_construct_standard_descriptor(dev, descriptor, read_address,
771             write_address, length, control);
772 }
773 
774 /*
775  * Functions for constructing extended descriptors.  If you disable some of the
776  * extended features in the hardware then you should pass in 0 for that
777  * particular descriptor element. These disabled elements will not be buffered
778  * by the dispatcher block.
779  * Returns:
780  * - status: return 0 (success)
781  *           return -EINVAL (invalid argument, could be due to argument which
782  *                          has larger value than hardware setting value)
783  */
alt_msgdma_construct_extended_st_to_mm_descriptor(alt_msgdma_dev * dev,alt_msgdma_extended_descriptor * descriptor,alt_u32 * write_address,alt_u32 length,alt_u32 control,alt_u16 sequence_number,alt_u8 write_burst_count,alt_u16 write_stride)784 int alt_msgdma_construct_extended_st_to_mm_descriptor (
785     alt_msgdma_dev *dev,
786 	alt_msgdma_extended_descriptor *descriptor,
787 	alt_u32 *write_address,
788 	alt_u32 length,
789 	alt_u32 control,
790 	alt_u16 sequence_number,
791 	alt_u8 write_burst_count,
792 	alt_u16 write_stride)
793 {
794     return alt_msgdma_construct_extended_descriptor(dev, descriptor,
795             NULL, write_address, length, control, sequence_number, 0,
796             write_burst_count, 0, write_stride);
797 }
798 
alt_msgdma_construct_extended_mm_to_st_descriptor(alt_msgdma_dev * dev,alt_msgdma_extended_descriptor * descriptor,alt_u32 * read_address,alt_u32 length,alt_u32 control,alt_u16 sequence_number,alt_u8 read_burst_count,alt_u16 read_stride)799 int alt_msgdma_construct_extended_mm_to_st_descriptor (
800     alt_msgdma_dev *dev,
801 	alt_msgdma_extended_descriptor *descriptor,
802 	alt_u32 *read_address,
803 	alt_u32 length,
804 	alt_u32 control,
805 	alt_u16 sequence_number,
806 	alt_u8 read_burst_count,
807 	alt_u16 read_stride)
808 {
809     return alt_msgdma_construct_extended_descriptor(dev, descriptor, read_address,
810             NULL, length, control, sequence_number, read_burst_count, 0,
811             read_stride, 0);
812 
813 }
814 
alt_msgdma_construct_extended_mm_to_mm_descriptor(alt_msgdma_dev * dev,alt_msgdma_extended_descriptor * descriptor,alt_u32 * read_address,alt_u32 * write_address,alt_u32 length,alt_u32 control,alt_u16 sequence_number,alt_u8 read_burst_count,alt_u8 write_burst_count,alt_u16 read_stride,alt_u16 write_stride)815 int alt_msgdma_construct_extended_mm_to_mm_descriptor (
816     alt_msgdma_dev *dev,
817     alt_msgdma_extended_descriptor *descriptor,
818     alt_u32 *read_address,
819     alt_u32 *write_address,
820     alt_u32 length,
821     alt_u32 control,
822     alt_u16 sequence_number,
823     alt_u8 read_burst_count,
824     alt_u8 write_burst_count,
825     alt_u16 read_stride,
826     alt_u16 write_stride)
827 {
828     return alt_msgdma_construct_extended_descriptor(dev, descriptor,
829             read_address, write_address, length, control, sequence_number,
830             read_burst_count, write_burst_count, read_stride, write_stride);
831 
832 }
833 
834 /********************** MSGDMA PREFETCHER PRIVATE APIs *************************/
835 
836 /*
837  * Base functions for constructing mm_to_st, st_to_mm, mm_to_mm standard
838  * descriptors for the prefetcher. Unnecessary elements are set to 0 for
839  * completeness and will be ignored by the hardware.
840  * The descriptor created will be suitable for park since this API will set next_ptr
841  * to itself as park_mode requires. Additionally OWN_BY_HW bit left as 0 (owned by sw)
842  * until the prefetcher is started with this descriptor in the list.
843  * Returns:
844  * - status: return 0 (success)
845  *           return -EINVAL (invalid argument, could be due to argument which
846  *                          has larger value than hardware setting value)
847  */
alt_msgdma_construct_prefetcher_standard_descriptor(alt_msgdma_dev * dev,alt_msgdma_prefetcher_standard_descriptor * descriptor,alt_u32 read_address,alt_u32 write_address,alt_u32 length,alt_u32 control)848 static int alt_msgdma_construct_prefetcher_standard_descriptor(
849     alt_msgdma_dev *dev,
850 	alt_msgdma_prefetcher_standard_descriptor *descriptor,
851 	alt_u32 read_address,
852 	alt_u32 write_address,
853 	alt_u32 length,
854 	alt_u32 control)
855 {
856     if(dev->max_byte < length ||
857        dev->enhanced_features != 0
858       )
859     {
860         return -EINVAL;
861     }
862     descriptor->read_address = read_address;
863     descriptor->write_address = write_address;
864     descriptor->transfer_length = length;
865     /* have descriptor point to itself for park_mode */
866     descriptor->next_desc_ptr = (alt_u32)descriptor;
867 
868     /* clear control own_by_hw bit field (SW owns this descriptor)*/
869     descriptor->control = (control
870     		& ALT_MSGDMA_PREFETCHER_DESCRIPTOR_CTRL_OWN_BY_HW_CLR_MASK)
871     		| ALTERA_MSGDMA_DESCRIPTOR_CONTROL_GO_MASK;
872 
873     return 0;
874 }
875 
876 /*
877  * Base functions for constructing mm_to_st, st_to_mm, mm_to_mm extended
878  * descriptors. Unnecessary elements are set to 0 for completeness and will be
879  * ignored by the hardware. The descriptor created will be suitable for park
880  * mode since this API will set next_ptr to itself as park_mode requires.
881  * Additionally OWN_BY_HW bit left as 0 (owned by sw) until the prefetcher is
882  * started with this descriptor in the list.
883  * Returns:
884  * - status: return 0 (success)
885  *           return -EINVAL (invalid argument, could be due to argument which
886  *                          has larger value than hardware setting value)
887  */
alt_msgdma_construct_prefetcher_extended_descriptor(alt_msgdma_dev * dev,alt_msgdma_prefetcher_extended_descriptor * descriptor,alt_u32 read_address_high,alt_u32 read_address_low,alt_u32 write_address_high,alt_u32 write_address_low,alt_u32 length,alt_u32 control,alt_u16 sequence_number,alt_u8 read_burst_count,alt_u8 write_burst_count,alt_u16 read_stride,alt_u16 write_stride)888 static int alt_msgdma_construct_prefetcher_extended_descriptor(
889     alt_msgdma_dev *dev,
890 	alt_msgdma_prefetcher_extended_descriptor *descriptor,
891 	alt_u32 read_address_high,
892 	alt_u32 read_address_low,
893 	alt_u32 write_address_high,
894 	alt_u32 write_address_low,
895 	alt_u32 length,
896 	alt_u32 control,
897 	alt_u16 sequence_number,
898 	alt_u8 read_burst_count,
899 	alt_u8 write_burst_count,
900 	alt_u16 read_stride,
901 	alt_u16 write_stride)
902 {
903 	msgdma_addr64 node_addr;
904 
905 	if(dev->max_byte < length ||
906        dev->max_stride < read_stride ||
907        dev->max_stride < write_stride ||
908        dev->enhanced_features != 1
909       )
910     {
911         return -EINVAL;
912     }
913 
914     descriptor->read_address_high = read_address_high;
915     descriptor->read_address_low = read_address_low;
916     descriptor->write_address_high = write_address_high;
917     descriptor->write_address_low = write_address_low;
918     descriptor->transfer_length = length;
919     descriptor->sequence_number = sequence_number;
920     descriptor->read_burst_count = read_burst_count;
921     descriptor->write_burst_count = write_burst_count;
922     descriptor->read_stride = read_stride;
923     descriptor->write_stride = write_stride;
924     /* have descriptor point to itself */
925 	node_addr.u64 = (uintptr_t)descriptor;
926     descriptor->next_desc_ptr_low = node_addr.u32[0];
927     descriptor->next_desc_ptr_high = node_addr.u32[1];
928 
929     /* clear control own_by_hw bit field (SW still owns this descriptor). */
930     descriptor->control = (control
931     		& ALT_MSGDMA_PREFETCHER_DESCRIPTOR_CTRL_OWN_BY_HW_CLR_MASK)
932     		| ALTERA_MSGDMA_DESCRIPTOR_CONTROL_GO_MASK;
933 
934   return 0 ;
935 }
936 
937 
938 /********************** MSGDMA PREFETCHER PUBLIC APIs ************************/
939 
940 /*
941  * Functions for constructing standard descriptors.  Unnecessary elements are
942  * set to 0 for completeness and will be ignored by the hardware.
943  * Returns:
944  * - status: return 0 (success)
945  *           return -EINVAL (invalid argument, could be due to argument which
946  *                          has larger value than hardware setting value)
947  */
alt_msgdma_construct_prefetcher_standard_mm_to_mm_descriptor(alt_msgdma_dev * dev,alt_msgdma_prefetcher_standard_descriptor * descriptor,alt_u32 read_address,alt_u32 write_address,alt_u32 length,alt_u32 control)948 int alt_msgdma_construct_prefetcher_standard_mm_to_mm_descriptor (
949 	alt_msgdma_dev *dev,
950 	alt_msgdma_prefetcher_standard_descriptor *descriptor,
951 	alt_u32 read_address,
952 	alt_u32 write_address,
953 	alt_u32 length,
954 	alt_u32 control)
955 {
956     return alt_msgdma_construct_prefetcher_standard_descriptor(dev, descriptor,
957     		read_address, write_address, length, control);
958 }
959 
alt_msgdma_construct_prefetcher_standard_st_to_mm_descriptor(alt_msgdma_dev * dev,alt_msgdma_prefetcher_standard_descriptor * descriptor,alt_u32 write_address,alt_u32 length,alt_u32 control)960 int alt_msgdma_construct_prefetcher_standard_st_to_mm_descriptor (
961 	alt_msgdma_dev *dev,
962 	alt_msgdma_prefetcher_standard_descriptor *descriptor,
963 	alt_u32 write_address,
964 	alt_u32 length,
965 	alt_u32 control)
966 {
967     return alt_msgdma_construct_prefetcher_standard_descriptor(dev, descriptor,
968     		0, write_address, length, control);
969 }
970 
alt_msgdma_construct_prefetcher_standard_mm_to_st_descriptor(alt_msgdma_dev * dev,alt_msgdma_prefetcher_standard_descriptor * descriptor,alt_u32 read_address,alt_u32 length,alt_u32 control)971 int alt_msgdma_construct_prefetcher_standard_mm_to_st_descriptor (
972 	alt_msgdma_dev *dev,
973 	alt_msgdma_prefetcher_standard_descriptor *descriptor,
974 	alt_u32 read_address,
975 	alt_u32 length,
976 	alt_u32 control)
977 {
978     return alt_msgdma_construct_prefetcher_standard_descriptor(dev, descriptor,
979     		read_address, 0, length, control);
980 }
981 
982 
983 /*
984  * Functions for constructing extended descriptors.  If you disable some of the
985  * extended features in the hardware then you should pass in 0 for that
986  * particular descriptor element. These disabled elements will not be buffered
987  * by the dispatcher block.
988  * Returns:
989  * - status: return 0 (success)
990  *           return -EINVAL (invalid argument, could be due to argument which
991  *                          has larger value than hardware setting value)
992  */
alt_msgdma_construct_prefetcher_extended_st_to_mm_descriptor(alt_msgdma_dev * dev,alt_msgdma_prefetcher_extended_descriptor * descriptor,alt_u32 write_address_high,alt_u32 write_address_low,alt_u32 length,alt_u32 control,alt_u16 sequence_number,alt_u8 write_burst_count,alt_u16 write_stride)993 int alt_msgdma_construct_prefetcher_extended_st_to_mm_descriptor (
994 	alt_msgdma_dev *dev,
995 	alt_msgdma_prefetcher_extended_descriptor *descriptor,
996 	alt_u32 write_address_high,
997 	alt_u32 write_address_low,
998 	alt_u32 length,
999 	alt_u32 control,
1000 	alt_u16 sequence_number,
1001 	alt_u8 write_burst_count,
1002 	alt_u16 write_stride)
1003 {
1004     return alt_msgdma_construct_prefetcher_extended_descriptor(dev, descriptor,
1005             0, 0, write_address_high, write_address_low, length, control,
1006 			sequence_number, 0, write_burst_count, 0, write_stride);
1007 }
1008 
alt_msgdma_construct_prefetcher_extended_mm_to_st_descriptor(alt_msgdma_dev * dev,alt_msgdma_prefetcher_extended_descriptor * descriptor,alt_u32 read_address_high,alt_u32 read_address_low,alt_u32 length,alt_u32 control,alt_u16 sequence_number,alt_u8 read_burst_count,alt_u16 read_stride)1009 int alt_msgdma_construct_prefetcher_extended_mm_to_st_descriptor (
1010 	alt_msgdma_dev *dev,
1011 	alt_msgdma_prefetcher_extended_descriptor *descriptor,
1012 	alt_u32 read_address_high,
1013 	alt_u32 read_address_low,
1014 	alt_u32 length,
1015 	alt_u32 control,
1016 	alt_u16 sequence_number,
1017 	alt_u8 read_burst_count,
1018 	alt_u16 read_stride)
1019 {
1020     return alt_msgdma_construct_prefetcher_extended_descriptor(dev, descriptor,
1021     		read_address_high, read_address_low, 0, 0, length, control,
1022 			sequence_number, read_burst_count, 0, read_stride, 0);
1023 }
1024 
alt_msgdma_construct_prefetcher_extended_mm_to_mm_descriptor(alt_msgdma_dev * dev,alt_msgdma_prefetcher_extended_descriptor * descriptor,alt_u32 read_address_high,alt_u32 read_address_low,alt_u32 write_address_high,alt_u32 write_address_low,alt_u32 length,alt_u32 control,alt_u16 sequence_number,alt_u8 read_burst_count,alt_u8 write_burst_count,alt_u16 read_stride,alt_u16 write_stride)1025 int alt_msgdma_construct_prefetcher_extended_mm_to_mm_descriptor (
1026 	alt_msgdma_dev *dev,
1027 	alt_msgdma_prefetcher_extended_descriptor *descriptor,
1028 	alt_u32 read_address_high,
1029 	alt_u32 read_address_low,
1030 	alt_u32 write_address_high,
1031 	alt_u32 write_address_low,
1032 	alt_u32 length,
1033 	alt_u32 control,
1034 	alt_u16 sequence_number,
1035 	alt_u8 read_burst_count,
1036 	alt_u8 write_burst_count,
1037 	alt_u16 read_stride,
1038 	alt_u16 write_stride)
1039 {
1040     return alt_msgdma_construct_prefetcher_extended_descriptor(dev, descriptor,
1041             read_address_high, read_address_low, write_address_high,
1042 			write_address_low, length, control, sequence_number,
1043 			read_burst_count, write_burst_count, read_stride, write_stride);
1044 
1045 }
1046 
1047 /* PREFETCHER linked list APIs */
1048 /*
1049  * Function for adding standard descriptors to a standard descriptor list
1050  * Returns:
1051  * - status: return 0 (success)
1052  *           return -EINVAL (invalid argument, could be due to descriptor
1053  *           already being in the list, descriptor pointer being NULL, or
1054  *           descriptor.next_ptr not pointing back to itslef)
1055  */
alt_msgdma_prefetcher_add_standard_desc_to_list(alt_msgdma_prefetcher_standard_descriptor ** list,alt_msgdma_prefetcher_standard_descriptor * descriptor)1056 int alt_msgdma_prefetcher_add_standard_desc_to_list (
1057 	alt_msgdma_prefetcher_standard_descriptor** list,
1058 	alt_msgdma_prefetcher_standard_descriptor* descriptor)
1059 {
1060 	alt_msgdma_prefetcher_standard_descriptor *last_descr_ptr;
1061 
1062 	if (descriptor == NULL)
1063 	{
1064 		return -EINVAL;  /* this descriptor cannot be NULL */
1065 	}
1066 	if (descriptor->next_desc_ptr != (alt_u32)descriptor)
1067 	{
1068 		return -EINVAL;  /* descriptor.next_ptr must point to itself */
1069 	}
1070 	if (*list == NULL)
1071 	{
1072 		*list = descriptor;  /* make this root-node if list is empty */
1073 		return 0;  /* successfully added */
1074 	}
1075 	if (*list == descriptor)
1076 	{
1077 		return -EINVAL;  /* this descriptor cannot already be root-node */
1078 	}
1079 
1080 	/* get to last node in the list */
1081 	last_descr_ptr = *list; /* start at list root-node */
1082 	/* traverse list until you get the last node */
1083 	while (last_descr_ptr->next_desc_ptr != (alt_u32)*list)
1084 	{
1085 		if (last_descr_ptr->next_desc_ptr == (alt_u32)descriptor)
1086 		{
1087 			return -EINVAL;  /* descriptor cannot already be in the list */
1088 		}
1089 		last_descr_ptr =
1090 			(alt_msgdma_prefetcher_standard_descriptor*)(last_descr_ptr->next_desc_ptr);
1091 	}
1092 	/* add this descriptor to end of list */
1093 	last_descr_ptr->next_desc_ptr = (alt_u32)((uintptr_t)descriptor);
1094 	/* ensure new last pointer points the start of the list */
1095 	descriptor->next_desc_ptr = (alt_u32)((uintptr_t)*list);
1096 	return 0; /* successfully added */
1097 }
1098 
alt_msgdma_prefetcher_add_extended_desc_to_list(alt_msgdma_prefetcher_extended_descriptor ** list,alt_msgdma_prefetcher_extended_descriptor * descriptor)1099 int alt_msgdma_prefetcher_add_extended_desc_to_list (
1100 	alt_msgdma_prefetcher_extended_descriptor** list,
1101 	alt_msgdma_prefetcher_extended_descriptor* descriptor)
1102 {
1103 	alt_msgdma_prefetcher_extended_descriptor *last_descr_ptr;
1104 	msgdma_addr64 root_node_addr, next_node_addr;
1105 
1106 	if (descriptor == NULL)
1107 	{
1108 		return -EINVAL;  /* this descriptor cannot be NULL */
1109 	}
1110 
1111 	next_node_addr.u64 = (uintptr_t)descriptor;
1112 	if( (descriptor->next_desc_ptr_low != next_node_addr.u32[0]) &&
1113 		(descriptor->next_desc_ptr_high != next_node_addr.u32[1]))
1114 	{
1115 		return -EINVAL;  /* descriptor.next_ptr must point to itself */
1116 	}
1117 
1118 	if (*list == NULL)
1119 	{
1120 		*list = descriptor;  /* make this the root-node if list is empty */
1121 		return 0;
1122 	}
1123 	if (*list == descriptor)
1124 	{
1125 		return -EINVAL;  /* this descriptor cannot already be root-node */
1126 	}
1127 
1128 	/* get to last node in the list */
1129 	last_descr_ptr = *list; /* start at list root-node */
1130 	/* the last nodes next ptr should point to the root node*/
1131 	root_node_addr.u64 = (uintptr_t)*list;
1132 
1133 	/* traverse list until you get the last node */
1134 	while ((last_descr_ptr->next_desc_ptr_low != root_node_addr.u32[0])
1135 		&& (last_descr_ptr->next_desc_ptr_high != root_node_addr.u32[1]))
1136 	{
1137 		/* first check if descriptor already in the list */
1138 		next_node_addr.u64 = (uintptr_t)descriptor;
1139 		if ((last_descr_ptr->next_desc_ptr_low == next_node_addr.u32[0])
1140 			&& (last_descr_ptr->next_desc_ptr_high == next_node_addr.u32[1]))
1141 		{
1142 			return -EINVAL;  /* descriptor cannot already be in the list */
1143 		}
1144 		/* go to next node in list, using 64 bit address */
1145 		next_node_addr.u32[0] = last_descr_ptr->next_desc_ptr_low;
1146 		next_node_addr.u32[1] = last_descr_ptr->next_desc_ptr_high;
1147 		last_descr_ptr =
1148 			(alt_msgdma_prefetcher_extended_descriptor*)((uintptr_t)next_node_addr.u64);
1149 	}
1150 	/* add this descriptor to end of list */
1151 	next_node_addr.u64 = (uintptr_t)descriptor;
1152 	last_descr_ptr->next_desc_ptr_low = next_node_addr.u32[0];
1153 	last_descr_ptr->next_desc_ptr_high = next_node_addr.u32[1];
1154 	/* ensure new last pointer points the beginning of the list */
1155 	descriptor->next_desc_ptr_low = root_node_addr.u32[0];
1156 	descriptor->next_desc_ptr_high = root_node_addr.u32[1];
1157 	return 0;
1158 }
1159 
1160 /*
1161  * Functions to set all the own-by-hw bits, need to call right before starting
1162  * prefetcher since if used the create descriptor APIs the set_by_hw bits are
1163  * still set to SW owned.
1164  */
alt_msgdma_prefetcher_set_std_list_own_by_hw_bits(alt_msgdma_prefetcher_standard_descriptor * list)1165 int alt_msgdma_prefetcher_set_std_list_own_by_hw_bits (
1166 	alt_msgdma_prefetcher_standard_descriptor *list)
1167 {
1168 	alt_u32 descriptor_control_field = 0;
1169 	alt_msgdma_prefetcher_standard_descriptor *last_descr_ptr;
1170 	if (list == NULL)
1171 	{
1172 		return -EINVAL;  /* this list cannot be empty */
1173 	}
1174 
1175 	/* update all nodes in the list */
1176 	last_descr_ptr = list; /* start at list root-node */
1177 	/* traverse list to update all of the nodes */
1178 	while (last_descr_ptr->next_desc_ptr != (alt_u32)list)
1179 	{
1180 		/* get current value */
1181 		descriptor_control_field = last_descr_ptr->control;
1182 		/* update own_by_hw bit only */
1183 		last_descr_ptr->control = descriptor_control_field
1184 				| ALT_MSGDMA_PREFETCHER_DESCRIPTOR_CTRL_OWN_BY_HW_SET_MASK;
1185 		/* go to next node in list */
1186 		last_descr_ptr =
1187 			(alt_msgdma_prefetcher_standard_descriptor*)(last_descr_ptr->next_desc_ptr);
1188 	}
1189 	/* update the last node in the list, currently last_descr_ptr after while loop */
1190 	descriptor_control_field = last_descr_ptr->control;    /* get current value */
1191 	/* update own_by_hw bit only */
1192 	last_descr_ptr->control = descriptor_control_field
1193 		| ALT_MSGDMA_PREFETCHER_DESCRIPTOR_CTRL_OWN_BY_HW_SET_MASK;
1194 
1195 	return 0;
1196 }
1197 
1198 /*
1199  * Functions to set all the own-by-hw bits, need to call right before starting
1200  * prefetcher since if used the create descriptor APIs the set_by_hw bits are
1201  * still set to SW owned.
1202  */
alt_msgdma_prefetcher_set_extd_list_own_by_hw_bits(alt_msgdma_prefetcher_extended_descriptor * list)1203 int alt_msgdma_prefetcher_set_extd_list_own_by_hw_bits (
1204 	alt_msgdma_prefetcher_extended_descriptor *list)
1205 {
1206 	alt_u32 descriptor_control_field = 0;
1207 	msgdma_addr64 root_node_addr, next_node_addr;
1208 	alt_msgdma_prefetcher_extended_descriptor *last_descr_ptr;
1209 
1210 	if (list == NULL)
1211 	{
1212 		return -EINVAL;  /* this list cannot be empty */
1213 	}
1214 
1215 	/* update all nodes in the list */
1216 	last_descr_ptr = list; /* start at list root-node */
1217 	/* the last nodes next ptr should point to the root node*/
1218 	root_node_addr.u64 = (uintptr_t)list;
1219 
1220 	/* traverse list until you get the last node */
1221 	while ((last_descr_ptr->next_desc_ptr_low != root_node_addr.u32[0])
1222 		&& (last_descr_ptr->next_desc_ptr_high != root_node_addr.u32[1]))
1223 	{
1224 		/* start with current value */
1225 		descriptor_control_field = last_descr_ptr->control;
1226 		/* update own_by_hw bit only */
1227 		last_descr_ptr->control = descriptor_control_field
1228 				| ALT_MSGDMA_PREFETCHER_DESCRIPTOR_CTRL_OWN_BY_HW_SET_MASK;
1229 		/* go to next node in list, using 64 bit address */
1230 		next_node_addr.u32[0] = last_descr_ptr->next_desc_ptr_low;
1231 		next_node_addr.u32[1] = last_descr_ptr->next_desc_ptr_high;
1232 		last_descr_ptr =
1233 			(alt_msgdma_prefetcher_extended_descriptor*)((uintptr_t)next_node_addr.u64);
1234 	}
1235 	/* update the last node in the list, currently last_descr_ptr after while loop */
1236 	descriptor_control_field = last_descr_ptr->control;    /* start with current value */
1237 	/* update own_by_hw bit only */
1238 	last_descr_ptr->control = descriptor_control_field
1239 		| ALT_MSGDMA_PREFETCHER_DESCRIPTOR_CTRL_OWN_BY_HW_SET_MASK;
1240 	return 0;
1241 }
1242 
1243 
1244 /*
1245  * Functions to start the prefetcher.  Will return error if prefetcher already
1246  * started.
1247  *
1248  * Arguments:# This driver supports HAL types
1249  * - *dev: Pointer to msgdma device (instance) structure.
1250  * - *standard_desc: Pointer to single standard descriptor  OR  *extended_desc:
1251  * 	 Pointer to single extended descriptor.
1252  * -  park_mode_en:  setting for prefetcher park mode
1253  * -  poll_en: setting for poll_en (IF poll frequency still 0 this API will
1254  * 	also set that to a default non-zero value)
1255  *
1256  *note: Must call API specific to descriptor type. Either
1257  *	 alt_msgdma_start_prefetcher_with_std_desc_list   OR
1258  *	 alt_msgdma_start_prefetcher_with_extd_desc_list
1259  *	 where the list paratmeter is the root-node of your linked list. Then those
1260  *	  APIs will call the base function accordingly.
1261  *
1262  * If a callback routine has been previously registered with this
1263  * particular msgdma controller, transfer will be set up to enable interrupt
1264  * generation. It is the responsibility of the application developer to check
1265  * source interruption, status completion and creating suitable interrupt
1266  * handling.
1267  * Note: "stop on error" of CSR control register is always masking within this
1268  *	 function. The CSR control can be set by user through calling
1269  *       "alt_register_callback" by passing user used defined control setting.
1270  *
1271  * Returns:
1272  * 0 -> success
1273  * -EBUSY -> prefetcher busy processing list already, it is up to user to stop
1274  *  prefetcher/dispatcher correctly before calling this function.
1275  *  if already busy will always return error.
1276  */
1277 
1278 /*
1279  * Base function to start prefetcher.
1280  */
alt_msgdma_start_prefetcher_with_list_addr(alt_msgdma_dev * dev,alt_u64 list_addr,alt_u8 park_mode_en,alt_u8 poll_en)1281 int alt_msgdma_start_prefetcher_with_list_addr (
1282 	alt_msgdma_dev *dev,
1283 	alt_u64  list_addr,
1284 	alt_u8 park_mode_en,
1285 	alt_u8 poll_en)
1286 {
1287 	alt_u32 prefetcher_ctl = 0;
1288 	alt_u32 dispatcher_ctl = 0;
1289 	alt_irq_context context = 0;
1290 
1291 	/* use helper struct to get easy access to hi/low address */
1292 	msgdma_addr64 root_node_addr;
1293 	root_node_addr.u64 = list_addr;
1294 
1295 	/*
1296 	 * When running in a multi threaded environment, obtain the "regs_lock"
1297 	 * semaphore. This ensures that accessing registers is thread-safe.
1298 	 */
1299 	ALT_SEM_PEND (dev->regs_lock, 0);
1300 
1301 	/* case where prefetcher already started, return busy error */
1302 	prefetcher_ctl = IORD_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base);
1303 	if(ALT_MSGDMA_PREFETCHER_CTRL_RUN_GET(prefetcher_ctl)){
1304 		/* release the registers semaphore */
1305 		ALT_SEM_POST (dev->regs_lock);
1306 		return -EBUSY;
1307 	}
1308 
1309 	/* Stop the msgdma dispatcher from issuing more descriptors to the
1310 	   read or write masters  */
1311 	/* stop issuing more descriptors */
1312 	dispatcher_ctl = ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK;
1313 
1314 	/* making sure the read-modify-write below can't be pre-empted */
1315 	context = alt_irq_disable_all();
1316 	IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, dispatcher_ctl);
1317 	/*
1318 	 * Clear any (previous) status register information
1319 	 * that might occlude our error checking later.
1320 	 */
1321 	IOWR_ALTERA_MSGDMA_CSR_STATUS( dev->csr_base,
1322 			IORD_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base));
1323 
1324 	alt_irq_enable_all(context);
1325 
1326 	/*
1327 	 * If a callback routine has been previously registered which will be
1328 	 * called from the msgdma ISR. Set up dispatcher to:
1329 	 *  - Run
1330 	 *  - Stop on an error with any particular descriptor
1331 	 */
1332 	if(dev->callback)
1333 	{
1334 		dispatcher_ctl |= (dev->control | ALTERA_MSGDMA_CSR_STOP_ON_ERROR_MASK
1335 				| ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK );
1336 		dispatcher_ctl &=  (~ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK);
1337 
1338 		prefetcher_ctl |= ALT_MSGDMA_PREFETCHER_CTRL_GLOBAL_INTR_EN_SET_MASK;
1339 	    /* making sure the read-modify-write below can't be pre-empted */
1340 	    context = alt_irq_disable_all();
1341 	    IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, dispatcher_ctl);
1342 		IOWR_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base, prefetcher_ctl);
1343 	    alt_irq_enable_all(context);
1344 	 }
1345 	 /*
1346 	  * No callback has been registered. Set up dispatcher to:
1347 	  *   - Run
1348 	  *   - Stop on an error with any particular descriptor
1349 	  *   - Disable interrupt generation
1350 	  */
1351 	 else
1352 	 {
1353 		 dispatcher_ctl |= (dev->control | ALTERA_MSGDMA_CSR_STOP_ON_ERROR_MASK);
1354 		 dispatcher_ctl &= (~ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK)
1355 				 & (~ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK);
1356 		 prefetcher_ctl &= ALT_MSGDMA_PREFETCHER_CTRL_GLOBAL_INTR_EN_CLR_MASK;
1357 	     /* making sure the read-modify-write below can't be pre-empted */
1358 	     context = alt_irq_disable_all();
1359 	     IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, dispatcher_ctl);
1360 	     IOWR_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base, prefetcher_ctl);
1361 	     alt_irq_enable_all(context);
1362 	 }
1363 
1364 	 /* set next descriptor registers to point to the list root-node */
1365 	 IOWR_ALT_MSGDMA_PREFETCHER_NEXT_DESCRIPTOR_PTR_LOW(dev->prefetcher_base,
1366 			 root_node_addr.u32[0]);
1367 	 IOWR_ALT_MSGDMA_PREFETCHER_NEXT_DESCRIPTOR_PTR_HIGH(dev->prefetcher_base,
1368 			 root_node_addr.u32[1]);
1369 
1370 	 /* set park-mode */
1371 	 if (park_mode_en){
1372 		 prefetcher_ctl |= ALT_MSGDMA_PREFETCHER_CTRL_PARK_MODE_SET_MASK;
1373 	 }
1374 	 else {
1375 		 prefetcher_ctl &= ALT_MSGDMA_PREFETCHER_CTRL_PARK_MODE_CLR_MASK;
1376 	 }
1377 
1378 	 /* set poll-en */
1379 	 if (poll_en){
1380 		 prefetcher_ctl |= ALT_MSGDMA_PREFETCHER_CTRL_DESC_POLL_EN_MASK;
1381 		 if(IORD_ALT_MSGDMA_PREFETCHER_DESCRIPTOR_POLLING_FREQ(
1382 				 dev->prefetcher_base) == 0){
1383 			 /* set poll frequency to some non-zero default value */
1384 			 IOWR_ALT_MSGDMA_PREFETCHER_DESCRIPTOR_POLLING_FREQ(
1385 					 dev->prefetcher_base, 0xFF);
1386 		 }
1387 	 }
1388 	 else {
1389 		 prefetcher_ctl &= ALT_MSGDMA_PREFETCHER_CTRL_DESC_POLL_EN_CLR_MASK;
1390 	 }
1391 
1392 	 /* set the prefetcher run bit */
1393 	 prefetcher_ctl |= ALT_MSGDMA_PREFETCHER_CTRL_RUN_SET_MASK;
1394 	 /* start the dma since run bit is set */
1395 	 IOWR_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base, prefetcher_ctl);
1396 
1397 	 /*
1398 	  * Now that access to the registers is complete, release the registers
1399 	  * semaphore so that other threads can access the registers.
1400 	  */
1401 	 ALT_SEM_POST (dev->regs_lock);
1402 
1403 	 return 0;
1404 }
1405 
1406 /*
1407  * Public functions to start prefetcher.
1408  */
alt_msgdma_start_prefetcher_with_std_desc_list(alt_msgdma_dev * dev,alt_msgdma_prefetcher_standard_descriptor * list,alt_u8 park_mode_en,alt_u8 poll_en)1409 int alt_msgdma_start_prefetcher_with_std_desc_list (
1410 	alt_msgdma_dev *dev,
1411 	alt_msgdma_prefetcher_standard_descriptor *list,
1412 	alt_u8 park_mode_en,
1413 	alt_u8 poll_en)
1414 {
1415 	if (alt_msgdma_prefetcher_set_std_list_own_by_hw_bits(list) != 0){
1416 		return -EINVAL;
1417 	}
1418 
1419 	return alt_msgdma_start_prefetcher_with_list_addr (dev, (uintptr_t)list,
1420 			park_mode_en, poll_en);
1421 }
1422 
alt_msgdma_start_prefetcher_with_extd_desc_list(alt_msgdma_dev * dev,alt_msgdma_prefetcher_extended_descriptor * list,alt_u8 park_mode_en,alt_u8 poll_en)1423 int alt_msgdma_start_prefetcher_with_extd_desc_list (
1424 	alt_msgdma_dev *dev,
1425 	alt_msgdma_prefetcher_extended_descriptor *list,
1426 	alt_u8 park_mode_en,
1427 	alt_u8 poll_en)
1428 {
1429 	if (alt_msgdma_prefetcher_set_extd_list_own_by_hw_bits(list) != 0){
1430 		return -EINVAL;
1431 	}
1432 	return alt_msgdma_start_prefetcher_with_list_addr (dev, (uintptr_t)list,
1433 			park_mode_en, poll_en);
1434 }
1435 
1436 
1437 /*
1438  * alt_msgdma_open - Retrieve a pointer to the msgdma
1439  *
1440  * Search the list of registered msgdma for one with the supplied name.
1441  *
1442  * The return value will be NULL on failure, and non-NULL otherwise.
1443  *
1444  * Arguments:
1445  * - *name: Character pointer to name of msgdma peripheral as registered
1446  *   with the HAL. For example, an msgdma controller named "msgdma_0"
1447  *   in Qsys would be opened by asking for "/dev/msgdma_0_csr".
1448  *
1449  * Returns:
1450  * - Pointer to msgdma device instance structure, or null if the device
1451  *   could not be opened.
1452  */
alt_msgdma_open(const char * name)1453 alt_msgdma_dev* alt_msgdma_open (const char* name)
1454 {
1455     alt_msgdma_dev* dev = NULL;
1456 
1457     dev = (alt_msgdma_dev*) alt_find_dev (name, &alt_msgdma_list);
1458 
1459     if (NULL == dev)
1460     {
1461         ALT_ERRNO = ENODEV;
1462     }
1463 
1464     return dev;
1465 }
1466 
1467 
1468 /*
1469  * alt_msgdma_init()
1470  *
1471  * Initializes the Modular Scatter-Gather DMA controller. This routine is called
1472  * from the ALTERA_MSGDMA_INIT macro and is called automatically
1473  * by alt_sys_init.c
1474  *
1475  * This routine disables interrupts, descriptor processing,
1476  * registers a specific instance of the device with the HAL,
1477  * and installs an interrupt handler for the device.
1478  */
alt_msgdma_init(alt_msgdma_dev * dev,alt_u32 ic_id,alt_u32 irq)1479 void alt_msgdma_init (alt_msgdma_dev *dev, alt_u32 ic_id, alt_u32 irq)
1480 {
1481     extern alt_llist alt_msgdma_list;
1482     alt_u32 temporary_control;
1483     int error;
1484 
1485     if (dev->prefetcher_enable)
1486     {
1487     	/* start prefetcher reset sequence */
1488     	IOWR_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base,
1489     			ALT_MSGDMA_PREFETCHER_CTRL_RESET_SET_MASK);
1490     	/* wait until hw clears the bit */
1491     	while(ALT_MSGDMA_PREFETCHER_CTRL_RESET_GET(
1492     			IORD_ALT_MSGDMA_PREFETCHER_CONTROL(dev->prefetcher_base)));
1493     	/*
1494     	 * This reset is intended to be used along with reset dispatcher in
1495     	 * dispatcher core. Once the reset sequence in prefetcher core has
1496     	 * completed, software is expected to reset the dispatcher core,
1497     	 * and polls for dispatcher�s reset sequence to be completed.
1498     	 */
1499     }
1500 
1501     /* Reset the registers and FIFOs of the dispatcher and master modules */
1502     /* set the reset bit, no need to read the control register first since
1503     this write is going to clear it out */
1504     IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, ALTERA_MSGDMA_CSR_RESET_MASK);
1505     while(0 != (IORD_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base)
1506     		& ALTERA_MSGDMA_CSR_RESET_STATE_MASK));
1507     /*
1508     * Disable interrupts, halt descriptor processing,
1509     * and clear status register content
1510     */
1511 
1512     /* disable global interrupt */
1513     temporary_control = IORD_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base)
1514     		& (~ALTERA_MSGDMA_CSR_GLOBAL_INTERRUPT_MASK);
1515     /* stopping descriptor */
1516     temporary_control |= ALTERA_MSGDMA_CSR_STOP_DESCRIPTORS_MASK;
1517     IOWR_ALTERA_MSGDMA_CSR_CONTROL(dev->csr_base, temporary_control);
1518 
1519     /* clear the CSR status register */
1520     IOWR_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base,
1521     		IORD_ALTERA_MSGDMA_CSR_STATUS(dev->csr_base));
1522 
1523     if (dev->prefetcher_enable)
1524     {
1525     	/* clear all status bits that are set, since theyre W1C */
1526     	IOWR_ALT_MSGDMA_PREFETCHER_STATUS(dev->prefetcher_base,
1527     			IORD_ALT_MSGDMA_PREFETCHER_STATUS(dev->prefetcher_base));
1528     }
1529 
1530     /* Register this instance of the msgdma controller with HAL */
1531     alt_dev_llist_insert((alt_dev_llist*) dev, &alt_msgdma_list);
1532 
1533     /*
1534      * Creating semaphores used to protect access to the registers
1535      * when running in a multi-threaded environment.
1536      */
1537     error = ALT_SEM_CREATE (&dev->regs_lock, 1);
1538 
1539     if (!error)
1540     {
1541         /* Install IRQ handler */
1542         alt_ic_isr_register(ic_id, irq, alt_msgdma_irq, dev, 0x0);
1543     }
1544     else
1545     {
1546         alt_printf("failed to create semaphores\n");
1547     }
1548 
1549     return;
1550 
1551 }
1552 
1553 
1554 /*
1555  * alt_msgdma_register_callback
1556  *
1557  * Associate a user-specific routine with the msgdma interrupt handler.
1558  * If a callback is registered, all non-blocking msgdma transfers will
1559  * enable interrupts that will cause the callback to be executed.
1560  * The callback runs as part of the interrupt service routine, and
1561  * great care must be taken to follow the guidelines for acceptable
1562  * interrupt service routine behaviour as described in the Nios II
1563  * Software Developer's Handbook.However, user can change some of the CSR
1564  * control setting in blocking transfer by calling this function.
1565  *
1566  * Note: To disable callbacks after registering one, this routine
1567  * may be called passing 0x0 to the callback argument.
1568  *
1569  * Arguments:
1570  * - *dev: Pointer to msgdma device (instance) structure.
1571  * - callback: Pointer to callback routine to execute at interrupt level
1572  * - control: For masking the source interruption and setting configuration in
1573  *            control register
1574  */
alt_msgdma_register_callback(alt_msgdma_dev * dev,alt_msgdma_callback callback,alt_u32 control,void * context)1575 void alt_msgdma_register_callback(
1576 	alt_msgdma_dev *dev,
1577 	alt_msgdma_callback callback,
1578 	alt_u32 control,
1579 	void *context)
1580 {
1581     dev->callback         = callback;
1582     dev->callback_context = context;
1583     dev->control          = control;
1584 
1585     return ;
1586 }
1587 
1588 /*
1589  * alt_msgdma_standard_descriptor_async_transfer
1590  *
1591  * Set up and commence a non-blocking transfer of one descriptors at a time.
1592  *
1593  * If the FIFO buffer for one of read/write is full at the time of this call,
1594  * the routine will immediately return -ENOSPC, the application can then decide
1595  * how to proceed without being blocked.
1596  *
1597  * Arguments:
1598  * - *dev: Pointer to msgdma device (instance) struct.
1599  * - *desc: Pointer to single (ready to run) descriptor.
1600  *
1601  * Returns:
1602  * 0 -> success
1603  * -ENOSPC -> FIFO descriptor buffer is full
1604  * -EPERM -> operation not permitted due to descriptor type conflict
1605  * -ETIME -> Time out and skipping the looping after 5 msec.
1606  */
alt_msgdma_standard_descriptor_async_transfer(alt_msgdma_dev * dev,alt_msgdma_standard_descriptor * desc)1607 int alt_msgdma_standard_descriptor_async_transfer(
1608 	alt_msgdma_dev *dev,
1609 	alt_msgdma_standard_descriptor *desc)
1610 {
1611    /*
1612    * Error detection/handling should be performed at the application
1613    * or callback level as appropriate.
1614    */
1615     return alt_msgdma_descriptor_async_transfer(dev, desc, NULL);
1616 
1617 }
1618 
1619 
1620 /*
1621  * alt_msgdma_extended_descriptor_async_transfer
1622  *
1623  * Set up and commence a non-blocking transfer of one descriptors at a time.
1624  *
1625  * If the FIFO buffer for one of read/write is full at the time of this call,
1626  * the routine will immediately return -ENOSPC, the application can then
1627  * decide how to proceed without being blocked.
1628  *
1629  * Arguments:
1630  * - *dev: Pointer to msgdma device (instance) struct.
1631  * - *desc: Pointer to single (ready to run) descriptor.
1632  *
1633  * Returns:
1634  * 0 -> success
1635  * -ENOSPC -> FIFO descriptor buffer is full
1636  * -EPERM -> operation not permitted due to descriptor type conflict
1637  * -ETIME -> Time out and skipping the looping after 5 msec.
1638  */
alt_msgdma_extended_descriptor_async_transfer(alt_msgdma_dev * dev,alt_msgdma_extended_descriptor * desc)1639 int alt_msgdma_extended_descriptor_async_transfer(
1640 	alt_msgdma_dev *dev,
1641 	alt_msgdma_extended_descriptor *desc)
1642 {
1643     /*
1644     * Error detection/handling should be performed at the application
1645     * or callback level as appropriate.
1646     */
1647     return alt_msgdma_descriptor_async_transfer(dev, NULL, desc);
1648 }
1649 
1650 
1651 /*
1652  * alt_msgdma_standard_descriptor_sync_transfer
1653  *
1654  * This function will start commencing a blocking transfer of one standard
1655  * descriptor at a time. If the FIFO buffer for one of read/write is full at the
1656  * time of this call, the routine will wait until free FIFO buffer available for
1657  * continue processing.
1658  *
1659  * The function will return "-1" if errors or conditions causing the dispatcher
1660  * stop issuing the commands to both read and write masters before both read and
1661  * write command buffers are empty.
1662  *
1663  * Additional error information is available in the status bits of
1664  * each descriptor that the msgdma processed; it is the responsibility
1665  * of the user's application to search through the descriptor
1666  * to gather specific error information.
1667  *
1668  * Arguments:
1669  * - *dev: Pointer to msgdma device (instance) structure.
1670  * - *desc: Pointer to single (ready to run) descriptor.
1671  *
1672  * Returns:
1673  * - status: return 0 (success)
1674  *           return error (errors or conditions causing msgdma stop issuing
1675  *           	commands to masters)
1676  *           Suggest suggest checking the bit set in the error with CSR status
1677  *           	register.
1678  *           return -EPERM (operation not permitted due to descriptor type
1679  *		conflict)
1680  *           return -ETIME (Time out and skipping the looping after 5 msec)
1681  */
alt_msgdma_standard_descriptor_sync_transfer(alt_msgdma_dev * dev,alt_msgdma_standard_descriptor * desc)1682 int alt_msgdma_standard_descriptor_sync_transfer(
1683 	alt_msgdma_dev *dev,
1684 	alt_msgdma_standard_descriptor *desc)
1685 {
1686     return alt_msgdma_descriptor_sync_transfer(dev, desc, NULL);
1687 }
1688 
1689 /*
1690  * alt_msgdma_extended_descriptor_sync_transfer
1691  *
1692  * This function will start commencing a blocking transfer of one extended
1693  * descriptor at a time. If the FIFO buffer for one of read/write is full at the
1694  * time of this call, the routine will wait until free FIFO buffer available for
1695  * continue processing.
1696  *
1697  * The function will return "-1" if errors or conditions causing the dispatcher
1698  * stop issuing the commands to both read and write masters before both read and
1699  * write command buffers are empty.
1700  *
1701  * Additional error information is available in the status bits of
1702  * each descriptor that the msgdma processed; it is the responsibility
1703  * of the user's application to search through the descriptor
1704  * to gather specific error information.
1705  *
1706  *
1707  * Arguments:
1708  * - *dev: Pointer to msgdma device (instance) structure.
1709  * - *desc: Pointer to single (ready to run) descriptor.
1710  *
1711  * Returns:
1712  * - status: return 0 (success)
1713  *           return error (errors or conditions causing msgdma stop issuing
1714  *		commands to masters)
1715  *           Suggest suggest checking the bit set in the error with CSR status
1716  *		register.
1717  *           return -EPERM (operation not permitted due to descriptor type
1718  *		conflict)
1719  *           return -ETIME (Time out and skipping the looping after 5 msec)
1720  */
alt_msgdma_extended_descriptor_sync_transfer(alt_msgdma_dev * dev,alt_msgdma_extended_descriptor * desc)1721 int alt_msgdma_extended_descriptor_sync_transfer(
1722 	alt_msgdma_dev *dev,
1723 	alt_msgdma_extended_descriptor *desc)
1724 {
1725     return alt_msgdma_descriptor_sync_transfer(dev, NULL, desc);
1726 }
1727