1 /*-------------------------------------------------------------
3 aram.c -- ARAM subsystem
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
28 -------------------------------------------------------------*/
35 #include "processor.h"
43 #define DSPCR_DSPRESET 0x0800 // Reset DSP
44 #define DSPCR_DSPDMA 0x0200 // ARAM dma in progress, if set
45 #define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
46 #define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
47 #define DSPCR_ARINTMSK 0x0040
48 #define DSPCR_ARINT 0x0020
49 #define DSPCR_AIINTMSK 0x0010
50 #define DSPCR_AIINT 0x0008
51 #define DSPCR_HALT 0x0004 // halt DSP
52 #define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
53 #define DSPCR_RES 0x0001 // reset DSP
55 #define AR_ARAMEXPANSION 2
57 #define _SHIFTL(v, s, w) \
58 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
59 #define _SHIFTR(v, s, w) \
60 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
62 static vu16
* const _dspReg
= (u16
*)0xCC005000;
64 static ARCallback __ARDmaCallback
= NULL
;
65 static u32 __ARInit_Flag
= 0;
66 static u32 __ARStackPointer
= 0;
67 static u32 __ARFreeBlocks
= 0;
68 static u32
*__ARBlockLen
= NULL
;
70 static u32 __ARInternalSize
= 0;
71 static u32 __ARExpansionSize
= 0;
72 static u32 __ARSize
= 0;
74 static void __ARHandler();
75 static void __ARCheckSize();
76 static void __ARClearArea(u32 aramaddr
,u32 len
);
78 extern void __UnmaskIrq(u32
);
79 extern void __MaskIrq(u32
);
81 ARCallback
AR_RegisterCallback(ARCallback callback
)
86 _CPU_ISR_Disable(level
);
87 old
= __ARDmaCallback
;
88 __ARDmaCallback
= callback
;
89 _CPU_ISR_Restore(level
);
96 _CPU_ISR_Disable(level
);
97 ret
= ((_dspReg
[5]&DSPCR_DSPDMA
)==DSPCR_DSPDMA
);
98 _CPU_ISR_Restore(level
);
102 u32
AR_Init(u32
*stack_idx_array
,u32 num_entries
)
108 u32 aram_base
= 0x4000;
110 if(__ARInit_Flag
) return aram_base
;
112 _CPU_ISR_Disable(level
);
114 __ARDmaCallback
= NULL
;
116 IRQ_Request(IRQ_DSP_ARAM
,__ARHandler
,NULL
);
117 __UnmaskIrq(IRQMASK(IRQ_DSP_ARAM
));
119 __ARStackPointer
= aram_base
;
120 __ARFreeBlocks
= num_entries
;
121 __ARBlockLen
= stack_idx_array
;
123 freq
= _dspReg
[13]&0xff;
124 if(((f32
)freq
)!=156.0 && ((f32
)freq
)!=176.0) {
125 printf("AR_Init(): Illegal SDRAM refresh value(%f)\n",(f32
)(freq
));
129 _dspReg
[13] = (_dspReg
[13]&~0xff)|(_dspReg
[13]&0xff);
134 _CPU_ISR_Restore(level
);
135 return __ARStackPointer
;
138 void AR_StartDMA(u32 dir
,u32 memaddr
,u32 aramaddr
,u32 len
)
142 _CPU_ISR_Disable(level
);
144 // set main memory address
145 _dspReg
[16] = (_dspReg
[16]&~0x03ff)|_SHIFTR(memaddr
,16,16);
146 _dspReg
[17] = (_dspReg
[17]&~0xffe0)|_SHIFTR(memaddr
, 0,16);
149 _dspReg
[18] = (_dspReg
[18]&~0x03ff)|_SHIFTR(aramaddr
,16,16);
150 _dspReg
[19] = (_dspReg
[19]&~0xffe0)|_SHIFTR(aramaddr
, 0,16);
153 _dspReg
[20] = (_dspReg
[20]&~0x8000)|_SHIFTL(dir
,15,1);
154 _dspReg
[20] = (_dspReg
[20]&~0x03ff)|_SHIFTR(len
,16,16);
155 _dspReg
[21] = (_dspReg
[21]&~0xffe0)|_SHIFTR(len
, 0,16);
157 _CPU_ISR_Restore(level
);
160 u32
AR_Alloc(u32 len
)
165 _CPU_ISR_Disable(level
);
166 curraddr
= __ARStackPointer
;
167 __ARStackPointer
+= len
;
168 *__ARBlockLen
++ = len
;
170 _CPU_ISR_Restore(level
);
175 u32
AR_Free(u32
*len
)
179 _CPU_ISR_Disable(level
);
181 if(len
) *len
= *__ARBlockLen
;
182 __ARStackPointer
-= *__ARBlockLen
;
184 _CPU_ISR_Restore(level
);
186 return __ARStackPointer
;
189 void AR_Clear(u32 flag
)
194 __ARClearArea(0,__ARInternalSize
);
198 __ARClearArea(0x4000,__ARInternalSize
-0x4000);
200 case AR_ARAMEXPANSION
:
201 if(__ARInternalSize
&& __ARExpansionSize
)
202 __ARClearArea(__ARInternalSize
,__ARExpansionSize
);
211 return __ARInit_Flag
;
224 u32
AR_GetBaseAddress()
229 u32
AR_GetInternalSize()
231 return __ARInternalSize
;
234 static __inline__
void __ARClearInterrupt()
238 cause
= _dspReg
[5]&~(DSPCR_DSPINT
|DSPCR_AIINT
);
240 printf("__ARClearInterrupt(0x%04x)\n",cause
);
242 _dspReg
[5] = (cause
|DSPCR_ARINT
);
245 static __inline__
void __ARWaitDma()
247 while(_dspReg
[5]&DSPCR_DSPDMA
);
250 static void __ARReadDMA(u32 memaddr
,u32 aramaddr
,u32 len
)
253 printf("__ARReadDMA(0x%08x,0x%08x,%d)\n",memaddr
,aramaddr
,len
);
255 // set main memory address
256 _dspReg
[16] = (_dspReg
[16]&~0x03ff)|_SHIFTR(memaddr
,16,16);
257 _dspReg
[17] = (_dspReg
[17]&~0xffe0)|_SHIFTR(memaddr
, 0,16);
260 _dspReg
[18] = (_dspReg
[18]&~0x03ff)|_SHIFTR(aramaddr
,16,16);
261 _dspReg
[19] = (_dspReg
[19]&~0xffe0)|_SHIFTR(aramaddr
, 0,16);
264 _dspReg
[20] = (_dspReg
[20]&~0x8000)|0x8000;
265 _dspReg
[20] = (_dspReg
[20]&~0x03ff)|_SHIFTR(len
,16,16);
266 _dspReg
[21] = (_dspReg
[21]&~0xffe0)|_SHIFTR(len
, 0,16);
269 __ARClearInterrupt();
273 static void __ARWriteDMA(u32 memaddr
,u32 aramaddr
,u32 len
)
276 printf("__ARWriteDMA(0x%08x,0x%08x,%d)\n",memaddr
,aramaddr
,len
);
278 // set main memory address
279 _dspReg
[16] = (_dspReg
[16]&~0x03ff)|_SHIFTR(memaddr
,16,16);
280 _dspReg
[17] = (_dspReg
[17]&~0xffe0)|_SHIFTR(memaddr
, 0,16);
283 _dspReg
[18] = (_dspReg
[18]&~0x03ff)|_SHIFTR(aramaddr
,16,16);
284 _dspReg
[19] = (_dspReg
[19]&~0xffe0)|_SHIFTR(aramaddr
, 0,16);
287 _dspReg
[20] = (_dspReg
[20]&~0x8000);
288 _dspReg
[20] = (_dspReg
[20]&~0x03ff)|_SHIFTR(len
,16,16);
289 _dspReg
[21] = (_dspReg
[21]&~0xffe0)|_SHIFTR(len
, 0,16);
292 __ARClearInterrupt();
295 static void __ARClearArea(u32 aramaddr
,u32 len
)
297 u32 currlen
,curraddr
,endaddr
;
298 static u8 zero_buffer
[2048] ATTRIBUTE_ALIGN(32);
300 while(!(_dspReg
[11]&0x0001));
302 memset(zero_buffer
,0,2048);
303 DCFlushRange(zero_buffer
,2048);
306 endaddr
= aramaddr
+len
;
309 while(curraddr
<endaddr
) {
310 if((endaddr
-curraddr
)<currlen
) currlen
= ((endaddr
-curraddr
)+31)&~31;
311 __ARWriteDMA((u32
)zero_buffer
,curraddr
,currlen
);
316 static void __ARCheckSize()
318 u32 i
,arsize
,arszflag
;
319 static u32 test_data
[8] ATTRIBUTE_ALIGN(32);
320 static u32 dummy_data
[8] ATTRIBUTE_ALIGN(32);
321 static u32 buffer
[8] ATTRIBUTE_ALIGN(32);
324 printf("__ARCheckSize()\n");
327 while(!(_dspReg
[11]&0x0001));
329 __ARSize
= __ARInternalSize
= arsize
= 0x1000000;
330 _dspReg
[9] = (_dspReg
[9]&~0x3f)|0x23;
333 test_data
[i
] = 0xBAD1BAD0;
334 dummy_data
[i
] = 0xDEADBEEF;
336 DCFlushRange(test_data
,32);
337 DCFlushRange(dummy_data
,32);
339 __ARExpansionSize
= 0;
340 __ARWriteDMA((u32
)test_data
,0x1000000,32);
341 __ARWriteDMA((u32
)test_data
,0x1200000,32);
342 __ARWriteDMA((u32
)test_data
,0x2000000,32);
343 __ARWriteDMA((u32
)test_data
,0x1000200,32);
344 __ARWriteDMA((u32
)test_data
,0x1400000,32);
347 DCFlushRange(buffer
,32);
349 __ARWriteDMA((u32
)dummy_data
,0x1000000,32);
351 DCInvalidateRange(buffer
,32);
352 __ARReadDMA((u32
)buffer
,0x1000000,32);
356 if(buffer
[0]==dummy_data
[0]) {
358 DCFlushRange(buffer
,32);
359 __ARReadDMA((u32
)buffer
,0x1200000,32);
361 if(buffer
[0]==dummy_data
[0]) {
362 __ARExpansionSize
= 0x200000;
364 goto end_check
; //not nice but fast
368 DCFlushRange(buffer
,32);
369 __ARReadDMA((u32
)buffer
,0x2000000,32);
371 if(buffer
[0]==dummy_data
[0]) {
372 __ARExpansionSize
= 0x400000;
375 goto end_check
; //not nice but fast
379 DCFlushRange(buffer
,32);
380 __ARReadDMA((u32
)buffer
,0x1400000,32);
382 if(buffer
[0]==dummy_data
[0]) {
383 __ARExpansionSize
= 0x1000000;
387 __ARExpansionSize
= 0x2000000;
392 _dspReg
[9] = (_dspReg
[9]&~0x3f)|arszflag
;
396 printf("__ARCheckSize(%d)\n",arsize
);
398 *(u32
*)0x800000d0 = arsize
;
402 static void __ARHandler()
405 printf("__ARHandler()\n");
407 __ARClearInterrupt();