Squash another bunch of iPod Nano 2G NAND bugs by moving the idle powerdown code...
[kugel-rb.git] / firmware / target / arm / s5l8700 / ipodnano2g / nand-nano2g.c
blob73673cdd679e6b592e550d0f91b27689b3ae7d93
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2009 by Michael Sparmann
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "config.h"
24 #include "system.h"
25 #include "kernel.h"
26 #include "cpu.h"
27 #include "inttypes.h"
28 #include "nand-target.h"
29 #include <pmu-target.h>
30 #include <mmu-target.h>
31 #include <string.h>
32 #include "led.h"
35 #define NAND_CMD_READ 0x00
36 #define NAND_CMD_PROGCNFRM 0x10
37 #define NAND_CMD_READ2 0x30
38 #define NAND_CMD_BLOCKERASE 0x60
39 #define NAND_CMD_GET_STATUS 0x70
40 #define NAND_CMD_PROGRAM 0x80
41 #define NAND_CMD_ERASECNFRM 0xD0
42 #define NAND_CMD_RESET 0xFF
44 #define NAND_STATUS_READY 0x40
46 #define NAND_DEVICEINFOTABLE_ENTRIES 33
48 static const struct nand_device_info_type nand_deviceinfotable[] =
50 {0x1580F1EC, 1024, 968, 0x40, 6, 2, 1, 2, 1},
51 {0x1580DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
52 {0x15C1DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
53 {0x1510DCEC, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
54 {0x95C1DCEC, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
55 {0x2514DCEC, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
56 {0x2514D3EC, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
57 {0x2555D3EC, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
58 {0x2555D5EC, 8192, 7744, 0x80, 7, 2, 1, 2, 1},
59 {0x2585D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
60 {0x9580DCAD, 4096, 3872, 0x40, 6, 3, 2, 3, 2},
61 {0xA514D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
62 {0xA550D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
63 {0xA560D5AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
64 {0xA555D5AD, 8192, 7744, 0x80, 7, 3, 2, 3, 2},
65 {0xA585D598, 8320, 7744, 0x80, 7, 3, 1, 2, 1},
66 {0xA584D398, 4160, 3872, 0x80, 7, 3, 1, 2, 1},
67 {0x95D1D32C, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
68 {0x1580DC2C, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
69 {0x15C1D32C, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
70 {0x9590DC2C, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
71 {0xA594D32C, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
72 {0x2584DC2C, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
73 {0xA5D5D52C, 8192, 7744, 0x80, 7, 3, 2, 2, 1},
74 {0x95D1D389, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
75 {0x1580DC89, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
76 {0x15C1D389, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
77 {0x9590DC89, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
78 {0xA594D389, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
79 {0x2584DC89, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
80 {0xA5D5D589, 8192, 7744, 0x80, 7, 2, 1, 2, 1},
81 {0xA514D320, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
82 {0xA555D520, 8192, 3872, 0x80, 7, 2, 1, 2, 1}
85 uint8_t nand_tunk1[4];
86 uint8_t nand_twp[4];
87 uint8_t nand_tunk2[4];
88 uint8_t nand_tunk3[4];
89 uint32_t nand_type[4];
90 int nand_powered = 0;
91 long nand_last_activity_value = -1;
92 static long nand_stack[20];
94 static struct mutex nand_mtx;
95 static struct wakeup nand_wakeup;
96 static struct mutex ecc_mtx;
97 static struct wakeup ecc_wakeup;
99 static uint8_t nand_data[0x800] __attribute__((aligned(16)));
100 static uint8_t nand_ctrl[0x200] __attribute__((aligned(16)));
101 static uint8_t nand_spare[0x40] __attribute__((aligned(16)));
102 static uint8_t nand_ecc[0x30] __attribute__((aligned(16)));
105 uint32_t nand_unlock(uint32_t rc)
107 led(false);
108 mutex_unlock(&nand_mtx);
109 return rc;
112 uint32_t ecc_unlock(uint32_t rc)
114 mutex_unlock(&ecc_mtx);
115 return rc;
118 uint32_t nand_timeout(long timeout)
120 if (TIME_AFTER(current_tick, timeout)) return 1;
121 else
123 yield();
124 return 0;
128 uint32_t nand_wait_rbbdone(void)
130 long timeout = current_tick + HZ / 50;
131 while (!(FMCSTAT & FMCSTAT_RBBDONE))
132 if (nand_timeout(timeout)) return 1;
133 FMCSTAT = FMCSTAT_RBBDONE;
134 return 0;
137 uint32_t nand_wait_cmddone(void)
139 long timeout = current_tick + HZ / 50;
140 while (!(FMCSTAT & FMCSTAT_CMDDONE))
141 if (nand_timeout(timeout)) return 1;
142 FMCSTAT = FMCSTAT_CMDDONE;
143 return 0;
146 uint32_t nand_wait_addrdone(void)
148 long timeout = current_tick + HZ / 50;
149 while (!(FMCSTAT & FMCSTAT_ADDRDONE))
150 if (nand_timeout(timeout)) return 1;
151 FMCSTAT = FMCSTAT_ADDRDONE;
152 return 0;
155 uint32_t nand_wait_chip_ready(uint32_t bank)
157 long timeout = current_tick + HZ / 50;
158 while (!(FMCSTAT & (FMCSTAT_BANK0READY << bank)))
159 if (nand_timeout(timeout)) return 1;
160 FMCSTAT = (FMCSTAT_BANK0READY << bank);
161 return 0;
164 void nand_set_fmctrl0(uint32_t bank, uint32_t flags)
166 FMCTRL0 = (nand_tunk1[bank] << 16) | (nand_twp[bank] << 12)
167 | (1 << 11) | 1 | (1 << (bank + 1)) | flags;
170 uint32_t nand_send_cmd(uint32_t cmd)
172 FMCMD = cmd;
173 return nand_wait_rbbdone();
176 uint32_t nand_send_address(uint32_t page, uint32_t offset)
178 FMANUM = 4;
179 FMADDR0 = (page << 16) | offset;
180 FMADDR1 = (page >> 16) & 0xFF;
181 FMCTRL1 = FMCTRL1_DOTRANSADDR;
182 return nand_wait_cmddone();
185 uint32_t nand_reset(uint32_t bank)
187 nand_set_fmctrl0(bank, 0);
188 if (nand_send_cmd(NAND_CMD_RESET)) return 1;
189 if (nand_wait_chip_ready(bank)) return 1;
190 FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
191 return 0;
194 uint32_t nand_wait_status_ready(uint32_t bank)
196 long timeout = current_tick + HZ / 50;
197 nand_set_fmctrl0(bank, 0);
198 if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)))
199 FMCSTAT = (FMCSTAT_BANK0READY << bank);
200 FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
201 if (nand_send_cmd(NAND_CMD_GET_STATUS)) return 1;
202 while (1)
204 if (nand_timeout(timeout)) return 1;
205 FMDNUM = 0;
206 FMCTRL1 = FMCTRL1_DOREADDATA;
207 if (nand_wait_addrdone()) return 1;
208 if ((FMFIFO & NAND_STATUS_READY)) break;
209 FMCTRL1 = FMCTRL1_CLEARRFIFO;
211 FMCTRL1 = FMCTRL1_CLEARRFIFO;
212 return nand_send_cmd(NAND_CMD_READ);
215 uint32_t nand_transfer_data(uint32_t bank, uint32_t direction,
216 void* buffer, uint32_t size)
218 long timeout = current_tick + HZ / 50;
219 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
220 FMDNUM = size - 1;
221 FMCTRL1 = FMCTRL1_DOREADDATA << direction;
222 DMACON3 = (2 << DMACON_DEVICE_SHIFT)
223 | (direction << DMACON_DIRECTION_SHIFT)
224 | (2 << DMACON_DATA_SIZE_SHIFT)
225 | (3 << DMACON_BURST_LEN_SHIFT);
226 while ((DMAALLST & DMAALLST_CHAN3_MASK))
227 DMACOM3 = DMACOM_CLEARBOTHDONE;
228 DMABASE3 = (uint32_t)buffer;
229 DMATCNT3 = (size >> 4) - 1;
230 clean_dcache();
231 DMACOM3 = 4;
232 while ((DMAALLST & DMAALLST_DMABUSY3))
233 if (nand_timeout(timeout)) return 1;
234 if (!direction) invalidate_dcache();
235 if (nand_wait_addrdone()) return 1;
236 if (!direction) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
237 return 0;
240 uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
242 mutex_lock(&ecc_mtx);
243 long timeout = current_tick + HZ / 50;
244 ECC_INT_CLR = 1;
245 SRCPND = INTMSK_ECC;
246 ECC_UNK1 = size;
247 ECC_DATA_PTR = (uint32_t)databuffer;
248 ECC_SPARE_PTR = (uint32_t)sparebuffer;
249 clean_dcache();
250 ECC_CTRL = ECCCTRL_STARTDECODING;
251 while (!(SRCPND & INTMSK_ECC))
252 if (nand_timeout(timeout)) return ecc_unlock(1);
253 invalidate_dcache();
254 ECC_INT_CLR = 1;
255 SRCPND = INTMSK_ECC;
256 return ecc_unlock(ECC_RESULT);
259 uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
261 mutex_lock(&ecc_mtx);
262 long timeout = current_tick + HZ / 50;
263 ECC_INT_CLR = 1;
264 SRCPND = INTMSK_ECC;
265 ECC_UNK1 = size;
266 ECC_DATA_PTR = (uint32_t)databuffer;
267 ECC_SPARE_PTR = (uint32_t)sparebuffer;
268 clean_dcache();
269 ECC_CTRL = ECCCTRL_STARTENCODING;
270 while (!(SRCPND & INTMSK_ECC))
271 if (nand_timeout(timeout)) return ecc_unlock(1);
272 invalidate_dcache();
273 ECC_INT_CLR = 1;
274 SRCPND = INTMSK_ECC;
275 return ecc_unlock(0);
278 uint32_t nand_check_empty(uint8_t* buffer)
280 uint32_t i, count;
281 count = 0;
282 for (i = 0; i < 0x40; i++) if (buffer[i] != 0xFF) count++;
283 if (count < 2) return 1;
284 return 0;
287 uint32_t nand_get_chip_type(uint32_t bank)
289 mutex_lock(&nand_mtx);
290 uint32_t result;
291 if (nand_reset(bank)) return nand_unlock(0xFFFFFFFF);
292 if (nand_send_cmd(0x90)) return nand_unlock(0xFFFFFFFF);
293 FMANUM = 0;
294 FMADDR0 = 0;
295 FMCTRL1 = FMCTRL1_DOTRANSADDR;
296 if (nand_wait_cmddone()) return nand_unlock(0xFFFFFFFF);
297 FMDNUM = 4;
298 FMCTRL1 = FMCTRL1_DOREADDATA;
299 if (nand_wait_addrdone()) return nand_unlock(0xFFFFFFFF);
300 result = FMFIFO;
301 FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
302 return nand_unlock(result);
305 void nand_set_active(void)
307 nand_last_activity_value = current_tick;
310 long nand_last_activity(void)
312 return nand_last_activity_value;
315 void nand_power_up(void)
317 uint32_t i;
318 mutex_lock(&nand_mtx);
319 nand_last_activity_value = current_tick;
320 PWRCONEXT &= ~0x40;
321 PWRCON &= ~0x100000;
322 PCON2 = 0x33333333;
323 PDAT2 = 0;
324 PCON3 = 0x11113333;
325 PDAT3 = 0;
326 PCON4 = 0x33333333;
327 PDAT4 = 0;
328 PCON5 = (PCON5 & ~0xF) | 3;
329 PUNK5 = 1;
330 pmu_ldo_set_voltage(4, 0x15);
331 pmu_ldo_power_on(4);
332 sleep(HZ / 20);
333 nand_last_activity_value = current_tick;
334 for (i = 0; i < 4; i++) nand_reset(i);
335 nand_powered = 1;
336 nand_last_activity_value = current_tick;
337 mutex_unlock(&nand_mtx);
340 void nand_power_down(void)
342 if (!nand_powered) return;
343 mutex_lock(&nand_mtx);
344 pmu_ldo_power_off(4);
345 PCON2 = 0x11111111;
346 PDAT2 = 0;
347 PCON3 = 0x11111111;
348 PDAT3 = 0;
349 PCON4 = 0x11111111;
350 PDAT4 = 0;
351 PCON5 = (PCON5 & ~0xF) | 1;
352 PUNK5 = 1;
353 PWRCONEXT |= 0x40;
354 PWRCON |= 0x100000;
355 nand_powered = 0;
356 mutex_unlock(&nand_mtx);
359 uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
360 void* sparebuffer, uint32_t doecc,
361 uint32_t checkempty)
363 uint8_t* data = nand_data;
364 uint8_t* spare = nand_spare;
365 if (databuffer && !((uint32_t)databuffer & 0xf))
366 data = (uint8_t*)databuffer;
367 if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
368 spare = (uint8_t*)sparebuffer;
369 mutex_lock(&nand_mtx);
370 nand_last_activity_value = current_tick;
371 led(true);
372 if (!nand_powered) nand_power_up();
373 uint32_t rc, eccresult;
374 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
375 if (nand_send_cmd(NAND_CMD_READ)) return nand_unlock(1);
376 if (nand_send_address(page, databuffer ? 0 : 0x800))
377 return nand_unlock(1);
378 if (nand_send_cmd(NAND_CMD_READ2)) return nand_unlock(1);
379 if (nand_wait_status_ready(bank)) return nand_unlock(1);
380 if (databuffer)
381 if (nand_transfer_data(bank, 0, data, 0x800))
382 return nand_unlock(1);
383 rc = 0;
384 if (!doecc)
386 if (databuffer && data != databuffer) memcpy(databuffer, data, 0x800);
387 if (sparebuffer)
389 if (nand_transfer_data(bank, 0, spare, 0x40))
390 return nand_unlock(1);
391 if (sparebuffer && spare != sparebuffer)
392 memcpy(sparebuffer, spare, 0x800);
393 if (checkempty)
394 rc = nand_check_empty((uint8_t*)sparebuffer) << 1;
396 return nand_unlock(rc);
398 if (nand_transfer_data(bank, 0, spare, 0x40)) return nand_unlock(1);
399 memcpy(nand_ecc, &spare[0xC], 0x28);
400 rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
401 if (databuffer && data != databuffer) memcpy(databuffer, data, 0x800);
402 memset(nand_ctrl, 0xFF, 0x200);
403 memcpy(nand_ctrl, spare, 0xC);
404 memcpy(nand_ecc, &spare[0x34], 0xC);
405 eccresult = ecc_decode(0, nand_ctrl, nand_ecc);
406 rc |= (eccresult & 0xF) << 8;
407 if (sparebuffer)
409 if (spare != sparebuffer) memcpy(sparebuffer, spare, 0x40);
410 if (eccresult & 1) memset(sparebuffer, 0xFF, 0xC);
411 else memcpy(sparebuffer, nand_ctrl, 0xC);
413 if (checkempty) rc |= nand_check_empty(spare) << 1;
415 return nand_unlock(rc);
418 uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
419 void* sparebuffer, uint32_t doecc)
421 uint8_t* data = nand_data;
422 uint8_t* spare = nand_spare;
423 if (databuffer && !((uint32_t)databuffer & 0xf))
424 data = (uint8_t*)databuffer;
425 if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
426 spare = (uint8_t*)sparebuffer;
427 mutex_lock(&nand_mtx);
428 nand_last_activity_value = current_tick;
429 led(true);
430 if (!nand_powered) nand_power_up();
431 if (sparebuffer)
433 if (spare != sparebuffer) memcpy(spare, sparebuffer, 0x40);
435 else memset(spare, 0xFF, 0x40);
436 if (doecc)
438 if (databuffer && data != databuffer) memcpy(data, databuffer, 0x800);
439 if (ecc_encode(3, data, nand_ecc)) return nand_unlock(1);
440 memcpy(&spare[0xC], nand_ecc, 0x28);
441 memset(nand_ctrl, 0xFF, 0x200);
442 memcpy(nand_ctrl, spare, 0xC);
443 if (ecc_encode(0, nand_ctrl, nand_ecc)) return nand_unlock(1);
444 memcpy(&spare[0x34], nand_ecc, 0xC);
446 nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
447 if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1);
448 if (nand_send_address(page, databuffer ? 0 : 0x800))
449 return nand_unlock(1);
450 if (databuffer)
451 if (nand_transfer_data(bank, 1, data, 0x800))
452 return nand_unlock(1);
453 if (sparebuffer || doecc)
454 if (nand_transfer_data(bank, 1, spare, 0x40))
455 return nand_unlock(1);
456 if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return nand_unlock(1);
457 return nand_unlock(nand_wait_status_ready(bank));
460 uint32_t nand_block_erase(uint32_t bank, uint32_t page)
462 mutex_lock(&nand_mtx);
463 nand_last_activity_value = current_tick;
464 led(true);
465 if (!nand_powered) nand_power_up();
466 nand_set_fmctrl0(bank, 0);
467 if (nand_send_cmd(NAND_CMD_BLOCKERASE)) return nand_unlock(1);
468 FMANUM = 2;
469 FMADDR0 = page;
470 FMCTRL1 = FMCTRL1_DOTRANSADDR;
471 if (nand_wait_cmddone()) return nand_unlock(1);
472 if (nand_send_cmd(NAND_CMD_ERASECNFRM)) return nand_unlock(1);
473 if (nand_wait_status_ready(bank)) return nand_unlock(1);
474 return nand_unlock(0);
477 const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
479 if (nand_type[bank] == 0xFFFFFFFF)
480 return (struct nand_device_info_type*)0;
481 return &nand_deviceinfotable[nand_type[bank]];
484 static void nand_thread(void)
486 while (1)
488 if (TIME_AFTER(current_tick, nand_last_activity_value + HZ / 5)
489 && nand_powered)
490 nand_power_down();
491 sleep(HZ / 10);
495 uint32_t nand_device_init(void)
497 mutex_init(&nand_mtx);
498 wakeup_init(&nand_wakeup);
499 mutex_init(&ecc_mtx);
500 wakeup_init(&ecc_wakeup);
502 uint32_t type;
503 uint32_t i, j;
504 nand_power_up();
505 for (i = 0; i < 4; i++)
507 nand_tunk1[i] = 7;
508 nand_twp[i] = 7;
509 nand_tunk2[i] = 7;
510 nand_tunk3[i] = 7;
511 type = nand_get_chip_type(i);
512 nand_type[i] = 0xFFFFFFFF;
513 if (type == 0xFFFFFFFF) continue;
514 for (j = 0; ; j++)
516 if (j == ARRAYLEN(nand_deviceinfotable)) break;
517 else if (nand_deviceinfotable[j].id == type)
519 nand_type[i] = j;
520 break;
523 nand_tunk1[i] = nand_deviceinfotable[nand_type[i]].tunk1;
524 nand_twp[i] = nand_deviceinfotable[nand_type[i]].twp;
525 nand_tunk2[i] = nand_deviceinfotable[nand_type[i]].tunk2;
526 nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3;
528 if (nand_type[0] == 0xFFFFFFFF) return 1;
530 nand_last_activity_value = current_tick;
531 create_thread(nand_thread, nand_stack,
532 sizeof(nand_stack), 0, "nand"
533 IF_PRIO(, PRIORITY_USER_INTERFACE)
534 IF_COP(, CPU));
536 return 0;