summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c')
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c204
1 files changed, 201 insertions, 3 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
index 3b5f88d3c2..84bf0e6bb8 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c
@@ -99,13 +99,14 @@ static struct wakeup ecc_wakeup;
99 99
100static uint8_t nand_data[0x800] __attribute__((aligned(16))); 100static uint8_t nand_data[0x800] __attribute__((aligned(16)));
101static uint8_t nand_ctrl[0x200] __attribute__((aligned(16))); 101static uint8_t nand_ctrl[0x200] __attribute__((aligned(16)));
102static uint8_t nand_spare[0x40] __attribute__((aligned(16))); 102static uint8_t nand_spare[4][0x40] __attribute__((aligned(16)));
103static uint8_t nand_ecc[0x30] __attribute__((aligned(16))); 103static uint8_t nand_ecc[0x30] __attribute__((aligned(16)));
104 104
105 105
106uint32_t nand_unlock(uint32_t rc) 106uint32_t nand_unlock(uint32_t rc)
107{ 107{
108 led(false); 108 led(false);
109 nand_last_activity_value = current_tick;
109 mutex_unlock(&nand_mtx); 110 mutex_unlock(&nand_mtx);
110 return rc; 111 return rc;
111} 112}
@@ -371,7 +372,7 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
371 uint32_t checkempty) 372 uint32_t checkempty)
372{ 373{
373 uint8_t* data = nand_data; 374 uint8_t* data = nand_data;
374 uint8_t* spare = nand_spare; 375 uint8_t* spare = nand_spare[0];
375 if (databuffer && !((uint32_t)databuffer & 0xf)) 376 if (databuffer && !((uint32_t)databuffer & 0xf))
376 data = (uint8_t*)databuffer; 377 data = (uint8_t*)databuffer;
377 if (sparebuffer && !((uint32_t)sparebuffer & 0xf)) 378 if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
@@ -432,7 +433,7 @@ uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
432 void* sparebuffer, uint32_t doecc) 433 void* sparebuffer, uint32_t doecc)
433{ 434{
434 uint8_t* data = nand_data; 435 uint8_t* data = nand_data;
435 uint8_t* spare = nand_spare; 436 uint8_t* spare = nand_spare[0];
436 if (databuffer && !((uint32_t)databuffer & 0xf)) 437 if (databuffer && !((uint32_t)databuffer & 0xf))
437 data = (uint8_t*)databuffer; 438 data = (uint8_t*)databuffer;
438 if (sparebuffer && !((uint32_t)sparebuffer & 0xf)) 439 if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
@@ -487,6 +488,203 @@ uint32_t nand_block_erase(uint32_t bank, uint32_t page)
487 return nand_unlock(0); 488 return nand_unlock(0);
488} 489}
489 490
491uint32_t nand_read_page_fast(uint32_t page, void* databuffer,
492 void* sparebuffer, uint32_t doecc,
493 uint32_t checkempty)
494{
495 uint32_t i, rc = 0;
496 if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf)
497 || !databuffer || !sparebuffer || !doecc)
498 {
499 for (i = 0; i < 4; i++)
500 {
501 if (nand_type[i] == 0xFFFFFFFF) continue;
502 void* databuf = (void*)0;
503 void* sparebuf = (void*)0;
504 if (databuffer) databuf = (void*)((uint32_t)databuffer + 0x800 * i);
505 if (sparebuffer) sparebuf = (void*)((uint32_t)sparebuffer + 0x40 * i);
506 uint32_t ret = nand_read_page(i, page, databuf, sparebuf, doecc, checkempty);
507 if (ret & 1) rc |= 1 << (i << 2);
508 if (ret & 2) rc |= 2 << (i << 2);
509 if (ret & 0x10) rc |= 4 << (i << 2);
510 if (ret & 0x100) rc |= 8 << (i << 2);
511 }
512 return rc;
513 }
514 mutex_lock(&nand_mtx);
515 nand_last_activity_value = current_tick;
516 led(true);
517 if (!nand_powered) nand_power_up();
518 for (i = 0; i < 4; i++)
519 {
520 if (nand_type[i] == 0xFFFFFFFF) continue;
521 nand_set_fmctrl0(i, FMCTRL0_ENABLEDMA);
522 if (nand_send_cmd(NAND_CMD_READ))
523 {
524 rc |= 1 << (i << 2);
525 continue;
526 }
527 if (nand_send_address(page, databuffer ? 0 : 0x800))
528 {
529 rc |= 1 << (i << 2);
530 continue;
531 }
532 if (nand_send_cmd(NAND_CMD_READ2))
533 {
534 rc |= 1 << (i << 2);
535 continue;
536 }
537 }
538 for (i = 0; i < 4; i++)
539 {
540 if (nand_type[i] == 0xFFFFFFFF) continue;
541 if (nand_wait_status_ready(i))
542 {
543 rc |= 1 << (i << 2);
544 continue;
545 }
546 if (nand_transfer_data(i, 0, (void*)((uint32_t)databuffer
547 + 0x800 * i), 0x800))
548 {
549 rc |= 1 << (i << 2);
550 continue;
551 }
552 if (nand_transfer_data(i, 0, (void*)((uint32_t)sparebuffer
553 + 0x40 * i), 0x40))
554 {
555 rc |= 1 << (i << 2);
556 continue;
557 }
558 memcpy(nand_ecc, (void*)((uint32_t)sparebuffer + 0x40 * i + 0xC), 0x28);
559 if (ecc_decode(3, (void*)((uint32_t)databuffer + 0x800 * i), nand_ecc) & 1)
560 rc |= 4 << (i << 2);
561 memset(nand_ctrl, 0xFF, 0x200);
562 memcpy(nand_ctrl, (void*)((uint32_t)sparebuffer + 0x40 * i), 0xC);
563 memcpy(nand_ecc, (void*)((uint32_t)sparebuffer + 0x40 * i + 0x34), 0xC);
564 if (ecc_decode(0, nand_ctrl, nand_ecc))
565 {
566 rc |= 8 << (i << 2);
567 memset((void*)((uint32_t)sparebuffer + 0x40 * i), 0xFF, 0xC);
568 }
569 else memcpy((void*)((uint32_t)sparebuffer + 0x40 * i), nand_ctrl, 0xC);
570 if (checkempty)
571 rc |= nand_check_empty((void*)((uint32_t)sparebuffer
572 + 0x40 * i)) << ((i << 2) + 1);
573 }
574 return nand_unlock(rc);
575}
576
577uint32_t nand_write_page_fast(uint32_t page, void* databuffer,
578 void* sparebuffer, uint32_t doecc)
579{
580 uint32_t i, rc = 0;
581 if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf)
582 || !databuffer || !sparebuffer || !doecc)
583 {
584 for (i = 0; i < 4; i++)
585 {
586 if (nand_type[i] == 0xFFFFFFFF) continue;
587 void* databuf = (void*)0;
588 void* sparebuf = (void*)0;
589 if (databuffer) databuf = (void*)((uint32_t)databuffer + 0x800 * i);
590 if (sparebuffer) sparebuf = (void*)((uint32_t)sparebuffer + 0x40 * i);
591 rc |= nand_write_page(i, page, databuf, sparebuf, doecc) << i;
592 }
593 return rc;
594 }
595 mutex_lock(&nand_mtx);
596 nand_last_activity_value = current_tick;
597 led(true);
598 if (!nand_powered) nand_power_up();
599 for (i = 0; i < 4; i++)
600 {
601 if (nand_type[i] == 0xFFFFFFFF) continue;
602 if (ecc_encode(3, (void*)((uint32_t)databuffer + 0x800 * i), nand_ecc))
603 {
604 rc |= 1 << i;
605 continue;
606 }
607 memcpy((void*)((uint32_t)sparebuffer + 0x40 * i + 0xC), nand_ecc, 0x28);
608 memset(nand_ctrl, 0xFF, 0x200);
609 memcpy(nand_ctrl, (void*)((uint32_t)sparebuffer + 0x40 * i), 0xC);
610 if (ecc_encode(0, nand_ctrl, nand_ecc))
611 {
612 rc |= 1 << i;
613 continue;
614 }
615 memcpy((void*)((uint32_t)sparebuffer + 0x40 * i + 0x34), nand_ecc, 0xC);
616 nand_set_fmctrl0(i, FMCTRL0_ENABLEDMA);
617 if (nand_send_cmd(NAND_CMD_PROGRAM))
618 {
619 rc |= 1 << i;
620 continue;
621 }
622 if (nand_send_address(page, databuffer ? 0 : 0x800))
623 {
624 rc |= 1 << i;
625 continue;
626 }
627 if (nand_transfer_data(i, 1, (void*)((uint32_t)databuffer
628 + 0x800 * i), 0x800))
629 {
630 rc |= 1 << i;
631 continue;
632 }
633 if (nand_transfer_data(i, 1, (void*)((uint32_t)sparebuffer
634 + 0x40 * i), 0x40))
635 {
636 rc |= 1 << i;
637 continue;
638 }
639 if (nand_send_cmd(NAND_CMD_PROGCNFRM))
640 {
641 rc |= 1 << i;
642 continue;
643 }
644 }
645 for (i = 0; i < 4; i++)
646 {
647 if (nand_type[i] == 0xFFFFFFFF) continue;
648 rc |= nand_wait_status_ready(i) << i;
649 }
650 return nand_unlock(rc);
651}
652
653uint32_t nand_block_erase_fast(uint32_t page)
654{
655 uint32_t i, rc = 0;
656 mutex_lock(&nand_mtx);
657 nand_last_activity_value = current_tick;
658 led(true);
659 if (!nand_powered) nand_power_up();
660 for (i = 0; i < 4; i++)
661 {
662 if (nand_type[i] == 0xFFFFFFFF) continue;
663 nand_set_fmctrl0(i, 0);
664 if (nand_send_cmd(NAND_CMD_BLOCKERASE))
665 {
666 rc |= 1 << i;
667 continue;
668 }
669 FMANUM = 2;
670 FMADDR0 = page;
671 FMCTRL1 = FMCTRL1_DOTRANSADDR;
672 if (nand_wait_cmddone())
673 {
674 rc |= 1 << i;
675 continue;
676 }
677 if (nand_send_cmd(NAND_CMD_ERASECNFRM)) rc |= 1 << i;
678 }
679 for (i = 0; i < 4; i++)
680 {
681 if (nand_type[i] == 0xFFFFFFFF) continue;
682 if (rc & (1 << i)) continue;
683 if (nand_wait_status_ready(i)) rc |= 1 << i;
684 }
685 return nand_unlock(rc);
686}
687
490const struct nand_device_info_type* nand_get_device_type(uint32_t bank) 688const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
491{ 689{
492 if (nand_type[bank] == 0xFFFFFFFF) 690 if (nand_type[bank] == 0xFFFFFFFF)