1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - library - dsp
3 File: dsp_if.c
4
5 Copyright 2007-2008 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:: 2008-09-17#$
14 $Rev: 8556 $
15 $Author: okubata_ryoma $
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: Power DSP block on but reset yet.
64 You should call DSP_ResetOff() to boot 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 cycle @ 134MHz
75 SCFG_ReleaseResetDSP(); // Release reset of DSP block
76 DSP_ResetOnCore(); // Set reset of DSP core
77 }
78 /*---------------------------------------------------------------------------*
79 Name: DSP_PowerOff
80
81 Description: Power DSP block off.
82
83 Arguments: None.
84
85 Returns: None.
86 *---------------------------------------------------------------------------*/
DSP_PowerOffCore(void)87 void DSP_PowerOffCore(void) // DSP_End
88 {
89 SCFG_ResetDSP(); // Sets reset of DSP block
90 SCFG_SupplyClockToDSP(FALSE); // Power off for DSP block
91 }
92
93 /*---------------------------------------------------------------------------*
94 Name: DSP_ResetOn
95
96 Description: Reset DSP unless Reset state.
97
98 Arguments: None.
99
100 Returns: None.
101 *---------------------------------------------------------------------------*/
DSP_ResetOnCore(void)102 void DSP_ResetOnCore(void)
103 {
104 if ((reg_DSP_PCFG & REG_DSP_PCFG_DSPR_MASK) == 0)
105 {
106 reg_DSP_PCFG |= REG_DSP_PCFG_DSPR_MASK;
107 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
108 {
109 }
110 }
111 }
112
113 /*---------------------------------------------------------------------------*
114 Name: DSP_ResetOff
115
116 Description: Boot DSP if in Reset state.
117
118 Arguments: None.
119
120 Returns: None.
121 *---------------------------------------------------------------------------*/
DSP_ResetOffCore(void)122 void DSP_ResetOffCore(void)
123 {
124 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
125 {
126 }
127 DSP_ResetInterfaceCore(); // Initialize DSP-A9IF
128 reg_DSP_PCFG &= ~REG_DSP_PCFG_DSPR_MASK;
129 }
130
131 /*---------------------------------------------------------------------------*
132 Name: DSP_ResetOffEx
133
134 Description: Boot DSP if in Reset state.
135
136 Arguments: bitmap: Enable interrupt for receive data from DSP bitmap
137
138 Returns: None.
139 *---------------------------------------------------------------------------*/
DSP_ResetOffExCore(u16 bitmap)140 void DSP_ResetOffExCore(u16 bitmap)
141 {
142 SDK_ASSERT(bitmap >= 0 && bitmap <= 7);
143
144 while ( reg_DSP_PSTS & REG_DSP_PSTS_PRST_MASK )
145 {
146 }
147 DSP_ResetInterfaceCore(); // Initialize DSP-A9IF
148 reg_DSP_PCFG |= (bitmap) << REG_DSP_PCFG_RRIE_SHIFT;
149 reg_DSP_PCFG &= ~REG_DSP_PCFG_DSPR_MASK;
150 }
151
152 /*---------------------------------------------------------------------------*
153 Name: DSP_ResetInterface
154
155 Description: Resets interface registers.
156 It should be called while in reset state.
157
158 Arguments: None.
159
160 Returns: None.
161 *---------------------------------------------------------------------------*/
DSP_ResetInterfaceCore(void)162 void DSP_ResetInterfaceCore(void)
163 {
164 if (reg_DSP_PCFG & REG_DSP_PCFG_DSPR_MASK)
165 {
166 u16 dummy;
167 reg_DSP_PCFG &= ~REG_DSP_PCFG_RRIE_MASK;
168 reg_DSP_PSEM = 0;
169 reg_DSP_PCLEAR = 0xFFFF;
170 dummy = dspData[0].recv;
171 dummy = dspData[1].recv;
172 dummy = dspData[2].recv;
173 }
174 }
175
176 /*---------------------------------------------------------------------------*
177 Name: DSP_EnableRecvDataInterrupt
178
179 Description: Enables interrupt for receive data from DSP.
180
181 Arguments: dataNo: Target data register (0-2)
182
183 Returns: None.
184 *---------------------------------------------------------------------------*/
DSP_EnableRecvDataInterruptCore(u32 dataNo)185 void DSP_EnableRecvDataInterruptCore(u32 dataNo)
186 {
187 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
188 reg_DSP_PCFG |= (1 << dataNo) << REG_DSP_PCFG_RRIE_SHIFT;
189 }
190
191 /*---------------------------------------------------------------------------*
192 Name: DSP_DisableRecvDataInterrupt
193
194 Description: Disables interrupt for receive data from DSP.
195
196 Arguments: dataNo: Target data register (0-2)
197
198 Returns: None.
199 *---------------------------------------------------------------------------*/
DSP_DisableRecvDataInterruptCore(u32 dataNo)200 void DSP_DisableRecvDataInterruptCore(u32 dataNo)
201 {
202 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
203 reg_DSP_PCFG &= ~((1 << dataNo) << REG_DSP_PCFG_RRIE_SHIFT);
204 }
205
206 /*---------------------------------------------------------------------------*
207 Name: DSP_SendDataIsEmpty
208
209 Description: Whether DSP has received sending data.
210
211 Arguments: dataNo: Target data register (0-2)
212
213 Returns: None.
214 *---------------------------------------------------------------------------*/
DSP_SendDataIsEmptyCore(u32 dataNo)215 BOOL DSP_SendDataIsEmptyCore(u32 dataNo)
216 {
217 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
218 return (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RCOMIM_SHIFT)) ? FALSE : TRUE;
219 }
220
221 /*---------------------------------------------------------------------------*
222 Name: DSP_RecvDataIsReady
223
224 Description: Whether there is sent data from DSP.
225
226 Arguments: dataNo: Target data register (0-2)
227
228 Returns: None.
229 *---------------------------------------------------------------------------*/
DSP_RecvDataIsReadyCore(u32 dataNo)230 BOOL DSP_RecvDataIsReadyCore(u32 dataNo)
231 {
232 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
233 return (reg_DSP_PSTS & ((1 << dataNo) << REG_DSP_PSTS_RRI_SHIFT)) ? TRUE : FALSE;
234 }
235
236 /*---------------------------------------------------------------------------*
237 Name: DSP_SendData
238
239 Description: Sends data to DSP.
240
241 Arguments: dataNo: Target data register (0-2)
242 data: Data to send
243
244 Returns: None.
245 *---------------------------------------------------------------------------*/
DSP_SendDataCore(u32 dataNo,u16 data)246 void DSP_SendDataCore(u32 dataNo, u16 data)
247 {
248 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
249 while (DSP_SendDataIsEmptyCore(dataNo) == FALSE)
250 {
251 }
252 dspData[dataNo].send = data;
253 }
254
255 /*---------------------------------------------------------------------------*
256 Name: DSP_RecvData
257
258 Description: Receives data from DSP.
259
260 Arguments: dataNo: Target data register (0-2)
261
262 Returns: receiving data
263 *---------------------------------------------------------------------------*/
DSP_RecvDataCore(u32 dataNo)264 u16 DSP_RecvDataCore(u32 dataNo)
265 {
266 SDK_ASSERT(dataNo >= 0 && dataNo <= 2);
267 while (DSP_RecvDataIsReadyCore(dataNo) == FALSE)
268 {
269 }
270 return dspData[dataNo].recv;
271 }
272
273 /*---------------------------------------------------------------------------*
274 Name: DSP_EnableFifoInterrupt
275
276 Description: Enables interrupt for FIFO.
277
278 Arguments: type: One of DSPFifoIntr
279
280 Returns: None.
281 *---------------------------------------------------------------------------*/
DSP_EnableFifoInterruptCore(DSPFifoIntr type)282 void DSP_EnableFifoInterruptCore(DSPFifoIntr type)
283 {
284 reg_DSP_PCFG |= type;
285 }
286
287 /*---------------------------------------------------------------------------*
288 Name: DSP_DisableFifoInterrupt
289
290 Description: Disables interrupt for FIFO.
291
292 Arguments: type: One of DSPFifoIntr
293
294 Returns: None.
295 *---------------------------------------------------------------------------*/
DSP_DisableFifoInterruptCore(DSPFifoIntr type)296 void DSP_DisableFifoInterruptCore(DSPFifoIntr type)
297 {
298 reg_DSP_PCFG &= ~type;
299 }
300
301 /*---------------------------------------------------------------------------*
302 Name: DSP_SendFifoEx
303
304 Description: Writes data into DSP memory space.
305
306 Arguments: memsel: One of DSPFifoMemSel
307 dest: Destination address (in half words).
308 If you want to set high address, ask DSP to set
309 DMA register.
310 src: Data to send
311 size: Data length to send (in half words)
312 flags: bitOR of DSPFifoFlag to specify special mode
313
314 Returns: None.
315 *---------------------------------------------------------------------------*/
DSP_SendFifoExCore(DSPFifoMemSel memsel,u16 dest,const u16 * src,int size,u16 flags)316 void DSP_SendFifoExCore(DSPFifoMemSel memsel, u16 dest, const u16 *src, int size, u16 flags)
317 {
318 OSIntrMode bak = OS_DisableInterrupts();
319 u16 incmode = (u16)((flags & DSP_FIFO_FLAG_DEST_FIX) ? 0 : REG_DSP_PCFG_AIM_MASK);
320
321 reg_DSP_PADR = dest;
322 reg_DSP_PCFG = (u16)((reg_DSP_PCFG & ~(REG_DSP_PCFG_MEMSEL_MASK|REG_DSP_PCFG_AIM_MASK))
323 | memsel | incmode);
324
325 if (flags & DSP_FIFO_FLAG_SRC_FIX)
326 {
327 while (size-- > 0)
328 {
329 while (reg_DSP_PSTS & REG_DSP_PSTS_WFFI_MASK)
330 {
331 }
332 reg_DSP_PDATA = *src;
333 }
334 }
335 else
336 {
337 while (size-- > 0)
338 {
339 while (reg_DSP_PSTS & REG_DSP_PSTS_WFFI_MASK)
340 {
341 }
342 reg_DSP_PDATA = *src++;
343 }
344 }
345 (void)OS_RestoreInterrupts(bak);
346 }
347
348 /*---------------------------------------------------------------------------*
349 Name: DSP_RecvFifoEx
350
351 Description: Reads data into DSP memory space.
352
353 Arguments: memsel: One of DSPFifoMemSel without PROGRAM area
354 dest: Data to receive
355 src: Source address (in half words).
356 if you want to set high address, ask DSP to set
357 DMA register.
358 size: Data length to receive (in half words).
359 Ignore unless continuous mode.
360 flags: bitOR of DSPFifoFlag to specify special mode
361
362 Returns: None.
363 *---------------------------------------------------------------------------*/
DSP_RecvFifoExCore(DSPFifoMemSel memsel,u16 * dest,u16 src,int size,u16 flags)364 void DSP_RecvFifoExCore(DSPFifoMemSel memsel, u16* dest, u16 src, int size, u16 flags)
365 {
366 OSIntrMode bak = OS_DisableInterrupts();
367 DSPFifoRecvLength len;
368 u16 incmode = (u16)((flags & DSP_FIFO_FLAG_SRC_FIX) ? 0 : REG_DSP_PCFG_AIM_MASK);
369
370 SDK_ASSERT(memsel != DSP_FIFO_MEMSEL_PROGRAM);
371
372 switch (flags & DSP_FIFO_FLAG_RECV_MASK)
373 {
374 case DSP_FIFO_FLAG_RECV_UNIT_2B:
375 len = DSP_FIFO_RECV_2B;
376 size = 1;
377 break;
378 case DSP_FIFO_FLAG_RECV_UNIT_16B:
379 len = DSP_FIFO_RECV_16B;
380 size = 8;
381 break;
382 case DSP_FIFO_FLAG_RECV_UNIT_32B:
383 len = DSP_FIFO_RECV_32B;
384 size = 16;
385 break;
386 default:
387 len = DSP_FIFO_RECV_CONTINUOUS;
388 break;
389 }
390
391 reg_DSP_PADR = src;
392 reg_DSP_PCFG = (u16)((reg_DSP_PCFG & ~(REG_DSP_PCFG_MEMSEL_MASK|REG_DSP_PCFG_DRS_MASK|REG_DSP_PCFG_AIM_MASK))
393 | memsel | len | incmode | REG_DSP_PCFG_RS_MASK);
394
395 if (flags & DSP_FIFO_FLAG_DEST_FIX)
396 {
397 while (size-- > 0)
398 {
399 while ((reg_DSP_PSTS & REG_DSP_PSTS_RFNEI_MASK) == 0)
400 {
401 }
402 *dest = reg_DSP_PDATA;
403 }
404 }
405 else
406 {
407 while (size-- > 0)
408 {
409 while ((reg_DSP_PSTS & REG_DSP_PSTS_RFNEI_MASK) == 0)
410 {
411 }
412 *dest++ = reg_DSP_PDATA;
413 }
414 }
415 reg_DSP_PCFG &= ~REG_DSP_PCFG_RS_MASK;
416 (void)OS_RestoreInterrupts(bak);
417 }
418
419 /*---------------------------------------------------------------------------*
420 Name: DSP_SetCommandReg
421
422 Description: Sets command register to signal to DSP.
423
424 Arguments: data: Data
425
426 Returns: None.
427 *---------------------------------------------------------------------------*/
DSP_SetCommandRegCore(u32 regNo,u16 data)428 void DSP_SetCommandRegCore(u32 regNo, u16 data)
429 {
430 SDK_ASSERT(regNo >= 0 && regNo <= 2);
431 dspData[regNo].send = data;
432 }
433
434 /*---------------------------------------------------------------------------*
435 Name: DSP_GetReplyReg
436
437 Description: Gets reply register to be recieved from DSP.
438
439 Arguments: None.
440
441 Returns: data.
442 *---------------------------------------------------------------------------*/
DSP_GetReplyRegCore(u32 regNo)443 u16 DSP_GetReplyRegCore(u32 regNo)
444 {
445 SDK_ASSERT(regNo >= 0 && regNo <= 2);
446 return dspData[regNo].recv;
447 }
448
449 /*---------------------------------------------------------------------------*
450 Name: DSP_SetSemaphore
451
452 Description: Sets semaphore to signal to DSP.
453 NOTE: received semaphore is individual register.
454
455 Arguments: mask: Bit mask to set
456
457 Returns: None.
458 *---------------------------------------------------------------------------*/
DSP_SetSemaphoreCore(u16 mask)459 void DSP_SetSemaphoreCore(u16 mask)
460 {
461 reg_DSP_PSEM = mask;
462 }
463
464 /*---------------------------------------------------------------------------*
465 Name: DSP_GetSemaphore
466
467 Description: Gets semaphore to be recieved from DSP.
468 NOTE: sending semaphore is individual register.
469
470 Arguments: None.
471
472 Returns: Bit mask is set by DSP.
473 *---------------------------------------------------------------------------*/
DSP_GetSemaphoreCore(void)474 u16 DSP_GetSemaphoreCore(void)
475 {
476 return reg_DSP_SEM;
477 }
478
479 /*---------------------------------------------------------------------------*
480 Name: DSP_ClearSemaphore
481
482 Description: Clears semaphore to be recieved from DSP.
483
484 Arguments: mask: Bit mask to clear
485
486 Returns: None.
487 *---------------------------------------------------------------------------*/
DSP_ClearSemaphoreCore(u16 mask)488 void DSP_ClearSemaphoreCore(u16 mask)
489 {
490 reg_DSP_PCLEAR = mask;
491 }
492
493 /*---------------------------------------------------------------------------*
494 Name: DSP_MaskSemaphore
495
496 Description: Masks semaphore to interrupt to ARM9.
497
498 Arguments: mask: Bit mask to disable to interrupt
499
500 Returns: None.
501 *---------------------------------------------------------------------------*/
DSP_MaskSemaphoreCore(u16 mask)502 void DSP_MaskSemaphoreCore(u16 mask)
503 {
504 reg_DSP_PMASK = mask;
505 }
506
507 /*---------------------------------------------------------------------------*
508 Name: DSP_CheckSemaphoreRequest
509
510 Description: Whether there is requested interrupt by semaphore
511
512 Arguments: None.
513
514 Returns: TRUE if requested.
515 *---------------------------------------------------------------------------*/
DSP_CheckSemaphoreRequestCore(void)516 BOOL DSP_CheckSemaphoreRequestCore(void)
517 {
518 return (reg_DSP_PSTS & REG_DSP_PSTS_PSEMI_MASK) >> REG_DSP_PSTS_PSEMI_SHIFT;
519 }
520
521
522 #if defined(DSP_SUPPORT_OBSOLETE_LOADER)
523 /*---------------------------------------------------------------------------*
524 * The following shows candidate interfaces for termination because they are considered not to be currently in use
525 *---------------------------------------------------------------------------*/
526
527 /*---------------------------------------------------------------------------*
528 * Below is the old interface using a straight-mapping method
529 *---------------------------------------------------------------------------*/
530
531 /*---------------------------------------------------------------------------*
532 Name: DSPi_MapProcessSlotAsStraight
533
534 Description: Initializes the slot map so the segment number and the WRAM slot number match.
535 (This method is used only with the initial load function that does not have Ex applied)
536
537 Arguments: context: DSPProcessContext structure
538 slotB: WRAM-B allowed for use for code memory
539 slotC: WRAM-C allowed for use for data memory
540
541 Returns: None.
542 *---------------------------------------------------------------------------*/
DSPi_MapProcessSlotAsStraight(DSPProcessContext * context,int slotB,int slotC)543 static BOOL DSPi_MapProcessSlotAsStraight(DSPProcessContext *context, int slotB, int slotC)
544 {
545 int segment;
546 for (segment = 0; segment < MI_WRAM_B_MAX_NUM; ++segment)
547 {
548 if (context->segmentCode & (1 << segment) != 0)
549 {
550 int slot = segment;
551 if ((slotB & (1 << slot)) == 0)
552 {
553 return FALSE;
554 }
555 context->slotOfSegmentCode[segment] = slot;
556 }
557 }
558 for (segment = 0; segment < MI_WRAM_C_MAX_NUM; ++segment)
559 {
560 if (context->segmentData & (1 << segment) != 0)
561 {
562 int slot = segment;
563 if ((slotC & (1 << slot)) == 0)
564 {
565 return FALSE;
566 }
567 context->slotOfSegmentData[segment] = slot;
568 }
569 }
570 return TRUE;
571 }
572
573 /*---------------------------------------------------------------------------*
574 Name: DSP_LoadFileAuto
575
576 Description: Loads a COFF format DSP program and assigns the necessary WRAM to DSP
577
578 Arguments: image: Coff file
579
580 Returns: TRUE if success.
581 *---------------------------------------------------------------------------*/
DSP_LoadFileAutoCore(const void * image)582 BOOL DSP_LoadFileAutoCore(const void *image)
583 {
584 // Temporarily convert to a memory file
585 FSFile memfile[1];
586 if(DSPi_CreateMemoryFile(memfile, image))
587 {
588 DSPProcessContext context[1];
589 DSP_InitProcessContext(context, NULL);
590 return DSP_StartupProcess(context, memfile, 0xFF, 0xFF, DSPi_MapProcessSlotAsStraight);
591 }
592 return FALSE;
593 }
594
595
596 #endif
597
598 /*---------------------------------------------------------------------------*
599 End of file
600 *---------------------------------------------------------------------------*/
601