Subversion Repositories freemyipod

Rev

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

Rev 61 Rev 66
Line 76... Line 76...
76
    {0xA5D5D589, 8192, 7744, 0x80, 7, 2, 1, 2, 1},
76
    {0xA5D5D589, 8192, 7744, 0x80, 7, 2, 1, 2, 1},
77
    {0xA514D320, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
77
    {0xA514D320, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
78
    {0xA555D520, 8192, 3872, 0x80, 7, 2, 1, 2, 1}
78
    {0xA555D520, 8192, 3872, 0x80, 7, 2, 1, 2, 1}
79
};
79
};
80
 
80
 
81
uint8_t nand_tunk1[4];
81
static uint8_t nand_tunk1[4];
82
uint8_t nand_twp[4];
82
static uint8_t nand_twp[4];
83
uint8_t nand_tunk2[4];
83
static uint8_t nand_tunk2[4];
84
uint8_t nand_tunk3[4];
84
static uint8_t nand_tunk3[4];
85
int nand_type[4];
85
static int nand_type[4];
86
int nand_powered = 0;
86
static int nand_powered = 0;
87
int nand_interleaved = 0;
87
static int nand_interleaved = 0;
88
int nand_cached = 0;
88
static int nand_cached = 0;
89
long nand_last_activity_value = -1;
89
static long nand_last_activity_value = -1;
90
static uint32_t nand_stack[0x80];
90
static uint32_t nand_stack[0x80];
91
 
91
 
92
static struct mutex nand_mtx;
92
static struct mutex nand_mtx;
93
static struct wakeup nand_wakeup;
93
static struct wakeup nand_wakeup;
94
static struct mutex ecc_mtx;
94
static struct mutex ecc_mtx;
Line 98... Line 98...
98
static uint8_t nand_ctrl[0x200] CACHEALIGN_ATTR;
98
static uint8_t nand_ctrl[0x200] CACHEALIGN_ATTR;
99
static uint8_t nand_spare[0x40] CACHEALIGN_ATTR;
99
static uint8_t nand_spare[0x40] CACHEALIGN_ATTR;
100
static uint8_t nand_ecc[0x30] CACHEALIGN_ATTR;
100
static uint8_t nand_ecc[0x30] CACHEALIGN_ATTR;
101
 
101
 
102
 
102
 
103
uint32_t nand_unlock(uint32_t rc)
103
static uint32_t nand_unlock(uint32_t rc)
104
{
104
{
105
    nand_last_activity_value = USEC_TIMER;
105
    nand_last_activity_value = USEC_TIMER;
106
    mutex_unlock(&nand_mtx);
106
    mutex_unlock(&nand_mtx);
107
    return rc;
107
    return rc;
108
}
108
}
109
 
109
 
110
uint32_t ecc_unlock(uint32_t rc)
110
static uint32_t ecc_unlock(uint32_t rc)
111
{
111
{
112
    mutex_unlock(&ecc_mtx);
112
    mutex_unlock(&ecc_mtx);
113
    return rc;
113
    return rc;
114
}
114
}
115
 
115
 
116
uint32_t nand_timeout(uint32_t timeout)
116
static uint32_t nand_timeout(long timeout)
117
{
117
{
118
    if (TIME_AFTER(USEC_TIMER, timeout)) return 1;
118
    if (TIME_AFTER(USEC_TIMER, timeout)) return 1;
119
    else
119
    else
120
    {
120
    {
121
        yield();
121
        yield();
122
        return 0;
122
        return 0;
123
    }
123
    }
124
}
124
}
125
 
125
 
126
uint32_t nand_wait_rbbdone(void)
126
static uint32_t nand_wait_rbbdone(void)
127
{
127
{
128
    uint32_t timeout = USEC_TIMER + 20000;
128
    uint32_t timeout = USEC_TIMER + 20000;
129
    while (!(FMCSTAT & FMCSTAT_RBBDONE))
129
    while (!(FMCSTAT & FMCSTAT_RBBDONE))
130
        if (nand_timeout(timeout)) return 1;
130
        if (nand_timeout(timeout)) return 1;
131
    FMCSTAT = FMCSTAT_RBBDONE;
131
    FMCSTAT = FMCSTAT_RBBDONE;
132
    return 0;
132
    return 0;
133
}
133
}
134
 
134
 
