#define BM_BCH_CTRL_COMPLETE_IRQ (1 << 0)
#define HW_BCH_STATUS0 0x00000010
+
#define HW_BCH_MODE 0x00000020
+#define BP_BCH_MODE_ERASE_THRESHOLD 0
+#define BM_BCH_MODE_ERASE_THRESHOLD (0xff << BP_BCH_MODE_ERASE_THRESHOLD)
+#define BF_BCH_MODE_ERASE_THRESHOLD(v) \
+ (((v) << BP_BCH_MODE_ERASE_THRESHOLD) & BM_BCH_MODE_ERASE_THRESHOLD)
+
#define HW_BCH_ENCODEPTR 0x00000030
#define HW_BCH_DATAPTR 0x00000040
#define HW_BCH_METAPTR 0x00000050
)
#define HW_BCH_VERSION 0x00000160
+#define HW_BCH_DEBUG1 0x00000170
+#define BP_BCH_DEBUG1_ERASED_ZERO_COUNT 0
+#define BM_BCH_DEBUG1_ERASED_ZERO_COUNT \
+ (0x1ff << BP_BCH_DEBUG1_ERASED_ZERO_COUNT)
#endif
| BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size, this),
r->bch_regs + HW_BCH_FLASH0LAYOUT1);
+ /* Set erase threshold to gf/2 for mx6qp and mx7 */
+ if (GPMI_IS_MX6QP(this) || GPMI_IS_MX7(this))
+ writel(BF_BCH_MODE_ERASE_THRESHOLD(gf_len/2),
+ r->bch_regs + HW_BCH_MODE);
+
/* Set *all* chip selects to use layout 0. */
writel(0, r->bch_regs + HW_BCH_LAYOUTSELECT);
.max_chain_delay = 12,
};
+static const struct gpmi_devdata gpmi_devdata_imx6qp = {
+ .type = IS_MX6QP,
+ .bch_max_ecc_strength = 40,
+ .max_chain_delay = 12,
+};
+
static const struct gpmi_devdata gpmi_devdata_imx6sx = {
.type = IS_MX6SX,
.bch_max_ecc_strength = 62,
{
struct gpmi_nand_data *this = nand_get_controller_data(chip);
struct bch_geometry *nfc_geo = &this->bch_geometry;
+ void __iomem *bch_regs = this->resources.bch_regs;
void *payload_virt;
dma_addr_t payload_phys;
void *auxiliary_virt;
unsigned char *status;
unsigned int max_bitflips = 0;
int ret;
+ int flag = 0;
dev_dbg(this->dev, "page number is : %d\n", page);
ret = read_page_prepare(this, buf, nfc_geo->payload_size,
payload_virt, payload_phys);
for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) {
- if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED))
+ if (*status == STATUS_GOOD)
continue;
+ if (*status == STATUS_ERASED) {
+ if (GPMI_IS_MX6QP(this) || GPMI_IS_MX7(this))
+ if (readl(bch_regs + HW_BCH_DEBUG1))
+ flag = 1;
+ continue;
+ }
+
if (*status == STATUS_UNCORRECTABLE) {
int eccbits = nfc_geo->ecc_strength * nfc_geo->gf_len;
u8 *eccbuf = this->raw_buffer;
chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
}
+ /* if bitflip occurred in erased page, change data to all 0xff */
+ if (flag)
+ memset(buf, 0xff, nfc_geo->payload_size);
+
return max_bitflips;
}
}, {
.compatible = "fsl,imx6q-gpmi-nand",
.data = &gpmi_devdata_imx6q,
+ }, {
+ .compatible = "fsl,imx6qp-gpmi-nand",
+ .data = (void *)&gpmi_devdata_imx6qp,
}, {
.compatible = "fsl,imx6sx-gpmi-nand",
.data = &gpmi_devdata_imx6sx,
IS_MX23,
IS_MX28,
IS_MX6Q,
+ IS_MX6QP,
IS_MX6SX,
IS_MX7D
};
#define GPMI_IS_MX23(x) ((x)->devdata->type == IS_MX23)
#define GPMI_IS_MX28(x) ((x)->devdata->type == IS_MX28)
#define GPMI_IS_MX6Q(x) ((x)->devdata->type == IS_MX6Q)
+#define GPMI_IS_MX6QP(x) ((x)->devdata->type == IS_MX6QP)
#define GPMI_IS_MX6SX(x) ((x)->devdata->type == IS_MX6SX)
#define GPMI_IS_MX7D(x) ((x)->devdata->type == IS_MX7D)
-#define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6SX(x))
+#define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6QP(x)\
+ || GPMI_IS_MX6SX(x))
#define GPMI_IS_MX7(x) (GPMI_IS_MX7D(x))
#endif