1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - SCFG
3 File: scfg_proc.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 *---------------------------------------------------------------------------*/
18 #include <nitro/pxi/common/fifo.h>
19 #include <twl/scfg.h>
20
21 typedef struct
22 {
23 BOOL lock;
24 u64 fuseData;
25 u32 readFlag;
26 SCFGCallback callback;
27 void* callbackArg;
28 }
29 SCFGFuseInfo;
30
31 SCFGFuseInfo SCFGi_FuseInfo;
32
33 static void SCFGi_SwitchCpuSpeed( SCFGCpuSpeed cpuSpeed );
34 static void SCFGi_CommonCallback(PXIFifoTag tag, u32 data, BOOL err);
35 static void SCFGi_SendPxiData(u32 command, u16 ordinal, u16 data);
36 static void SCFGi_Sync( u64 fuseData, void* arg );
37
38 /*---------------------------------------------------------------------------*
39 Name: SCFG_Init
40
41 Description: initialize scfg
42
43 Arguments: None
44
45 Returns: None
46 *---------------------------------------------------------------------------*/
SCFG_Init(void)47 void SCFG_Init(void)
48 {
49 PXI_SetFifoRecvCallback( PXI_FIFO_TAG_SCFG, SCFGi_CommonCallback );
50
51 //---- clear fuse info
52 SCFGi_FuseInfo.lock = FALSE;
53 }
54
55 //================================================================================
56 // CPU SPEED
57 //================================================================================
58 /*---------------------------------------------------------------------------*
59 Name: (SCFGi_SwitchCpuSpeed)
60
61 Description: subroutine of SCFG_SetCpuSpeed.
62 switch cpu speed and wait while proper clocks
63
64 Arguments: cpuSpeed : SCFG_CPU_SPEED_1X : same as NITRO (67.03MHz)
65 SCFG_CPU_SPEED_2X : doubled against NITRO (134.06MHz)
66
67 Returns: None
68 *---------------------------------------------------------------------------*/
69 #define SCFGi_SWITCH_CPU_WAIT 10 // 10 cycle for safety (actually 8 cycle is needed)
70 #define SCFGi_SWITCH_CPU_WAIT2 (SCFGi_SWITCH_CPU_WAIT*2)
71
72 #include <twl/itcm_begin.h>
73 #include <nitro/code32.h>
SCFGi_SwitchCpuSpeed(SCFGCpuSpeed cpuSpeed)74 asm void SCFGi_SwitchCpuSpeed( SCFGCpuSpeed cpuSpeed )
75 {
76 //---- get current cpu speed setting
77 ldr r2, =REG_CLK_ADDR
78 ldrh r1, [r2]
79
80 //---- clear bit
81 bic r1, r1, #REG_SCFG_CLK_CPUSPD_MASK // #REG_SCFG_CLK_CPUSPD_MASK = #1
82 orr r1, r0, r1
83 strh r1, [r2]
84
85 cmp r0, #SCFG_CPU_SPEED_1X
86 moveq r0, #SCFGi_SWITCH_CPU_WAIT
87 movne r0, #SCFGi_SWITCH_CPU_WAIT2
88
89 _1:
90 subs r0, r0, #4
91 bcs _1
92 bx lr
93 }
94 #include <nitro/codereset.h>
95 #include <twl/itcm_end.h>
96
97 /*---------------------------------------------------------------------------*
98 Name: SCFG_SetCpuSpeed
99
100 Description: set ARM9 CPU speed
101
102 Arguments: cpuSpeed : SCFG_CPU_SPEED_1X : same as NITRO (67.03MHz)
103 SCFG_CPU_SPEED_2X : doubled against NITRO (134.06MHz)
104 Returns: None
105 *---------------------------------------------------------------------------*/
SCFG_SetCpuSpeed(SCFGCpuSpeed cpuSpeed)106 void SCFG_SetCpuSpeed( SCFGCpuSpeed cpuSpeed )
107 {
108 OSIntrMode enable;
109
110 SDK_ASSERT( cpuSpeed == SCFG_CPU_SPEED_1X || cpuSpeed == SCFG_CPU_SPEED_2X );
111
112 enable = OS_DisableInterrupts();
113
114 //---- if same with current speed, skip switching
115 if ( cpuSpeed != SCFG_GetCpuSpeed() )
116 {
117 SCFGi_SwitchCpuSpeed( cpuSpeed );
118 }
119
120 (void)OS_RestoreInterrupts(enable);
121 }
122
123 //================================================================================
124 // PXI system
125 //================================================================================
126 #define SCFGi_READ_FUSE_DONE 0xf
127
128 /*---------------------------------------------------------------------------*
129 Name: ( SCFGi_CommonCallback )
130
131 Description: SCFG callback for PXI
132
133 Arguments: tag : 5bit
134 pxiData : 26bit
135 err : 1bit
136
137 Returns: None
138 *---------------------------------------------------------------------------*/
SCFGi_CommonCallback(PXIFifoTag tag,u32 pxiData,BOOL err)139 static void SCFGi_CommonCallback( PXIFifoTag tag, u32 pxiData, BOOL err )
140 {
141 #pragma unused (tag, err)
142 u16 command = (u16)( (pxiData & SCFG_PXI_COMMAND_MASK) >> SCFG_PXI_COMMAND_SHIFT );
143 u16 ordinal = (u16)( (pxiData & SCFG_PXI_ORDINAL_MASK) >> SCFG_PXI_ORDINAL_SHIFT );
144 u16 data = (u16)( (pxiData & SCFG_PXI_DATA_MASK) >> SCFG_PXI_DATA_SHIFT );
145
146 switch( command )
147 {
148 case SCFGi_PXI_COMMAND_READ:
149 //OS_Printf("ARM9: (%d) %04x\n", ordinal, data);
150 SCFGi_FuseInfo.fuseData |= (((u64)data) << (ordinal << 4));
151 SCFGi_FuseInfo.readFlag |= (1 << ordinal);
152
153 //---- check if reading fuse data is complete
154 if ( SCFGi_FuseInfo.readFlag == SCFGi_READ_FUSE_DONE )
155 {
156 if (SCFGi_FuseInfo.callback)
157 {
158 (SCFGi_FuseInfo.callback)(SCFGi_FuseInfo.fuseData, SCFGi_FuseInfo.callbackArg);
159 SCFGi_FuseInfo.callback = NULL;
160 }
161 SCFGi_FuseInfo.lock = FALSE;
162 }
163 break;
164 case SCFGi_PXI_COMMAND_READ_OP:
165 {
166 u64 tempData;
167
168 *((u16*)&tempData) = data;
169 if (SCFGi_FuseInfo.callback)
170 {
171 (SCFGi_FuseInfo.callback)(tempData, SCFGi_FuseInfo.callbackArg);
172 SCFGi_FuseInfo.callback = NULL;
173 }
174 SCFGi_FuseInfo.lock = FALSE;
175 }
176 break;
177 default:
178 //---- unknown pxi command
179 OS_Panic("illegal SCFG Pxi.");
180 }
181 }
182
183 /*---------------------------------------------------------------------------*
184 Name: ( SCFGi_SendPxiData )
185
186 Description: send data via PXI
187
188 Arguments: data : data to send
189
190 Returns: None
191 *---------------------------------------------------------------------------*/
SCFGi_SendPxiData(u32 command,u16 ordinal,u16 data)192 static void SCFGi_SendPxiData(u32 command, u16 ordinal, u16 data)
193 {
194 u32 pxiData =
195 (u32)(((command << SCFG_PXI_COMMAND_SHIFT) & SCFG_PXI_COMMAND_MASK) |
196 ((ordinal << SCFG_PXI_ORDINAL_SHIFT) & SCFG_PXI_ORDINAL_MASK) |
197 (( data << SCFG_PXI_DATA_SHIFT) & SCFG_PXI_DATA_MASK ) );
198
199 while (PXI_SendWordByFifo(PXI_FIFO_TAG_SCFG, pxiData, FALSE) != PXI_FIFO_SUCCESS)
200 {
201 // do nothing
202 }
203 }
204
205 /*---------------------------------------------------------------------------*
206 Name: SCFG_ReadFuseDataAsync
207
208 Description: send a read command to ARM7
209
210 Arguments: callback : callback
211 arg : callback argument
212
213 Returns: TRUE : success to send a command
214 FALSE : failed (locked.)
215 *---------------------------------------------------------------------------*/
SCFG_ReadFuseDataAsync(SCFGCallback callback,void * arg)216 BOOL SCFG_ReadFuseDataAsync( SCFGCallback callback, void* arg )
217 {
218 OSIntrMode enable = OS_DisableInterrupts();
219
220 if ( SCFGi_FuseInfo.lock )
221 {
222 (void)OS_RestoreInterrupts(enable);
223 return FALSE;
224 }
225
226 SCFGi_FuseInfo.lock = TRUE;
227 SCFGi_FuseInfo.callback = callback;
228 SCFGi_FuseInfo.callbackArg = arg;
229 SCFGi_FuseInfo.readFlag = 0;
230 SCFGi_FuseInfo.fuseData = 0;
231
232 //---- send a fuse read command to ARM7
233 SCFGi_SendPxiData( SCFGi_PXI_COMMAND_READ, 0, 0 );
234
235 (void)OS_RestoreInterrupts(enable);
236 return TRUE;
237 }
238
239 /*---------------------------------------------------------------------------*
240 Name: SCFG_ReadFuseData
241
242 Description: read fuse data from ARM7.
243 wait till finish to read
244
245 Arguments: None
246
247 Returns: 0 : failed
248 >0 : fuse data
249 *---------------------------------------------------------------------------*/
250 typedef struct
251 {
252 BOOL flag;
253 u64 data;
254 } SCFGiDataForSync;
255
256 //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SCFG_ReadFuseData(void)257 u64 SCFG_ReadFuseData( void )
258 {
259 volatile SCFGiDataForSync info;
260
261 info.flag = FALSE;
262 if ( SCFG_ReadFuseDataAsync( SCFGi_Sync, (void*)&info ) )
263 {
264 while( info.flag == FALSE )
265 {
266 }
267 return info.data;
268 }
269 else
270 {
271 return 0;
272 }
273 }
274
275 /*---------------------------------------------------------------------------*
276 Name: SCFG_ReadBondingOptionAsync
277
278 Description: send a bonding option read command to ARM7
279
280 Arguments: callback : callback
281 arg : callback argument
282
283 Returns: TRUE : success to send a command
284 FALSE : failed (locked.)
285 *---------------------------------------------------------------------------*/
SCFG_ReadBondingOptionAsync(SCFGCallback callback,void * arg)286 BOOL SCFG_ReadBondingOptionAsync( SCFGCallback callback, void* arg )
287 {
288 OSIntrMode enable = OS_DisableInterrupts();
289
290 if ( SCFGi_FuseInfo.lock )
291 {
292 (void)OS_RestoreInterrupts(enable);
293 return FALSE;
294 }
295
296 SCFGi_FuseInfo.lock = TRUE;
297 SCFGi_FuseInfo.callback = callback;
298 SCFGi_FuseInfo.callbackArg = arg;
299
300 //---- send a bonding option read command to ARM7
301 SCFGi_SendPxiData( SCFGi_PXI_COMMAND_READ_OP, 0, 0 );
302
303 (void)OS_RestoreInterrupts(enable);
304 return TRUE;
305 }
306
307 /*---------------------------------------------------------------------------*
308 Name: SCFG_ReadBondingOption
309
310 Description: read bonding option information from ARM7.
311 wait till finish to read
312
313 Arguments: None
314
315 Returns: 0xffff : failed
316 0 ~ 3 : bonding option information
317 *---------------------------------------------------------------------------*/
SCFG_ReadBondingOption(void)318 u16 SCFG_ReadBondingOption( void )
319 {
320 volatile SCFGiDataForSync info;
321
322 info.flag = FALSE;
323 if ( SCFG_ReadBondingOptionAsync( SCFGi_Sync, (void*)&info ) )
324 {
325 while ( info.flag == FALSE )
326 {
327 }
328 return *(u16*)(&info.data);
329 }
330 else
331 {
332 return 0xffff;
333 }
334 }
335
336 /*---------------------------------------------------------------------------*
337 Name: ( SCFGi_Sync )
338
339 Description: callback for SCFG_ReadFuseData to set fusedata
340
341 Arguments: fuseData : fuse data
342 arg : pointer to data info struct
343
344 Returns: None
345 *---------------------------------------------------------------------------*/
SCFGi_Sync(u64 fuseData,void * arg)346 static void SCFGi_Sync( u64 fuseData, void* arg )
347 {
348 ((SCFGiDataForSync*)arg)->flag = TRUE;
349 ((SCFGiDataForSync*)arg)->data = fuseData;
350 }
351