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