blob: 6736822c4751bda8269029c33979bc224e8371de [file] [log] [blame]
Vimal Singh67ce04b2009-05-12 13:47:03 -07001/*
2 * Copyright © 2004 Texas Instruments, Jian Zhang <jzhang@ti.com>
3 * Copyright © 2004 Micron Technology Inc.
4 * Copyright © 2004 David Brownell
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/platform_device.h>
12#include <linux/dma-mapping.h>
13#include <linux/delay.h>
vimal singhc276aca2009-06-27 11:07:06 +053014#include <linux/jiffies.h>
15#include <linux/sched.h>
Vimal Singh67ce04b2009-05-12 13:47:03 -070016#include <linux/mtd/mtd.h>
17#include <linux/mtd/nand.h>
18#include <linux/mtd/partitions.h>
19#include <linux/io.h>
20
21#include <asm/dma.h>
22
23#include <mach/gpmc.h>
24#include <mach/nand.h>
25
26#define GPMC_IRQ_STATUS 0x18
27#define GPMC_ECC_CONFIG 0x1F4
28#define GPMC_ECC_CONTROL 0x1F8
29#define GPMC_ECC_SIZE_CONFIG 0x1FC
30#define GPMC_ECC1_RESULT 0x200
31
32#define DRIVER_NAME "omap2-nand"
33
34/* size (4 KiB) for IO mapping */
35#define NAND_IO_SIZE SZ_4K
36
37#define NAND_WP_OFF 0
38#define NAND_WP_BIT 0x00000010
39#define WR_RD_PIN_MONITORING 0x00600000
40
41#define GPMC_BUF_FULL 0x00000001
42#define GPMC_BUF_EMPTY 0x00000000
43
44#define NAND_Ecc_P1e (1 << 0)
45#define NAND_Ecc_P2e (1 << 1)
46#define NAND_Ecc_P4e (1 << 2)
47#define NAND_Ecc_P8e (1 << 3)
48#define NAND_Ecc_P16e (1 << 4)
49#define NAND_Ecc_P32e (1 << 5)
50#define NAND_Ecc_P64e (1 << 6)
51#define NAND_Ecc_P128e (1 << 7)
52#define NAND_Ecc_P256e (1 << 8)
53#define NAND_Ecc_P512e (1 << 9)
54#define NAND_Ecc_P1024e (1 << 10)
55#define NAND_Ecc_P2048e (1 << 11)
56
57#define NAND_Ecc_P1o (1 << 16)
58#define NAND_Ecc_P2o (1 << 17)
59#define NAND_Ecc_P4o (1 << 18)
60#define NAND_Ecc_P8o (1 << 19)
61#define NAND_Ecc_P16o (1 << 20)
62#define NAND_Ecc_P32o (1 << 21)
63#define NAND_Ecc_P64o (1 << 22)
64#define NAND_Ecc_P128o (1 << 23)
65#define NAND_Ecc_P256o (1 << 24)
66#define NAND_Ecc_P512o (1 << 25)
67#define NAND_Ecc_P1024o (1 << 26)
68#define NAND_Ecc_P2048o (1 << 27)
69
70#define TF(value) (value ? 1 : 0)
71
72#define P2048e(a) (TF(a & NAND_Ecc_P2048e) << 0)
73#define P2048o(a) (TF(a & NAND_Ecc_P2048o) << 1)
74#define P1e(a) (TF(a & NAND_Ecc_P1e) << 2)
75#define P1o(a) (TF(a & NAND_Ecc_P1o) << 3)
76#define P2e(a) (TF(a & NAND_Ecc_P2e) << 4)
77#define P2o(a) (TF(a & NAND_Ecc_P2o) << 5)
78#define P4e(a) (TF(a & NAND_Ecc_P4e) << 6)
79#define P4o(a) (TF(a & NAND_Ecc_P4o) << 7)
80
81#define P8e(a) (TF(a & NAND_Ecc_P8e) << 0)
82#define P8o(a) (TF(a & NAND_Ecc_P8o) << 1)
83#define P16e(a) (TF(a & NAND_Ecc_P16e) << 2)
84#define P16o(a) (TF(a & NAND_Ecc_P16o) << 3)
85#define P32e(a) (TF(a & NAND_Ecc_P32e) << 4)
86#define P32o(a) (TF(a & NAND_Ecc_P32o) << 5)
87#define P64e(a) (TF(a & NAND_Ecc_P64e) << 6)
88#define P64o(a) (TF(a & NAND_Ecc_P64o) << 7)
89
90#define P128e(a) (TF(a & NAND_Ecc_P128e) << 0)
91#define P128o(a) (TF(a & NAND_Ecc_P128o) << 1)
92#define P256e(a) (TF(a & NAND_Ecc_P256e) << 2)
93#define P256o(a) (TF(a & NAND_Ecc_P256o) << 3)
94#define P512e(a) (TF(a & NAND_Ecc_P512e) << 4)
95#define P512o(a) (TF(a & NAND_Ecc_P512o) << 5)
96#define P1024e(a) (TF(a & NAND_Ecc_P1024e) << 6)
97#define P1024o(a) (TF(a & NAND_Ecc_P1024o) << 7)
98
99#define P8e_s(a) (TF(a & NAND_Ecc_P8e) << 0)
100#define P8o_s(a) (TF(a & NAND_Ecc_P8o) << 1)
101#define P16e_s(a) (TF(a & NAND_Ecc_P16e) << 2)
102#define P16o_s(a) (TF(a & NAND_Ecc_P16o) << 3)
103#define P1e_s(a) (TF(a & NAND_Ecc_P1e) << 4)
104#define P1o_s(a) (TF(a & NAND_Ecc_P1o) << 5)
105#define P2e_s(a) (TF(a & NAND_Ecc_P2e) << 6)
106#define P2o_s(a) (TF(a & NAND_Ecc_P2o) << 7)
107
108#define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0)
109#define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1)
110
111#ifdef CONFIG_MTD_PARTITIONS
112static const char *part_probes[] = { "cmdlinepart", NULL };
113#endif
114
vimal singh59e9c5a2009-07-13 16:26:24 +0530115#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
116static int use_prefetch = 1;
117
118/* "modprobe ... use_prefetch=0" etc */
119module_param(use_prefetch, bool, 0);
120MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
121#else
122const int use_prefetch;
123#endif
124
Vimal Singh67ce04b2009-05-12 13:47:03 -0700125struct omap_nand_info {
126 struct nand_hw_control controller;
127 struct omap_nand_platform_data *pdata;
128 struct mtd_info mtd;
129 struct mtd_partition *parts;
130 struct nand_chip nand;
131 struct platform_device *pdev;
132
133 int gpmc_cs;
134 unsigned long phys_base;
135 void __iomem *gpmc_cs_baseaddr;
136 void __iomem *gpmc_baseaddr;
vimal singh59e9c5a2009-07-13 16:26:24 +0530137 void __iomem *nand_pref_fifo_add;
Vimal Singh67ce04b2009-05-12 13:47:03 -0700138};
139
140/**
141 * omap_nand_wp - This function enable or disable the Write Protect feature
142 * @mtd: MTD device structure
143 * @mode: WP ON/OFF
144 */
145static void omap_nand_wp(struct mtd_info *mtd, int mode)
146{
147 struct omap_nand_info *info = container_of(mtd,
148 struct omap_nand_info, mtd);
149
150 unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG);
151
152 if (mode)
153 config &= ~(NAND_WP_BIT); /* WP is ON */
154 else
155 config |= (NAND_WP_BIT); /* WP is OFF */
156
157 __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG));
158}
159
160/**
161 * omap_hwcontrol - hardware specific access to control-lines
162 * @mtd: MTD device structure
163 * @cmd: command to device
164 * @ctrl:
165 * NAND_NCE: bit 0 -> don't care
166 * NAND_CLE: bit 1 -> Command Latch
167 * NAND_ALE: bit 2 -> Address Latch
168 *
169 * NOTE: boards may use different bits for these!!
170 */
171static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
172{
173 struct omap_nand_info *info = container_of(mtd,
174 struct omap_nand_info, mtd);
175 switch (ctrl) {
176 case NAND_CTRL_CHANGE | NAND_CTRL_CLE:
177 info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
178 GPMC_CS_NAND_COMMAND;
179 info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
180 GPMC_CS_NAND_DATA;
181 break;
182
183 case NAND_CTRL_CHANGE | NAND_CTRL_ALE:
184 info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
185 GPMC_CS_NAND_ADDRESS;
186 info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
187 GPMC_CS_NAND_DATA;
188 break;
189
190 case NAND_CTRL_CHANGE | NAND_NCE:
191 info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr +
192 GPMC_CS_NAND_DATA;
193 info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr +
194 GPMC_CS_NAND_DATA;
195 break;
196 }
197
198 if (cmd != NAND_CMD_NONE)
199 __raw_writeb(cmd, info->nand.IO_ADDR_W);
200}
201
202/**
vimal singh59e9c5a2009-07-13 16:26:24 +0530203 * omap_read_buf8 - read data from NAND controller into buffer
204 * @mtd: MTD device structure
205 * @buf: buffer to store date
206 * @len: number of bytes to read
207 */
208static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len)
209{
210 struct nand_chip *nand = mtd->priv;
211
212 ioread8_rep(nand->IO_ADDR_R, buf, len);
213}
214
215/**
216 * omap_write_buf8 - write buffer to NAND controller
217 * @mtd: MTD device structure
218 * @buf: data buffer
219 * @len: number of bytes to write
220 */
221static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len)
222{
223 struct omap_nand_info *info = container_of(mtd,
224 struct omap_nand_info, mtd);
225 u_char *p = (u_char *)buf;
226
227 while (len--) {
228 iowrite8(*p++, info->nand.IO_ADDR_W);
229 while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
230 GPMC_STATUS) & GPMC_BUF_FULL));
231 }
232}
233
234/**
Vimal Singh67ce04b2009-05-12 13:47:03 -0700235 * omap_read_buf16 - read data from NAND controller into buffer
236 * @mtd: MTD device structure
237 * @buf: buffer to store date
238 * @len: number of bytes to read
239 */
240static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
241{
242 struct nand_chip *nand = mtd->priv;
243
vimal singh59e9c5a2009-07-13 16:26:24 +0530244 ioread16_rep(nand->IO_ADDR_R, buf, len / 2);
Vimal Singh67ce04b2009-05-12 13:47:03 -0700245}
246
247/**
248 * omap_write_buf16 - write buffer to NAND controller
249 * @mtd: MTD device structure
250 * @buf: data buffer
251 * @len: number of bytes to write
252 */
253static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len)
254{
255 struct omap_nand_info *info = container_of(mtd,
256 struct omap_nand_info, mtd);
257 u16 *p = (u16 *) buf;
258
259 /* FIXME try bursts of writesw() or DMA ... */
260 len >>= 1;
261
262 while (len--) {
vimal singh59e9c5a2009-07-13 16:26:24 +0530263 iowrite16(*p++, info->nand.IO_ADDR_W);
Vimal Singh67ce04b2009-05-12 13:47:03 -0700264
265 while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr +
266 GPMC_STATUS) & GPMC_BUF_FULL))
267 ;
268 }
269}
vimal singh59e9c5a2009-07-13 16:26:24 +0530270
271/**
272 * omap_read_buf_pref - read data from NAND controller into buffer
273 * @mtd: MTD device structure
274 * @buf: buffer to store date
275 * @len: number of bytes to read
276 */
277static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
278{
279 struct omap_nand_info *info = container_of(mtd,
280 struct omap_nand_info, mtd);
281 uint32_t pfpw_status = 0, r_count = 0;
282 int ret = 0;
283 u32 *p = (u32 *)buf;
284
285 /* take care of subpage reads */
286 for (; len % 4 != 0; ) {
287 *buf++ = __raw_readb(info->nand.IO_ADDR_R);
288 len--;
289 }
290 p = (u32 *) buf;
291
292 /* configure and start prefetch transfer */
293 ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
294 if (ret) {
295 /* PFPW engine is busy, use cpu copy method */
296 if (info->nand.options & NAND_BUSWIDTH_16)
297 omap_read_buf16(mtd, buf, len);
298 else
299 omap_read_buf8(mtd, buf, len);
300 } else {
301 do {
302 pfpw_status = gpmc_prefetch_status();
303 r_count = ((pfpw_status >> 24) & 0x7F) >> 2;
304 ioread32_rep(info->nand_pref_fifo_add, p, r_count);
305 p += r_count;
306 len -= r_count << 2;
307 } while (len);
308
309 /* disable and stop the PFPW engine */
310 gpmc_prefetch_reset();
311 }
312}
313
314/**
315 * omap_write_buf_pref - write buffer to NAND controller
316 * @mtd: MTD device structure
317 * @buf: data buffer
318 * @len: number of bytes to write
319 */
320static void omap_write_buf_pref(struct mtd_info *mtd,
321 const u_char *buf, int len)
322{
323 struct omap_nand_info *info = container_of(mtd,
324 struct omap_nand_info, mtd);
325 uint32_t pfpw_status = 0, w_count = 0;
326 int i = 0, ret = 0;
327 u16 *p = (u16 *) buf;
328
329 /* take care of subpage writes */
330 if (len % 2 != 0) {
331 writeb(*buf, info->nand.IO_ADDR_R);
332 p = (u16 *)(buf + 1);
333 len--;
334 }
335
336 /* configure and start prefetch transfer */
337 ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
338 if (ret) {
339 /* PFPW engine is busy, use cpu copy method */
340 if (info->nand.options & NAND_BUSWIDTH_16)
341 omap_write_buf16(mtd, buf, len);
342 else
343 omap_write_buf8(mtd, buf, len);
344 } else {
345 pfpw_status = gpmc_prefetch_status();
346 while (pfpw_status & 0x3FFF) {
347 w_count = ((pfpw_status >> 24) & 0x7F) >> 1;
348 for (i = 0; (i < w_count) && len; i++, len -= 2)
349 iowrite16(*p++, info->nand_pref_fifo_add);
350 pfpw_status = gpmc_prefetch_status();
351 }
352
353 /* disable and stop the PFPW engine */
354 gpmc_prefetch_reset();
355 }
356}
357
Vimal Singh67ce04b2009-05-12 13:47:03 -0700358/**
359 * omap_verify_buf - Verify chip data against buffer
360 * @mtd: MTD device structure
361 * @buf: buffer containing the data to compare
362 * @len: number of bytes to compare
363 */
364static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len)
365{
366 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
367 mtd);
368 u16 *p = (u16 *) buf;
369
370 len >>= 1;
371 while (len--) {
372 if (*p++ != cpu_to_le16(readw(info->nand.IO_ADDR_R)))
373 return -EFAULT;
374 }
375
376 return 0;
377}
378
379#ifdef CONFIG_MTD_NAND_OMAP_HWECC
380/**
381 * omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller
382 * @mtd: MTD device structure
383 */
384static void omap_hwecc_init(struct mtd_info *mtd)
385{
386 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
387 mtd);
388 struct nand_chip *chip = mtd->priv;
389 unsigned long val = 0x0;
390
391 /* Read from ECC Control Register */
392 val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL);
393 /* Clear all ECC | Enable Reg1 */
394 val = ((0x00000001<<8) | 0x00000001);
395 __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
396
397 /* Read from ECC Size Config Register */
398 val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
399 /* ECCSIZE1=512 | Select eccResultsize[0-3] */
400 val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F));
401 __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG);
402}
403
404/**
405 * gen_true_ecc - This function will generate true ECC value
406 * @ecc_buf: buffer to store ecc code
407 *
408 * This generated true ECC value can be used when correcting
409 * data read from NAND flash memory core
410 */
411static void gen_true_ecc(u8 *ecc_buf)
412{
413 u32 tmp = ecc_buf[0] | (ecc_buf[1] << 16) |
414 ((ecc_buf[2] & 0xF0) << 20) | ((ecc_buf[2] & 0x0F) << 8);
415
416 ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) |
417 P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
418 ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) |
419 P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
420 ecc_buf[2] = ~(P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) |
421 P1e(tmp) | P2048o(tmp) | P2048e(tmp));
422}
423
424/**
425 * omap_compare_ecc - Detect (2 bits) and correct (1 bit) error in data
426 * @ecc_data1: ecc code from nand spare area
427 * @ecc_data2: ecc code from hardware register obtained from hardware ecc
428 * @page_data: page data
429 *
430 * This function compares two ECC's and indicates if there is an error.
431 * If the error can be corrected it will be corrected to the buffer.
432 */
433static int omap_compare_ecc(u8 *ecc_data1, /* read from NAND memory */
434 u8 *ecc_data2, /* read from register */
435 u8 *page_data)
436{
437 uint i;
438 u8 tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
439 u8 comp0_bit[8], comp1_bit[8], comp2_bit[8];
440 u8 ecc_bit[24];
441 u8 ecc_sum = 0;
442 u8 find_bit = 0;
443 uint find_byte = 0;
444 int isEccFF;
445
446 isEccFF = ((*(u32 *)ecc_data1 & 0xFFFFFF) == 0xFFFFFF);
447
448 gen_true_ecc(ecc_data1);
449 gen_true_ecc(ecc_data2);
450
451 for (i = 0; i <= 2; i++) {
452 *(ecc_data1 + i) = ~(*(ecc_data1 + i));
453 *(ecc_data2 + i) = ~(*(ecc_data2 + i));
454 }
455
456 for (i = 0; i < 8; i++) {
457 tmp0_bit[i] = *ecc_data1 % 2;
458 *ecc_data1 = *ecc_data1 / 2;
459 }
460
461 for (i = 0; i < 8; i++) {
462 tmp1_bit[i] = *(ecc_data1 + 1) % 2;
463 *(ecc_data1 + 1) = *(ecc_data1 + 1) / 2;
464 }
465
466 for (i = 0; i < 8; i++) {
467 tmp2_bit[i] = *(ecc_data1 + 2) % 2;
468 *(ecc_data1 + 2) = *(ecc_data1 + 2) / 2;
469 }
470
471 for (i = 0; i < 8; i++) {
472 comp0_bit[i] = *ecc_data2 % 2;
473 *ecc_data2 = *ecc_data2 / 2;
474 }
475
476 for (i = 0; i < 8; i++) {
477 comp1_bit[i] = *(ecc_data2 + 1) % 2;
478 *(ecc_data2 + 1) = *(ecc_data2 + 1) / 2;
479 }
480
481 for (i = 0; i < 8; i++) {
482 comp2_bit[i] = *(ecc_data2 + 2) % 2;
483 *(ecc_data2 + 2) = *(ecc_data2 + 2) / 2;
484 }
485
486 for (i = 0; i < 6; i++)
487 ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
488
489 for (i = 0; i < 8; i++)
490 ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
491
492 for (i = 0; i < 8; i++)
493 ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
494
495 ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
496 ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
497
498 for (i = 0; i < 24; i++)
499 ecc_sum += ecc_bit[i];
500
501 switch (ecc_sum) {
502 case 0:
503 /* Not reached because this function is not called if
504 * ECC values are equal
505 */
506 return 0;
507
508 case 1:
509 /* Uncorrectable error */
510 DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR 1\n");
511 return -1;
512
513 case 11:
514 /* UN-Correctable error */
515 DEBUG(MTD_DEBUG_LEVEL0, "ECC UNCORRECTED_ERROR B\n");
516 return -1;
517
518 case 12:
519 /* Correctable error */
520 find_byte = (ecc_bit[23] << 8) +
521 (ecc_bit[21] << 7) +
522 (ecc_bit[19] << 6) +
523 (ecc_bit[17] << 5) +
524 (ecc_bit[15] << 4) +
525 (ecc_bit[13] << 3) +
526 (ecc_bit[11] << 2) +
527 (ecc_bit[9] << 1) +
528 ecc_bit[7];
529
530 find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
531
532 DEBUG(MTD_DEBUG_LEVEL0, "Correcting single bit ECC error at "
533 "offset: %d, bit: %d\n", find_byte, find_bit);
534
535 page_data[find_byte] ^= (1 << find_bit);
536
537 return 0;
538 default:
539 if (isEccFF) {
540 if (ecc_data2[0] == 0 &&
541 ecc_data2[1] == 0 &&
542 ecc_data2[2] == 0)
543 return 0;
544 }
545 DEBUG(MTD_DEBUG_LEVEL0, "UNCORRECTED_ERROR default\n");
546 return -1;
547 }
548}
549
550/**
551 * omap_correct_data - Compares the ECC read with HW generated ECC
552 * @mtd: MTD device structure
553 * @dat: page data
554 * @read_ecc: ecc read from nand flash
555 * @calc_ecc: ecc read from HW ECC registers
556 *
557 * Compares the ecc read from nand spare area with ECC registers values
558 * and if ECC's mismached, it will call 'omap_compare_ecc' for error detection
559 * and correction.
560 */
561static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
562 u_char *read_ecc, u_char *calc_ecc)
563{
564 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
565 mtd);
566 int blockCnt = 0, i = 0, ret = 0;
567
568 /* Ex NAND_ECC_HW12_2048 */
569 if ((info->nand.ecc.mode == NAND_ECC_HW) &&
570 (info->nand.ecc.size == 2048))
571 blockCnt = 4;
572 else
573 blockCnt = 1;
574
575 for (i = 0; i < blockCnt; i++) {
576 if (memcmp(read_ecc, calc_ecc, 3) != 0) {
577 ret = omap_compare_ecc(read_ecc, calc_ecc, dat);
578 if (ret < 0)
579 return ret;
580 }
581 read_ecc += 3;
582 calc_ecc += 3;
583 dat += 512;
584 }
585 return 0;
586}
587
588/**
589 * omap_calcuate_ecc - Generate non-inverted ECC bytes.
590 * @mtd: MTD device structure
591 * @dat: The pointer to data on which ecc is computed
592 * @ecc_code: The ecc_code buffer
593 *
594 * Using noninverted ECC can be considered ugly since writing a blank
595 * page ie. padding will clear the ECC bytes. This is no problem as long
596 * nobody is trying to write data on the seemingly unused page. Reading
597 * an erased page will produce an ECC mismatch between generated and read
598 * ECC bytes that has to be dealt with separately.
599 */
600static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
601 u_char *ecc_code)
602{
603 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
604 mtd);
605 unsigned long val = 0x0;
606 unsigned long reg;
607
608 /* Start Reading from HW ECC1_Result = 0x200 */
609 reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT);
610 val = __raw_readl(reg);
611 *ecc_code++ = val; /* P128e, ..., P1e */
612 *ecc_code++ = val >> 16; /* P128o, ..., P1o */
613 /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */
614 *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0);
615 reg += 4;
616
617 return 0;
618}
619
620/**
621 * omap_enable_hwecc - This function enables the hardware ecc functionality
622 * @mtd: MTD device structure
623 * @mode: Read/Write mode
624 */
625static void omap_enable_hwecc(struct mtd_info *mtd, int mode)
626{
627 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
628 mtd);
629 struct nand_chip *chip = mtd->priv;
630 unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
631 unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG);
632
633 switch (mode) {
634 case NAND_ECC_READ:
635 __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
636 /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
637 val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
638 break;
639 case NAND_ECC_READSYN:
640 __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
641 /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
642 val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
643 break;
644 case NAND_ECC_WRITE:
645 __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL);
646 /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */
647 val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1);
648 break;
649 default:
650 DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n",
651 mode);
652 break;
653 }
654
655 __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG);
656}
657#endif
658
659/**
660 * omap_wait - wait until the command is done
661 * @mtd: MTD device structure
662 * @chip: NAND Chip structure
663 *
664 * Wait function is called during Program and erase operations and
665 * the way it is called from MTD layer, we should wait till the NAND
666 * chip is ready after the programming/erase operation has completed.
667 *
668 * Erase can take up to 400ms and program up to 20ms according to
669 * general NAND and SmartMedia specs
670 */
671static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
672{
673 struct nand_chip *this = mtd->priv;
674 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
675 mtd);
676 unsigned long timeo = jiffies;
vimal singhc276aca2009-06-27 11:07:06 +0530677 int status = NAND_STATUS_FAIL, state = this->state;
Vimal Singh67ce04b2009-05-12 13:47:03 -0700678
679 if (state == FL_ERASING)
680 timeo += (HZ * 400) / 1000;
681 else
682 timeo += (HZ * 20) / 1000;
683
684 this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr +
685 GPMC_CS_NAND_COMMAND;
686 this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA;
687
688 __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W);
689
690 while (time_before(jiffies, timeo)) {
691 status = __raw_readb(this->IO_ADDR_R);
vimal singhc276aca2009-06-27 11:07:06 +0530692 if (status & NAND_STATUS_READY)
Vimal Singh67ce04b2009-05-12 13:47:03 -0700693 break;
vimal singhc276aca2009-06-27 11:07:06 +0530694 cond_resched();
Vimal Singh67ce04b2009-05-12 13:47:03 -0700695 }
696 return status;
697}
698
699/**
700 * omap_dev_ready - calls the platform specific dev_ready function
701 * @mtd: MTD device structure
702 */
703static int omap_dev_ready(struct mtd_info *mtd)
704{
705 struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
706 mtd);
707 unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS);
708
709 if ((val & 0x100) == 0x100) {
710 /* Clear IRQ Interrupt */
711 val |= 0x100;
712 val &= ~(0x0);
713 __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS);
714 } else {
715 unsigned int cnt = 0;
716 while (cnt++ < 0x1FF) {
717 if ((val & 0x100) == 0x100)
718 return 0;
719 val = __raw_readl(info->gpmc_baseaddr +
720 GPMC_IRQ_STATUS);
721 }
722 }
723
724 return 1;
725}
726
727static int __devinit omap_nand_probe(struct platform_device *pdev)
728{
729 struct omap_nand_info *info;
730 struct omap_nand_platform_data *pdata;
731 int err;
732 unsigned long val;
733
734
735 pdata = pdev->dev.platform_data;
736 if (pdata == NULL) {
737 dev_err(&pdev->dev, "platform data missing\n");
738 return -ENODEV;
739 }
740
741 info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL);
742 if (!info)
743 return -ENOMEM;
744
745 platform_set_drvdata(pdev, info);
746
747 spin_lock_init(&info->controller.lock);
748 init_waitqueue_head(&info->controller.wq);
749
750 info->pdev = pdev;
751
752 info->gpmc_cs = pdata->cs;
753 info->gpmc_baseaddr = pdata->gpmc_baseaddr;
754 info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr;
755
756 info->mtd.priv = &info->nand;
757 info->mtd.name = dev_name(&pdev->dev);
758 info->mtd.owner = THIS_MODULE;
759
760 err = gpmc_cs_request(info->gpmc_cs, NAND_IO_SIZE, &info->phys_base);
761 if (err < 0) {
762 dev_err(&pdev->dev, "Cannot request GPMC CS\n");
763 goto out_free_info;
764 }
765
766 /* Enable RD PIN Monitoring Reg */
767 if (pdata->dev_ready) {
768 val = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1);
769 val |= WR_RD_PIN_MONITORING;
770 gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG1, val);
771 }
772
773 val = gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG7);
774 val &= ~(0xf << 8);
775 val |= (0xc & 0xf) << 8;
776 gpmc_cs_write_reg(info->gpmc_cs, GPMC_CS_CONFIG7, val);
777
778 /* NAND write protect off */
779 omap_nand_wp(&info->mtd, NAND_WP_OFF);
780
781 if (!request_mem_region(info->phys_base, NAND_IO_SIZE,
782 pdev->dev.driver->name)) {
783 err = -EBUSY;
784 goto out_free_cs;
785 }
786
787 info->nand.IO_ADDR_R = ioremap(info->phys_base, NAND_IO_SIZE);
788 if (!info->nand.IO_ADDR_R) {
789 err = -ENOMEM;
790 goto out_release_mem_region;
791 }
vimal singh59e9c5a2009-07-13 16:26:24 +0530792
Vimal Singh67ce04b2009-05-12 13:47:03 -0700793 info->nand.controller = &info->controller;
794
795 info->nand.IO_ADDR_W = info->nand.IO_ADDR_R;
796 info->nand.cmd_ctrl = omap_hwcontrol;
797
Vimal Singh67ce04b2009-05-12 13:47:03 -0700798 /*
799 * If RDY/BSY line is connected to OMAP then use the omap ready
800 * funcrtion and the generic nand_wait function which reads the status
801 * register after monitoring the RDY/BSY line.Otherwise use a standard
802 * chip delay which is slightly more than tR (AC Timing) of the NAND
803 * device and read status register until you get a failure or success
804 */
805 if (pdata->dev_ready) {
806 info->nand.dev_ready = omap_dev_ready;
807 info->nand.chip_delay = 0;
808 } else {
809 info->nand.waitfunc = omap_wait;
810 info->nand.chip_delay = 50;
811 }
812
813 info->nand.options |= NAND_SKIP_BBTSCAN;
814 if ((gpmc_cs_read_reg(info->gpmc_cs, GPMC_CS_CONFIG1) & 0x3000)
815 == 0x1000)
816 info->nand.options |= NAND_BUSWIDTH_16;
817
vimal singh59e9c5a2009-07-13 16:26:24 +0530818 if (use_prefetch) {
819 /* copy the virtual address of nand base for fifo access */
820 info->nand_pref_fifo_add = info->nand.IO_ADDR_R;
821
822 info->nand.read_buf = omap_read_buf_pref;
823 info->nand.write_buf = omap_write_buf_pref;
824 } else {
825 if (info->nand.options & NAND_BUSWIDTH_16) {
826 info->nand.read_buf = omap_read_buf16;
827 info->nand.write_buf = omap_write_buf16;
828 } else {
829 info->nand.read_buf = omap_read_buf8;
830 info->nand.write_buf = omap_write_buf8;
831 }
832 }
833 info->nand.verify_buf = omap_verify_buf;
834
Vimal Singh67ce04b2009-05-12 13:47:03 -0700835#ifdef CONFIG_MTD_NAND_OMAP_HWECC
836 info->nand.ecc.bytes = 3;
837 info->nand.ecc.size = 512;
838 info->nand.ecc.calculate = omap_calculate_ecc;
839 info->nand.ecc.hwctl = omap_enable_hwecc;
840 info->nand.ecc.correct = omap_correct_data;
841 info->nand.ecc.mode = NAND_ECC_HW;
842
843 /* init HW ECC */
844 omap_hwecc_init(&info->mtd);
845#else
846 info->nand.ecc.mode = NAND_ECC_SOFT;
847#endif
848
849 /* DIP switches on some boards change between 8 and 16 bit
850 * bus widths for flash. Try the other width if the first try fails.
851 */
852 if (nand_scan(&info->mtd, 1)) {
853 info->nand.options ^= NAND_BUSWIDTH_16;
854 if (nand_scan(&info->mtd, 1)) {
855 err = -ENXIO;
856 goto out_release_mem_region;
857 }
858 }
859
860#ifdef CONFIG_MTD_PARTITIONS
861 err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
862 if (err > 0)
863 add_mtd_partitions(&info->mtd, info->parts, err);
864 else if (pdata->parts)
865 add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts);
866 else
867#endif
868 add_mtd_device(&info->mtd);
869
870 platform_set_drvdata(pdev, &info->mtd);
871
872 return 0;
873
874out_release_mem_region:
875 release_mem_region(info->phys_base, NAND_IO_SIZE);
876out_free_cs:
877 gpmc_cs_free(info->gpmc_cs);
878out_free_info:
879 kfree(info);
880
881 return err;
882}
883
884static int omap_nand_remove(struct platform_device *pdev)
885{
886 struct mtd_info *mtd = platform_get_drvdata(pdev);
887 struct omap_nand_info *info = mtd->priv;
888
889 platform_set_drvdata(pdev, NULL);
890 /* Release NAND device, its internal structures and partitions */
891 nand_release(&info->mtd);
vimal singh59e9c5a2009-07-13 16:26:24 +0530892 iounmap(info->nand_pref_fifo_add);
Vimal Singh67ce04b2009-05-12 13:47:03 -0700893 kfree(&info->mtd);
894 return 0;
895}
896
897static struct platform_driver omap_nand_driver = {
898 .probe = omap_nand_probe,
899 .remove = omap_nand_remove,
900 .driver = {
901 .name = DRIVER_NAME,
902 .owner = THIS_MODULE,
903 },
904};
905
906static int __init omap_nand_init(void)
907{
908 printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME);
909 return platform_driver_register(&omap_nand_driver);
910}
911
912static void __exit omap_nand_exit(void)
913{
914 platform_driver_unregister(&omap_nand_driver);
915}
916
917module_init(omap_nand_init);
918module_exit(omap_nand_exit);
919
920MODULE_ALIAS(DRIVER_NAME);
921MODULE_LICENSE("GPL");
922MODULE_DESCRIPTION("Glue layer for NAND flash on TI OMAP boards");