1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - CTRDG - libraries - ARM9
3 File: ctrdg_flash_common.c
4
5 Copyright 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:: 2007-11-15#$
14 $Rev: 2414 $
15 $Author: hatamoto_minoru $
16 *---------------------------------------------------------------------------*/
17 #include <nitro.h>
18
19 // Function's prototype declaration-------------
20
21 u32 CTRDGi_ReadAgbFlashCore(CTRDGTaskInfo * arg);
22 u32 CTRDGi_VerifyAgbFlashCore(CTRDGTaskInfo * arg);
23 u32 CTRDGi_WriteAndVerifyAgbFlashSectorCore(CTRDGTaskInfo * arg);
24 u32 CTRDGi_WriteAndVerifyAgbFlashSectorCore(CTRDGTaskInfo * arg);
25
26 u8 CTRDGi_ReadSrFunc(u8 *adr); //The polling function is referenced separately from 512K and 1M
27
28 // Global variables-----------------------------
29
30 u16 ctrdg_flash_remainder;
31
32 const CTRDGFlashType *AgbFlash;
33 u16 (*CTRDGi_WriteAgbFlashSector) (u16 secNo, u8 *src);
34 u16 (*CTRDGi_EraseAgbFlashChip) (void);
35 u16 (*CTRDGi_EraseAgbFlashSector) (u16 sec_num);
36 void (*CTRDGi_WriteAgbFlashSectorAsync) (u16 secNo, u8 *src, CTRDG_TASK_FUNC callback);
37 void (*CTRDGi_EraseAgbFlashChipAsync) (CTRDG_TASK_FUNC callback);
38 void (*CTRDGi_EraseAgbFlashSectorAsync) (u16 sec_num, CTRDG_TASK_FUNC callback);
39 u16 (*CTRDGi_PollingSR) (u16 phase, u8 *adr, u16 lastData);
40 const u16 (*ctrdgi_fl_maxtime);
41
42 OSTick start_tick, timeout_tick;
43
44 /*Exclusive control*/
45 u16 ctrdgi_flash_lock_id;
46 BOOL ctrdgi_backup_irq;
47
48 vu16 ctrdgi_timeoutFlag; //The polling function is referenced separately from 512K and 1M
49
50
51 /*******************************************************
52
53 Function's description
54
55 ********************************************************/
CTRDGi_SetFlashBankMx(u16 bank)56 void CTRDGi_SetFlashBankMx(u16 bank)
57 {
58 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xaa;
59 *(vu8 *)CTRDG_BACKUP_COM_ADR2 = 0x55;
60 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xb0;
61 *(vu8 *)CTRDG_AGB_FLASH_ADR = (u8)bank;
62 }
63
64 // Flash Identify functions---------------------
CTRDGi_ReadFlashID(void)65 u16 CTRDGi_ReadFlashID(void)
66 {
67 u16 flashID;
68
69 // Read flashID
70 ctrdgi_backup_irq = OS_DisableIrq();
71
72 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xaa;
73 *(vu8 *)CTRDG_BACKUP_COM_ADR2 = 0x55;
74 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0x90;
75
76 (void)OS_RestoreIrq(ctrdgi_backup_irq);
77 /*Wait 20 ms */
78 StartFlashTimer(0);
79 while (!ctrdgi_timeoutFlag)
80 {
81 CheckFlashTimer();
82 };
83
84 //Manufacturer ID
85 flashID = (u16)(CTRDGi_ReadSrFunc((u8 *)CTRDG_BACKUP_DEVICE_ID_ADR) << 8);
86 flashID |= CTRDGi_ReadSrFunc((u8 *)CTRDG_BACKUP_VENDER_ID_ADR);
87
88 // Exit readID-mode(ATMEL)
89 ctrdgi_backup_irq = OS_DisableIrq();
90
91 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xaa;
92 *(vu8 *)CTRDG_BACKUP_COM_ADR2 = 0x55;
93 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xf0;
94
95 // Reset
96 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xf0;
97
98 (void)OS_RestoreIrq(ctrdgi_backup_irq);
99
100 //Wait 20ms
101 StartFlashTimer(0);
102 while (!ctrdgi_timeoutFlag)
103 {
104 CheckFlashTimer();
105 };
106
107 return flashID;
108 }
109
110
StartFlashTimer(u16 phase)111 void StartFlashTimer(u16 phase)
112 {
113 ctrdgi_timeoutFlag = FALSE;
114
115 timeout_tick = (u64)*(ctrdgi_fl_maxtime + phase);
116 start_tick = OS_GetTick();
117 }
118
CheckFlashTimer(void)119 void CheckFlashTimer(void)
120 {
121 OSTick current_tick, process_tick, process_time;
122
123 current_tick = OS_GetTick();
124 process_tick = current_tick - start_tick;
125 process_time = OS_TicksToMilliSeconds(process_tick);
126 if (timeout_tick <= process_time)
127 ctrdgi_timeoutFlag = TRUE;
128 }
129
130 // Flash access functions-------------------------------
131
132 //* Use function pointers corresponding to each routine.
133
134 // Data Polling ----------------------------------------
CTRDGi_ReadSrFunc(u8 * adr)135 u8 CTRDGi_ReadSrFunc(u8 *adr)
136 {
137 return *adr;
138 }
139
140
141 //u8 pollflag;
CTRDGi_PollingSR512kCOMMON(u16 phase,u8 * adr,u16 lastData)142 u16 CTRDGi_PollingSR512kCOMMON(u16 phase, u8 *adr, u16 lastData)
143 {
144 u16 poll;
145 u16 result;
146
147 //++++++++++++++++++++++++ For debug
148 // pollflag=1;
149 //++++++++++++++++++++++++
150 result = CTRDG_BACKUP_RESULT_OK;
151 StartFlashTimer(phase);
152 while (1)
153 {
154 poll = CTRDGi_ReadSrFunc(adr);
155 if (poll == lastData)
156 {
157 break;
158 }
159 if (ctrdgi_timeoutFlag)
160 {
161 if (CTRDGi_ReadSrFunc(adr) == lastData)
162 {
163 break;
164 }
165 else
166 {
167 if (AgbFlash->makerID == 0xc2)
168 { // Megachips makerID
169 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xf0; // Command reset
170 }
171 result = (u16)(CTRDG_BACKUP_RESULT_ERROR | CTRDG_BACKUP_RESULT_TIMEOUT | phase);
172 break;
173 }
174 }
175 }
176 if (!CTRDG_IsExisting())
177 result = CTRDG_BACKUP_RESULT_PULLEDOUT;
178 //++++++++++++++++++++++++ For debug
179 // pollflag=0;
180 //++++++++++++++++++++++++ For debug
181 return result;
182 }
183
184
185 //u8 pollflag;
CTRDGi_PollingSR1MCOMMON(u16 phase,u8 * adr,u16 lastData)186 u16 CTRDGi_PollingSR1MCOMMON(u16 phase, u8 *adr, u16 lastData)
187 {
188 u16 poll;
189 u16 result;
190
191 //++++++++++++++++++++++++ For debug
192 // pollflag=1;
193 //++++++++++++++++++++++++
194 result = CTRDG_BACKUP_RESULT_OK;
195 StartFlashTimer(phase);
196 while (1)
197 {
198 CheckFlashTimer();
199 poll = CTRDGi_ReadSrFunc(adr);
200
201 if (poll == lastData)
202 {
203 break;
204 }
205 else
206 {
207 if ((poll & 0x20) != 0)
208 { //Q5(TimeOutFlag)
209 if (CTRDGi_ReadSrFunc(adr) == lastData)
210 {
211 break;
212 }
213 else
214 {
215 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xf0; // Command reset
216 result =
217 (u16)(CTRDG_BACKUP_RESULT_ERROR | CTRDG_BACKUP_RESULT_Q5TIMEOUT | phase);
218 break;
219 }
220 }
221 }
222 if (ctrdgi_timeoutFlag)
223 {
224 if (CTRDGi_ReadSrFunc(adr) == lastData)
225 {
226 break;
227 }
228 else
229 {
230 *(vu8 *)CTRDG_BACKUP_COM_ADR1 = 0xf0; // Command reset
231 result = (u16)(CTRDG_BACKUP_RESULT_ERROR | CTRDG_BACKUP_RESULT_TIMEOUT | phase);
232 break;
233 }
234 }
235 }
236 if (!CTRDG_IsExisting())
237 result = CTRDG_BACKUP_RESULT_PULLEDOUT;
238 //++++++++++++++++++++++++ For debug
239 // pollflag=0;
240 //++++++++++++++++++++++++ For debug
241 return result;
242 }
243
244
245 /*------------------------------------------------------------------*/
246 /* Data readout */
247 /*------------------------------------------------------------------*/
CTRDGi_ReadAgbFlashCore(CTRDGTaskInfo * arg)248 u32 CTRDGi_ReadAgbFlashCore(CTRDGTaskInfo * arg)
249 {
250 u8 *src;
251 MICartridgeRamCycle ram_cycle;
252 CTRDGTaskInfo p = *arg;
253 u16 sec_num = p.sec_num;
254 u32 offset = p.offset;
255 u8 *dst = p.dst;
256 u32 size = p.size;
257
258 /*Exclusive control (lock) */
259 (void)OS_LockCartridge(ctrdgi_flash_lock_id);
260 /*Access cycle settings */
261 ram_cycle = MI_GetCartridgeRamCycle();
262 MI_SetCartridgeRamCycle(MI_CTRDG_RAMCYCLE_18);
263
264 // Set bank if 1MbitFlash
265 if (AgbFlash->romSize == 0x00020000)
266 {
267 CTRDGi_SetFlashBankMx((u16)(sec_num >> 4));
268 sec_num &= 0x0f;
269 }
270
271 src = (u8 *)(CTRDG_AGB_FLASH_ADR + (sec_num << AgbFlash->sector.shift) + offset);
272
273 while (size--)
274 *dst++ = *src++;
275
276 /*Access cycle settings */
277 MI_SetCartridgeRamCycle(ram_cycle);
278 /*Exclusive control (unlock) */
279 (void)OS_UnlockCartridge(ctrdgi_flash_lock_id);
280
281 return 0;
282 }
283
CTRDGi_VerifyFlashSectorCore(u8 * src,u8 * tgt,u32 size)284 static u32 CTRDGi_VerifyFlashSectorCore(u8 *src, u8 *tgt, u32 size)
285 {
286 while (size--)
287 {
288 if (*tgt++ != *src++)
289 return (u32)tgt - 1;
290 }
291 return 0;
292 }
293
294 /*------------------------------------------------------------------*/
295 /* Verfiy data by the byte */
296 /*------------------------------------------------------------------*/
CTRDGi_VerifyAgbFlashCore(CTRDGTaskInfo * arg)297 u32 CTRDGi_VerifyAgbFlashCore(CTRDGTaskInfo * arg)
298 {
299 u8 *tgt;
300 u32 result;
301 MICartridgeRamCycle ram_cycle;
302 CTRDGTaskInfo p = *arg;
303 u16 sec_num = p.sec_num;
304 u8 *src = p.data;
305 u32 size = p.size;
306
307 /*Exclusive control (lock) */
308 (void)OS_LockCartridge(ctrdgi_flash_lock_id);
309 /*Access cycle settings */
310 ram_cycle = MI_GetCartridgeRamCycle();
311 MI_SetCartridgeRamCycle(MI_CTRDG_RAMCYCLE_18);
312
313 // Set bank if 1MbitFlash
314 if (AgbFlash->romSize == 0x00020000)
315 {
316 CTRDGi_SetFlashBankMx((u16)(sec_num >> 4));
317 sec_num &= 0x0f;
318 }
319
320 tgt = (u8 *)(CTRDG_AGB_FLASH_ADR + (sec_num << AgbFlash->sector.shift));
321 result = CTRDGi_VerifyFlashSectorCore(src, tgt, size);
322
323 /*Access cycle settings */
324 MI_SetCartridgeRamCycle(ram_cycle);
325 /*Exclusive control (unlock) */
326 (void)OS_UnlockCartridge(ctrdgi_flash_lock_id);
327 return result;
328 }
329
330
331 /*------------------------------------------------------------------*/
332 /* Write data by the sector; verify by the byte */
333 /*------------------------------------------------------------------*/
CTRDGi_WriteAndVerifyAgbFlashSectorCore(CTRDGTaskInfo * arg)334 u32 CTRDGi_WriteAndVerifyAgbFlashSectorCore(CTRDGTaskInfo * arg)
335 {
336 u16 retry;
337 u32 result;
338 CTRDGTaskInfo p = *arg;
339 u16 sec_num = p.sec_num;
340 u32 offset = p.offset;
341 u8 *src = p.data;
342 u32 verifysize = p.size;
343
344 retry = 0;
345 while (retry < CTRDG_AGB_FLASH_RETRY_MAX)
346 {
347 result = (u32)CTRDG_WriteAgbFlashSector(sec_num, src);
348 if (result == 0)
349 {
350 result = CTRDG_VerifyAgbFlash(sec_num, src, verifysize);
351 if (result == 0)
352 break;
353 }
354 retry++;
355 }
356 return result;
357 }
358
CTRDG_ReadAgbFlash(u16 sec_num,u32 offset,u8 * dst,u32 size)359 void CTRDG_ReadAgbFlash(u16 sec_num, u32 offset, u8 *dst, u32 size)
360 {
361 CTRDGTaskInfo p;
362 p.sec_num = sec_num;
363 p.offset = offset;
364 p.dst = dst;
365 p.size = size;
366
367 (void)CTRDGi_ReadAgbFlashCore(&p);
368 }
369
CTRDG_EraseAgbFlashChip(void)370 u16 CTRDG_EraseAgbFlashChip(void)
371 {
372 u16 result = (*CTRDGi_EraseAgbFlashChip) ();
373
374 return result;
375 }
376
CTRDG_EraseAgbFlashSector(u16 secNo)377 u16 CTRDG_EraseAgbFlashSector(u16 secNo)
378 {
379 u16 result = (*CTRDGi_EraseAgbFlashSector) (secNo);
380
381 return result;
382 }
383
CTRDG_WriteAgbFlashSector(u16 secNo,u8 * src)384 u16 CTRDG_WriteAgbFlashSector(u16 secNo, u8 *src)
385 {
386 u16 result = (*CTRDGi_WriteAgbFlashSector) (secNo, src);
387
388 return result;
389 }
390
CTRDG_VerifyAgbFlash(u16 sec_num,u8 * src,u32 size)391 u32 CTRDG_VerifyAgbFlash(u16 sec_num, u8 *src, u32 size)
392 {
393 u32 result;
394 CTRDGTaskInfo p;
395 p.sec_num = sec_num;
396 p.data = src;
397 p.size = size;
398 result = CTRDGi_VerifyAgbFlashCore(&p);
399
400 return result;
401 }
402
CTRDG_WriteAndVerifyAgbFlash(u16 sec_num,u8 * src,u32 verifysize)403 u32 CTRDG_WriteAndVerifyAgbFlash(u16 sec_num, u8 *src, u32 verifysize)
404 {
405 u32 result;
406 CTRDGTaskInfo p;
407 p.sec_num = sec_num;
408 p.data = src;
409 p.size = verifysize;
410 result = CTRDGi_WriteAndVerifyAgbFlashSectorCore(&p);
411
412 return result;
413 }
414
CTRDG_ReadAgbFlashAsync(u16 sec_num,u32 offset,u8 * dst,u32 size,CTRDG_TASK_FUNC callback)415 void CTRDG_ReadAgbFlashAsync(u16 sec_num, u32 offset, u8 *dst, u32 size, CTRDG_TASK_FUNC callback)
416 {
417 CTRDGTaskInfo p;
418 p.sec_num = sec_num;
419 p.offset = offset;
420 p.dst = dst;
421 p.size = size;
422
423 CTRDGi_SetTask(&p, CTRDGi_ReadAgbFlashCore, callback);
424 }
425
CTRDG_EraseAgbFlashChipAsync(CTRDG_TASK_FUNC callback)426 void CTRDG_EraseAgbFlashChipAsync(CTRDG_TASK_FUNC callback)
427 {
428 (*CTRDGi_EraseAgbFlashChipAsync) (callback);
429 }
430
CTRDG_EraseAgbFlashSectorAsync(u16 secNo,CTRDG_TASK_FUNC callback)431 void CTRDG_EraseAgbFlashSectorAsync(u16 secNo, CTRDG_TASK_FUNC callback)
432 {
433 (*CTRDGi_EraseAgbFlashSectorAsync) (secNo, callback);
434 }
435
CTRDG_WriteAgbFlashSectorAsync(u16 secNo,u8 * src,CTRDG_TASK_FUNC callback)436 void CTRDG_WriteAgbFlashSectorAsync(u16 secNo, u8 *src, CTRDG_TASK_FUNC callback)
437 {
438 (*CTRDGi_WriteAgbFlashSectorAsync) (secNo, src, callback);
439 }
440
CTRDG_VerifyAgbFlashAsync(u16 sec_num,u8 * src,u32 size,CTRDG_TASK_FUNC callback)441 void CTRDG_VerifyAgbFlashAsync(u16 sec_num, u8 *src, u32 size, CTRDG_TASK_FUNC callback)
442 {
443 CTRDGTaskInfo p;
444 p.sec_num = sec_num;
445 p.data = src;
446 p.size = size;
447 CTRDGi_SetTask(&p, CTRDGi_VerifyAgbFlashCore, callback);
448 }
449
CTRDG_WriteAndVerifyAgbFlashAsync(u16 sec_num,u8 * src,u32 verifysize,CTRDG_TASK_FUNC callback)450 void CTRDG_WriteAndVerifyAgbFlashAsync(u16 sec_num, u8 *src, u32 verifysize,
451 CTRDG_TASK_FUNC callback)
452 {
453 CTRDGTaskInfo p;
454 p.sec_num = sec_num;
455 p.data = src;
456 p.size = verifysize;
457 CTRDGi_SetTask(&p, CTRDGi_WriteAndVerifyAgbFlashSectorCore, callback);
458 }
459