135
uint32_t nand_wait_cmddone(void)
135
static uint32_t nand_wait_cmddone(void)
136
{
136
{
137
    uint32_t timeout = USEC_TIMER + 20000;
137
    uint32_t timeout = USEC_TIMER + 20000;
138
    while (!(FMCSTAT & FMCSTAT_CMDDONE))
138
    while (!(FMCSTAT & FMCSTAT_CMDDONE))
139
        if (nand_timeout(timeout)) return 1;
139
        if (nand_timeout(timeout)) return 1;
140
    FMCSTAT = FMCSTAT_CMDDONE;
140
    FMCSTAT = FMCSTAT_CMDDONE;
141
    return 0;
141
    return 0;
142
}
142
}
143
 
143
 
144
uint32_t nand_wait_addrdone(void)
144
static uint32_t nand_wait_addrdone(void)
145
{
145
{
146
    uint32_t timeout = USEC_TIMER + 20000;
146
    uint32_t timeout = USEC_TIMER + 20000;
147
    while (!(FMCSTAT & FMCSTAT_ADDRDONE))
147
    while (!(FMCSTAT & FMCSTAT_ADDRDONE))
148
        if (nand_timeout(timeout)) return 1;
148
        if (nand_timeout(timeout)) return 1;
149
    FMCSTAT = FMCSTAT_ADDRDONE;
149
    FMCSTAT = FMCSTAT_ADDRDONE;
150
    return 0;
150
    return 0;
151
}
151
}
152
 
152
 
153
uint32_t nand_wait_chip_ready(uint32_t bank)
153
static uint32_t nand_wait_chip_ready(uint32_t bank)
154
{
154
{
155
    uint32_t timeout = USEC_TIMER + 20000;
155
    uint32_t timeout = USEC_TIMER + 20000;
156
    while (!(FMCSTAT & (FMCSTAT_BANK0READY << bank)))
156
    while (!(FMCSTAT & (FMCSTAT_BANK0READY << bank)))
157
        if (nand_timeout(timeout)) return 1;
157
        if (nand_timeout(timeout)) return 1;
158
    FMCSTAT = (FMCSTAT_BANK0READY << bank);
158
    FMCSTAT = (FMCSTAT_BANK0READY << bank);
159
    return 0;
159
    return 0;
160
}
160
}
161
 
161
 
162
void nand_set_fmctrl0(uint32_t bank, uint32_t flags)
162
static void nand_set_fmctrl0(uint32_t bank, uint32_t flags)
163
{
163
{
164
    FMCTRL0 = (nand_tunk1[bank] << 16) | (nand_twp[bank] << 12)
164
    FMCTRL0 = (nand_tunk1[bank] << 16) | (nand_twp[bank] << 12)
165
            | (1 << 11) | 1 | (1 << (bank + 1)) | flags;
165
            | (1 << 11) | 1 | (1 << (bank + 1)) | flags;
166
}
166
}
167
 
167
 
168
uint32_t nand_send_cmd(uint32_t cmd)
168
static uint32_t nand_send_cmd(uint32_t cmd)
169
{
169
{
170
    FMCMD = cmd;
170
    FMCMD = cmd;
171
    return nand_wait_rbbdone();
171
    return nand_wait_rbbdone();
172
}
172
}
173
 
173
 
174
uint32_t nand_send_address(uint32_t page, uint32_t offset)
174
static uint32_t nand_send_address(uint32_t page, uint32_t offset)
175
{
175
{
176
    FMANUM = 4;
176
    FMANUM = 4;
177
    FMADDR0 = (page << 16) | offset;
177
    FMADDR0 = (page << 16) | offset;
178
    FMADDR1 = (page >> 16) & 0xFF;
178
    FMADDR1 = (page >> 16) & 0xFF;
179
    FMCTRL1 = FMCTRL1_DOTRANSADDR;
179
    FMCTRL1 = FMCTRL1_DOTRANSADDR;
Line 188... Line 188...
188
    FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
188
    FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
189
    sleep(1000);
189
    sleep(1000);
190
    return 0;
190
    return 0;
191
}
191
}
192
 
192
 
193
uint32_t nand_wait_status_ready(uint32_t bank)
193
static uint32_t nand_wait_status_ready(uint32_t bank)
194
{
194
{
195
    uint32_t timeout = USEC_TIMER + 20000;
195
    uint32_t timeout = USEC_TIMER + 20000;
196
    nand_set_fmctrl0(bank, 0);
196
    nand_set_fmctrl0(bank, 0);
197
    if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)))
197
    if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)))
198
        FMCSTAT = (FMCSTAT_BANK0READY << bank);
