diff options
Diffstat (limited to 'drivers/mtd/nand/mpc5121_nfc.c')
-rw-r--r-- | drivers/mtd/nand/mpc5121_nfc.c | 917 |
1 files changed, 917 insertions, 0 deletions
diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c new file mode 100644 index 00000000000..3d0867d829c --- /dev/null +++ b/drivers/mtd/nand/mpc5121_nfc.c | |||
@@ -0,0 +1,917 @@ | |||
1 | /* | ||
2 | * Copyright 2004-2008 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2009 Semihalf. | ||
4 | * | ||
5 | * Approved as OSADL project by a majority of OSADL members and funded | ||
6 | * by OSADL membership fees in 2009; for details see www.osadl.org. | ||
7 | * | ||
8 | * Based on original driver from Freescale Semiconductor | ||
9 | * written by John Rigby <jrigby@freescale.com> on basis | ||
10 | * of drivers/mtd/nand/mxc_nand.c. Reworked and extended | ||
11 | * Piotr Ziecik <kosmo@semihalf.com>. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License | ||
15 | * as published by the Free Software Foundation; either version 2 | ||
16 | * of the License, or (at your option) any later version. | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | ||
25 | * MA 02110-1301, USA. | ||
26 | */ | ||
27 | |||
28 | #include <linux/module.h> | ||
29 | #include <linux/clk.h> | ||
30 | #include <linux/gfp.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <linux/io.h> | ||
35 | #include <linux/mtd/mtd.h> | ||
36 | #include <linux/mtd/nand.h> | ||
37 | #include <linux/mtd/partitions.h> | ||
38 | #include <linux/of_device.h> | ||
39 | #include <linux/of_platform.h> | ||
40 | |||
41 | #include <asm/mpc5121.h> | ||
42 | |||
43 | /* Addresses for NFC MAIN RAM BUFFER areas */ | ||
44 | #define NFC_MAIN_AREA(n) ((n) * 0x200) | ||
45 | |||
46 | /* Addresses for NFC SPARE BUFFER areas */ | ||
47 | #define NFC_SPARE_BUFFERS 8 | ||
48 | #define NFC_SPARE_LEN 0x40 | ||
49 | #define NFC_SPARE_AREA(n) (0x1000 + ((n) * NFC_SPARE_LEN)) | ||
50 | |||
51 | /* MPC5121 NFC registers */ | ||
52 | #define NFC_BUF_ADDR 0x1E04 | ||
53 | #define NFC_FLASH_ADDR 0x1E06 | ||
54 | #define NFC_FLASH_CMD 0x1E08 | ||
55 | #define NFC_CONFIG 0x1E0A | ||
56 | #define NFC_ECC_STATUS1 0x1E0C | ||
57 | #define NFC_ECC_STATUS2 0x1E0E | ||
58 | #define NFC_SPAS 0x1E10 | ||
59 | #define NFC_WRPROT 0x1E12 | ||
60 | #define NFC_NF_WRPRST 0x1E18 | ||
61 | #define NFC_CONFIG1 0x1E1A | ||
62 | #define NFC_CONFIG2 0x1E1C | ||
63 | #define NFC_UNLOCKSTART_BLK0 0x1E20 | ||
64 | #define NFC_UNLOCKEND_BLK0 0x1E22 | ||
65 | #define NFC_UNLOCKSTART_BLK1 0x1E24 | ||
66 | #define NFC_UNLOCKEND_BLK1 0x1E26 | ||
67 | #define NFC_UNLOCKSTART_BLK2 0x1E28 | ||
68 | #define NFC_UNLOCKEND_BLK2 0x1E2A | ||
69 | #define NFC_UNLOCKSTART_BLK3 0x1E2C | ||
70 | #define NFC_UNLOCKEND_BLK3 0x1E2E | ||
71 | |||
72 | /* Bit Definitions: NFC_BUF_ADDR */ | ||
73 | #define NFC_RBA_MASK (7 << 0) | ||
74 | #define NFC_ACTIVE_CS_SHIFT 5 | ||
75 | #define NFC_ACTIVE_CS_MASK (3 << NFC_ACTIVE_CS_SHIFT) | ||
76 | |||
77 | /* Bit Definitions: NFC_CONFIG */ | ||
78 | #define NFC_BLS_UNLOCKED (1 << 1) | ||
79 | |||
80 | /* Bit Definitions: NFC_CONFIG1 */ | ||
81 | #define NFC_ECC_4BIT (1 << 0) | ||
82 | #define NFC_FULL_PAGE_DMA (1 << 1) | ||
83 | #define NFC_SPARE_ONLY (1 << 2) | ||
84 | #define NFC_ECC_ENABLE (1 << 3) | ||
85 | #define NFC_INT_MASK (1 << 4) | ||
86 | #define NFC_BIG_ENDIAN (1 << 5) | ||
87 | #define NFC_RESET (1 << 6) | ||
88 | #define NFC_CE (1 << 7) | ||
89 | #define NFC_ONE_CYCLE (1 << 8) | ||
90 | #define NFC_PPB_32 (0 << 9) | ||
91 | #define NFC_PPB_64 (1 << 9) | ||
92 | #define NFC_PPB_128 (2 << 9) | ||
93 | #define NFC_PPB_256 (3 << 9) | ||
94 | #define NFC_PPB_MASK (3 << 9) | ||
95 | #define NFC_FULL_PAGE_INT (1 << 11) | ||
96 | |||
97 | /* Bit Definitions: NFC_CONFIG2 */ | ||
98 | #define NFC_COMMAND (1 << 0) | ||
99 | #define NFC_ADDRESS (1 << 1) | ||
100 | #define NFC_INPUT (1 << 2) | ||
101 | #define NFC_OUTPUT (1 << 3) | ||
102 | #define NFC_ID (1 << 4) | ||
103 | #define NFC_STATUS (1 << 5) | ||
104 | #define NFC_CMD_FAIL (1 << 15) | ||
105 | #define NFC_INT (1 << 15) | ||
106 | |||
107 | /* Bit Definitions: NFC_WRPROT */ | ||
108 | #define NFC_WPC_LOCK_TIGHT (1 << 0) | ||
109 | #define NFC_WPC_LOCK (1 << 1) | ||
110 | #define NFC_WPC_UNLOCK (1 << 2) | ||
111 | |||
112 | #define DRV_NAME "mpc5121_nfc" | ||
113 | |||
114 | /* Timeouts */ | ||
115 | #define NFC_RESET_TIMEOUT 1000 /* 1 ms */ | ||
116 | #define NFC_TIMEOUT (HZ / 10) /* 1/10 s */ | ||
117 | |||
118 | struct mpc5121_nfc_prv { | ||
119 | struct mtd_info mtd; | ||
120 | struct nand_chip chip; | ||
121 | int irq; | ||
122 | void __iomem *regs; | ||
123 | struct clk *clk; | ||
124 | wait_queue_head_t irq_waitq; | ||
125 | uint column; | ||
126 | int spareonly; | ||
127 | void __iomem *csreg; | ||
128 | struct device *dev; | ||
129 | }; | ||
130 | |||
131 | static void mpc5121_nfc_done(struct mtd_info *mtd); | ||
132 | |||
133 | #ifdef CONFIG_MTD_PARTITIONS | ||
134 | static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL }; | ||
135 | #endif | ||
136 | |||
137 | /* Read NFC register */ | ||
138 | static inline u16 nfc_read(struct mtd_info *mtd, uint reg) | ||
139 | { | ||
140 | struct nand_chip *chip = mtd->priv; | ||
141 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
142 | |||
143 | return in_be16(prv->regs + reg); | ||
144 | } | ||
145 | |||
146 | /* Write NFC register */ | ||
147 | static inline void nfc_write(struct mtd_info *mtd, uint reg, u16 val) | ||
148 | { | ||
149 | struct nand_chip *chip = mtd->priv; | ||
150 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
151 | |||
152 | out_be16(prv->regs + reg, val); | ||
153 | } | ||
154 | |||
155 | /* Set bits in NFC register */ | ||
156 | static inline void nfc_set(struct mtd_info *mtd, uint reg, u16 bits) | ||
157 | { | ||
158 | nfc_write(mtd, reg, nfc_read(mtd, reg) | bits); | ||
159 | } | ||
160 | |||
161 | /* Clear bits in NFC register */ | ||
162 | static inline void nfc_clear(struct mtd_info *mtd, uint reg, u16 bits) | ||
163 | { | ||
164 | nfc_write(mtd, reg, nfc_read(mtd, reg) & ~bits); | ||
165 | } | ||
166 | |||
167 | /* Invoke address cycle */ | ||
168 | static inline void mpc5121_nfc_send_addr(struct mtd_info *mtd, u16 addr) | ||
169 | { | ||
170 | nfc_write(mtd, NFC_FLASH_ADDR, addr); | ||
171 | nfc_write(mtd, NFC_CONFIG2, NFC_ADDRESS); | ||
172 | mpc5121_nfc_done(mtd); | ||
173 | } | ||
174 | |||
175 | /* Invoke command cycle */ | ||
176 | static inline void mpc5121_nfc_send_cmd(struct mtd_info *mtd, u16 cmd) | ||
177 | { | ||
178 | nfc_write(mtd, NFC_FLASH_CMD, cmd); | ||
179 | nfc_write(mtd, NFC_CONFIG2, NFC_COMMAND); | ||
180 | mpc5121_nfc_done(mtd); | ||
181 | } | ||
182 | |||
183 | /* Send data from NFC buffers to NAND flash */ | ||
184 | static inline void mpc5121_nfc_send_prog_page(struct mtd_info *mtd) | ||
185 | { | ||
186 | nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK); | ||
187 | nfc_write(mtd, NFC_CONFIG2, NFC_INPUT); | ||
188 | mpc5121_nfc_done(mtd); | ||
189 | } | ||
190 | |||
191 | /* Receive data from NAND flash */ | ||
192 | static inline void mpc5121_nfc_send_read_page(struct mtd_info *mtd) | ||
193 | { | ||
194 | nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK); | ||
195 | nfc_write(mtd, NFC_CONFIG2, NFC_OUTPUT); | ||
196 | mpc5121_nfc_done(mtd); | ||
197 | } | ||
198 | |||
199 | /* Receive ID from NAND flash */ | ||
200 | static inline void mpc5121_nfc_send_read_id(struct mtd_info *mtd) | ||
201 | { | ||
202 | nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK); | ||
203 | nfc_write(mtd, NFC_CONFIG2, NFC_ID); | ||
204 | mpc5121_nfc_done(mtd); | ||
205 | } | ||
206 | |||
207 | /* Receive status from NAND flash */ | ||
208 | static inline void mpc5121_nfc_send_read_status(struct mtd_info *mtd) | ||
209 | { | ||
210 | nfc_clear(mtd, NFC_BUF_ADDR, NFC_RBA_MASK); | ||
211 | nfc_write(mtd, NFC_CONFIG2, NFC_STATUS); | ||
212 | mpc5121_nfc_done(mtd); | ||
213 | } | ||
214 | |||
215 | /* NFC interrupt handler */ | ||
216 | static irqreturn_t mpc5121_nfc_irq(int irq, void *data) | ||
217 | { | ||
218 | struct mtd_info *mtd = data; | ||
219 | struct nand_chip *chip = mtd->priv; | ||
220 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
221 | |||
222 | nfc_set(mtd, NFC_CONFIG1, NFC_INT_MASK); | ||
223 | wake_up(&prv->irq_waitq); | ||
224 | |||
225 | return IRQ_HANDLED; | ||
226 | } | ||
227 | |||
228 | /* Wait for operation complete */ | ||
229 | static void mpc5121_nfc_done(struct mtd_info *mtd) | ||
230 | { | ||
231 | struct nand_chip *chip = mtd->priv; | ||
232 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
233 | int rv; | ||
234 | |||
235 | if ((nfc_read(mtd, NFC_CONFIG2) & NFC_INT) == 0) { | ||
236 | nfc_clear(mtd, NFC_CONFIG1, NFC_INT_MASK); | ||
237 | rv = wait_event_timeout(prv->irq_waitq, | ||
238 | (nfc_read(mtd, NFC_CONFIG2) & NFC_INT), NFC_TIMEOUT); | ||
239 | |||
240 | if (!rv) | ||
241 | dev_warn(prv->dev, | ||
242 | "Timeout while waiting for interrupt.\n"); | ||
243 | } | ||
244 | |||
245 | nfc_clear(mtd, NFC_CONFIG2, NFC_INT); | ||
246 | } | ||
247 | |||
248 | /* Do address cycle(s) */ | ||
249 | static void mpc5121_nfc_addr_cycle(struct mtd_info *mtd, int column, int page) | ||
250 | { | ||
251 | struct nand_chip *chip = mtd->priv; | ||
252 | u32 pagemask = chip->pagemask; | ||
253 | |||
254 | if (column != -1) { | ||
255 | mpc5121_nfc_send_addr(mtd, column); | ||
256 | if (mtd->writesize > 512) | ||
257 | mpc5121_nfc_send_addr(mtd, column >> 8); | ||
258 | } | ||
259 | |||
260 | if (page != -1) { | ||
261 | do { | ||
262 | mpc5121_nfc_send_addr(mtd, page & 0xFF); | ||
263 | page >>= 8; | ||
264 | pagemask >>= 8; | ||
265 | } while (pagemask); | ||
266 | } | ||
267 | } | ||
268 | |||
269 | /* Control chip select signals */ | ||
270 | static void mpc5121_nfc_select_chip(struct mtd_info *mtd, int chip) | ||
271 | { | ||
272 | if (chip < 0) { | ||
273 | nfc_clear(mtd, NFC_CONFIG1, NFC_CE); | ||
274 | return; | ||
275 | } | ||
276 | |||
277 | nfc_clear(mtd, NFC_BUF_ADDR, NFC_ACTIVE_CS_MASK); | ||
278 | nfc_set(mtd, NFC_BUF_ADDR, (chip << NFC_ACTIVE_CS_SHIFT) & | ||
279 | NFC_ACTIVE_CS_MASK); | ||
280 | nfc_set(mtd, NFC_CONFIG1, NFC_CE); | ||
281 | } | ||
282 | |||
283 | /* Init external chip select logic on ADS5121 board */ | ||
284 | static int ads5121_chipselect_init(struct mtd_info *mtd) | ||
285 | { | ||
286 | struct nand_chip *chip = mtd->priv; | ||
287 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
288 | struct device_node *dn; | ||
289 | |||
290 | dn = of_find_compatible_node(NULL, NULL, "fsl,mpc5121ads-cpld"); | ||
291 | if (dn) { | ||
292 | prv->csreg = of_iomap(dn, 0); | ||
293 | of_node_put(dn); | ||
294 | if (!prv->csreg) | ||
295 | return -ENOMEM; | ||
296 | |||
297 | /* CPLD Register 9 controls NAND /CE Lines */ | ||
298 | prv->csreg += 9; | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | return -EINVAL; | ||
303 | } | ||
304 | |||
305 | /* Control chips select signal on ADS5121 board */ | ||
306 | static void ads5121_select_chip(struct mtd_info *mtd, int chip) | ||
307 | { | ||
308 | struct nand_chip *nand = mtd->priv; | ||
309 | struct mpc5121_nfc_prv *prv = nand->priv; | ||
310 | u8 v; | ||
311 | |||
312 | v = in_8(prv->csreg); | ||
313 | v |= 0x0F; | ||
314 | |||
315 | if (chip >= 0) { | ||
316 | mpc5121_nfc_select_chip(mtd, 0); | ||
317 | v &= ~(1 << chip); | ||
318 | } else | ||
319 | mpc5121_nfc_select_chip(mtd, -1); | ||
320 | |||
321 | out_8(prv->csreg, v); | ||
322 | } | ||
323 | |||
324 | /* Read NAND Ready/Busy signal */ | ||
325 | static int mpc5121_nfc_dev_ready(struct mtd_info *mtd) | ||
326 | { | ||
327 | /* | ||
328 | * NFC handles ready/busy signal internally. Therefore, this function | ||
329 | * always returns status as ready. | ||
330 | */ | ||
331 | return 1; | ||
332 | } | ||
333 | |||
334 | /* Write command to NAND flash */ | ||
335 | static void mpc5121_nfc_command(struct mtd_info *mtd, unsigned command, | ||
336 | int column, int page) | ||
337 | { | ||
338 | struct nand_chip *chip = mtd->priv; | ||
339 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
340 | |||
341 | prv->column = (column >= 0) ? column : 0; | ||
342 | prv->spareonly = 0; | ||
343 | |||
344 | switch (command) { | ||
345 | case NAND_CMD_PAGEPROG: | ||
346 | mpc5121_nfc_send_prog_page(mtd); | ||
347 | break; | ||
348 | /* | ||
349 | * NFC does not support sub-page reads and writes, | ||
350 | * so emulate them using full page transfers. | ||
351 | */ | ||
352 | case NAND_CMD_READ0: | ||
353 | column = 0; | ||
354 | break; | ||
355 | |||
356 | case NAND_CMD_READ1: | ||
357 | prv->column += 256; | ||
358 | command = NAND_CMD_READ0; | ||
359 | column = 0; | ||
360 | break; | ||
361 | |||
362 | case NAND_CMD_READOOB: | ||
363 | prv->spareonly = 1; | ||
364 | command = NAND_CMD_READ0; | ||
365 | column = 0; | ||
366 | break; | ||
367 | |||
368 | case NAND_CMD_SEQIN: | ||
369 | mpc5121_nfc_command(mtd, NAND_CMD_READ0, column, page); | ||
370 | column = 0; | ||
371 | break; | ||
372 | |||
373 | case NAND_CMD_ERASE1: | ||
374 | case NAND_CMD_ERASE2: | ||
375 | case NAND_CMD_READID: | ||
376 | case NAND_CMD_STATUS: | ||
377 | break; | ||
378 | |||
379 | default: | ||
380 | return; | ||
381 | } | ||
382 | |||
383 | mpc5121_nfc_send_cmd(mtd, command); | ||
384 | mpc5121_nfc_addr_cycle(mtd, column, page); | ||
385 | |||
386 | switch (command) { | ||
387 | case NAND_CMD_READ0: | ||
388 | if (mtd->writesize > 512) | ||
389 | mpc5121_nfc_send_cmd(mtd, NAND_CMD_READSTART); | ||
390 | mpc5121_nfc_send_read_page(mtd); | ||
391 | break; | ||
392 | |||
393 | case NAND_CMD_READID: | ||
394 | mpc5121_nfc_send_read_id(mtd); | ||
395 | break; | ||
396 | |||
397 | case NAND_CMD_STATUS: | ||
398 | mpc5121_nfc_send_read_status(mtd); | ||
399 | if (chip->options & NAND_BUSWIDTH_16) | ||
400 | prv->column = 1; | ||
401 | else | ||
402 | prv->column = 0; | ||
403 | break; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | /* Copy data from/to NFC spare buffers. */ | ||
408 | static void mpc5121_nfc_copy_spare(struct mtd_info *mtd, uint offset, | ||
409 | u8 *buffer, uint size, int wr) | ||
410 | { | ||
411 | struct nand_chip *nand = mtd->priv; | ||
412 | struct mpc5121_nfc_prv *prv = nand->priv; | ||
413 | uint o, s, sbsize, blksize; | ||
414 | |||
415 | /* | ||
416 | * NAND spare area is available through NFC spare buffers. | ||
417 | * The NFC divides spare area into (page_size / 512) chunks. | ||
418 | * Each chunk is placed into separate spare memory area, using | ||
419 | * first (spare_size / num_of_chunks) bytes of the buffer. | ||
420 | * | ||
421 | * For NAND device in which the spare area is not divided fully | ||
422 | * by the number of chunks, number of used bytes in each spare | ||
423 | * buffer is rounded down to the nearest even number of bytes, | ||
424 | * and all remaining bytes are added to the last used spare area. | ||
425 | * | ||
426 | * For more information read section 26.6.10 of MPC5121e | ||
427 | * Microcontroller Reference Manual, Rev. 3. | ||
428 | */ | ||
429 | |||
430 | /* Calculate number of valid bytes in each spare buffer */ | ||
431 | sbsize = (mtd->oobsize / (mtd->writesize / 512)) & ~1; | ||
432 | |||
433 | while (size) { | ||
434 | /* Calculate spare buffer number */ | ||
435 | s = offset / sbsize; | ||
436 | if (s > NFC_SPARE_BUFFERS - 1) | ||
437 | s = NFC_SPARE_BUFFERS - 1; | ||
438 | |||
439 | /* | ||
440 | * Calculate offset to requested data block in selected spare | ||
441 | * buffer and its size. | ||
442 | */ | ||
443 | o = offset - (s * sbsize); | ||
444 | blksize = min(sbsize - o, size); | ||
445 | |||
446 | if (wr) | ||
447 | memcpy_toio(prv->regs + NFC_SPARE_AREA(s) + o, | ||
448 | buffer, blksize); | ||
449 | else | ||
450 | memcpy_fromio(buffer, | ||
451 | prv->regs + NFC_SPARE_AREA(s) + o, blksize); | ||
452 | |||
453 | buffer += blksize; | ||
454 | offset += blksize; | ||
455 | size -= blksize; | ||
456 | }; | ||
457 | } | ||
458 | |||
459 | /* Copy data from/to NFC main and spare buffers */ | ||
460 | static void mpc5121_nfc_buf_copy(struct mtd_info *mtd, u_char *buf, int len, | ||
461 | int wr) | ||
462 | { | ||
463 | struct nand_chip *chip = mtd->priv; | ||
464 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
465 | uint c = prv->column; | ||
466 | uint l; | ||
467 | |||
468 | /* Handle spare area access */ | ||
469 | if (prv->spareonly || c >= mtd->writesize) { | ||
470 | /* Calculate offset from beginning of spare area */ | ||
471 | if (c >= mtd->writesize) | ||
472 | c -= mtd->writesize; | ||
473 | |||
474 | prv->column += len; | ||
475 | mpc5121_nfc_copy_spare(mtd, c, buf, len, wr); | ||
476 | return; | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * Handle main area access - limit copy length to prevent | ||
481 | * crossing main/spare boundary. | ||
482 | */ | ||
483 | l = min((uint)len, mtd->writesize - c); | ||
484 | prv->column += l; | ||
485 | |||
486 | if (wr) | ||
487 | memcpy_toio(prv->regs + NFC_MAIN_AREA(0) + c, buf, l); | ||
488 | else | ||
489 | memcpy_fromio(buf, prv->regs + NFC_MAIN_AREA(0) + c, l); | ||
490 | |||
491 | /* Handle crossing main/spare boundary */ | ||
492 | if (l != len) { | ||
493 | buf += l; | ||
494 | len -= l; | ||
495 | mpc5121_nfc_buf_copy(mtd, buf, len, wr); | ||
496 | } | ||
497 | } | ||
498 | |||
499 | /* Read data from NFC buffers */ | ||
500 | static void mpc5121_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) | ||
501 | { | ||
502 | mpc5121_nfc_buf_copy(mtd, buf, len, 0); | ||
503 | } | ||
504 | |||
505 | /* Write data to NFC buffers */ | ||
506 | static void mpc5121_nfc_write_buf(struct mtd_info *mtd, | ||
507 | const u_char *buf, int len) | ||
508 | { | ||
509 | mpc5121_nfc_buf_copy(mtd, (u_char *)buf, len, 1); | ||
510 | } | ||
511 | |||
512 | /* Compare buffer with NAND flash */ | ||
513 | static int mpc5121_nfc_verify_buf(struct mtd_info *mtd, | ||
514 | const u_char *buf, int len) | ||
515 | { | ||
516 | u_char tmp[256]; | ||
517 | uint bsize; | ||
518 | |||
519 | while (len) { | ||
520 | bsize = min(len, 256); | ||
521 | mpc5121_nfc_read_buf(mtd, tmp, bsize); | ||
522 | |||
523 | if (memcmp(buf, tmp, bsize)) | ||
524 | return 1; | ||
525 | |||
526 | buf += bsize; | ||
527 | len -= bsize; | ||
528 | } | ||
529 | |||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | /* Read byte from NFC buffers */ | ||
534 | static u8 mpc5121_nfc_read_byte(struct mtd_info *mtd) | ||
535 | { | ||
536 | u8 tmp; | ||
537 | |||
538 | mpc5121_nfc_read_buf(mtd, &tmp, sizeof(tmp)); | ||
539 | |||
540 | return tmp; | ||
541 | } | ||
542 | |||
543 | /* Read word from NFC buffers */ | ||
544 | static u16 mpc5121_nfc_read_word(struct mtd_info *mtd) | ||
545 | { | ||
546 | u16 tmp; | ||
547 | |||
548 | mpc5121_nfc_read_buf(mtd, (u_char *)&tmp, sizeof(tmp)); | ||
549 | |||
550 | return tmp; | ||
551 | } | ||
552 | |||
553 | /* | ||
554 | * Read NFC configuration from Reset Config Word | ||
555 | * | ||
556 | * NFC is configured during reset in basis of information stored | ||
557 | * in Reset Config Word. There is no other way to set NAND block | ||
558 | * size, spare size and bus width. | ||
559 | */ | ||
560 | static int mpc5121_nfc_read_hw_config(struct mtd_info *mtd) | ||
561 | { | ||
562 | struct nand_chip *chip = mtd->priv; | ||
563 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
564 | struct mpc512x_reset_module *rm; | ||
565 | struct device_node *rmnode; | ||
566 | uint rcw_pagesize = 0; | ||
567 | uint rcw_sparesize = 0; | ||
568 | uint rcw_width; | ||
569 | uint rcwh; | ||
570 | uint romloc, ps; | ||
571 | |||
572 | rmnode = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset"); | ||
573 | if (!rmnode) { | ||
574 | dev_err(prv->dev, "Missing 'fsl,mpc5121-reset' " | ||
575 | "node in device tree!\n"); | ||
576 | return -ENODEV; | ||
577 | } | ||
578 | |||
579 | rm = of_iomap(rmnode, 0); | ||
580 | if (!rm) { | ||
581 | dev_err(prv->dev, "Error mapping reset module node!\n"); | ||
582 | return -EBUSY; | ||
583 | } | ||
584 | |||
585 | rcwh = in_be32(&rm->rcwhr); | ||
586 | |||
587 | /* Bit 6: NFC bus width */ | ||
588 | rcw_width = ((rcwh >> 6) & 0x1) ? 2 : 1; | ||
589 | |||
590 | /* Bit 7: NFC Page/Spare size */ | ||
591 | ps = (rcwh >> 7) & 0x1; | ||
592 | |||
593 | /* Bits [22:21]: ROM Location */ | ||
594 | romloc = (rcwh >> 21) & 0x3; | ||
595 | |||
596 | /* Decode RCW bits */ | ||
597 | switch ((ps << 2) | romloc) { | ||
598 | case 0x00: | ||
599 | case 0x01: | ||
600 | rcw_pagesize = 512; | ||
601 | rcw_sparesize = 16; | ||
602 | break; | ||
603 | case 0x02: | ||
604 | case 0x03: | ||
605 | rcw_pagesize = 4096; | ||
606 | rcw_sparesize = 128; | ||
607 | break; | ||
608 | case 0x04: | ||
609 | case 0x05: | ||
610 | rcw_pagesize = 2048; | ||
611 | rcw_sparesize = 64; | ||
612 | break; | ||
613 | case 0x06: | ||
614 | case 0x07: | ||
615 | rcw_pagesize = 4096; | ||
616 | rcw_sparesize = 218; | ||
617 | break; | ||
618 | } | ||
619 | |||
620 | mtd->writesize = rcw_pagesize; | ||
621 | mtd->oobsize = rcw_sparesize; | ||
622 | if (rcw_width == 2) | ||
623 | chip->options |= NAND_BUSWIDTH_16; | ||
624 | |||
625 | dev_notice(prv->dev, "Configured for " | ||
626 | "%u-bit NAND, page size %u " | ||
627 | "with %u spare.\n", | ||
628 | rcw_width * 8, rcw_pagesize, | ||
629 | rcw_sparesize); | ||
630 | iounmap(rm); | ||
631 | of_node_put(rmnode); | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | /* Free driver resources */ | ||
636 | static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) | ||
637 | { | ||
638 | struct nand_chip *chip = mtd->priv; | ||
639 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
640 | |||
641 | if (prv->clk) { | ||
642 | clk_disable(prv->clk); | ||
643 | clk_put(prv->clk); | ||
644 | } | ||
645 | |||
646 | if (prv->csreg) | ||
647 | iounmap(prv->csreg); | ||
648 | } | ||
649 | |||
650 | static int __devinit mpc5121_nfc_probe(struct of_device *op, | ||
651 | const struct of_device_id *match) | ||
652 | { | ||
653 | struct device_node *rootnode, *dn = op->node; | ||
654 | struct device *dev = &op->dev; | ||
655 | struct mpc5121_nfc_prv *prv; | ||
656 | struct resource res; | ||
657 | struct mtd_info *mtd; | ||
658 | #ifdef CONFIG_MTD_PARTITIONS | ||
659 | struct mtd_partition *parts; | ||
660 | #endif | ||
661 | struct nand_chip *chip; | ||
662 | unsigned long regs_paddr, regs_size; | ||
663 | const uint *chips_no; | ||
664 | int resettime = 0; | ||
665 | int retval = 0; | ||
666 | int rev, len; | ||
667 | |||
668 | /* | ||
669 | * Check SoC revision. This driver supports only NFC | ||
670 | * in MPC5121 revision 2 and MPC5123 revision 3. | ||
671 | */ | ||
672 | rev = (mfspr(SPRN_SVR) >> 4) & 0xF; | ||
673 | if ((rev != 2) && (rev != 3)) { | ||
674 | dev_err(dev, "SoC revision %u is not supported!\n", rev); | ||
675 | return -ENXIO; | ||
676 | } | ||
677 | |||
678 | prv = devm_kzalloc(dev, sizeof(*prv), GFP_KERNEL); | ||
679 | if (!prv) { | ||
680 | dev_err(dev, "Memory exhausted!\n"); | ||
681 | return -ENOMEM; | ||
682 | } | ||
683 | |||
684 | mtd = &prv->mtd; | ||
685 | chip = &prv->chip; | ||
686 | |||
687 | mtd->priv = chip; | ||
688 | chip->priv = prv; | ||
689 | prv->dev = dev; | ||
690 | |||
691 | /* Read NFC configuration from Reset Config Word */ | ||
692 | retval = mpc5121_nfc_read_hw_config(mtd); | ||
693 | if (retval) { | ||
694 | dev_err(dev, "Unable to read NFC config!\n"); | ||
695 | return retval; | ||
696 | } | ||
697 | |||
698 | prv->irq = irq_of_parse_and_map(dn, 0); | ||
699 | if (prv->irq == NO_IRQ) { | ||
700 | dev_err(dev, "Error mapping IRQ!\n"); | ||
701 | return -EINVAL; | ||
702 | } | ||
703 | |||
704 | retval = of_address_to_resource(dn, 0, &res); | ||
705 | if (retval) { | ||
706 | dev_err(dev, "Error parsing memory region!\n"); | ||
707 | return retval; | ||
708 | } | ||
709 | |||
710 | chips_no = of_get_property(dn, "chips", &len); | ||
711 | if (!chips_no || len != sizeof(*chips_no)) { | ||
712 | dev_err(dev, "Invalid/missing 'chips' property!\n"); | ||
713 | return -EINVAL; | ||
714 | } | ||
715 | |||
716 | regs_paddr = res.start; | ||
717 | regs_size = res.end - res.start + 1; | ||
718 | |||
719 | if (!devm_request_mem_region(dev, regs_paddr, regs_size, DRV_NAME)) { | ||
720 | dev_err(dev, "Error requesting memory region!\n"); | ||
721 | return -EBUSY; | ||
722 | } | ||
723 | |||
724 | prv->regs = devm_ioremap(dev, regs_paddr, regs_size); | ||
725 | if (!prv->regs) { | ||
726 | dev_err(dev, "Error mapping memory region!\n"); | ||
727 | return -ENOMEM; | ||
728 | } | ||
729 | |||
730 | mtd->name = "MPC5121 NAND"; | ||
731 | chip->dev_ready = mpc5121_nfc_dev_ready; | ||
732 | chip->cmdfunc = mpc5121_nfc_command; | ||
733 | chip->read_byte = mpc5121_nfc_read_byte; | ||
734 | chip->read_word = mpc5121_nfc_read_word; | ||
735 | chip->read_buf = mpc5121_nfc_read_buf; | ||
736 | chip->write_buf = mpc5121_nfc_write_buf; | ||
737 | chip->verify_buf = mpc5121_nfc_verify_buf; | ||
738 | chip->select_chip = mpc5121_nfc_select_chip; | ||
739 | chip->options = NAND_NO_AUTOINCR | NAND_USE_FLASH_BBT; | ||
740 | chip->ecc.mode = NAND_ECC_SOFT; | ||
741 | |||
742 | /* Support external chip-select logic on ADS5121 board */ | ||
743 | rootnode = of_find_node_by_path("/"); | ||
744 | if (of_device_is_compatible(rootnode, "fsl,mpc5121ads")) { | ||
745 | retval = ads5121_chipselect_init(mtd); | ||
746 | if (retval) { | ||
747 | dev_err(dev, "Chipselect init error!\n"); | ||
748 | of_node_put(rootnode); | ||
749 | return retval; | ||
750 | } | ||
751 | |||
752 | chip->select_chip = ads5121_select_chip; | ||
753 | } | ||
754 | of_node_put(rootnode); | ||
755 | |||
756 | /* Enable NFC clock */ | ||
757 | prv->clk = clk_get(dev, "nfc_clk"); | ||
758 | if (!prv->clk) { | ||
759 | dev_err(dev, "Unable to acquire NFC clock!\n"); | ||
760 | retval = -ENODEV; | ||
761 | goto error; | ||
762 | } | ||
763 | |||
764 | clk_enable(prv->clk); | ||
765 | |||
766 | /* Reset NAND Flash controller */ | ||
767 | nfc_set(mtd, NFC_CONFIG1, NFC_RESET); | ||
768 | while (nfc_read(mtd, NFC_CONFIG1) & NFC_RESET) { | ||
769 | if (resettime++ >= NFC_RESET_TIMEOUT) { | ||
770 | dev_err(dev, "Timeout while resetting NFC!\n"); | ||
771 | retval = -EINVAL; | ||
772 | goto error; | ||
773 | } | ||
774 | |||
775 | udelay(1); | ||
776 | } | ||
777 | |||
778 | /* Enable write to NFC memory */ | ||
779 | nfc_write(mtd, NFC_CONFIG, NFC_BLS_UNLOCKED); | ||
780 | |||
781 | /* Enable write to all NAND pages */ | ||
782 | nfc_write(mtd, NFC_UNLOCKSTART_BLK0, 0x0000); | ||
783 | nfc_write(mtd, NFC_UNLOCKEND_BLK0, 0xFFFF); | ||
784 | nfc_write(mtd, NFC_WRPROT, NFC_WPC_UNLOCK); | ||
785 | |||
786 | /* | ||
787 | * Setup NFC: | ||
788 | * - Big Endian transfers, | ||
789 | * - Interrupt after full page read/write. | ||
790 | */ | ||
791 | nfc_write(mtd, NFC_CONFIG1, NFC_BIG_ENDIAN | NFC_INT_MASK | | ||
792 | NFC_FULL_PAGE_INT); | ||
793 | |||
794 | /* Set spare area size */ | ||
795 | nfc_write(mtd, NFC_SPAS, mtd->oobsize >> 1); | ||
796 | |||
797 | init_waitqueue_head(&prv->irq_waitq); | ||
798 | retval = devm_request_irq(dev, prv->irq, &mpc5121_nfc_irq, 0, DRV_NAME, | ||
799 | mtd); | ||
800 | if (retval) { | ||
801 | dev_err(dev, "Error requesting IRQ!\n"); | ||
802 | goto error; | ||
803 | } | ||
804 | |||
805 | /* Detect NAND chips */ | ||
806 | if (nand_scan(mtd, *chips_no)) { | ||
807 | dev_err(dev, "NAND Flash not found !\n"); | ||
808 | devm_free_irq(dev, prv->irq, mtd); | ||
809 | retval = -ENXIO; | ||
810 | goto error; | ||
811 | } | ||
812 | |||
813 | /* Set erase block size */ | ||
814 | switch (mtd->erasesize / mtd->writesize) { | ||
815 | case 32: | ||
816 | nfc_set(mtd, NFC_CONFIG1, NFC_PPB_32); | ||
817 | break; | ||
818 | |||
819 | case 64: | ||
820 | nfc_set(mtd, NFC_CONFIG1, NFC_PPB_64); | ||
821 | break; | ||
822 | |||
823 | case 128: | ||
824 | nfc_set(mtd, NFC_CONFIG1, NFC_PPB_128); | ||
825 | break; | ||
826 | |||
827 | case 256: | ||
828 | nfc_set(mtd, NFC_CONFIG1, NFC_PPB_256); | ||
829 | break; | ||
830 | |||
831 | default: | ||
832 | dev_err(dev, "Unsupported NAND flash!\n"); | ||
833 | devm_free_irq(dev, prv->irq, mtd); | ||
834 | retval = -ENXIO; | ||
835 | goto error; | ||
836 | } | ||
837 | |||
838 | dev_set_drvdata(dev, mtd); | ||
839 | |||
840 | /* Register device in MTD */ | ||
841 | #ifdef CONFIG_MTD_PARTITIONS | ||
842 | retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0); | ||
843 | #ifdef CONFIG_MTD_OF_PARTS | ||
844 | if (retval == 0) | ||
845 | retval = of_mtd_parse_partitions(dev, dn, &parts); | ||
846 | #endif | ||
847 | if (retval < 0) { | ||
848 | dev_err(dev, "Error parsing MTD partitions!\n"); | ||
849 | devm_free_irq(dev, prv->irq, mtd); | ||
850 | retval = -EINVAL; | ||
851 | goto error; | ||
852 | } | ||
853 | |||
854 | if (retval > 0) | ||
855 | retval = add_mtd_partitions(mtd, parts, retval); | ||
856 | else | ||
857 | #endif | ||
858 | retval = add_mtd_device(mtd); | ||
859 | |||
860 | if (retval) { | ||
861 | dev_err(dev, "Error adding MTD device!\n"); | ||
862 | devm_free_irq(dev, prv->irq, mtd); | ||
863 | goto error; | ||
864 | } | ||
865 | |||
866 | return 0; | ||
867 | error: | ||
868 | mpc5121_nfc_free(dev, mtd); | ||
869 | return retval; | ||
870 | } | ||
871 | |||
872 | static int __devexit mpc5121_nfc_remove(struct of_device *op) | ||
873 | { | ||
874 | struct device *dev = &op->dev; | ||
875 | struct mtd_info *mtd = dev_get_drvdata(dev); | ||
876 | struct nand_chip *chip = mtd->priv; | ||
877 | struct mpc5121_nfc_prv *prv = chip->priv; | ||
878 | |||
879 | nand_release(mtd); | ||
880 | devm_free_irq(dev, prv->irq, mtd); | ||
881 | mpc5121_nfc_free(dev, mtd); | ||
882 | |||
883 | return 0; | ||
884 | } | ||
885 | |||
886 | static struct of_device_id mpc5121_nfc_match[] __devinitdata = { | ||
887 | { .compatible = "fsl,mpc5121-nfc", }, | ||
888 | {}, | ||
889 | }; | ||
890 | |||
891 | static struct of_platform_driver mpc5121_nfc_driver = { | ||
892 | .match_table = mpc5121_nfc_match, | ||
893 | .probe = mpc5121_nfc_probe, | ||
894 | .remove = __devexit_p(mpc5121_nfc_remove), | ||
895 | .driver = { | ||
896 | .name = DRV_NAME, | ||
897 | .owner = THIS_MODULE, | ||
898 | }, | ||
899 | }; | ||
900 | |||
901 | static int __init mpc5121_nfc_init(void) | ||
902 | { | ||
903 | return of_register_platform_driver(&mpc5121_nfc_driver); | ||
904 | } | ||
905 | |||
906 | module_init(mpc5121_nfc_init); | ||
907 | |||
908 | static void __exit mpc5121_nfc_cleanup(void) | ||
909 | { | ||
910 | of_unregister_platform_driver(&mpc5121_nfc_driver); | ||
911 | } | ||
912 | |||
913 | module_exit(mpc5121_nfc_cleanup); | ||
914 | |||
915 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
916 | MODULE_DESCRIPTION("MPC5121 NAND MTD driver"); | ||
917 | MODULE_LICENSE("GPL"); | ||