Subversion Repositories freemyipod

Rev

Rev 58 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 58 Rev 61
Line 80... Line 80...
80
 
80
 
81
uint8_t nand_tunk1[4];
81
uint8_t nand_tunk1[4];
82
uint8_t nand_twp[4];
82
uint8_t nand_twp[4];
83
uint8_t nand_tunk2[4];
83
uint8_t nand_tunk2[4];
84
uint8_t nand_tunk3[4];
84
uint8_t nand_tunk3[4];
85
uint32_t nand_type[4];
85
int nand_type[4];
86
int nand_powered = 0;
86
int nand_powered = 0;
87
int nand_interleaved = 0;
87
int nand_interleaved = 0;
88
int nand_cached = 0;
88
int nand_cached = 0;
89
long nand_last_activity_value = -1;
89
long nand_last_activity_value = -1;
90
static uint32_t nand_stack[0x80];
90
static uint32_t nand_stack[0x80];
Line 297... Line 297...
297
 
297
 
298
uint32_t nand_get_chip_type(uint32_t bank)
298
uint32_t nand_get_chip_type(uint32_t bank)
299
{
299
{
300
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
300
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
301
    uint32_t result;
301
    uint32_t result;
302
    if (nand_reset(bank)) return nand_unlock(0xFFFFFFFF);
302
    if (nand_reset(bank)) return nand_unlock(0xFFFFFFFE);
303
    if (nand_send_cmd(0x90)) return nand_unlock(0xFFFFFFFF);
303
    if (nand_send_cmd(0x90)) return nand_unlock(0xFFFFFFFD);
304
    FMANUM = 0;
304
    FMANUM = 0;
305
    FMADDR0 = 0;
305
    FMADDR0 = 0;
306
    FMCTRL1 = FMCTRL1_DOTRANSADDR;
306
    FMCTRL1 = FMCTRL1_DOTRANSADDR;
307
    if (nand_wait_cmddone()) return nand_unlock(0xFFFFFFFF);
307
    if (nand_wait_cmddone()) return nand_unlock(0xFFFFFFFC);
308
    FMDNUM = 4;
308
    FMDNUM = 4;
309
    FMCTRL1 = FMCTRL1_DOREADDATA;
309
    FMCTRL1 = FMCTRL1_DOREADDATA;
310
    if (nand_wait_addrdone()) return nand_unlock(0xFFFFFFFF);
310
    if (nand_wait_addrdone()) return nand_unlock(0xFFFFFFFB);
311
    result = FMFIFO;
311
    result = FMFIFO;
312
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
312
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
313
    return nand_unlock(result);
313
    return nand_unlock(result);
314
}
314
}
315
 
315
 
Line 341... Line 341...
341
    pmu_ldo_set_voltage(4, 0x15);
341
    pmu_ldo_set_voltage(4, 0x15);
342
    pmu_ldo_power_on(4);
342
    pmu_ldo_power_on(4);
343
    sleep(50000);
343
    sleep(50000);
344
    nand_last_activity_value = USEC_TIMER;
344
    nand_last_activity_value = USEC_TIMER;
345
    for (i = 0; i < 4; i++)
345
    for (i = 0; i < 4; i++)
346
    {
-
 
347
        if(nand_type[i] != 0xFFFFFFFF)
346
        if (nand_type[i] >= 0)
348
        {
-
 
349
            if(nand_reset(i))
347
            if (nand_reset(i))
350
                
-
 
351
				panicf(PANIC_FATAL, "nand_power_up: nand_reset(bank=%d) failed.", (unsigned int)i);
348
				panicf(PANIC_FATAL, "nand_power_up: nand_reset(bank=%d) failed.", (unsigned int)i);
352
        }
-
 
353
    }
-
 
354
    nand_powered = 1;
349
    nand_powered = 1;
355
    nand_last_activity_value = USEC_TIMER;
350
    nand_last_activity_value = USEC_TIMER;
356
    mutex_unlock(&nand_mtx);
351
    mutex_unlock(&nand_mtx);
357
}
352
}
358
 
353
 
Line 503... Line 498...
503
    if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf)
498
    if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf)
504
     || !databuffer || !sparebuffer || !doecc)
499
     || !databuffer || !sparebuffer || !doecc)
