Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: brcmnand: Add v7.2 controller support

The 7.2 controller differs in a few area compared to its predecssor (7.1):

- NAND scrambler, which we are not using just yet
- higher ECC levels (up to 120 bits) per 1KB data blocks, also not supported yet
- up to 128B OOB

This patch adds the necessary code to support such a controller
generation and updates the Device Tree binding.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Kamal Dasu <kdasu.kdev@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>

authored by

Florian Fainelli and committed by
Boris Brezillon
decba6d4 cabfeaa6

+78 -14
+1
Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
··· 27 27 brcm,brcmnand-v6.2 28 28 brcm,brcmnand-v7.0 29 29 brcm,brcmnand-v7.1 30 + brcm,brcmnand-v7.2 30 31 brcm,brcmnand 31 32 - reg : the register start and length for NAND register region. 32 33 (optional) Flash DMA register range (if present)
+77 -14
drivers/mtd/nand/brcmnand/brcmnand.c
··· 340 340 [BRCMNAND_FC_BASE] = 0x400, 341 341 }; 342 342 343 + /* BRCMNAND v7.2 */ 344 + static const u16 brcmnand_regs_v72[] = { 345 + [BRCMNAND_CMD_START] = 0x04, 346 + [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, 347 + [BRCMNAND_CMD_ADDRESS] = 0x0c, 348 + [BRCMNAND_INTFC_STATUS] = 0x14, 349 + [BRCMNAND_CS_SELECT] = 0x18, 350 + [BRCMNAND_CS_XOR] = 0x1c, 351 + [BRCMNAND_LL_OP] = 0x20, 352 + [BRCMNAND_CS0_BASE] = 0x50, 353 + [BRCMNAND_CS1_BASE] = 0, 354 + [BRCMNAND_CORR_THRESHOLD] = 0xdc, 355 + [BRCMNAND_CORR_THRESHOLD_EXT] = 0xe0, 356 + [BRCMNAND_UNCORR_COUNT] = 0xfc, 357 + [BRCMNAND_CORR_COUNT] = 0x100, 358 + [BRCMNAND_CORR_EXT_ADDR] = 0x10c, 359 + [BRCMNAND_CORR_ADDR] = 0x110, 360 + [BRCMNAND_UNCORR_EXT_ADDR] = 0x114, 361 + [BRCMNAND_UNCORR_ADDR] = 0x118, 362 + [BRCMNAND_SEMAPHORE] = 0x150, 363 + [BRCMNAND_ID] = 0x194, 364 + [BRCMNAND_ID_EXT] = 0x198, 365 + [BRCMNAND_LL_RDATA] = 0x19c, 366 + [BRCMNAND_OOB_READ_BASE] = 0x200, 367 + [BRCMNAND_OOB_READ_10_BASE] = 0, 368 + [BRCMNAND_OOB_WRITE_BASE] = 0x400, 369 + [BRCMNAND_OOB_WRITE_10_BASE] = 0, 370 + [BRCMNAND_FC_BASE] = 0x600, 371 + }; 372 + 343 373 enum brcmnand_cs_reg { 344 374 BRCMNAND_CS_CFG_EXT = 0, 345 375 BRCMNAND_CS_CFG, ··· 465 435 } 466 436 467 437 /* Register offsets */ 468 - if (ctrl->nand_version >= 0x0701) 438 + if (ctrl->nand_version >= 0x0702) 439 + ctrl->reg_offsets = brcmnand_regs_v72; 440 + else if (ctrl->nand_version >= 0x0701) 469 441 ctrl->reg_offsets = brcmnand_regs_v71; 470 442 else if (ctrl->nand_version >= 0x0600) 471 443 ctrl->reg_offsets = brcmnand_regs_v60; ··· 512 480 } 513 481 514 482 /* Maximum spare area sector size (per 512B) */ 515 - if (ctrl->nand_version >= 0x0600) 483 + if (ctrl->nand_version >= 0x0702) 484 + ctrl->max_oob = 128; 485 + else if (ctrl->nand_version >= 0x0600) 516 486 ctrl->max_oob = 64; 517 487 else if (ctrl->nand_version >= 0x0500) 518 488 ctrl->max_oob = 32; ··· 617 583 enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD; 618 584 int cs = host->cs; 619 585 620 - if (ctrl->nand_version >= 0x0600) 586 + if (ctrl->nand_version >= 0x0702) 587 + bits = 7; 588 + else if (ctrl->nand_version >= 0x0600) 621 589 bits = 6; 622 590 else if (ctrl->nand_version >= 0x0500) 623 591 bits = 5; 624 592 else 625 593 bits = 4; 626 594 627 - if (ctrl->nand_version >= 0x0600) { 595 + if (ctrl->nand_version >= 0x0702) { 596 + if (cs >= 4) 597 + reg = BRCMNAND_CORR_THRESHOLD_EXT; 598 + shift = (cs % 4) * bits; 599 + } else if (ctrl->nand_version >= 0x0600) { 628 600 if (cs >= 5) 629 601 reg = BRCMNAND_CORR_THRESHOLD_EXT; 630 602 shift = (cs % 5) * bits; ··· 671 631 672 632 static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) 673 633 { 674 - if (ctrl->nand_version >= 0x0600) 634 + if (ctrl->nand_version >= 0x0702) 635 + return GENMASK(7, 0); 636 + else if (ctrl->nand_version >= 0x0600) 675 637 return GENMASK(6, 0); 676 638 else 677 639 return GENMASK(5, 0); 678 640 } 679 641 680 642 #define NAND_ACC_CONTROL_ECC_SHIFT 16 643 + #define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13 681 644 682 645 static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl) 683 646 { 684 647 u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f; 685 648 686 - return mask << NAND_ACC_CONTROL_ECC_SHIFT; 649 + mask <<= NAND_ACC_CONTROL_ECC_SHIFT; 650 + 651 + /* v7.2 includes additional ECC levels */ 652 + if (ctrl->nand_version >= 0x0702) 653 + mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT; 654 + 655 + return mask; 687 656 } 688 657 689 658 static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en) ··· 716 667 717 668 static inline int brcmnand_sector_1k_shift(struct brcmnand_controller *ctrl) 718 669 { 719 - if (ctrl->nand_version >= 0x0600) 670 + if (ctrl->nand_version >= 0x0702) 671 + return 9; 672 + else if (ctrl->nand_version >= 0x0600) 720 673 return 7; 721 674 else if (ctrl->nand_version >= 0x0500) 722 675 return 6; ··· 824 773 * Internal support functions 825 774 ***********************************************************************/ 826 775 827 - static inline bool is_hamming_ecc(struct brcmnand_cfg *cfg) 776 + static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl, 777 + struct brcmnand_cfg *cfg) 828 778 { 829 - return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 && 830 - cfg->ecc_level == 15; 779 + if (ctrl->nand_version <= 0x0701) 780 + return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 && 781 + cfg->ecc_level == 15; 782 + else 783 + return cfg->sector_size_1k == 0 && ((cfg->spare_area_size == 16 && 784 + cfg->ecc_level == 15) || 785 + (cfg->spare_area_size == 28 && cfg->ecc_level == 16)); 831 786 } 832 787 833 788 /* ··· 988 931 if (p->sector_size_1k) 989 932 ecc_level <<= 1; 990 933 991 - if (is_hamming_ecc(p)) { 934 + if (is_hamming_ecc(host->ctrl, p)) { 992 935 ecc->bytes = 3 * sectors; 993 936 mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops); 994 937 return 0; ··· 1914 1857 return 0; 1915 1858 } 1916 1859 1917 - static void brcmnand_print_cfg(char *buf, struct brcmnand_cfg *cfg) 1860 + static void brcmnand_print_cfg(struct brcmnand_host *host, 1861 + char *buf, struct brcmnand_cfg *cfg) 1918 1862 { 1919 1863 buf += sprintf(buf, 1920 1864 "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit", ··· 1926 1868 cfg->spare_area_size, cfg->device_width); 1927 1869 1928 1870 /* Account for Hamming ECC and for BCH 512B vs 1KiB sectors */ 1929 - if (is_hamming_ecc(cfg)) 1871 + if (is_hamming_ecc(host->ctrl, cfg)) 1930 1872 sprintf(buf, ", Hamming ECC"); 1931 1873 else if (cfg->sector_size_1k) 1932 1874 sprintf(buf, ", BCH-%u (1KiB sector)", cfg->ecc_level << 1); ··· 2045 1987 2046 1988 brcmnand_set_ecc_enabled(host, 1); 2047 1989 2048 - brcmnand_print_cfg(msg, cfg); 1990 + brcmnand_print_cfg(host, msg, cfg); 2049 1991 dev_info(ctrl->dev, "detected %s\n", msg); 2050 1992 2051 1993 /* Configure ACC_CONTROL */ ··· 2053 1995 tmp = nand_readreg(ctrl, offs); 2054 1996 tmp &= ~ACC_CONTROL_PARTIAL_PAGE; 2055 1997 tmp &= ~ACC_CONTROL_RD_ERASED; 1998 + 1999 + /* We need to turn on Read from erased paged protected by ECC */ 2000 + if (ctrl->nand_version >= 0x0702) 2001 + tmp |= ACC_CONTROL_RD_ERASED; 2056 2002 tmp &= ~ACC_CONTROL_FAST_PGM_RDIN; 2057 2003 if (ctrl->features & BRCMNAND_HAS_PREFETCH) { 2058 2004 /* ··· 2257 2195 { .compatible = "brcm,brcmnand-v6.2" }, 2258 2196 { .compatible = "brcm,brcmnand-v7.0" }, 2259 2197 { .compatible = "brcm,brcmnand-v7.1" }, 2198 + { .compatible = "brcm,brcmnand-v7.2" }, 2260 2199 {}, 2261 2200 }; 2262 2201 MODULE_DEVICE_TABLE(of, brcmnand_of_match);