11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 293db446aSBoris Brezillon /* Freescale Enhanced Local Bus Controller NAND driver 393db446aSBoris Brezillon * 493db446aSBoris Brezillon * Copyright © 2006-2007, 2010 Freescale Semiconductor 593db446aSBoris Brezillon * 693db446aSBoris Brezillon * Authors: Nick Spence <nick.spence@freescale.com>, 793db446aSBoris Brezillon * Scott Wood <scottwood@freescale.com> 893db446aSBoris Brezillon * Jack Lan <jack.lan@freescale.com> 993db446aSBoris Brezillon * Roy Zang <tie-fei.zang@freescale.com> 1093db446aSBoris Brezillon */ 1193db446aSBoris Brezillon 1293db446aSBoris Brezillon #include <linux/module.h> 1393db446aSBoris Brezillon #include <linux/types.h> 1493db446aSBoris Brezillon #include <linux/kernel.h> 1593db446aSBoris Brezillon #include <linux/string.h> 1693db446aSBoris Brezillon #include <linux/ioport.h> 1793db446aSBoris Brezillon #include <linux/of_address.h> 1893db446aSBoris Brezillon #include <linux/of_platform.h> 1993db446aSBoris Brezillon #include <linux/platform_device.h> 2093db446aSBoris Brezillon #include <linux/slab.h> 2193db446aSBoris Brezillon #include <linux/interrupt.h> 2293db446aSBoris Brezillon 2393db446aSBoris Brezillon #include <linux/mtd/mtd.h> 2493db446aSBoris Brezillon #include <linux/mtd/rawnand.h> 2593db446aSBoris Brezillon #include <linux/mtd/partitions.h> 2693db446aSBoris Brezillon 2793db446aSBoris Brezillon #include <asm/io.h> 2893db446aSBoris Brezillon #include <asm/fsl_lbc.h> 2993db446aSBoris Brezillon 3093db446aSBoris Brezillon #define MAX_BANKS 8 3193db446aSBoris Brezillon #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ 3293db446aSBoris Brezillon #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ 3393db446aSBoris Brezillon 3493db446aSBoris Brezillon /* mtd information per set */ 3593db446aSBoris Brezillon 3693db446aSBoris Brezillon struct fsl_elbc_mtd { 3793db446aSBoris Brezillon struct nand_chip chip; 3893db446aSBoris Brezillon struct fsl_lbc_ctrl *ctrl; 3993db446aSBoris Brezillon 4093db446aSBoris Brezillon struct device *dev; 4193db446aSBoris Brezillon int bank; /* Chip select bank number */ 4293db446aSBoris Brezillon u8 __iomem *vbase; /* Chip select base virtual address */ 4393db446aSBoris Brezillon int page_size; /* NAND page size (0=512, 1=2048) */ 4493db446aSBoris Brezillon unsigned int fmr; /* FCM Flash Mode Register value */ 4593db446aSBoris Brezillon }; 4693db446aSBoris Brezillon 4793db446aSBoris Brezillon /* Freescale eLBC FCM controller information */ 4893db446aSBoris Brezillon 4993db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl { 507da45139SMiquel Raynal struct nand_controller controller; 5193db446aSBoris Brezillon struct fsl_elbc_mtd *chips[MAX_BANKS]; 5293db446aSBoris Brezillon 5393db446aSBoris Brezillon u8 __iomem *addr; /* Address of assigned FCM buffer */ 5493db446aSBoris Brezillon unsigned int page; /* Last page written to / read from */ 5593db446aSBoris Brezillon unsigned int read_bytes; /* Number of bytes read during command */ 5693db446aSBoris Brezillon unsigned int column; /* Saved column from SEQIN */ 5793db446aSBoris Brezillon unsigned int index; /* Pointer to next byte to 'read' */ 5893db446aSBoris Brezillon unsigned int status; /* status read from LTESR after last op */ 5993db446aSBoris Brezillon unsigned int mdr; /* UPM/FCM Data Register value */ 6093db446aSBoris Brezillon unsigned int use_mdr; /* Non zero if the MDR is to be set */ 6193db446aSBoris Brezillon unsigned int oob; /* Non zero if operating on OOB data */ 6293db446aSBoris Brezillon unsigned int counter; /* counter for the initializations */ 6393db446aSBoris Brezillon unsigned int max_bitflips; /* Saved during READ0 cmd */ 6493db446aSBoris Brezillon }; 6593db446aSBoris Brezillon 6693db446aSBoris Brezillon /* These map to the positions used by the FCM hardware ECC generator */ 6793db446aSBoris Brezillon 6893db446aSBoris Brezillon static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section, 6993db446aSBoris Brezillon struct mtd_oob_region *oobregion) 7093db446aSBoris Brezillon { 7193db446aSBoris Brezillon struct nand_chip *chip = mtd_to_nand(mtd); 7293db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 7393db446aSBoris Brezillon 7493db446aSBoris Brezillon if (section >= chip->ecc.steps) 7593db446aSBoris Brezillon return -ERANGE; 7693db446aSBoris Brezillon 7793db446aSBoris Brezillon oobregion->offset = (16 * section) + 6; 7893db446aSBoris Brezillon if (priv->fmr & FMR_ECCM) 7993db446aSBoris Brezillon oobregion->offset += 2; 8093db446aSBoris Brezillon 8193db446aSBoris Brezillon oobregion->length = chip->ecc.bytes; 8293db446aSBoris Brezillon 8393db446aSBoris Brezillon return 0; 8493db446aSBoris Brezillon } 8593db446aSBoris Brezillon 8693db446aSBoris Brezillon static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section, 8793db446aSBoris Brezillon struct mtd_oob_region *oobregion) 8893db446aSBoris Brezillon { 8993db446aSBoris Brezillon struct nand_chip *chip = mtd_to_nand(mtd); 9093db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 9193db446aSBoris Brezillon 9293db446aSBoris Brezillon if (section > chip->ecc.steps) 9393db446aSBoris Brezillon return -ERANGE; 9493db446aSBoris Brezillon 9593db446aSBoris Brezillon if (!section) { 9693db446aSBoris Brezillon oobregion->offset = 0; 9793db446aSBoris Brezillon if (mtd->writesize > 512) 9893db446aSBoris Brezillon oobregion->offset++; 9993db446aSBoris Brezillon oobregion->length = (priv->fmr & FMR_ECCM) ? 7 : 5; 10093db446aSBoris Brezillon } else { 10193db446aSBoris Brezillon oobregion->offset = (16 * section) - 10293db446aSBoris Brezillon ((priv->fmr & FMR_ECCM) ? 5 : 7); 10393db446aSBoris Brezillon if (section < chip->ecc.steps) 10493db446aSBoris Brezillon oobregion->length = 13; 10593db446aSBoris Brezillon else 10693db446aSBoris Brezillon oobregion->length = mtd->oobsize - oobregion->offset; 10793db446aSBoris Brezillon } 10893db446aSBoris Brezillon 10993db446aSBoris Brezillon return 0; 11093db446aSBoris Brezillon } 11193db446aSBoris Brezillon 11293db446aSBoris Brezillon static const struct mtd_ooblayout_ops fsl_elbc_ooblayout_ops = { 11393db446aSBoris Brezillon .ecc = fsl_elbc_ooblayout_ecc, 11493db446aSBoris Brezillon .free = fsl_elbc_ooblayout_free, 11593db446aSBoris Brezillon }; 11693db446aSBoris Brezillon 11793db446aSBoris Brezillon /* 11893db446aSBoris Brezillon * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt, 11993db446aSBoris Brezillon * interfere with ECC positions, that's why we implement our own descriptors. 12093db446aSBoris Brezillon * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0. 12193db446aSBoris Brezillon */ 12293db446aSBoris Brezillon static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; 12393db446aSBoris Brezillon static u8 mirror_pattern[] = {'1', 't', 'b', 'B' }; 12493db446aSBoris Brezillon 12593db446aSBoris Brezillon static struct nand_bbt_descr bbt_main_descr = { 12693db446aSBoris Brezillon .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | 12793db446aSBoris Brezillon NAND_BBT_2BIT | NAND_BBT_VERSION, 12893db446aSBoris Brezillon .offs = 11, 12993db446aSBoris Brezillon .len = 4, 13093db446aSBoris Brezillon .veroffs = 15, 13193db446aSBoris Brezillon .maxblocks = 4, 13293db446aSBoris Brezillon .pattern = bbt_pattern, 13393db446aSBoris Brezillon }; 13493db446aSBoris Brezillon 13593db446aSBoris Brezillon static struct nand_bbt_descr bbt_mirror_descr = { 13693db446aSBoris Brezillon .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | 13793db446aSBoris Brezillon NAND_BBT_2BIT | NAND_BBT_VERSION, 13893db446aSBoris Brezillon .offs = 11, 13993db446aSBoris Brezillon .len = 4, 14093db446aSBoris Brezillon .veroffs = 15, 14193db446aSBoris Brezillon .maxblocks = 4, 14293db446aSBoris Brezillon .pattern = mirror_pattern, 14393db446aSBoris Brezillon }; 14493db446aSBoris Brezillon 14593db446aSBoris Brezillon /*=================================*/ 14693db446aSBoris Brezillon 14793db446aSBoris Brezillon /* 14893db446aSBoris Brezillon * Set up the FCM hardware block and page address fields, and the fcm 14993db446aSBoris Brezillon * structure addr field to point to the correct FCM buffer in memory 15093db446aSBoris Brezillon */ 15193db446aSBoris Brezillon static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) 15293db446aSBoris Brezillon { 15393db446aSBoris Brezillon struct nand_chip *chip = mtd_to_nand(mtd); 15493db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 15593db446aSBoris Brezillon struct fsl_lbc_ctrl *ctrl = priv->ctrl; 15693db446aSBoris Brezillon struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 15793db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; 15893db446aSBoris Brezillon int buf_num; 15993db446aSBoris Brezillon 16093db446aSBoris Brezillon elbc_fcm_ctrl->page = page_addr; 16193db446aSBoris Brezillon 16293db446aSBoris Brezillon if (priv->page_size) { 16393db446aSBoris Brezillon /* 16493db446aSBoris Brezillon * large page size chip : FPAR[PI] save the lowest 6 bits, 16593db446aSBoris Brezillon * FBAR[BLK] save the other bits. 16693db446aSBoris Brezillon */ 16793db446aSBoris Brezillon out_be32(&lbc->fbar, page_addr >> 6); 16893db446aSBoris Brezillon out_be32(&lbc->fpar, 16993db446aSBoris Brezillon ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | 17093db446aSBoris Brezillon (oob ? FPAR_LP_MS : 0) | column); 17193db446aSBoris Brezillon buf_num = (page_addr & 1) << 2; 17293db446aSBoris Brezillon } else { 17393db446aSBoris Brezillon /* 17493db446aSBoris Brezillon * small page size chip : FPAR[PI] save the lowest 5 bits, 17593db446aSBoris Brezillon * FBAR[BLK] save the other bits. 17693db446aSBoris Brezillon */ 17793db446aSBoris Brezillon out_be32(&lbc->fbar, page_addr >> 5); 17893db446aSBoris Brezillon out_be32(&lbc->fpar, 17993db446aSBoris Brezillon ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) | 18093db446aSBoris Brezillon (oob ? FPAR_SP_MS : 0) | column); 18193db446aSBoris Brezillon buf_num = page_addr & 7; 18293db446aSBoris Brezillon } 18393db446aSBoris Brezillon 18493db446aSBoris Brezillon elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024; 18593db446aSBoris Brezillon elbc_fcm_ctrl->index = column; 18693db446aSBoris Brezillon 18793db446aSBoris Brezillon /* for OOB data point to the second half of the buffer */ 18893db446aSBoris Brezillon if (oob) 18993db446aSBoris Brezillon elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512; 19093db446aSBoris Brezillon 19193db446aSBoris Brezillon dev_vdbg(priv->dev, "set_addr: bank=%d, " 19293db446aSBoris Brezillon "elbc_fcm_ctrl->addr=0x%p (0x%p), " 19393db446aSBoris Brezillon "index %x, pes %d ps %d\n", 19493db446aSBoris Brezillon buf_num, elbc_fcm_ctrl->addr, priv->vbase, 19593db446aSBoris Brezillon elbc_fcm_ctrl->index, 19693db446aSBoris Brezillon chip->phys_erase_shift, chip->page_shift); 19793db446aSBoris Brezillon } 19893db446aSBoris Brezillon 19993db446aSBoris Brezillon /* 20093db446aSBoris Brezillon * execute FCM command and wait for it to complete 20193db446aSBoris Brezillon */ 20293db446aSBoris Brezillon static int fsl_elbc_run_command(struct mtd_info *mtd) 20393db446aSBoris Brezillon { 20493db446aSBoris Brezillon struct nand_chip *chip = mtd_to_nand(mtd); 20593db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 20693db446aSBoris Brezillon struct fsl_lbc_ctrl *ctrl = priv->ctrl; 20793db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; 20893db446aSBoris Brezillon struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 20993db446aSBoris Brezillon 21093db446aSBoris Brezillon /* Setup the FMR[OP] to execute without write protection */ 21193db446aSBoris Brezillon out_be32(&lbc->fmr, priv->fmr | 3); 21293db446aSBoris Brezillon if (elbc_fcm_ctrl->use_mdr) 21393db446aSBoris Brezillon out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr); 21493db446aSBoris Brezillon 21593db446aSBoris Brezillon dev_vdbg(priv->dev, 21693db446aSBoris Brezillon "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", 21793db446aSBoris Brezillon in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); 21893db446aSBoris Brezillon dev_vdbg(priv->dev, 21993db446aSBoris Brezillon "fsl_elbc_run_command: fbar=%08x fpar=%08x " 22093db446aSBoris Brezillon "fbcr=%08x bank=%d\n", 22193db446aSBoris Brezillon in_be32(&lbc->fbar), in_be32(&lbc->fpar), 22293db446aSBoris Brezillon in_be32(&lbc->fbcr), priv->bank); 22393db446aSBoris Brezillon 22493db446aSBoris Brezillon ctrl->irq_status = 0; 22593db446aSBoris Brezillon /* execute special operation */ 22693db446aSBoris Brezillon out_be32(&lbc->lsor, priv->bank); 22793db446aSBoris Brezillon 22893db446aSBoris Brezillon /* wait for FCM complete flag or timeout */ 22993db446aSBoris Brezillon wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, 23093db446aSBoris Brezillon FCM_TIMEOUT_MSECS * HZ/1000); 23193db446aSBoris Brezillon elbc_fcm_ctrl->status = ctrl->irq_status; 23293db446aSBoris Brezillon /* store mdr value in case it was needed */ 23393db446aSBoris Brezillon if (elbc_fcm_ctrl->use_mdr) 23493db446aSBoris Brezillon elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr); 23593db446aSBoris Brezillon 23693db446aSBoris Brezillon elbc_fcm_ctrl->use_mdr = 0; 23793db446aSBoris Brezillon 23893db446aSBoris Brezillon if (elbc_fcm_ctrl->status != LTESR_CC) { 23993db446aSBoris Brezillon dev_info(priv->dev, 24093db446aSBoris Brezillon "command failed: fir %x fcr %x status %x mdr %x\n", 24193db446aSBoris Brezillon in_be32(&lbc->fir), in_be32(&lbc->fcr), 24293db446aSBoris Brezillon elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr); 24393db446aSBoris Brezillon return -EIO; 24493db446aSBoris Brezillon } 24593db446aSBoris Brezillon 246bace41f8SMiquel Raynal if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST) 24793db446aSBoris Brezillon return 0; 24893db446aSBoris Brezillon 24993db446aSBoris Brezillon elbc_fcm_ctrl->max_bitflips = 0; 25093db446aSBoris Brezillon 25193db446aSBoris Brezillon if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) { 25293db446aSBoris Brezillon uint32_t lteccr = in_be32(&lbc->lteccr); 25393db446aSBoris Brezillon /* 25493db446aSBoris Brezillon * if command was a full page read and the ELBC 25593db446aSBoris Brezillon * has the LTECCR register, then bits 12-15 (ppc order) of 25693db446aSBoris Brezillon * LTECCR indicates which 512 byte sub-pages had fixed errors. 25793db446aSBoris Brezillon * bits 28-31 are uncorrectable errors, marked elsewhere. 25893db446aSBoris Brezillon * for small page nand only 1 bit is used. 25993db446aSBoris Brezillon * if the ELBC doesn't have the lteccr register it reads 0 26093db446aSBoris Brezillon * FIXME: 4 bits can be corrected on NANDs with 2k pages, so 26193db446aSBoris Brezillon * count the number of sub-pages with bitflips and update 26293db446aSBoris Brezillon * ecc_stats.corrected accordingly. 26393db446aSBoris Brezillon */ 26493db446aSBoris Brezillon if (lteccr & 0x000F000F) 26593db446aSBoris Brezillon out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */ 26693db446aSBoris Brezillon if (lteccr & 0x000F0000) { 26793db446aSBoris Brezillon mtd->ecc_stats.corrected++; 26893db446aSBoris Brezillon elbc_fcm_ctrl->max_bitflips = 1; 26993db446aSBoris Brezillon } 27093db446aSBoris Brezillon } 27193db446aSBoris Brezillon 27293db446aSBoris Brezillon return 0; 27393db446aSBoris Brezillon } 27493db446aSBoris Brezillon 27593db446aSBoris Brezillon static void fsl_elbc_do_read(struct nand_chip *chip, int oob) 27693db446aSBoris Brezillon { 27793db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 27893db446aSBoris Brezillon struct fsl_lbc_ctrl *ctrl = priv->ctrl; 27993db446aSBoris Brezillon struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 28093db446aSBoris Brezillon 28193db446aSBoris Brezillon if (priv->page_size) { 28293db446aSBoris Brezillon out_be32(&lbc->fir, 28393db446aSBoris Brezillon (FIR_OP_CM0 << FIR_OP0_SHIFT) | 28493db446aSBoris Brezillon (FIR_OP_CA << FIR_OP1_SHIFT) | 28593db446aSBoris Brezillon (FIR_OP_PA << FIR_OP2_SHIFT) | 28693db446aSBoris Brezillon (FIR_OP_CM1 << FIR_OP3_SHIFT) | 28793db446aSBoris Brezillon (FIR_OP_RBW << FIR_OP4_SHIFT)); 28893db446aSBoris Brezillon 28993db446aSBoris Brezillon out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | 29093db446aSBoris Brezillon (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); 29193db446aSBoris Brezillon } else { 29293db446aSBoris Brezillon out_be32(&lbc->fir, 29393db446aSBoris Brezillon (FIR_OP_CM0 << FIR_OP0_SHIFT) | 29493db446aSBoris Brezillon (FIR_OP_CA << FIR_OP1_SHIFT) | 29593db446aSBoris Brezillon (FIR_OP_PA << FIR_OP2_SHIFT) | 29693db446aSBoris Brezillon (FIR_OP_RBW << FIR_OP3_SHIFT)); 29793db446aSBoris Brezillon 29893db446aSBoris Brezillon if (oob) 29993db446aSBoris Brezillon out_be32(&lbc->fcr, NAND_CMD_READOOB << FCR_CMD0_SHIFT); 30093db446aSBoris Brezillon else 30193db446aSBoris Brezillon out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT); 30293db446aSBoris Brezillon } 30393db446aSBoris Brezillon } 30493db446aSBoris Brezillon 30593db446aSBoris Brezillon /* cmdfunc send commands to the FCM */ 3065295cf2eSBoris Brezillon static void fsl_elbc_cmdfunc(struct nand_chip *chip, unsigned int command, 30793db446aSBoris Brezillon int column, int page_addr) 30893db446aSBoris Brezillon { 3095295cf2eSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(chip); 31093db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 31193db446aSBoris Brezillon struct fsl_lbc_ctrl *ctrl = priv->ctrl; 31293db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; 31393db446aSBoris Brezillon struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 31493db446aSBoris Brezillon 31593db446aSBoris Brezillon elbc_fcm_ctrl->use_mdr = 0; 31693db446aSBoris Brezillon 31793db446aSBoris Brezillon /* clear the read buffer */ 31893db446aSBoris Brezillon elbc_fcm_ctrl->read_bytes = 0; 31993db446aSBoris Brezillon if (command != NAND_CMD_PAGEPROG) 32093db446aSBoris Brezillon elbc_fcm_ctrl->index = 0; 32193db446aSBoris Brezillon 32293db446aSBoris Brezillon switch (command) { 32393db446aSBoris Brezillon /* READ0 and READ1 read the entire buffer to use hardware ECC. */ 32493db446aSBoris Brezillon case NAND_CMD_READ1: 32593db446aSBoris Brezillon column += 256; 326025a06c1SMiquel Raynal fallthrough; 32793db446aSBoris Brezillon case NAND_CMD_READ0: 32893db446aSBoris Brezillon dev_dbg(priv->dev, 32993db446aSBoris Brezillon "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" 33093db446aSBoris Brezillon " 0x%x, column: 0x%x.\n", page_addr, column); 33193db446aSBoris Brezillon 33293db446aSBoris Brezillon 33393db446aSBoris Brezillon out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ 33493db446aSBoris Brezillon set_addr(mtd, 0, page_addr, 0); 33593db446aSBoris Brezillon 33693db446aSBoris Brezillon elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; 33793db446aSBoris Brezillon elbc_fcm_ctrl->index += column; 33893db446aSBoris Brezillon 33993db446aSBoris Brezillon fsl_elbc_do_read(chip, 0); 34093db446aSBoris Brezillon fsl_elbc_run_command(mtd); 34193db446aSBoris Brezillon return; 34293db446aSBoris Brezillon 343070fb974SMarek Behún /* RNDOUT moves the pointer inside the page */ 344070fb974SMarek Behún case NAND_CMD_RNDOUT: 345070fb974SMarek Behún dev_dbg(priv->dev, 346070fb974SMarek Behún "fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n", 347070fb974SMarek Behún column); 348070fb974SMarek Behún 349070fb974SMarek Behún elbc_fcm_ctrl->index = column; 350070fb974SMarek Behún return; 351070fb974SMarek Behún 35293db446aSBoris Brezillon /* READOOB reads only the OOB because no ECC is performed. */ 35393db446aSBoris Brezillon case NAND_CMD_READOOB: 35493db446aSBoris Brezillon dev_vdbg(priv->dev, 35593db446aSBoris Brezillon "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" 35693db446aSBoris Brezillon " 0x%x, column: 0x%x.\n", page_addr, column); 35793db446aSBoris Brezillon 35893db446aSBoris Brezillon out_be32(&lbc->fbcr, mtd->oobsize - column); 35993db446aSBoris Brezillon set_addr(mtd, column, page_addr, 1); 36093db446aSBoris Brezillon 36193db446aSBoris Brezillon elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; 36293db446aSBoris Brezillon 36393db446aSBoris Brezillon fsl_elbc_do_read(chip, 1); 36493db446aSBoris Brezillon fsl_elbc_run_command(mtd); 36593db446aSBoris Brezillon return; 36693db446aSBoris Brezillon 36793db446aSBoris Brezillon case NAND_CMD_READID: 36893db446aSBoris Brezillon case NAND_CMD_PARAM: 36993db446aSBoris Brezillon dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command); 37093db446aSBoris Brezillon 37193db446aSBoris Brezillon out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | 37293db446aSBoris Brezillon (FIR_OP_UA << FIR_OP1_SHIFT) | 37393db446aSBoris Brezillon (FIR_OP_RBW << FIR_OP2_SHIFT)); 37493db446aSBoris Brezillon out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT); 37593db446aSBoris Brezillon /* 37693db446aSBoris Brezillon * although currently it's 8 bytes for READID, we always read 37793db446aSBoris Brezillon * the maximum 256 bytes(for PARAM) 37893db446aSBoris Brezillon */ 37993db446aSBoris Brezillon out_be32(&lbc->fbcr, 256); 38093db446aSBoris Brezillon elbc_fcm_ctrl->read_bytes = 256; 38193db446aSBoris Brezillon elbc_fcm_ctrl->use_mdr = 1; 38293db446aSBoris Brezillon elbc_fcm_ctrl->mdr = column; 38393db446aSBoris Brezillon set_addr(mtd, 0, 0, 0); 38493db446aSBoris Brezillon fsl_elbc_run_command(mtd); 38593db446aSBoris Brezillon return; 38693db446aSBoris Brezillon 38793db446aSBoris Brezillon /* ERASE1 stores the block and page address */ 38893db446aSBoris Brezillon case NAND_CMD_ERASE1: 38993db446aSBoris Brezillon dev_vdbg(priv->dev, 39093db446aSBoris Brezillon "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " 39193db446aSBoris Brezillon "page_addr: 0x%x.\n", page_addr); 39293db446aSBoris Brezillon set_addr(mtd, 0, page_addr, 0); 39393db446aSBoris Brezillon return; 39493db446aSBoris Brezillon 39593db446aSBoris Brezillon /* ERASE2 uses the block and page address from ERASE1 */ 39693db446aSBoris Brezillon case NAND_CMD_ERASE2: 39793db446aSBoris Brezillon dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); 39893db446aSBoris Brezillon 39993db446aSBoris Brezillon out_be32(&lbc->fir, 40093db446aSBoris Brezillon (FIR_OP_CM0 << FIR_OP0_SHIFT) | 40193db446aSBoris Brezillon (FIR_OP_PA << FIR_OP1_SHIFT) | 40293db446aSBoris Brezillon (FIR_OP_CM2 << FIR_OP2_SHIFT) | 40393db446aSBoris Brezillon (FIR_OP_CW1 << FIR_OP3_SHIFT) | 40493db446aSBoris Brezillon (FIR_OP_RS << FIR_OP4_SHIFT)); 40593db446aSBoris Brezillon 40693db446aSBoris Brezillon out_be32(&lbc->fcr, 40793db446aSBoris Brezillon (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) | 40893db446aSBoris Brezillon (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | 40993db446aSBoris Brezillon (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); 41093db446aSBoris Brezillon 41193db446aSBoris Brezillon out_be32(&lbc->fbcr, 0); 41293db446aSBoris Brezillon elbc_fcm_ctrl->read_bytes = 0; 41393db446aSBoris Brezillon elbc_fcm_ctrl->use_mdr = 1; 41493db446aSBoris Brezillon 41593db446aSBoris Brezillon fsl_elbc_run_command(mtd); 41693db446aSBoris Brezillon return; 41793db446aSBoris Brezillon 41893db446aSBoris Brezillon /* SEQIN sets up the addr buffer and all registers except the length */ 41993db446aSBoris Brezillon case NAND_CMD_SEQIN: { 42093db446aSBoris Brezillon __be32 fcr; 42193db446aSBoris Brezillon dev_vdbg(priv->dev, 42293db446aSBoris Brezillon "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " 42393db446aSBoris Brezillon "page_addr: 0x%x, column: 0x%x.\n", 42493db446aSBoris Brezillon page_addr, column); 42593db446aSBoris Brezillon 42693db446aSBoris Brezillon elbc_fcm_ctrl->column = column; 42793db446aSBoris Brezillon elbc_fcm_ctrl->use_mdr = 1; 42893db446aSBoris Brezillon 42993db446aSBoris Brezillon if (column >= mtd->writesize) { 43093db446aSBoris Brezillon /* OOB area */ 43193db446aSBoris Brezillon column -= mtd->writesize; 43293db446aSBoris Brezillon elbc_fcm_ctrl->oob = 1; 43393db446aSBoris Brezillon } else { 43493db446aSBoris Brezillon WARN_ON(column != 0); 43593db446aSBoris Brezillon elbc_fcm_ctrl->oob = 0; 43693db446aSBoris Brezillon } 43793db446aSBoris Brezillon 43893db446aSBoris Brezillon fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | 43993db446aSBoris Brezillon (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | 44093db446aSBoris Brezillon (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT); 44193db446aSBoris Brezillon 44293db446aSBoris Brezillon if (priv->page_size) { 44393db446aSBoris Brezillon out_be32(&lbc->fir, 44493db446aSBoris Brezillon (FIR_OP_CM2 << FIR_OP0_SHIFT) | 44593db446aSBoris Brezillon (FIR_OP_CA << FIR_OP1_SHIFT) | 44693db446aSBoris Brezillon (FIR_OP_PA << FIR_OP2_SHIFT) | 44793db446aSBoris Brezillon (FIR_OP_WB << FIR_OP3_SHIFT) | 44893db446aSBoris Brezillon (FIR_OP_CM3 << FIR_OP4_SHIFT) | 44993db446aSBoris Brezillon (FIR_OP_CW1 << FIR_OP5_SHIFT) | 45093db446aSBoris Brezillon (FIR_OP_RS << FIR_OP6_SHIFT)); 45193db446aSBoris Brezillon } else { 45293db446aSBoris Brezillon out_be32(&lbc->fir, 45393db446aSBoris Brezillon (FIR_OP_CM0 << FIR_OP0_SHIFT) | 45493db446aSBoris Brezillon (FIR_OP_CM2 << FIR_OP1_SHIFT) | 45593db446aSBoris Brezillon (FIR_OP_CA << FIR_OP2_SHIFT) | 45693db446aSBoris Brezillon (FIR_OP_PA << FIR_OP3_SHIFT) | 45793db446aSBoris Brezillon (FIR_OP_WB << FIR_OP4_SHIFT) | 45893db446aSBoris Brezillon (FIR_OP_CM3 << FIR_OP5_SHIFT) | 45993db446aSBoris Brezillon (FIR_OP_CW1 << FIR_OP6_SHIFT) | 46093db446aSBoris Brezillon (FIR_OP_RS << FIR_OP7_SHIFT)); 46193db446aSBoris Brezillon 46293db446aSBoris Brezillon if (elbc_fcm_ctrl->oob) 46393db446aSBoris Brezillon /* OOB area --> READOOB */ 46493db446aSBoris Brezillon fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; 46593db446aSBoris Brezillon else 46693db446aSBoris Brezillon /* First 256 bytes --> READ0 */ 46793db446aSBoris Brezillon fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT; 46893db446aSBoris Brezillon } 46993db446aSBoris Brezillon 47093db446aSBoris Brezillon out_be32(&lbc->fcr, fcr); 47193db446aSBoris Brezillon set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob); 47293db446aSBoris Brezillon return; 47393db446aSBoris Brezillon } 47493db446aSBoris Brezillon 47593db446aSBoris Brezillon /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ 47693db446aSBoris Brezillon case NAND_CMD_PAGEPROG: { 47793db446aSBoris Brezillon dev_vdbg(priv->dev, 47893db446aSBoris Brezillon "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " 47993db446aSBoris Brezillon "writing %d bytes.\n", elbc_fcm_ctrl->index); 48093db446aSBoris Brezillon 48193db446aSBoris Brezillon /* if the write did not start at 0 or is not a full page 48293db446aSBoris Brezillon * then set the exact length, otherwise use a full page 48393db446aSBoris Brezillon * write so the HW generates the ECC. 48493db446aSBoris Brezillon */ 48593db446aSBoris Brezillon if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || 48693db446aSBoris Brezillon elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) 48793db446aSBoris Brezillon out_be32(&lbc->fbcr, 48893db446aSBoris Brezillon elbc_fcm_ctrl->index - elbc_fcm_ctrl->column); 48993db446aSBoris Brezillon else 49093db446aSBoris Brezillon out_be32(&lbc->fbcr, 0); 49193db446aSBoris Brezillon 49293db446aSBoris Brezillon fsl_elbc_run_command(mtd); 49393db446aSBoris Brezillon return; 49493db446aSBoris Brezillon } 49593db446aSBoris Brezillon 49693db446aSBoris Brezillon /* CMD_STATUS must read the status byte while CEB is active */ 49793db446aSBoris Brezillon /* Note - it does not wait for the ready line */ 49893db446aSBoris Brezillon case NAND_CMD_STATUS: 49993db446aSBoris Brezillon out_be32(&lbc->fir, 50093db446aSBoris Brezillon (FIR_OP_CM0 << FIR_OP0_SHIFT) | 50193db446aSBoris Brezillon (FIR_OP_RBW << FIR_OP1_SHIFT)); 50293db446aSBoris Brezillon out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); 50393db446aSBoris Brezillon out_be32(&lbc->fbcr, 1); 50493db446aSBoris Brezillon set_addr(mtd, 0, 0, 0); 50593db446aSBoris Brezillon elbc_fcm_ctrl->read_bytes = 1; 50693db446aSBoris Brezillon 50793db446aSBoris Brezillon fsl_elbc_run_command(mtd); 50893db446aSBoris Brezillon 50993db446aSBoris Brezillon /* The chip always seems to report that it is 51093db446aSBoris Brezillon * write-protected, even when it is not. 51193db446aSBoris Brezillon */ 51293db446aSBoris Brezillon setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP); 51393db446aSBoris Brezillon return; 51493db446aSBoris Brezillon 51593db446aSBoris Brezillon /* RESET without waiting for the ready line */ 51693db446aSBoris Brezillon case NAND_CMD_RESET: 51793db446aSBoris Brezillon dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); 51893db446aSBoris Brezillon out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); 51993db446aSBoris Brezillon out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); 52093db446aSBoris Brezillon fsl_elbc_run_command(mtd); 52193db446aSBoris Brezillon return; 52293db446aSBoris Brezillon 52393db446aSBoris Brezillon default: 52493db446aSBoris Brezillon dev_err(priv->dev, 52593db446aSBoris Brezillon "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", 52693db446aSBoris Brezillon command); 52793db446aSBoris Brezillon } 52893db446aSBoris Brezillon } 52993db446aSBoris Brezillon 530758b56f5SBoris Brezillon static void fsl_elbc_select_chip(struct nand_chip *chip, int cs) 53193db446aSBoris Brezillon { 53293db446aSBoris Brezillon /* The hardware does not seem to support multiple 53393db446aSBoris Brezillon * chips per bank. 53493db446aSBoris Brezillon */ 53593db446aSBoris Brezillon } 53693db446aSBoris Brezillon 53793db446aSBoris Brezillon /* 53893db446aSBoris Brezillon * Write buf to the FCM Controller Data Buffer 53993db446aSBoris Brezillon */ 540c0739d85SBoris Brezillon static void fsl_elbc_write_buf(struct nand_chip *chip, const u8 *buf, int len) 54193db446aSBoris Brezillon { 542c0739d85SBoris Brezillon struct mtd_info *mtd = nand_to_mtd(chip); 54393db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 54493db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; 54593db446aSBoris Brezillon unsigned int bufsize = mtd->writesize + mtd->oobsize; 54693db446aSBoris Brezillon 54793db446aSBoris Brezillon if (len <= 0) { 54893db446aSBoris Brezillon dev_err(priv->dev, "write_buf of %d bytes", len); 54993db446aSBoris Brezillon elbc_fcm_ctrl->status = 0; 55093db446aSBoris Brezillon return; 55193db446aSBoris Brezillon } 55293db446aSBoris Brezillon 55393db446aSBoris Brezillon if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) { 55493db446aSBoris Brezillon dev_err(priv->dev, 55593db446aSBoris Brezillon "write_buf beyond end of buffer " 55693db446aSBoris Brezillon "(%d requested, %u available)\n", 55793db446aSBoris Brezillon len, bufsize - elbc_fcm_ctrl->index); 55893db446aSBoris Brezillon len = bufsize - elbc_fcm_ctrl->index; 55993db446aSBoris Brezillon } 56093db446aSBoris Brezillon 56193db446aSBoris Brezillon memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len); 56293db446aSBoris Brezillon /* 56393db446aSBoris Brezillon * This is workaround for the weird elbc hangs during nand write, 56493db446aSBoris Brezillon * Scott Wood says: "...perhaps difference in how long it takes a 56593db446aSBoris Brezillon * write to make it through the localbus compared to a write to IMMR 56693db446aSBoris Brezillon * is causing problems, and sync isn't helping for some reason." 56793db446aSBoris Brezillon * Reading back the last byte helps though. 56893db446aSBoris Brezillon */ 56993db446aSBoris Brezillon in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1); 57093db446aSBoris Brezillon 57193db446aSBoris Brezillon elbc_fcm_ctrl->index += len; 57293db446aSBoris Brezillon } 57393db446aSBoris Brezillon 57493db446aSBoris Brezillon /* 57593db446aSBoris Brezillon * read a byte from either the FCM hardware buffer if it has any data left 57693db446aSBoris Brezillon * otherwise issue a command to read a single byte. 57793db446aSBoris Brezillon */ 5787e534323SBoris Brezillon static u8 fsl_elbc_read_byte(struct nand_chip *chip) 57993db446aSBoris Brezillon { 58093db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 58193db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; 58293db446aSBoris Brezillon 58393db446aSBoris Brezillon /* If there are still bytes in the FCM, then use the next byte. */ 58493db446aSBoris Brezillon if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes) 58593db446aSBoris Brezillon return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]); 58693db446aSBoris Brezillon 58793db446aSBoris Brezillon dev_err(priv->dev, "read_byte beyond end of buffer\n"); 58893db446aSBoris Brezillon return ERR_BYTE; 58993db446aSBoris Brezillon } 59093db446aSBoris Brezillon 59193db446aSBoris Brezillon /* 59293db446aSBoris Brezillon * Read from the FCM Controller Data Buffer 59393db446aSBoris Brezillon */ 5947e534323SBoris Brezillon static void fsl_elbc_read_buf(struct nand_chip *chip, u8 *buf, int len) 59593db446aSBoris Brezillon { 59693db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 59793db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; 59893db446aSBoris Brezillon int avail; 59993db446aSBoris Brezillon 60093db446aSBoris Brezillon if (len < 0) 60193db446aSBoris Brezillon return; 60293db446aSBoris Brezillon 60393db446aSBoris Brezillon avail = min((unsigned int)len, 60493db446aSBoris Brezillon elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index); 60593db446aSBoris Brezillon memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail); 60693db446aSBoris Brezillon elbc_fcm_ctrl->index += avail; 60793db446aSBoris Brezillon 60893db446aSBoris Brezillon if (len > avail) 60993db446aSBoris Brezillon dev_err(priv->dev, 61093db446aSBoris Brezillon "read_buf beyond end of buffer " 61193db446aSBoris Brezillon "(%d requested, %d available)\n", 61293db446aSBoris Brezillon len, avail); 61393db446aSBoris Brezillon } 61493db446aSBoris Brezillon 61593db446aSBoris Brezillon /* This function is called after Program and Erase Operations to 61693db446aSBoris Brezillon * check for success or failure. 61793db446aSBoris Brezillon */ 618f1d46942SBoris Brezillon static int fsl_elbc_wait(struct nand_chip *chip) 61993db446aSBoris Brezillon { 62093db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 62193db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; 62293db446aSBoris Brezillon 62393db446aSBoris Brezillon if (elbc_fcm_ctrl->status != LTESR_CC) 62493db446aSBoris Brezillon return NAND_STATUS_FAIL; 62593db446aSBoris Brezillon 62693db446aSBoris Brezillon /* The chip always seems to report that it is 62793db446aSBoris Brezillon * write-protected, even when it is not. 62893db446aSBoris Brezillon */ 62993db446aSBoris Brezillon return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP; 63093db446aSBoris Brezillon } 63193db446aSBoris Brezillon 632b9761687SBoris Brezillon static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf, 633b9761687SBoris Brezillon int oob_required, int page) 63493db446aSBoris Brezillon { 635b9761687SBoris Brezillon struct mtd_info *mtd = nand_to_mtd(chip); 63693db446aSBoris Brezillon struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 63793db446aSBoris Brezillon struct fsl_lbc_ctrl *ctrl = priv->ctrl; 63893db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; 63993db446aSBoris Brezillon 64093db446aSBoris Brezillon nand_read_page_op(chip, page, 0, buf, mtd->writesize); 64193db446aSBoris Brezillon if (oob_required) 6427e534323SBoris Brezillon fsl_elbc_read_buf(chip, chip->oob_poi, mtd->oobsize); 64393db446aSBoris Brezillon 644f1d46942SBoris Brezillon if (fsl_elbc_wait(chip) & NAND_STATUS_FAIL) 64593db446aSBoris Brezillon mtd->ecc_stats.failed++; 64693db446aSBoris Brezillon 64793db446aSBoris Brezillon return elbc_fcm_ctrl->max_bitflips; 64893db446aSBoris Brezillon } 64993db446aSBoris Brezillon 65093db446aSBoris Brezillon /* ECC will be calculated automatically, and errors will be detected in 65193db446aSBoris Brezillon * waitfunc. 65293db446aSBoris Brezillon */ 653767eb6fbSBoris Brezillon static int fsl_elbc_write_page(struct nand_chip *chip, const uint8_t *buf, 654767eb6fbSBoris Brezillon int oob_required, int page) 65593db446aSBoris Brezillon { 656767eb6fbSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(chip); 657767eb6fbSBoris Brezillon 65893db446aSBoris Brezillon nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize); 659c0739d85SBoris Brezillon fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize); 66093db446aSBoris Brezillon 66193db446aSBoris Brezillon return nand_prog_page_end_op(chip); 66293db446aSBoris Brezillon } 66393db446aSBoris Brezillon 66493db446aSBoris Brezillon /* ECC will be calculated automatically, and errors will be detected in 66593db446aSBoris Brezillon * waitfunc. 66693db446aSBoris Brezillon */ 667767eb6fbSBoris Brezillon static int fsl_elbc_write_subpage(struct nand_chip *chip, uint32_t offset, 668767eb6fbSBoris Brezillon uint32_t data_len, const uint8_t *buf, 669767eb6fbSBoris Brezillon int oob_required, int page) 67093db446aSBoris Brezillon { 671767eb6fbSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(chip); 672767eb6fbSBoris Brezillon 67393db446aSBoris Brezillon nand_prog_page_begin_op(chip, page, 0, NULL, 0); 674c0739d85SBoris Brezillon fsl_elbc_write_buf(chip, buf, mtd->writesize); 675c0739d85SBoris Brezillon fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize); 67693db446aSBoris Brezillon return nand_prog_page_end_op(chip); 67793db446aSBoris Brezillon } 67893db446aSBoris Brezillon 67993db446aSBoris Brezillon static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) 68093db446aSBoris Brezillon { 68193db446aSBoris Brezillon struct fsl_lbc_ctrl *ctrl = priv->ctrl; 68293db446aSBoris Brezillon struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 68393db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; 68493db446aSBoris Brezillon struct nand_chip *chip = &priv->chip; 68593db446aSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(chip); 68693db446aSBoris Brezillon 68793db446aSBoris Brezillon dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); 68893db446aSBoris Brezillon 68993db446aSBoris Brezillon /* Fill in fsl_elbc_mtd structure */ 69093db446aSBoris Brezillon mtd->dev.parent = priv->dev; 69193db446aSBoris Brezillon nand_set_flash_node(chip, priv->dev->of_node); 69293db446aSBoris Brezillon 69393db446aSBoris Brezillon /* set timeout to maximum */ 69493db446aSBoris Brezillon priv->fmr = 15 << FMR_CWTO_SHIFT; 69593db446aSBoris Brezillon if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS) 69693db446aSBoris Brezillon priv->fmr |= FMR_ECCM; 69793db446aSBoris Brezillon 69893db446aSBoris Brezillon /* fill in nand_chip structure */ 69993db446aSBoris Brezillon /* set up function call table */ 700716bbbabSBoris Brezillon chip->legacy.read_byte = fsl_elbc_read_byte; 701716bbbabSBoris Brezillon chip->legacy.write_buf = fsl_elbc_write_buf; 702716bbbabSBoris Brezillon chip->legacy.read_buf = fsl_elbc_read_buf; 7037d6c37e9SBoris Brezillon chip->legacy.select_chip = fsl_elbc_select_chip; 704bf6065c6SBoris Brezillon chip->legacy.cmdfunc = fsl_elbc_cmdfunc; 7058395b753SBoris Brezillon chip->legacy.waitfunc = fsl_elbc_wait; 70645240367SBoris Brezillon chip->legacy.set_features = nand_get_set_features_notsupp; 70745240367SBoris Brezillon chip->legacy.get_features = nand_get_set_features_notsupp; 70893db446aSBoris Brezillon 70993db446aSBoris Brezillon chip->bbt_td = &bbt_main_descr; 71093db446aSBoris Brezillon chip->bbt_md = &bbt_mirror_descr; 71193db446aSBoris Brezillon 71293db446aSBoris Brezillon /* set up nand options */ 71393db446aSBoris Brezillon chip->bbt_options = NAND_BBT_USE_FLASH; 71493db446aSBoris Brezillon 71593db446aSBoris Brezillon chip->controller = &elbc_fcm_ctrl->controller; 71693db446aSBoris Brezillon nand_set_controller_data(chip, priv); 71793db446aSBoris Brezillon 71893db446aSBoris Brezillon return 0; 71993db446aSBoris Brezillon } 72093db446aSBoris Brezillon 7219fed3115SMarek Behún static int fsl_elbc_attach_chip(struct nand_chip *chip) 7229fed3115SMarek Behún { 7239fed3115SMarek Behún struct mtd_info *mtd = nand_to_mtd(chip); 7249fed3115SMarek Behún struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); 7259fed3115SMarek Behún struct fsl_lbc_ctrl *ctrl = priv->ctrl; 7269fed3115SMarek Behún struct fsl_lbc_regs __iomem *lbc = ctrl->regs; 7279fed3115SMarek Behún unsigned int al; 728*b5626525SPali Rohár u32 br; 7299fed3115SMarek Behún 730f6424c22SMarek Behún /* 731f6424c22SMarek Behún * if ECC was not chosen in DT, decide whether to use HW or SW ECC from 732f6424c22SMarek Behún * CS Base Register 733f6424c22SMarek Behún */ 734049e43b9SPali Rohár if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_INVALID) { 735f6424c22SMarek Behún /* If CS Base Register selects full hardware ECC then use it */ 736f6424c22SMarek Behún if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == 737f6424c22SMarek Behún BR_DECC_CHK_GEN) { 738bace41f8SMiquel Raynal chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; 739f6424c22SMarek Behún } else { 740f6424c22SMarek Behún /* otherwise fall back to default software ECC */ 741bace41f8SMiquel Raynal chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT; 742e0a564aeSMiquel Raynal chip->ecc.algo = NAND_ECC_ALGO_HAMMING; 743f6424c22SMarek Behún } 744049e43b9SPali Rohár } 745049e43b9SPali Rohár 746049e43b9SPali Rohár switch (chip->ecc.engine_type) { 747049e43b9SPali Rohár /* if HW ECC was chosen, setup ecc and oob layout */ 748049e43b9SPali Rohár case NAND_ECC_ENGINE_TYPE_ON_HOST: 749049e43b9SPali Rohár chip->ecc.read_page = fsl_elbc_read_page; 750049e43b9SPali Rohár chip->ecc.write_page = fsl_elbc_write_page; 751049e43b9SPali Rohár chip->ecc.write_subpage = fsl_elbc_write_subpage; 752049e43b9SPali Rohár mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); 753049e43b9SPali Rohár chip->ecc.size = 512; 754049e43b9SPali Rohár chip->ecc.bytes = 3; 755049e43b9SPali Rohár chip->ecc.strength = 1; 756f6424c22SMarek Behún break; 757f6424c22SMarek Behún 758049e43b9SPali Rohár /* if none or SW ECC was chosen, we do not need to set anything here */ 759049e43b9SPali Rohár case NAND_ECC_ENGINE_TYPE_NONE: 760bace41f8SMiquel Raynal case NAND_ECC_ENGINE_TYPE_SOFT: 761049e43b9SPali Rohár case NAND_ECC_ENGINE_TYPE_ON_DIE: 762f6424c22SMarek Behún break; 763f6424c22SMarek Behún 764f6424c22SMarek Behún default: 765f6424c22SMarek Behún return -EINVAL; 766f6424c22SMarek Behún } 767f6424c22SMarek Behún 768*b5626525SPali Rohár /* enable/disable HW ECC checking and generating based on if HW ECC was chosen */ 769*b5626525SPali Rohár br = in_be32(&lbc->bank[priv->bank].br) & ~BR_DECC; 770*b5626525SPali Rohár if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_ON_HOST) 771*b5626525SPali Rohár out_be32(&lbc->bank[priv->bank].br, br | BR_DECC_CHK_GEN); 772*b5626525SPali Rohár else 773*b5626525SPali Rohár out_be32(&lbc->bank[priv->bank].br, br | BR_DECC_OFF); 774*b5626525SPali Rohár 7759fed3115SMarek Behún /* calculate FMR Address Length field */ 7769fed3115SMarek Behún al = 0; 7779fed3115SMarek Behún if (chip->pagemask & 0xffff0000) 7789fed3115SMarek Behún al++; 7799fed3115SMarek Behún if (chip->pagemask & 0xff000000) 7809fed3115SMarek Behún al++; 7819fed3115SMarek Behún 7829fed3115SMarek Behún priv->fmr |= al << FMR_AL_SHIFT; 7839fed3115SMarek Behún 7849fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", 7859fed3115SMarek Behún nanddev_ntargets(&chip->base)); 7869fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n", 7879fed3115SMarek Behún nanddev_target_size(&chip->base)); 7889fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", 7899fed3115SMarek Behún chip->pagemask); 7909fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->legacy.chip_delay = %d\n", 7919fed3115SMarek Behún chip->legacy.chip_delay); 7929fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", 7939fed3115SMarek Behún chip->badblockpos); 7949fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", 7959fed3115SMarek Behún chip->chip_shift); 7969fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n", 7979fed3115SMarek Behún chip->page_shift); 7989fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", 7999fed3115SMarek Behún chip->phys_erase_shift); 800bace41f8SMiquel Raynal dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.engine_type = %d\n", 801bace41f8SMiquel Raynal chip->ecc.engine_type); 8029fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", 8039fed3115SMarek Behún chip->ecc.steps); 8049fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", 8059fed3115SMarek Behún chip->ecc.bytes); 8069fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", 8079fed3115SMarek Behún chip->ecc.total); 8089fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: mtd->ooblayout = %p\n", 8099fed3115SMarek Behún mtd->ooblayout); 8109fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); 8119fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); 8129fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", 8139fed3115SMarek Behún mtd->erasesize); 8149fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n", 8159fed3115SMarek Behún mtd->writesize); 8169fed3115SMarek Behún dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n", 8179fed3115SMarek Behún mtd->oobsize); 8189fed3115SMarek Behún 8199fed3115SMarek Behún /* adjust Option Register and ECC to match Flash page size */ 8209fed3115SMarek Behún if (mtd->writesize == 512) { 8219fed3115SMarek Behún priv->page_size = 0; 8229fed3115SMarek Behún clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); 8239fed3115SMarek Behún } else if (mtd->writesize == 2048) { 8249fed3115SMarek Behún priv->page_size = 1; 8259fed3115SMarek Behún setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); 8269fed3115SMarek Behún } else { 8279fed3115SMarek Behún dev_err(priv->dev, 8289fed3115SMarek Behún "fsl_elbc_init: page size %d is not supported\n", 8299fed3115SMarek Behún mtd->writesize); 8309fed3115SMarek Behún return -ENOTSUPP; 8319fed3115SMarek Behún } 8329fed3115SMarek Behún 8339fed3115SMarek Behún return 0; 8349fed3115SMarek Behún } 8359fed3115SMarek Behún 8369fed3115SMarek Behún static const struct nand_controller_ops fsl_elbc_controller_ops = { 8379fed3115SMarek Behún .attach_chip = fsl_elbc_attach_chip, 8389fed3115SMarek Behún }; 8399fed3115SMarek Behún 84093db446aSBoris Brezillon static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) 84193db446aSBoris Brezillon { 84293db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; 84393db446aSBoris Brezillon struct mtd_info *mtd = nand_to_mtd(&priv->chip); 84493db446aSBoris Brezillon 84593db446aSBoris Brezillon kfree(mtd->name); 84693db446aSBoris Brezillon 84793db446aSBoris Brezillon if (priv->vbase) 84893db446aSBoris Brezillon iounmap(priv->vbase); 84993db446aSBoris Brezillon 85093db446aSBoris Brezillon elbc_fcm_ctrl->chips[priv->bank] = NULL; 85193db446aSBoris Brezillon kfree(priv); 85293db446aSBoris Brezillon return 0; 85393db446aSBoris Brezillon } 85493db446aSBoris Brezillon 85593db446aSBoris Brezillon static DEFINE_MUTEX(fsl_elbc_nand_mutex); 85693db446aSBoris Brezillon 85793db446aSBoris Brezillon static int fsl_elbc_nand_probe(struct platform_device *pdev) 85893db446aSBoris Brezillon { 85993db446aSBoris Brezillon struct fsl_lbc_regs __iomem *lbc; 86093db446aSBoris Brezillon struct fsl_elbc_mtd *priv; 86193db446aSBoris Brezillon struct resource res; 86293db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; 86393db446aSBoris Brezillon static const char *part_probe_types[] 86493db446aSBoris Brezillon = { "cmdlinepart", "RedBoot", "ofpart", NULL }; 86593db446aSBoris Brezillon int ret; 86693db446aSBoris Brezillon int bank; 86793db446aSBoris Brezillon struct device *dev; 86893db446aSBoris Brezillon struct device_node *node = pdev->dev.of_node; 86993db446aSBoris Brezillon struct mtd_info *mtd; 87093db446aSBoris Brezillon 87193db446aSBoris Brezillon if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) 87293db446aSBoris Brezillon return -ENODEV; 87393db446aSBoris Brezillon lbc = fsl_lbc_ctrl_dev->regs; 87493db446aSBoris Brezillon dev = fsl_lbc_ctrl_dev->dev; 87593db446aSBoris Brezillon 87693db446aSBoris Brezillon /* get, allocate and map the memory resource */ 87793db446aSBoris Brezillon ret = of_address_to_resource(node, 0, &res); 87893db446aSBoris Brezillon if (ret) { 87993db446aSBoris Brezillon dev_err(dev, "failed to get resource\n"); 88093db446aSBoris Brezillon return ret; 88193db446aSBoris Brezillon } 88293db446aSBoris Brezillon 88393db446aSBoris Brezillon /* find which chip select it is connected to */ 88493db446aSBoris Brezillon for (bank = 0; bank < MAX_BANKS; bank++) 88593db446aSBoris Brezillon if ((in_be32(&lbc->bank[bank].br) & BR_V) && 88693db446aSBoris Brezillon (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM && 88793db446aSBoris Brezillon (in_be32(&lbc->bank[bank].br) & 88893db446aSBoris Brezillon in_be32(&lbc->bank[bank].or) & BR_BA) 88993db446aSBoris Brezillon == fsl_lbc_addr(res.start)) 89093db446aSBoris Brezillon break; 89193db446aSBoris Brezillon 89293db446aSBoris Brezillon if (bank >= MAX_BANKS) { 89393db446aSBoris Brezillon dev_err(dev, "address did not match any chip selects\n"); 89493db446aSBoris Brezillon return -ENODEV; 89593db446aSBoris Brezillon } 89693db446aSBoris Brezillon 89793db446aSBoris Brezillon priv = kzalloc(sizeof(*priv), GFP_KERNEL); 89893db446aSBoris Brezillon if (!priv) 89993db446aSBoris Brezillon return -ENOMEM; 90093db446aSBoris Brezillon 90193db446aSBoris Brezillon mutex_lock(&fsl_elbc_nand_mutex); 90293db446aSBoris Brezillon if (!fsl_lbc_ctrl_dev->nand) { 90393db446aSBoris Brezillon elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL); 90493db446aSBoris Brezillon if (!elbc_fcm_ctrl) { 90593db446aSBoris Brezillon mutex_unlock(&fsl_elbc_nand_mutex); 90693db446aSBoris Brezillon ret = -ENOMEM; 90793db446aSBoris Brezillon goto err; 90893db446aSBoris Brezillon } 90993db446aSBoris Brezillon elbc_fcm_ctrl->counter++; 91093db446aSBoris Brezillon 9117da45139SMiquel Raynal nand_controller_init(&elbc_fcm_ctrl->controller); 91293db446aSBoris Brezillon fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl; 91393db446aSBoris Brezillon } else { 91493db446aSBoris Brezillon elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; 91593db446aSBoris Brezillon } 91693db446aSBoris Brezillon mutex_unlock(&fsl_elbc_nand_mutex); 91793db446aSBoris Brezillon 91893db446aSBoris Brezillon elbc_fcm_ctrl->chips[bank] = priv; 91993db446aSBoris Brezillon priv->bank = bank; 92093db446aSBoris Brezillon priv->ctrl = fsl_lbc_ctrl_dev; 92193db446aSBoris Brezillon priv->dev = &pdev->dev; 92293db446aSBoris Brezillon dev_set_drvdata(priv->dev, priv); 92393db446aSBoris Brezillon 92493db446aSBoris Brezillon priv->vbase = ioremap(res.start, resource_size(&res)); 92593db446aSBoris Brezillon if (!priv->vbase) { 92693db446aSBoris Brezillon dev_err(dev, "failed to map chip region\n"); 92793db446aSBoris Brezillon ret = -ENOMEM; 92893db446aSBoris Brezillon goto err; 92993db446aSBoris Brezillon } 93093db446aSBoris Brezillon 93193db446aSBoris Brezillon mtd = nand_to_mtd(&priv->chip); 93293db446aSBoris Brezillon mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); 93393db446aSBoris Brezillon if (!nand_to_mtd(&priv->chip)->name) { 93493db446aSBoris Brezillon ret = -ENOMEM; 93593db446aSBoris Brezillon goto err; 93693db446aSBoris Brezillon } 93793db446aSBoris Brezillon 93893db446aSBoris Brezillon ret = fsl_elbc_chip_init(priv); 93993db446aSBoris Brezillon if (ret) 94093db446aSBoris Brezillon goto err; 94193db446aSBoris Brezillon 9425bf3e76bSMiquel Raynal priv->chip.controller->ops = &fsl_elbc_controller_ops; 94300ad378fSBoris Brezillon ret = nand_scan(&priv->chip, 1); 94493db446aSBoris Brezillon if (ret) 94593db446aSBoris Brezillon goto err; 94693db446aSBoris Brezillon 94793db446aSBoris Brezillon /* First look for RedBoot table or partitions on the command 94893db446aSBoris Brezillon * line, these take precedence over device tree information */ 94939b77c58SMiquel Raynal ret = mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0); 95039b77c58SMiquel Raynal if (ret) 95139b77c58SMiquel Raynal goto cleanup_nand; 95293db446aSBoris Brezillon 95363fa37f0SShreeya Patel pr_info("eLBC NAND device at 0x%llx, bank %d\n", 95493db446aSBoris Brezillon (unsigned long long)res.start, priv->bank); 95539b77c58SMiquel Raynal 95693db446aSBoris Brezillon return 0; 95793db446aSBoris Brezillon 95839b77c58SMiquel Raynal cleanup_nand: 95939b77c58SMiquel Raynal nand_cleanup(&priv->chip); 96093db446aSBoris Brezillon err: 96193db446aSBoris Brezillon fsl_elbc_chip_remove(priv); 96239b77c58SMiquel Raynal 96393db446aSBoris Brezillon return ret; 96493db446aSBoris Brezillon } 96593db446aSBoris Brezillon 96693db446aSBoris Brezillon static int fsl_elbc_nand_remove(struct platform_device *pdev) 96793db446aSBoris Brezillon { 96893db446aSBoris Brezillon struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; 96993db446aSBoris Brezillon struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev); 970128bbbf0SMiquel Raynal struct nand_chip *chip = &priv->chip; 971128bbbf0SMiquel Raynal int ret; 97293db446aSBoris Brezillon 973128bbbf0SMiquel Raynal ret = mtd_device_unregister(nand_to_mtd(chip)); 974128bbbf0SMiquel Raynal WARN_ON(ret); 975128bbbf0SMiquel Raynal nand_cleanup(chip); 976128bbbf0SMiquel Raynal 97793db446aSBoris Brezillon fsl_elbc_chip_remove(priv); 97893db446aSBoris Brezillon 97993db446aSBoris Brezillon mutex_lock(&fsl_elbc_nand_mutex); 98093db446aSBoris Brezillon elbc_fcm_ctrl->counter--; 98193db446aSBoris Brezillon if (!elbc_fcm_ctrl->counter) { 98293db446aSBoris Brezillon fsl_lbc_ctrl_dev->nand = NULL; 98393db446aSBoris Brezillon kfree(elbc_fcm_ctrl); 98493db446aSBoris Brezillon } 98593db446aSBoris Brezillon mutex_unlock(&fsl_elbc_nand_mutex); 98693db446aSBoris Brezillon 98793db446aSBoris Brezillon return 0; 98893db446aSBoris Brezillon 98993db446aSBoris Brezillon } 99093db446aSBoris Brezillon 99193db446aSBoris Brezillon static const struct of_device_id fsl_elbc_nand_match[] = { 99293db446aSBoris Brezillon { .compatible = "fsl,elbc-fcm-nand", }, 99393db446aSBoris Brezillon {} 99493db446aSBoris Brezillon }; 99593db446aSBoris Brezillon MODULE_DEVICE_TABLE(of, fsl_elbc_nand_match); 99693db446aSBoris Brezillon 99793db446aSBoris Brezillon static struct platform_driver fsl_elbc_nand_driver = { 99893db446aSBoris Brezillon .driver = { 99993db446aSBoris Brezillon .name = "fsl,elbc-fcm-nand", 100093db446aSBoris Brezillon .of_match_table = fsl_elbc_nand_match, 100193db446aSBoris Brezillon }, 100293db446aSBoris Brezillon .probe = fsl_elbc_nand_probe, 100393db446aSBoris Brezillon .remove = fsl_elbc_nand_remove, 100493db446aSBoris Brezillon }; 100593db446aSBoris Brezillon 100693db446aSBoris Brezillon module_platform_driver(fsl_elbc_nand_driver); 100793db446aSBoris Brezillon 100893db446aSBoris Brezillon MODULE_LICENSE("GPL"); 100993db446aSBoris Brezillon MODULE_AUTHOR("Freescale"); 101093db446aSBoris Brezillon MODULE_DESCRIPTION("Freescale Enhanced Local Bus Controller MTD NAND driver"); 1011