]>
Commit | Line | Data |
---|---|---|
76b10467 SW |
1 | /* Freescale Enhanced Local Bus Controller NAND driver |
2 | * | |
3ab8f2a2 | 3 | * Copyright © 2006-2007, 2010 Freescale Semiconductor |
76b10467 SW |
4 | * |
5 | * Authors: Nick Spence <nick.spence@freescale.com>, | |
6 | * Scott Wood <scottwood@freescale.com> | |
3ab8f2a2 RZ |
7 | * Jack Lan <jack.lan@freescale.com> |
8 | * Roy Zang <tie-fei.zang@freescale.com> | |
76b10467 SW |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or | |
13 | * (at your option) any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
21 | * along with this program; if not, write to the Free Software | |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 | */ | |
24 | ||
25 | #include <linux/module.h> | |
26 | #include <linux/types.h> | |
76b10467 SW |
27 | #include <linux/kernel.h> |
28 | #include <linux/string.h> | |
29 | #include <linux/ioport.h> | |
5af50730 | 30 | #include <linux/of_address.h> |
76b10467 | 31 | #include <linux/of_platform.h> |
3ab8f2a2 | 32 | #include <linux/platform_device.h> |
76b10467 SW |
33 | #include <linux/slab.h> |
34 | #include <linux/interrupt.h> | |
35 | ||
36 | #include <linux/mtd/mtd.h> | |
37 | #include <linux/mtd/nand.h> | |
38 | #include <linux/mtd/nand_ecc.h> | |
39 | #include <linux/mtd/partitions.h> | |
40 | ||
41 | #include <asm/io.h> | |
d4a32fe4 | 42 | #include <asm/fsl_lbc.h> |
76b10467 SW |
43 | |
44 | #define MAX_BANKS 8 | |
45 | #define ERR_BYTE 0xFF /* Value returned for read bytes when read failed */ | |
46 | #define FCM_TIMEOUT_MSECS 500 /* Maximum number of mSecs to wait for FCM */ | |
47 | ||
76b10467 SW |
48 | /* mtd information per set */ |
49 | ||
50 | struct fsl_elbc_mtd { | |
76b10467 | 51 | struct nand_chip chip; |
3ab8f2a2 | 52 | struct fsl_lbc_ctrl *ctrl; |
76b10467 SW |
53 | |
54 | struct device *dev; | |
55 | int bank; /* Chip select bank number */ | |
56 | u8 __iomem *vbase; /* Chip select base virtual address */ | |
57 | int page_size; /* NAND page size (0=512, 1=2048) */ | |
58 | unsigned int fmr; /* FCM Flash Mode Register value */ | |
59 | }; | |
60 | ||
25985edc | 61 | /* Freescale eLBC FCM controller information */ |
76b10467 | 62 | |
3ab8f2a2 | 63 | struct fsl_elbc_fcm_ctrl { |
76b10467 SW |
64 | struct nand_hw_control controller; |
65 | struct fsl_elbc_mtd *chips[MAX_BANKS]; | |
66 | ||
76b10467 SW |
67 | u8 __iomem *addr; /* Address of assigned FCM buffer */ |
68 | unsigned int page; /* Last page written to / read from */ | |
69 | unsigned int read_bytes; /* Number of bytes read during command */ | |
70 | unsigned int column; /* Saved column from SEQIN */ | |
71 | unsigned int index; /* Pointer to next byte to 'read' */ | |
72 | unsigned int status; /* status read from LTESR after last op */ | |
73 | unsigned int mdr; /* UPM/FCM Data Register value */ | |
74 | unsigned int use_mdr; /* Non zero if the MDR is to be set */ | |
75 | unsigned int oob; /* Non zero if operating on OOB data */ | |
3ab8f2a2 | 76 | unsigned int counter; /* counter for the initializations */ |
3f91e94f | 77 | unsigned int max_bitflips; /* Saved during READ0 cmd */ |
76b10467 SW |
78 | }; |
79 | ||
80 | /* These map to the positions used by the FCM hardware ECC generator */ | |
81 | ||
c2e197b0 BB |
82 | static int fsl_elbc_ooblayout_ecc(struct mtd_info *mtd, int section, |
83 | struct mtd_oob_region *oobregion) | |
84 | { | |
85 | struct nand_chip *chip = mtd_to_nand(mtd); | |
86 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); | |
76b10467 | 87 | |
c2e197b0 BB |
88 | if (section >= chip->ecc.steps) |
89 | return -ERANGE; | |
76b10467 | 90 | |
c2e197b0 BB |
91 | oobregion->offset = (16 * section) + 6; |
92 | if (priv->fmr & FMR_ECCM) | |
93 | oobregion->offset += 2; | |
76b10467 | 94 | |
c2e197b0 BB |
95 | oobregion->length = chip->ecc.bytes; |
96 | ||
97 | return 0; | |
98 | } | |
99 | ||
100 | static int fsl_elbc_ooblayout_free(struct mtd_info *mtd, int section, | |
101 | struct mtd_oob_region *oobregion) | |
102 | { | |
103 | struct nand_chip *chip = mtd_to_nand(mtd); | |
104 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); | |
105 | ||
106 | if (section > chip->ecc.steps) | |
107 | return -ERANGE; | |
108 | ||
109 | if (!section) { | |
110 | oobregion->offset = 0; | |
111 | if (mtd->writesize > 512) | |
112 | oobregion->offset++; | |
113 | oobregion->length = (priv->fmr & FMR_ECCM) ? 7 : 5; | |
114 | } else { | |
115 | oobregion->offset = (16 * section) - | |
116 | ((priv->fmr & FMR_ECCM) ? 5 : 7); | |
117 | if (section < chip->ecc.steps) | |
118 | oobregion->length = 13; | |
119 | else | |
120 | oobregion->length = mtd->oobsize - oobregion->offset; | |
121 | } | |
122 | ||
123 | return 0; | |
124 | } | |
125 | ||
126 | static const struct mtd_ooblayout_ops fsl_elbc_ooblayout_ops = { | |
127 | .ecc = fsl_elbc_ooblayout_ecc, | |
128 | .free = fsl_elbc_ooblayout_free, | |
76b10467 SW |
129 | }; |
130 | ||
ec6e0ea3 AV |
131 | /* |
132 | * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt, | |
133 | * interfere with ECC positions, that's why we implement our own descriptors. | |
134 | * OOB {11, 5}, works for both SP and LP chips, with ECCM = 1 and ECCM = 0. | |
135 | */ | |
136 | static u8 bbt_pattern[] = {'B', 'b', 't', '0' }; | |
137 | static u8 mirror_pattern[] = {'1', 't', 'b', 'B' }; | |
138 | ||
139 | static struct nand_bbt_descr bbt_main_descr = { | |
140 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | | |
141 | NAND_BBT_2BIT | NAND_BBT_VERSION, | |
142 | .offs = 11, | |
143 | .len = 4, | |
144 | .veroffs = 15, | |
145 | .maxblocks = 4, | |
146 | .pattern = bbt_pattern, | |
147 | }; | |
148 | ||
149 | static struct nand_bbt_descr bbt_mirror_descr = { | |
150 | .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE | | |
151 | NAND_BBT_2BIT | NAND_BBT_VERSION, | |
152 | .offs = 11, | |
153 | .len = 4, | |
154 | .veroffs = 15, | |
155 | .maxblocks = 4, | |
156 | .pattern = mirror_pattern, | |
157 | }; | |
158 | ||
76b10467 SW |
159 | /*=================================*/ |
160 | ||
161 | /* | |
162 | * Set up the FCM hardware block and page address fields, and the fcm | |
163 | * structure addr field to point to the correct FCM buffer in memory | |
164 | */ | |
165 | static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) | |
166 | { | |
4bd4ebcc | 167 | struct nand_chip *chip = mtd_to_nand(mtd); |
d699ed25 | 168 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 | 169 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
d4a32fe4 | 170 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
3ab8f2a2 | 171 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; |
76b10467 SW |
172 | int buf_num; |
173 | ||
3ab8f2a2 | 174 | elbc_fcm_ctrl->page = page_addr; |
76b10467 | 175 | |
76b10467 | 176 | if (priv->page_size) { |
9ae84fe8 LS |
177 | /* |
178 | * large page size chip : FPAR[PI] save the lowest 6 bits, | |
179 | * FBAR[BLK] save the other bits. | |
180 | */ | |
181 | out_be32(&lbc->fbar, page_addr >> 6); | |
76b10467 SW |
182 | out_be32(&lbc->fpar, |
183 | ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) | | |
184 | (oob ? FPAR_LP_MS : 0) | column); | |
185 | buf_num = (page_addr & 1) << 2; | |
186 | } else { | |
9ae84fe8 LS |
187 | /* |
188 | * small page size chip : FPAR[PI] save the lowest 5 bits, | |
189 | * FBAR[BLK] save the other bits. | |
190 | */ | |
191 | out_be32(&lbc->fbar, page_addr >> 5); | |
76b10467 SW |
192 | out_be32(&lbc->fpar, |
193 | ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) | | |
194 | (oob ? FPAR_SP_MS : 0) | column); | |
195 | buf_num = page_addr & 7; | |
196 | } | |
197 | ||
3ab8f2a2 RZ |
198 | elbc_fcm_ctrl->addr = priv->vbase + buf_num * 1024; |
199 | elbc_fcm_ctrl->index = column; | |
76b10467 SW |
200 | |
201 | /* for OOB data point to the second half of the buffer */ | |
202 | if (oob) | |
3ab8f2a2 | 203 | elbc_fcm_ctrl->index += priv->page_size ? 2048 : 512; |
76b10467 | 204 | |
3ab8f2a2 RZ |
205 | dev_vdbg(priv->dev, "set_addr: bank=%d, " |
206 | "elbc_fcm_ctrl->addr=0x%p (0x%p), " | |
76b10467 | 207 | "index %x, pes %d ps %d\n", |
3ab8f2a2 RZ |
208 | buf_num, elbc_fcm_ctrl->addr, priv->vbase, |
209 | elbc_fcm_ctrl->index, | |
76b10467 SW |
210 | chip->phys_erase_shift, chip->page_shift); |
211 | } | |
212 | ||
213 | /* | |
214 | * execute FCM command and wait for it to complete | |
215 | */ | |
216 | static int fsl_elbc_run_command(struct mtd_info *mtd) | |
217 | { | |
4bd4ebcc | 218 | struct nand_chip *chip = mtd_to_nand(mtd); |
d699ed25 | 219 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 RZ |
220 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
221 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | |
d4a32fe4 | 222 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
76b10467 SW |
223 | |
224 | /* Setup the FMR[OP] to execute without write protection */ | |
225 | out_be32(&lbc->fmr, priv->fmr | 3); | |
3ab8f2a2 RZ |
226 | if (elbc_fcm_ctrl->use_mdr) |
227 | out_be32(&lbc->mdr, elbc_fcm_ctrl->mdr); | |
76b10467 | 228 | |
3ab8f2a2 | 229 | dev_vdbg(priv->dev, |
76b10467 SW |
230 | "fsl_elbc_run_command: fmr=%08x fir=%08x fcr=%08x\n", |
231 | in_be32(&lbc->fmr), in_be32(&lbc->fir), in_be32(&lbc->fcr)); | |
3ab8f2a2 | 232 | dev_vdbg(priv->dev, |
76b10467 SW |
233 | "fsl_elbc_run_command: fbar=%08x fpar=%08x " |
234 | "fbcr=%08x bank=%d\n", | |
235 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), | |
236 | in_be32(&lbc->fbcr), priv->bank); | |
237 | ||
1938de46 | 238 | ctrl->irq_status = 0; |
76b10467 SW |
239 | /* execute special operation */ |
240 | out_be32(&lbc->lsor, priv->bank); | |
241 | ||
242 | /* wait for FCM complete flag or timeout */ | |
76b10467 SW |
243 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, |
244 | FCM_TIMEOUT_MSECS * HZ/1000); | |
3ab8f2a2 | 245 | elbc_fcm_ctrl->status = ctrl->irq_status; |
76b10467 | 246 | /* store mdr value in case it was needed */ |
3ab8f2a2 RZ |
247 | if (elbc_fcm_ctrl->use_mdr) |
248 | elbc_fcm_ctrl->mdr = in_be32(&lbc->mdr); | |
76b10467 | 249 | |
3ab8f2a2 | 250 | elbc_fcm_ctrl->use_mdr = 0; |
76b10467 | 251 | |
3ab8f2a2 RZ |
252 | if (elbc_fcm_ctrl->status != LTESR_CC) { |
253 | dev_info(priv->dev, | |
c1317f71 SW |
254 | "command failed: fir %x fcr %x status %x mdr %x\n", |
255 | in_be32(&lbc->fir), in_be32(&lbc->fcr), | |
3ab8f2a2 | 256 | elbc_fcm_ctrl->status, elbc_fcm_ctrl->mdr); |
c1317f71 SW |
257 | return -EIO; |
258 | } | |
76b10467 | 259 | |
f975c6bc MH |
260 | if (chip->ecc.mode != NAND_ECC_HW) |
261 | return 0; | |
262 | ||
3f91e94f MD |
263 | elbc_fcm_ctrl->max_bitflips = 0; |
264 | ||
f975c6bc MH |
265 | if (elbc_fcm_ctrl->read_bytes == mtd->writesize + mtd->oobsize) { |
266 | uint32_t lteccr = in_be32(&lbc->lteccr); | |
267 | /* | |
268 | * if command was a full page read and the ELBC | |
269 | * has the LTECCR register, then bits 12-15 (ppc order) of | |
270 | * LTECCR indicates which 512 byte sub-pages had fixed errors. | |
271 | * bits 28-31 are uncorrectable errors, marked elsewhere. | |
272 | * for small page nand only 1 bit is used. | |
273 | * if the ELBC doesn't have the lteccr register it reads 0 | |
3f91e94f MD |
274 | * FIXME: 4 bits can be corrected on NANDs with 2k pages, so |
275 | * count the number of sub-pages with bitflips and update | |
276 | * ecc_stats.corrected accordingly. | |
f975c6bc MH |
277 | */ |
278 | if (lteccr & 0x000F000F) | |
279 | out_be32(&lbc->lteccr, 0x000F000F); /* clear lteccr */ | |
3f91e94f | 280 | if (lteccr & 0x000F0000) { |
f975c6bc | 281 | mtd->ecc_stats.corrected++; |
3f91e94f MD |
282 | elbc_fcm_ctrl->max_bitflips = 1; |
283 | } | |
f975c6bc MH |
284 | } |
285 | ||
c1317f71 | 286 | return 0; |
76b10467 SW |
287 | } |
288 | ||
289 | static void fsl_elbc_do_read(struct nand_chip *chip, int oob) | |
290 | { | |
d699ed25 | 291 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 | 292 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
d4a32fe4 | 293 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
76b10467 SW |
294 | |
295 | if (priv->page_size) { | |
296 | out_be32(&lbc->fir, | |
476459a6 | 297 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
76b10467 SW |
298 | (FIR_OP_CA << FIR_OP1_SHIFT) | |
299 | (FIR_OP_PA << FIR_OP2_SHIFT) | | |
476459a6 | 300 | (FIR_OP_CM1 << FIR_OP3_SHIFT) | |
76b10467 SW |
301 | (FIR_OP_RBW << FIR_OP4_SHIFT)); |
302 | ||
303 | out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | | |
304 | (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); | |
305 | } else { | |
306 | out_be32(&lbc->fir, | |
476459a6 | 307 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
76b10467 SW |
308 | (FIR_OP_CA << FIR_OP1_SHIFT) | |
309 | (FIR_OP_PA << FIR_OP2_SHIFT) | | |
310 | (FIR_OP_RBW << FIR_OP3_SHIFT)); | |
311 | ||
312 | if (oob) | |
313 | out_be32(&lbc->fcr, NAND_CMD_READOOB << FCR_CMD0_SHIFT); | |
314 | else | |
315 | out_be32(&lbc->fcr, NAND_CMD_READ0 << FCR_CMD0_SHIFT); | |
316 | } | |
317 | } | |
318 | ||
319 | /* cmdfunc send commands to the FCM */ | |
320 | static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |
321 | int column, int page_addr) | |
322 | { | |
4bd4ebcc | 323 | struct nand_chip *chip = mtd_to_nand(mtd); |
d699ed25 | 324 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 RZ |
325 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
326 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | |
d4a32fe4 | 327 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
76b10467 | 328 | |
3ab8f2a2 | 329 | elbc_fcm_ctrl->use_mdr = 0; |
76b10467 SW |
330 | |
331 | /* clear the read buffer */ | |
3ab8f2a2 | 332 | elbc_fcm_ctrl->read_bytes = 0; |
76b10467 | 333 | if (command != NAND_CMD_PAGEPROG) |
3ab8f2a2 | 334 | elbc_fcm_ctrl->index = 0; |
76b10467 SW |
335 | |
336 | switch (command) { | |
337 | /* READ0 and READ1 read the entire buffer to use hardware ECC. */ | |
338 | case NAND_CMD_READ1: | |
339 | column += 256; | |
340 | ||
341 | /* fall-through */ | |
342 | case NAND_CMD_READ0: | |
3ab8f2a2 | 343 | dev_dbg(priv->dev, |
76b10467 SW |
344 | "fsl_elbc_cmdfunc: NAND_CMD_READ0, page_addr:" |
345 | " 0x%x, column: 0x%x.\n", page_addr, column); | |
346 | ||
347 | ||
348 | out_be32(&lbc->fbcr, 0); /* read entire page to enable ECC */ | |
349 | set_addr(mtd, 0, page_addr, 0); | |
350 | ||
3ab8f2a2 RZ |
351 | elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; |
352 | elbc_fcm_ctrl->index += column; | |
76b10467 SW |
353 | |
354 | fsl_elbc_do_read(chip, 0); | |
355 | fsl_elbc_run_command(mtd); | |
356 | return; | |
357 | ||
358 | /* READOOB reads only the OOB because no ECC is performed. */ | |
359 | case NAND_CMD_READOOB: | |
3ab8f2a2 | 360 | dev_vdbg(priv->dev, |
76b10467 SW |
361 | "fsl_elbc_cmdfunc: NAND_CMD_READOOB, page_addr:" |
362 | " 0x%x, column: 0x%x.\n", page_addr, column); | |
363 | ||
364 | out_be32(&lbc->fbcr, mtd->oobsize - column); | |
365 | set_addr(mtd, column, page_addr, 1); | |
366 | ||
3ab8f2a2 | 367 | elbc_fcm_ctrl->read_bytes = mtd->writesize + mtd->oobsize; |
76b10467 SW |
368 | |
369 | fsl_elbc_do_read(chip, 1); | |
370 | fsl_elbc_run_command(mtd); | |
371 | return; | |
372 | ||
76b10467 | 373 | case NAND_CMD_READID: |
f57eb5cc SL |
374 | case NAND_CMD_PARAM: |
375 | dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD %x\n", command); | |
76b10467 | 376 | |
476459a6 | 377 | out_be32(&lbc->fir, (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
76b10467 SW |
378 | (FIR_OP_UA << FIR_OP1_SHIFT) | |
379 | (FIR_OP_RBW << FIR_OP2_SHIFT)); | |
f57eb5cc SL |
380 | out_be32(&lbc->fcr, command << FCR_CMD0_SHIFT); |
381 | /* | |
382 | * although currently it's 8 bytes for READID, we always read | |
383 | * the maximum 256 bytes(for PARAM) | |
384 | */ | |
385 | out_be32(&lbc->fbcr, 256); | |
386 | elbc_fcm_ctrl->read_bytes = 256; | |
3ab8f2a2 | 387 | elbc_fcm_ctrl->use_mdr = 1; |
f57eb5cc | 388 | elbc_fcm_ctrl->mdr = column; |
76b10467 SW |
389 | set_addr(mtd, 0, 0, 0); |
390 | fsl_elbc_run_command(mtd); | |
391 | return; | |
392 | ||
393 | /* ERASE1 stores the block and page address */ | |
394 | case NAND_CMD_ERASE1: | |
3ab8f2a2 | 395 | dev_vdbg(priv->dev, |
76b10467 SW |
396 | "fsl_elbc_cmdfunc: NAND_CMD_ERASE1, " |
397 | "page_addr: 0x%x.\n", page_addr); | |
398 | set_addr(mtd, 0, page_addr, 0); | |
399 | return; | |
400 | ||
401 | /* ERASE2 uses the block and page address from ERASE1 */ | |
402 | case NAND_CMD_ERASE2: | |
3ab8f2a2 | 403 | dev_vdbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_ERASE2.\n"); |
76b10467 SW |
404 | |
405 | out_be32(&lbc->fir, | |
476459a6 | 406 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
76b10467 | 407 | (FIR_OP_PA << FIR_OP1_SHIFT) | |
476459a6 SW |
408 | (FIR_OP_CM2 << FIR_OP2_SHIFT) | |
409 | (FIR_OP_CW1 << FIR_OP3_SHIFT) | | |
410 | (FIR_OP_RS << FIR_OP4_SHIFT)); | |
76b10467 SW |
411 | |
412 | out_be32(&lbc->fcr, | |
413 | (NAND_CMD_ERASE1 << FCR_CMD0_SHIFT) | | |
476459a6 SW |
414 | (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | |
415 | (NAND_CMD_ERASE2 << FCR_CMD2_SHIFT)); | |
76b10467 SW |
416 | |
417 | out_be32(&lbc->fbcr, 0); | |
3ab8f2a2 RZ |
418 | elbc_fcm_ctrl->read_bytes = 0; |
419 | elbc_fcm_ctrl->use_mdr = 1; | |
76b10467 SW |
420 | |
421 | fsl_elbc_run_command(mtd); | |
422 | return; | |
423 | ||
424 | /* SEQIN sets up the addr buffer and all registers except the length */ | |
425 | case NAND_CMD_SEQIN: { | |
426 | __be32 fcr; | |
3ab8f2a2 RZ |
427 | dev_vdbg(priv->dev, |
428 | "fsl_elbc_cmdfunc: NAND_CMD_SEQIN/PAGE_PROG, " | |
76b10467 SW |
429 | "page_addr: 0x%x, column: 0x%x.\n", |
430 | page_addr, column); | |
431 | ||
eeda667a | 432 | elbc_fcm_ctrl->column = column; |
3ab8f2a2 | 433 | elbc_fcm_ctrl->use_mdr = 1; |
76b10467 | 434 | |
a9a552f0 LS |
435 | if (column >= mtd->writesize) { |
436 | /* OOB area */ | |
437 | column -= mtd->writesize; | |
438 | elbc_fcm_ctrl->oob = 1; | |
439 | } else { | |
440 | WARN_ON(column != 0); | |
441 | elbc_fcm_ctrl->oob = 0; | |
442 | } | |
443 | ||
476459a6 SW |
444 | fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) | |
445 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT) | | |
446 | (NAND_CMD_PAGEPROG << FCR_CMD3_SHIFT); | |
57650664 | 447 | |
476459a6 | 448 | if (priv->page_size) { |
76b10467 | 449 | out_be32(&lbc->fir, |
476459a6 | 450 | (FIR_OP_CM2 << FIR_OP0_SHIFT) | |
76b10467 SW |
451 | (FIR_OP_CA << FIR_OP1_SHIFT) | |
452 | (FIR_OP_PA << FIR_OP2_SHIFT) | | |
453 | (FIR_OP_WB << FIR_OP3_SHIFT) | | |
476459a6 SW |
454 | (FIR_OP_CM3 << FIR_OP4_SHIFT) | |
455 | (FIR_OP_CW1 << FIR_OP5_SHIFT) | | |
456 | (FIR_OP_RS << FIR_OP6_SHIFT)); | |
76b10467 SW |
457 | } else { |
458 | out_be32(&lbc->fir, | |
476459a6 | 459 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | |
76b10467 SW |
460 | (FIR_OP_CM2 << FIR_OP1_SHIFT) | |
461 | (FIR_OP_CA << FIR_OP2_SHIFT) | | |
462 | (FIR_OP_PA << FIR_OP3_SHIFT) | | |
463 | (FIR_OP_WB << FIR_OP4_SHIFT) | | |
476459a6 SW |
464 | (FIR_OP_CM3 << FIR_OP5_SHIFT) | |
465 | (FIR_OP_CW1 << FIR_OP6_SHIFT) | | |
466 | (FIR_OP_RS << FIR_OP7_SHIFT)); | |
76b10467 | 467 | |
a9a552f0 | 468 | if (elbc_fcm_ctrl->oob) |
76b10467 | 469 | /* OOB area --> READOOB */ |
76b10467 | 470 | fcr |= NAND_CMD_READOOB << FCR_CMD0_SHIFT; |
a9a552f0 | 471 | else |
76b10467 SW |
472 | /* First 256 bytes --> READ0 */ |
473 | fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT; | |
76b10467 SW |
474 | } |
475 | ||
476 | out_be32(&lbc->fcr, fcr); | |
3ab8f2a2 | 477 | set_addr(mtd, column, page_addr, elbc_fcm_ctrl->oob); |
76b10467 SW |
478 | return; |
479 | } | |
480 | ||
481 | /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ | |
482 | case NAND_CMD_PAGEPROG: { | |
3ab8f2a2 | 483 | dev_vdbg(priv->dev, |
76b10467 | 484 | "fsl_elbc_cmdfunc: NAND_CMD_PAGEPROG " |
3ab8f2a2 | 485 | "writing %d bytes.\n", elbc_fcm_ctrl->index); |
76b10467 SW |
486 | |
487 | /* if the write did not start at 0 or is not a full page | |
488 | * then set the exact length, otherwise use a full page | |
489 | * write so the HW generates the ECC. | |
490 | */ | |
3ab8f2a2 | 491 | if (elbc_fcm_ctrl->oob || elbc_fcm_ctrl->column != 0 || |
52a474de | 492 | elbc_fcm_ctrl->index != mtd->writesize + mtd->oobsize) |
e32de766 LS |
493 | out_be32(&lbc->fbcr, |
494 | elbc_fcm_ctrl->index - elbc_fcm_ctrl->column); | |
52a474de | 495 | else |
76b10467 | 496 | out_be32(&lbc->fbcr, 0); |
76b10467 SW |
497 | |
498 | fsl_elbc_run_command(mtd); | |
76b10467 SW |
499 | return; |
500 | } | |
501 | ||
502 | /* CMD_STATUS must read the status byte while CEB is active */ | |
503 | /* Note - it does not wait for the ready line */ | |
504 | case NAND_CMD_STATUS: | |
505 | out_be32(&lbc->fir, | |
506 | (FIR_OP_CM0 << FIR_OP0_SHIFT) | | |
507 | (FIR_OP_RBW << FIR_OP1_SHIFT)); | |
508 | out_be32(&lbc->fcr, NAND_CMD_STATUS << FCR_CMD0_SHIFT); | |
509 | out_be32(&lbc->fbcr, 1); | |
510 | set_addr(mtd, 0, 0, 0); | |
3ab8f2a2 | 511 | elbc_fcm_ctrl->read_bytes = 1; |
76b10467 SW |
512 | |
513 | fsl_elbc_run_command(mtd); | |
514 | ||
515 | /* The chip always seems to report that it is | |
516 | * write-protected, even when it is not. | |
517 | */ | |
3ab8f2a2 | 518 | setbits8(elbc_fcm_ctrl->addr, NAND_STATUS_WP); |
76b10467 SW |
519 | return; |
520 | ||
521 | /* RESET without waiting for the ready line */ | |
522 | case NAND_CMD_RESET: | |
3ab8f2a2 | 523 | dev_dbg(priv->dev, "fsl_elbc_cmdfunc: NAND_CMD_RESET.\n"); |
76b10467 SW |
524 | out_be32(&lbc->fir, FIR_OP_CM0 << FIR_OP0_SHIFT); |
525 | out_be32(&lbc->fcr, NAND_CMD_RESET << FCR_CMD0_SHIFT); | |
526 | fsl_elbc_run_command(mtd); | |
527 | return; | |
528 | ||
529 | default: | |
3ab8f2a2 | 530 | dev_err(priv->dev, |
76b10467 SW |
531 | "fsl_elbc_cmdfunc: error, unsupported command 0x%x.\n", |
532 | command); | |
533 | } | |
534 | } | |
535 | ||
536 | static void fsl_elbc_select_chip(struct mtd_info *mtd, int chip) | |
537 | { | |
538 | /* The hardware does not seem to support multiple | |
539 | * chips per bank. | |
540 | */ | |
541 | } | |
542 | ||
543 | /* | |
544 | * Write buf to the FCM Controller Data Buffer | |
545 | */ | |
546 | static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |
547 | { | |
4bd4ebcc | 548 | struct nand_chip *chip = mtd_to_nand(mtd); |
d699ed25 | 549 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 | 550 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
76b10467 SW |
551 | unsigned int bufsize = mtd->writesize + mtd->oobsize; |
552 | ||
0ff6631b | 553 | if (len <= 0) { |
3ab8f2a2 RZ |
554 | dev_err(priv->dev, "write_buf of %d bytes", len); |
555 | elbc_fcm_ctrl->status = 0; | |
76b10467 SW |
556 | return; |
557 | } | |
558 | ||
3ab8f2a2 RZ |
559 | if ((unsigned int)len > bufsize - elbc_fcm_ctrl->index) { |
560 | dev_err(priv->dev, | |
76b10467 SW |
561 | "write_buf beyond end of buffer " |
562 | "(%d requested, %u available)\n", | |
3ab8f2a2 RZ |
563 | len, bufsize - elbc_fcm_ctrl->index); |
564 | len = bufsize - elbc_fcm_ctrl->index; | |
76b10467 SW |
565 | } |
566 | ||
3ab8f2a2 | 567 | memcpy_toio(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], buf, len); |
0ff6631b AV |
568 | /* |
569 | * This is workaround for the weird elbc hangs during nand write, | |
570 | * Scott Wood says: "...perhaps difference in how long it takes a | |
571 | * write to make it through the localbus compared to a write to IMMR | |
572 | * is causing problems, and sync isn't helping for some reason." | |
573 | * Reading back the last byte helps though. | |
574 | */ | |
3ab8f2a2 | 575 | in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index] + len - 1); |
0ff6631b | 576 | |
3ab8f2a2 | 577 | elbc_fcm_ctrl->index += len; |
76b10467 SW |
578 | } |
579 | ||
580 | /* | |
581 | * read a byte from either the FCM hardware buffer if it has any data left | |
582 | * otherwise issue a command to read a single byte. | |
583 | */ | |
584 | static u8 fsl_elbc_read_byte(struct mtd_info *mtd) | |
585 | { | |
4bd4ebcc | 586 | struct nand_chip *chip = mtd_to_nand(mtd); |
d699ed25 | 587 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 | 588 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
76b10467 SW |
589 | |
590 | /* If there are still bytes in the FCM, then use the next byte. */ | |
3ab8f2a2 RZ |
591 | if (elbc_fcm_ctrl->index < elbc_fcm_ctrl->read_bytes) |
592 | return in_8(&elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index++]); | |
76b10467 | 593 | |
3ab8f2a2 | 594 | dev_err(priv->dev, "read_byte beyond end of buffer\n"); |
76b10467 SW |
595 | return ERR_BYTE; |
596 | } | |
597 | ||
598 | /* | |
599 | * Read from the FCM Controller Data Buffer | |
600 | */ | |
601 | static void fsl_elbc_read_buf(struct mtd_info *mtd, u8 *buf, int len) | |
602 | { | |
4bd4ebcc | 603 | struct nand_chip *chip = mtd_to_nand(mtd); |
d699ed25 | 604 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 | 605 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
76b10467 SW |
606 | int avail; |
607 | ||
608 | if (len < 0) | |
609 | return; | |
610 | ||
3ab8f2a2 RZ |
611 | avail = min((unsigned int)len, |
612 | elbc_fcm_ctrl->read_bytes - elbc_fcm_ctrl->index); | |
613 | memcpy_fromio(buf, &elbc_fcm_ctrl->addr[elbc_fcm_ctrl->index], avail); | |
614 | elbc_fcm_ctrl->index += avail; | |
76b10467 SW |
615 | |
616 | if (len > avail) | |
3ab8f2a2 | 617 | dev_err(priv->dev, |
76b10467 SW |
618 | "read_buf beyond end of buffer " |
619 | "(%d requested, %d available)\n", | |
620 | len, avail); | |
621 | } | |
622 | ||
76b10467 SW |
623 | /* This function is called after Program and Erase Operations to |
624 | * check for success or failure. | |
625 | */ | |
626 | static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip) | |
627 | { | |
d699ed25 | 628 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 | 629 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
76b10467 | 630 | |
3ab8f2a2 | 631 | if (elbc_fcm_ctrl->status != LTESR_CC) |
76b10467 SW |
632 | return NAND_STATUS_FAIL; |
633 | ||
634 | /* The chip always seems to report that it is | |
635 | * write-protected, even when it is not. | |
636 | */ | |
3ab8f2a2 | 637 | return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP; |
76b10467 SW |
638 | } |
639 | ||
640 | static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |
641 | { | |
4bd4ebcc | 642 | struct nand_chip *chip = mtd_to_nand(mtd); |
d699ed25 | 643 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3ab8f2a2 | 644 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
d4a32fe4 | 645 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
76b10467 SW |
646 | unsigned int al; |
647 | ||
648 | /* calculate FMR Address Length field */ | |
649 | al = 0; | |
650 | if (chip->pagemask & 0xffff0000) | |
651 | al++; | |
652 | if (chip->pagemask & 0xff000000) | |
653 | al++; | |
654 | ||
d8251108 | 655 | priv->fmr |= al << FMR_AL_SHIFT; |
76b10467 | 656 | |
3ab8f2a2 | 657 | dev_dbg(priv->dev, "fsl_elbc_init: nand->numchips = %d\n", |
76b10467 | 658 | chip->numchips); |
3ab8f2a2 | 659 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chipsize = %lld\n", |
76b10467 | 660 | chip->chipsize); |
3ab8f2a2 | 661 | dev_dbg(priv->dev, "fsl_elbc_init: nand->pagemask = %8x\n", |
76b10467 | 662 | chip->pagemask); |
3ab8f2a2 | 663 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_delay = %d\n", |
76b10467 | 664 | chip->chip_delay); |
3ab8f2a2 | 665 | dev_dbg(priv->dev, "fsl_elbc_init: nand->badblockpos = %d\n", |
76b10467 | 666 | chip->badblockpos); |
3ab8f2a2 | 667 | dev_dbg(priv->dev, "fsl_elbc_init: nand->chip_shift = %d\n", |
76b10467 | 668 | chip->chip_shift); |
3ab8f2a2 | 669 | dev_dbg(priv->dev, "fsl_elbc_init: nand->page_shift = %d\n", |
76b10467 | 670 | chip->page_shift); |
3ab8f2a2 | 671 | dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", |
76b10467 | 672 | chip->phys_erase_shift); |
3ab8f2a2 | 673 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", |
76b10467 | 674 | chip->ecc.mode); |
3ab8f2a2 | 675 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", |
76b10467 | 676 | chip->ecc.steps); |
3ab8f2a2 | 677 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.bytes = %d\n", |
76b10467 | 678 | chip->ecc.bytes); |
3ab8f2a2 | 679 | dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.total = %d\n", |
76b10467 | 680 | chip->ecc.total); |
c2e197b0 BB |
681 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->ooblayout = %p\n", |
682 | mtd->ooblayout); | |
3ab8f2a2 RZ |
683 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); |
684 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size); | |
685 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->erasesize = %d\n", | |
76b10467 | 686 | mtd->erasesize); |
3ab8f2a2 | 687 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->writesize = %d\n", |
76b10467 | 688 | mtd->writesize); |
3ab8f2a2 | 689 | dev_dbg(priv->dev, "fsl_elbc_init: mtd->oobsize = %d\n", |
76b10467 SW |
690 | mtd->oobsize); |
691 | ||
692 | /* adjust Option Register and ECC to match Flash page size */ | |
693 | if (mtd->writesize == 512) { | |
694 | priv->page_size = 0; | |
1938de46 | 695 | clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); |
76b10467 SW |
696 | } else if (mtd->writesize == 2048) { |
697 | priv->page_size = 1; | |
698 | setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); | |
76b10467 | 699 | } else { |
3ab8f2a2 | 700 | dev_err(priv->dev, |
76b10467 SW |
701 | "fsl_elbc_init: page size %d is not supported\n", |
702 | mtd->writesize); | |
703 | return -1; | |
704 | } | |
705 | ||
76b10467 SW |
706 | return 0; |
707 | } | |
708 | ||
1fbb938d BN |
709 | static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
710 | uint8_t *buf, int oob_required, int page) | |
76b10467 | 711 | { |
d699ed25 | 712 | struct fsl_elbc_mtd *priv = nand_get_controller_data(chip); |
3f91e94f MD |
713 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
714 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; | |
715 | ||
76b10467 | 716 | fsl_elbc_read_buf(mtd, buf, mtd->writesize); |
d112dc7f BN |
717 | if (oob_required) |
718 | fsl_elbc_read_buf(mtd, chip->oob_poi, mtd->oobsize); | |
76b10467 SW |
719 | |
720 | if (fsl_elbc_wait(mtd, chip) & NAND_STATUS_FAIL) | |
721 | mtd->ecc_stats.failed++; | |
722 | ||
3f91e94f | 723 | return elbc_fcm_ctrl->max_bitflips; |
76b10467 SW |
724 | } |
725 | ||
726 | /* ECC will be calculated automatically, and errors will be detected in | |
727 | * waitfunc. | |
728 | */ | |
fdbad98d | 729 | static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
45aaeff9 | 730 | const uint8_t *buf, int oob_required, int page) |
76b10467 | 731 | { |
76b10467 SW |
732 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); |
733 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | |
fdbad98d JW |
734 | |
735 | return 0; | |
76b10467 SW |
736 | } |
737 | ||
f034d87d PG |
738 | /* ECC will be calculated automatically, and errors will be detected in |
739 | * waitfunc. | |
740 | */ | |
741 | static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip, | |
742 | uint32_t offset, uint32_t data_len, | |
45aaeff9 | 743 | const uint8_t *buf, int oob_required, int page) |
f034d87d PG |
744 | { |
745 | fsl_elbc_write_buf(mtd, buf, mtd->writesize); | |
746 | fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); | |
747 | ||
748 | return 0; | |
749 | } | |
750 | ||
76b10467 SW |
751 | static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) |
752 | { | |
3ab8f2a2 | 753 | struct fsl_lbc_ctrl *ctrl = priv->ctrl; |
d4a32fe4 | 754 | struct fsl_lbc_regs __iomem *lbc = ctrl->regs; |
3ab8f2a2 | 755 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand; |
76b10467 | 756 | struct nand_chip *chip = &priv->chip; |
18ba50c3 | 757 | struct mtd_info *mtd = nand_to_mtd(chip); |
76b10467 SW |
758 | |
759 | dev_dbg(priv->dev, "eLBC Set Information for bank %d\n", priv->bank); | |
760 | ||
761 | /* Fill in fsl_elbc_mtd structure */ | |
18ba50c3 | 762 | mtd->dev.parent = priv->dev; |
a61ae81a | 763 | nand_set_flash_node(chip, priv->dev->of_node); |
03ed1078 | 764 | |
d8251108 SL |
765 | /* set timeout to maximum */ |
766 | priv->fmr = 15 << FMR_CWTO_SHIFT; | |
767 | if (in_be32(&lbc->bank[priv->bank].or) & OR_FCM_PGS) | |
768 | priv->fmr |= FMR_ECCM; | |
76b10467 SW |
769 | |
770 | /* fill in nand_chip structure */ | |
771 | /* set up function call table */ | |
772 | chip->read_byte = fsl_elbc_read_byte; | |
773 | chip->write_buf = fsl_elbc_write_buf; | |
774 | chip->read_buf = fsl_elbc_read_buf; | |
76b10467 SW |
775 | chip->select_chip = fsl_elbc_select_chip; |
776 | chip->cmdfunc = fsl_elbc_cmdfunc; | |
777 | chip->waitfunc = fsl_elbc_wait; | |
778 | ||
ec6e0ea3 AV |
779 | chip->bbt_td = &bbt_main_descr; |
780 | chip->bbt_md = &bbt_mirror_descr; | |
781 | ||
76b10467 | 782 | /* set up nand options */ |
bb9ebd4e | 783 | chip->bbt_options = NAND_BBT_USE_FLASH; |
76b10467 | 784 | |
3ab8f2a2 | 785 | chip->controller = &elbc_fcm_ctrl->controller; |
d699ed25 | 786 | nand_set_controller_data(chip, priv); |
76b10467 SW |
787 | |
788 | chip->ecc.read_page = fsl_elbc_read_page; | |
789 | chip->ecc.write_page = fsl_elbc_write_page; | |
f034d87d | 790 | chip->ecc.write_subpage = fsl_elbc_write_subpage; |
76b10467 SW |
791 | |
792 | /* If CS Base Register selects full hardware ECC then use it */ | |
793 | if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == | |
794 | BR_DECC_CHK_GEN) { | |
795 | chip->ecc.mode = NAND_ECC_HW; | |
c2e197b0 | 796 | mtd_set_ooblayout(mtd, &fsl_elbc_ooblayout_ops); |
76b10467 SW |
797 | chip->ecc.size = 512; |
798 | chip->ecc.bytes = 3; | |
6a918bad | 799 | chip->ecc.strength = 1; |
76b10467 SW |
800 | } else { |
801 | /* otherwise fall back to default software ECC */ | |
802 | chip->ecc.mode = NAND_ECC_SOFT; | |
e99b0d98 | 803 | chip->ecc.algo = NAND_ECC_HAMMING; |
76b10467 SW |
804 | } |
805 | ||
806 | return 0; | |
807 | } | |
808 | ||
809 | static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | |
810 | { | |
3ab8f2a2 | 811 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = priv->ctrl->nand; |
18ba50c3 | 812 | struct mtd_info *mtd = nand_to_mtd(&priv->chip); |
76b10467 | 813 | |
18ba50c3 BB |
814 | nand_release(mtd); |
815 | ||
816 | kfree(mtd->name); | |
9ebed3e6 | 817 | |
76b10467 SW |
818 | if (priv->vbase) |
819 | iounmap(priv->vbase); | |
820 | ||
3ab8f2a2 | 821 | elbc_fcm_ctrl->chips[priv->bank] = NULL; |
76b10467 | 822 | kfree(priv); |
76b10467 SW |
823 | return 0; |
824 | } | |
825 | ||
3ab8f2a2 RZ |
826 | static DEFINE_MUTEX(fsl_elbc_nand_mutex); |
827 | ||
06f25510 | 828 | static int fsl_elbc_nand_probe(struct platform_device *pdev) |
76b10467 | 829 | { |
3ab8f2a2 | 830 | struct fsl_lbc_regs __iomem *lbc; |
76b10467 SW |
831 | struct fsl_elbc_mtd *priv; |
832 | struct resource res; | |
3ab8f2a2 | 833 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl; |
76b10467 | 834 | static const char *part_probe_types[] |
b6b0fae7 | 835 | = { "cmdlinepart", "RedBoot", "ofpart", NULL }; |
76b10467 SW |
836 | int ret; |
837 | int bank; | |
3ab8f2a2 RZ |
838 | struct device *dev; |
839 | struct device_node *node = pdev->dev.of_node; | |
18ba50c3 | 840 | struct mtd_info *mtd; |
3ab8f2a2 RZ |
841 | |
842 | if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs) | |
843 | return -ENODEV; | |
844 | lbc = fsl_lbc_ctrl_dev->regs; | |
845 | dev = fsl_lbc_ctrl_dev->dev; | |
76b10467 SW |
846 | |
847 | /* get, allocate and map the memory resource */ | |
848 | ret = of_address_to_resource(node, 0, &res); | |
849 | if (ret) { | |
3ab8f2a2 | 850 | dev_err(dev, "failed to get resource\n"); |
76b10467 SW |
851 | return ret; |
852 | } | |
853 | ||
854 | /* find which chip select it is connected to */ | |
855 | for (bank = 0; bank < MAX_BANKS; bank++) | |
856 | if ((in_be32(&lbc->bank[bank].br) & BR_V) && | |
857 | (in_be32(&lbc->bank[bank].br) & BR_MSEL) == BR_MS_FCM && | |
858 | (in_be32(&lbc->bank[bank].br) & | |
859 | in_be32(&lbc->bank[bank].or) & BR_BA) | |
0b824d2b | 860 | == fsl_lbc_addr(res.start)) |
76b10467 SW |
861 | break; |
862 | ||
863 | if (bank >= MAX_BANKS) { | |
3ab8f2a2 | 864 | dev_err(dev, "address did not match any chip selects\n"); |
76b10467 SW |
865 | return -ENODEV; |
866 | } | |
867 | ||
868 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | |
869 | if (!priv) | |
870 | return -ENOMEM; | |
871 | ||
3ab8f2a2 RZ |
872 | mutex_lock(&fsl_elbc_nand_mutex); |
873 | if (!fsl_lbc_ctrl_dev->nand) { | |
874 | elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL); | |
875 | if (!elbc_fcm_ctrl) { | |
3ab8f2a2 RZ |
876 | mutex_unlock(&fsl_elbc_nand_mutex); |
877 | ret = -ENOMEM; | |
878 | goto err; | |
879 | } | |
880 | elbc_fcm_ctrl->counter++; | |
881 | ||
d45bc58d | 882 | nand_hw_control_init(&elbc_fcm_ctrl->controller); |
3ab8f2a2 RZ |
883 | fsl_lbc_ctrl_dev->nand = elbc_fcm_ctrl; |
884 | } else { | |
885 | elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; | |
886 | } | |
887 | mutex_unlock(&fsl_elbc_nand_mutex); | |
888 | ||
889 | elbc_fcm_ctrl->chips[bank] = priv; | |
76b10467 | 890 | priv->bank = bank; |
3ab8f2a2 | 891 | priv->ctrl = fsl_lbc_ctrl_dev; |
874d72c4 SW |
892 | priv->dev = &pdev->dev; |
893 | dev_set_drvdata(priv->dev, priv); | |
76b10467 | 894 | |
8a19b558 | 895 | priv->vbase = ioremap(res.start, resource_size(&res)); |
76b10467 | 896 | if (!priv->vbase) { |
3ab8f2a2 | 897 | dev_err(dev, "failed to map chip region\n"); |
76b10467 SW |
898 | ret = -ENOMEM; |
899 | goto err; | |
900 | } | |
901 | ||
18ba50c3 BB |
902 | mtd = nand_to_mtd(&priv->chip); |
903 | mtd->name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); | |
904 | if (!nand_to_mtd(&priv->chip)->name) { | |
9ebed3e6 AV |
905 | ret = -ENOMEM; |
906 | goto err; | |
907 | } | |
908 | ||
76b10467 SW |
909 | ret = fsl_elbc_chip_init(priv); |
910 | if (ret) | |
911 | goto err; | |
912 | ||
18ba50c3 | 913 | ret = nand_scan_ident(mtd, 1, NULL); |
76b10467 SW |
914 | if (ret) |
915 | goto err; | |
916 | ||
18ba50c3 | 917 | ret = fsl_elbc_chip_init_tail(mtd); |
76b10467 SW |
918 | if (ret) |
919 | goto err; | |
920 | ||
18ba50c3 | 921 | ret = nand_scan_tail(mtd); |
76b10467 SW |
922 | if (ret) |
923 | goto err; | |
924 | ||
76b10467 SW |
925 | /* First look for RedBoot table or partitions on the command |
926 | * line, these take precedence over device tree information */ | |
18ba50c3 | 927 | mtd_device_parse_register(mtd, part_probe_types, NULL, |
99add422 | 928 | NULL, 0); |
76b10467 | 929 | |
4712fff9 SR |
930 | printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n", |
931 | (unsigned long long)res.start, priv->bank); | |
76b10467 SW |
932 | return 0; |
933 | ||
934 | err: | |
935 | fsl_elbc_chip_remove(priv); | |
936 | return ret; | |
937 | } | |
938 | ||
3ab8f2a2 | 939 | static int fsl_elbc_nand_remove(struct platform_device *pdev) |
76b10467 | 940 | { |
3ab8f2a2 | 941 | struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = fsl_lbc_ctrl_dev->nand; |
874d72c4 SW |
942 | struct fsl_elbc_mtd *priv = dev_get_drvdata(&pdev->dev); |
943 | ||
944 | fsl_elbc_chip_remove(priv); | |
3ab8f2a2 RZ |
945 | |
946 | mutex_lock(&fsl_elbc_nand_mutex); | |
947 | elbc_fcm_ctrl->counter--; | |
948 | if (!elbc_fcm_ctrl->counter) { | |
949 | fsl_lbc_ctrl_dev->nand = NULL; | |
950 | kfree(elbc_fcm_ctrl); | |
76b10467 | 951 | } |
3ab8f2a2 | 952 | mutex_unlock(&fsl_elbc_nand_mutex); |
76b10467 SW |
953 | |
954 | return 0; | |
955 | ||
76b10467 SW |
956 | } |
957 | ||
3ab8f2a2 RZ |
958 | static const struct of_device_id fsl_elbc_nand_match[] = { |
959 | { .compatible = "fsl,elbc-fcm-nand", }, | |
76b10467 SW |
960 | {} |
961 | }; | |
030a70b9 | 962 | MODULE_DEVICE_TABLE(of, fsl_elbc_nand_match); |
76b10467 | 963 | |
3ab8f2a2 | 964 | static struct platform_driver fsl_elbc_nand_driver = { |
76b10467 | 965 | .driver = { |
3ab8f2a2 | 966 | .name = "fsl,elbc-fcm-nand", |
3ab8f2a2 | 967 | .of_match_table = fsl_elbc_nand_match, |
76b10467 | 968 | }, |
3ab8f2a2 RZ |
969 | .probe = fsl_elbc_nand_probe, |
970 | .remove = fsl_elbc_nand_remove, | |
76b10467 SW |
971 | }; |
972 | ||
f99640de | 973 | module_platform_driver(fsl_elbc_nand_driver); |
76b10467 SW |
974 | |
975 | MODULE_LICENSE("GPL"); | |
976 | MODULE_AUTHOR("Freescale"); | |
977 | MODULE_DESCRIPTION("Freescale Enhanced Local Bus Controller MTD NAND driver"); |