| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2017 Free Electrons |
|---|
| 3 | 4 | * Copyright (C) 2017 NextThing Co |
|---|
| 4 | 5 | * |
|---|
| 5 | 6 | * Author: Boris Brezillon <boris.brezillon@free-electrons.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 9 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 10 | | - * (at your option) any later version. |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 13 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | | - * GNU General Public License for more details. |
|---|
| 16 | 7 | */ |
|---|
| 17 | 8 | |
|---|
| 18 | | -#include <linux/mtd/rawnand.h> |
|---|
| 19 | 9 | #include <linux/sizes.h> |
|---|
| 20 | 10 | #include <linux/slab.h> |
|---|
| 11 | + |
|---|
| 12 | +#include "internals.h" |
|---|
| 21 | 13 | |
|---|
| 22 | 14 | #define NAND_HYNIX_CMD_SET_PARAMS 0x36 |
|---|
| 23 | 15 | #define NAND_HYNIX_CMD_APPLY_PARAMS 0x16 |
|---|
| .. | .. |
|---|
| 34 | 26 | struct hynix_read_retry { |
|---|
| 35 | 27 | int nregs; |
|---|
| 36 | 28 | const u8 *regs; |
|---|
| 37 | | - u8 values[0]; |
|---|
| 29 | + u8 values[]; |
|---|
| 38 | 30 | }; |
|---|
| 39 | 31 | |
|---|
| 40 | 32 | /** |
|---|
| .. | .. |
|---|
| 79 | 71 | |
|---|
| 80 | 72 | static int hynix_nand_cmd_op(struct nand_chip *chip, u8 cmd) |
|---|
| 81 | 73 | { |
|---|
| 82 | | - struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 83 | | - |
|---|
| 84 | | - if (chip->exec_op) { |
|---|
| 74 | + if (nand_has_exec_op(chip)) { |
|---|
| 85 | 75 | struct nand_op_instr instrs[] = { |
|---|
| 86 | 76 | NAND_OP_CMD(cmd, 0), |
|---|
| 87 | 77 | }; |
|---|
| 88 | | - struct nand_operation op = NAND_OPERATION(instrs); |
|---|
| 78 | + struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); |
|---|
| 89 | 79 | |
|---|
| 90 | 80 | return nand_exec_op(chip, &op); |
|---|
| 91 | 81 | } |
|---|
| 92 | 82 | |
|---|
| 93 | | - chip->cmdfunc(mtd, cmd, -1, -1); |
|---|
| 83 | + chip->legacy.cmdfunc(chip, cmd, -1, -1); |
|---|
| 94 | 84 | |
|---|
| 95 | 85 | return 0; |
|---|
| 96 | 86 | } |
|---|
| 97 | 87 | |
|---|
| 98 | 88 | static int hynix_nand_reg_write_op(struct nand_chip *chip, u8 addr, u8 val) |
|---|
| 99 | 89 | { |
|---|
| 100 | | - struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 101 | 90 | u16 column = ((u16)addr << 8) | addr; |
|---|
| 102 | 91 | |
|---|
| 103 | | - if (chip->exec_op) { |
|---|
| 92 | + if (nand_has_exec_op(chip)) { |
|---|
| 104 | 93 | struct nand_op_instr instrs[] = { |
|---|
| 105 | 94 | NAND_OP_ADDR(1, &addr, 0), |
|---|
| 106 | 95 | NAND_OP_8BIT_DATA_OUT(1, &val, 0), |
|---|
| 107 | 96 | }; |
|---|
| 108 | | - struct nand_operation op = NAND_OPERATION(instrs); |
|---|
| 97 | + struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs); |
|---|
| 109 | 98 | |
|---|
| 110 | 99 | return nand_exec_op(chip, &op); |
|---|
| 111 | 100 | } |
|---|
| 112 | 101 | |
|---|
| 113 | | - chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1); |
|---|
| 114 | | - chip->write_byte(mtd, val); |
|---|
| 102 | + chip->legacy.cmdfunc(chip, NAND_CMD_NONE, column, -1); |
|---|
| 103 | + chip->legacy.write_byte(chip, val); |
|---|
| 115 | 104 | |
|---|
| 116 | 105 | return 0; |
|---|
| 117 | 106 | } |
|---|
| 118 | 107 | |
|---|
| 119 | | -static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) |
|---|
| 108 | +static int hynix_nand_setup_read_retry(struct nand_chip *chip, int retry_mode) |
|---|
| 120 | 109 | { |
|---|
| 121 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 122 | 110 | struct hynix_nand *hynix = nand_get_manufacturer_data(chip); |
|---|
| 123 | 111 | const u8 *values; |
|---|
| 124 | 112 | int i, ret; |
|---|
| .. | .. |
|---|
| 349 | 337 | rr->nregs = nregs; |
|---|
| 350 | 338 | rr->regs = hynix_1xnm_mlc_read_retry_regs; |
|---|
| 351 | 339 | hynix->read_retry = rr; |
|---|
| 352 | | - chip->setup_read_retry = hynix_nand_setup_read_retry; |
|---|
| 340 | + chip->ops.setup_read_retry = hynix_nand_setup_read_retry; |
|---|
| 353 | 341 | chip->read_retries = nmodes; |
|---|
| 354 | 342 | |
|---|
| 355 | 343 | out: |
|---|
| .. | .. |
|---|
| 421 | 409 | bool valid_jedecid) |
|---|
| 422 | 410 | { |
|---|
| 423 | 411 | struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 412 | + struct nand_memory_organization *memorg; |
|---|
| 424 | 413 | u8 oobsize; |
|---|
| 414 | + |
|---|
| 415 | + memorg = nanddev_get_memorg(&chip->base); |
|---|
| 425 | 416 | |
|---|
| 426 | 417 | oobsize = ((chip->id.data[3] >> 2) & 0x3) | |
|---|
| 427 | 418 | ((chip->id.data[3] >> 4) & 0x4); |
|---|
| .. | .. |
|---|
| 429 | 420 | if (valid_jedecid) { |
|---|
| 430 | 421 | switch (oobsize) { |
|---|
| 431 | 422 | case 0: |
|---|
| 432 | | - mtd->oobsize = 2048; |
|---|
| 423 | + memorg->oobsize = 2048; |
|---|
| 433 | 424 | break; |
|---|
| 434 | 425 | case 1: |
|---|
| 435 | | - mtd->oobsize = 1664; |
|---|
| 426 | + memorg->oobsize = 1664; |
|---|
| 436 | 427 | break; |
|---|
| 437 | 428 | case 2: |
|---|
| 438 | | - mtd->oobsize = 1024; |
|---|
| 429 | + memorg->oobsize = 1024; |
|---|
| 439 | 430 | break; |
|---|
| 440 | 431 | case 3: |
|---|
| 441 | | - mtd->oobsize = 640; |
|---|
| 432 | + memorg->oobsize = 640; |
|---|
| 442 | 433 | break; |
|---|
| 443 | 434 | default: |
|---|
| 444 | 435 | /* |
|---|
| .. | .. |
|---|
| 453 | 444 | } else { |
|---|
| 454 | 445 | switch (oobsize) { |
|---|
| 455 | 446 | case 0: |
|---|
| 456 | | - mtd->oobsize = 128; |
|---|
| 447 | + memorg->oobsize = 128; |
|---|
| 457 | 448 | break; |
|---|
| 458 | 449 | case 1: |
|---|
| 459 | | - mtd->oobsize = 224; |
|---|
| 450 | + memorg->oobsize = 224; |
|---|
| 460 | 451 | break; |
|---|
| 461 | 452 | case 2: |
|---|
| 462 | | - mtd->oobsize = 448; |
|---|
| 453 | + memorg->oobsize = 448; |
|---|
| 463 | 454 | break; |
|---|
| 464 | 455 | case 3: |
|---|
| 465 | | - mtd->oobsize = 64; |
|---|
| 456 | + memorg->oobsize = 64; |
|---|
| 466 | 457 | break; |
|---|
| 467 | 458 | case 4: |
|---|
| 468 | | - mtd->oobsize = 32; |
|---|
| 459 | + memorg->oobsize = 32; |
|---|
| 469 | 460 | break; |
|---|
| 470 | 461 | case 5: |
|---|
| 471 | | - mtd->oobsize = 16; |
|---|
| 462 | + memorg->oobsize = 16; |
|---|
| 472 | 463 | break; |
|---|
| 473 | 464 | case 6: |
|---|
| 474 | | - mtd->oobsize = 640; |
|---|
| 465 | + memorg->oobsize = 640; |
|---|
| 475 | 466 | break; |
|---|
| 476 | 467 | default: |
|---|
| 477 | 468 | /* |
|---|
| .. | .. |
|---|
| 495 | 486 | * the actual OOB size for this chip is: 640 * 16k / 8k). |
|---|
| 496 | 487 | */ |
|---|
| 497 | 488 | if (chip->id.data[1] == 0xde) |
|---|
| 498 | | - mtd->oobsize *= mtd->writesize / SZ_8K; |
|---|
| 489 | + memorg->oobsize *= memorg->pagesize / SZ_8K; |
|---|
| 499 | 490 | } |
|---|
| 491 | + |
|---|
| 492 | + mtd->oobsize = memorg->oobsize; |
|---|
| 500 | 493 | } |
|---|
| 501 | 494 | |
|---|
| 502 | 495 | static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip, |
|---|
| 503 | 496 | bool valid_jedecid) |
|---|
| 504 | 497 | { |
|---|
| 498 | + struct nand_device *base = &chip->base; |
|---|
| 499 | + struct nand_ecc_props requirements = {}; |
|---|
| 505 | 500 | u8 ecc_level = (chip->id.data[4] >> 4) & 0x7; |
|---|
| 506 | 501 | |
|---|
| 507 | 502 | if (valid_jedecid) { |
|---|
| 508 | 503 | /* Reference: H27UCG8T2E datasheet */ |
|---|
| 509 | | - chip->ecc_step_ds = 1024; |
|---|
| 504 | + requirements.step_size = 1024; |
|---|
| 510 | 505 | |
|---|
| 511 | 506 | switch (ecc_level) { |
|---|
| 512 | 507 | case 0: |
|---|
| 513 | | - chip->ecc_step_ds = 0; |
|---|
| 514 | | - chip->ecc_strength_ds = 0; |
|---|
| 508 | + requirements.step_size = 0; |
|---|
| 509 | + requirements.strength = 0; |
|---|
| 515 | 510 | break; |
|---|
| 516 | 511 | case 1: |
|---|
| 517 | | - chip->ecc_strength_ds = 4; |
|---|
| 512 | + requirements.strength = 4; |
|---|
| 518 | 513 | break; |
|---|
| 519 | 514 | case 2: |
|---|
| 520 | | - chip->ecc_strength_ds = 24; |
|---|
| 515 | + requirements.strength = 24; |
|---|
| 521 | 516 | break; |
|---|
| 522 | 517 | case 3: |
|---|
| 523 | | - chip->ecc_strength_ds = 32; |
|---|
| 518 | + requirements.strength = 32; |
|---|
| 524 | 519 | break; |
|---|
| 525 | 520 | case 4: |
|---|
| 526 | | - chip->ecc_strength_ds = 40; |
|---|
| 521 | + requirements.strength = 40; |
|---|
| 527 | 522 | break; |
|---|
| 528 | 523 | case 5: |
|---|
| 529 | | - chip->ecc_strength_ds = 50; |
|---|
| 524 | + requirements.strength = 50; |
|---|
| 530 | 525 | break; |
|---|
| 531 | 526 | case 6: |
|---|
| 532 | | - chip->ecc_strength_ds = 60; |
|---|
| 527 | + requirements.strength = 60; |
|---|
| 533 | 528 | break; |
|---|
| 534 | 529 | default: |
|---|
| 535 | 530 | /* |
|---|
| .. | .. |
|---|
| 550 | 545 | if (nand_tech < 3) { |
|---|
| 551 | 546 | /* > 26nm, reference: H27UBG8T2A datasheet */ |
|---|
| 552 | 547 | if (ecc_level < 5) { |
|---|
| 553 | | - chip->ecc_step_ds = 512; |
|---|
| 554 | | - chip->ecc_strength_ds = 1 << ecc_level; |
|---|
| 548 | + requirements.step_size = 512; |
|---|
| 549 | + requirements.strength = 1 << ecc_level; |
|---|
| 555 | 550 | } else if (ecc_level < 7) { |
|---|
| 556 | 551 | if (ecc_level == 5) |
|---|
| 557 | | - chip->ecc_step_ds = 2048; |
|---|
| 552 | + requirements.step_size = 2048; |
|---|
| 558 | 553 | else |
|---|
| 559 | | - chip->ecc_step_ds = 1024; |
|---|
| 560 | | - chip->ecc_strength_ds = 24; |
|---|
| 554 | + requirements.step_size = 1024; |
|---|
| 555 | + requirements.strength = 24; |
|---|
| 561 | 556 | } else { |
|---|
| 562 | 557 | /* |
|---|
| 563 | 558 | * We should never reach this case, but if that |
|---|
| .. | .. |
|---|
| 570 | 565 | } else { |
|---|
| 571 | 566 | /* <= 26nm, reference: H27UBG8T2B datasheet */ |
|---|
| 572 | 567 | if (!ecc_level) { |
|---|
| 573 | | - chip->ecc_step_ds = 0; |
|---|
| 574 | | - chip->ecc_strength_ds = 0; |
|---|
| 568 | + requirements.step_size = 0; |
|---|
| 569 | + requirements.strength = 0; |
|---|
| 575 | 570 | } else if (ecc_level < 5) { |
|---|
| 576 | | - chip->ecc_step_ds = 512; |
|---|
| 577 | | - chip->ecc_strength_ds = 1 << (ecc_level - 1); |
|---|
| 571 | + requirements.step_size = 512; |
|---|
| 572 | + requirements.strength = 1 << (ecc_level - 1); |
|---|
| 578 | 573 | } else { |
|---|
| 579 | | - chip->ecc_step_ds = 1024; |
|---|
| 580 | | - chip->ecc_strength_ds = 24 + |
|---|
| 574 | + requirements.step_size = 1024; |
|---|
| 575 | + requirements.strength = 24 + |
|---|
| 581 | 576 | (8 * (ecc_level - 5)); |
|---|
| 582 | 577 | } |
|---|
| 583 | 578 | } |
|---|
| 584 | 579 | } |
|---|
| 580 | + |
|---|
| 581 | + nanddev_set_ecc_requirements(base, &requirements); |
|---|
| 585 | 582 | } |
|---|
| 586 | 583 | |
|---|
| 587 | 584 | static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip, |
|---|
| .. | .. |
|---|
| 590 | 587 | u8 nand_tech; |
|---|
| 591 | 588 | |
|---|
| 592 | 589 | /* We need scrambling on all TLC NANDs*/ |
|---|
| 593 | | - if (chip->bits_per_cell > 2) |
|---|
| 590 | + if (nanddev_bits_per_cell(&chip->base) > 2) |
|---|
| 594 | 591 | chip->options |= NAND_NEED_SCRAMBLING; |
|---|
| 595 | 592 | |
|---|
| 596 | 593 | /* And on MLC NANDs with sub-3xnm process */ |
|---|
| .. | .. |
|---|
| 612 | 609 | static void hynix_nand_decode_id(struct nand_chip *chip) |
|---|
| 613 | 610 | { |
|---|
| 614 | 611 | struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 612 | + struct nand_memory_organization *memorg; |
|---|
| 615 | 613 | bool valid_jedecid; |
|---|
| 616 | 614 | u8 tmp; |
|---|
| 615 | + |
|---|
| 616 | + memorg = nanddev_get_memorg(&chip->base); |
|---|
| 617 | 617 | |
|---|
| 618 | 618 | /* |
|---|
| 619 | 619 | * Exclude all SLC NANDs from this advanced detection scheme. |
|---|
| .. | .. |
|---|
| 628 | 628 | } |
|---|
| 629 | 629 | |
|---|
| 630 | 630 | /* Extract pagesize */ |
|---|
| 631 | | - mtd->writesize = 2048 << (chip->id.data[3] & 0x03); |
|---|
| 631 | + memorg->pagesize = 2048 << (chip->id.data[3] & 0x03); |
|---|
| 632 | + mtd->writesize = memorg->pagesize; |
|---|
| 632 | 633 | |
|---|
| 633 | 634 | tmp = (chip->id.data[3] >> 4) & 0x3; |
|---|
| 634 | 635 | /* |
|---|
| .. | .. |
|---|
| 638 | 639 | * The only exception is when ID[3][4:5] == 3 and ID[3][7] == 0, in |
|---|
| 639 | 640 | * this case the erasesize is set to 768KiB. |
|---|
| 640 | 641 | */ |
|---|
| 641 | | - if (chip->id.data[3] & 0x80) |
|---|
| 642 | + if (chip->id.data[3] & 0x80) { |
|---|
| 643 | + memorg->pages_per_eraseblock = (SZ_1M << tmp) / |
|---|
| 644 | + memorg->pagesize; |
|---|
| 642 | 645 | mtd->erasesize = SZ_1M << tmp; |
|---|
| 643 | | - else if (tmp == 3) |
|---|
| 646 | + } else if (tmp == 3) { |
|---|
| 647 | + memorg->pages_per_eraseblock = (SZ_512K + SZ_256K) / |
|---|
| 648 | + memorg->pagesize; |
|---|
| 644 | 649 | mtd->erasesize = SZ_512K + SZ_256K; |
|---|
| 645 | | - else |
|---|
| 650 | + } else { |
|---|
| 651 | + memorg->pages_per_eraseblock = (SZ_128K << tmp) / |
|---|
| 652 | + memorg->pagesize; |
|---|
| 646 | 653 | mtd->erasesize = SZ_128K << tmp; |
|---|
| 654 | + } |
|---|
| 647 | 655 | |
|---|
| 648 | 656 | /* |
|---|
| 649 | 657 | * Modern Toggle DDR NANDs have a valid JEDECID even though they are |
|---|
| .. | .. |
|---|
| 669 | 677 | nand_set_manufacturer_data(chip, NULL); |
|---|
| 670 | 678 | } |
|---|
| 671 | 679 | |
|---|
| 680 | +static int |
|---|
| 681 | +h27ucg8t2atrbc_choose_interface_config(struct nand_chip *chip, |
|---|
| 682 | + struct nand_interface_config *iface) |
|---|
| 683 | +{ |
|---|
| 684 | + onfi_fill_interface_config(chip, iface, NAND_SDR_IFACE, 4); |
|---|
| 685 | + |
|---|
| 686 | + return nand_choose_best_sdr_timings(chip, iface, NULL); |
|---|
| 687 | +} |
|---|
| 688 | + |
|---|
| 672 | 689 | static int hynix_nand_init(struct nand_chip *chip) |
|---|
| 673 | 690 | { |
|---|
| 674 | 691 | struct hynix_nand *hynix; |
|---|
| 675 | 692 | int ret; |
|---|
| 676 | 693 | |
|---|
| 677 | 694 | if (!nand_is_slc(chip)) |
|---|
| 678 | | - chip->bbt_options |= NAND_BBT_SCANLASTPAGE; |
|---|
| 695 | + chip->options |= NAND_BBM_LASTPAGE; |
|---|
| 679 | 696 | else |
|---|
| 680 | | - chip->bbt_options |= NAND_BBT_SCAN2NDPAGE; |
|---|
| 697 | + chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE; |
|---|
| 681 | 698 | |
|---|
| 682 | 699 | hynix = kzalloc(sizeof(*hynix), GFP_KERNEL); |
|---|
| 683 | 700 | if (!hynix) |
|---|
| .. | .. |
|---|
| 685 | 702 | |
|---|
| 686 | 703 | nand_set_manufacturer_data(chip, hynix); |
|---|
| 687 | 704 | |
|---|
| 705 | + if (!strncmp("H27UCG8T2ATR-BC", chip->parameters.model, |
|---|
| 706 | + sizeof("H27UCG8T2ATR-BC") - 1)) |
|---|
| 707 | + chip->ops.choose_interface_config = |
|---|
| 708 | + h27ucg8t2atrbc_choose_interface_config; |
|---|
| 709 | + |
|---|
| 688 | 710 | ret = hynix_nand_rr_init(chip); |
|---|
| 689 | 711 | if (ret) |
|---|
| 690 | 712 | hynix_nand_cleanup(chip); |
|---|