/*---------------------------------------------------------------------------* Project: TwlSDK - CTRDG - libraries - ARM9 File: ctrdg_flash_MX29L010.c Copyright 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:: 2007-11-15#$ $Rev: 2414 $ $Author: hatamoto_minoru $ *---------------------------------------------------------------------------*/ #include // Extern data declaration---------------------- extern u16 CTRDGi_PollingSR1MCOMMON(u16 phase, u8 *adr, u16 lastData); // Function's prototype declaration------------- u16 CTRDGi_EraseFlashChipMX(void); u16 CTRDGi_EraseFlashSectorMX(u16 secNo); u16 CTRDGi_WriteFlashSectorMX(u16 secNo, u8 *src); u32 CTRDGi_EraseFlashChipCoreMX(CTRDGTaskInfo * arg); u32 CTRDGi_EraseFlashSectorCoreMX(CTRDGTaskInfo * arg); u32 CTRDGi_WriteFlashSectorCoreMX(CTRDGTaskInfo * arg); void CTRDGi_EraseFlashChipAsyncMX(CTRDG_TASK_FUNC callback); void CTRDGi_EraseFlashSectorAsyncMX(u16 secNo, CTRDG_TASK_FUNC callback); void CTRDGi_WriteFlashSectorAsyncMX(u16 secNo, u8 *src, CTRDG_TASK_FUNC callback); // Const data----------------------------------- static const u16 MxMaxTime[] = { 10, // Common 10ms 10, // Program 10ms(exactly:20usec) 2000, // Sector erase 2s 2000, // Chip erase 2s }; const CTRDGiFlashTypePlus MX29L010 = { CTRDGi_WriteFlashSectorMX, CTRDGi_EraseFlashChipMX, CTRDGi_EraseFlashSectorMX, CTRDGi_WriteFlashSectorAsyncMX, CTRDGi_EraseFlashChipAsyncMX, CTRDGi_EraseFlashSectorAsyncMX, CTRDGi_PollingSR1MCOMMON, MxMaxTime, { /* For debugging */ //#ifndef __FLASH_DEBUG 0x00020000, // ROM size {0x00001000, 12, 32, 0}, // Sector size, shift, count, top //#else // 0x00004000, // {0x00000200, 9, 32, 0}, //#endif {MI_CTRDG_RAMCYCLE_18, MI_CTRDG_RAMCYCLE_8}, // agb read cycle=8, write cycle=3 0xc2, // Maker ID 0x09, // Device ID }, }; const CTRDGiFlashTypePlus defaultFlash1M = { CTRDGi_WriteFlashSectorMX, CTRDGi_EraseFlashChipMX, CTRDGi_EraseFlashSectorMX, CTRDGi_WriteFlashSectorAsyncMX, CTRDGi_EraseFlashChipAsyncMX, CTRDGi_EraseFlashSectorAsyncMX, CTRDGi_PollingSR1MCOMMON, MxMaxTime, { /* For debugging */ //#ifndef __FLASH_DEBUG 0x00020000, // ROM size {0x00001000, 12, 32, 0}, // Sector size, shift, count, top //#else // 0x00004000, // {0x00000200, 9, 32, 0}, //#endif {MI_CTRDG_RAMCYCLE_18, MI_CTRDG_RAMCYCLE_8}, // agb read cycle=8, write cycle=3 0x00, // Maker ID 0x00, // Device ID }, }; /*Exclusive control*/ extern u16 ctrdgi_flash_lock_id; extern BOOL ctrdgi_backup_irq; /******************************************************* Function's description ********************************************************/ u32 CTRDGi_EraseFlashChipCoreMX(CTRDGTaskInfo * arg) { /* For debugging */ //#ifdef __FLASH_DEBUG // u32 i; //#endif MICartridgeRamCycle ram_cycle; u32 result; (void)arg; /*Exclusive control (lock) */ (void)OS_LockCartridge(ctrdgi_flash_lock_id); /*Access cycle settings */ ram_cycle = MI_GetCartridgeRamCycle(); MI_SetCartridgeRamCycle(AgbFlash->agbWait[0]); // *(vu16 *)REG_EXMEMCNT_ADDR=(*(vu16 *)REG_EXMEMCNT_ADDR & 0xfffc)|AgbFlash->agbWait[0]; // read 3cycles wait ctrdgi_backup_irq = OS_DisableIrq(); *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xaa; *(vu8 *)CTRDG_BACKUP_COM_ADR2 = 0x55; *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0x80; *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xaa; *(vu8 *)CTRDG_BACKUP_COM_ADR2 = 0x55; *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0x10; /* For debugging */ //#ifdef __FLASH_DEBUG // adr=(u8 *)CTRDG_AGB_FLASH_ADR; // for(i=0;iromSize;i++) // *adr++=0xff; //#endif (void)OS_RestoreIrq(ctrdgi_backup_irq); result = CTRDGi_PollingSR(CTRDG_BACKUP_PHASE_CHIP_ERASE, (u8 *)CTRDG_AGB_FLASH_ADR, 0xff); // *(vu16 *)REG_EXMEMCNT_ADDR=(*(vu16 *)REG_EXMEMCNT_ADDR & 0xfffc)| 1; /*Access cycle settings */ MI_SetCartridgeRamCycle(ram_cycle); /*Exclusive control (unlock) */ (void)OS_UnlockCartridge(ctrdgi_flash_lock_id); return result; } u32 CTRDGi_EraseFlashSectorCoreMX(CTRDGTaskInfo * arg) { u8 *adr; u16 retry; MICartridgeRamCycle ram_cycle; u32 result; CTRDGTaskInfo p = *arg; u16 secNo = p.sec_num; if (secNo >= AgbFlash->sector.count) return CTRDG_BACKUP_RESULT_ERROR | CTRDG_BACKUP_PHASE_PARAMETER_CHECK; /*Exclusive control (lock) */ (void)OS_LockCartridge(ctrdgi_flash_lock_id); /*Access cycle settings */ ram_cycle = MI_GetCartridgeRamCycle(); MI_SetCartridgeRamCycle(AgbFlash->agbWait[0]); // Bank set CTRDGi_SetFlashBankMx((u16)(secNo >> 4)); secNo &= 0x0f; retry = 0; erase_again: // *(vu16 *)REG_EXMEMCNT_ADDR=(*(vu16 *)REG_EXMEMCNT_ADDR & 0xfffc)|AgbFlash->agbWait[0]; // read 3cycles wait adr = (u8 *)(CTRDG_AGB_FLASH_ADR + (secNo << AgbFlash->sector.shift)); ctrdgi_backup_irq = OS_DisableIrq(); *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xaa; *(vu8 *)CTRDG_BACKUP_COM_ADR2 = 0x55; *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0x80; *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xaa; *(vu8 *)CTRDG_BACKUP_COM_ADR2 = 0x55; *(vu8 *)adr = 0x30; /* For debugging */ //#ifdef __FLASH_DEBUG // for(i=0;isector.size;i++) // *adr++=0xff; // adr=(u8 *)(CTRDG_AGB_FLASH_ADR+(secNo<sector.shift)); //#endif (void)OS_RestoreIrq(ctrdgi_backup_irq); result = CTRDGi_PollingSR(CTRDG_BACKUP_PHASE_SECTOR_ERASE, adr, 0xff); if (((result & (CTRDG_BACKUP_RESULT_ERROR | CTRDG_BACKUP_RESULT_Q5TIMEOUT)) != 0) && (retry == 0)) { retry++; goto erase_again; } /*Access cycle settings */ MI_SetCartridgeRamCycle(ram_cycle); /*Exclusive control (unlock) */ (void)OS_UnlockCartridge(ctrdgi_flash_lock_id); // *(vu16 *)REG_EXMEMCNT_ADDR=(*(vu16 *)REG_EXMEMCNT_ADDR & 0xfffc)| 1; return result; } static u16 CTRDGi_ProgramFlashByteMX(u8 *src, u8 *dst) { u16 result; /*Exclusive control (lock) */ // OS_LockCartridge(ctrdgi_flash_lock_id); *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xaa; *(vu8 *)CTRDG_BACKUP_COM_ADR2 = 0x55; *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xa0; *dst = *src; result = CTRDGi_PollingSR(CTRDG_BACKUP_PHASE_PROGRAM, dst, *src); /*Exclusive control (unlock) */ // OS_UnlockCartridge(ctrdgi_flash_lock_id); return result; } u32 CTRDGi_WriteFlashSectorCoreMX(CTRDGTaskInfo * arg) { u8 *tgt; //,readFuncBuff[32]; MICartridgeRamCycle ram_cycle; u32 result; CTRDGTaskInfo p = *arg; u16 secNo = p.sec_num; u8 *src = p.data; if (secNo >= AgbFlash->sector.count) return CTRDG_BACKUP_RESULT_ERROR | CTRDG_BACKUP_PHASE_PARAMETER_CHECK; // Erase result = CTRDGi_EraseFlashSectorMX(secNo); if (result) { return result; } /*Exclusive control (lock) */ (void)OS_LockCartridge(ctrdgi_flash_lock_id); /*Access cycle settings */ ram_cycle = MI_GetCartridgeRamCycle(); MI_SetCartridgeRamCycle(AgbFlash->agbWait[0]); // Program // Bank set CTRDGi_SetFlashBankMx((u16)(secNo >> 4)); secNo &= 0x0f; // *(vu16 *)REG_EXMEMCNT_ADDR=(*(vu16 *)REG_EXMEMCNT_ADDR & 0xfffc)|AgbFlash->agbWait[0]; // read 3cycles wait ctrdg_flash_remainder = (u16)AgbFlash->sector.size; tgt = (u8 *)(CTRDG_AGB_FLASH_ADR + (secNo << AgbFlash->sector.shift)); ctrdgi_backup_irq = OS_DisableIrq(); while (ctrdg_flash_remainder) { result = CTRDGi_ProgramFlashByteMX(src, tgt); if (result) break; ctrdg_flash_remainder--; src++; tgt++; } (void)OS_RestoreIrq(ctrdgi_backup_irq); /*Access cycle settings */ MI_SetCartridgeRamCycle(ram_cycle); /*Exclusive control (unlock) */ (void)OS_UnlockCartridge(ctrdgi_flash_lock_id); return result; } u16 CTRDGi_EraseFlashChipMX(void) { u16 result; CTRDGTaskInfo p; result = (u16)CTRDGi_EraseFlashChipCoreMX(&p); return result; } u16 CTRDGi_EraseFlashSectorMX(u16 secNo) { u16 result; CTRDGTaskInfo p; p.sec_num = secNo; result = (u16)CTRDGi_EraseFlashSectorCoreMX(&p); return result; } u16 CTRDGi_WriteFlashSectorMX(u16 secNo, u8 *src) { u16 result; CTRDGTaskInfo p; p.sec_num = secNo; p.data = src; result = (u16)CTRDGi_WriteFlashSectorCoreMX(&p); return result; } void CTRDGi_EraseFlashChipAsyncMX(CTRDG_TASK_FUNC callback) { CTRDGTaskInfo p; CTRDGi_SetTask(&p, CTRDGi_EraseFlashChipCoreMX, callback); } void CTRDGi_EraseFlashSectorAsyncMX(u16 secNo, CTRDG_TASK_FUNC callback) { CTRDGTaskInfo p; p.sec_num = secNo; CTRDGi_SetTask(&p, CTRDGi_EraseFlashSectorCoreMX, callback); } void CTRDGi_WriteFlashSectorAsyncMX(u16 secNo, u8 *src, CTRDG_TASK_FUNC callback) { CTRDGTaskInfo p; p.sec_num = secNo; p.data = src; CTRDGi_SetTask(&p, CTRDGi_WriteFlashSectorCoreMX, callback); }