1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Test commands File: cfe_dmtest.c
6 * A temporary sandbox for data mover test routines and commands.
8 *********************************************************************
10 * Copyright 2000,2001,2002,2003
11 * Broadcom Corporation. All rights reserved.
13 * This software is furnished under license and may be used and
14 * copied only in accordance with the following terms and
15 * conditions. Subject to these conditions, you may download,
16 * copy, install, use, modify and distribute modified or unmodified
17 * copies of this software in source and/or binary form. No title
18 * or ownership is transferred hereby.
20 * 1) Any source code used, modified or distributed must reproduce
21 * and retain this copyright notice and list of conditions
22 * as they appear in the source file.
24 * 2) No right is granted to use any trade name, trademark, or
25 * logo of Broadcom Corporation. The "Broadcom Corporation"
26 * name may not be used to endorse or promote products derived
27 * from this software without the prior written permission of
28 * Broadcom Corporation.
30 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
32 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
33 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
34 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
35 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
36 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
40 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
41 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
42 * THE POSSIBILITY OF SUCH DAMAGE.
43 ********************************************************************* */
47 #include "sb1250_defs.h"
48 #include "sb1250_regs.h"
49 #include "sb1250_int.h"
50 #include "sb1250_dma.h"
52 #define M_DM_DSCRA_THROTTLE _SB_MAKEMASK1(43)
57 #include "lib_types.h"
58 #include "lib_string.h"
59 #include "lib_malloc.h"
60 #include "lib_printf.h"
63 #include "ui_command.h"
64 #include "cfe_console.h"
65 #include "cfe_timer.h"
67 #include "cfe_devfuncs.h"
70 #include "lib_hssubr.h"
71 #include "addrspace.h"
73 #ifdef __long64 /* Temporary hack */
80 if (va
- K0BASE
>= 0 && va
- K0BASE
< K0SIZE
)
82 else if (va
- K1BASE
>= 0 && va
- K1BASE
< K1SIZE
)
85 pa
= XKPHYS_TO_PHYS(va
);
91 void dm_bzero(void *dest
, int cnt
);
92 void dm_bsink(void *src
, int cnt
);
93 void dm_bcopy(void *src
, void *dest
, int cnt
);
94 void dm_multibcopy(void *src
, void *dest
, int cnt
, int blksize
);
96 static uint64_t zb_hz
;
97 static uint64_t zb_mhz
;
99 static int ui_cmd_zero(ui_cmdline_t
*cmd
, int argc
, char *argv
[]);
100 static int ui_cmd_sink(ui_cmdline_t
*cmd
, int argc
, char *argv
[]);
101 static int ui_cmd_cpy(ui_cmdline_t
*cmd
, int argc
, char *argv
[]);
102 static int ui_cmd_mcpy(ui_cmdline_t
*cmd
, int argc
, char *argv
[]);
105 static int ui_cmd_testdm(ui_cmdline_t
*cmd
, int argc
, char *argv
[]);
106 static int ui_cmd_talkdm(ui_cmdline_t
*cmd
, int argc
, char *argv
[]);
108 int ui_init_testcmds2(void);
109 int ui_init_testcmds2(void)
111 zb_hz
= cfe_cpu_speed
/2;
112 zb_mhz
= (zb_hz
+ 500000)/1000000;
115 cmd_addcmd("test dm",
118 "Loop copying memory using the data mover",
119 "test dm [-v|-p] [-u] [-t] [-off] [dest src len]\n\n"
120 "This command continuously copies from source to destination\n "
121 " using the data mover and displays MB/s (times 10)",
122 "-p;Address is a physical address|"
123 "-v;Address is a (kernel) virtual address|"
124 "-u;Uncachable source and destination|"
132 "This command sends to the text demon using the\n "
133 " data mover and mailbox variables",
134 "-l;Use local addresses");
136 /* timing/utility commands */
140 "Read memory using the data mover",
141 "sink [-v|-p] [-u|-l2] [addr [len]]\n\n"
142 "This command reads a region of memory using the data\n"
143 "mover and discards the result.",
144 "-p;Address is a physical address|"
145 "-v;Address is a (kernel) virtual address|"
146 "-u;Uncachable source|"
147 "-l2;L2 allocate at source");
151 "Zero memory using the data mover",
152 "zero [-v|-p] [-u|-l2] [addr [len]]\n\n"
153 "This command clears a region of memory to zero using the\n"
155 "-p;Address is a physical address|"
156 "-v;Address is a (kernel) virtual address|"
157 "-u;Uncachable destination|"
158 "-l2;L2 allocate at destination");
162 "Copy memory using the data mover with multiple descriptors",
163 "cpy [-v|-p] [-u|-l2] dest src [[len] blksize]\n\n"
164 "This command copies from source to destination using the\n"
165 "data mover with blksize bytes per descriptor.",
166 "-p;Address is a physical address|"
167 "-v;Address is a (kernel) virtual address|"
168 "-u;Uncachable source and destination|"
169 "-l2;L2 allocate at destination");
173 "Copy memory using the data mover",
174 "cpy [-v|-p] [-u|-l2] dest src [len]\n\n"
175 "This command copies from source to destination using the\n"
177 "-p;Address is a physical address|"
178 "-v;Address is a (kernel) virtual address|"
179 "-u;Uncachable source and destination|"
180 "-l2;L2 allocate at destination");
187 #define dm_nextbuf(d,f) ((((d)->f+1) == (d)->dm_dscrring_end) ? \
188 (d)->dm_dscrring : (d)->f+1)
190 /* The following macro won't work with 64-bit virtual addresses. */
191 #define SBDMA_VTOP(x) ((uint64_t) K1_TO_PHYS((uint64_t)((unsigned long)(x))))
194 /* abbreviations for generating descriptors */
196 typedef uint64_t flags_t
;
198 #define SRCUNC M_DM_DSCRA_UN_SRC /* Source uncached */
199 #define SRCINC V_DM_DSCRA_DIR_SRC_INCR /* inc src ptr */
200 #define SRCDEC V_DM_DSCRA_DIR_SRC_DECR /* dec src ptr */
201 #define SRCCON V_DM_DSCRA_DIR_SRC_CONST /* src ptr constant */
203 #define DSTUNC M_DM_DSCRA_UN_DEST /* Dest uncached */
204 #define DSTINC V_DM_DSCRA_DIR_DEST_INCR /* inc dest ptr */
205 #define DSTDEC V_DM_DSCRA_DIR_DEST_DECR /* dec dest ptr */
206 #define DSTCON V_DM_DSCRA_DIR_DEST_CONST /* dest ptr constant */
208 #define ZEROMEM M_DM_DSCRA_ZERO_MEM /* just zero dest */
209 #define PREFETCH M_DM_DSCRA_PREFETCH /* don't write dest */
210 #define L2CDEST M_DM_DSCRA_L2C_DEST /* dest l2 cacheable */
211 #define L2CSRC M_DM_DSCRA_L2C_SRC /* src l2 cacheable */
213 /* NB: THROTTLE is defined only for pass 1 parts. */
214 #define THROTTLE M_DM_DSCRA_THROTTLE /* throttle DMA */
216 #ifdef _SBDMA_INTERRUPTS_
217 #define INTER M_DM_DSCRA_INTERRUPT /* int on dscr done */
223 typedef uint32_t sbport_t
;
224 typedef uint64_t sbphysaddr_t
;
226 typedef struct sbdmadscr_s
{
231 typedef struct sbgendma_s
{
232 int ch
; /* channel number */
234 void *dm_dscrmem
; /* Memory for descriptor list */
236 sbport_t dm_dscrbase
; /* Descriptor base address */
237 sbport_t dm_dscrcnt
; /* Descriptor count register */
238 sbport_t dm_curdscr
; /* current descriptor address */
240 sbdmadscr_t
*dm_dscrring
; /* base of descriptor table */
241 sbdmadscr_t
*dm_dscrring_end
; /* end of descriptor table */
243 sbphysaddr_t dm_dscrring_phys
; /* and also the phys addr */
244 sbdmadscr_t
*dm_addptr
; /* next dscr for sw to add */
245 sbdmadscr_t
*dm_remptr
; /* next dscr for sw to remove */
247 /* number of descriptors we have not told the hardware about yet. */
254 #define DM_READCSR(x) SBREADCSR(x)
255 #define DM_WRITECSR(x,y) SBWRITECSR(x,y)
257 static sbgendma_t sbgendma_ctx
[DM_NUM_CHANNELS
];
259 /* Channel allocation:
260 0 utility commands that use the data mover (foreground)
261 1 data mover test loop (background)
262 2 talk command (background)
263 3 data mover multicopy (foreground)
266 #define SBDMA_CMD_CH 0
267 #define SBDMA_TEST_CH 1
268 #define SBDMA_TALK_CH 2
269 #define SBDMA_MCMD_CH 3
272 static int sbgendma_initialized
= 0;
275 /* For Pass 1, dedicate an SCD peformance counter to use as a counter
277 #include "sb1250_scd.h"
278 #define ZCTR_MODULUS 0x10000000000LL
280 /* The counter is a shared resource that must be reset periodically
281 since it doesn't roll over. Furthermore, there is a pass one bug
282 that makes the interrupt unreliable and the final value either all
283 ones or all zeros. We therefore reset the count when it exceeds
284 half the modulus. We also assume that intervals of interest
285 are much less than half the modulus and attempt to adjust for
286 the reset in zclk_elapsed. */
289 zclk_init(uint64_t val
)
291 *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0
)) = val
;
292 *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_CFG
)) =
293 V_SPC_CFG_SRC0(1) | M_SPC_CFG_ENABLE
;
301 ticks
= *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0
));
302 if (ticks
== 0 || ticks
== ZCTR_MODULUS
-1) {
306 else if (ticks
>= ZCTR_MODULUS
/2) {
307 ticks
-= ZCTR_MODULUS
/2;
308 zclk_init(ticks
); /* Ignore the fudge and lose a few ticks */
314 zclk_elapsed(uint64_t stop
, uint64_t start
)
316 return ((stop
>= start
) ? stop
: stop
+ ZCTR_MODULUS
/2) - start
;
320 /* *********************************************************************
323 * Process "completed" buffers on the specified DMA channel.
324 * This is normally called within the interrupt service routine.
325 * Note that this isn't really ideal for priority channels, since
326 * it processes all of the packets on a given channel before
330 * d - DMA channel context
333 * number of packets processed.
334 ********************************************************************* */
336 dm_procbuffers(sbgendma_t
*d
)
343 /* Figure out where we are (as an index) and where
344 the hardware is (also as an index)
346 This could be done faster if (for example) the
347 descriptor table was page-aligned and contiguous in
348 both virtual and physical memory -- you could then
349 just compare the low-order bits of the virtual address
350 (dm_remptr) and the physical address (dm_curdscr CSR) */
352 curidx
= d
->dm_remptr
- d
->dm_dscrring
;
353 hwidx
= ((DM_READCSR(d
->dm_curdscr
) & M_DM_CUR_DSCR_DSCR_ADDR
) -
354 d
->dm_dscrring_phys
) / sizeof(sbdmadscr_t
);
356 /* If they're the same, we've processed all of the descriptors
362 /* Otherwise, issue the upcall, or do whatever we want to do
363 to indicate to the client program that the operation is
364 complete (not used here). */
368 /* .. and advance to the next buffer. */
370 d
->dm_remptr
= dm_nextbuf(d
, dm_remptr
);
377 /* *********************************************************************
378 * DM_ADDDESCR(d,newdsc,n)
380 * Add a descriptor to the specified DMA channel.
383 * d - DMA channel descriptor
384 * newdsc - pointer to descriptor
385 * n - number of descriptors to add
388 * number of descriptors actually added
389 ********************************************************************* */
391 dm_adddescr(sbgendma_t
*d
, sbdmadscr_t
*newdsc
, int n
)
394 sbdmadscr_t
*nextdsc
;
400 nextdsc
= dm_nextbuf(d
, dm_addptr
);
402 /* Test whether the ring is full (next == remptr) */
404 if (nextdsc
== d
->dm_remptr
) {
408 dsc
->dscr_a
= newdsc
->dscr_a
;
409 dsc
->dscr_b
= newdsc
->dscr_b
;
411 d
->dm_addptr
= nextdsc
;
424 /* *********************************************************************
427 * Start DMA on the specified channel, queueing all descriptors
428 * that we have added with dm_adddescr()
434 * start time (zbclks)
435 ********************************************************************* */
437 dm_start(sbgendma_t
*d
)
443 DM_WRITECSR(d
->dm_dscrcnt
, d
->dm_newcnt
);
451 #ifdef _SBDMA_INTERRUPTS_
452 /* *********************************************************************
455 * "interrupt" routine for a given channel
458 * ctx - DMA channel context
462 ********************************************************************* */
464 dm_interrupt(void *ctx
)
466 sbgendma_t
*d
= (sbgendma_t
*)ctx
;
468 /* Clear the interrupt (better in procbuffers? */
469 (void) DM_READCSR(d
->dm_dscrbase
);
473 if (G_DM_CUR_DSCR_DSCR_COUNT(DM_READCSR(d
->dm_curdscr
)) == 0)
478 /* *********************************************************************
481 * Returns TRUE if all descriptors on the specified channel
488 * 1 if all descriptors are processed (none pending in hw)
489 * 0 if there are still some descriptors in progress
490 ********************************************************************* */
492 dm_isdone(sbgendma_t
*d
)
494 cfe_irq_poll(NULL
); /* avoid full bg poll if timing */
496 return (d
->dm_busy
== 0);
500 /* *********************************************************************
503 * Returns elapsed zb clks when an interrupt becomes pending on
504 * the channel and also processes the interrupt.
505 * CAUTION: spins forever if misused.
512 ********************************************************************* */
514 #define IMR_POINTER(cpu,reg) \
515 ((volatile uint64_t *)(PHYS_TO_K1(A_IMR_REGISTER(cpu,reg))))
516 extern int32_t _getcause(void); /* return value of CP0 CAUSE */
519 dm_wait(sbgendma_t
*d
)
521 uint64_t mask
= (1LL << (K_INT_DM_CH_0
+ d
->ch
));
522 volatile uint64_t *status
= IMR_POINTER(0, R_IMR_INTERRUPT_SOURCE_STATUS
);
526 while ((_getcause() & M_CAUSE_IP2
) == 0)
528 if ((*status
& mask
) != 0)
536 while (!dm_isdone(d
))
541 #else /* !_SBDMA_INTERRUPTS_ */
543 /* *********************************************************************
546 * Returns TRUE if all descriptors on the specified channel
553 * 1 if all descriptors are processed (none pending in hw)
554 * 0 if there are still some descriptors in progress
555 ********************************************************************* */
557 dm_isdone(sbgendma_t
*d
)
559 #ifdef _SBDMA_TEST_PTRS_
563 /* If polling, now is a good time to process finished descriptors. */
567 /* Test for DMA complete. There are two ways to do this, to use
568 the same technique the interrupt routine uses and compare the
569 pointers to the descriptor tables, or we can use the count.
570 Both methods are shown below. */
572 #ifdef _SBDMA_TEST_PTRS_
573 curidx
= d
->dm_addptr
- d
->dm_dscrring
;
574 hwidx
= ((DM_READCSR(d
->dm_curdscr
) & M_DM_CUR_DSCR_DSCR_ADDR
) -
575 d
->dm_dscrring_phys
) / sizeof(sbdmadscr_t
);
576 return (curidx
== hwidx
);
578 return (G_DM_CUR_DSCR_DSCR_COUNT(DM_READCSR(d
->dm_curdscr
)) == 0);
583 /* *********************************************************************
586 * Returns elapsed zb clks when an interrupt becomes pending on
587 * the channel and also processes the interrupt.
588 * CAUTION: spins forever if misused.
595 ********************************************************************* */
598 dm_wait(sbgendma_t
*d
)
602 while (!dm_isdone(d
))
609 #endif /* !_SBDMA_INTERRUPTS_ */
612 /* *********************************************************************
613 * DM_BUILDDESCR_P(dsc,dest,src,len,flags)
615 * Builds a descriptor.
618 * dsc - pointer to descriptor to build
619 * dest - destination address (physical)
620 * src - source address (physical)
621 * len - number of bytes to transfer
622 * flags - flags for transfer
626 ********************************************************************* */
628 dm_builddescr_p(sbdmadscr_t
*dsc
, uint64_t dest
, uint64_t src
,
629 int len
, flags_t flags
)
631 dsc
->dscr_a
= dest
| flags
;
632 dsc
->dscr_b
= src
| V_DM_DSCRB_SRC_LENGTH(len
);
636 #define CACHE_ALIGN(x, t) ((t)(((unsigned long)(x) + 31) & ~31))
638 /* *********************************************************************
639 * DM_ALLOCDSCRS(count)
641 * Allocates dynamic storage for a descriptor ring
644 * cnt - number of descriptors
647 * pointer to the allocated space (use only cache-aligned slots)
648 ********************************************************************* */
650 dm_allocdscrs(int cnt
)
652 /* Allocate with enough fudge to cache-align. */
653 return KMALLOC(cnt
* sizeof(sbdmadscr_t
) + 32, 0);
657 /* *********************************************************************
658 * DM_INITCTX(ch,n,priority)
660 * Initialize a generic DMA context - this structure describes
661 * the hardware and software state for the device driver.
664 * ch - channel number (0..3)
665 * n - desired number of available descriptors
666 * (ring size is n+1 to distinguish full/empty cases)
667 * priority - priority for this channel (K_DM_DSCR_BASE_PRIORITY_x)
671 ********************************************************************* */
673 dm_initctx(int ch
, int n
, int priority
)
678 /* Initialize the fields in the DMA controller's context. */
680 d
= &sbgendma_ctx
[ch
];
683 d
->dm_dscrbase
= (sbport_t
) A_DM_REGISTER(ch
, R_DM_DSCR_BASE
);
684 d
->dm_dscrcnt
= (sbport_t
) A_DM_REGISTER(ch
, R_DM_DSCR_COUNT
);
685 d
->dm_curdscr
= (sbport_t
) A_DM_REGISTER(ch
, R_DM_CUR_DSCR_ADDR
);
687 /* Initialize the pointers to the DMA descriptor ring. */
689 d
->dm_dscrmem
= dm_allocdscrs(n
+1);
691 d
->dm_dscrring
= CACHE_ALIGN(d
->dm_dscrmem
, sbdmadscr_t
*);
692 d
->dm_dscrring_end
= d
->dm_dscrring
+ (n
+1);
694 d
->dm_addptr
= d
->dm_dscrring
;
695 d
->dm_remptr
= d
->dm_dscrring
;
700 /* Calculate the physical address of the start of the descriptor
701 ring. We need this for determining when the pointers wrap. */
703 d
->dm_dscrring_phys
= (sbphysaddr_t
) SBDMA_VTOP(d
->dm_dscrring
);
705 /* Finally, set up the DMA controller. */
707 base
= d
->dm_dscrring_phys
|
708 V_DM_DSCR_BASE_PRIORITY(priority
) |
709 V_DM_DSCR_BASE_RINGSZ(n
+1);
710 DM_WRITECSR(d
->dm_dscrbase
, base
);
711 (void)DM_READCSR(d
->dm_dscrbase
); /* push */
713 base
= d
->dm_dscrring_phys
|
714 V_DM_DSCR_BASE_PRIORITY(priority
) |
715 V_DM_DSCR_BASE_RINGSZ(n
+1) |
716 M_DM_DSCR_BASE_RESET
; /* disable and reset */
717 DM_WRITECSR(d
->dm_dscrbase
, base
);
718 (void)DM_READCSR(d
->dm_dscrbase
); /* push */
720 base
= d
->dm_dscrring_phys
|
721 V_DM_DSCR_BASE_PRIORITY(priority
) |
722 V_DM_DSCR_BASE_RINGSZ(n
+1) |
723 M_DM_DSCR_BASE_ENABL
; /* enable */
724 DM_WRITECSR(d
->dm_dscrbase
, base
);
728 /* *********************************************************************
731 * Finalize a generic DMA context - this structure describes
732 * the hardware and software state for the device driver.
735 * ch - channel number (0..3)
739 ********************************************************************* */
746 /* Finalize the fields in the DMA controller's context. */
748 d
= &sbgendma_ctx
[ch
];
750 if (d
->dm_dscrmem
!= NULL
) {
751 KFREE(d
->dm_dscrmem
);
753 d
->dm_dscrmem
= NULL
;
755 d
->dm_dscrring
= NULL
;
756 d
->dm_dscrring_end
= NULL
;
764 d
->dm_dscrring_phys
= (sbphysaddr_t
) 0;
765 base
= d
->dm_dscrring_phys
;
766 DM_WRITECSR(d
->dm_dscrbase
, base
);
767 (void)DM_READCSR(d
->dm_dscrbase
); /* push */
769 DM_WRITECSR(d
->dm_dscrbase
, base
| M_DM_DSCR_BASE_RESET
);
773 /* *********************************************************************
774 * DM_STARTONE(ch,dscr)
776 * Start a single descriptor
779 * ch - DMA channel number.
780 * dscr - descriptor to run
783 * start time (zbclks)
784 ********************************************************************* */
786 dm_startone(int ch
, sbdmadscr_t
*dscr
)
788 sbgendma_t
*d
= &sbgendma_ctx
[ch
];
790 /* Try to put it on the queue. If this doesn't work, call the
791 polling function until we get space. This can happen if the
792 ring is full when we attempt to add a descriptor, which is very
793 unlikely in this test program. */
796 if (dm_adddescr(d
, dscr
, 1) == 1) {
807 /* *********************************************************************
810 * Run a single descriptor, waiting until it completes before
811 * returning to the calling program.
814 * ch - DMA channel number.
815 * dscr - descriptor to run
818 * elapsed time (zbclks)
819 ********************************************************************* */
821 dm_runone(int ch
, sbdmadscr_t
*dscr
)
823 sbgendma_t
*d
= &sbgendma_ctx
[ch
];
824 uint64_t start
, stop
;
826 start
= dm_startone(ch
, dscr
);
829 return zclk_elapsed(stop
, start
);
833 /* *********************************************************************
836 * Reset and initialize global data structures.
843 ********************************************************************* */
850 for (ch
= 0; ch
< DM_NUM_CHANNELS
; ch
++) {
851 dscrbase_p
= (sbport_t
) A_DM_REGISTER(ch
, R_DM_DSCR_BASE
);
852 DM_WRITECSR(dscrbase_p
, M_DM_DSCR_BASE_RESET
);
855 for (ch
= 0; ch
< DM_NUM_CHANNELS
; ch
++) {
856 dscrbase_p
= (sbport_t
) A_DM_REGISTER(ch
, R_DM_DSCR_BASE
);
857 while (DM_READCSR(dscrbase_p
) && M_DM_DSCR_BASE_ACTIVE
) {
865 /* *********************************************************************
868 * Initialize global data structures if necessary.
875 ********************************************************************* */
879 if (!sbgendma_initialized
) {
882 zclk_init(0); /* Time origin is arbitrary */
884 dm_initctx(SBDMA_CMD_CH
, 1, K_DM_DSCR_BASE_PRIORITY_1
);
885 #ifdef _SBDMA_INTERRUPTS_
886 cfe_request_irq(K_INT_DM_CH_0
+ SBDMA_CMD_CH
,
887 dm_interrupt
, &sbgendma_ctx
[SBDMA_CMD_CH
], 0, 0);
888 #endif /* _SBDMA_INTERRUPTS_ */
890 sbgendma_initialized
= 1;
895 /* *********************************************************************
898 * Initialize global data structures, if necessary.
901 * flush - flush caches first (for timing)
905 ********************************************************************* */
907 dm_cmd_init(int flush
)
916 /* *********************************************************************
917 * DM_BCOPY_P(src,dest,cnt,flags)
919 * This is an example implementation of "bcopy" that uses
923 * ch - DMA channel number.
924 * src - source physical address
925 * dest - destination physical address
926 * cnt - count of bytes to copy
927 * flags - option flags
930 * elapsed time (zbclks)
931 ********************************************************************* */
933 dm_bcopy_p(int ch
, long src
, long dest
, int cnt
, flags_t flags
)
937 if ((unsigned long)src
< (unsigned long)dest
938 && (unsigned long)(src
+ cnt
) > (unsigned long)dest
) {
939 flags
|= SRCDEC
|DSTDEC
;
944 flags
|= SRCINC
|DSTINC
;
947 dm_builddescr_p(&dscr
, dest
, src
, cnt
, flags
|INTER
);
948 return dm_runone(ch
, &dscr
);
952 /* *********************************************************************
953 * DM_BCOPY(src,dest,cnt)
955 * This is an example implementation of "bcopy" that uses
959 * src - source virtual address
960 * dest - destination virtual address
961 * cnt - count of bytes to copy
965 ********************************************************************* */
967 dm_bcopy(void *src
, void *dest
, int cnt
)
969 dm_bcopy_p(SBDMA_CMD_CH
, phys_addr((long)src
), phys_addr((long)dest
), cnt
, 0);
973 /* *********************************************************************
974 * DM_MULTIBCOPY_P(ch,src,dest,cnt,flags)
977 * ch - DMA channel number.
978 * src - source physical address
979 * dest - destination physical address
980 * cnt - count of bytes to copy
981 * step - maximum bytes per descriptor
982 * flags - option flags
985 * elapsed time (zbclks)
986 ********************************************************************* */
988 dm_multibcopy_p(int ch
, long src
, long dest
, int cnt
, int step
, flags_t flags
)
990 sbgendma_t
*d
= &sbgendma_ctx
[ch
];
993 uint64_t start
, stop
;
995 dnum
= (cnt
+ (step
-1))/step
;
1000 flags
|= SRCINC
|DSTINC
;
1003 dm_initctx(ch
, dnum
, K_DM_DSCR_BASE_PRIORITY_1
);
1004 #ifdef _SBDMA_INTERRUPTS_
1005 cfe_request_irq(K_INT_DM_CH_0
+ ch
, dm_interrupt
, d
, 0, 0);
1009 int n
= (cnt
< step
? cnt
: step
);
1014 dm_builddescr_p(&dscr
, dest
, src
, n
, flags
);
1015 dm_adddescr(d
, &dscr
, 1);
1021 start
= dm_start(d
);
1024 cfe_free_irq(K_INT_DM_CH_0
+ ch
, 0);
1027 return zclk_elapsed(stop
, start
);
1030 /* *********************************************************************
1031 * DM_MULTIBCOPY(src,dest,cnt)
1033 * This is a variant of BCOPY that queues up several descriptors to
1037 * src - source virtual address
1038 * dest - destination virtual address
1039 * len - count of bytes to copy
1040 * blksize - maximum bytes per descriptor
1044 ********************************************************************* */
1046 dm_multibcopy(void *src
, void *dest
, int len
, int blksize
)
1048 dm_multibcopy_p(SBDMA_CMD_CH
, phys_addr((long) src
), phys_addr((long) dest
),
1053 /* *********************************************************************
1054 * DM_BZERO_P(dest,cnt,flags)
1057 * ch - DMA channel number.
1058 * dest - physical address
1059 * cnt - count of bytes to zero
1060 * flags - option flags
1063 * elapsed time (zbclks)
1064 ********************************************************************* */
1066 dm_bzero_p(int ch
, long dest
, int cnt
, flags_t flags
)
1070 flags
|= SRCCON
|ZEROMEM
|DSTINC
;
1071 dm_builddescr_p(&dscr
, dest
, 0, cnt
, flags
|INTER
);
1072 return dm_runone(ch
, &dscr
);
1075 /* *********************************************************************
1076 * DM_BZERO(dest,cnt)
1078 * This is an example implementation of "bzero" that uses
1082 * dest - destination virtual address
1083 * cnt - count of bytes to zero
1087 ********************************************************************* */
1089 dm_bzero(void *dest
, int cnt
)
1091 dm_bzero_p(SBDMA_CMD_CH
, phys_addr((long) dest
), cnt
, 0);
1095 /* *********************************************************************
1096 * DM_BSINK_P(ch,src,cnt,flags)
1099 * ch - DMA channel number.
1100 * src - physical address
1101 * cnt - count of bytes to read
1102 * flags - option flags
1105 * elapsed time (zbclks)
1106 ********************************************************************* */
1108 dm_bsink_p(int ch
, long src
, int cnt
, flags_t flags
)
1112 flags
|= SRCINC
|PREFETCH
|DSTCON
;
1113 dm_builddescr_p(&dscr
, 0, src
, cnt
, flags
|INTER
);
1114 return dm_runone(ch
, &dscr
);
1117 /* *********************************************************************
1121 * src - physical address
1122 * cnt - count of bytes to read
1126 ********************************************************************* */
1128 dm_bsink(void *src
, int cnt
)
1130 dm_bsink_p(SBDMA_CMD_CH
, phys_addr((long) src
), cnt
, 0);
1134 /* Address parsing adapted from ui_examcmds. */
1136 #define ATYPE_TYPE_NONE 0
1137 #define ATYPE_TYPE_PHYS 1
1138 #define ATYPE_TYPE_VIRT 2
1139 #define ATYPE_TYPE_MASK (ATYPE_TYPE_PHYS | ATYPE_TYPE_VIRT)
1142 getaddrarg(ui_cmdline_t
*cmd
, int arg
, long *addr
, int *atype
)
1149 *atype
&= ~ATYPE_TYPE_MASK
;
1150 *atype
|= ATYPE_TYPE_NONE
;
1152 if (cmd_sw_isset(cmd
, "-p")) {
1153 *atype
|= ATYPE_TYPE_PHYS
;
1155 else if (cmd_sw_isset(cmd
, "-v")) {
1156 *atype
|= ATYPE_TYPE_VIRT
;
1159 *atype
|= ATYPE_TYPE_VIRT
; /* best default? */
1164 char *x
= cmd_getarg(cmd
, arg
);
1168 /* Following gdb, we Make 64-bit addresses expressed as
1169 8-digit numbers sign extend automagically. Saves
1170 typing, but is very gross. */
1172 longaddr
= strlen(x
);
1173 if (memcmp(x
, "0x", 2) == 0) longaddr
-= 2;
1175 *addr
= (longaddr
> 8) ? (long) xtoq(x
) : (long) xtoi(x
);
1184 getlenarg(ui_cmdline_t
*cmd
, int arg
, size_t *len
)
1191 char *x
= cmd_getarg(cmd
, arg
);
1195 *len
= (size_t) xtoi(x
);
1203 show_rate(size_t len
, uint64_t elapsed
)
1208 if (elapsed
== 0) elapsed
= 1; /* zbclk always 0 in the simulator */
1210 rate
= ((uint64_t)len
* zb_mhz
* 10L)/elapsed
;
1211 sprintf(digits
, "%04d", rate
);
1213 printf("%3d.%1d MB/s\n", rate
/10L, rate
%10L);
1218 ui_cmd_zero(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
1226 getaddrarg(cmd
, 0, &dest
, &dtype
);
1227 getlenarg(cmd
, 1, &len
);
1228 if (cmd_sw_isset(cmd
, "-u"))
1230 else if (cmd_sw_isset(cmd
, "-l2"))
1233 if ((dtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1234 dest
= phys_addr(dest
);
1236 if (len
> 0x100000) len
= 0x100000;
1238 dm_cmd_init((flags
& DSTUNC
) != DSTUNC
);
1240 elapsed
= dm_bzero_p(SBDMA_CMD_CH
, dest
, len
, flags
);
1242 show_rate(len
, elapsed
);
1248 ui_cmd_sink(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
1256 getaddrarg(cmd
, 0, &src
, &stype
);
1257 getlenarg(cmd
, 1, &len
);
1258 if (cmd_sw_isset(cmd
, "-u"))
1260 else if (cmd_sw_isset(cmd
, "-l2"))
1263 if ((stype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1264 src
= phys_addr(src
);
1266 if (len
> 0x100000) len
= 0x100000;
1268 dm_cmd_init((flags
& SRCUNC
) != SRCUNC
);
1270 elapsed
= dm_bsink_p(SBDMA_CMD_CH
, src
, len
, flags
);
1272 show_rate(len
, elapsed
);
1278 ui_cmd_cpy(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
1286 getaddrarg(cmd
, 0, &dest
, &dtype
);
1287 getaddrarg(cmd
, 1, &src
, &stype
);
1288 getlenarg(cmd
, 2, &len
);
1289 if (cmd_sw_isset(cmd
, "-u"))
1290 flags
|= SRCUNC
|DSTUNC
;
1291 else if (cmd_sw_isset(cmd
, "-l2"))
1294 if ((dtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1295 dest
= phys_addr(dest
);
1296 if ((stype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1297 src
= phys_addr(src
);
1299 if (len
> 0x100000) len
= 0x100000;
1301 dm_cmd_init((flags
& (SRCUNC
|DSTUNC
)) != (SRCUNC
|DSTUNC
));
1303 elapsed
= dm_bcopy_p(SBDMA_CMD_CH
, src
, dest
, len
, flags
);
1305 show_rate(len
, elapsed
);
1310 ui_cmd_mcpy(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
1314 size_t len
, blksize
;
1318 getaddrarg(cmd
, 0, &dest
, &dtype
);
1319 getaddrarg(cmd
, 1, &src
, &stype
);
1320 getlenarg(cmd
, 2, &len
);
1321 getlenarg(cmd
, 3, &blksize
);
1322 if (cmd_sw_isset(cmd
, "-u"))
1323 flags
|= SRCUNC
|DSTUNC
;
1324 else if (cmd_sw_isset(cmd
, "-l2"))
1327 if ((dtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1328 dest
= phys_addr(dest
);
1329 if ((stype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1330 src
= phys_addr(src
);
1332 dm_cmd_init((flags
& (SRCUNC
|DSTUNC
)) != (SRCUNC
|DSTUNC
));
1335 elapsed
= dm_bcopy_p(SBDMA_CMD_CH
, src
, dest
, len
, flags
);
1337 elapsed
= dm_multibcopy_p(SBDMA_MCMD_CH
, src
, dest
, len
, blksize
, flags
);
1339 show_rate(len
, elapsed
);
1344 /* *********************************************************************
1354 ********************************************************************* */
1356 #ifdef _SBDMA_INTERRUPTS_
1360 typedef struct sbgendma_args_s
{
1368 uint64_t delta
[N_SAMPLES
];
1375 dm_restart(sbgendma_args_t
*args
)
1379 dm_builddescr_p(&dscr
, args
->dest
, args
->src
, args
->len
, args
->flags
);
1381 args
->start
= dm_startone(args
->ch
, &dscr
);
1385 dm_interrupt_loop(void *ctx
)
1387 sbgendma_args_t
*args
= (sbgendma_args_t
*)ctx
;
1388 sbgendma_t
*d
= &sbgendma_ctx
[args
->ch
];
1390 /* Clear the interrupt (better in procbuffers? */
1391 (void) DM_READCSR(d
->dm_dscrbase
);
1395 if (G_DM_CUR_DSCR_DSCR_COUNT(DM_READCSR(d
->dm_curdscr
)) == 0) {
1396 uint64_t start
, now
;
1400 start
= args
->start
;
1404 if (args
->len
== 0) {
1406 cfe_free_irq(K_INT_DM_CH_0
+ args
->ch
, 0);
1407 dm_uninitctx(args
->ch
);
1413 args
->delta
[args
->index
] = zclk_elapsed(now
, start
);
1414 args
->index
= (args
->index
+ 1) % N_SAMPLES
;
1416 if (zclk_elapsed(now
, args
->last
) > zb_hz
/4) {
1422 for (i
= 0; i
< N_SAMPLES
; i
++)
1423 avg
+= args
->delta
[i
];
1425 rate
= ((uint64_t)(args
->len
) * zb_mhz
* 10L)/avg
;
1426 sprintf(digits
, "%04d", rate
);
1428 #define WRITECSR(csr,val) *((volatile uint64_t *) (csr)) = (val)
1431 WRITECSR(PHYS_TO_K1(A_GPIO_PIN_SET
), M_GPIO_DEBUG_LED
);
1433 WRITECSR(PHYS_TO_K1(A_GPIO_PIN_CLR
), M_GPIO_DEBUG_LED
);
1435 if (args
->count
% (5*60*4) == 0)
1436 xprintf("%ld\n", args
->count
/(60*4));
1446 static sbgendma_args_t
*test_args
[DM_NUM_CHANNELS
] = {
1447 NULL
, NULL
, NULL
, NULL
1451 ui_cmd_testdm(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
1457 sbgendma_args_t
*args
;
1458 int ch
= SBDMA_TEST_CH
; /* always single channel for now */
1462 /* OK values for demos */
1463 dest
= 0xE000120000LL
;
1464 src
= 0x0000020000LL
;
1468 getaddrarg(cmd
, 0, &dest
, &dtype
);
1469 getaddrarg(cmd
, 1, &src
, &stype
);
1470 getlenarg(cmd
, 2, &len
);
1471 if (cmd_sw_isset(cmd
, "-u"))
1472 flags
|= SRCUNC
|DSTUNC
;
1473 if (cmd_sw_isset(cmd
, "-t"))
1476 if ((dtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1477 dest
= phys_addr(dest
);
1478 if ((stype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1479 src
= phys_addr(src
);
1482 if (cmd_sw_isset(cmd
, "-off"))
1485 if ((unsigned long)src
< (unsigned long)dest
1486 && (unsigned long)(src
+ len
) > (unsigned long)dest
) {
1487 flags
|= SRCDEC
|DSTDEC
;
1492 flags
|= SRCINC
|DSTINC
;
1495 args
= test_args
[ch
];
1497 args
= (sbgendma_args_t
*)KMALLOC(sizeof(sbgendma_args_t
), 0);
1503 test_args
[ch
] = args
;
1509 args
->flags
= flags
|INTER
;
1511 for (i
= 0; i
< N_SAMPLES
; i
++)
1518 if (!args
->enabled
&& len
!= 0) {
1519 dm_initctx(args
->ch
, 1, K_DM_DSCR_BASE_PRIORITY_1
);
1520 cfe_request_irq(K_INT_DM_CH_0
+ args
->ch
,
1521 dm_interrupt_loop
, args
, 0, 0);
1524 args
->last
= zclk_get();
1530 #else /* !_SBDMA_INTERRUPTS_ */
1533 ui_cmd_testdm(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
1539 uint64_t now
, elapsed
;
1544 getaddrarg(cmd
, 0, &dest
, &dtype
);
1545 getaddrarg(cmd
, 1, &src
, &stype
);
1546 getlenarg(cmd
, 2, &len
);
1547 if (cmd_sw_isset(cmd
, "-u"))
1548 flags
|= SRCUNC
|DSTUNC
;
1550 if ((dtype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1551 dest
= phys_addr(dest
);
1552 if ((stype
& ATYPE_TYPE_MASK
) == ATYPE_TYPE_VIRT
)
1553 src
= phys_addr(src
);
1557 printf("Press ENTER to stop timing\n");
1559 dm_cmd_init((flags
& (SRCUNC
|DSTUNC
)) != (SRCUNC
|DSTUNC
));
1560 dm_initctx(SBDMA_TEST_CH
, 1, K_DM_DSCR_BASE_PRIORITY_1
);
1563 elapsed
= dm_bcopy_p(SBDMA_TEST_CH
, src
, dest
, len
, flags
);
1566 if (zclk_elapsed(now
, last
) > zb_hz
/4) {
1568 rate
= ((uint64_t)len
* zb_mhz
* 10L)/elapsed
;
1569 sprintf(digits
, "%04d", rate
);
1573 } while (!console_status());
1575 dm_uninitctx(SBDMA_TEST_CH
);
1578 #endif /* !_SBDMA_INTERRUPTS_ */
1583 /* The communication area */
1585 #define SBDMA_REMOTEP(x) ((uint64_t)(x) | 0xe000000000LL)
1587 /* Using physical address 0x10000 as the mailbox base is arbitrary but
1588 compatible with CFE. */
1589 #define MBOX_PADDR 0x10000
1590 #define BUFFER_PADDR (MBOX_PADDR + sizeof(int))
1592 #define BUFFER_SIZE 200
1594 static int listener
= 0;
1597 cfe_recvdm(void *arg
)
1599 /* always use the local values */
1600 volatile int *mailbox
= (volatile int *) PHYS_TO_K1(MBOX_PADDR
);
1601 volatile char *rx_buffer
= (volatile char *) PHYS_TO_K1(BUFFER_PADDR
);
1606 for (len
= 0; len
< BUFFER_SIZE
-1 && rx_buffer
[len
] != '\000'; len
++)
1608 rx_buffer
[len
] = '\000';
1609 console_write("[", 1);
1610 console_write((char *)rx_buffer
, len
);
1611 console_write("]\r\n", 3);
1617 ui_cmd_talkdm(ui_cmdline_t
*cmd
, int argc
, char *argv
[])
1619 volatile int *mailbox
;
1620 char tx_buffer
[BUFFER_SIZE
];
1623 int local
= cmd_sw_isset(cmd
, "-l");
1624 static char prompt
[] = "Enter text, exit with \"!<ENTER>\"\r\n";
1627 *((volatile int *) PHYS_TO_K1(MBOX_PADDR
)) = 0;
1628 cfe_bg_add(cfe_recvdm
, NULL
);
1632 src
= K0_TO_PHYS((uint64_t)tx_buffer
);
1634 mailbox
= (volatile int *) PHYS_TO_K1 (MBOX_PADDR
);
1638 mailbox
= (volatile int *)
1639 PHYS_TO_XKSEG_UNCACHED (SBDMA_REMOTEP(MBOX_PADDR
));
1640 dst
= SBDMA_REMOTEP(BUFFER_PADDR
);
1644 dm_initctx(SBDMA_TALK_CH
, 1, K_DM_DSCR_BASE_PRIORITY_1
);
1645 #ifdef _SBDMA_INTERRUPTS_
1646 cfe_request_irq(K_INT_DM_CH_0
+ SBDMA_TALK_CH
,
1647 dm_interrupt
, &sbgendma_ctx
[SBDMA_TALK_CH
], 0, 0);
1648 #endif /* _SBDMA_INTERRUPTS_ */
1650 console_write(prompt
, strlen(prompt
));
1653 tx_len
= console_readline("", tx_buffer
, BUFFER_SIZE
-1);
1655 if (tx_len
== 1 && tx_buffer
[0] == '!') {
1656 console_write("bye\r\n", 5);
1660 tx_buffer
[tx_len
] = '\000';
1662 while (*mailbox
== 1)
1665 dm_bcopy_p(SBDMA_TALK_CH
, src
, dst
, tx_len
+1, 0);
1668 while (*mailbox
== 1)
1672 #ifdef _SBDMA_INTERRUPTS_
1673 cfe_free_irq(K_INT_DM_CH_0
+ SBDMA_TALK_CH
, 0);
1675 dm_uninitctx(SBDMA_TALK_CH
);
1680 #else /* ! __long64 */
1681 int ui_init_testcmds2(void);
1682 int ui_init_testcmds2(void)
1686 #endif /* __long64 */