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