blob: 634c550db13a7c6c4100e9fa4b51efa9fdc4bda9 [file] [log] [blame]
Thomas Gleixner1a59d1b82019-05-27 08:55:05 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Scott Wood76b10462008-02-06 15:36:21 -06002/* Freescale Enhanced Local Bus Controller NAND driver
3 *
Roy Zang3ab8f2a2010-10-18 15:22:31 +08004 * Copyright © 2006-2007, 2010 Freescale Semiconductor
Scott Wood76b10462008-02-06 15:36:21 -06005 *
6 * Authors: Nick Spence <nick.spence@freescale.com>,
7 * Scott Wood <scottwood@freescale.com>
Roy Zang3ab8f2a2010-10-18 15:22:31 +08008 * Jack Lan <jack.lan@freescale.com>
9 * Roy Zang <tie-fei.zang@freescale.com>
Scott Wood76b10462008-02-06 15:36:21 -060010 */
11
12#include <linux/module.h>
13#include <linux/types.h>
Scott Wood76b10462008-02-06 15:36:21 -060014#include <linux/kernel.h>
15#include <linux/string.h>
16#include <linux/ioport.h>
Rob Herring5af50732013-09-17 14:28:33 -050017#include <linux/of_address.h>
Scott Wood76b10462008-02-06 15:36:21 -060018#include <linux/of_platform.h>
Roy Zang3ab8f2a2010-10-18 15:22:31 +080019#include <linux/platform_device.h>
Scott Wood76b10462008-02-06 15:36:21 -060020#include <linux/slab.h>
21#include <linux/interrupt.h>
22
23#include <linux/mtd/mtd.h>
Boris Brezillond4092d72017-08-04 17:29:10 +020024#include <linux/mtd/rawnand.h>
Scott Wood76b10462008-02-06 15:36:21 -060025#include <linux/mtd/nand_ecc.h>
26#include <linux/mtd/partitions.h>
27
28#include <asm/io.h>
Anton Vorontsovd4a32fe2008-03-11 20:23:28 +030029#include <asm/fsl_lbc.h>
Scott Wood76b10462008-02-06 15:36:21 -060030
31#define MAX_BANKS 8
32#define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */
33#define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */
34
Scott Wood76b10462008-02-06 15:36:21 -060035/* mtd information per set */
36
37struct fsl_elbc_mtd {
Scott Wood76b10462008-02-06 15:36:21 -060038 struct nand_chip chip;
Roy Zang3ab8f2a2010-10-18 15:22:31 +080039 struct fsl_lbc_ctrl *ctrl;
Scott Wood76b10462008-02-06 15:36:21 -060040
41 struct device *dev;
42 int bank; /* Chip select bank number */
43 u8 __iomem *vbase; /* Chip select base virtual address */
44 int page_size; /* NAND page size (0=512, 1=2048) */
45 unsigned int fmr; /* FCM Flash Mode Register value */
46};
47
Lucas De Marchi25985ed2011-03-30 22:57:33 -030048/* Freescale eLBC FCM controller information */
Scott Wood76b10462008-02-06 15:36:21 -060049
Roy Zang3ab8f2a2010-10-18 15:22:31 +080050struct fsl_elbc_fcm_ctrl {
Miquel Raynal7da45132018-07-17 09:08:02 +020051 struct nand_controller controller;
Scott Wood76b10462008-02-06 15:36:21 -060052 struct fsl_elbc_mtd *chips[MAX_BANKS];
53
Scott Wood76b10462008-02-06 15:36:21 -060054 u8 __iomem *addr; /* Address of assigned FCM buffer */
55 unsigned int page; /* Last page written to / read from */
56 unsigned int read_bytes; /* Number of bytes read during command */
57 unsigned int column; /* Saved column from SEQIN */
58 unsigned int index; /* Pointer to next byte to 'read' */
59 unsigned int status; /* status read from LTESR after last op */
60 unsigned int mdr; /* UPM/FCM Data Register value */
61 unsigned int use_mdr; /* Non zero if the MDR is to be set */
62 unsigned int oob; /* Non zero if operating on OOB data */
Roy Zang3ab8f2a2010-10-18 15:22:31 +080063 unsigned int counter; /* counter for the initializations */
Mike Dunn3f91e942012-04-25 12:06:09 -070064 unsigned int max_bitflips; /* Saved during READ0 cmd */
Scott Wood76b10462008-02-06 15:36:21 -060065};
66
67/* These map to the positions used by the FCM hardware ECC generator */
68
Boris Brezillonc2e197b2016-02-03 20:01:04 +010069static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section,
70 struct mtd_oob_region *oobregion)
71{
72 struct nand_chip *chip = mtd_to_nand(mtd);
73 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Scott Wood76b10462008-02-06 15:36:21 -060074
Boris Brezillonc2e197b2016-02-03 20:01:04 +010075 if (section >= chip->ecc.steps)
76 return -ERANGE;
Scott Wood76b10462008-02-06 15:36:21 -060077
Boris Brezillonc2e197b2016-02-03 20:01:04 +010078 oobregion->offset = (16 * section) + 6;
79 if (priv->fmr & FMR_ECCM)
80 oobregion->offset += 2;
Scott Wood76b10462008-02-06 15:36:21 -060081
Boris Brezillonc2e197b2016-02-03 20:01:04 +010082 oobregion->length = chip->ecc.bytes;
83
84 return 0;
85}
86
87static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section,
88 struct mtd_oob_region *oobregion)
89{
90 struct nand_chip *chip = mtd_to_nand(mtd);
91 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
92
93 if (section > chip->ecc.steps)
94 return -ERANGE;
95
96 if (!section) {
97 oobregion->offset = 0;
98 if (mtd->writesize > 512)
99 oobregion->offset++;
100 oobregion->length = (priv->fmr & FMR_ECCM) ? 7 : 5;
101 } else {
102 oobregion->offset = (16 * section) -
103 ((priv->fmr & FMR_ECCM) ? 5 : 7);
104 if (section < chip->ecc.steps)
105 oobregion->length = 13;
106 else
107 oobregion->length = mtd->oobsize - oobregion->offset;
108 }
109
110 return 0;
111}
112
113static const struct mtd_ooblayout_ops fsl_elbc_ooblayout_ops = {
114 .ecc = fsl_elbc_ooblayout_ecc,
115 .free = fsl_elbc_ooblayout_free,
Scott Wood76b10462008-02-06 15:36:21 -0600116};
117
Anton Vorontsov452db272008-06-27 23:04:04 +0400118/*
Anton Vorontsovec6e0ea2008-06-27 23:04:13 +0400119 * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
120 * interfere with ECC positions, that's why we implement our own descriptors.
121 * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0.
122 */
123static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
124static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
125
126static struct nand_bbt_descr bbt_main_descr = {
127 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
128 NAND_BBT_2BIT | NAND_BBT_VERSION,
129 .offs = 11,
130 .len = 4,
131 .veroffs = 15,
132 .maxblocks = 4,
133 .pattern = bbt_pattern,
134};
135
136static struct nand_bbt_descr bbt_mirror_descr = {
137 .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
138 NAND_BBT_2BIT | NAND_BBT_VERSION,
139 .offs = 11,
140 .len = 4,
141 .veroffs = 15,
142 .maxblocks = 4,
143 .pattern = mirror_pattern,
144};
145
Scott Wood76b10462008-02-06 15:36:21 -0600146/*=================================*/
147
148/*
149 * Set up the FCM hardware block and page address fields, and the fcm
150 * structure addr field to point to the correct FCM buffer in memory
151 */
152static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
153{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100154 struct nand_chip *chip = mtd_to_nand(mtd);
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100155 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800156 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
Anton Vorontsovd4a32fe2008-03-11 20:23:28 +0300157 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800158 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
Scott Wood76b10462008-02-06 15:36:21 -0600159 int buf_num;
160
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800161 elbc_fcm_ctrl->page = page_addr;
Scott Wood76b10462008-02-06 15:36:21 -0600162
Scott Wood76b10462008-02-06 15:36:21 -0600163 if (priv->page_size) {
Liu Shuo9ae84fe2011-12-09 17:42:54 +0800164 /*
165 * large page size chip : FPAR[PI] save the lowest 6 bits,
166 * FBAR[BLK] save the other bits.
167 */
168 out_be32(&lbc->fbar, page_addr >> 6);
Scott Wood76b10462008-02-06 15:36:21 -0600169 out_be32(&lbc->fpar,
170 ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
171 (oob ? FPAR_LP_MS : 0) | column);
172 buf_num = (page_addr & 1) << 2;
173 } else {
Liu Shuo9ae84fe2011-12-09 17:42:54 +0800174 /*
175 * small page size chip : FPAR[PI] save the lowest 5 bits,
176 * FBAR[BLK] save the other bits.
177 */
178 out_be32(&lbc->fbar, page_addr >> 5);
Scott Wood76b10462008-02-06 15:36:21 -0600179 out_be32(&lbc->fpar,
180 ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
181 (oob ? FPAR_SP_MS : 0) | column);
182 buf_num = page_addr & 7;
183 }
184
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800185 elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024;
186 elbc_fcm_ctrl->index = column;
Scott Wood76b10462008-02-06 15:36:21 -0600187
188 /* for OOB data point to the second half of the buffer */
189 if (oob)
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800190 elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512;
Scott Wood76b10462008-02-06 15:36:21 -0600191
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800192 dev_vdbg(priv->dev, "set_addr: bank=%d, "
193 "elbc_fcm_ctrl->addr=0x%p (0x%p), "
Scott Wood76b10462008-02-06 15:36:21 -0600194 "index %x, pes %d ps %d\n",
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800195 buf_num, elbc_fcm_ctrl->addr, priv->vbase,
196 elbc_fcm_ctrl->index,
Scott Wood76b10462008-02-06 15:36:21 -0600197 chip->phys_erase_shift, chip->page_shift);
198}
199
200/*
201 * execute FCM command and wait for it to complete
202 */
203static int fsl_elbc_run_command(struct mtd_info *mtd)
204{
Boris BREZILLON4bd4ebc2015-12-01 12:03:04 +0100205 struct nand_chip *chip = mtd_to_nand(mtd);
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100206 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800207 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
208 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
Anton Vorontsovd4a32fe2008-03-11 20:23:28 +0300209 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
Scott Wood76b10462008-02-06 15:36:21 -0600210
211 /* Setup the FMR[OP] to execute without write protection */
212 out_be32(&lbc->fmr, priv->fmr | 3);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800213 if (elbc_fcm_ctrl->use_mdr)
214 out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr);
Scott Wood76b10462008-02-06 15:36:21 -0600215
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800216 dev_vdbg(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600217 "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n",
218 in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr));
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800219 dev_vdbg(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600220 "fsl_elbc_run_command: fbar=%08x fpar=%08x "
221 "fbcr=%08x bank=%d\n",
222 in_be32(&lbc->fbar), in_be32(&lbc->fpar),
223 in_be32(&lbc->fbcr), priv->bank);
224
Mike Hench1938de42008-03-19 12:40:15 -0500225 ctrl->irq_status = 0;
Scott Wood76b10462008-02-06 15:36:21 -0600226 /* execute special operation */
227 out_be32(&lbc->lsor, priv->bank);
228
229 /* wait for FCM complete flag or timeout */
Scott Wood76b10462008-02-06 15:36:21 -0600230 wait_event_timeout(ctrl->irq_wait, ctrl->irq_status,
231 FCM_TIMEOUT_MSECS * HZ/1000);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800232 elbc_fcm_ctrl->status = ctrl->irq_status;
Scott Wood76b10462008-02-06 15:36:21 -0600233 /* store mdr value in case it was needed */
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800234 if (elbc_fcm_ctrl->use_mdr)
235 elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr);
Scott Wood76b10462008-02-06 15:36:21 -0600236
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800237 elbc_fcm_ctrl->use_mdr = 0;
Scott Wood76b10462008-02-06 15:36:21 -0600238
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800239 if (elbc_fcm_ctrl->status != LTESR_CC) {
240 dev_info(priv->dev,
Scott Woodc1317f72009-11-13 14:14:15 -0600241 "command failed: fir %x fcr %x status %x mdr %x\n",
242 in_be32(&lbc->fir), in_be32(&lbc->fcr),
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800243 elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr);
Scott Woodc1317f72009-11-13 14:14:15 -0600244 return -EIO;
245 }
Scott Wood76b10462008-02-06 15:36:21 -0600246
Michael Henchf975c6b2011-07-26 15:07:42 -0500247 if (chip->ecc.mode != NAND_ECC_HW)
248 return 0;
249
Mike Dunn3f91e942012-04-25 12:06:09 -0700250 elbc_fcm_ctrl->max_bitflips = 0;
251
Michael Henchf975c6b2011-07-26 15:07:42 -0500252 if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) {
253 uint32_t lteccr = in_be32(&lbc->lteccr);
254 /*
255 * if command was a full page read and the ELBC
256 * has the LTECCR register, then bits 12-15 (ppc order) of
257 * LTECCR indicates which 512 byte sub-pages had fixed errors.
258 * bits 28-31 are uncorrectable errors, marked elsewhere.
259 * for small page nand only 1 bit is used.
260 * if the ELBC doesn't have the lteccr register it reads 0
Mike Dunn3f91e942012-04-25 12:06:09 -0700261 * FIXME: 4 bits can be corrected on NANDs with 2k pages, so
262 * count the number of sub-pages with bitflips and update
263 * ecc_stats.corrected accordingly.
Michael Henchf975c6b2011-07-26 15:07:42 -0500264 */
265 if (lteccr & 0x000F000F)
266 out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */
Mike Dunn3f91e942012-04-25 12:06:09 -0700267 if (lteccr & 0x000F0000) {
Michael Henchf975c6b2011-07-26 15:07:42 -0500268 mtd->ecc_stats.corrected++;
Mike Dunn3f91e942012-04-25 12:06:09 -0700269 elbc_fcm_ctrl->max_bitflips = 1;
270 }
Michael Henchf975c6b2011-07-26 15:07:42 -0500271 }
272
Scott Woodc1317f72009-11-13 14:14:15 -0600273 return 0;
Scott Wood76b10462008-02-06 15:36:21 -0600274}
275
276static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
277{
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100278 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800279 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
Anton Vorontsovd4a32fe2008-03-11 20:23:28 +0300280 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
Scott Wood76b10462008-02-06 15:36:21 -0600281
282 if (priv->page_size) {
283 out_be32(&lbc->fir,
Scott Wood476459a2009-11-13 14:13:01 -0600284 (FIR_OP_CM0 << FIR_OP0_SHIFT) |
Scott Wood76b10462008-02-06 15:36:21 -0600285 (FIR_OP_CA << FIR_OP1_SHIFT) |
286 (FIR_OP_PA << FIR_OP2_SHIFT) |
Scott Wood476459a2009-11-13 14:13:01 -0600287 (FIR_OP_CM1 << FIR_OP3_SHIFT) |
Scott Wood76b10462008-02-06 15:36:21 -0600288 (FIR_OP_RBW << FIR_OP4_SHIFT));
289
290 out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
291 (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
292 } else {
293 out_be32(&lbc->fir,
Scott Wood476459a2009-11-13 14:13:01 -0600294 (FIR_OP_CM0 << FIR_OP0_SHIFT) |
Scott Wood76b10462008-02-06 15:36:21 -0600295 (FIR_OP_CA << FIR_OP1_SHIFT) |
296 (FIR_OP_PA << FIR_OP2_SHIFT) |
297 (FIR_OP_RBW << FIR_OP3_SHIFT));
298
299 if (oob)
300 out_be32(&lbc->fcr, NAND_CMD_READOOB << FCR_CMD0_SHIFT);
301 else
302 out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT);
303 }
304}
305
306/* cmdfunc send commands to the FCM */
Boris Brezillon5295cf22018-09-06 14:05:28 +0200307static void fsl_elbc_cmdfunc(struct nand_chip *chip, unsigned int command,
Scott Wood76b10462008-02-06 15:36:21 -0600308 int column, int page_addr)
309{
Boris Brezillon5295cf22018-09-06 14:05:28 +0200310 struct mtd_info *mtd = nand_to_mtd(chip);
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100311 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800312 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
313 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
Anton Vorontsovd4a32fe2008-03-11 20:23:28 +0300314 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
Scott Wood76b10462008-02-06 15:36:21 -0600315
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800316 elbc_fcm_ctrl->use_mdr = 0;
Scott Wood76b10462008-02-06 15:36:21 -0600317
318 /* clear the read buffer */
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800319 elbc_fcm_ctrl->read_bytes = 0;
Scott Wood76b10462008-02-06 15:36:21 -0600320 if (command != NAND_CMD_PAGEPROG)
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800321 elbc_fcm_ctrl->index = 0;
Scott Wood76b10462008-02-06 15:36:21 -0600322
323 switch (command) {
324 /* READ0 and READ1 read the entire buffer to use hardware ECC. */
325 case NAND_CMD_READ1:
326 column += 256;
327
328 /* fall-through */
329 case NAND_CMD_READ0:
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800330 dev_dbg(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600331 "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:"
332 " 0x%x, column: 0x%x.\n", page_addr, column);
333
334
335 out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */
336 set_addr(mtd, 0, page_addr, 0);
337
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800338 elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
339 elbc_fcm_ctrl->index += column;
Scott Wood76b10462008-02-06 15:36:21 -0600340
341 fsl_elbc_do_read(chip, 0);
342 fsl_elbc_run_command(mtd);
343 return;
344
Marek Behún070fb972019-03-22 14:26:18 +0100345 /* RNDOUT moves the pointer inside the page */
346 case NAND_CMD_RNDOUT:
347 dev_dbg(priv->dev,
348 "fsl_elbc_cmdfunc: NAND_CMD_RNDOUT, column: 0x%x.\n",
349 column);
350
351 elbc_fcm_ctrl->index = column;
352 return;
353
Scott Wood76b10462008-02-06 15:36:21 -0600354 /* READOOB reads only the OOB because no ECC is performed. */
355 case NAND_CMD_READOOB:
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800356 dev_vdbg(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600357 "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:"
358 " 0x%x, column: 0x%x.\n", page_addr, column);
359
360 out_be32(&lbc->fbcr, mtd->oobsize - column);
361 set_addr(mtd, column, page_addr, 1);
362
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800363 elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize;
Scott Wood76b10462008-02-06 15:36:21 -0600364
365 fsl_elbc_do_read(chip, 1);
366 fsl_elbc_run_command(mtd);
367 return;
368
Scott Wood76b10462008-02-06 15:36:21 -0600369 case NAND_CMD_READID:
Shengzhou Liuf57eb5c2011-12-12 17:40:53 +0800370 case NAND_CMD_PARAM:
371 dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command);
Scott Wood76b10462008-02-06 15:36:21 -0600372
Scott Wood476459a2009-11-13 14:13:01 -0600373 out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) |
Scott Wood76b10462008-02-06 15:36:21 -0600374 (FIR_OP_UA << FIR_OP1_SHIFT) |
375 (FIR_OP_RBW << FIR_OP2_SHIFT));
Shengzhou Liuf57eb5c2011-12-12 17:40:53 +0800376 out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT);
377 /*
378 * although currently it's 8 bytes for READID, we always read
379 * the maximum 256 bytes(for PARAM)
380 */
381 out_be32(&lbc->fbcr, 256);
382 elbc_fcm_ctrl->read_bytes = 256;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800383 elbc_fcm_ctrl->use_mdr = 1;
Shengzhou Liuf57eb5c2011-12-12 17:40:53 +0800384 elbc_fcm_ctrl->mdr = column;
Scott Wood76b10462008-02-06 15:36:21 -0600385 set_addr(mtd, 0, 0, 0);
386 fsl_elbc_run_command(mtd);
387 return;
388
389 /* ERASE1 stores the block and page address */
390 case NAND_CMD_ERASE1:
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800391 dev_vdbg(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600392 "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, "
393 "page_addr: 0x%x.\n", page_addr);
394 set_addr(mtd, 0, page_addr, 0);
395 return;
396
397 /* ERASE2 uses the block and page address from ERASE1 */
398 case NAND_CMD_ERASE2:
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800399 dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n");
Scott Wood76b10462008-02-06 15:36:21 -0600400
401 out_be32(&lbc->fir,
Scott Wood476459a2009-11-13 14:13:01 -0600402 (FIR_OP_CM0 << FIR_OP0_SHIFT) |
Scott Wood76b10462008-02-06 15:36:21 -0600403 (FIR_OP_PA << FIR_OP1_SHIFT) |
Scott Wood476459a2009-11-13 14:13:01 -0600404 (FIR_OP_CM2 << FIR_OP2_SHIFT) |
405 (FIR_OP_CW1 << FIR_OP3_SHIFT) |
406 (FIR_OP_RS << FIR_OP4_SHIFT));
Scott Wood76b10462008-02-06 15:36:21 -0600407
408 out_be32(&lbc->fcr,
409 (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) |
Scott Wood476459a2009-11-13 14:13:01 -0600410 (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
411 (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT));
Scott Wood76b10462008-02-06 15:36:21 -0600412
413 out_be32(&lbc->fbcr, 0);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800414 elbc_fcm_ctrl->read_bytes = 0;
415 elbc_fcm_ctrl->use_mdr = 1;
Scott Wood76b10462008-02-06 15:36:21 -0600416
417 fsl_elbc_run_command(mtd);
418 return;
419
420 /* SEQIN sets up the addr buffer and all registers except the length */
421 case NAND_CMD_SEQIN: {
422 __be32 fcr;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800423 dev_vdbg(priv->dev,
424 "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, "
Scott Wood76b10462008-02-06 15:36:21 -0600425 "page_addr: 0x%x, column: 0x%x.\n",
426 page_addr, column);
427
Sergej.Stepanov@ids.deeeda6672010-11-23 18:38:36 +0100428 elbc_fcm_ctrl->column = column;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800429 elbc_fcm_ctrl->use_mdr = 1;
Scott Wood476459a2009-11-13 14:13:01 -0600430
Liu Shuoa9a552f2011-12-04 12:31:36 +0800431 if (column >= mtd->writesize) {
432 /* OOB area */
433 column -= mtd->writesize;
434 elbc_fcm_ctrl->oob = 1;
435 } else {
436 WARN_ON(column != 0);
437 elbc_fcm_ctrl->oob = 0;
438 }
439
Scott Wood476459a2009-11-13 14:13:01 -0600440 fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
441 (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) |
442 (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT);
Scott Wood76b10462008-02-06 15:36:21 -0600443
Scott Wood76b10462008-02-06 15:36:21 -0600444 if (priv->page_size) {
445 out_be32(&lbc->fir,
Scott Wood476459a2009-11-13 14:13:01 -0600446 (FIR_OP_CM2 << FIR_OP0_SHIFT) |
Scott Wood76b10462008-02-06 15:36:21 -0600447 (FIR_OP_CA << FIR_OP1_SHIFT) |
448 (FIR_OP_PA << FIR_OP2_SHIFT) |
449 (FIR_OP_WB << FIR_OP3_SHIFT) |
Scott Wood476459a2009-11-13 14:13:01 -0600450 (FIR_OP_CM3 << FIR_OP4_SHIFT) |
451 (FIR_OP_CW1 << FIR_OP5_SHIFT) |
452 (FIR_OP_RS << FIR_OP6_SHIFT));
Scott Wood76b10462008-02-06 15:36:21 -0600453 } else {
454 out_be32(&lbc->fir,
Scott Wood476459a2009-11-13 14:13:01 -0600455 (FIR_OP_CM0 << FIR_OP0_SHIFT) |
Scott Wood76b10462008-02-06 15:36:21 -0600456 (FIR_OP_CM2 << FIR_OP1_SHIFT) |
457 (FIR_OP_CA << FIR_OP2_SHIFT) |
458 (FIR_OP_PA << FIR_OP3_SHIFT) |
459 (FIR_OP_WB << FIR_OP4_SHIFT) |
Scott Wood476459a2009-11-13 14:13:01 -0600460 (FIR_OP_CM3 << FIR_OP5_SHIFT) |
461 (FIR_OP_CW1 << FIR_OP6_SHIFT) |
462 (FIR_OP_RS << FIR_OP7_SHIFT));
Scott Wood76b10462008-02-06 15:36:21 -0600463
Liu Shuoa9a552f2011-12-04 12:31:36 +0800464 if (elbc_fcm_ctrl->oob)
Scott Wood76b10462008-02-06 15:36:21 -0600465 /* OOB area --> READOOB */
Scott Wood76b10462008-02-06 15:36:21 -0600466 fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT;
Liu Shuoa9a552f2011-12-04 12:31:36 +0800467 else
Scott Wood76b10462008-02-06 15:36:21 -0600468 /* First 256 bytes --> READ0 */
469 fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT;
Scott Wood76b10462008-02-06 15:36:21 -0600470 }
471
472 out_be32(&lbc->fcr, fcr);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800473 set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob);
Scott Wood76b10462008-02-06 15:36:21 -0600474 return;
475 }
476
477 /* PAGEPROG reuses all of the setup from SEQIN and adds the length */
478 case NAND_CMD_PAGEPROG: {
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800479 dev_vdbg(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600480 "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG "
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800481 "writing %d bytes.\n", elbc_fcm_ctrl->index);
Scott Wood76b10462008-02-06 15:36:21 -0600482
483 /* if the write did not start at 0 or is not a full page
484 * then set the exact length, otherwise use a full page
485 * write so the HW generates the ECC.
486 */
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800487 if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 ||
Mike Hench52a474d2011-07-05 19:14:48 -0400488 elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize)
Liu Shuoe32de762011-12-04 12:31:37 +0800489 out_be32(&lbc->fbcr,
490 elbc_fcm_ctrl->index - elbc_fcm_ctrl->column);
Mike Hench52a474d2011-07-05 19:14:48 -0400491 else
Scott Wood76b10462008-02-06 15:36:21 -0600492 out_be32(&lbc->fbcr, 0);
Scott Wood76b10462008-02-06 15:36:21 -0600493
494 fsl_elbc_run_command(mtd);
Scott Wood76b10462008-02-06 15:36:21 -0600495 return;
496 }
497
498 /* CMD_STATUS must read the status byte while CEB is active */
499 /* Note - it does not wait for the ready line */
500 case NAND_CMD_STATUS:
501 out_be32(&lbc->fir,
502 (FIR_OP_CM0 << FIR_OP0_SHIFT) |
503 (FIR_OP_RBW << FIR_OP1_SHIFT));
504 out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT);
505 out_be32(&lbc->fbcr, 1);
506 set_addr(mtd, 0, 0, 0);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800507 elbc_fcm_ctrl->read_bytes = 1;
Scott Wood76b10462008-02-06 15:36:21 -0600508
509 fsl_elbc_run_command(mtd);
510
511 /* The chip always seems to report that it is
512 * write-protected, even when it is not.
513 */
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800514 setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP);
Scott Wood76b10462008-02-06 15:36:21 -0600515 return;
516
517 /* RESET without waiting for the ready line */
518 case NAND_CMD_RESET:
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800519 dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n");
Scott Wood76b10462008-02-06 15:36:21 -0600520 out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT);
521 out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT);
522 fsl_elbc_run_command(mtd);
523 return;
524
525 default:
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800526 dev_err(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600527 "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n",
528 command);
529 }
530}
531
Boris Brezillon758b56f2018-09-06 14:05:24 +0200532static void fsl_elbc_select_chip(struct nand_chip *chip, int cs)
Scott Wood76b10462008-02-06 15:36:21 -0600533{
534 /* The hardware does not seem to support multiple
535 * chips per bank.
536 */
537}
538
539/*
540 * Write buf to the FCM Controller Data Buffer
541 */
Boris Brezillonc0739d82018-09-06 14:05:23 +0200542static void fsl_elbc_write_buf(struct nand_chip *chip, const u8 *buf, int len)
Scott Wood76b10462008-02-06 15:36:21 -0600543{
Boris Brezillonc0739d82018-09-06 14:05:23 +0200544 struct mtd_info *mtd = nand_to_mtd(chip);
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100545 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800546 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
Scott Wood76b10462008-02-06 15:36:21 -0600547 unsigned int bufsize = mtd->writesize + mtd->oobsize;
548
Anton Vorontsov0ff66312008-03-28 22:10:54 +0300549 if (len <= 0) {
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800550 dev_err(priv->dev, "write_buf of %d bytes", len);
551 elbc_fcm_ctrl->status = 0;
Scott Wood76b10462008-02-06 15:36:21 -0600552 return;
553 }
554
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800555 if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) {
556 dev_err(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600557 "write_buf beyond end of buffer "
558 "(%d requested, %u available)\n",
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800559 len, bufsize - elbc_fcm_ctrl->index);
560 len = bufsize - elbc_fcm_ctrl->index;
Scott Wood76b10462008-02-06 15:36:21 -0600561 }
562
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800563 memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len);
Anton Vorontsov0ff66312008-03-28 22:10:54 +0300564 /*
565 * This is workaround for the weird elbc hangs during nand write,
566 * Scott Wood says: "...perhaps difference in how long it takes a
567 * write to make it through the localbus compared to a write to IMMR
568 * is causing problems, and sync isn't helping for some reason."
569 * Reading back the last byte helps though.
570 */
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800571 in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1);
Anton Vorontsov0ff66312008-03-28 22:10:54 +0300572
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800573 elbc_fcm_ctrl->index += len;
Scott Wood76b10462008-02-06 15:36:21 -0600574}
575
576/*
577 * read a byte from either the FCM hardware buffer if it has any data left
578 * otherwise issue a command to read a single byte.
579 */
Boris Brezillon7e534322018-09-06 14:05:22 +0200580static u8 fsl_elbc_read_byte(struct nand_chip *chip)
Scott Wood76b10462008-02-06 15:36:21 -0600581{
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100582 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800583 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
Scott Wood76b10462008-02-06 15:36:21 -0600584
585 /* If there are still bytes in the FCM, then use the next byte. */
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800586 if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes)
587 return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]);
Scott Wood76b10462008-02-06 15:36:21 -0600588
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800589 dev_err(priv->dev, "read_byte beyond end of buffer\n");
Scott Wood76b10462008-02-06 15:36:21 -0600590 return ERR_BYTE;
591}
592
593/*
594 * Read from the FCM Controller Data Buffer
595 */
Boris Brezillon7e534322018-09-06 14:05:22 +0200596static void fsl_elbc_read_buf(struct nand_chip *chip, u8 *buf, int len)
Scott Wood76b10462008-02-06 15:36:21 -0600597{
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100598 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800599 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
Scott Wood76b10462008-02-06 15:36:21 -0600600 int avail;
601
602 if (len < 0)
603 return;
604
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800605 avail = min((unsigned int)len,
606 elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index);
607 memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail);
608 elbc_fcm_ctrl->index += avail;
Scott Wood76b10462008-02-06 15:36:21 -0600609
610 if (len > avail)
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800611 dev_err(priv->dev,
Scott Wood76b10462008-02-06 15:36:21 -0600612 "read_buf beyond end of buffer "
613 "(%d requested, %d available)\n",
614 len, avail);
615}
616
Scott Wood76b10462008-02-06 15:36:21 -0600617/* This function is called after Program and Erase Operations to
618 * check for success or failure.
619 */
Boris Brezillonf1d46942018-09-06 14:05:29 +0200620static int fsl_elbc_wait(struct nand_chip *chip)
Scott Wood76b10462008-02-06 15:36:21 -0600621{
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100622 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800623 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
Scott Wood76b10462008-02-06 15:36:21 -0600624
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800625 if (elbc_fcm_ctrl->status != LTESR_CC)
Scott Wood76b10462008-02-06 15:36:21 -0600626 return NAND_STATUS_FAIL;
627
628 /* The chip always seems to report that it is
629 * write-protected, even when it is not.
630 */
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800631 return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
Scott Wood76b10462008-02-06 15:36:21 -0600632}
633
Boris Brezillonb9761682018-09-06 14:05:20 +0200634static int fsl_elbc_read_page(struct nand_chip *chip, uint8_t *buf,
635 int oob_required, int page)
Scott Wood76b10462008-02-06 15:36:21 -0600636{
Boris Brezillonb9761682018-09-06 14:05:20 +0200637 struct mtd_info *mtd = nand_to_mtd(chip);
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100638 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
Mike Dunn3f91e942012-04-25 12:06:09 -0700639 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
640 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
641
Boris Brezillon25f815f2017-11-30 18:01:30 +0100642 nand_read_page_op(chip, page, 0, buf, mtd->writesize);
Brian Norrisd112dc72012-05-02 10:15:00 -0700643 if (oob_required)
Boris Brezillon7e534322018-09-06 14:05:22 +0200644 fsl_elbc_read_buf(chip, chip->oob_poi, mtd->oobsize);
Scott Wood76b10462008-02-06 15:36:21 -0600645
Boris Brezillonf1d46942018-09-06 14:05:29 +0200646 if (fsl_elbc_wait(chip) & NAND_STATUS_FAIL)
Scott Wood76b10462008-02-06 15:36:21 -0600647 mtd->ecc_stats.failed++;
648
Mike Dunn3f91e942012-04-25 12:06:09 -0700649 return elbc_fcm_ctrl->max_bitflips;
Scott Wood76b10462008-02-06 15:36:21 -0600650}
651
652/* ECC will be calculated automatically, and errors will be detected in
653 * waitfunc.
654 */
Boris Brezillon767eb6f2018-09-06 14:05:21 +0200655static int fsl_elbc_write_page(struct nand_chip *chip, const uint8_t *buf,
656 int oob_required, int page)
Scott Wood76b10462008-02-06 15:36:21 -0600657{
Boris Brezillon767eb6f2018-09-06 14:05:21 +0200658 struct mtd_info *mtd = nand_to_mtd(chip);
659
Boris Brezillon25f815f2017-11-30 18:01:30 +0100660 nand_prog_page_begin_op(chip, page, 0, buf, mtd->writesize);
Boris Brezillonc0739d82018-09-06 14:05:23 +0200661 fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize);
Josh Wufdbad98d2012-06-25 18:07:45 +0800662
Boris Brezillon25f815f2017-11-30 18:01:30 +0100663 return nand_prog_page_end_op(chip);
Scott Wood76b10462008-02-06 15:36:21 -0600664}
665
Pekon Guptaf034d872014-05-06 09:41:32 +0530666/* ECC will be calculated automatically, and errors will be detected in
667 * waitfunc.
668 */
Boris Brezillon767eb6f2018-09-06 14:05:21 +0200669static int fsl_elbc_write_subpage(struct nand_chip *chip, uint32_t offset,
670 uint32_t data_len, const uint8_t *buf,
671 int oob_required, int page)
Pekon Guptaf034d872014-05-06 09:41:32 +0530672{
Boris Brezillon767eb6f2018-09-06 14:05:21 +0200673 struct mtd_info *mtd = nand_to_mtd(chip);
674
Boris Brezillon25f815f2017-11-30 18:01:30 +0100675 nand_prog_page_begin_op(chip, page, 0, NULL, 0);
Boris Brezillonc0739d82018-09-06 14:05:23 +0200676 fsl_elbc_write_buf(chip, buf, mtd->writesize);
677 fsl_elbc_write_buf(chip, chip->oob_poi, mtd->oobsize);
Boris Brezillon25f815f2017-11-30 18:01:30 +0100678 return nand_prog_page_end_op(chip);
Pekon Guptaf034d872014-05-06 09:41:32 +0530679}
680
Scott Wood76b10462008-02-06 15:36:21 -0600681static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
682{
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800683 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
Anton Vorontsovd4a32fe2008-03-11 20:23:28 +0300684 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800685 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
Scott Wood76b10462008-02-06 15:36:21 -0600686 struct nand_chip *chip = &priv->chip;
Boris BREZILLON18ba50c2015-12-10 09:00:02 +0100687 struct mtd_info *mtd = nand_to_mtd(chip);
Scott Wood76b10462008-02-06 15:36:21 -0600688
689 dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank);
690
691 /* Fill in fsl_elbc_mtd structure */
Boris BREZILLON18ba50c2015-12-10 09:00:02 +0100692 mtd->dev.parent = priv->dev;
Brian Norrisa61ae812015-10-30 20:33:25 -0700693 nand_set_flash_node(chip, priv->dev->of_node);
Jason Jin03ed1072008-12-09 14:32:31 +0800694
Shengzhou Liud8251102011-12-12 17:40:52 +0800695 /* set timeout to maximum */
696 priv->fmr = 15 << FMR_CWTO_SHIFT;
697 if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS)
698 priv->fmr |= FMR_ECCM;
Scott Wood76b10462008-02-06 15:36:21 -0600699
700 /* fill in nand_chip structure */
701 /* set up function call table */
Boris Brezillon716bbba2018-09-07 00:38:35 +0200702 chip->legacy.read_byte = fsl_elbc_read_byte;
703 chip->legacy.write_buf = fsl_elbc_write_buf;
704 chip->legacy.read_buf = fsl_elbc_read_buf;
Boris Brezillon7d6c37e2018-11-11 08:55:22 +0100705 chip->legacy.select_chip = fsl_elbc_select_chip;
Boris Brezillonbf6065c2018-09-07 00:38:36 +0200706 chip->legacy.cmdfunc = fsl_elbc_cmdfunc;
Boris Brezillon8395b752018-09-07 00:38:37 +0200707 chip->legacy.waitfunc = fsl_elbc_wait;
Boris Brezillon45240362018-09-07 00:38:40 +0200708 chip->legacy.set_features = nand_get_set_features_notsupp;
709 chip->legacy.get_features = nand_get_set_features_notsupp;
Scott Wood76b10462008-02-06 15:36:21 -0600710
Anton Vorontsovec6e0ea2008-06-27 23:04:13 +0400711 chip->bbt_td = &bbt_main_descr;
712 chip->bbt_md = &bbt_mirror_descr;
713
Scott Wood76b10462008-02-06 15:36:21 -0600714 /* set up nand options */
Brian Norrisbb9ebd42011-05-31 16:31:23 -0700715 chip->bbt_options = NAND_BBT_USE_FLASH;
Scott Wood76b10462008-02-06 15:36:21 -0600716
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800717 chip->controller = &elbc_fcm_ctrl->controller;
Boris BREZILLONd699ed22015-12-10 09:00:41 +0100718 nand_set_controller_data(chip, priv);
Scott Wood76b10462008-02-06 15:36:21 -0600719
Scott Wood76b10462008-02-06 15:36:21 -0600720 return 0;
721}
722
Marek Behún9fed3112019-03-22 14:26:17 +0100723static int fsl_elbc_attach_chip(struct nand_chip *chip)
724{
725 struct mtd_info *mtd = nand_to_mtd(chip);
726 struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
727 struct fsl_lbc_ctrl *ctrl = priv->ctrl;
728 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
729 unsigned int al;
730
Marek Behúnf6424c22019-03-22 14:26:19 +0100731 switch (chip->ecc.mode) {
732 /*
733 * if ECC was not chosen in DT, decide whether to use HW or SW ECC from
734 * CS Base Register
735 */
736 case NAND_ECC_NONE:
737 /* If CS Base Register selects full hardware ECC then use it */
738 if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) ==
739 BR_DECC_CHK_GEN) {
740 chip->ecc.read_page = fsl_elbc_read_page;
741 chip->ecc.write_page = fsl_elbc_write_page;
742 chip->ecc.write_subpage = fsl_elbc_write_subpage;
743
744 chip->ecc.mode = NAND_ECC_HW;
745 mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops);
746 chip->ecc.size = 512;
747 chip->ecc.bytes = 3;
748 chip->ecc.strength = 1;
749 } else {
750 /* otherwise fall back to default software ECC */
751 chip->ecc.mode = NAND_ECC_SOFT;
752 chip->ecc.algo = NAND_ECC_HAMMING;
753 }
754 break;
755
756 /* if SW ECC was chosen in DT, we do not need to set anything here */
757 case NAND_ECC_SOFT:
758 break;
759
760 /* should we also implement NAND_ECC_HW to do as the code above? */
761 default:
762 return -EINVAL;
763 }
764
Marek Behún9fed3112019-03-22 14:26:17 +0100765 /* calculate FMR Address Length field */
766 al = 0;
767 if (chip->pagemask & 0xffff0000)
768 al++;
769 if (chip->pagemask & 0xff000000)
770 al++;
771
772 priv->fmr |= al << FMR_AL_SHIFT;
773
774 dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n",
775 nanddev_ntargets(&chip->base));
776 dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
777 nanddev_target_size(&chip->base));
778 dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
779 chip->pagemask);
780 dev_dbg(priv->dev, "fsl_elbc_init: nand->legacy.chip_delay = %d\n",
781 chip->legacy.chip_delay);
782 dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n",
783 chip->badblockpos);
784 dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n",
785 chip->chip_shift);
786 dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n",
787 chip->page_shift);
788 dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n",
789 chip->phys_erase_shift);
790 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n",
791 chip->ecc.mode);
792 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n",
793 chip->ecc.steps);
794 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n",
795 chip->ecc.bytes);
796 dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n",
797 chip->ecc.total);
798 dev_dbg(priv->dev, "fsl_elbc_init: mtd->ooblayout = %p\n",
799 mtd->ooblayout);
800 dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
801 dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
802 dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
803 mtd->erasesize);
804 dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n",
805 mtd->writesize);
806 dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n",
807 mtd->oobsize);
808
809 /* adjust Option Register and ECC to match Flash page size */
810 if (mtd->writesize == 512) {
811 priv->page_size = 0;
812 clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
813 } else if (mtd->writesize == 2048) {
814 priv->page_size = 1;
815 setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS);
816 } else {
817 dev_err(priv->dev,
818 "fsl_elbc_init: page size %d is not supported\n",
819 mtd->writesize);
820 return -ENOTSUPP;
821 }
822
823 return 0;
824}
825
826static const struct nand_controller_ops fsl_elbc_controller_ops = {
827 .attach_chip = fsl_elbc_attach_chip,
828};
829
Scott Wood76b10462008-02-06 15:36:21 -0600830static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
831{
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800832 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand;
Boris BREZILLON18ba50c2015-12-10 09:00:02 +0100833 struct mtd_info *mtd = nand_to_mtd(&priv->chip);
Scott Wood76b10462008-02-06 15:36:21 -0600834
Boris BREZILLON18ba50c2015-12-10 09:00:02 +0100835 kfree(mtd->name);
Anton Vorontsov9ebed3e2008-03-18 19:34:03 +0300836
Scott Wood76b10462008-02-06 15:36:21 -0600837 if (priv->vbase)
838 iounmap(priv->vbase);
839
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800840 elbc_fcm_ctrl->chips[priv->bank] = NULL;
Scott Wood76b10462008-02-06 15:36:21 -0600841 kfree(priv);
Scott Wood76b10462008-02-06 15:36:21 -0600842 return 0;
843}
844
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800845static DEFINE_MUTEX(fsl_elbc_nand_mutex);
846
Bill Pemberton06f25512012-11-19 13:23:07 -0500847static int fsl_elbc_nand_probe(struct platform_device *pdev)
Scott Wood76b10462008-02-06 15:36:21 -0600848{
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800849 struct fsl_lbc_regs __iomem *lbc;
Scott Wood76b10462008-02-06 15:36:21 -0600850 struct fsl_elbc_mtd *priv;
851 struct resource res;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800852 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
Scott Wood76b10462008-02-06 15:36:21 -0600853 static const char *part_probe_types[]
Dmitry Eremin-Solenikovb6b0fae2011-05-30 01:02:22 +0400854 = { "cmdlinepart", "RedBoot", "ofpart", NULL };
Scott Wood76b10462008-02-06 15:36:21 -0600855 int ret;
856 int bank;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800857 struct device *dev;
858 struct device_node *node = pdev->dev.of_node;
Boris BREZILLON18ba50c2015-12-10 09:00:02 +0100859 struct mtd_info *mtd;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800860
861 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
862 return -ENODEV;
863 lbc = fsl_lbc_ctrl_dev->regs;
864 dev = fsl_lbc_ctrl_dev->dev;
Scott Wood76b10462008-02-06 15:36:21 -0600865
866 /* get, allocate and map the memory resource */
867 ret = of_address_to_resource(node, 0, &res);
868 if (ret) {
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800869 dev_err(dev, "failed to get resource\n");
Scott Wood76b10462008-02-06 15:36:21 -0600870 return ret;
871 }
872
873 /* find which chip select it is connected to */
874 for (bank = 0; bank < MAX_BANKS; bank++)
875 if ((in_be32(&lbc->bank[bank].br) & BR_V) &&
876 (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM &&
877 (in_be32(&lbc->bank[bank].br) &
878 in_be32(&lbc->bank[bank].or) & BR_BA)
Lan Chunhe-B258060b824d22010-10-18 15:22:32 +0800879 == fsl_lbc_addr(res.start))
Scott Wood76b10462008-02-06 15:36:21 -0600880 break;
881
882 if (bank >= MAX_BANKS) {
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800883 dev_err(dev, "address did not match any chip selects\n");
Scott Wood76b10462008-02-06 15:36:21 -0600884 return -ENODEV;
885 }
886
887 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
888 if (!priv)
889 return -ENOMEM;
890
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800891 mutex_lock(&fsl_elbc_nand_mutex);
892 if (!fsl_lbc_ctrl_dev->nand) {
893 elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL);
894 if (!elbc_fcm_ctrl) {
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800895 mutex_unlock(&fsl_elbc_nand_mutex);
896 ret = -ENOMEM;
897 goto err;
898 }
899 elbc_fcm_ctrl->counter++;
900
Miquel Raynal7da45132018-07-17 09:08:02 +0200901 nand_controller_init(&elbc_fcm_ctrl->controller);
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800902 fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl;
903 } else {
904 elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
905 }
906 mutex_unlock(&fsl_elbc_nand_mutex);
907
908 elbc_fcm_ctrl->chips[bank] = priv;
Scott Wood76b10462008-02-06 15:36:21 -0600909 priv->bank = bank;
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800910 priv->ctrl = fsl_lbc_ctrl_dev;
Scott Wood874d72c2012-06-06 18:36:39 -0500911 priv->dev = &pdev->dev;
912 dev_set_drvdata(priv->dev, priv);
Scott Wood76b10462008-02-06 15:36:21 -0600913
H Hartley Sweeten8a19b552009-12-14 16:19:44 -0500914 priv->vbase = ioremap(res.start, resource_size(&res));
Scott Wood76b10462008-02-06 15:36:21 -0600915 if (!priv->vbase) {
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800916 dev_err(dev, "failed to map chip region\n");
Scott Wood76b10462008-02-06 15:36:21 -0600917 ret = -ENOMEM;
918 goto err;
919 }
920
Boris BREZILLON18ba50c2015-12-10 09:00:02 +0100921 mtd = nand_to_mtd(&priv->chip);
922 mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start);
923 if (!nand_to_mtd(&priv->chip)->name) {
Anton Vorontsov9ebed3e2008-03-18 19:34:03 +0300924 ret = -ENOMEM;
925 goto err;
926 }
927
Scott Wood76b10462008-02-06 15:36:21 -0600928 ret = fsl_elbc_chip_init(priv);
929 if (ret)
930 goto err;
931
Miquel Raynal5bf3e762018-07-25 10:37:40 +0200932 priv->chip.controller->ops = &fsl_elbc_controller_ops;
Boris Brezillon00ad3782018-09-06 14:05:14 +0200933 ret = nand_scan(&priv->chip, 1);
Scott Wood76b10462008-02-06 15:36:21 -0600934 if (ret)
935 goto err;
936
Scott Wood76b10462008-02-06 15:36:21 -0600937 /* First look for RedBoot table or partitions on the command
938 * line, these take precedence over device tree information */
Miquel Raynal39b77c52018-04-21 20:00:34 +0200939 ret = mtd_device_parse_register(mtd, part_probe_types, NULL, NULL, 0);
940 if (ret)
941 goto cleanup_nand;
Scott Wood76b10462008-02-06 15:36:21 -0600942
Shreeya Patel63fa37f2018-02-22 22:01:22 +0530943 pr_info("eLBC NAND device at 0x%llx, bank %d\n",
944 (unsigned long long)res.start, priv->bank);
Miquel Raynal39b77c52018-04-21 20:00:34 +0200945
Scott Wood76b10462008-02-06 15:36:21 -0600946 return 0;
947
Miquel Raynal39b77c52018-04-21 20:00:34 +0200948cleanup_nand:
949 nand_cleanup(&priv->chip);
Scott Wood76b10462008-02-06 15:36:21 -0600950err:
951 fsl_elbc_chip_remove(priv);
Miquel Raynal39b77c52018-04-21 20:00:34 +0200952
Scott Wood76b10462008-02-06 15:36:21 -0600953 return ret;
954}
955
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800956static int fsl_elbc_nand_remove(struct platform_device *pdev)
Scott Wood76b10462008-02-06 15:36:21 -0600957{
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800958 struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand;
Scott Wood874d72c2012-06-06 18:36:39 -0500959 struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev);
960
Boris Brezillon59ac2762018-09-06 14:05:15 +0200961 nand_release(&priv->chip);
Scott Wood874d72c2012-06-06 18:36:39 -0500962 fsl_elbc_chip_remove(priv);
Scott Wood76b10462008-02-06 15:36:21 -0600963
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800964 mutex_lock(&fsl_elbc_nand_mutex);
965 elbc_fcm_ctrl->counter--;
966 if (!elbc_fcm_ctrl->counter) {
967 fsl_lbc_ctrl_dev->nand = NULL;
968 kfree(elbc_fcm_ctrl);
Scott Wood76b10462008-02-06 15:36:21 -0600969 }
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800970 mutex_unlock(&fsl_elbc_nand_mutex);
Scott Wood76b10462008-02-06 15:36:21 -0600971
972 return 0;
973
Scott Wood76b10462008-02-06 15:36:21 -0600974}
975
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800976static const struct of_device_id fsl_elbc_nand_match[] = {
977 { .compatible = "fsl,elbc-fcm-nand", },
Scott Wood76b10462008-02-06 15:36:21 -0600978 {}
979};
Luis de Bethencourt030a70b2015-09-18 00:11:59 +0200980MODULE_DEVICE_TABLE(of, fsl_elbc_nand_match);
Scott Wood76b10462008-02-06 15:36:21 -0600981
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800982static struct platform_driver fsl_elbc_nand_driver = {
Scott Wood76b10462008-02-06 15:36:21 -0600983 .driver = {
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800984 .name = "fsl,elbc-fcm-nand",
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800985 .of_match_table = fsl_elbc_nand_match,
Scott Wood76b10462008-02-06 15:36:21 -0600986 },
Roy Zang3ab8f2a2010-10-18 15:22:31 +0800987 .probe = fsl_elbc_nand_probe,
988 .remove = fsl_elbc_nand_remove,
Scott Wood76b10462008-02-06 15:36:21 -0600989};
990
Axel Linf99640d2011-11-27 20:45:03 +0800991module_platform_driver(fsl_elbc_nand_driver);
Scott Wood76b10462008-02-06 15:36:21 -0600992
993MODULE_LICENSE("GPL");
994MODULE_AUTHOR("Freescale");
995MODULE_DESCRIPTION("Freescale Enhanced Local Bus Controller MTD NAND driver");