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