uboot/drivers/mtd/nand/omap_gpmc.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
   3 * Rohit Choraria <rohitkc@ti.com>
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25#include <asm/io.h>
  26#include <asm/errno.h>
  27#include <asm/arch/mem.h>
  28#include <asm/arch/cpu.h>
  29#include <asm/omap_gpmc.h>
  30#include <linux/mtd/nand_ecc.h>
  31#include <linux/bch.h>
  32#include <linux/compiler.h>
  33#include <nand.h>
  34#ifdef CONFIG_AM33XX
  35#include <asm/arch/elm.h>
  36#endif
  37
  38static uint8_t cs;
  39static __maybe_unused struct nand_ecclayout hw_nand_oob =
  40        GPMC_NAND_HW_ECC_LAYOUT;
  41static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob =
  42        GPMC_NAND_HW_BCH8_ECC_LAYOUT;
  43
  44/*
  45 * omap_nand_hwcontrol - Set the address pointers corretly for the
  46 *                      following address/data/command operation
  47 */
  48static void omap_nand_hwcontrol(struct mtd_info *mtd, int32_t cmd,
  49                                uint32_t ctrl)
  50{
  51        register struct nand_chip *this = mtd->priv;
  52
  53        /*
  54         * Point the IO_ADDR to DATA and ADDRESS registers instead
  55         * of chip address
  56         */
  57        switch (ctrl) {
  58        case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
  59                this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
  60                break;
  61        case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
  62                this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_adr;
  63                break;
  64        case NAND_CTRL_CHANGE | NAND_NCE:
  65                this->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
  66                break;
  67        }
  68
  69        if (cmd != NAND_CMD_NONE)
  70                writeb(cmd, this->IO_ADDR_W);
  71}
  72
  73#ifdef CONFIG_SPL_BUILD
  74/* Check wait pin as dev ready indicator */
  75int omap_spl_dev_ready(struct mtd_info *mtd)
  76{
  77        return gpmc_cfg->status & (1 << 8);
  78}
  79#endif
  80
  81/*
  82 * omap_hwecc_init - Initialize the Hardware ECC for NAND flash in
  83 *                   GPMC controller
  84 * @mtd:        MTD device structure
  85 *
  86 */
  87static void __maybe_unused omap_hwecc_init(struct nand_chip *chip)
  88{
  89        /*
  90         * Init ECC Control Register
  91         * Clear all ECC | Enable Reg1
  92         */
  93        writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
  94        writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL, &gpmc_cfg->ecc_size_config);
  95}
  96
  97/*
  98 * gen_true_ecc - This function will generate true ECC value, which
  99 * can be used when correcting data read from NAND flash memory core
 100 *
 101 * @ecc_buf:    buffer to store ecc code
 102 *
 103 * @return:     re-formatted ECC value
 104 */
 105static uint32_t gen_true_ecc(uint8_t *ecc_buf)
 106{
 107        return ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xF0) << 20) |
 108                ((ecc_buf[2] & 0x0F) << 8);
 109}
 110
 111/*
 112 * omap_correct_data - Compares the ecc read from nand spare area with ECC
 113 * registers values and corrects one bit error if it has occured
 114 * Further details can be had from OMAP TRM and the following selected links:
 115 * http://en.wikipedia.org/wiki/Hamming_code
 116 * http://www.cs.utexas.edu/users/plaxton/c/337/05f/slides/ErrorCorrection-4.pdf
 117 *
 118 * @mtd:                 MTD device structure
 119 * @dat:                 page data
 120 * @read_ecc:            ecc read from nand flash
 121 * @calc_ecc:            ecc read from ECC registers
 122 *
 123 * @return 0 if data is OK or corrected, else returns -1
 124 */
 125static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
 126                                uint8_t *read_ecc, uint8_t *calc_ecc)
 127{
 128        uint32_t orig_ecc, new_ecc, res, hm;
 129        uint16_t parity_bits, byte;
 130        uint8_t bit;
 131
 132        /* Regenerate the orginal ECC */
 133        orig_ecc = gen_true_ecc(read_ecc);
 134        new_ecc = gen_true_ecc(calc_ecc);
 135        /* Get the XOR of real ecc */
 136        res = orig_ecc ^ new_ecc;
 137        if (res) {
 138                /* Get the hamming width */
 139                hm = hweight32(res);
 140                /* Single bit errors can be corrected! */
 141                if (hm == 12) {
 142                        /* Correctable data! */
 143                        parity_bits = res >> 16;
 144                        bit = (parity_bits & 0x7);
 145                        byte = (parity_bits >> 3) & 0x1FF;
 146                        /* Flip the bit to correct */
 147                        dat[byte] ^= (0x1 << bit);
 148                } else if (hm == 1) {
 149                        printf("Error: Ecc is wrong\n");
 150                        /* ECC itself is corrupted */
 151                        return 2;
 152                } else {
 153                        /*
 154                         * hm distance != parity pairs OR one, could mean 2 bit
 155                         * error OR potentially be on a blank page..
 156                         * orig_ecc: contains spare area data from nand flash.
 157                         * new_ecc: generated ecc while reading data area.
 158                         * Note: if the ecc = 0, all data bits from which it was
 159                         * generated are 0xFF.
 160                         * The 3 byte(24 bits) ecc is generated per 512byte
 161                         * chunk of a page. If orig_ecc(from spare area)
 162                         * is 0xFF && new_ecc(computed now from data area)=0x0,
 163                         * this means that data area is 0xFF and spare area is
 164                         * 0xFF. A sure sign of a erased page!
 165                         */
 166                        if ((orig_ecc == 0x0FFF0FFF) && (new_ecc == 0x00000000))
 167                                return 0;
 168                        printf("Error: Bad compare! failed\n");
 169                        /* detected 2 bit error */
 170                        return -1;
 171                }
 172        }
 173        return 0;
 174}
 175
 176/*
 177 *  omap_calculate_ecc - Generate non-inverted ECC bytes.
 178 *
 179 *  Using noninverted ECC can be considered ugly since writing a blank
 180 *  page ie. padding will clear the ECC bytes. This is no problem as
 181 *  long nobody is trying to write data on the seemingly unused page.
 182 *  Reading an erased page will produce an ECC mismatch between
 183 *  generated and read ECC bytes that has to be dealt with separately.
 184 *  E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
 185 *  is used, the result of read will be 0x0 while the ECC offsets of the
 186 *  spare area will be 0xFF which will result in an ECC mismatch.
 187 *  @mtd:       MTD structure
 188 *  @dat:       unused
 189 *  @ecc_code:  ecc_code buffer
 190 */
 191static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
 192                const uint8_t *dat, uint8_t *ecc_code)
 193{
 194        u_int32_t val;
 195
 196        /* Start Reading from HW ECC1_Result = 0x200 */
 197        val = readl(&gpmc_cfg->ecc1_result);
 198
 199        ecc_code[0] = val & 0xFF;
 200        ecc_code[1] = (val >> 16) & 0xFF;
 201        ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
 202
 203        /*
 204         * Stop reading anymore ECC vals and clear old results
 205         * enable will be called if more reads are required
 206         */
 207        writel(0x000, &gpmc_cfg->ecc_config);
 208
 209        return 0;
 210}
 211
 212/*
 213 * omap_enable_ecc - This function enables the hardware ecc functionality
 214 * @mtd:        MTD device structure
 215 * @mode:       Read/Write mode
 216 */
 217static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 218{
 219        struct nand_chip *chip = mtd->priv;
 220        uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
 221
 222        switch (mode) {
 223        case NAND_ECC_READ:
 224        case NAND_ECC_WRITE:
 225                /* Clear the ecc result registers, select ecc reg as 1 */
 226                writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
 227
 228                /*
 229                 * Size 0 = 0xFF, Size1 is 0xFF - both are 512 bytes
 230                 * tell all regs to generate size0 sized regs
 231                 * we just have a single ECC engine for all CS
 232                 */
 233                writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL,
 234                        &gpmc_cfg->ecc_size_config);
 235                val = (dev_width << 7) | (cs << 1) | (0x1);
 236                writel(val, &gpmc_cfg->ecc_config);
 237                break;
 238        default:
 239                printf("Error: Unrecognized Mode[%d]!\n", mode);
 240                break;
 241        }
 242}
 243
 244/*
 245 * Generic BCH interface
 246 */
 247struct nand_bch_priv {
 248        uint8_t mode;
 249        uint8_t type;
 250        uint8_t nibbles;
 251        struct bch_control *control;
 252};
 253
 254/* bch types */
 255#define ECC_BCH4        0
 256#define ECC_BCH8        1
 257#define ECC_BCH16       2
 258
 259/* GPMC ecc engine settings */
 260#define BCH_WRAPMODE_1          1       /* BCH wrap mode 1 */
 261#define BCH_WRAPMODE_6          6       /* BCH wrap mode 6 */
 262
 263/* BCH nibbles for diff bch levels */
 264#define NAND_ECC_HW_BCH ((uint8_t)(NAND_ECC_HW_OOB_FIRST) + 1)
 265#define ECC_BCH4_NIBBLES        13
 266#define ECC_BCH8_NIBBLES        26
 267#define ECC_BCH16_NIBBLES       52
 268
 269/*
 270 * This can be a single instance cause all current users have only one NAND
 271 * with nearly the same setup (BCH8, some with ELM and others with sw BCH
 272 * library).
 273 * When some users with other BCH strength will exists this have to change!
 274 */
 275static __maybe_unused struct nand_bch_priv bch_priv = {
 276        .mode = NAND_ECC_HW_BCH,
 277        .type = ECC_BCH8,
 278        .nibbles = ECC_BCH8_NIBBLES,
 279        .control = NULL
 280};
 281
 282/*
 283 * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
 284 *                              GPMC controller
 285 * @mtd:        MTD device structure
 286 * @mode:       Read/Write mode
 287 */
 288__maybe_unused
 289static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
 290{
 291        uint32_t val;
 292        uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
 293#ifdef CONFIG_AM33XX
 294        uint32_t unused_length = 0;
 295#endif
 296        uint32_t wr_mode = BCH_WRAPMODE_6;
 297        struct nand_bch_priv *bch = chip->priv;
 298
 299        /* Clear the ecc result registers, select ecc reg as 1 */
 300        writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
 301
 302#ifdef CONFIG_AM33XX
 303        wr_mode = BCH_WRAPMODE_1;
 304
 305        switch (bch->nibbles) {
 306        case ECC_BCH4_NIBBLES:
 307                unused_length = 3;
 308                break;
 309        case ECC_BCH8_NIBBLES:
 310                unused_length = 2;
 311                break;
 312        case ECC_BCH16_NIBBLES:
 313                unused_length = 0;
 314                break;
 315        }
 316
 317        /*
 318         * This is ecc_size_config for ELM mode.
 319         * Here we are using different settings for read and write access and
 320         * also depending on BCH strength.
 321         */
 322        switch (mode) {
 323        case NAND_ECC_WRITE:
 324                /* write access only setup eccsize1 config */
 325                val = ((unused_length + bch->nibbles) << 22);
 326                break;
 327
 328        case NAND_ECC_READ:
 329        default:
 330                /*
 331                 * by default eccsize0 selected for ecc1resultsize
 332                 * eccsize0 config.
 333                 */
 334                val  = (bch->nibbles << 12);
 335                /* eccsize1 config */
 336                val |= (unused_length << 22);
 337                break;
 338        }
 339#else
 340        /*
 341         * This ecc_size_config setting is for BCH sw library.
 342         *
 343         * Note: we only support BCH8 currently with BCH sw library!
 344         * Should be really easy to adobt to BCH4, however some omap3 have
 345         * flaws with BCH4.
 346         *
 347         * Here we are using wrapping mode 6 both for reading and writing, with:
 348         *  size0 = 0  (no additional protected byte in spare area)
 349         *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
 350         */
 351        val = (32 << 22) | (0 << 12);
 352#endif
 353        /* ecc size configuration */
 354        writel(val, &gpmc_cfg->ecc_size_config);
 355
 356        /*
 357         * Configure the ecc engine in gpmc
 358         * We assume 512 Byte sector pages for access to NAND.
 359         */
 360        val  = (1 << 16);               /* enable BCH mode */
 361        val |= (bch->type << 12);       /* setup BCH type */
 362        val |= (wr_mode << 8);          /* setup wrapping mode */
 363        val |= (dev_width << 7);        /* setup device width (16 or 8 bit) */
 364        val |= (cs << 1);               /* setup chip select to work on */
 365        debug("set ECC_CONFIG=0x%08x\n", val);
 366        writel(val, &gpmc_cfg->ecc_config);
 367}
 368
 369/*
 370 * omap_enable_ecc_bch - This function enables the bch h/w ecc functionality
 371 * @mtd:        MTD device structure
 372 * @mode:       Read/Write mode
 373 */
 374__maybe_unused
 375static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
 376{
 377        struct nand_chip *chip = mtd->priv;
 378
 379        omap_hwecc_init_bch(chip, mode);
 380        /* enable ecc */
 381        writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config);
 382}
 383
 384/*
 385 * omap_ecc_disable - Disable H/W ECC calculation
 386 *
 387 * @mtd:        MTD device structure
 388 */
 389static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
 390{
 391        writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
 392}
 393
 394/*
 395 * BCH8 support (needs ELM and thus AM33xx-only)
 396 */
 397#ifdef CONFIG_AM33XX
 398/*
 399 * omap_read_bch8_result - Read BCH result for BCH8 level
 400 *
 401 * @mtd:        MTD device structure
 402 * @big_endian: When set read register 3 first
 403 * @ecc_code:   Read syndrome from BCH result registers
 404 */
 405static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
 406                                uint8_t *ecc_code)
 407{
 408        uint32_t *ptr;
 409        int8_t i = 0, j;
 410
 411        if (big_endian) {
 412                ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
 413                ecc_code[i++] = readl(ptr) & 0xFF;
 414                ptr--;
 415                for (j = 0; j < 3; j++) {
 416                        ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
 417                        ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
 418                        ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
 419                        ecc_code[i++] = readl(ptr) & 0xFF;
 420                        ptr--;
 421                }
 422        } else {
 423                ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[0];
 424                for (j = 0; j < 3; j++) {
 425                        ecc_code[i++] = readl(ptr) & 0xFF;
 426                        ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
 427                        ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
 428                        ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
 429                        ptr++;
 430                }
 431                ecc_code[i++] = readl(ptr) & 0xFF;
 432                ecc_code[i++] = 0;      /* 14th byte is always zero */
 433        }
 434}
 435
 436/*
 437 * omap_rotate_ecc_bch - Rotate the syndrome bytes
 438 *
 439 * @mtd:        MTD device structure
 440 * @calc_ecc:   ECC read from ECC registers
 441 * @syndrome:   Rotated syndrome will be retuned in this array
 442 *
 443 */
 444static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
 445                uint8_t *syndrome)
 446{
 447        struct nand_chip *chip = mtd->priv;
 448        struct nand_bch_priv *bch = chip->priv;
 449        uint8_t n_bytes = 0;
 450        int8_t i, j;
 451
 452        switch (bch->type) {
 453        case ECC_BCH4:
 454                n_bytes = 8;
 455                break;
 456
 457        case ECC_BCH16:
 458                n_bytes = 28;
 459                break;
 460
 461        case ECC_BCH8:
 462        default:
 463                n_bytes = 13;
 464                break;
 465        }
 466
 467        for (i = 0, j = (n_bytes-1); i < n_bytes; i++, j--)
 468                syndrome[i] =  calc_ecc[j];
 469}
 470
 471/*
 472 *  omap_calculate_ecc_bch - Read BCH ECC result
 473 *
 474 *  @mtd:       MTD structure
 475 *  @dat:       unused
 476 *  @ecc_code:  ecc_code buffer
 477 */
 478static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
 479                                uint8_t *ecc_code)
 480{
 481        struct nand_chip *chip = mtd->priv;
 482        struct nand_bch_priv *bch = chip->priv;
 483        uint8_t big_endian = 1;
 484        int8_t ret = 0;
 485
 486        if (bch->type == ECC_BCH8)
 487                omap_read_bch8_result(mtd, big_endian, ecc_code);
 488        else /* BCH4 and BCH16 currently not supported */
 489                ret = -1;
 490
 491        /*
 492         * Stop reading anymore ECC vals and clear old results
 493         * enable will be called if more reads are required
 494         */
 495        omap_ecc_disable(mtd);
 496
 497        return ret;
 498}
 499
 500/*
 501 * omap_fix_errors_bch - Correct bch error in the data
 502 *
 503 * @mtd:        MTD device structure
 504 * @data:       Data read from flash
 505 * @error_count:Number of errors in data
 506 * @error_loc:  Locations of errors in the data
 507 *
 508 */
 509static void omap_fix_errors_bch(struct mtd_info *mtd, uint8_t *data,
 510                uint32_t error_count, uint32_t *error_loc)
 511{
 512        struct nand_chip *chip = mtd->priv;
 513        struct nand_bch_priv *bch = chip->priv;
 514        uint8_t count = 0;
 515        uint32_t error_byte_pos;
 516        uint32_t error_bit_mask;
 517        uint32_t last_bit = (bch->nibbles * 4) - 1;
 518
 519        /* Flip all bits as specified by the error location array. */
 520        /* FOR( each found error location flip the bit ) */
 521        for (count = 0; count < error_count; count++) {
 522                if (error_loc[count] > last_bit) {
 523                        /* Remove the ECC spare bits from correction. */
 524                        error_loc[count] -= (last_bit + 1);
 525                        /* Offset bit in data region */
 526                        error_byte_pos = ((512 * 8) -
 527                                        (error_loc[count]) - 1) / 8;
 528                        /* Error Bit mask */
 529                        error_bit_mask = 0x1 << (error_loc[count] % 8);
 530                        /* Toggle the error bit to make the correction. */
 531                        data[error_byte_pos] ^= error_bit_mask;
 532                }
 533        }
 534}
 535
 536/*
 537 * omap_correct_data_bch - Compares the ecc read from nand spare area
 538 * with ECC registers values and corrects one bit error if it has occured
 539 *
 540 * @mtd:        MTD device structure
 541 * @dat:        page data
 542 * @read_ecc:   ecc read from nand flash (ignored)
 543 * @calc_ecc:   ecc read from ECC registers
 544 *
 545 * @return 0 if data is OK or corrected, else returns -1
 546 */
 547static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
 548                                uint8_t *read_ecc, uint8_t *calc_ecc)
 549{
 550        struct nand_chip *chip = mtd->priv;
 551        struct nand_bch_priv *bch = chip->priv;
 552        uint8_t syndrome[28];
 553        uint32_t error_count = 0;
 554        uint32_t error_loc[8];
 555        uint32_t i, ecc_flag;
 556
 557        ecc_flag = 0;
 558        for (i = 0; i < chip->ecc.bytes; i++)
 559                if (read_ecc[i] != 0xff)
 560                        ecc_flag = 1;
 561
 562        if (!ecc_flag)
 563                return 0;
 564
 565        elm_reset();
 566        elm_config((enum bch_level)(bch->type));
 567
 568        /*
 569         * while reading ECC result we read it in big endian.
 570         * Hence while loading to ELM we have rotate to get the right endian.
 571         */
 572        omap_rotate_ecc_bch(mtd, calc_ecc, syndrome);
 573
 574        /* use elm module to check for errors */
 575        if (elm_check_error(syndrome, bch->nibbles, &error_count,
 576                                error_loc) != 0) {
 577                printf("ECC: uncorrectable.\n");
 578                return -1;
 579        }
 580
 581        /* correct bch error */
 582        if (error_count > 0)
 583                omap_fix_errors_bch(mtd, dat, error_count, error_loc);
 584
 585        return 0;
 586}
 587
 588/**
 589 * omap_read_page_bch - hardware ecc based page read function
 590 * @mtd:        mtd info structure
 591 * @chip:       nand chip info structure
 592 * @buf:        buffer to store read data
 593 * @page:       page number to read
 594 *
 595 */
 596static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 597                                uint8_t *buf, int page)
 598{
 599        int i, eccsize = chip->ecc.size;
 600        int eccbytes = chip->ecc.bytes;
 601        int eccsteps = chip->ecc.steps;
 602        uint8_t *p = buf;
 603        uint8_t *ecc_calc = chip->buffers->ecccalc;
 604        uint8_t *ecc_code = chip->buffers->ecccode;
 605        uint32_t *eccpos = chip->ecc.layout->eccpos;
 606        uint8_t *oob = chip->oob_poi;
 607        uint32_t data_pos;
 608        uint32_t oob_pos;
 609
 610        data_pos = 0;
 611        /* oob area start */
 612        oob_pos = (eccsize * eccsteps) + chip->ecc.layout->eccpos[0];
 613        oob += chip->ecc.layout->eccpos[0];
 614
 615        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize,
 616                                oob += eccbytes) {
 617                chip->ecc.hwctl(mtd, NAND_ECC_READ);
 618                /* read data */
 619                chip->cmdfunc(mtd, NAND_CMD_RNDOUT, data_pos, page);
 620                chip->read_buf(mtd, p, eccsize);
 621
 622                /* read respective ecc from oob area */
 623                chip->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_pos, page);
 624                chip->read_buf(mtd, oob, eccbytes);
 625                /* read syndrome */
 626                chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 627
 628                data_pos += eccsize;
 629                oob_pos += eccbytes;
 630        }
 631
 632        for (i = 0; i < chip->ecc.total; i++)
 633                ecc_code[i] = chip->oob_poi[eccpos[i]];
 634
 635        eccsteps = chip->ecc.steps;
 636        p = buf;
 637
 638        for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 639                int stat;
 640
 641                stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
 642                if (stat < 0)
 643                        mtd->ecc_stats.failed++;
 644                else
 645                        mtd->ecc_stats.corrected += stat;
 646        }
 647        return 0;
 648}
 649#endif /* CONFIG_AM33XX */
 650
 651/*
 652 * OMAP3 BCH8 support (with BCH library)
 653 */
 654#ifdef CONFIG_NAND_OMAP_BCH8
 655/*
 656 *  omap_calculate_ecc_bch - Read BCH ECC result
 657 *
 658 *  @mtd:       MTD device structure
 659 *  @dat:       The pointer to data on which ecc is computed (unused here)
 660 *  @ecc:       The ECC output buffer
 661 */
 662static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
 663                                uint8_t *ecc)
 664{
 665        int ret = 0;
 666        size_t i;
 667        unsigned long nsectors, val1, val2, val3, val4;
 668
 669        nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
 670
 671        for (i = 0; i < nsectors; i++) {
 672                /* Read hw-computed remainder */
 673                val1 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[0]);
 674                val2 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[1]);
 675                val3 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[2]);
 676                val4 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[3]);
 677
 678                /*
 679                 * Add constant polynomial to remainder, in order to get an ecc
 680                 * sequence of 0xFFs for a buffer filled with 0xFFs.
 681                 */
 682                *ecc++ = 0xef ^ (val4 & 0xFF);
 683                *ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF);
 684                *ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF);
 685                *ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF);
 686                *ecc++ = 0xed ^ (val3 & 0xFF);
 687                *ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF);
 688                *ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF);
 689                *ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
 690                *ecc++ = 0x97 ^ (val2 & 0xFF);
 691                *ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF);
 692                *ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
 693                *ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF);
 694                *ecc++ = 0xb5 ^ (val1 & 0xFF);
 695        }
 696
 697        /*
 698         * Stop reading anymore ECC vals and clear old results
 699         * enable will be called if more reads are required
 700         */
 701        omap_ecc_disable(mtd);
 702
 703        return ret;
 704}
 705
 706/**
 707 * omap_correct_data_bch - Decode received data and correct errors
 708 * @mtd: MTD device structure
 709 * @data: page data
 710 * @read_ecc: ecc read from nand flash
 711 * @calc_ecc: ecc read from HW ECC registers
 712 */
 713static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
 714                                 u_char *read_ecc, u_char *calc_ecc)
 715{
 716        int i, count;
 717        /* cannot correct more than 8 errors */
 718        unsigned int errloc[8];
 719        struct nand_chip *chip = mtd->priv;
 720        struct nand_bch_priv *chip_priv = chip->priv;
 721        struct bch_control *bch = chip_priv->control;
 722
 723        count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
 724        if (count > 0) {
 725                /* correct errors */
 726                for (i = 0; i < count; i++) {
 727                        /* correct data only, not ecc bytes */
 728                        if (errloc[i] < 8*512)
 729                                data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
 730                        printf("corrected bitflip %u\n", errloc[i]);
 731#ifdef DEBUG
 732                        puts("read_ecc: ");
 733                        /*
 734                         * BCH8 have 13 bytes of ECC; BCH4 needs adoption
 735                         * here!
 736                         */
 737                        for (i = 0; i < 13; i++)
 738                                printf("%02x ", read_ecc[i]);
 739                        puts("\n");
 740                        puts("calc_ecc: ");
 741                        for (i = 0; i < 13; i++)
 742                                printf("%02x ", calc_ecc[i]);
 743                        puts("\n");
 744#endif
 745                }
 746        } else if (count < 0) {
 747                puts("ecc unrecoverable error\n");
 748        }
 749        return count;
 750}
 751
 752/**
 753 * omap_free_bch - Release BCH ecc resources
 754 * @mtd: MTD device structure
 755 */
 756static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
 757{
 758        struct nand_chip *chip = mtd->priv;
 759        struct nand_bch_priv *chip_priv = chip->priv;
 760        struct bch_control *bch = NULL;
 761
 762        if (chip_priv)
 763                bch = chip_priv->control;
 764
 765        if (bch) {
 766                free_bch(bch);
 767                chip_priv->control = NULL;
 768        }
 769}
 770#endif /* CONFIG_NAND_OMAP_BCH8 */
 771
 772#ifndef CONFIG_SPL_BUILD
 773/*
 774 * omap_nand_switch_ecc - switch the ECC operation between different engines
 775 * (h/w and s/w) and different algorithms (hamming and BCHx)
 776 *
 777 * @hardware            - true if one of the HW engines should be used
 778 * @eccstrength         - the number of bits that could be corrected
 779 *                        (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
 780 */
 781void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 782{
 783        struct nand_chip *nand;
 784        struct mtd_info *mtd;
 785
 786        if (nand_curr_device < 0 ||
 787            nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
 788            !nand_info[nand_curr_device].name) {
 789                printf("Error: Can't switch ecc, no devices available\n");
 790                return;
 791        }
 792
 793        mtd = &nand_info[nand_curr_device];
 794        nand = mtd->priv;
 795
 796        nand->options |= NAND_OWN_BUFFERS;
 797
 798        /* Reset ecc interface */
 799        nand->ecc.mode = NAND_ECC_NONE;
 800        nand->ecc.read_page = NULL;
 801        nand->ecc.write_page = NULL;
 802        nand->ecc.read_oob = NULL;
 803        nand->ecc.write_oob = NULL;
 804        nand->ecc.hwctl = NULL;
 805        nand->ecc.correct = NULL;
 806        nand->ecc.calculate = NULL;
 807
 808        /* Setup the ecc configurations again */
 809        if (hardware) {
 810                if (eccstrength == 1) {
 811                        nand->ecc.mode = NAND_ECC_HW;
 812                        nand->ecc.layout = &hw_nand_oob;
 813                        nand->ecc.size = 512;
 814                        nand->ecc.bytes = 3;
 815                        nand->ecc.hwctl = omap_enable_hwecc;
 816                        nand->ecc.correct = omap_correct_data;
 817                        nand->ecc.calculate = omap_calculate_ecc;
 818                        omap_hwecc_init(nand);
 819                        printf("1-bit hamming HW ECC selected\n");
 820                }
 821#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
 822                else if (eccstrength == 8) {
 823                        nand->ecc.mode = NAND_ECC_HW;
 824                        nand->ecc.layout = &hw_bch8_nand_oob;
 825                        nand->ecc.size = 512;
 826#ifdef CONFIG_AM33XX
 827                        nand->ecc.bytes = 14;
 828                        nand->ecc.read_page = omap_read_page_bch;
 829#else
 830                        nand->ecc.bytes = 13;
 831#endif
 832                        nand->ecc.hwctl = omap_enable_ecc_bch;
 833                        nand->ecc.correct = omap_correct_data_bch;
 834                        nand->ecc.calculate = omap_calculate_ecc_bch;
 835                        omap_hwecc_init_bch(nand, NAND_ECC_READ);
 836                        printf("8-bit BCH HW ECC selected\n");
 837                }
 838#endif
 839        } else {
 840                nand->ecc.mode = NAND_ECC_SOFT;
 841                /* Use mtd default settings */
 842                nand->ecc.layout = NULL;
 843                nand->ecc.size = 0;
 844                printf("SW ECC selected\n");
 845        }
 846
 847        /* Update NAND handling after ECC mode switch */
 848        nand_scan_tail(mtd);
 849
 850        nand->options &= ~NAND_OWN_BUFFERS;
 851}
 852#endif /* CONFIG_SPL_BUILD */
 853
 854/*
 855 * Board-specific NAND initialization. The following members of the
 856 * argument are board-specific:
 857 * - IO_ADDR_R: address to read the 8 I/O lines of the flash device
 858 * - IO_ADDR_W: address to write the 8 I/O lines of the flash device
 859 * - cmd_ctrl: hardwarespecific function for accesing control-lines
 860 * - waitfunc: hardwarespecific function for accesing device ready/busy line
 861 * - ecc.hwctl: function to enable (reset) hardware ecc generator
 862 * - ecc.mode: mode of ecc, see defines
 863 * - chip_delay: chip dependent delay for transfering data from array to
 864 *   read regs (tR)
 865 * - options: various chip options. They can partly be set to inform
 866 *   nand_scan about special functionality. See the defines for further
 867 *   explanation
 868 */
 869int board_nand_init(struct nand_chip *nand)
 870{
 871        int32_t gpmc_config = 0;
 872        cs = 0;
 873
 874        /*
 875         * xloader/Uboot's gpmc configuration would have configured GPMC for
 876         * nand type of memory. The following logic scans and latches on to the
 877         * first CS with NAND type memory.
 878         * TBD: need to make this logic generic to handle multiple CS NAND
 879         * devices.
 880         */
 881        while (cs < GPMC_MAX_CS) {
 882                /* Check if NAND type is set */
 883                if ((readl(&gpmc_cfg->cs[cs].config1) & 0xC00) == 0x800) {
 884                        /* Found it!! */
 885                        break;
 886                }
 887                cs++;
 888        }
 889        if (cs >= GPMC_MAX_CS) {
 890                printf("NAND: Unable to find NAND settings in "
 891                        "GPMC Configuration - quitting\n");
 892                return -ENODEV;
 893        }
 894
 895        gpmc_config = readl(&gpmc_cfg->config);
 896        /* Disable Write protect */
 897        gpmc_config |= 0x10;
 898        writel(gpmc_config, &gpmc_cfg->config);
 899
 900        nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
 901        nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
 902
 903        nand->cmd_ctrl = omap_nand_hwcontrol;
 904        nand->options = NAND_NO_PADDING | NAND_CACHEPRG | NAND_NO_AUTOINCR;
 905        /* If we are 16 bit dev, our gpmc config tells us that */
 906        if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
 907                nand->options |= NAND_BUSWIDTH_16;
 908
 909        nand->chip_delay = 100;
 910
 911#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
 912#ifdef CONFIG_AM33XX
 913        /* AM33xx uses the ELM */
 914        /* required in case of BCH */
 915        elm_init();
 916#else
 917        /*
 918         * Whereas other OMAP based SoC do not have the ELM, they use the BCH
 919         * SW library.
 920         */
 921        bch_priv.control = init_bch(13, 8, 0x201b /* hw polynominal */);
 922        if (!bch_priv.control) {
 923                puts("Could not init_bch()\n");
 924                return -ENODEV;
 925        }
 926#endif
 927        /* BCH info that will be correct for SPL or overridden otherwise. */
 928        nand->priv = &bch_priv;
 929#endif
 930
 931        /* Default ECC mode */
 932#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
 933        nand->ecc.mode = NAND_ECC_HW;
 934        nand->ecc.layout = &hw_bch8_nand_oob;
 935        nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
 936        nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
 937        nand->ecc.hwctl = omap_enable_ecc_bch;
 938        nand->ecc.correct = omap_correct_data_bch;
 939        nand->ecc.calculate = omap_calculate_ecc_bch;
 940#ifdef CONFIG_AM33XX
 941        nand->ecc.read_page = omap_read_page_bch;
 942#endif
 943        omap_hwecc_init_bch(nand, NAND_ECC_READ);
 944#else
 945#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
 946        nand->ecc.mode = NAND_ECC_SOFT;
 947#else
 948        nand->ecc.mode = NAND_ECC_HW;
 949        nand->ecc.layout = &hw_nand_oob;
 950        nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
 951        nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
 952        nand->ecc.hwctl = omap_enable_hwecc;
 953        nand->ecc.correct = omap_correct_data;
 954        nand->ecc.calculate = omap_calculate_ecc;
 955        omap_hwecc_init(nand);
 956#endif
 957#endif
 958
 959#ifdef CONFIG_SPL_BUILD
 960        if (nand->options & NAND_BUSWIDTH_16)
 961                nand->read_buf = nand_read_buf16;
 962        else
 963                nand->read_buf = nand_read_buf;
 964        nand->dev_ready = omap_spl_dev_ready;
 965#endif
 966
 967        return 0;
 968}
 969