198
        FMCSTAT = (FMCSTAT_BANK0READY << bank);
Line 209... Line 209...
209
    }
209
    }
210
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
210
    FMCTRL1 = FMCTRL1_CLEARRFIFO;
211
    return nand_send_cmd(NAND_CMD_READ);
211
    return nand_send_cmd(NAND_CMD_READ);
212
}
212
}
213
 
213
 
214
void nand_transfer_data_start(uint32_t bank, uint32_t direction,
214
static void nand_transfer_data_start(uint32_t bank, uint32_t direction,
215
                              void* buffer, uint32_t size)
215
                                     void* buffer, uint32_t size)
216
{
216
{
217
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
217
    nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
218
    FMDNUM = size - 1;
218
    FMDNUM = size - 1;
219
    FMCTRL1 = FMCTRL1_DOREADDATA << direction;
219
    FMCTRL1 = FMCTRL1_DOREADDATA << direction;
220
    DMACON3 = (2 << DMACON_DEVICE_SHIFT)
220
    DMACON3 = (2 << DMACON_DEVICE_SHIFT)
Line 227... Line 227...
227
    DMATCNT3 = (size >> 4) - 1;
227
    DMATCNT3 = (size >> 4) - 1;
228
    clean_dcache();
228
    clean_dcache();
229
    DMACOM3 = 4;
229
    DMACOM3 = 4;
230
}
230
}
231
 
231
 
232
uint32_t nand_transfer_data_collect(uint32_t direction)
232
static uint32_t nand_transfer_data_collect(uint32_t direction)
233
{
233
{
234
    uint32_t timeout = USEC_TIMER + 20000;
234
    uint32_t timeout = USEC_TIMER + 20000;
235
    while ((DMAALLST & DMAALLST_DMABUSY3))
235
    while ((DMAALLST & DMAALLST_DMABUSY3))
236
        if (nand_timeout(timeout)) return 1;
236
        if (nand_timeout(timeout)) return 1;
237
    if (!direction) invalidate_dcache();
237
    if (!direction) invalidate_dcache();
Line 239... Line 239...
239
    if (!direction) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
239
    if (!direction) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
240
    else FMCTRL1 = FMCTRL1_CLEARRFIFO;
240
    else FMCTRL1 = FMCTRL1_CLEARRFIFO;
241
    return 0;
241
    return 0;
242
}
242
}
243
 
243
 
244
uint32_t nand_transfer_data(uint32_t bank, uint32_t direction,
244
static uint32_t nand_transfer_data(uint32_t bank, uint32_t direction,
245
                            void* buffer, uint32_t size)
245
                                   void* buffer, uint32_t size)
246
{
246
{
247
    nand_transfer_data_start(bank, direction, buffer, size);
247
    nand_transfer_data_start(bank, direction, buffer, size);
248
    uint32_t rc = nand_transfer_data_collect(direction);
248
    uint32_t rc = nand_transfer_data_collect(direction);
249
    return rc;
249
    return rc;
250
}
250
}
251
 
251
 
252
void ecc_start(uint32_t size, void* databuffer, void* sparebuffer, uint32_t type)
252
static void ecc_start(uint32_t size, void* databuffer, void* sparebuffer,
-
 
253
                      uint32_t type)
253
{
254
{
254
    mutex_lock(&ecc_mtx, TIMEOUT_BLOCK);
255
    mutex_lock(&ecc_mtx, TIMEOUT_BLOCK);
255
    ECC_INT_CLR = 1;
256
    ECC_INT_CLR = 1;
256
    SRCPND = INTMSK_ECC;
257
    SRCPND = INTMSK_ECC;
257
    ECC_UNK1 = size;
258
    ECC_UNK1 = size;
Line 259... Line 260...
259
    ECC_SPARE_PTR = (uint32_t)sparebuffer;
260
    ECC_SPARE_PTR = (uint32_t)sparebuffer;
260
    clean_dcache();
261
    clean_dcache();
261
    ECC_CTRL = type;
262
    ECC_CTRL = type;
262
}
263
}
263
 
264
 
