1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - library - dsp
3 File: dsp_if.c
4
5 Copyright 2007-2009 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2010-01-12#$
14 $Rev: 11277 $
15 $Author: kakemizu_hironori $
16 *---------------------------------------------------------------------------*/
17 #include <twl.h>
18 #include <twl/dsp.h>
19
20 #include <dsp_coff.h>
21 #include "dsp_process.h"
22
23 /*---------------------------------------------------------------------------*
24 Constant definitions
25 *---------------------------------------------------------------------------*/
26
27 #define reg_CFG_DSP_RST *(vu8*)REG_RST_ADDR
28
29 #define REG_DSP_PCFG_RRIE_MASK (REG_DSP_PCFG_PRIE0_MASK | REG_DSP_PCFG_PRIE1_MASK | REG_DSP_PCFG_PRIE2_MASK)
30 #define REG_DSP_PCFG_RRIE_SHIFT REG_DSP_PCFG_PRIE0_SHIFT
31 #define REG_DSP_PSTS_RCOMIM_SHIFT REG_DSP_PSTS_RCOMIM0_SHIFT
32 #define REG_DSP_PSTS_RRI_SHIFT REG_DSP_PSTS_RRI0_SHIFT
33
34
35 #define DSP_DPRINTF(...) ((void) 0)
36 //#define DSP_DPRINTF OS_TPrintf
37
38 /*---------------------------------------------------------------------------*
39 Type Definitions
40 *---------------------------------------------------------------------------*/
41 typedef struct DSPData
42 {
43 u16 send;
44 u16 reserve1;
45 u16 recv;
46 u16 reserve2;
47 }
48 DSPData;
49
50
51 /*---------------------------------------------------------------------------*
52 Static Variable Definitions
53 *---------------------------------------------------------------------------*/
54 static volatile DSPData *const dspData = (DSPData*)REG_COM0_ADDR;
55
56 /*---------------------------------------------------------------------------*
57 Internal Function Definitions
58 *---------------------------------------------------------------------------*/
59
60 /*---------------------------------------------------------------------------*
61 Name: DSP_PowerOn
62
63 Description: Turns on the DSP and configures it to be in the reset state.
64 You must call DSP_ResetOff() to start the DSP.
65
66 Arguments: None.
67
68 Returns: None.
69 *---------------------------------------------------------------------------*/
DSP_PowerOnCore(void)70 void DSP_PowerOnCore(void) // DSP_Init
71 {
72 SCFG_ResetDSP(); // Confirms reset of DSP block
73 SCFG_SupplyClockToDSP(TRUE); // Power on for DSP block
74 OS_SpinWaitSysCycles(2); // Wait 8 cycles @ 134 MHz
75 SCFG_ReleaseResetDSP(); // Release reset of DSP block
76 DSP_ResetOnCore(); // Set reset of DSP core
77 }
78
79 /*---------------------------------------------------------------------------*
80 Name: DSP_PowerOff
81
82 Description: Turns off the DSP.
83
84 Arguments: None.
85
86 Returns: None.
87 *---------------------------------------------------------------------------*/
DSP_PowerOffCore(void)88 void DSP_PowerOffCore(void) // DSP_End
89 {
90 SCFG_ResetDSP(); // Sets reset of DSP block
91 SCFG_SupplyClockToDSP(FALSE); // Power off for DSP block
92 }
93
94 /*---------------------------------------------------------------------------*
95 Name: DSP_ResetOn
96
97 Description: Resets the DSP.
98
99 Arguments: None.
100
101 Returns: None.
102 *---------------------------------------------------------------------------*/
DSP_ResetOnCore(void)103 void DSP_ResetOnCore(void)
104 {
105 OS_SpinWaitSysCycles(4);
106 if ((reg_DSP_PCFG & REG_DSP_PCFG_DSPR_MASK) == 0)
107 {
108 reg_DSP_PCFG |= REG_DSP_PCFG_DSPR_MASK;
109 OS_SpinWaitSysCycles(4);
110 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
111 {
112 }
113 }
114 }
115
116 /*---------------------------------------------------------------------------*
117 Name: DSP_ResetOff
118
119 Description: Starts the DSP from the reset state.
120
121 Arguments: None.
122
123 Returns: None.
124 *---------------------------------------------------------------------------*/
DSP_ResetOffCore(void)125 void DSP_ResetOffCore(void)
126 {
127 OS_SpinWaitSysCycles(4);
128 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
129 {
130 }
131 DSP_ResetInterfaceCore(); // Initialize DSP-A9IF
132 OS_SpinWaitSysCycles(4);
133 reg_DSP_PCFG &= ~REG_DSP_PCFG_DSPR_MASK;
134 }
135
136 /*---------------------------------------------------------------------------*
137 Name: DSP_ResetOffEx
138
139 Description: Starts the DSP from the reset state.
140
141 Arguments: bitmap: Bitmap of the reply registers and semaphores that allow interrupts from the DSP to the ARM9
142
143 Returns: None.
144 *---------------------------------------------------------------------------*/
DSP_ResetOffExCore(u16 bitmap)145 void DSP_ResetOffExCore(u16 bitmap)
146 {
147 SDK_ASSERT(bitmap >= 0 && bitmap <= 7);
148
149 OS_SpinWaitSysCycles(4);
150 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
151 {
152 }
153 DSP_ResetInterfaceCore(); // Initialize DSP-A9IF
154 OS_SpinWaitSysCycles(4);
155 reg_DSP_PCFG |= (bitmap) << REG_DSP_PCFG_RRIE_SHIFT;
156 OS_SpinWaitSysCycles(4);
157 reg_DSP_PCFG &= ~REG_DSP_PCFG_DSPR_MASK;
158 }
159
160 /*---------------------------------------------------------------------------*
161 Name: DSP_ResetInterface
162
163 Description: Initializes the registers.
164 You must call this function when the DSP is reset.
165
166 Arguments: None.
167
168 Returns: None.
169 *---------------------------------------------------------------------------*/
DSP_ResetInterfaceCore(void)170 void DSP_ResetInterfaceCore(void)
171 {
172 OS_SpinWaitSysCycles(4);
173 if (reg_DSP_PCFG & REG_DSP_PCFG_DSPR_MASK)
174 {
175 u16 dummy;
176 reg_DSP_PCFG &= ~REG_DSP_PCFG_RRIE_MASK;
177 reg_DSP_PSEM = 0;
178 reg_DSP_PCLEAR = 0xFFFF;
179 dummy = dspData[0].recv;
180 dummy = dspData[1].recv;
181 dummy = dspData[2].recv;
182 }
183 }
184
185 /*---------------------------------------------------------------------------*
186 Name: DSP_EnableRecvDataInterrupt
187
188 Description: Enables interrupts for the specified reply register.
189
190 Arguments: dataNo: Reply register number (0-2)
191
192 Returns: None.
193 *---------------------------------------------------------------------------*/
DSP_EnableRecvDataInterruptCore(u32 dataNo)194 void DSP_EnableRecvDataInterruptCore(u32 dataNo)
195 {
196 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
197 OS_SpinWaitSysCycles(4);
198 reg_DSP_PCFG |= (1 << dataNo) << REG_DSP_PCFG_RRIE_SHIFT;
199 }
200
201 /*---------------------------------------------------------------------------*
202 Name: DSP_DisableRecvDataInterrupt
203
204 Description: Disables interrupts for the specified reply register.
205
206 Arguments: dataNo: Reply register number (0-2)
207
208 Returns: None.
209 *---------------------------------------------------------------------------*/
DSP_DisableRecvDataInterruptCore(u32 dataNo)210 void DSP_DisableRecvDataInterruptCore(u32 dataNo)
211 {
212 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
213 OS_SpinWaitSysCycles(4);
214 reg_DSP_PCFG &= ~((1 << dataNo) << REG_DSP_PCFG_RRIE_SHIFT);
215 }
216
217 /*---------------------------------------------------------------------------*
218 Name: DSP_SendDataIsEmpty
219
220 Description: Checks whether the DSP has received data for the specified command register.
221
222 Arguments: dataNo: Command register number (0-2)
223
224 Returns: TRUE if the DSP has already received data.
225 *---------------------------------------------------------------------------*/
DSP_SendDataIsEmptyCore(u32 dataNo)226 BOOL DSP_SendDataIsEmptyCore(u32 dataNo)
227 {
228 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
229 OS_SpinWaitSysCycles(4);
230 return (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RCOMIM_SHIFT)) ? FALSE : TRUE;
231 }
232
233 /*---------------------------------------------------------------------------*
234 Name: DSP_RecvDataIsReady
235
236 Description: Checks whether data was sent from the DSP to the specified reply register.
237
238 Arguments: dataNo: Reply register number (0-2)
239
240 Returns: TRUE if the DSP has sent data.
241 *---------------------------------------------------------------------------*/
DSP_RecvDataIsReadyCore(u32 dataNo)242 BOOL DSP_RecvDataIsReadyCore(u32 dataNo)
243 {
244 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
245 OS_SpinWaitSysCycles(4);
246 return (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RRI_SHIFT)) ? TRUE : FALSE;
247 }
248
249 /*---------------------------------------------------------------------------*
250 Name: DSP_SendData
251
252 Description: Sends data to the DSP.
253
254 Arguments: dataNo: Command register number (0-2)
255 data: Data to send
256
257 Returns: None.
258 *---------------------------------------------------------------------------*/
DSP_SendDataCore(u32 dataNo,u16 data)259 void DSP_SendDataCore(u32 dataNo, u16 data)
260 {
261 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
262 OS_SpinWaitSysCycles(4);
263 while (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RCOMIM_SHIFT))
264 {
265 }
266 dspData[dataNo].send = data;
267 }
268
269 /*---------------------------------------------------------------------------*
270 Name: DSP_RecvData
271
272 Description: Receives data from the DSP.
273
274 Arguments: dataNo: Reply register number (0-2)
275
276 Returns: The received data.
277 *---------------------------------------------------------------------------*/
DSP_RecvDataCore(u32 dataNo)278 u16 DSP_RecvDataCore(u32 dataNo)
279 {
280 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
281 OS_SpinWaitSysCycles(4);
282 while (!(reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RRI_SHIFT)))
283 {
284 }
285 return dspData[dataNo].recv;
286 }
287
288 /*---------------------------------------------------------------------------*
289 Name: DSP_EnableFifoInterrupt
290
291 Description: Enables FIFO interrupts.
292
293 Arguments: type: Cause of the FIFO interrupt
294
295 Returns: None.
296 *---------------------------------------------------------------------------*/
DSP_EnableFifoInterruptCore(DSPFifoIntr type)297 void DSP_EnableFifoInterruptCore(DSPFifoIntr type)
298 {
299 OS_SpinWaitSysCycles(4);
300 reg_DSP_PCFG |= type;
301 }
302
303 /*---------------------------------------------------------------------------*
304 Name: DSP_DisableFifoInterrupt
305
306 Description: Disables FIFO interrupts.
307
308 Arguments: type: Cause of the FIFO interrupt
309
310 Returns: None.
311 *---------------------------------------------------------------------------*/
DSP_DisableFifoInterruptCore(DSPFifoIntr type)312 void DSP_DisableFifoInterruptCore(DSPFifoIntr type)
313 {
314 OS_SpinWaitSysCycles(4);
315 reg_DSP_PCFG &= ~type;
316 }
317
318 /*---------------------------------------------------------------------------*
319 Name: DSP_SendFifoEx
320
321 Description: Writes data in the DSP's memory space.
322
323 Arguments: memsel: Memory space in which to write data
324 dest: Address to write to (half-word).
325 If the most-significant 16 bits are set, values must be set in the DMA register in advance.
326
327 src: Data to write
328 size: Length of the data to write (half-word)
329 flags: You can select a write mode other than DSP_FIFO_FLAG_RECV_UNIT_* from DSPFifoFlag
330
331
332 Returns: None.
333 *---------------------------------------------------------------------------*/
DSP_SendFifoExCore(DSPFifoMemSel memsel,u16 dest,const u16 * src,int size,u16 flags)334 void DSP_SendFifoExCore(DSPFifoMemSel memsel, u16 dest, const u16 *src, int size, u16 flags)
335 {
336 OSIntrMode bak = OS_DisableInterrupts();
337 u16 incmode = (u16)((flags & DSP_FIFO_FLAG_DEST_FIX) ? 0 : REG_DSP_PCFG_AIM_MASK);
338
339 OS_SpinWaitSysCycles(4);
340 reg_DSP_PCFG = (u16)((reg_DSP_PCFG & ~(REG_DSP_PCFG_MEMSEL_MASK|REG_DSP_PCFG_AIM_MASK))
341 | memsel | incmode);
342 reg_DSP_PADR = dest;
343
344 if (flags & DSP_FIFO_FLAG_SRC_FIX)
345 {
346 while (size-- > 0)
347 {
348 OS_SpinWaitSysCycles(4);
349 while (reg_DSP_PSTS & REG_DSP_PSTS_WFFI_MASK)
350 {
351 }
352 reg_DSP_PDATA = *src;
353 }
354 }
355 else
356 {
357 while (size-- > 0)
358 {
359 OS_SpinWaitSysCycles(4);
360 while (reg_DSP_PSTS & REG_DSP_PSTS_WFFI_MASK)
361 {
362 }
363 reg_DSP_PDATA = *src++;
364 }
365 }
366 (void)OS_RestoreInterrupts(bak);
367 }
368
369 /*---------------------------------------------------------------------------*
370 Name: DSP_RecvFifoEx
371
372 Description: Reads data from the DSP's memory space.
373
374 Arguments: memsel: Memory space to read data from (other than program memory)
375 dest: Address at which to receive data
376 src: Address from which the data was received (half-word)
377 If the most-significant 16 bits are set, values must be set in the DMA register in advance.
378
379 size: Data size to read (half-word)
380 flags: Select the read mode from DSPFifoFlag
381
382 Returns: None.
383 *---------------------------------------------------------------------------*/
DSP_RecvFifoExCore(DSPFifoMemSel memsel,u16 * dest,u16 src,int size,u16 flags)384 void DSP_RecvFifoExCore(DSPFifoMemSel memsel, u16* dest, u16 src, int size, u16 flags)
385 {
386 OSIntrMode bak = OS_DisableInterrupts();
387 DSPFifoRecvLength len;
388 u16 incmode = (u16)((flags & DSP_FIFO_FLAG_SRC_FIX) ? 0 : REG_DSP_PCFG_AIM_MASK);
389
390 SDK_ASSERT(memsel != DSP_FIFO_MEMSEL_PROGRAM);
391
392 switch (flags & DSP_FIFO_FLAG_RECV_MASK)
393 {
394 case DSP_FIFO_FLAG_RECV_UNIT_2B:
395 len = DSP_FIFO_RECV_2B;
396 size = 1;
397 break;
398 case DSP_FIFO_FLAG_RECV_UNIT_16B:
399 len = DSP_FIFO_RECV_16B;
400 size = 8;
401 break;
402 case DSP_FIFO_FLAG_RECV_UNIT_32B:
403 len = DSP_FIFO_RECV_32B;
404 size = 16;
405 break;
406 default:
407 len = DSP_FIFO_RECV_CONTINUOUS;
408 break;
409 }
410
411 reg_DSP_PADR = src;
412 OS_SpinWaitSysCycles(4);
413 reg_DSP_PCFG = (u16)((reg_DSP_PCFG & ~(REG_DSP_PCFG_MEMSEL_MASK|REG_DSP_PCFG_DRS_MASK|REG_DSP_PCFG_AIM_MASK))
414 | memsel | len | incmode | REG_DSP_PCFG_RS_MASK);
415
416 if (flags & DSP_FIFO_FLAG_DEST_FIX)
417 {
418 while (size-- > 0)
419 {
420 OS_SpinWaitSysCycles(4);
421 while ((reg_DSP_PSTS & REG_DSP_PSTS_RFNEI_MASK) == 0)
422 {
423 }
424 *dest = reg_DSP_PDATA;
425 }
426 }
427 else
428 {
429 while (size-- > 0)
430 {
431 OS_SpinWaitSysCycles(4);
432 while ((reg_DSP_PSTS & REG_DSP_PSTS_RFNEI_MASK) == 0)
433 {
434 }
435 *dest++ = reg_DSP_PDATA;
436 }
437 }
438 OS_SpinWaitSysCycles(4);
439 reg_DSP_PCFG &= ~REG_DSP_PCFG_RS_MASK;
440 (void)OS_RestoreInterrupts(bak);
441 }
442
443 /*---------------------------------------------------------------------------*
444 Name: DSP_SetCommandReg
445
446 Description: Writes a value to a command register.
447
448 Arguments: regNo: Command register number (0-2)
449 data: Data
450
451 Returns: None.
452 *---------------------------------------------------------------------------*/
DSP_SetCommandRegCore(u32 regNo,u16 data)453 void DSP_SetCommandRegCore(u32 regNo, u16 data)
454 {
455 SDK_ASSERT(regNo >= 0 && regNo <= 2);
456 OS_SpinWaitSysCycles(4);
457 dspData[regNo].send = data;
458 }
459
460 /*---------------------------------------------------------------------------*
461 Name: DSP_GetReplyReg
462
463 Description: Reads a value from a reply register.
464
465 Arguments: regNo: Reply register number (0-2)
466
467 Returns: The data read.
468 *---------------------------------------------------------------------------*/
DSP_GetReplyRegCore(u32 regNo)469 u16 DSP_GetReplyRegCore(u32 regNo)
470 {
471 SDK_ASSERT(regNo >= 0 && regNo <= 2);
472 OS_SpinWaitSysCycles(4);
473 return dspData[regNo].recv;
474 }
475
476 /*---------------------------------------------------------------------------*
477 Name: DSP_SetSemaphore
478
479 Description: Writes a value to the semaphore register used to send notifications from the ARM to the DSP.
480
481 Arguments: mask: Value to set
482
483 Returns: None.
484 *---------------------------------------------------------------------------*/
DSP_SetSemaphoreCore(u16 mask)485 void DSP_SetSemaphoreCore(u16 mask)
486 {
487 reg_DSP_PSEM = mask;
488 }
489
490 /*---------------------------------------------------------------------------*
491 Name: DSP_GetSemaphore
492
493 Description: Reads the value of the semaphore register for sending notifications from the DSP to an ARM processor.
494
495 Arguments: None.
496
497 Returns: The value written to the semaphore by the DSP.
498 *---------------------------------------------------------------------------*/
DSP_GetSemaphoreCore(void)499 u16 DSP_GetSemaphoreCore(void)
500 {
501 OS_SpinWaitSysCycles(4);
502 return reg_DSP_SEM;
503 }
504
505 /*---------------------------------------------------------------------------*
506 Name: DSP_ClearSemaphore
507
508 Description: Clears the value of the semaphore register for sending notifications from the DSP to an ARM processor.
509
510 Arguments: mask: Bits to clear
511
512 Returns: None.
513 *---------------------------------------------------------------------------*/
DSP_ClearSemaphoreCore(u16 mask)514 void DSP_ClearSemaphoreCore(u16 mask)
515 {
516 reg_DSP_PCLEAR = mask;
517 }
518
519 /*---------------------------------------------------------------------------*
520 Name: DSP_MaskSemaphore
521
522 Description: Sets bits that correspond to interrupts to disable in the semaphore register for sending notifications from the DSP to an ARM processor.
523
524 Arguments: mask: Bits corresponding to interrupts to disable
525
526 Returns: None.
527 *---------------------------------------------------------------------------*/
DSP_MaskSemaphoreCore(u16 mask)528 void DSP_MaskSemaphoreCore(u16 mask)
529 {
530 reg_DSP_PMASK = mask;
531 }
532
533 /*---------------------------------------------------------------------------*
534 Name: DSP_CheckSemaphoreRequest
535
536 Description: Checks whether there is an interrupt request from the semaphore register.
537
538 Arguments: None.
539
540 Returns: TRUE if there is a request.
541 *---------------------------------------------------------------------------*/
DSP_CheckSemaphoreRequestCore(void)542 BOOL DSP_CheckSemaphoreRequestCore(void)
543 {
544 return (reg_DSP_PSTS & REG_DSP_PSTS_PSEMI_MASK) >> REG_DSP_PSTS_PSEMI_SHIFT;
545 }
546
547
548 #if defined(DSP_SUPPORT_OBSOLETE_LOADER)
549 /*---------------------------------------------------------------------------*
550 * The following shows candidate interfaces for termination because they are considered not to be currently in use
551 *---------------------------------------------------------------------------*/
552
553 /*---------------------------------------------------------------------------*
554 * Below is the old interface using a straight-mapping method
555 *---------------------------------------------------------------------------*/
556
557 /*---------------------------------------------------------------------------*
558 Name: DSPi_MapProcessSlotAsStraight
559
560 Description: Initializes the slot map so the segment number and the WRAM slot number match.
561 (This method is used only with the initial load function that does not have Ex applied.)
562
563 Arguments: context: DSPProcessContext structure
564 slotB: WRAM-B allowed for use for code memory
565 slotC: WRAM-C allowed for use for data memory
566
567 Returns: None.
568 *---------------------------------------------------------------------------*/
DSPi_MapProcessSlotAsStraight(DSPProcessContext * context,int slotB,int slotC)569 static BOOL DSPi_MapProcessSlotAsStraight(DSPProcessContext *context, int slotB, int slotC)
570 {
571 int segment;
572 for (segment = 0; segment < MI_WRAM_B_MAX_NUM; ++segment)
573 {
574 if (context->segmentCode & (1 << segment) != 0)
575 {
576 int slot = segment;
577 if ((slotB & (1 << slot)) == 0)
578 {
579 return FALSE;
580 }
581 context->slotOfSegmentCode[segment] = slot;
582 }
583 }
584 for (segment = 0; segment < MI_WRAM_C_MAX_NUM; ++segment)
585 {
586 if (context->segmentData & (1 << segment) != 0)
587 {
588 int slot = segment;
589 if ((slotC & (1 << slot)) == 0)
590 {
591 return FALSE;
592 }
593 context->slotOfSegmentData[segment] = slot;
594 }
595 }
596 return TRUE;
597 }
598
599 /*---------------------------------------------------------------------------*
600 Name: DSP_LoadFileAuto
601
602 Description: Loads a COFF format DSP program and assigns the necessary WRAM to DSP.
603
604 Arguments: image: COFF file
605
606 Returns: TRUE on success.
607 *---------------------------------------------------------------------------*/
DSP_LoadFileAutoCore(const void * image)608 BOOL DSP_LoadFileAutoCore(const void *image)
609 {
610 // Temporarily convert to a memory file
611 FSFile memfile[1];
612 if(DSPi_CreateMemoryFile(memfile, image))
613 {
614 DSPProcessContext context[1];
615 DSP_InitProcessContext(context, NULL);
616 return DSP_StartupProcess(context, memfile, 0xFF, 0xFF, DSPi_MapProcessSlotAsStraight);
617 }
618 return FALSE;
619 }
620
621
622 #endif
623
624 /*---------------------------------------------------------------------------*
625 End of file
626 *---------------------------------------------------------------------------*/
627