uboot/drivers/mtd/nand/raw/sunxi_nand_spl.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2014-2015, Antmicro Ltd <www.antmicro.com>
   4 * Copyright (c) 2015, AW-SOM Technologies <www.aw-som.com>
   5 */
   6
   7#include <asm/arch/clock.h>
   8#include <asm/io.h>
   9#include <common.h>
  10#include <config.h>
  11#include <nand.h>
  12#include <linux/bitops.h>
  13#include <linux/ctype.h>
  14#include <linux/delay.h>
  15#include <linux/mtd/rawnand.h>
  16
  17/* registers */
  18#define NFC_CTL                    0x00000000
  19#define NFC_ST                     0x00000004
  20#define NFC_INT                    0x00000008
  21#define NFC_TIMING_CTL             0x0000000C
  22#define NFC_TIMING_CFG             0x00000010
  23#define NFC_ADDR_LOW               0x00000014
  24#define NFC_ADDR_HIGH              0x00000018
  25#define NFC_SECTOR_NUM             0x0000001C
  26#define NFC_CNT                    0x00000020
  27#define NFC_CMD                    0x00000024
  28#define NFC_RCMD_SET               0x00000028
  29#define NFC_WCMD_SET               0x0000002C
  30#define NFC_IO_DATA                0x00000030
  31#define NFC_ECC_CTL                0x00000034
  32#define NFC_ECC_ST                 0x00000038
  33#define NFC_DEBUG                  0x0000003C
  34#define NFC_ECC_CNT0               0x00000040
  35#define NFC_ECC_CNT1               0x00000044
  36#define NFC_ECC_CNT2               0x00000048
  37#define NFC_ECC_CNT3               0x0000004C
  38#define NFC_USER_DATA_BASE         0x00000050
  39#define NFC_EFNAND_STATUS          0x00000090
  40#define NFC_SPARE_AREA             0x000000A0
  41#define NFC_PATTERN_ID             0x000000A4
  42#define NFC_RAM0_BASE              0x00000400
  43#define NFC_RAM1_BASE              0x00000800
  44
  45#define NFC_CTL_EN                 (1 << 0)
  46#define NFC_CTL_RESET              (1 << 1)
  47#define NFC_CTL_RAM_METHOD         (1 << 14)
  48#define NFC_CTL_PAGE_SIZE_MASK     (0xf << 8)
  49#define NFC_CTL_PAGE_SIZE(a)       ((fls(a) - 11) << 8)
  50
  51
  52#define NFC_ECC_EN                 (1 << 0)
  53#define NFC_ECC_PIPELINE           (1 << 3)
  54#define NFC_ECC_EXCEPTION          (1 << 4)
  55#define NFC_ECC_BLOCK_SIZE         (1 << 5)
  56#define NFC_ECC_RANDOM_EN          (1 << 9)
  57#define NFC_ECC_RANDOM_DIRECTION   (1 << 10)
  58
  59
  60#define NFC_ADDR_NUM_OFFSET        16
  61#define NFC_SEND_ADDR              (1 << 19)
  62#define NFC_ACCESS_DIR             (1 << 20)
  63#define NFC_DATA_TRANS             (1 << 21)
  64#define NFC_SEND_CMD1              (1 << 22)
  65#define NFC_WAIT_FLAG              (1 << 23)
  66#define NFC_SEND_CMD2              (1 << 24)
  67#define NFC_SEQ                    (1 << 25)
  68#define NFC_DATA_SWAP_METHOD       (1 << 26)
  69#define NFC_ROW_AUTO_INC           (1 << 27)
  70#define NFC_SEND_CMD3              (1 << 28)
  71#define NFC_SEND_CMD4              (1 << 29)
  72#define NFC_RAW_CMD                (0 << 30)
  73#define NFC_ECC_CMD                (1 << 30)
  74#define NFC_PAGE_CMD               (2 << 30)
  75
  76#define NFC_ST_CMD_INT_FLAG        (1 << 1)
  77#define NFC_ST_DMA_INT_FLAG        (1 << 2)
  78#define NFC_ST_CMD_FIFO_STAT       (1 << 3)
  79
  80#define NFC_READ_CMD_OFFSET         0
  81#define NFC_RANDOM_READ_CMD0_OFFSET 8
  82#define NFC_RANDOM_READ_CMD1_OFFSET 16
  83
  84#define NFC_CMD_RNDOUTSTART        0xE0
  85#define NFC_CMD_RNDOUT             0x05
  86#define NFC_CMD_READSTART          0x30
  87
  88struct nfc_config {
  89        int page_size;
  90        int ecc_strength;
  91        int ecc_size;
  92        int addr_cycles;
  93        int nseeds;
  94        bool randomize;
  95        bool valid;
  96};
  97
  98/* minimal "boot0" style NAND support for Allwinner A20 */
  99
 100/* random seed used by linux */
 101const uint16_t random_seed[128] = {
 102        0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
 103        0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
 104        0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
 105        0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
 106        0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
 107        0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
 108        0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
 109        0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
 110        0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
 111        0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
 112        0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
 113        0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
 114        0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
 115        0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
 116        0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
 117        0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
 118};
 119
 120#define DEFAULT_TIMEOUT_US      100000
 121
 122static int check_value_inner(int offset, int expected_bits,
 123                             int timeout_us, int negation)
 124{
 125        do {
 126                int val = readl(offset) & expected_bits;
 127                if (negation ? !val : val)
 128                        return 1;
 129                udelay(1);
 130        } while (--timeout_us);
 131
 132        return 0;
 133}
 134
 135static inline int check_value(int offset, int expected_bits,
 136                              int timeout_us)
 137{
 138        return check_value_inner(offset, expected_bits, timeout_us, 0);
 139}
 140
 141static inline int check_value_negated(int offset, int unexpected_bits,
 142                                      int timeout_us)
 143{
 144        return check_value_inner(offset, unexpected_bits, timeout_us, 1);
 145}
 146
 147static int nand_wait_cmd_fifo_empty(void)
 148{
 149        if (!check_value_negated(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_FIFO_STAT,
 150                                 DEFAULT_TIMEOUT_US)) {
 151                printf("nand: timeout waiting for empty cmd FIFO\n");
 152                return -ETIMEDOUT;
 153        }
 154
 155        return 0;
 156}
 157
 158static int nand_wait_int(void)
 159{
 160        if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_INT_FLAG,
 161                         DEFAULT_TIMEOUT_US)) {
 162                printf("nand: timeout waiting for interruption\n");
 163                return -ETIMEDOUT;
 164        }
 165
 166        return 0;
 167}
 168
 169static int nand_exec_cmd(u32 cmd)
 170{
 171        int ret;
 172
 173        ret = nand_wait_cmd_fifo_empty();
 174        if (ret)
 175                return ret;
 176
 177        writel(NFC_ST_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_ST);
 178        writel(cmd, SUNXI_NFC_BASE + NFC_CMD);
 179
 180        return nand_wait_int();
 181}
 182
 183void nand_init(void)
 184{
 185        uint32_t val;
 186
 187        board_nand_init();
 188
 189        val = readl(SUNXI_NFC_BASE + NFC_CTL);
 190        /* enable and reset CTL */
 191        writel(val | NFC_CTL_EN | NFC_CTL_RESET,
 192               SUNXI_NFC_BASE + NFC_CTL);
 193
 194        if (!check_value_negated(SUNXI_NFC_BASE + NFC_CTL,
 195                                 NFC_CTL_RESET, DEFAULT_TIMEOUT_US)) {
 196                printf("Couldn't initialize nand\n");
 197        }
 198
 199        /* reset NAND */
 200        nand_exec_cmd(NFC_SEND_CMD1 | NFC_WAIT_FLAG | NAND_CMD_RESET);
 201}
 202
 203static void nand_apply_config(const struct nfc_config *conf)
 204{
 205        u32 val;
 206
 207        nand_wait_cmd_fifo_empty();
 208
 209        val = readl(SUNXI_NFC_BASE + NFC_CTL);
 210        val &= ~NFC_CTL_PAGE_SIZE_MASK;
 211        writel(val | NFC_CTL_RAM_METHOD | NFC_CTL_PAGE_SIZE(conf->page_size),
 212               SUNXI_NFC_BASE + NFC_CTL);
 213        writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
 214        writel(conf->page_size, SUNXI_NFC_BASE + NFC_SPARE_AREA);
 215}
 216
 217static int nand_load_page(const struct nfc_config *conf, u32 offs)
 218{
 219        int page = offs / conf->page_size;
 220
 221        writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
 222               (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
 223               (NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
 224               SUNXI_NFC_BASE + NFC_RCMD_SET);
 225        writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_ADDR_LOW);
 226        writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_ADDR_HIGH);
 227
 228        return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
 229                             NFC_SEND_ADDR | NFC_WAIT_FLAG |
 230                             ((conf->addr_cycles - 1) << NFC_ADDR_NUM_OFFSET));
 231}
 232
 233static int nand_change_column(u16 column)
 234{
 235        int ret;
 236
 237        writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
 238               (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
 239               (NFC_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
 240               SUNXI_NFC_BASE + NFC_RCMD_SET);
 241        writel(column, SUNXI_NFC_BASE + NFC_ADDR_LOW);
 242
 243        ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
 244                            (1 << NFC_ADDR_NUM_OFFSET) | NFC_SEND_ADDR |
 245                            NFC_CMD_RNDOUT);
 246        if (ret)
 247                return ret;
 248
 249        /* Ensure tCCS has passed before reading data */
 250        udelay(1);
 251
 252        return 0;
 253}
 254
 255static const int ecc_bytes[] = {32, 46, 54, 60, 74, 88, 102, 110, 116};
 256
 257static int nand_read_page(const struct nfc_config *conf, u32 offs,
 258                          void *dest, int len)
 259{
 260        int nsectors = len / conf->ecc_size;
 261        u16 rand_seed = 0;
 262        int oob_chunk_sz = ecc_bytes[conf->ecc_strength];
 263        int page = offs / conf->page_size;
 264        u32 ecc_st;
 265        int i;
 266
 267        if (offs % conf->page_size || len % conf->ecc_size ||
 268            len > conf->page_size || len < 0)
 269                return -EINVAL;
 270
 271        /* Choose correct seed if randomized */
 272        if (conf->randomize)
 273                rand_seed = random_seed[page % conf->nseeds];
 274
 275        /* Retrieve data from SRAM (PIO) */
 276        for (i = 0; i < nsectors; i++) {
 277                int data_off = i * conf->ecc_size;
 278                int oob_off = conf->page_size + (i * oob_chunk_sz);
 279                u8 *data = dest + data_off;
 280
 281                /* Clear ECC status and restart ECC engine */
 282                writel(0, SUNXI_NFC_BASE + NFC_ECC_ST);
 283                writel((rand_seed << 16) | (conf->ecc_strength << 12) |
 284                       (conf->randomize ? NFC_ECC_RANDOM_EN : 0) |
 285                       (conf->ecc_size == 512 ? NFC_ECC_BLOCK_SIZE : 0) |
 286                       NFC_ECC_EN | NFC_ECC_EXCEPTION,
 287                       SUNXI_NFC_BASE + NFC_ECC_CTL);
 288
 289                /* Move the data in SRAM */
 290                nand_change_column(data_off);
 291                writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
 292                nand_exec_cmd(NFC_DATA_TRANS);
 293
 294                /*
 295                 * Let the ECC engine consume the ECC bytes and possibly correct
 296                 * the data.
 297                 */
 298                nand_change_column(oob_off);
 299                nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_CMD);
 300
 301                /* Get the ECC status */
 302                ecc_st = readl(SUNXI_NFC_BASE + NFC_ECC_ST);
 303
 304                /* ECC error detected. */
 305                if (ecc_st & 0xffff)
 306                        return -EIO;
 307
 308                /*
 309                 * Return 1 if the first chunk is empty (needed for
 310                 * configuration detection).
 311                 */
 312                if (!i && (ecc_st & 0x10000))
 313                        return 1;
 314
 315                /* Retrieve the data from SRAM */
 316                memcpy_fromio(data, SUNXI_NFC_BASE + NFC_RAM0_BASE,
 317                              conf->ecc_size);
 318
 319                /* Stop the ECC engine */
 320                writel(readl(SUNXI_NFC_BASE + NFC_ECC_CTL) & ~NFC_ECC_EN,
 321                       SUNXI_NFC_BASE + NFC_ECC_CTL);
 322
 323                if (data_off + conf->ecc_size >= len)
 324                        break;
 325        }
 326
 327        return 0;
 328}
 329
 330static int nand_max_ecc_strength(struct nfc_config *conf)
 331{
 332        int max_oobsize, max_ecc_bytes;
 333        int nsectors = conf->page_size / conf->ecc_size;
 334        int i;
 335
 336        /*
 337         * ECC strength is limited by the size of the OOB area which is
 338         * correlated with the page size.
 339         */
 340        switch (conf->page_size) {
 341        case 2048:
 342                max_oobsize = 64;
 343                break;
 344        case 4096:
 345                max_oobsize = 256;
 346                break;
 347        case 8192:
 348                max_oobsize = 640;
 349                break;
 350        case 16384:
 351                max_oobsize = 1664;
 352                break;
 353        default:
 354                return -EINVAL;
 355        }
 356
 357        max_ecc_bytes = max_oobsize / nsectors;
 358
 359        for (i = 0; i < ARRAY_SIZE(ecc_bytes); i++) {
 360                if (ecc_bytes[i] > max_ecc_bytes)
 361                        break;
 362        }
 363
 364        if (!i)
 365                return -EINVAL;
 366
 367        return i - 1;
 368}
 369
 370static int nand_detect_ecc_config(struct nfc_config *conf, u32 offs,
 371                                  void *dest)
 372{
 373        /* NAND with pages > 4k will likely require 1k sector size. */
 374        int min_ecc_size = conf->page_size > 4096 ? 1024 : 512;
 375        int page = offs / conf->page_size;
 376        int ret;
 377
 378        /*
 379         * In most cases, 1k sectors are preferred over 512b ones, start
 380         * testing this config first.
 381         */
 382        for (conf->ecc_size = 1024; conf->ecc_size >= min_ecc_size;
 383             conf->ecc_size >>= 1) {
 384                int max_ecc_strength = nand_max_ecc_strength(conf);
 385
 386                nand_apply_config(conf);
 387
 388                /*
 389                 * We are starting from the maximum ECC strength because
 390                 * most of the time NAND vendors provide an OOB area that
 391                 * barely meets the ECC requirements.
 392                 */
 393                for (conf->ecc_strength = max_ecc_strength;
 394                     conf->ecc_strength >= 0;
 395                     conf->ecc_strength--) {
 396                        conf->randomize = false;
 397                        if (nand_change_column(0))
 398                                return -EIO;
 399
 400                        /*
 401                         * Only read the first sector to speedup detection.
 402                         */
 403                        ret = nand_read_page(conf, offs, dest, conf->ecc_size);
 404                        if (!ret) {
 405                                return 0;
 406                        } else if (ret > 0) {
 407                                /*
 408                                 * If page is empty we can't deduce anything
 409                                 * about the ECC config => stop the detection.
 410                                 */
 411                                return -EINVAL;
 412                        }
 413
 414                        conf->randomize = true;
 415                        conf->nseeds = ARRAY_SIZE(random_seed);
 416                        do {
 417                                if (nand_change_column(0))
 418                                        return -EIO;
 419
 420                                if (!nand_read_page(conf, offs, dest,
 421                                                    conf->ecc_size))
 422                                        return 0;
 423
 424                                /*
 425                                 * Find the next ->nseeds value that would
 426                                 * change the randomizer seed for the page
 427                                 * we're trying to read.
 428                                 */
 429                                while (conf->nseeds >= 16) {
 430                                        int seed = page % conf->nseeds;
 431
 432                                        conf->nseeds >>= 1;
 433                                        if (seed != page % conf->nseeds)
 434                                                break;
 435                                }
 436                        } while (conf->nseeds >= 16);
 437                }
 438        }
 439
 440        return -EINVAL;
 441}
 442
 443static int nand_detect_config(struct nfc_config *conf, u32 offs, void *dest)
 444{
 445        if (conf->valid)
 446                return 0;
 447
 448        /*
 449         * Modern NANDs are more likely than legacy ones, so we start testing
 450         * with 5 address cycles.
 451         */
 452        for (conf->addr_cycles = 5;
 453             conf->addr_cycles >= 4;
 454             conf->addr_cycles--) {
 455                int max_page_size = conf->addr_cycles == 4 ? 2048 : 16384;
 456
 457                /*
 458                 * Ignoring 1k pages cause I'm not even sure this case exist
 459                 * in the real world.
 460                 */
 461                for (conf->page_size = 2048; conf->page_size <= max_page_size;
 462                     conf->page_size <<= 1) {
 463                        if (nand_load_page(conf, offs))
 464                                return -1;
 465
 466                        if (!nand_detect_ecc_config(conf, offs, dest)) {
 467                                conf->valid = true;
 468                                return 0;
 469                        }
 470                }
 471        }
 472
 473        return -EINVAL;
 474}
 475
 476static int nand_read_buffer(struct nfc_config *conf, uint32_t offs,
 477                            unsigned int size, void *dest)
 478{
 479        int first_seed = 0, page, ret;
 480
 481        size = ALIGN(size, conf->page_size);
 482        page = offs / conf->page_size;
 483        if (conf->randomize)
 484                first_seed = page % conf->nseeds;
 485
 486        for (; size; size -= conf->page_size) {
 487                if (nand_load_page(conf, offs))
 488                        return -1;
 489
 490                ret = nand_read_page(conf, offs, dest, conf->page_size);
 491                /*
 492                 * The ->nseeds value should be equal to the number of pages
 493                 * in an eraseblock. Since we don't know this information in
 494                 * advance we might have picked a wrong value.
 495                 */
 496                if (ret < 0 && conf->randomize) {
 497                        int cur_seed = page % conf->nseeds;
 498
 499                        /*
 500                         * We already tried all the seed values => we are
 501                         * facing a real corruption.
 502                         */
 503                        if (cur_seed < first_seed)
 504                                return -EIO;
 505
 506                        /* Try to adjust ->nseeds and read the page again... */
 507                        conf->nseeds = cur_seed;
 508
 509                        if (nand_change_column(0))
 510                                return -EIO;
 511
 512                        /* ... it still fails => it's a real corruption. */
 513                        if (nand_read_page(conf, offs, dest, conf->page_size))
 514                                return -EIO;
 515                } else if (ret && conf->randomize) {
 516                        memset(dest, 0xff, conf->page_size);
 517                }
 518
 519                page++;
 520                offs += conf->page_size;
 521                dest += conf->page_size;
 522        }
 523
 524        return 0;
 525}
 526
 527int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
 528{
 529        static struct nfc_config conf = { };
 530        int ret;
 531
 532        ret = nand_detect_config(&conf, offs, dest);
 533        if (ret)
 534                return ret;
 535
 536        return nand_read_buffer(&conf, offs, size, dest);
 537}
 538
 539void nand_deselect(void)
 540{
 541        struct sunxi_ccm_reg *const ccm =
 542                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 543
 544        clrbits_le32(&ccm->ahb_gate0, (CLK_GATE_OPEN << AHB_GATE_OFFSET_NAND0));
 545#ifdef CONFIG_MACH_SUN9I
 546        clrbits_le32(&ccm->ahb_gate1, (1 << AHB_GATE_OFFSET_DMA));
 547#else
 548        clrbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
 549#endif
 550        clrbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
 551}
 552