/*---------------------------------------------------------------------------* Project: TwlSDK - SCFG File: scfg_proc.c Copyright 2007-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2009-06-19#$ $Rev: 10786 $ $Author: okajima_manabu $ *---------------------------------------------------------------------------*/ #include #include typedef struct { BOOL lock; u64 fuseData; u32 readFlag; SCFGCallback callback; void* callbackArg; } SCFGFuseInfo; SCFGFuseInfo SCFGi_FuseInfo; static void SCFGi_SwitchCpuSpeed( SCFGCpuSpeed cpuSpeed ); static void SCFGi_CommonCallback(PXIFifoTag tag, u32 data, BOOL err); static void SCFGi_SendPxiData(u32 command, u16 ordinal, u16 data); static void SCFGi_Sync( u64 fuseData, void* arg ); /*---------------------------------------------------------------------------* Name: SCFG_Init Description: initialize scfg Arguments: None Returns: None *---------------------------------------------------------------------------*/ void SCFG_Init(void) { PXI_SetFifoRecvCallback( PXI_FIFO_TAG_SCFG, SCFGi_CommonCallback ); //---- clear fuse info SCFGi_FuseInfo.lock = FALSE; } //================================================================================ // CPU SPEED //================================================================================ /*---------------------------------------------------------------------------* Name: (SCFGi_SwitchCpuSpeed) Description: subroutine of SCFG_SetCpuSpeed. switch cpu speed and wait while proper clocks Arguments: cpuSpeed : SCFG_CPU_SPEED_1X : same as NITRO (67.03MHz) SCFG_CPU_SPEED_2X : doubled against NITRO (134.06MHz) Returns: None *---------------------------------------------------------------------------*/ #define SCFGi_SWITCH_CPU_WAIT 10 // 10 cycle for safety (actually 8 cycle is needed) #define SCFGi_SWITCH_CPU_WAIT2 (SCFGi_SWITCH_CPU_WAIT*2) #include #include asm void SCFGi_SwitchCpuSpeed( SCFGCpuSpeed cpuSpeed ) { //---- get current cpu speed setting ldr r2, =REG_CLK_ADDR ldrh r1, [r2] //---- clear bit bic r1, r1, #REG_SCFG_CLK_CPUSPD_MASK // #REG_SCFG_CLK_CPUSPD_MASK = #1 orr r1, r0, r1 strh r1, [r2] cmp r0, #SCFG_CPU_SPEED_1X moveq r0, #SCFGi_SWITCH_CPU_WAIT movne r0, #SCFGi_SWITCH_CPU_WAIT2 _1: subs r0, r0, #4 bcs _1 bx lr } #include #include /*---------------------------------------------------------------------------* Name: SCFG_SetCpuSpeed Description: set ARM9 CPU speed Arguments: cpuSpeed : SCFG_CPU_SPEED_1X : same as NITRO (67.03MHz) SCFG_CPU_SPEED_2X : doubled against NITRO (134.06MHz) Returns: None *---------------------------------------------------------------------------*/ void SCFG_SetCpuSpeed( SCFGCpuSpeed cpuSpeed ) { OSIntrMode enable; SDK_ASSERT( cpuSpeed == SCFG_CPU_SPEED_1X || cpuSpeed == SCFG_CPU_SPEED_2X ); enable = OS_DisableInterrupts(); //---- if same with current speed, skip switching if ( cpuSpeed != SCFG_GetCpuSpeed() ) { SCFGi_SwitchCpuSpeed( cpuSpeed ); } (void)OS_RestoreInterrupts(enable); } //================================================================================ // PXI system //================================================================================ #define SCFGi_READ_FUSE_DONE 0xf /*---------------------------------------------------------------------------* Name: ( SCFGi_CommonCallback ) Description: SCFG callback for PXI Arguments: tag : 5bit pxiData : 26bit err : 1bit Returns: None *---------------------------------------------------------------------------*/ static void SCFGi_CommonCallback( PXIFifoTag tag, u32 pxiData, BOOL err ) { #pragma unused (tag, err) u16 command = (u16)( (pxiData & SCFG_PXI_COMMAND_MASK) >> SCFG_PXI_COMMAND_SHIFT ); u16 ordinal = (u16)( (pxiData & SCFG_PXI_ORDINAL_MASK) >> SCFG_PXI_ORDINAL_SHIFT ); u16 data = (u16)( (pxiData & SCFG_PXI_DATA_MASK) >> SCFG_PXI_DATA_SHIFT ); switch( command ) { case SCFGi_PXI_COMMAND_READ: //OS_TPrintf("ARM9: (%d) %04x\n", ordinal, data); SCFGi_FuseInfo.fuseData |= (((u64)data) << (ordinal << 4)); SCFGi_FuseInfo.readFlag |= (1 << ordinal); //---- check if reading fuse data is complete if ( SCFGi_FuseInfo.readFlag == SCFGi_READ_FUSE_DONE ) { if (SCFGi_FuseInfo.callback) { (SCFGi_FuseInfo.callback)(SCFGi_FuseInfo.fuseData, SCFGi_FuseInfo.callbackArg); SCFGi_FuseInfo.callback = NULL; } SCFGi_FuseInfo.lock = FALSE; } break; case SCFGi_PXI_COMMAND_READ_OP: { u64 tempData; *((u16*)&tempData) = data; if (SCFGi_FuseInfo.callback) { (SCFGi_FuseInfo.callback)(tempData, SCFGi_FuseInfo.callbackArg); SCFGi_FuseInfo.callback = NULL; } SCFGi_FuseInfo.lock = FALSE; } break; default: //---- unknown pxi command OS_TPanic("illegal SCFG Pxi."); } } /*---------------------------------------------------------------------------* Name: ( SCFGi_SendPxiData ) Description: send data via PXI Arguments: data : data to send Returns: None *---------------------------------------------------------------------------*/ static void SCFGi_SendPxiData(u32 command, u16 ordinal, u16 data) { u32 pxiData = (u32)(((command << SCFG_PXI_COMMAND_SHIFT) & SCFG_PXI_COMMAND_MASK) | ((ordinal << SCFG_PXI_ORDINAL_SHIFT) & SCFG_PXI_ORDINAL_MASK) | (( data << SCFG_PXI_DATA_SHIFT) & SCFG_PXI_DATA_MASK ) ); while (PXI_SendWordByFifo(PXI_FIFO_TAG_SCFG, pxiData, FALSE) != PXI_FIFO_SUCCESS) { // do nothing } } /*---------------------------------------------------------------------------* Name: SCFG_ReadFuseDataAsync Description: send a read command to ARM7 Arguments: callback : callback arg : callback argument Returns: TRUE : success to send a command FALSE : failed (locked.) *---------------------------------------------------------------------------*/ BOOL SCFG_ReadFuseDataAsync( SCFGCallback callback, void* arg ) { OSIntrMode enable = OS_DisableInterrupts(); if ( SCFGi_FuseInfo.lock ) { (void)OS_RestoreInterrupts(enable); return FALSE; } SCFGi_FuseInfo.lock = TRUE; SCFGi_FuseInfo.callback = callback; SCFGi_FuseInfo.callbackArg = arg; SCFGi_FuseInfo.readFlag = 0; SCFGi_FuseInfo.fuseData = 0; //---- send a fuse read command to ARM7 SCFGi_SendPxiData( SCFGi_PXI_COMMAND_READ, 0, 0 ); (void)OS_RestoreInterrupts(enable); return TRUE; } /*---------------------------------------------------------------------------* Name: SCFG_ReadFuseData Description: read fuse data from ARM7. wait till finish to read Arguments: None Returns: 0 : failed >0 : fuse data *---------------------------------------------------------------------------*/ typedef struct { BOOL flag; u64 data; } SCFGiDataForSync; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - u64 SCFG_ReadFuseData( void ) { volatile SCFGiDataForSync info; info.flag = FALSE; if ( SCFG_ReadFuseDataAsync( SCFGi_Sync, (void*)&info ) ) { while( info.flag == FALSE ) { } return info.data; } else { return 0; } } /*---------------------------------------------------------------------------* Name: SCFG_ReadBondingOptionAsync Description: send a bonding option read command to ARM7 Arguments: callback : callback arg : callback argument Returns: TRUE : success to send a command FALSE : failed (locked.) *---------------------------------------------------------------------------*/ BOOL SCFG_ReadBondingOptionAsync( SCFGCallback callback, void* arg ) { OSIntrMode enable = OS_DisableInterrupts(); if ( SCFGi_FuseInfo.lock ) { (void)OS_RestoreInterrupts(enable); return FALSE; } SCFGi_FuseInfo.lock = TRUE; SCFGi_FuseInfo.callback = callback; SCFGi_FuseInfo.callbackArg = arg; //---- send a bonding option read command to ARM7 SCFGi_SendPxiData( SCFGi_PXI_COMMAND_READ_OP, 0, 0 ); (void)OS_RestoreInterrupts(enable); return TRUE; } /*---------------------------------------------------------------------------* Name: SCFG_ReadBondingOption Description: read bonding option information from ARM7. wait till finish to read Arguments: None Returns: 0xffff : failed 0 ~ 3 : bonding option information *---------------------------------------------------------------------------*/ u16 SCFG_ReadBondingOption( void ) { volatile SCFGiDataForSync info; info.flag = FALSE; if ( SCFG_ReadBondingOptionAsync( SCFGi_Sync, (void*)&info ) ) { while ( info.flag == FALSE ) { } return *(u16*)(&info.data); } else { return 0xffff; } } /*---------------------------------------------------------------------------* Name: ( SCFGi_Sync ) Description: callback for SCFG_ReadFuseData to set fusedata Arguments: fuseData : fuse data arg : pointer to data info struct Returns: None *---------------------------------------------------------------------------*/ static void SCFGi_Sync( u64 fuseData, void* arg ) { ((SCFGiDataForSync*)arg)->flag = TRUE; ((SCFGiDataForSync*)arg)->data = fuseData; }