505
    {
500
    {
506
        for (i = 0; i < 4; i++)
501
        for (i = 0; i < 4; i++)
507
        {
502
        {
508
            if (nand_type[i] == 0xFFFFFFFF) continue;
503
            if (nand_type[i] < 0) continue;
509
            void* databuf = (void*)0;
504
            void* databuf = (void*)0;
510
            void* sparebuf = (void*)0;
505
            void* sparebuf = (void*)0;
511
            if (databuffer) databuf = (void*)((uint32_t)databuffer + 0x800 * i);
506
            if (databuffer) databuf = (void*)((uint32_t)databuffer + 0x800 * i);
512
            if (sparebuffer) sparebuf = (void*)((uint32_t)sparebuffer + 0x40 * i);
507
            if (sparebuffer) sparebuf = (void*)((uint32_t)sparebuffer + 0x40 * i);
513
            uint32_t ret = nand_read_page(i, page, databuf, sparebuf, doecc, checkempty);
508
            uint32_t ret = nand_read_page(i, page, databuf, sparebuf, doecc, checkempty);
Line 520... Line 515...
520
    }
515
    }
521
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
516
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
522
    nand_last_activity_value = USEC_TIMER;
517
    nand_last_activity_value = USEC_TIMER;
523
    if (!nand_powered) nand_power_up();
518
    if (!nand_powered) nand_power_up();
524
    uint8_t status[4];
519
    uint8_t status[4];
525
    for (i = 0; i < 4; i++) status[i] = (nand_type[i] == 0xFFFFFFFF);
520
    for (i = 0; i < 4; i++) status[i] = (nand_type[i] < 0);
526
    for (i = 0; i < 4; i++)
521
    for (i = 0; i < 4; i++)
527
    {
522
    {
528
        if (!status[i])
523
        if (!status[i])
529
        {
524
        {
530
            nand_set_fmctrl0(i, FMCTRL0_ENABLEDMA);
525
            nand_set_fmctrl0(i, FMCTRL0_ENABLEDMA);
Line 614... Line 609...
614
        if (checkempty)
609
        if (checkempty)
615
            status[i - 1] |= nand_check_empty((void*)((uint32_t)sparebuffer
610
            status[i - 1] |= nand_check_empty((void*)((uint32_t)sparebuffer
616
                                                    + 0x40 * (i - 1))) << 1;
611
                                                    + 0x40 * (i - 1))) << 1;
617
    }
612
    }
618
    for (i = 0; i < 4; i++)
613
    for (i = 0; i < 4; i++)
619
        if (nand_type[i] != 0xFFFFFFFF)
614
        if (nand_type[i] < 0)
620
            rc |= status[i] << (i << 2);
615
            rc |= status[i] << (i << 2);
621
    return nand_unlock(rc);
616
    return nand_unlock(rc);
622
}
617
}
623
 
618
 
624
uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
619
uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
Line 669... Line 664...
669
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
664
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
670
    nand_last_activity_value = USEC_TIMER;
665
    nand_last_activity_value = USEC_TIMER;
671
    if (!nand_powered) nand_power_up();
666
    if (!nand_powered) nand_power_up();
672
    for (i = 0; i < 4; i++)
667
    for (i = 0; i < 4; i++)
673
    {
668
    {
674
        if (nand_type[i] == 0xFFFFFFFF) continue;
669
        if (nand_type[i] < 0) continue;
675
        nand_set_fmctrl0(i, 0);
670
        nand_set_fmctrl0(i, 0);
676
        if (nand_send_cmd(NAND_CMD_BLOCKERASE))
671
        if (nand_send_cmd(NAND_CMD_BLOCKERASE))
677
        {
672
        {
678
            rc |= 1 << i;
673
            rc |= 1 << i;
679
            continue;
674
            continue;
Line 688... Line 683...
688
        }
683
        }
689
        if (nand_send_cmd(NAND_CMD_ERASECNFRM)) rc |= 1 << i;
684
        if (nand_send_cmd(NAND_CMD_ERASECNFRM)) rc |= 1 << i;
690
    }
685
    }
691
    for (i = 0; i < 4; i++)
686
    for (i = 0; i < 4; i++)
692
    {
687
    {
693
        if (nand_type[i] == 0xFFFFFFFF) continue;
688
        if (nand_type[i] < 0) continue;
694
        if (rc & (1 << i)) continue;
689
        if (rc & (1 << i)) continue;
695
        if (nand_wait_status_ready(i)) rc |= 1 << i;
690
        if (nand_wait_status_ready(i)) rc |= 1 << i;
696
    }
691
    }
697
    return nand_unlock(rc);
692
    return nand_unlock(rc);
698
}
693
}
699
 
694
 
