/** * struct anfc_op - Defines how to execute an operation * @pkt_reg: Packet register * @addr1_reg: Memory address 1 register * @addr2_reg: Memory address 2 register * @cmd_reg: Command register * @prog_reg: Program register * @steps: Number of "packets" to read/write * @rdy_timeout_ms: Timeout for waits on Ready/Busy pin * @len: Data transfer length * @read: Data transfer direction from the controller point of view * @buf: Data buffer
*/ struct anfc_op {
u32 pkt_reg;
u32 addr1_reg;
u32 addr2_reg;
u32 cmd_reg;
u32 prog_reg; int steps; unsignedint rdy_timeout_ms; unsignedint len; bool read;
u8 *buf;
};
/** * struct anand - Defines the NAND chip related information * @node: Used to store NAND chips into a list * @chip: NAND chip information structure * @rb: Ready-busy line * @page_sz: Register value of the page_sz field to use * @clk: Expected clock frequency to use * @data_iface: Data interface timing mode to use * @timings: NV-DDR specific timings to use * @ecc_conf: Hardware ECC configuration value * @strength: Register value of the ECC strength * @raddr_cycles: Row address cycle information * @caddr_cycles: Column address cycle information * @ecc_bits: Exact number of ECC bits per syndrome * @ecc_total: Total number of ECC bytes * @errloc: Array of errors located with soft BCH * @hw_ecc: Buffer to store syndromes computed by hardware * @bch: BCH structure * @cs_idx: Array of chip-select for this device, values are indexes * of the controller structure @gpio_cs array * @ncs_idx: Size of the @cs_idx array
*/ struct anand { struct list_head node; struct nand_chip chip; unsignedint rb; unsignedint page_sz; unsignedlong clk;
u32 data_iface;
u32 timings;
u32 ecc_conf;
u32 strength;
u16 raddr_cycles;
u16 caddr_cycles; unsignedint ecc_bits; unsignedint ecc_total; unsignedint *errloc;
u8 *hw_ecc; struct bch_control *bch; int *cs_idx; int ncs_idx;
};
/** * struct arasan_nfc - Defines the Arasan NAND flash controller driver instance * @dev: Pointer to the device structure * @base: Remapped register area * @controller_clk: Pointer to the system clock * @bus_clk: Pointer to the flash clock * @controller: Base controller structure * @chips: List of all NAND chips attached to the controller * @cur_clk: Current clock rate * @cs_array: CS array. Native CS are left empty, the other cells are * populated with their corresponding GPIO descriptor. * @ncs: Size of @cs_array * @cur_cs: Index in @cs_array of the currently in use CS * @native_cs: Currently selected native CS * @spare_cs: Native CS that is not wired (may be selected when a GPIO * CS is in use)
*/ struct arasan_nfc { struct device *dev; void __iomem *base; struct clk *controller_clk; struct clk *bus_clk; struct nand_controller controller; struct list_head chips; unsignedint cur_clk; struct gpio_desc **cs_array; unsignedint ncs; int cur_cs; unsignedint native_cs; unsignedint spare_cs;
};
/* There is no R/B interrupt, we must poll a register */
ret = readl_relaxed_poll_timeout(nfc->base + READY_STS_REG, val,
val & BIT(anand->rb),
1, timeout_ms * 1000); if (ret) {
dev_err(nfc->dev, "Timeout waiting for R/B 0x%x\n",
readl_relaxed(nfc->base + READY_STS_REG)); return -ETIMEDOUT;
}
/* Update the controller timings and the potential ECC configuration */
writel_relaxed(anand->data_iface, nfc->base + DATA_INTERFACE_REG);
writel_relaxed(anand->timings, nfc->base + TIMING_REG);
/* Update clock frequency */ if (nfc->cur_clk != anand->clk) {
clk_disable_unprepare(nfc->bus_clk);
ret = clk_set_rate(nfc->bus_clk, anand->clk); if (ret) {
dev_err(nfc->dev, "Failed to change clock rate\n"); return ret;
}
ret = clk_prepare_enable(nfc->bus_clk); if (ret) {
dev_err(nfc->dev, "Failed to re-enable the bus clock\n"); return ret;
}
nfc->cur_clk = anand->clk;
}
return 0;
}
/* * When using the embedded hardware ECC engine, the controller is in charge of * feeding the engine with, first, the ECC residue present in the data array. * A typical read operation is: * 1/ Assert the read operation by sending the relevant command/address cycles * but targeting the column of the first ECC bytes in the OOB area instead of * the main data directly. * 2/ After having read the relevant number of ECC bytes, the controller uses * the RNDOUT/RNDSTART commands which are set into the "ECC Spare Command * Register" to move the pointer back at the beginning of the main data. * 3/ It will read the content of the main area for a given size (pktsize) and * will feed the ECC engine with this buffer again. * 4/ The ECC engine derives the ECC bytes for the given data and compare them * with the ones already received. It eventually trigger status flags and * then set the "Buffer Read Ready" flag. * 5/ The corrected data is then available for reading from the data port * register. * * The hardware BCH ECC engine is known to be inconstent in BCH mode and never * reports uncorrectable errors. Because of this bug, we have to use the * software BCH implementation in the read path.
*/ staticint anfc_read_page_hw_ecc(struct nand_chip *chip, u8 *buf, int oob_required, int page)
{ struct arasan_nfc *nfc = to_anfc(chip->controller); struct mtd_info *mtd = nand_to_mtd(chip); struct anand *anand = to_anand(chip); unsignedint len = mtd->writesize + (oob_required ? mtd->oobsize : 0); unsignedint max_bitflips = 0;
dma_addr_t dma_addr; int step, ret; struct anfc_op nfc_op = {
.pkt_reg =
PKT_SIZE(chip->ecc.size) |
PKT_STEPS(chip->ecc.steps),
.addr1_reg =
(page & 0xFF) << (8 * (anand->caddr_cycles)) |
(((page >> 8) & 0xFF) << (8 * (1 + anand->caddr_cycles))),
.addr2_reg =
((page >> 16) & 0xFF) |
ADDR2_STRENGTH(anand->strength) |
ADDR2_CS(nfc->native_cs),
.cmd_reg =
CMD_1(NAND_CMD_READ0) |
CMD_2(NAND_CMD_READSTART) |
CMD_PAGE_SIZE(anand->page_sz) |
CMD_DMA_ENABLE |
CMD_NADDRS(anand->caddr_cycles +
anand->raddr_cycles),
.prog_reg = PROG_PGRD,
};
ret = anfc_wait_for_event(nfc, XFER_COMPLETE);
dma_unmap_single(nfc->dev, dma_addr, len, DMA_FROM_DEVICE); if (ret) {
dev_err(nfc->dev, "Error reading page %d\n", page); return ret;
}
/* Store the raw OOB bytes as well */
ret = nand_change_read_column_op(chip, mtd->writesize, chip->oob_poi,
mtd->oobsize, 0); if (ret) return ret;
/* * For each step, compute by softare the BCH syndrome over the raw data. * Compare the theoretical amount of errors and compare with the * hardware engine feedback.
*/ for (step = 0; step < chip->ecc.steps; step++) {
u8 *raw_buf = &buf[step * chip->ecc.size]; unsignedint bit, byte; int bf, i;
/* Extract the syndrome, it is not necessarily aligned */
memset(anand->hw_ecc, 0, chip->ecc.bytes);
nand_extract_bits(anand->hw_ecc, 0,
&chip->oob_poi[mtd->oobsize - anand->ecc_total],
anand->ecc_bits * step, anand->ecc_bits);
bf = bch_decode(anand->bch, raw_buf, chip->ecc.size,
anand->hw_ecc, NULL, NULL, anand->errloc); if (!bf) { continue;
} elseif (bf > 0) { for (i = 0; i < bf; i++) { /* Only correct the data, not the syndrome */ if (anand->errloc[i] < (chip->ecc.size * 8)) {
bit = BIT(anand->errloc[i] & 7);
byte = anand->errloc[i] >> 3;
raw_buf[byte] ^= bit;
}
}
for (i = 0; i < min(ANFC_MAX_ADDR_CYC, naddrs); i++) { if (i < 4)
nfc_op->addr1_reg |= (u32)addrs[i] << i * 8; else
nfc_op->addr2_reg |= addrs[i];
}
break; case NAND_OP_DATA_IN_INSTR:
nfc_op->read = true;
fallthrough; case NAND_OP_DATA_OUT_INSTR:
offset = nand_subop_get_data_start_off(subop, op_id);
buf = instr->ctx.data.buf.in;
nfc_op->buf = &buf[offset];
nfc_op->len = nand_subop_get_data_len(subop, op_id);
ret = anfc_pkt_len_config(nfc_op->len, &nfc_op->steps,
&pktsize); if (ret) return ret;
/* * Number of DATA cycles must be aligned on 4, this * means the controller might read/write more than * requested. This is harmless most of the time as extra * DATA are discarded in the write path and read pointer * adjusted in the read path. * * FIXME: The core should mark operations where * reading/writing more is allowed so the exec_op() * implementation can take the right decision when the * alignment constraint is not met: adjust the number of * DATA cycles when it's allowed, reject the operation * otherwise.
*/
nfc_op->pkt_reg |= PKT_SIZE(round_up(pktsize, 4)) |
PKT_STEPS(nfc_op->steps); break; case NAND_OP_WAITRDY_INSTR:
nfc_op->rdy_timeout_ms = instr->ctx.waitrdy.timeout_ms; break;
}
}
for (i = 0; i < nfc_op->steps; i++) {
dir = nfc_op->read ? READ_READY : WRITE_READY;
ret = anfc_wait_for_event(nfc, dir); if (ret) {
dev_err(nfc->dev, "PIO %s ready signal not received\n",
nfc_op->read ? "Read" : "Write"); return ret;
}
/* * Experience shows that while in SDR mode sending a CHANGE READ COLUMN * command through the READ PAGE "type" always works fine, when in * NV-DDR mode the same command simply fails. However, it was also * spotted that any CHANGE READ COLUMN command sent through the CHANGE * READ COLUMN ENHANCED "type" would correctly work in both cases (SDR * and NV-DDR). So, for simplicity, let's program the controller with * the CHANGE READ COLUMN ENHANCED "type" whenever we are requested to * perform a CHANGE READ COLUMN operation.
*/ if (subop->instrs[0].ctx.cmd.opcode == NAND_CMD_RNDOUT &&
subop->instrs[2].ctx.cmd.opcode == NAND_CMD_RNDOUTSTART)
prog_reg = PROG_CHG_RD_COL_ENH;
/* * The controller abstracts all the NAND operations and do not support * data only operations. * * TODO: The nand_op_parser framework should be extended to * support custom checks on DATA instructions.
*/ for (op_id = 0; op_id < op->ninstrs; op_id++) {
instr = &op->instrs[op_id];
switch (instr->type) { case NAND_OP_ADDR_INSTR: if (instr->ctx.addr.naddrs > ANFC_MAX_ADDR_CYC) return -ENOTSUPP;
break; case NAND_OP_DATA_IN_INSTR: case NAND_OP_DATA_OUT_INSTR: if (instr->ctx.data.len > ANFC_MAX_CHUNK_SIZE) return -ENOTSUPP;
if (anfc_pkt_len_config(instr->ctx.data.len, NULL, NULL)) return -ENOTSUPP;
break; default: break;
}
}
/* * The controller does not allow to proceed with a CMD+DATA_IN cycle * manually on the bus by reading data from the data register. Instead, * the controller abstract a status read operation with its own status * register after ordering a read status operation. Hence, we cannot * support any CMD+DATA_IN operation other than a READ STATUS. * * TODO: The nand_op_parser() framework should be extended to describe * fixed patterns instead of open-coding this check here.
*/ if (op->ninstrs == 2 &&
op->instrs[0].type == NAND_OP_CMD_INSTR &&
op->instrs[0].ctx.cmd.opcode != NAND_CMD_STATUS &&
op->instrs[1].type == NAND_OP_DATA_IN_INSTR) return -ENOTSUPP;
if (nand_interface_is_sdr(conf)) {
anand->clk = ANFC_XLNX_SDR_DFLT_CORE_CLK;
} else { /* ONFI timings are defined in picoseconds */
anand->clk = div_u64((u64)NSEC_PER_SEC * 1000,
conf->timings.nvddr.tCK_min);
}
/* * Due to a hardware bug in the ZynqMP SoC, SDR timing modes 0-1 work * with f > 90MHz (default clock is 100MHz) but signals are unstable * with higher modes. Hence we decrease a little bit the clock rate to * 80MHz when using SDR modes 2-5 with this SoC.
*/ if (of_device_is_compatible(np, "xlnx,zynqmp-nand-controller") &&
nand_interface_is_sdr(conf) && conf->timings.mode >= 2)
anand->clk = ANFC_XLNX_SDR_HS_CORE_CLK;
return 0;
}
staticint anfc_calc_hw_ecc_bytes(int step_size, int strength)
{ unsignedint bch_gf_mag, ecc_bits;
switch (step_size) { case SZ_512:
bch_gf_mag = 13; break; case SZ_1K:
bch_gf_mag = 14; break; default: return -EINVAL;
}
switch (mtd->writesize) { case SZ_512: case SZ_2K: case SZ_4K: case SZ_8K: case SZ_16K: break; default:
dev_err(nfc->dev, "Unsupported page size %d\n", mtd->writesize); return -EINVAL;
}
ret = nand_ecc_choose_conf(chip, &anfc_hw_ecc_caps, mtd->oobsize); if (ret) return ret;
switch (ecc->strength) { case 12:
anand->strength = 0x1; break; case 8:
anand->strength = 0x2; break; case 4:
anand->strength = 0x3; break; case 24:
anand->strength = 0x4; break; default:
dev_err(nfc->dev, "Unsupported strength %d\n", ecc->strength); return -EINVAL;
}
switch (mtd->writesize) { case 512:
anand->page_sz = 0; break; case 1024:
anand->page_sz = 5; break; case 2048:
anand->page_sz = 1; break; case 4096:
anand->page_sz = 2; break; case 8192:
anand->page_sz = 3; break; case 16384:
anand->page_sz = 4; break; default: return -EINVAL;
}
/* These hooks are valid for all ECC providers */
chip->ecc.read_page_raw = nand_monolithic_read_page_raw;
chip->ecc.write_page_raw = nand_monolithic_write_page_raw;
switch (chip->ecc.engine_type) { case NAND_ECC_ENGINE_TYPE_NONE: case NAND_ECC_ENGINE_TYPE_SOFT: case NAND_ECC_ENGINE_TYPE_ON_DIE: break; case NAND_ECC_ENGINE_TYPE_ON_HOST:
ret = anfc_init_hw_ecc_controller(nfc, chip); break; default:
dev_err(nfc->dev, "Unsupported ECC mode: %d\n",
chip->ecc.engine_type); return -EINVAL;
}
anand->cs_idx = devm_kcalloc(nfc->dev, anand->ncs_idx, sizeof(*anand->cs_idx), GFP_KERNEL); if (!anand->cs_idx) return -ENOMEM;
for (i = 0; i < anand->ncs_idx; i++) {
ret = of_property_read_u32_index(np, "reg", i,
&anand->cs_idx[i]); if (ret) {
dev_err(nfc->dev, "invalid CS property: %d\n", ret); return ret;
}
}
/* Ready-busy init */
ret = of_property_read_u32(np, "nand-rb", &rb); if (ret) return ret;
/* Enable interrupt status */
writel_relaxed(EVENT_MASK, nfc->base + INTR_STS_EN_REG);
nfc->cur_cs = -1;
}
staticint anfc_parse_cs(struct arasan_nfc *nfc)
{ int ret;
/* Check the gpio-cs property */
ret = rawnand_dt_parse_gpio_cs(nfc->dev, &nfc->cs_array, &nfc->ncs); if (ret) return ret;
/* * The controller native CS cannot be both disabled at the same time. * Hence, only one native CS can be used if GPIO CS are needed, so that * the other is selected when a non-native CS must be asserted (not * wired physically or configured as GPIO instead of NAND CS). In this * case, the "not" chosen CS is assigned to nfc->spare_cs and selected * whenever a GPIO CS must be asserted.
*/ if (nfc->cs_array) { if (nfc->ncs > 2 && !nfc->cs_array[0] && !nfc->cs_array[1]) {
dev_err(nfc->dev, "Assign a single native CS when using GPIOs\n"); return -EINVAL;
}
if (nfc->cs_array[0])
nfc->spare_cs = 0; else
nfc->spare_cs = 1;
}
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.