| Line 92... |
Line 92... |
| 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;
|
| 95 |
static struct wakeup ecc_wakeup;
|
95 |
static struct wakeup ecc_wakeup;
|
| 96 |
|
96 |
|
| 97 |
static uint8_t nand_data[0x800] CACHEALIGN_ATTR;
|
- |
|
| 98 |
static uint8_t nand_ctrl[0x200] CACHEALIGN_ATTR;
|
97 |
static uint8_t nand_ctrl[0x200] CACHEALIGN_ATTR;
|
| 99 |
static uint8_t nand_spare[0x40] CACHEALIGN_ATTR;
|
98 |
static uint8_t nand_spare[0x40] CACHEALIGN_ATTR;
|
| 100 |
static uint8_t nand_ecc[0x30] CACHEALIGN_ATTR;
|
99 |
static uint8_t nand_ecc[0x30] CACHEALIGN_ATTR;
|
| 101 |
|
100 |
|
| 102 |
|
101 |
|
| Line 373... |
Line 372... |
| 373 |
|
372 |
|
| 374 |
uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
|
373 |
uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
|
| 375 |
void* sparebuffer, uint32_t doecc,
|
374 |
void* sparebuffer, uint32_t doecc,
|
| 376 |
uint32_t checkempty)
|
375 |
uint32_t checkempty)
|
| 377 |
{
|
376 |
{
|
| 378 |
uint8_t* data = nand_data;
|
377 |
uint8_t* data = (uint8_t*)databuffer;
|
| 379 |
uint8_t* spare = nand_spare;
|
378 |
uint8_t* spare = nand_spare;
|
| 380 |
if (databuffer && !((uint32_t)databuffer & 0xf))
|
379 |
if (sparebuffer) spare = (uint8_t*)sparebuffer;
|
| 381 |
data = (uint8_t*)databuffer;
|
380 |
if ((uint32_t)databuffer & 0xf)
|
| - |
|
381 |
panicf(PANIC_KILLUSERTHREADS,
|
| - |
|
382 |
"nand_read_page: Misaligned data buffer at %08X (bank %lu, page %lu)",
|
| - |
|
383 |
(unsigned int)databuffer, bank, page);
|
| 382 |
if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
|
384 |
if ((uint32_t)sparebuffer & 0xf)
|
| - |
|
385 |
panicf(PANIC_KILLUSERTHREADS,
|
| - |
|
386 |
"nand_read_page: Misaligned spare buffer at %08X (bank %lu, page %lu)",
|
| 383 |
spare = (uint8_t*)sparebuffer;
|
387 |
(unsigned int)sparebuffer, bank, page);
|
| 384 |
mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
|
388 |
mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
|
| 385 |
nand_last_activity_value = USEC_TIMER;
|
389 |
nand_last_activity_value = USEC_TIMER;
|
| 386 |
if (!nand_powered) nand_power_up();
|
390 |
if (!nand_powered) nand_power_up();
|
| 387 |
uint32_t rc, eccresult;
|
391 |
uint32_t rc, eccresult;
|
| 388 |
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
392 |
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
| 389 |
if (nand_send_cmd(NAND_CMD_READ)) return nand_unlock(1);
|
393 |
if (nand_send_cmd(NAND_CMD_READ)) return nand_unlock(1);
|
| 390 |
if (nand_send_address(page, databuffer ? 0 : 0x800))
|
394 |
if (nand_send_address(page, data ? 0 : 0x800))
|
| 391 |
return nand_unlock(1);
|
395 |
return nand_unlock(1);
|
| 392 |
if (nand_send_cmd(NAND_CMD_READ2)) return nand_unlock(1);
|
396 |
if (nand_send_cmd(NAND_CMD_READ2)) return nand_unlock(1);
|
| 393 |
if (nand_wait_status_ready(bank)) return nand_unlock(1);
|
397 |
if (nand_wait_status_ready(bank)) return nand_unlock(1);
|
| 394 |
if (databuffer)
|
398 |
if (data)
|
| 395 |
if (nand_transfer_data(bank, 0, data, 0x800))
|
399 |
if (nand_transfer_data(bank, 0, data, 0x800))
|
| 396 |
return nand_unlock(1);
|
400 |
return nand_unlock(1);
|
| 397 |
rc = 0;
|
401 |
rc = 0;
|
| 398 |
if (!doecc)
|
402 |
if (!doecc)
|
| 399 |
{
|
403 |
{
|
| 400 |
if (databuffer && data != databuffer) memcpy(databuffer, data, 0x800);
|
- |
|
| 401 |
if (sparebuffer)
|
404 |
if (sparebuffer)
|
| 402 |
{
|
405 |
{
|
| 403 |
if (nand_transfer_data(bank, 0, spare, 0x40))
|
406 |
if (nand_transfer_data(bank, 0, spare, 0x40))
|
| 404 |
return nand_unlock(1);
|
407 |
return nand_unlock(1);
|
| 405 |
if (sparebuffer && spare != sparebuffer)
|
408 |
if (sparebuffer)
|
| 406 |
memcpy(sparebuffer, spare, 0x800);
|
409 |
memcpy(sparebuffer, spare, 0x800);
|
| 407 |
if (checkempty)
|
410 |
if (checkempty)
|
| 408 |
rc = nand_check_empty((uint8_t*)sparebuffer) << 1;
|
411 |
rc = nand_check_empty((uint8_t*)sparebuffer) << 1;
|
| 409 |
}
|
412 |
}
|
| 410 |
return nand_unlock(rc);
|
413 |
return nand_unlock(rc);
|
| Line 412... |
Line 415... |
| 412 |
if (nand_transfer_data(bank, 0, spare, 0x40)) return nand_unlock(1);
|
415 |
if (nand_transfer_data(bank, 0, spare, 0x40)) return nand_unlock(1);
|
| 413 |
if (databuffer)
|
416 |
if (databuffer)
|
| 414 |
{
|
417 |
{
|
| 415 |
memcpy(nand_ecc, &spare[0xC], 0x28);
|
418 |
memcpy(nand_ecc, &spare[0xC], 0x28);
|
| 416 |
rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
|
419 |
rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
|
| 417 |
if (data != databuffer) memcpy(databuffer, data, 0x800);
|
- |
|
| 418 |
}
|
420 |
}
|
| 419 |
memset(nand_ctrl, 0xFF, 0x200);
|
421 |
memset(nand_ctrl, 0xFF, 0x200);
|
| 420 |
memcpy(nand_ctrl, spare, 0xC);
|
422 |
memcpy(nand_ctrl, spare, 0xC);
|
| 421 |
memcpy(nand_ecc, &spare[0x34], 0xC);
|
423 |
memcpy(nand_ecc, &spare[0x34], 0xC);
|
| 422 |
eccresult = ecc_decode(0, nand_ctrl, nand_ecc);
|
424 |
eccresult = ecc_decode(0, nand_ctrl, nand_ecc);
|
| 423 |
rc |= (eccresult & 0xF) << 8;
|
425 |
rc |= (eccresult & 0xF) << 8;
|
| 424 |
if (sparebuffer)
|
426 |
if (sparebuffer)
|
| 425 |
{
|
427 |
{
|
| 426 |
if (spare != sparebuffer) memcpy(sparebuffer, spare, 0x40);
|
- |
|
| 427 |
if (eccresult & 1) memset(sparebuffer, 0xFF, 0xC);
|
428 |
if (eccresult & 1) memset(sparebuffer, 0xFF, 0xC);
|
| 428 |
else memcpy(sparebuffer, nand_ctrl, 0xC);
|
429 |
else memcpy(sparebuffer, nand_ctrl, 0xC);
|
| 429 |
}
|
430 |
}
|
| 430 |
if (checkempty) rc |= nand_check_empty(spare) << 1;
|
431 |
if (checkempty) rc |= nand_check_empty(spare) << 1;
|
| 431 |
|
432 |
|
| Line 434... |
Line 435... |
| 434 |
|
435 |
|
| 435 |
static uint32_t nand_write_page_int(uint32_t bank, uint32_t page,
|
436 |
static uint32_t nand_write_page_int(uint32_t bank, uint32_t page,
|
| 436 |
void* databuffer, void* sparebuffer,
|
437 |
void* databuffer, void* sparebuffer,
|
| 437 |
uint32_t doecc, uint32_t wait)
|
438 |
uint32_t doecc, uint32_t wait)
|
| 438 |
{
|
439 |
{
|
| 439 |
uint8_t* data = nand_data;
|
440 |
uint8_t* data = (uint8_t*)databuffer;
|
| 440 |
uint8_t* spare = nand_spare;
|
441 |
uint8_t* spare = nand_spare;
|
| 441 |
if (databuffer && !((uint32_t)databuffer & 0xf))
|
442 |
if (sparebuffer) spare = (uint8_t*)sparebuffer;
|
| 442 |
data = (uint8_t*)databuffer;
|
443 |
if ((uint32_t)databuffer & 0xf)
|
| - |
|
444 |
panicf(PANIC_KILLUSERTHREADS,
|
| - |
|
445 |
"nand_write_page: Misaligned data buffer at %08X (bank %lu, page %lu)",
|
| - |
|
446 |
(unsigned int)databuffer, bank, page);
|
| 443 |
if (sparebuffer && !((uint32_t)sparebuffer & 0xf))
|
447 |
if ((uint32_t)sparebuffer & 0xf)
|
| - |
|
448 |
panicf(PANIC_KILLUSERTHREADS,
|
| - |
|
449 |
"nand_write_page: Misaligned spare buffer at %08X (bank %lu, page %lu)",
|
| 444 |
spare = (uint8_t*)sparebuffer;
|
450 |
(unsigned int)sparebuffer, bank, page);
|
| 445 |
mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
|
451 |
mutex_lock(&nand_mtx, TIMEOUT_BLOCK);
|
| 446 |
nand_last_activity_value = USEC_TIMER;
|
452 |
nand_last_activity_value = USEC_TIMER;
|
| 447 |
if (!nand_powered) nand_power_up();
|
453 |
if (!nand_powered) nand_power_up();
|
| 448 |
if (sparebuffer)
|
- |
|
| 449 |
{
|
- |
|
| 450 |
if (spare != sparebuffer) memcpy(spare, sparebuffer, 0x40);
|
- |
|
| 451 |
}
|
- |
|
| 452 |
else memset(spare, 0xFF, 0x40);
|
454 |
if (!sparebuffer) memset(spare, 0xFF, 0x40);
|
| 453 |
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
455 |
nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
| 454 |
if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1);
|
456 |
if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1);
|
| 455 |
if (nand_send_address(page, databuffer ? 0 : 0x800))
|
457 |
if (nand_send_address(page, data ? 0 : 0x800))
|
| 456 |
return nand_unlock(1);
|
458 |
return nand_unlock(1);
|
| 457 |
if (databuffer && data != databuffer) memcpy(data, databuffer, 0x800);
|
- |
|
| 458 |
if (databuffer) nand_transfer_data_start(bank, 1, data, 0x800);
|
459 |
if (data) nand_transfer_data_start(bank, 1, data, 0x800);
|
| 459 |
if (doecc)
|
460 |
if (doecc)
|
| 460 |
{
|
461 |
{
|
| 461 |
if (ecc_encode(3, data, nand_ecc)) return nand_unlock(1);
|
462 |
if (ecc_encode(3, data, nand_ecc)) return nand_unlock(1);
|
| 462 |
memcpy(&spare[0xC], nand_ecc, 0x28);
|
463 |
memcpy(&spare[0xC], nand_ecc, 0x28);
|
| 463 |
memset(nand_ctrl, 0xFF, 0x200);
|
464 |
memset(nand_ctrl, 0xFF, 0x200);
|
| 464 |
memcpy(nand_ctrl, spare, 0xC);
|
465 |
memcpy(nand_ctrl, spare, 0xC);
|
| 465 |
if (ecc_encode(0, nand_ctrl, nand_ecc)) return nand_unlock(1);
|
466 |
if (ecc_encode(0, nand_ctrl, nand_ecc)) return nand_unlock(1);
|
| 466 |
memcpy(&spare[0x34], nand_ecc, 0xC);
|
467 |
memcpy(&spare[0x34], nand_ecc, 0xC);
|
| 467 |
}
|
468 |
}
|
| 468 |
if (databuffer)
|
469 |
if (data)
|
| 469 |
if (nand_transfer_data_collect(1))
|
470 |
if (nand_transfer_data_collect(1))
|
| 470 |
return nand_unlock(1);
|
471 |
return nand_unlock(1);
|
| 471 |
if (sparebuffer || doecc)
|
472 |
if (sparebuffer || doecc)
|
| 472 |
if (nand_transfer_data(bank, 1, spare, 0x40))
|
473 |
if (nand_transfer_data(bank, 1, spare, 0x40))
|
| 473 |
return nand_unlock(1);
|
474 |
return nand_unlock(1);
|