700
const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
695
const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
701
{
696
{
702
    if (nand_type[bank] == 0xFFFFFFFF)
697
    if (nand_type[bank] < 0)
703
        return (struct nand_device_info_type*)0;
698
        return (struct nand_device_info_type*)0;
704
    return &nand_deviceinfotable[nand_type[bank]];
699
    return &nand_deviceinfotable[nand_type[bank]];
705
}
700
}
706
 
701
 
707
static void nand_thread(void)
702
static void nand_thread(void)
Line 712... Line 707...
712
            nand_power_down();
707
            nand_power_down();
713
        sleep(100000);
708
        sleep(100000);
714
    }
709
    }
715
}
710
}
716
 
711
 
717
uint32_t nand_device_init(void)
712
int nand_device_init(void)
718
{
713
{
719
    mutex_init(&nand_mtx);
714
    mutex_init(&nand_mtx);
720
    wakeup_init(&nand_wakeup);
715
    wakeup_init(&nand_wakeup);
721
    mutex_init(&ecc_mtx);
716
    mutex_init(&ecc_mtx);
722
    wakeup_init(&ecc_wakeup);
717
    wakeup_init(&ecc_wakeup);
Line 724... Line 719...
724
    uint32_t type;
719
    uint32_t type;
725
    uint32_t i, j;
720
    uint32_t i, j;
726
 
721
 
727
    /* Assume there are 0 banks, to prevent
722
    /* Assume there are 0 banks, to prevent
728
       nand_power_up from talking with them yet. */
723
       nand_power_up from talking with them yet. */
729
    for(i = 0; i < 4; i++) nand_type[i] = 0xFFFFFFFF;
724
    for (i = 0; i < 4; i++) nand_type[i] = -1;
730
    nand_power_up();
725
    nand_power_up();
731
 
726
 
732
    /* Now that the flash is powered on, detect how
727
    /* Now that the flash is powered on, detect how
733
       many banks we really have and initialize them. */
728
       many banks we really have and initialize them. */
734
    for (i = 0; i < 4; i++)
729
    for (i = 0; i < 4; i++)
Line 736... Line 731...
736
        nand_tunk1[i] = 7;
731
        nand_tunk1[i] = 7;
737
        nand_twp[i] = 7;
732
        nand_twp[i] = 7;
738
        nand_tunk2[i] = 7;
733
        nand_tunk2[i] = 7;
739
        nand_tunk3[i] = 7;
734
        nand_tunk3[i] = 7;
740
        type = nand_get_chip_type(i);
735
        type = nand_get_chip_type(i);
741
        if (type == 0xFFFFFFFF) continue;
736
        if (type >= 0xFFFFFFF0)
-
 
737
        {
-
 
738
            nand_type[i] = (int)type;
-
 
739
            continue;
-
 
740
        }
742
        for (j = 0; ; j++)
741
        for (j = 0; ; j++)
743
        {
742
        {
744
            if (j == ARRAYLEN(nand_deviceinfotable)) break;
743
            if (j == ARRAYLEN(nand_deviceinfotable)) break;
745
            else if (nand_deviceinfotable[j].id == type)
744
            else if (nand_deviceinfotable[j].id == type)
746
            {
745
            {
Line 751... Line 750...
751
        nand_tunk1[i] = nand_deviceinfotable[nand_type[i]].tunk1;
750
        nand_tunk1[i] = nand_deviceinfotable[nand_type[i]].tunk1;
752
        nand_twp[i] = nand_deviceinfotable[nand_type[i]].twp;
751
        nand_twp[i] = nand_deviceinfotable[nand_type[i]].twp;
753
        nand_tunk2[i] = nand_deviceinfotable[nand_type[i]].tunk2;
752
        nand_tunk2[i] = nand_deviceinfotable[nand_type[i]].tunk2;
754
        nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3;
753
        nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3;
755
    }
754
    }
756
    if (nand_type[0] == 0xFFFFFFFF) return 1;
755
    if (nand_type[0] < 0) return nand_type[0];
757
    nand_interleaved = ((nand_type[0] >> 22) & 1);
756
    nand_interleaved = ((nand_type[0] >> 22) & 1);
758
    nand_cached = ((nand_type[0] >> 23) & 1);
757
    nand_cached = ((nand_type[0] >> 23) & 1);
759
 
758
 
760
    nand_last_activity_value = USEC_TIMER;
759
    nand_last_activity_value = USEC_TIMER;
761
    thread_create("NAND idle monitor", nand_thread, nand_stack,
760
    thread_create("NAND idle monitor", nand_thread, nand_stack,