/* * According to SPEAr300 Reference Manual (RM0082) * TOUDEL = 7ns (Output delay from the flip-flops to the board) * TINDEL = 5ns (Input delay from the board to the flipflop)
*/ #define TOUTDEL 7000 #define TINDEL 5000
/** * struct fsmc_nand_data - structure for FSMC NAND device state * * @base: Inherit from the nand_controller struct * @pid: Part ID on the AMBA PrimeCell format * @nand: Chip related info for a NAND flash. * * @bank: Bank number for probed device. * @dev: Parent device * @mode: Access mode * @clk: Clock structure for FSMC. * * @read_dma_chan: DMA channel for read access * @write_dma_chan: DMA channel for write access to NAND * @dma_access_complete: Completion structure * * @dev_timings: NAND timings * * @data_pa: NAND Physical port for Data. * @data_va: NAND port for Data. * @cmd_va: NAND port for Command. * @addr_va: NAND port for Address. * @regs_va: Registers base address for a given bank.
*/ struct fsmc_nand_data { struct nand_controller base;
u32 pid; struct nand_chip nand;
/* * ECC placement definitions in oobfree type format. * There are 13 bytes of ecc for every 512 byte block and it has to be read * consecutively and immediately after the 512 byte data block for hardware to * generate the error bit offsets in 512 byte data.
*/ staticint fsmc_ecc4_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion)
{ struct nand_chip *chip = mtd_to_nand(mtd);
/* * fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction up to * max of 1-bit)
*/ staticint fsmc_read_hwecc_ecc1(struct nand_chip *chip, const u8 *data,
u8 *ecc)
{ struct fsmc_nand_data *host = nand_to_fsmc(chip);
u32 ecc_tmp;
len = len >> 2; for (i = 0; i < len; i++)
writel_relaxed(p[i], host->data_va);
} else { for (i = 0; i < len; i++)
writeb_relaxed(buf[i], host->data_va);
}
}
/* * fsmc_read_buf - read chip data into buffer * @host: FSMC NAND controller * @buf: buffer to store date * @len: number of bytes to read
*/ staticvoid fsmc_read_buf(struct fsmc_nand_data *host, u8 *buf, int len)
{ int i;
len = len >> 2; for (i = 0; i < len; i++)
p[i] = readl_relaxed(host->data_va);
} else { for (i = 0; i < len; i++)
buf[i] = readb_relaxed(host->data_va);
}
}
/* * fsmc_read_buf_dma - read chip data into buffer * @host: FSMC NAND controller * @buf: buffer to store date * @len: number of bytes to read
*/ staticvoid fsmc_read_buf_dma(struct fsmc_nand_data *host, u8 *buf, int len)
{
dma_xfer(host, buf, len, DMA_FROM_DEVICE);
}
/* * fsmc_write_buf_dma - write buffer to chip * @host: FSMC NAND controller * @buf: data buffer * @len: number of bytes to write
*/ staticvoid fsmc_write_buf_dma(struct fsmc_nand_data *host, const u8 *buf, int len)
{
dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
}
/* * fsmc_exec_op - hook called by the core to execute NAND operations * * This controller is simple enough and thus does not need to use the parser * provided by the core, instead, handle every situation here.
*/ staticint fsmc_exec_op(struct nand_chip *chip, conststruct nand_operation *op, bool check_only)
{ struct fsmc_nand_data *host = nand_to_fsmc(chip); conststruct nand_op_instr *instr = NULL; int ret = 0; unsignedint op_id; int i;
switch (instr->type) { case NAND_OP_CMD_INSTR:
writeb_relaxed(instr->ctx.cmd.opcode, host->cmd_va); break;
case NAND_OP_ADDR_INSTR: for (i = 0; i < instr->ctx.addr.naddrs; i++)
writeb_relaxed(instr->ctx.addr.addrs[i],
host->addr_va); break;
case NAND_OP_DATA_IN_INSTR: if (host->mode == USE_DMA_ACCESS)
fsmc_read_buf_dma(host, instr->ctx.data.buf.in,
instr->ctx.data.len); else
fsmc_read_buf(host, instr->ctx.data.buf.in,
instr->ctx.data.len); break;
case NAND_OP_DATA_OUT_INSTR: if (host->mode == USE_DMA_ACCESS)
fsmc_write_buf_dma(host,
instr->ctx.data.buf.out,
instr->ctx.data.len); else
fsmc_write_buf(host, instr->ctx.data.buf.out,
instr->ctx.data.len); break;
case NAND_OP_WAITRDY_INSTR:
ret = nand_soft_waitrdy(chip,
instr->ctx.waitrdy.timeout_ms); break;
}
if (instr->delay_ns)
ndelay(instr->delay_ns);
}
return ret;
}
/* * fsmc_read_page_hwecc * @chip: nand chip info structure * @buf: buffer to store read data * @oob_required: caller expects OOB data read to chip->oob_poi * @page: page number to read * * This routine is needed for fsmc version 8 as reading from NAND chip has to be * performed in a strict sequence as follows: * data(512 byte) -> ecc(13 byte) * After this read, fsmc hardware generates and reports error data bits(up to a * max of 8 bits)
*/ staticint fsmc_read_page_hwecc(struct nand_chip *chip, u8 *buf, int oob_required, int page)
{ struct mtd_info *mtd = nand_to_mtd(chip); int i, j, s, stat, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; int eccsteps = chip->ecc.steps;
u8 *p = buf;
u8 *ecc_calc = chip->ecc.calc_buf;
u8 *ecc_code = chip->ecc.code_buf; int off, len, ret, group = 0; /* * ecc_oob is intentionally taken as u16. In 16bit devices, we * end up reading 14 bytes (7 words) from oob. The local array is * to maintain word alignment
*/
u16 ecc_oob[7];
u8 *oob = (u8 *)&ecc_oob[0]; unsignedint max_bitflips = 0;
for (i = 0, s = 0; s < eccsteps; s++, i += eccbytes, p += eccsize) {
nand_read_page_op(chip, page, s * eccsize, NULL, 0);
chip->ecc.hwctl(chip, NAND_ECC_READ);
ret = nand_read_data_op(chip, p, eccsize, false, false); if (ret) return ret;
ret = mtd_ooblayout_ecc(mtd, group++, &oobregion); if (ret) return ret;
off = oobregion.offset;
len = oobregion.length;
/* * length is intentionally kept a higher multiple of 2 * to read at least 13 bytes even in case of 16 bit NAND * devices
*/ if (chip->options & NAND_BUSWIDTH_16)
len = roundup(len, 2);
/* * fsmc_bch8_correct_data * @mtd: mtd info structure * @dat: buffer of read data * @read_ecc: ecc read from device spare area * @calc_ecc: ecc calculated from read data * * calc_ecc is a 104 bit information containing maximum of 8 error * offset information of 13 bits each in 512 bytes of read data.
*/ staticint fsmc_bch8_correct_data(struct nand_chip *chip, u8 *dat,
u8 *read_ecc, u8 *calc_ecc)
{ struct fsmc_nand_data *host = nand_to_fsmc(chip);
u32 err_idx[8];
u32 num_err, i;
u32 ecc1, ecc2, ecc3, ecc4;
/* no bit flipping */ if (likely(num_err == 0)) return 0;
/* too many errors */ if (unlikely(num_err > 8)) { /* * This is a temporary erase check. A newly erased page read * would result in an ecc error because the oob data is also * erased to FF and the calculated ecc for an FF data is not * FF..FF. * This is a workaround to skip performing correction in case * data is FF..FF * * Logic: * For every page, each bit written as 0 is counted until these * number of bits are greater than 8 (the maximum correction * capability of FSMC for each 512 + 13 bytes)
*/
int bits_ecc = count_written_bits(read_ecc, chip->ecc.bytes, 8); int bits_data = count_written_bits(dat, chip->ecc.size, 8);
if ((bits_ecc + bits_data) <= 8) { if (bits_data)
memset(dat, 0xff, chip->ecc.size); return bits_data;
}
return -EBADMSG;
}
/* * ------------------- calc_ecc[] bit wise -----------|--13 bits--| * |---idx[7]--|--.....-----|---idx[2]--||---idx[1]--||---idx[0]--| * * calc_ecc is a 104 bit information containing maximum of 8 error * offset information of 13 bits each. calc_ecc is copied into a * u64 array and error offset indexes are populated in err_idx * array
*/
ecc1 = readl_relaxed(host->regs_va + ECC1);
ecc2 = readl_relaxed(host->regs_va + ECC2);
ecc3 = readl_relaxed(host->regs_va + ECC3);
ecc4 = readl_relaxed(host->regs_va + STS);
if (AMBA_REV_BITS(host->pid) >= 8) { switch (mtd->oobsize) { case 16: case 64: case 128: case 224: case 256: break; default:
dev_warn(host->dev, "No oob scheme defined for oobsize %d\n",
mtd->oobsize); return -EINVAL;
}
/* * Don't set layout for BCH4 SW ECC. This will be * generated later during BCH initialization.
*/ if (nand->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) { switch (mtd->oobsize) { case 16: case 64: case 128:
mtd_set_ooblayout(mtd,
&fsmc_ecc1_ooblayout_ops); break; default:
dev_warn(host->dev, "No oob scheme defined for oobsize %d\n",
mtd->oobsize); return -EINVAL;
}
}
/* Allocate memory for the device structure (and zero it) */
host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); if (!host) return -ENOMEM;
nand = &host->nand;
ret = fsmc_nand_probe_config_dt(pdev, host, nand); if (ret) return ret;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
host->data_va = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(host->data_va)) return PTR_ERR(host->data_va);
host->data_pa = (dma_addr_t)res->start;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_addr");
host->addr_va = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(host->addr_va)) return PTR_ERR(host->addr_va);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_cmd");
host->cmd_va = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(host->cmd_va)) return PTR_ERR(host->cmd_va);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs");
base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(base)) return PTR_ERR(base);
host->regs_va = base + FSMC_NOR_REG_SIZE +
(host->bank * FSMC_NAND_BANK_SZ);
host->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(host->clk)) {
dev_err(&pdev->dev, "failed to fetch block clock\n"); return PTR_ERR(host->clk);
}
/* * This device ID is actually a common AMBA ID as used on the * AMBA PrimeCell bus. However it is not a PrimeCell.
*/ for (pid = 0, i = 0; i < 4; i++)
pid |= (readl(base + resource_size(res) - 0x20 + 4 * i) &
255) << (i * 8);
if (host) {
ret = clk_prepare_enable(host->clk); if (ret) {
dev_err(dev, "failed to enable clk\n"); return ret;
} if (host->dev_timings)
fsmc_nand_setup(host, host->dev_timings);
nand_reset(&host->nand, 0);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.