uboot/drivers/mtd/nand/raw/am335x_spl_bch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2012
   4 * Konstantin Kozhevnikov, Cogent Embedded
   5 *
   6 * based on nand_spl_simple code
   7 *
   8 * (C) Copyright 2006-2008
   9 * Stefan Roese, DENX Software Engineering, sr@denx.de.
  10 */
  11
  12#include <common.h>
  13#include <nand.h>
  14#include <asm/io.h>
  15#include <linux/mtd/nand_ecc.h>
  16
  17static int nand_ecc_pos[] = CONFIG_SYS_NAND_ECCPOS;
  18static struct mtd_info *mtd;
  19static struct nand_chip nand_chip;
  20
  21#define ECCSTEPS        (CONFIG_SYS_NAND_PAGE_SIZE / \
  22                                        CONFIG_SYS_NAND_ECCSIZE)
  23#define ECCTOTAL        (ECCSTEPS * CONFIG_SYS_NAND_ECCBYTES)
  24
  25
  26/*
  27 * NAND command for large page NAND devices (2k)
  28 */
  29static int nand_command(int block, int page, uint32_t offs,
  30        u8 cmd)
  31{
  32        struct nand_chip *this = mtd_to_nand(mtd);
  33        int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;
  34        void (*hwctrl)(struct mtd_info *mtd, int cmd,
  35                        unsigned int ctrl) = this->cmd_ctrl;
  36
  37        while (!this->dev_ready(mtd))
  38                ;
  39
  40        /* Emulate NAND_CMD_READOOB */
  41        if (cmd == NAND_CMD_READOOB) {
  42                offs += CONFIG_SYS_NAND_PAGE_SIZE;
  43                cmd = NAND_CMD_READ0;
  44        }
  45
  46        /* Begin command latch cycle */
  47        hwctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
  48
  49        if (cmd == NAND_CMD_RESET) {
  50                hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
  51
  52                /*
  53                 * Apply this short delay always to ensure that we do wait
  54                 * tWB in any case on any machine.
  55                 */
  56                ndelay(150);
  57
  58                while (!this->dev_ready(mtd))
  59                        ;
  60                return 0;
  61        }
  62
  63        /* Shift the offset from byte addressing to word addressing. */
  64        if ((this->options & NAND_BUSWIDTH_16) && !nand_opcode_8bits(cmd))
  65                offs >>= 1;
  66
  67        /* Set ALE and clear CLE to start address cycle */
  68        /* Column address */
  69        hwctrl(mtd, offs & 0xff,
  70                       NAND_CTRL_ALE | NAND_CTRL_CHANGE); /* A[7:0] */
  71        hwctrl(mtd, (offs >> 8) & 0xff, NAND_CTRL_ALE); /* A[11:9] */
  72        /* Row address */
  73        if (cmd != NAND_CMD_RNDOUT) {
  74                hwctrl(mtd, (page_addr & 0xff),
  75                       NAND_CTRL_ALE); /* A[19:12] */
  76                hwctrl(mtd, ((page_addr >> 8) & 0xff),
  77                       NAND_CTRL_ALE); /* A[27:20] */
  78#ifdef CONFIG_SYS_NAND_5_ADDR_CYCLE
  79                /* One more address cycle for devices > 128MiB */
  80                hwctrl(mtd, (page_addr >> 16) & 0x0f,
  81                       NAND_CTRL_ALE); /* A[31:28] */
  82#endif
  83        }
  84
  85        hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
  86
  87
  88        /*
  89         * Program and erase have their own busy handlers status, sequential
  90         * in and status need no delay.
  91         */
  92        switch (cmd) {
  93        case NAND_CMD_CACHEDPROG:
  94        case NAND_CMD_PAGEPROG:
  95        case NAND_CMD_ERASE1:
  96        case NAND_CMD_ERASE2:
  97        case NAND_CMD_SEQIN:
  98        case NAND_CMD_RNDIN:
  99        case NAND_CMD_STATUS:
 100                return 0;
 101
 102        case NAND_CMD_RNDOUT:
 103                /* No ready / busy check necessary */
 104                hwctrl(mtd, NAND_CMD_RNDOUTSTART, NAND_CTRL_CLE |
 105                       NAND_CTRL_CHANGE);
 106                hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 107                return 0;
 108
 109        case NAND_CMD_READ0:
 110                /* Latch in address */
 111                hwctrl(mtd, NAND_CMD_READSTART,
 112                       NAND_CTRL_CLE | NAND_CTRL_CHANGE);
 113                hwctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 114        }
 115
 116        /*
 117         * Apply this short delay always to ensure that we do wait tWB in
 118         * any case on any machine.
 119         */
 120        ndelay(150);
 121
 122        while (!this->dev_ready(mtd))
 123                ;
 124
 125        return 0;
 126}
 127
 128static int nand_is_bad_block(int block)
 129{
 130        struct nand_chip *this = mtd_to_nand(mtd);
 131
 132        nand_command(block, 0, CONFIG_SYS_NAND_BAD_BLOCK_POS,
 133                NAND_CMD_READOOB);
 134
 135        /*
 136         * Read one byte (or two if it's a 16 bit chip).
 137         */
 138        if (this->options & NAND_BUSWIDTH_16) {
 139                if (readw(this->IO_ADDR_R) != 0xffff)
 140                        return 1;
 141        } else {
 142                if (readb(this->IO_ADDR_R) != 0xff)
 143                        return 1;
 144        }
 145
 146        return 0;
 147}
 148
 149static int nand_read_page(int block, int page, void *dst)
 150{
 151        struct nand_chip *this = mtd_to_nand(mtd);
 152        u_char ecc_calc[ECCTOTAL];
 153        u_char ecc_code[ECCTOTAL];
 154        u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
 155        int i;
 156        int eccsize = CONFIG_SYS_NAND_ECCSIZE;
 157        int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
 158        int eccsteps = ECCSTEPS;
 159        uint8_t *p = dst;
 160        uint32_t data_pos = 0;
 161        uint8_t *oob = &oob_data[0] + nand_ecc_pos[0];
 162        uint32_t oob_pos = eccsize * eccsteps + nand_ecc_pos[0];
 163
 164        nand_command(block, page, 0, NAND_CMD_READ0);
 165
 166        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 167                this->ecc.hwctl(mtd, NAND_ECC_READ);
 168                nand_command(block, page, data_pos, NAND_CMD_RNDOUT);
 169
 170                this->read_buf(mtd, p, eccsize);
 171
 172                nand_command(block, page, oob_pos, NAND_CMD_RNDOUT);
 173
 174                this->read_buf(mtd, oob, eccbytes);
 175                this->ecc.calculate(mtd, p, &ecc_calc[i]);
 176
 177                data_pos += eccsize;
 178                oob_pos += eccbytes;
 179                oob += eccbytes;
 180        }
 181
 182        /* Pick the ECC bytes out of the oob data */
 183        for (i = 0; i < ECCTOTAL; i++)
 184                ecc_code[i] = oob_data[nand_ecc_pos[i]];
 185
 186        eccsteps = ECCSTEPS;
 187        p = dst;
 188
 189        for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 190                /* No chance to do something with the possible error message
 191                 * from correct_data(). We just hope that all possible errors
 192                 * are corrected by this routine.
 193                 */
 194                this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
 195        }
 196
 197        return 0;
 198}
 199
 200/* nand_init() - initialize data to make nand usable by SPL */
 201void nand_init(void)
 202{
 203        /*
 204         * Init board specific nand support
 205         */
 206        mtd = nand_to_mtd(&nand_chip);
 207        nand_chip.IO_ADDR_R = nand_chip.IO_ADDR_W =
 208                (void  __iomem *)CONFIG_SYS_NAND_BASE;
 209        board_nand_init(&nand_chip);
 210
 211        if (nand_chip.select_chip)
 212                nand_chip.select_chip(mtd, 0);
 213
 214        /* NAND chip may require reset after power-on */
 215        nand_command(0, 0, 0, NAND_CMD_RESET);
 216}
 217
 218/* Unselect after operation */
 219void nand_deselect(void)
 220{
 221        if (nand_chip.select_chip)
 222                nand_chip.select_chip(mtd, -1);
 223}
 224
 225#include "nand_spl_loaders.c"
 226