264
uint32_t ecc_collect(void)
265
static uint32_t ecc_collect(void)
265
{
266
{
266
    uint32_t timeout = USEC_TIMER + 20000;
267
    uint32_t timeout = USEC_TIMER + 20000;
267
    while (!(SRCPND & INTMSK_ECC))
268
    while (!(SRCPND & INTMSK_ECC))
268
        if (nand_timeout(timeout)) return ecc_unlock(1);
269
        if (nand_timeout(timeout)) return ecc_unlock(1);
269
    invalidate_dcache();
270
    invalidate_dcache();
270
    ECC_INT_CLR = 1;
271
    ECC_INT_CLR = 1;
271
    SRCPND = INTMSK_ECC;
272
    SRCPND = INTMSK_ECC;
272
    return ecc_unlock(ECC_RESULT);
273
    return ecc_unlock(ECC_RESULT);
273
}
274
}
274
 
275
 
275
uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
276
static uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
276
{
277
{
277
    ecc_start(size, databuffer, sparebuffer, ECCCTRL_STARTDECODING);
278
    ecc_start(size, databuffer, sparebuffer, ECCCTRL_STARTDECODING);
278
    uint32_t rc = ecc_collect();
279
    uint32_t rc = ecc_collect();
279
    return rc;
280
    return rc;
280
}
281
}
281
 
282
 
282
uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
283
static uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
283
{
284
{
284
    ecc_start(size, databuffer, sparebuffer, ECCCTRL_STARTENCODING);
285
    ecc_start(size, databuffer, sparebuffer, ECCCTRL_STARTENCODING);
285
    ecc_collect();
286
    ecc_collect();
286
    return 0;
287
    return 0;
287
}
288
}
288
 
289
 
289
uint32_t nand_check_empty(uint8_t* buffer)
290
static uint32_t nand_check_empty(uint8_t* buffer)
290
{
291
{
291
    uint32_t i, count;
292
    uint32_t i, count;
292
    count = 0;
293
    count = 0;
293
    for (i = 0; i < 0x40; i++) if (buffer[i] != 0xFF) count++;
294
    for (i = 0; i < 0x40; i++) if (buffer[i] != 0xFF) count++;
294
    if (count < 2) return 1;
295
    if (count < 2) return 1;
295
    return 0;
296
    return 0;
296
}
297
}
297
 
298
 
298
uint32_t nand_get_chip_type(uint32_t bank)
299
static uint32_t nand_get_chip_type(uint32_t bank)
299
{
300
{
300
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
301
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
301
    uint32_t result;
302
    uint32_t result;
302
    if (nand_reset(bank)) return nand_unlock(0xFFFFFFFE);
303
    if (nand_reset(bank)) return nand_unlock(0xFFFFFFFE);
303
    if (nand_send_cmd(0x90)) return nand_unlock(0xFFFFFFFD);
304
    if (nand_send_cmd(0x90)) return nand_unlock(0xFFFFFFFD);
Line 429... Line 430...
429
    if (checkempty) rc |= nand_check_empty(spare) << 1;
430
    if (checkempty) rc |= nand_check_empty(spare) << 1;
430
 
431
 
431
    return nand_unlock(rc);
432
    return nand_unlock(rc);
432
}
433
}
433
 
434
 
434
uint32_t nand_write_page_int(uint32_t bank, uint32_t page, void* databuffer,
435
static uint32_t nand_write_page_int(uint32_t bank, uint32_t page,
-
 
436
                                    void* databuffer, void* sparebuffer,
435
                             void* sparebuffer, uint32_t doecc, uint32_t wait)
437
                                    uint32_t doecc, uint32_t wait)
436
{
438
{
437
    uint8_t* data = nand_data;
439
    uint8_t* data = nand_data;
438
    uint8_t* spare = nand_spare;
440
    uint8_t* spare = nand_spare;
439
    if (databuffer && !((uint32_t)databuffer & 0xf))
441
    if (databuffer && !((uint32_t)databuffer & 0xf))
440
        data = (uint8_t*)databuffer;
442
        data = (uint8_t*)databuffer;
Line 656... Line 658...
656
uint32_t nand_write_page_collect(uint32_t bank)
658
uint32_t nand_write_page_collect(uint32_t bank)
657
{
659
{
658
    return nand_wait_status_ready(bank);
660
    return nand_wait_status_ready(bank);
659
}
661
}
660
 
662
 
661
uint32_t nand_block_erase_fast(uint32_t page)
663
static uint32_t nand_block_erase_fast(uint32_t page)
662
{
664
{
663
    uint32_t i, rc = 0;
665
    uint32_t i, rc = 0;
664
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
666
    mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
665
    nand_last_activity_value = USEC_TIMER;
667
    nand_last_activity_value = USEC_TIMER;
666
    if (!nand_powered) nand_power_up();
668
    if (!nand_powered) nand_power_up();