/* * Direct Addressing - the slave address forms the control information (command * type, bank, block, and page address). The slave data is the actual data to * be transferred. This mode requires 28 bits of address region allocated.
*/ static u32 denali_direct_read(struct denali_controller *denali, u32 addr)
{ return ioread32(denali->host + addr);
}
/* * Indexed Addressing - address translation module intervenes in passing the * control information. This mode reduces the required address range. The * control information and transferred data are latched by the registers in * the translation module.
*/ static u32 denali_indexed_read(struct denali_controller *denali, u32 addr)
{
iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); return ioread32(denali->host + DENALI_INDEXED_DATA);
}
if (irq_mask & irq_status) { /* return immediately if the IRQ has already happened. */
spin_unlock_irqrestore(&denali->irq_lock, flags); return irq_status;
}
staticint denali_payload_xfer(struct nand_chip *chip, void *buf, bool write)
{ struct denali_controller *denali = to_denali_controller(chip); struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int writesize = mtd->writesize; int oob_skip = denali->oob_skip_bytes; int ret, i, pos, len;
for (i = 0; i < ecc->steps; i++) {
pos = i * (ecc->size + ecc->bytes);
len = ecc->size;
if (pos >= writesize) {
pos += oob_skip;
} elseif (pos + len > writesize) { /* This chunk overwraps the BBM area. Must be split */
ret = denali_change_column(chip, pos, buf,
writesize - pos, write); if (ret) return ret;
ret = denali_change_column(chip, pos, buf, len, write); if (ret) return ret;
buf += len;
}
return 0;
}
staticint denali_oob_xfer(struct nand_chip *chip, void *buf, bool write)
{ struct denali_controller *denali = to_denali_controller(chip); struct mtd_info *mtd = nand_to_mtd(chip); struct nand_ecc_ctrl *ecc = &chip->ecc; int writesize = mtd->writesize; int oobsize = mtd->oobsize; int oob_skip = denali->oob_skip_bytes; int ret, i, pos, len;
/* BBM at the beginning of the OOB area */
ret = denali_change_column(chip, writesize, buf, oob_skip, write); if (ret) return ret;
buf += oob_skip;
for (i = 0; i < ecc->steps; i++) {
pos = ecc->size + i * (ecc->size + ecc->bytes);
if (i == ecc->steps - 1) /* The last chunk includes OOB free */
len = writesize + oobsize - pos - oob_skip; else
len = ecc->bytes;
if (pos >= writesize) {
pos += oob_skip;
} elseif (pos + len > writesize) { /* This chunk overwraps the BBM area. Must be split */
ret = denali_change_column(chip, pos, buf,
writesize - pos, write); if (ret) return ret;
if (ecc_cor & ECC_COR_INFO__UNCOR_ERR) { /* * This flag is set when uncorrectable error occurs at least in * one ECC sector. We can not know "how many sectors", or * "which sector(s)". We need erase-page check for all sectors.
*/
*uncor_ecc_flags = GENMASK(chip->ecc.steps - 1, 0); return 0;
}
/* * The register holds the maximum of per-sector corrected bitflips. * This is suitable for the return value of the ->read_page() callback. * Unfortunately, we can not know the total number of corrected bits in * the page. Increase the stats by max_bitflips. (compromised solution)
*/
ecc_stats->corrected += max_bitflips;
/* reset the bitflip counter when crossing ECC sector */ if (err_sector != prev_sector)
bitflips = 0;
if (err_cor_info & ERR_CORRECTION_INFO__UNCOR) { /* * Check later if this is a real ECC error, or * an erased sector.
*/
*uncor_ecc_flags |= BIT(err_sector);
} elseif (err_byte < ecc_size) { /* * If err_byte is larger than ecc_size, means error * happened in OOB, so we ignore it. It's no need for * us to correct it err_device is represented the NAND * error bits are happened in if there are more than * one NAND connected.
*/ int offset; unsignedint flips_in_byte;
prev_sector = err_sector;
} while (!(err_cor_info & ERR_CORRECTION_INFO__LAST_ERR));
/* * Once handle all ECC errors, controller will trigger an * ECC_TRANSACTION_DONE interrupt.
*/
irq_status = denali_wait_for_irq(denali, INTR__ECC_TRANSACTION_DONE); if (!(irq_status & INTR__ECC_TRANSACTION_DONE)) return -EIO;
if (write) { /* * INTR__PROGRAM_COMP is never asserted for the DMA transfer. * We can use INTR__DMA_CMD_COMP instead. This flag is asserted * when the page program is completed.
*/
irq_mask = INTR__DMA_CMD_COMP | INTR__PROGRAM_FAIL;
ecc_err_mask = 0;
} elseif (denali->caps & DENALI_CAP_HW_ECC_FIXUP) {
irq_mask = INTR__DMA_CMD_COMP;
ecc_err_mask = INTR__ECC_UNCOR_ERR;
} else {
irq_mask = INTR__DMA_CMD_COMP;
ecc_err_mask = INTR__ECC_ERR;
}
iowrite32(DMA_ENABLE__FLAG, denali->reg + DMA_ENABLE); /* * The ->setup_dma() hook kicks DMA by using the data/command * interface, which belongs to a different AXI port from the * register interface. Read back the register to avoid a race.
*/
ioread32(denali->reg + DMA_ENABLE);
timings = nand_get_sdr_timings(conf); if (IS_ERR(timings)) return PTR_ERR(timings);
/* clk_x period in picoseconds */
t_x = DIV_ROUND_DOWN_ULL(1000000000000ULL, denali->clk_x_rate); if (!t_x) return -EINVAL;
/* * The bus interface clock, clk_x, is phase aligned with the core clock. * The clk_x is an integral multiple N of the core clk. The value N is * configured at IP delivery time, and its available value is 4, 5, 6.
*/
mult_x = DIV_ROUND_CLOSEST_ULL(denali->clk_x_rate, denali->clk_rate); if (mult_x < 4 || mult_x > 6) return -EINVAL;
if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) return 0;
/* * tCCS, tWHR -> WE_2_RE * * With WE_2_RE properly set, the Denali controller automatically takes * care of the delay; the driver need not set NAND_WAIT_TCCS.
*/
we_2_re = DIV_ROUND_UP(max(timings->tCCS_min, timings->tWHR_min), t_x);
we_2_re = min_t(int, we_2_re, TWHR2_AND_WE_2_RE__WE_2_RE);
/* for older versions, ADDR_2_DATA is only 6 bit wide */
addr_2_data_mask = TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA; if (denali->revision < 0x0501)
addr_2_data_mask >>= 1;
/* * Determine the minimum of acc_clks to meet the setup timing when * capturing the incoming data. * * The delay on the chip side is well-defined as tREA, but we need to * take additional delay into account. This includes a certain degree * of unknowledge, such as signal propagation delays on the PCB and * in the SoC, load capacity of the I/O pins, etc.
*/
acc_clks = DIV_ROUND_UP(timings->tREA_max + data_setup_on_host, t_x);
/* Determine the minimum of rdwr_en_lo_cnt from RE#/WE# pulse width */
rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x);
/* Extend rdwr_en_lo to meet the data hold timing */
rdwr_en_lo = max_t(int, rdwr_en_lo,
acc_clks - timings->tRHOH_min / t_x);
/* Extend rdwr_en_lo to meet the requirement for RE#/WE# cycle time */
rdwr_en_lo_hi = DIV_ROUND_UP(max(timings->tRC_min, timings->tWC_min),
t_x);
rdwr_en_lo = max(rdwr_en_lo, rdwr_en_lo_hi - rdwr_en_hi);
rdwr_en_lo = min_t(int, rdwr_en_lo, RDWR_EN_LO_CNT__VALUE);
/* Center the data latch timing for extra safety */
acc_clks = (acc_clks + rdwr_en_lo +
DIV_ROUND_UP(timings->tRHOH_min, t_x)) / 2;
acc_clks = min_t(int, acc_clks, ACC_CLKS__VALUE);
/* * Support for multi device: * When the IP configuration is x16 capable and two x8 chips are * connected in parallel, DEVICES_CONNECTED should be set to 2. * In this case, the core framework knows nothing about this fact, * so we should tell it the _logical_ pagesize and anything necessary.
*/
denali->devs_per_cs = ioread32(denali->reg + DEVICES_CONNECTED);
/* * On some SoCs, DEVICES_CONNECTED is not auto-detected. * For those, DEVICES_CONNECTED is left to 0. Set 1 if it is the case.
*/ if (denali->devs_per_cs == 0) {
denali->devs_per_cs = 1;
iowrite32(1, denali->reg + DEVICES_CONNECTED);
}
if (denali->devs_per_cs == 1) return 0;
if (denali->devs_per_cs != 2) {
dev_err(denali->dev, "unsupported number of devices %d\n",
denali->devs_per_cs); return -EINVAL;
}
for (i = 0; i < len; i += 2) {
data = denali->host_read(denali, type | DENALI_BANK(denali)); /* bit 31:24 and 15:8 are used for DDR */
buf[i] = data;
buf[i + 1] = data >> 16;
}
}
staticint denali_exec_op(struct nand_chip *chip, conststruct nand_operation *op, bool check_only)
{ int i, ret;
if (check_only) return 0;
denali_select_target(chip, op->cs);
/* * Some commands contain NAND_OP_WAITRDY_INSTR. * irq must be cleared here to catch the R/B# interrupt there.
*/
denali_reset_irq(to_denali_controller(chip));
for (i = 0; i < op->ninstrs; i++) {
ret = denali_exec_instr(chip, &op->instrs[i]); if (ret) return ret;
}
int denali_chip_init(struct denali_controller *denali, struct denali_chip *dchip)
{ struct nand_chip *chip = &dchip->chip; struct mtd_info *mtd = nand_to_mtd(chip); struct denali_chip *dchip2; int i, j, ret;
chip->controller = &denali->controller;
/* sanity checks for bank numbers */ for (i = 0; i < dchip->nsels; i++) { unsignedint bank = dchip->sels[i].bank;
if (bank >= denali->nbanks) {
dev_err(denali->dev, "unsupported bank %d\n", bank); return -EINVAL;
}
for (j = 0; j < i; j++) { if (bank == dchip->sels[j].bank) {
dev_err(denali->dev, "bank %d is assigned twice in the same chip\n",
bank); return -EINVAL;
}
}
/* * Fallback to the default name if DT did not give "label" property. * Use "label" property if multiple chips are connected.
*/ if (!mtd->name && list_empty(&denali->chips))
mtd->name = "denali-nand";
if (denali->dma_avail) {
chip->options |= NAND_USES_DMA;
chip->buf_align = 16;
}
/* clk rate info is needed for setup_interface */ if (!denali->clk_rate || !denali->clk_x_rate)
chip->options |= NAND_KEEP_TIMINGS;
/* * The REVISION register may not be reliable. Platforms are allowed to * override it.
*/ if (!denali->revision)
denali->revision = swab16(ioread32(denali->reg + REVISION));
/* the encoding changed from rev 5.0 to 5.1 */ if (denali->revision < 0x0501)
denali->nbanks <<= 1;
if (features & FEATURES__DMA)
denali->dma_avail = true;
if (denali->dma_avail) { int dma_bit = denali->caps & DENALI_CAP_DMA_64BIT ? 64 : 32;
ret = dma_set_mask(denali->dev, DMA_BIT_MASK(dma_bit)); if (ret) {
dev_info(denali->dev, "Failed to set DMA mask. Disabling DMA.\n");
denali->dma_avail = false;
}
}
if (denali->dma_avail) { if (denali->caps & DENALI_CAP_DMA_64BIT)
denali->setup_dma = denali_setup_dma64; else
denali->setup_dma = denali_setup_dma32;
}
/* * Set how many bytes should be skipped before writing data in OOB. * If a platform requests a non-zero value, set it to the register. * Otherwise, read the value out, expecting it has already been set up * by firmware.
*/ if (denali->oob_skip_bytes)
iowrite32(denali->oob_skip_bytes,
denali->reg + SPARE_AREA_SKIP_BYTES); else
denali->oob_skip_bytes = ioread32(denali->reg +
SPARE_AREA_SKIP_BYTES);
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.