Commit 8fca2d8cb84fb039bb41061f5f5fd9f31cd596c9
Committed by
Scott Wood
1 parent
080a71e8e9
Exists in
v2017.01-smarct4x
and in
34 other branches
mtd: vf610_nfc: enable ONFI detection
This changes enable ONFI detection. The Read ID command now allows one address byte which is needed for ONFI detection. To read the ONFI parameter page, the NAND_CMD_PARAM need to be supported. The CMD code enables one command and one address byte along with reading data from flash using R/B#, as specified by ONFI. Signed-off-by: Stefan Agner <stefan@agner.ch>
Showing 3 changed files with 51 additions and 18 deletions Side-by-side Diff
drivers/mtd/nand/vf610_nfc.c
... | ... | @@ -62,6 +62,7 @@ |
62 | 62 | * Briefly these are bitmasks of controller cycles. |
63 | 63 | */ |
64 | 64 | #define READ_PAGE_CMD_CODE 0x7EE0 |
65 | +#define READ_ONFI_PARAM_CMD_CODE 0x4860 | |
65 | 66 | #define PROGRAM_PAGE_CMD_CODE 0x7FC0 |
66 | 67 | #define ERASE_CMD_CODE 0x4EC0 |
67 | 68 | #define READ_ID_CMD_CODE 0x4804 |
... | ... | @@ -150,6 +151,7 @@ |
150 | 151 | int alt_buf; |
151 | 152 | #define ALT_BUF_ID 1 |
152 | 153 | #define ALT_BUF_STAT 2 |
154 | +#define ALT_BUF_ONFI 3 | |
153 | 155 | struct clk *clk; |
154 | 156 | }; |
155 | 157 | |
... | ... | @@ -390,6 +392,16 @@ |
390 | 392 | vf610_nfc_ecc_mode(mtd, ECC_HW_MODE); |
391 | 393 | break; |
392 | 394 | |
395 | + case NAND_CMD_PARAM: | |
396 | + nfc->alt_buf = ALT_BUF_ONFI; | |
397 | + vf610_nfc_transfer_size(nfc->regs, 768); | |
398 | + vf610_nfc_send_command(nfc->regs, NAND_CMD_PARAM, | |
399 | + READ_ONFI_PARAM_CMD_CODE); | |
400 | + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK, | |
401 | + ROW_ADDR_SHIFT, column); | |
402 | + vf610_nfc_ecc_mode(mtd, ECC_BYPASS); | |
403 | + break; | |
404 | + | |
393 | 405 | case NAND_CMD_ERASE1: |
394 | 406 | vf610_nfc_transfer_size(nfc->regs, 0); |
395 | 407 | vf610_nfc_send_commands(nfc->regs, command, |
396 | 408 | |
... | ... | @@ -399,8 +411,11 @@ |
399 | 411 | |
400 | 412 | case NAND_CMD_READID: |
401 | 413 | nfc->alt_buf = ALT_BUF_ID; |
414 | + nfc->column = 0; | |
402 | 415 | vf610_nfc_transfer_size(nfc->regs, 0); |
403 | 416 | vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE); |
417 | + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK, | |
418 | + ROW_ADDR_SHIFT, column); | |
404 | 419 | break; |
405 | 420 | |
406 | 421 | case NAND_CMD_STATUS: |
407 | 422 | |
... | ... | @@ -422,18 +437,12 @@ |
422 | 437 | struct vf610_nfc *nfc = mtd_to_nfc(mtd); |
423 | 438 | uint c = nfc->column; |
424 | 439 | |
425 | - switch (nfc->alt_buf) { | |
426 | - case ALT_BUF_ID: | |
427 | - *buf = vf610_nfc_get_id(mtd, c); | |
428 | - break; | |
429 | - case ALT_BUF_STAT: | |
430 | - *buf = vf610_nfc_get_status(mtd); | |
431 | - break; | |
432 | - default: | |
433 | - vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); | |
434 | - break; | |
435 | - } | |
440 | + /* Alternate buffers are only supported through read_byte */ | |
441 | + if (nfc->alt_buf) | |
442 | + return; | |
436 | 443 | |
444 | + vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); | |
445 | + | |
437 | 446 | nfc->column += len; |
438 | 447 | } |
439 | 448 | |
440 | 449 | |
... | ... | @@ -453,8 +462,29 @@ |
453 | 462 | /* Read byte from NFC buffers */ |
454 | 463 | static u8 vf610_nfc_read_byte(struct mtd_info *mtd) |
455 | 464 | { |
465 | + struct vf610_nfc *nfc = mtd_to_nfc(mtd); | |
456 | 466 | u8 tmp; |
457 | - vf610_nfc_read_buf(mtd, &tmp, sizeof(tmp)); | |
467 | + uint c = nfc->column; | |
468 | + | |
469 | + switch (nfc->alt_buf) { | |
470 | + case ALT_BUF_ID: | |
471 | + tmp = vf610_nfc_get_id(mtd, c); | |
472 | + break; | |
473 | + case ALT_BUF_STAT: | |
474 | + tmp = vf610_nfc_get_status(mtd); | |
475 | + break; | |
476 | + case ALT_BUF_ONFI: | |
477 | +#ifdef __LITTLE_ENDIAN | |
478 | + /* Reverse byte since the controller uses big endianness */ | |
479 | + c = nfc->column ^ 0x3; | |
480 | + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); | |
481 | + break; | |
482 | +#endif | |
483 | + default: | |
484 | + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); | |
485 | + break; | |
486 | + } | |
487 | + nfc->column++; | |
458 | 488 | return tmp; |
459 | 489 | } |
460 | 490 | |
461 | 491 | |
462 | 492 | |
... | ... | @@ -602,14 +632,12 @@ |
602 | 632 | mtd->priv = chip; |
603 | 633 | chip->priv = nfc; |
604 | 634 | |
605 | - if (cfg.width == 16) { | |
635 | + if (cfg.width == 16) | |
606 | 636 | chip->options |= NAND_BUSWIDTH_16; |
607 | - vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); | |
608 | - } else { | |
609 | - chip->options &= ~NAND_BUSWIDTH_16; | |
610 | - vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); | |
611 | - } | |
612 | 637 | |
638 | + /* Use 8-bit mode during initialization */ | |
639 | + vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); | |
640 | + | |
613 | 641 | /* Disable subpage writes as we do not provide ecc->hwctl */ |
614 | 642 | chip->options |= NAND_NO_SUBPAGE_WRITE; |
615 | 643 | |
... | ... | @@ -650,6 +678,9 @@ |
650 | 678 | err = -ENXIO; |
651 | 679 | goto error; |
652 | 680 | } |
681 | + | |
682 | + if (cfg.width == 16) | |
683 | + vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); | |
653 | 684 | |
654 | 685 | chip->ecc.mode = NAND_ECC_SOFT; /* default */ |
655 | 686 |
include/configs/colibri_vf.h