/* Resource names for the GPMI NAND driver. */ #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" #define GPMI_NAND_BCH_REGS_ADDR_RES_NAME "bch" #define GPMI_NAND_BCH_INTERRUPT_RES_NAME "bch"
/* Converts time to clock cycles */ #define TO_CYCLES(duration, period) DIV_ROUND_UP_ULL(duration, period)
#define MXS_SET_ADDR 0x4 #define MXS_CLR_ADDR 0x8 /* * Clear the bit and poll it cleared. This is usually called with * a reset address and mask being either SFTRST(bit 31) or CLKGATE * (bit 30).
*/ staticint clear_poll_bit(void __iomem *addr, u32 mask)
{ int timeout = 0x400;
/* clear the bit */
writel(mask, addr + MXS_CLR_ADDR);
/* * SFTRST needs 3 GPMI clocks to settle, the reference manual * recommends to wait 1us.
*/
udelay(1);
/* poll the bit becoming clear */ while ((readl(addr) & mask) && --timeout) /* nothing */;
return !timeout;
}
#define MODULE_CLKGATE (1 << 30) #define MODULE_SFTRST (1 << 31) /* * The current mxs_reset_block() will do two things: * [1] enable the module. * [2] reset the module. * * In most of the cases, it's ok. * But in MX23, there is a hardware bug in the BCH block (see erratum #2847). * If you try to soft reset the BCH block, it becomes unusable until * the next hard reset. This case occurs in the NAND boot mode. When the board * boots by NAND, the ROM of the chip will initialize the BCH blocks itself. * So If the driver tries to reset the BCH again, the BCH will not work anymore. * You will see a DMA timeout in this case. The bug has been fixed * in the following chips, such as MX28. * * To avoid this bug, just add a new parameter `just_enable` for * the mxs_reset_block(), and rewrite it here.
*/ staticint gpmi_reset_block(void __iomem *reset_addr, bool just_enable)
{ int ret; int timeout = 0x400;
/* clear and poll SFTRST */
ret = clear_poll_bit(reset_addr, MODULE_SFTRST); if (unlikely(ret)) goto error;
ret = pm_runtime_resume_and_get(this->dev); if (ret < 0) return ret;
ret = gpmi_reset_block(r->gpmi_regs, false); if (ret) goto err_out;
/* * Reset BCH here, too. We got failures otherwise :( * See later BCH reset for explanation of MX23 and MX28 handling
*/
ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this)); if (ret) goto err_out;
/* Select BCH ECC. */
writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET);
/* * Decouple the chip select from dma channel. We use dma0 for all * the chips, force all NAND RDY_BUSY inputs to be sourced from * RDY_BUSY0.
*/
writel(BM_GPMI_CTRL1_DECOUPLE_CS | BM_GPMI_CTRL1_GANGED_RDYBUSY,
r->gpmi_regs + HW_GPMI_CTRL1_SET);
/* This function is very useful. It is called only when the bug occur. */ staticvoid gpmi_dump_info(struct gpmi_nand_data *this)
{ struct resources *r = &this->resources; struct bch_geometry *geo = &this->bch_geometry;
u32 reg; int i;
dev_err(this->dev, "Show GPMI registers :\n"); for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) {
reg = readl(r->gpmi_regs + i * 0x10);
dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
}
/* start to print out the BCH info */
dev_err(this->dev, "Show BCH registers :\n"); for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) {
reg = readl(r->bch_regs + i * 0x10);
dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg);
}
dev_err(this->dev, "BCH Geometry :\n" "GF length : %u\n" "ECC Strength : %u\n" "Page Size in Bytes : %u\n" "Metadata Size in Bytes : %u\n" "ECC0 Chunk Size in Bytes: %u\n" "ECCn Chunk Size in Bytes: %u\n" "ECC Chunk Count : %u\n" "Payload Size in Bytes : %u\n" "Auxiliary Size in Bytes: %u\n" "Auxiliary Status Offset: %u\n" "Block Mark Byte Offset : %u\n" "Block Mark Bit Offset : %u\n",
geo->gf_len,
geo->ecc_strength,
geo->page_size,
geo->metadata_size,
geo->ecc0_chunk_size,
geo->eccn_chunk_size,
geo->ecc_chunk_count,
geo->payload_size,
geo->auxiliary_size,
geo->auxiliary_status_offset,
geo->block_mark_byte_offset,
geo->block_mark_bit_offset);
}
if (j < geo->eccn_chunk_size * 8) {
*chunk_num = i+1;
dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
geo->ecc_strength, *chunk_num); returntrue;
}
returnfalse;
}
/* * If we can get the ECC information from the nand chip, we do not * need to calculate them ourselves. * * We may have available oob space in this case.
*/ staticint set_geometry_by_ecc_info(struct gpmi_nand_data *this, unsignedint ecc_strength, unsignedint ecc_step)
{ struct bch_geometry *geo = &this->bch_geometry; struct nand_chip *chip = &this->nand; struct mtd_info *mtd = nand_to_mtd(chip); unsignedint block_mark_bit_offset;
/* * Now, the NAND chip with 2K page(data chunk is 512byte) shows below: * * | P | * |<----------------------------------------------------->| * | | * | (Block Mark) | * | P' | | | | * |<-------------------------------------------->| D | | O' | * | |<---->| |<--->| * V V V V V * +---+----------+-+----------+-+----------+-+----------+-+-----+ * | M | data |E| data |E| data |E| data |E| | * +---+----------+-+----------+-+----------+-+----------+-+-----+ * ^ ^ * | O | * |<------------>| * | | * * P : the page size for BCH module. * E : The ECC strength. * G : the length of Galois Field. * N : The chunk count of per page. * M : the metasize of per page. * C : the ecc chunk size, aka the "data" above. * P': the nand chip's page size. * O : the nand chip's oob size. * O': the free oob. * * The formula for P is : * * E * G * N * P = ------------ + P' + M * 8 * * The position of block mark moves forward in the ECC-based view * of page, and the delta is: * * E * G * (N - 1) * D = (---------------- + M) * 8 * * Please see the comment in legacy_set_geometry(). * With the condition C >= O , we still can get same result. * So the bit position of the physical block mark within the ECC-based * view of the page is : * (P' - D) * 8
*/
geo->page_size = mtd->writesize + geo->metadata_size +
(geo->gf_len * geo->ecc_strength * geo->ecc_chunk_count) / 8;
/* * Calculate the ECC strength by hand: * E : The ECC strength. * G : the length of Galois Field. * N : The chunk count of per page. * O : the oobsize of the NAND chip. * M : the metasize of per page. * * The formula is : * E * G * N * ------------ <= (O - M) * 8 * * So, we get E by: * (O - M) * 8 * E <= ------------- * G * N
*/ staticinlineint get_ecc_strength(struct gpmi_nand_data *this)
{ struct bch_geometry *geo = &this->bch_geometry; struct mtd_info *mtd = nand_to_mtd(&this->nand); int ecc_strength;
/* sanity check for the minimum ecc nand required */ if (!(requirements->strength > 0 &&
requirements->step_size > 0)) return -EINVAL;
geo->ecc_strength = requirements->strength;
/* check if platform can support this nand */ if (!gpmi_check_ecc(this)) {
dev_err(this->dev, "unsupported NAND chip, minimum ecc required %d\n",
geo->ecc_strength); return -EINVAL;
}
/* calculate the maximum ecc platform can support*/
geo->metadata_size = 10;
geo->gf_len = 14;
geo->ecc0_chunk_size = 1024;
geo->eccn_chunk_size = 1024;
geo->ecc_chunk_count = mtd->writesize / geo->eccn_chunk_size;
max_ecc = min(get_ecc_strength(this),
this->devdata->bch_max_ecc_strength);
/* * search a supported ecc strength that makes bbm * located in data chunk
*/
geo->ecc_strength = max_ecc; while (!(geo->ecc_strength < requirements->strength)) { if (bbm_in_data_chunk(this, &bbm_chunk)) goto geo_setting;
geo->ecc_strength -= 2;
}
/* if none of them works, keep using the minimum ecc */ /* nand required but changing ecc page layout */
geo->ecc_strength = requirements->strength; /* add extra ecc for meta data */
geo->ecc0_chunk_size = 0;
geo->ecc_chunk_count = (mtd->writesize / geo->eccn_chunk_size) + 1;
geo->ecc_for_meta = 1; /* check if oob can afford this extra ecc chunk */ if (mtd->oobsize * 8 < geo->metadata_size * 8 +
geo->gf_len * geo->ecc_strength * geo->ecc_chunk_count) {
dev_err(this->dev, "unsupported NAND chip with new layout\n"); return -EINVAL;
}
/* * The auxiliary buffer contains the metadata and the ECC status. The * metadata is padded to the nearest 32-bit boundary. The ECC status * contains one byte for every ECC chunk, and is also padded to the * nearest 32-bit boundary.
*/
geo->auxiliary_status_offset = ALIGN(geo->metadata_size, 4);
geo->auxiliary_size = ALIGN(geo->metadata_size, 4)
+ ALIGN(geo->ecc_chunk_count, 4);
if (!this->swap_block_mark) return 0;
/* calculate the number of ecc chunk behind the bbm */
i = (mtd->writesize / geo->eccn_chunk_size) - bbm_chunk + 1;
/* * The size of the metadata can be changed, though we set it to 10 * bytes now. But it can't be too large, because we have to save * enough space for BCH.
*/
geo->metadata_size = 10;
/* The default for the length of Galois Field. */
geo->gf_len = 13;
/* The default for chunk size. */
geo->ecc0_chunk_size = 512;
geo->eccn_chunk_size = 512; while (geo->eccn_chunk_size < mtd->oobsize) {
geo->ecc0_chunk_size *= 2; /* keep C >= O */
geo->eccn_chunk_size *= 2; /* keep C >= O */
geo->gf_len = 14;
}
/* We use the same ECC strength for all chunks. */
geo->ecc_strength = get_ecc_strength(this); if (!gpmi_check_ecc(this)) {
dev_err(this->dev, "ecc strength: %d cannot be supported by the controller (%d)\n" "try to use minimum ecc strength that NAND chip required\n",
geo->ecc_strength,
this->devdata->bch_max_ecc_strength); return -EINVAL;
}
/* * The auxiliary buffer contains the metadata and the ECC status. The * metadata is padded to the nearest 32-bit boundary. The ECC status * contains one byte for every ECC chunk, and is also padded to the * nearest 32-bit boundary.
*/
metadata_size = ALIGN(geo->metadata_size, 4);
status_size = ALIGN(geo->ecc_chunk_count, 4);
/* * We need to compute the byte and bit offsets of * the physical block mark within the ECC-based view of the page. * * NAND chip with 2K page shows below: * (Block Mark) * | | * | D | * |<---->| * V V * +---+----------+-+----------+-+----------+-+----------+-+ * | M | data |E| data |E| data |E| data |E| * +---+----------+-+----------+-+----------+-+----------+-+ * * The position of block mark moves forward in the ECC-based view * of page, and the delta is: * * E * G * (N - 1) * D = (---------------- + M) * 8 * * With the formula to compute the ECC strength, and the condition * : C >= O (C is the ecc chunk size) * * It's easy to deduce to the following result: * * E * G (O - M) C - M C - M * ----------- <= ------- <= -------- < --------- * 8 N N (N - 1) * * So, we get: * * E * G * (N - 1) * D = (---------------- + M) < C * 8 * * The above inequality means the position of block mark * within the ECC-based view of the page is still in the data chunk, * and it's NOT in the ECC bits of the chunk. * * Use the following to compute the bit position of the * physical block mark within the ECC-based view of the page: * (page_size - D) * 8 * * --Huang Shijie
*/
block_mark_bit_offset = mtd->writesize * 8 -
(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+ geo->metadata_size * 8);
/* use legacy bch geometry settings by default*/ if ((!use_minimun_ecc && mtd->oobsize < 1024) ||
!(requirements->strength > 0 && requirements->step_size > 0)) {
dev_dbg(this->dev, "use legacy bch geometry\n");
err = legacy_set_geometry(this); if (!err) return 0;
}
/* for large oob nand */ if (mtd->oobsize > 1024) {
dev_dbg(this->dev, "use large oob bch geometry\n");
err = set_geometry_for_large_oob(this); if (!err) return 0;
}
/* otherwise use the minimum ecc nand chip required */
dev_dbg(this->dev, "use minimum ecc bch geometry\n");
err = set_geometry_by_ecc_info(this, requirements->strength,
requirements->step_size); if (err)
dev_err(this->dev, "none of the bch geometry setting works\n");
return err;
}
/* Configures the geometry for BCH. */ staticint bch_set_geometry(struct gpmi_nand_data *this)
{ struct resources *r = &this->resources; int ret;
ret = common_nfc_set_geometry(this); if (ret) return ret;
ret = pm_runtime_resume_and_get(this->dev); if (ret < 0) { return ret;
}
/* * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. * and MX28.
*/
ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MXS(this)); if (ret) goto err_out;
/* Set *all* chip selects to use layout 0. */
writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
ret = 0;
err_out:
pm_runtime_mark_last_busy(this->dev);
pm_runtime_put_autosuspend(this->dev);
return ret;
}
/* * <1> Firstly, we should know what's the GPMI-clock means. * The GPMI-clock is the internal clock in the gpmi nand controller. * If you set 100MHz to gpmi nand controller, the GPMI-clock's period * is 10ns. Mark the GPMI-clock's period as GPMI-clock-period. * * <2> Secondly, we should know what's the frequency on the nand chip pins. * The frequency on the nand chip pins is derived from the GPMI-clock. * We can get it from the following equation: * * F = G / (DS + DH) * * F : the frequency on the nand chip pins. * G : the GPMI clock, such as 100MHz. * DS : GPMI_HW_GPMI_TIMING0:DATA_SETUP * DH : GPMI_HW_GPMI_TIMING0:DATA_HOLD * * <3> Thirdly, when the frequency on the nand chip pins is above 33MHz, * the nand EDO(extended Data Out) timing could be applied. * The GPMI implements a feedback read strobe to sample the read data. * The feedback read strobe can be delayed to support the nand EDO timing * where the read strobe may deasserts before the read data is valid, and * read data is valid for some time after read strobe. * * The following figure illustrates some aspects of a NAND Flash read: * * |<---tREA---->| * | | * | | | * |<--tRP-->| | * | | | * __ ___|__________________________________ * RDN \________/ | * | * /---------\ * Read Data --------------< >--------- * \---------/ * | | * |<-D->| * FeedbackRDN ________ ____________ * \___________/ * * D stands for delay, set in the HW_GPMI_CTRL1:RDN_DELAY. * * * <4> Now, we begin to describe how to compute the right RDN_DELAY. * * 4.1) From the aspect of the nand chip pins: * Delay = (tREA + C - tRP) {1} * * tREA : the maximum read access time. * C : a constant to adjust the delay. default is 4000ps. * tRP : the read pulse width, which is exactly: * tRP = (GPMI-clock-period) * DATA_SETUP * * 4.2) From the aspect of the GPMI nand controller: * Delay = RDN_DELAY * 0.125 * RP {2} * * RP : the DLL reference period. * if (GPMI-clock-period > DLL_THRETHOLD) * RP = GPMI-clock-period / 2; * else * RP = GPMI-clock-period; * * Set the HW_GPMI_CTRL1:HALF_PERIOD if GPMI-clock-period * is greater DLL_THRETHOLD. In other SOCs, the DLL_THRETHOLD * is 16000ps, but in mx6q, we use 12000ps. * * 4.3) since {1} equals {2}, we get: * * (tREA + 4000 - tRP) * 8 * RDN_DELAY = ----------------------- {3} * RP
*/ staticint gpmi_nfc_compute_timings(struct gpmi_nand_data *this, conststruct nand_sdr_timings *sdr)
{ struct gpmi_nfc_hardware_timing *hw = &this->hw; struct resources *r = &this->resources; unsignedint dll_threshold_ps = this->devdata->max_chain_delay; unsignedint period_ps, reference_period_ps; unsignedint data_setup_cycles, data_hold_cycles, addr_setup_cycles; unsignedint tRP_ps; bool use_half_period; int sample_delay_ps, sample_delay_factor; unsignedint busy_timeout_cycles;
u8 wrn_dly_sel; unsignedlong clk_rate, min_rate;
u64 busy_timeout_ps;
/* Clock dividers do NOT guarantee a clean clock signal on its output * during the change of the divide factor on i.MX6Q/UL/SX. On i.MX7/8, * all clock dividers provide these guarantee.
*/ if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this))
clk_disable_unprepare(r->clock[0]);
ret = clk_set_rate(r->clock[0], hw->clk_rate); if (ret) {
dev_err(this->dev, "cannot set clock rate to %lu Hz: %d\n", hw->clk_rate, ret); return ret;
}
if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6SX(this)) {
ret = clk_prepare_enable(r->clock[0]); if (ret) return ret;
}
/* * Clear several CTRL1 fields, DLL must be disabled when setting * RDN_DELAY or HALF_PERIOD.
*/
writel(BM_GPMI_CTRL1_CLEAR_MASK, gpmi_regs + HW_GPMI_CTRL1_CLR);
writel(hw->ctrl1n, gpmi_regs + HW_GPMI_CTRL1_SET);
/* Wait 64 clock cycles before using the GPMI after enabling the DLL */
dll_wait_time_us = USEC_PER_SEC / hw->clk_rate * 64; if (!dll_wait_time_us)
dll_wait_time_us = 1;
/* Wait for the DLL to settle. */
udelay(dll_wait_time_us);
return 0;
}
staticint gpmi_setup_interface(struct nand_chip *chip, int chipnr, conststruct nand_interface_config *conf)
{ struct gpmi_nand_data *this = nand_get_controller_data(chip); conststruct nand_sdr_timings *sdr; int ret;
staticstruct dma_chan *get_dma_chan(struct gpmi_nand_data *this)
{ /* We use the DMA channel 0 to access all the nand chips. */ return this->dma_chans[0];
}
/* This will be called after the DMA operation is finished. */ staticvoid dma_irq_callback(void *param)
{ struct gpmi_nand_data *this = param; struct completion *dma_c = &this->dma_done;
staticint gpmi_raw_len_to_len(struct gpmi_nand_data *this, int raw_len)
{ /* * raw_len is the length to read/write including bch data which * we are passed in exec_op. Calculate the data length from it.
*/ if (this->bch) return ALIGN_DOWN(raw_len, this->bch_geometry.eccn_chunk_size); else return raw_len;
}
/* Can we use the upper's buffer directly for DMA? */ staticbool prepare_data_dma(struct gpmi_nand_data *this, constvoid *buf, int raw_len, struct scatterlist *sgl, enum dma_data_direction dr)
{ int ret; int len = gpmi_raw_len_to_len(this, raw_len);
/* first try to map the upper buffer directly */ if (virt_addr_valid(buf) && !object_is_on_stack(buf)) {
sg_init_one(sgl, buf, len);
ret = dma_map_sg(this->dev, sgl, 1, dr); if (ret == 0) goto map_fail;
returntrue;
}
map_fail: /* We have to use our own DMA buffer. */
sg_init_one(sgl, this->data_buffer_dma, len);
/* * We may change the layout if we can get the ECC info from the datasheet, * else we will use all the (page + OOB).
*/ staticint gpmi_ooblayout_ecc(struct mtd_info *mtd, int section, struct mtd_oob_region *oobregion)
{ struct nand_chip *chip = mtd_to_nand(mtd); struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *geo = &this->bch_geometry;
/* * [2] Allocate a read/write data buffer. * The gpmi_alloc_dma_buffer can be called twice. * We allocate a PAGE_SIZE length buffer if gpmi_alloc_dma_buffer * is called before the NAND identification; and we allocate a * buffer of the real NAND page size when the gpmi_alloc_dma_buffer * is called after.
*/
this->data_buffer_dma = kzalloc(mtd->writesize ?: PAGE_SIZE,
GFP_DMA | GFP_KERNEL); if (this->data_buffer_dma == NULL) goto error_alloc;
this->auxiliary_virt = dma_alloc_coherent(dev, geo->auxiliary_size,
&this->auxiliary_phys, GFP_DMA); if (!this->auxiliary_virt) goto error_alloc;
/* * Handles block mark swapping. * It can be called in swapping the block mark, or swapping it back, * because the operations are the same.
*/ staticvoid block_mark_swapping(struct gpmi_nand_data *this, void *payload, void *auxiliary)
{ struct bch_geometry *nfc_geo = &this->bch_geometry; unsignedchar *p; unsignedchar *a; unsignedint bit; unsignedchar mask; unsignedchar from_data; unsignedchar from_oob;
if (!this->swap_block_mark) return;
/* * If control arrives here, we're swapping. Make some convenience * variables.
*/
bit = nfc_geo->block_mark_bit_offset;
p = payload + nfc_geo->block_mark_byte_offset;
a = auxiliary;
/* * Get the byte from the data area that overlays the block mark. Since * the ECC engine applies its own view to the bits in the page, the * physical block mark won't (in general) appear on a byte boundary in * the data.
*/
from_data = (p[0] >> bit) | (p[1] << (8 - bit));
staticint gpmi_count_bitflips(struct nand_chip *chip, void *buf, int first, int last, int meta)
{ struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; struct mtd_info *mtd = nand_to_mtd(chip); int i; unsignedchar *status; unsignedint max_bitflips = 0;
/* Loop over status bytes, accumulating ECC status. */
status = this->auxiliary_virt + ALIGN(meta, 4);
for (i = first; i < last; i++, status++) { if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED)) continue;
if (*status == STATUS_UNCORRECTABLE) { int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *eccbuf = this->raw_buffer; int offset, bitoffset; int eccbytes; int flips;
/* * ECC data are not byte aligned and we may have * in-band data in the first and last byte of * eccbuf. Set non-eccbits to one so that * nand_check_erased_ecc_chunk() does not count them * as bitflips.
*/ if (bitoffset)
eccbuf[0] |= GENMASK(bitoffset - 1, 0);
/* * The ECC hardware has an uncorrectable ECC status * code in case we have bitflips in an erased page. As * nothing was written into this subpage the ECC is * obviously wrong and we can not trust it. We assume * at this point that we are reading an erased page and * try to correct the bitflips in buffer up to * ecc_strength bitflips. If this is a page with random * data, we exceed this number of bitflips and have a * ECC failure. Otherwise we use the corrected buffer.
*/ if (i == 0) { /* The first block includes metadata */
flips = nand_check_erased_ecc_chunk(
buf + i * nfc_geo->eccn_chunk_size,
nfc_geo->eccn_chunk_size,
eccbuf, eccbytes,
this->auxiliary_virt,
nfc_geo->metadata_size,
nfc_geo->ecc_strength);
} else {
flips = nand_check_erased_ecc_chunk(
buf + i * nfc_geo->eccn_chunk_size,
nfc_geo->eccn_chunk_size,
eccbuf, eccbytes,
NULL, 0,
nfc_geo->ecc_strength);
}
/* handle the block mark swapping */
block_mark_swapping(this, buf, this->auxiliary_virt);
if (oob_required) { /* * It's time to deliver the OOB bytes. See gpmi_ecc_read_oob() * for details about our policy for delivering the OOB. * * We fill the caller's buffer with set bits, and then copy the * block mark to th caller's buffer. Note that, if block mark * swapping was necessary, it has already been done, so we can * rely on the first byte of the auxiliary buffer to contain * the block mark.
*/
memset(chip->oob_poi, ~0, mtd->oobsize);
chip->oob_poi[0] = ((uint8_t *)this->auxiliary_virt)[0];
}
return max_bitflips;
}
/* Fake a virtual small page for the subpage read */ staticint gpmi_ecc_read_subpage(struct nand_chip *chip, uint32_t offs,
uint32_t len, uint8_t *buf, int page)
{ struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *geo = &this->bch_geometry; int size = chip->ecc.size; /* ECC chunk size */ int meta, n, page_size; unsignedint max_bitflips; unsignedint ecc_strength; int first, last, marker_pos; int ecc_parity_size; int col = 0; int ret;
/* The size of ECC parity */
ecc_parity_size = geo->gf_len * geo->ecc_strength / 8;
/* Align it with the chunk size */
first = offs / size;
last = (offs + len - 1) / size;
if (this->swap_block_mark) { /* * Find the chunk which contains the Block Marker. * If this chunk is in the range of [first, last], * we have to read out the whole page. * Why? since we had swapped the data at the position of Block * Marker to the metadata which is bound with the chunk 0.
*/
marker_pos = geo->block_mark_byte_offset / size; if (last >= marker_pos && first <= marker_pos) {
dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n",
page, first, last, marker_pos); return gpmi_ecc_read_page(chip, buf, 0, page);
}
}
/* * if there is an ECC dedicate for meta: * - need to add an extra ECC size when calculating col and page_size, * if the meta size is NOT zero. * - ecc0_chunk size need to set to the same size as other chunks, * if the meta size is zero.
*/
meta = geo->metadata_size; if (first) { if (geo->ecc_for_meta)
col = meta + ecc_parity_size
+ (size + ecc_parity_size) * first; else
col = meta + (size + ecc_parity_size) * first;
meta = 0;
buf = buf + first * size;
}
ecc_parity_size = geo->gf_len * geo->ecc_strength / 8;
n = last - first + 1;
if (geo->ecc_for_meta && meta)
page_size = meta + ecc_parity_size
+ (size + ecc_parity_size) * n; else
page_size = meta + (size + ecc_parity_size) * n;
if (this->swap_block_mark) { /* * When doing bad block marker swapping we must always copy the * input buffer as we can't modify the const buffer.
*/
memcpy(this->data_buffer_dma, buf, mtd->writesize);
buf = this->data_buffer_dma;
block_mark_swapping(this, this->data_buffer_dma,
this->auxiliary_virt);
}
/* * There are several places in this driver where we have to handle the OOB and * block marks. This is the function where things are the most complicated, so * this is where we try to explain it all. All the other places refer back to * here. * * These are the rules, in order of decreasing importance: * * 1) Nothing the caller does can be allowed to imperil the block mark. * * 2) In read operations, the first byte of the OOB we return must reflect the * true state of the block mark, no matter where that block mark appears in * the physical page. * * 3) ECC-based read operations return an OOB full of set bits (since we never * allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads * return). * * 4) "Raw" read operations return a direct view of the physical bytes in the * page, using the conventional definition of which bytes are data and which * are OOB. This gives the caller a way to see the actual, physical bytes * in the page, without the distortions applied by our ECC engine. * * * What we do for this specific read operation depends on two questions: * * 1) Are we doing a "raw" read, or an ECC-based read? * * 2) Are we using block mark swapping or transcription? * * There are four cases, illustrated by the following Karnaugh map: * * | Raw | ECC-based | * -------------+-------------------------+-------------------------+ * | Read the conventional | | * | OOB at the end of the | | * Swapping | page and return it. It | | * | contains exactly what | | * | we want. | Read the block mark and | * -------------+-------------------------+ return it in a buffer | * | Read the conventional | full of set bits. | * | OOB at the end of the | | * | page and also the block | | * Transcribing | mark in the metadata. | | * | Copy the block mark | | * | into the first byte of | | * | the OOB. | | * -------------+-------------------------+-------------------------+ * * Note that we break rule #4 in the Transcribing/Raw case because we're not * giving an accurate view of the actual, physical bytes in the page (we're * overwriting the block mark). That's OK because it's more important to follow * rule #2. * * It turns out that knowing whether we want an "ECC-based" or "raw" read is not * easy. When reading a page, for example, the NAND Flash MTD code calls our * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an * ECC-based or raw view of the page is implicit in which function it calls * (there is a similar pair of ECC-based/raw functions for writing).
*/ staticint gpmi_ecc_read_oob(struct nand_chip *chip, int page)
{ struct mtd_info *mtd = nand_to_mtd(chip); struct gpmi_nand_data *this = nand_get_controller_data(chip); int ret;
/* clear the OOB buffer */
memset(chip->oob_poi, ~0, mtd->oobsize);
/* Read out the conventional OOB. */
ret = nand_read_page_op(chip, page, mtd->writesize, chip->oob_poi,
mtd->oobsize); if (ret) return ret;
/* * Now, we want to make sure the block mark is correct. In the * non-transcribing case (!GPMI_IS_MX23()), we already have it. * Otherwise, we need to explicitly read it.
*/ if (GPMI_IS_MX23(this)) { /* Read the block mark into the first byte of the OOB buffer. */
ret = nand_read_page_op(chip, page, 0, chip->oob_poi, 1); if (ret) return ret;
}
return 0;
}
staticint gpmi_ecc_write_oob(struct nand_chip *chip, int page)
{ struct mtd_info *mtd = nand_to_mtd(chip); struct mtd_oob_region of = { };
/* Do we have available oob area? */
mtd_ooblayout_free(mtd, 0, &of); if (!of.length) return -EPERM;
/* * This function reads a NAND page without involving the ECC engine (no HW * ECC correction). * The tricky part in the GPMI/BCH controller is that it stores ECC bits * inline (interleaved with payload DATA), and do not align data chunk on * byte boundaries. * We thus need to take care moving the payload data and ECC bits stored in the * page into the provided buffers, which is why we're using nand_extract_bits(). * * See set_geometry_by_ecc_info inline comments to have a full description * of the layout used by the GPMI controller.
*/ staticint gpmi_ecc_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
{ struct mtd_info *mtd = nand_to_mtd(chip); struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; int eccsize = nfc_geo->eccn_chunk_size; int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *tmp_buf = this->raw_buffer;
size_t src_bit_off;
size_t oob_bit_off;
size_t oob_byte_off;
uint8_t *oob = chip->oob_poi; int step; int ret;
ret = nand_read_page_op(chip, page, 0, tmp_buf,
mtd->writesize + mtd->oobsize); if (ret) return ret;
/* * If required, swap the bad block marker and the data stored in the * metadata section, so that we don't wrongly consider a block as bad. * * See the layout description for a detailed explanation on why this * is needed.
*/ if (this->swap_block_mark)
swap(tmp_buf[0], tmp_buf[mtd->writesize]);
/* * Copy the metadata section into the oob buffer (this section is * guaranteed to be aligned on a byte boundary).
*/ if (oob_required)
memcpy(oob, tmp_buf, nfc_geo->metadata_size);
/* * This function writes a NAND page without involving the ECC engine (no HW * ECC generation). * The tricky part in the GPMI/BCH controller is that it stores ECC bits * inline (interleaved with payload DATA), and do not align data chunk on * byte boundaries. * We thus need to take care moving the OOB area at the right place in the * final page, which is why we're using nand_extract_bits(). * * See set_geometry_by_ecc_info inline comments to have a full description * of the layout used by the GPMI controller.
*/ staticint gpmi_ecc_write_page_raw(struct nand_chip *chip, const uint8_t *buf, int oob_required, int page)
{ struct mtd_info *mtd = nand_to_mtd(chip); struct gpmi_nand_data *this = nand_get_controller_data(chip); struct bch_geometry *nfc_geo = &this->bch_geometry; int eccsize = nfc_geo->eccn_chunk_size; int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *tmp_buf = this->raw_buffer;
uint8_t *oob = chip->oob_poi;
size_t dst_bit_off;
size_t oob_bit_off;
size_t oob_byte_off; int step;
/* * Initialize all bits to 1 in case we don't have a buffer for the * payload or oob data in order to leave unspecified bits of data * to their initial state.
*/ if (!buf || !oob_required)
memset(tmp_buf, 0xff, mtd->writesize + mtd->oobsize);
/* * First copy the metadata section (stored in oob buffer) at the * beginning of the page, as imposed by the GPMI layout.
*/
memcpy(tmp_buf, oob, nfc_geo->metadata_size);
oob_bit_off = nfc_geo->metadata_size * 8;
dst_bit_off = oob_bit_off;
/* Interleave payload data and ECC bits */ for (step = 0; step < nfc_geo->ecc_chunk_count; step++) { if (buf)
nand_extract_bits(tmp_buf, dst_bit_off, buf,
step * eccsize * 8, eccsize * 8);
dst_bit_off += eccsize * 8;
/* Align last ECC block to align a byte boundary */ if (step == nfc_geo->ecc_chunk_count - 1 &&
(oob_bit_off + eccbits) % 8)
eccbits += 8 - ((oob_bit_off + eccbits) % 8);
if (oob_required)
nand_extract_bits(tmp_buf, dst_bit_off, oob,
oob_bit_off, eccbits);
/* * If required, swap the bad block marker and the first byte of the * metadata section, so that we don't modify the bad block marker. * * See the layout description for a detailed explanation on why this * is needed.
*/ if (this->swap_block_mark)
swap(tmp_buf[0], tmp_buf[mtd->writesize]);
/* * Set the boot block stride size. * * In principle, we should be reading this from the OTP bits, since * that's where the ROM is going to get it. In fact, we don't have any * way to read the OTP bits, so we go with the default and hope for the * best.
*/
geometry->stride_size_in_pages = 64;
/* * Set the search area stride exponent. * * In principle, we should be reading this from the OTP bits, since * that's where the ROM is going to get it. In fact, we don't have any * way to read the OTP bits, so we go with the default and hope for the * best.
*/
geometry->search_area_stride_exponent = 2; return 0;
}
/* Compute the number of strides in a search area. */
search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
nand_select_target(chip, 0);
/* * Loop through the first search area, looking for the NCB fingerprint.
*/
dev_dbg(dev, "Scanning for an NCB fingerprint...\n");
for (stride = 0; stride < search_area_size_in_strides; stride++) { /* Compute the page addresses. */
page = stride * rom_geo->stride_size_in_pages;
dev_dbg(dev, "Looking for a fingerprint in page 0x%x\n", page);
/* * Read the NCB fingerprint. The fingerprint is four bytes long * and starts in the 12th byte of the page.
*/
ret = nand_read_page_op(chip, page, 12, buffer,
strlen(fingerprint)); if (ret) continue;
/* Look for the fingerprint. */ if (!memcmp(buffer, fingerprint, strlen(fingerprint))) {
found_an_ncb_fingerprint = true; break;
}
}
nand_deselect_target(chip);
if (found_an_ncb_fingerprint)
dev_dbg(dev, "\tFound a fingerprint\n"); else
dev_dbg(dev, "\tNo fingerprint found\n"); return found_an_ncb_fingerprint;
}
/* Loop over blocks in the first search area, erasing them. */
dev_dbg(dev, "Erasing the search area...\n");
for (block = 0; block < search_area_size_in_blocks; block++) { /* Erase this block. */
dev_dbg(dev, "\tErasing block 0x%x\n", block);
status = nand_erase_op(chip, block); if (status)
dev_err(dev, "[%s] Erase failed.\n", __func__);
}
/* Write the NCB fingerprint into the page buffer. */
memset(buffer, ~0, mtd->writesize);
memcpy(buffer + 12, fingerprint, strlen(fingerprint));
/* Loop through the first search area, writing NCB fingerprints. */
dev_dbg(dev, "Writing NCB fingerprints...\n"); for (stride = 0; stride < search_area_size_in_strides; stride++) { /* Compute the page addresses. */
page = stride * rom_geo->stride_size_in_pages;
/* Write the first page of the current stride. */
dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
status = chip->ecc.write_page_raw(chip, buffer, 0, page); if (status)
dev_err(dev, "[%s] Write failed.\n", __func__);
}
nand_deselect_target(chip);
return 0;
}
staticint mx23_boot_init(struct gpmi_nand_data *this)
{ struct device *dev = this->dev; struct nand_chip *chip = &this->nand; struct mtd_info *mtd = nand_to_mtd(chip); unsignedint block_count; unsignedint block; int chipnr; int page;
loff_t byte;
uint8_t block_mark; int ret = 0;
/* * If control arrives here, we can't use block mark swapping, which * means we're forced to use transcription. First, scan for the * transcription stamp. If we find it, then we don't have to do * anything -- the block marks are already transcribed.
*/ if (mx23_check_transcription_stamp(this)) return 0;
/* * If control arrives here, we couldn't find a transcription stamp, so * so we presume the block marks are in the conventional location.
*/
dev_dbg(dev, "Transcribing bad block marks...\n");
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.28 Sekunden
(vorverarbeitet)
¤
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.