drivers/hwmon/w83791d.c: fix unused var warning
[linux-2.6] / drivers / mtd / nand / s3c2410.c
1 /* linux/drivers/mtd/nand/s3c2410.c
2  *
3  * Copyright © 2004-2008 Simtec Electronics
4  *      http://armlinux.simtec.co.uk/
5  *      Ben Dooks <ben@simtec.co.uk>
6  *
7  * Samsung S3C2410/S3C2440/S3C2412 NAND driver
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23
24 #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
25 #define DEBUG
26 #endif
27
28 #include <linux/module.h>
29 #include <linux/types.h>
30 #include <linux/init.h>
31 #include <linux/kernel.h>
32 #include <linux/string.h>
33 #include <linux/ioport.h>
34 #include <linux/platform_device.h>
35 #include <linux/delay.h>
36 #include <linux/err.h>
37 #include <linux/slab.h>
38 #include <linux/clk.h>
39 #include <linux/cpufreq.h>
40
41 #include <linux/mtd/mtd.h>
42 #include <linux/mtd/nand.h>
43 #include <linux/mtd/nand_ecc.h>
44 #include <linux/mtd/partitions.h>
45
46 #include <asm/io.h>
47
48 #include <asm/plat-s3c/regs-nand.h>
49 #include <asm/plat-s3c/nand.h>
50
51 #ifdef CONFIG_MTD_NAND_S3C2410_HWECC
52 static int hardware_ecc = 1;
53 #else
54 static int hardware_ecc = 0;
55 #endif
56
57 #ifdef CONFIG_MTD_NAND_S3C2410_CLKSTOP
58 static int clock_stop = 1;
59 #else
60 static const int clock_stop = 0;
61 #endif
62
63
64 /* new oob placement block for use with hardware ecc generation
65  */
66
67 static struct nand_ecclayout nand_hw_eccoob = {
68         .eccbytes = 3,
69         .eccpos = {0, 1, 2},
70         .oobfree = {{8, 8}}
71 };
72
73 /* controller and mtd information */
74
75 struct s3c2410_nand_info;
76
77 struct s3c2410_nand_mtd {
78         struct mtd_info                 mtd;
79         struct nand_chip                chip;
80         struct s3c2410_nand_set         *set;
81         struct s3c2410_nand_info        *info;
82         int                             scan_res;
83 };
84
85 enum s3c_cpu_type {
86         TYPE_S3C2410,
87         TYPE_S3C2412,
88         TYPE_S3C2440,
89 };
90
91 /* overview of the s3c2410 nand state */
92
93 struct s3c2410_nand_info {
94         /* mtd info */
95         struct nand_hw_control          controller;
96         struct s3c2410_nand_mtd         *mtds;
97         struct s3c2410_platform_nand    *platform;
98
99         /* device info */
100         struct device                   *device;
101         struct resource                 *area;
102         struct clk                      *clk;
103         void __iomem                    *regs;
104         void __iomem                    *sel_reg;
105         int                             sel_bit;
106         int                             mtd_count;
107         unsigned long                   save_sel;
108         unsigned long                   clk_rate;
109
110         enum s3c_cpu_type               cpu_type;
111
112 #ifdef CONFIG_CPU_FREQ
113         struct notifier_block   freq_transition;
114 #endif
115 };
116
117 /* conversion functions */
118
119 static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
120 {
121         return container_of(mtd, struct s3c2410_nand_mtd, mtd);
122 }
123
124 static struct s3c2410_nand_info *s3c2410_nand_mtd_toinfo(struct mtd_info *mtd)
125 {
126         return s3c2410_nand_mtd_toours(mtd)->info;
127 }
128
129 static struct s3c2410_nand_info *to_nand_info(struct platform_device *dev)
130 {
131         return platform_get_drvdata(dev);
132 }
133
134 static struct s3c2410_platform_nand *to_nand_plat(struct platform_device *dev)
135 {
136         return dev->dev.platform_data;
137 }
138
139 static inline int allow_clk_stop(struct s3c2410_nand_info *info)
140 {
141         return clock_stop;
142 }
143
144 /* timing calculations */
145
146 #define NS_IN_KHZ 1000000
147
148 static int s3c_nand_calc_rate(int wanted, unsigned long clk, int max)
149 {
150         int result;
151
152         result = (wanted * clk) / NS_IN_KHZ;
153         result++;
154
155         pr_debug("result %d from %ld, %d\n", result, clk, wanted);
156
157         if (result > max) {
158                 printk("%d ns is too big for current clock rate %ld\n", wanted, clk);
159                 return -1;
160         }
161
162         if (result < 1)
163                 result = 1;
164
165         return result;
166 }
167
168 #define to_ns(ticks,clk) (((ticks) * NS_IN_KHZ) / (unsigned int)(clk))
169
170 /* controller setup */
171
172 static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)
173 {
174         struct s3c2410_platform_nand *plat = info->platform;
175         int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4;
176         int tacls, twrph0, twrph1;
177         unsigned long clkrate = clk_get_rate(info->clk);
178         unsigned long set, cfg, mask;
179         unsigned long flags;
180
181         /* calculate the timing information for the controller */
182
183         info->clk_rate = clkrate;
184         clkrate /= 1000;        /* turn clock into kHz for ease of use */
185
186         if (plat != NULL) {
187                 tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
188                 twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
189                 twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
190         } else {
191                 /* default timings */
192                 tacls = tacls_max;
193                 twrph0 = 8;
194                 twrph1 = 8;
195         }
196
197         if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
198                 dev_err(info->device, "cannot get suitable timings\n");
199                 return -EINVAL;
200         }
201
202         dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
203                tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));
204
205         switch (info->cpu_type) {
206         case TYPE_S3C2410:
207                 mask = (S3C2410_NFCONF_TACLS(3) |
208                         S3C2410_NFCONF_TWRPH0(7) |
209                         S3C2410_NFCONF_TWRPH1(7));
210                 set = S3C2410_NFCONF_EN;
211                 set |= S3C2410_NFCONF_TACLS(tacls - 1);
212                 set |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
213                 set |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
214                 break;
215
216         case TYPE_S3C2440:
217         case TYPE_S3C2412:
218                 mask = (S3C2410_NFCONF_TACLS(tacls_max - 1) |
219                         S3C2410_NFCONF_TWRPH0(7) |
220                         S3C2410_NFCONF_TWRPH1(7));
221
222                 set = S3C2440_NFCONF_TACLS(tacls - 1);
223                 set |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
224                 set |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
225                 break;
226
227         default:
228                 /* keep compiler happy */
229                 mask = 0;
230                 set = 0;
231                 BUG();
232         }
233
234         dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
235
236         local_irq_save(flags);
237
238         cfg = readl(info->regs + S3C2410_NFCONF);
239         cfg &= ~mask;
240         cfg |= set;
241         writel(cfg, info->regs + S3C2410_NFCONF);
242
243         local_irq_restore(flags);
244
245         return 0;
246 }
247
248 static int s3c2410_nand_inithw(struct s3c2410_nand_info *info)
249 {
250         int ret;
251
252         ret = s3c2410_nand_setrate(info);
253         if (ret < 0)
254                 return ret;
255
256         switch (info->cpu_type) {
257         case TYPE_S3C2410:
258         default:
259                 break;
260
261         case TYPE_S3C2440:
262         case TYPE_S3C2412:
263                 /* enable the controller and de-assert nFCE */
264
265                 writel(S3C2440_NFCONT_ENABLE, info->regs + S3C2440_NFCONT);
266         }
267
268         return 0;
269 }
270
271 /* select chip */
272
273 static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
274 {
275         struct s3c2410_nand_info *info;
276         struct s3c2410_nand_mtd *nmtd;
277         struct nand_chip *this = mtd->priv;
278         unsigned long cur;
279
280         nmtd = this->priv;
281         info = nmtd->info;
282
283         if (chip != -1 && allow_clk_stop(info))
284                 clk_enable(info->clk);
285
286         cur = readl(info->sel_reg);
287
288         if (chip == -1) {
289                 cur |= info->sel_bit;
290         } else {
291                 if (nmtd->set != NULL && chip > nmtd->set->nr_chips) {
292                         dev_err(info->device, "invalid chip %d\n", chip);
293                         return;
294                 }
295
296                 if (info->platform != NULL) {
297                         if (info->platform->select_chip != NULL)
298                                 (info->platform->select_chip) (nmtd->set, chip);
299                 }
300
301                 cur &= ~info->sel_bit;
302         }
303
304         writel(cur, info->sel_reg);
305
306         if (chip == -1 && allow_clk_stop(info))
307                 clk_disable(info->clk);
308 }
309
310 /* s3c2410_nand_hwcontrol
311  *
312  * Issue command and address cycles to the chip
313 */
314
315 static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd,
316                                    unsigned int ctrl)
317 {
318         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
319
320         if (cmd == NAND_CMD_NONE)
321                 return;
322
323         if (ctrl & NAND_CLE)
324                 writeb(cmd, info->regs + S3C2410_NFCMD);
325         else
326                 writeb(cmd, info->regs + S3C2410_NFADDR);
327 }
328
329 /* command and control functions */
330
331 static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd,
332                                    unsigned int ctrl)
333 {
334         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
335
336         if (cmd == NAND_CMD_NONE)
337                 return;
338
339         if (ctrl & NAND_CLE)
340                 writeb(cmd, info->regs + S3C2440_NFCMD);
341         else
342                 writeb(cmd, info->regs + S3C2440_NFADDR);
343 }
344
345 /* s3c2410_nand_devready()
346  *
347  * returns 0 if the nand is busy, 1 if it is ready
348 */
349
350 static int s3c2410_nand_devready(struct mtd_info *mtd)
351 {
352         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
353         return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
354 }
355
356 static int s3c2440_nand_devready(struct mtd_info *mtd)
357 {
358         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
359         return readb(info->regs + S3C2440_NFSTAT) & S3C2440_NFSTAT_READY;
360 }
361
362 static int s3c2412_nand_devready(struct mtd_info *mtd)
363 {
364         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
365         return readb(info->regs + S3C2412_NFSTAT) & S3C2412_NFSTAT_READY;
366 }
367
368 /* ECC handling functions */
369
370 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
371                                      u_char *read_ecc, u_char *calc_ecc)
372 {
373         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
374         unsigned int diff0, diff1, diff2;
375         unsigned int bit, byte;
376
377         pr_debug("%s(%p,%p,%p,%p)\n", __func__, mtd, dat, read_ecc, calc_ecc);
378
379         diff0 = read_ecc[0] ^ calc_ecc[0];
380         diff1 = read_ecc[1] ^ calc_ecc[1];
381         diff2 = read_ecc[2] ^ calc_ecc[2];
382
383         pr_debug("%s: rd %02x%02x%02x calc %02x%02x%02x diff %02x%02x%02x\n",
384                  __func__,
385                  read_ecc[0], read_ecc[1], read_ecc[2],
386                  calc_ecc[0], calc_ecc[1], calc_ecc[2],
387                  diff0, diff1, diff2);
388
389         if (diff0 == 0 && diff1 == 0 && diff2 == 0)
390                 return 0;               /* ECC is ok */
391
392         /* sometimes people do not think about using the ECC, so check
393          * to see if we have an 0xff,0xff,0xff read ECC and then ignore
394          * the error, on the assumption that this is an un-eccd page.
395          */
396         if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff
397             && info->platform->ignore_unset_ecc)
398                 return 0;
399
400         /* Can we correct this ECC (ie, one row and column change).
401          * Note, this is similar to the 256 error code on smartmedia */
402
403         if (((diff0 ^ (diff0 >> 1)) & 0x55) == 0x55 &&
404             ((diff1 ^ (diff1 >> 1)) & 0x55) == 0x55 &&
405             ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) {
406                 /* calculate the bit position of the error */
407
408                 bit  = ((diff2 >> 3) & 1) |
409                        ((diff2 >> 4) & 2) |
410                        ((diff2 >> 5) & 4);
411
412                 /* calculate the byte position of the error */
413
414                 byte = ((diff2 << 7) & 0x100) |
415                        ((diff1 << 0) & 0x80)  |
416                        ((diff1 << 1) & 0x40)  |
417                        ((diff1 << 2) & 0x20)  |
418                        ((diff1 << 3) & 0x10)  |
419                        ((diff0 >> 4) & 0x08)  |
420                        ((diff0 >> 3) & 0x04)  |
421                        ((diff0 >> 2) & 0x02)  |
422                        ((diff0 >> 1) & 0x01);
423
424                 dev_dbg(info->device, "correcting error bit %d, byte %d\n",
425                         bit, byte);
426
427                 dat[byte] ^= (1 << bit);
428                 return 1;
429         }
430
431         /* if there is only one bit difference in the ECC, then
432          * one of only a row or column parity has changed, which
433          * means the error is most probably in the ECC itself */
434
435         diff0 |= (diff1 << 8);
436         diff0 |= (diff2 << 16);
437
438         if ((diff0 & ~(1<<fls(diff0))) == 0)
439                 return 1;
440
441         return -1;
442 }
443
444 /* ECC functions
445  *
446  * These allow the s3c2410 and s3c2440 to use the controller's ECC
447  * generator block to ECC the data as it passes through]
448 */
449
450 static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
451 {
452         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
453         unsigned long ctrl;
454
455         ctrl = readl(info->regs + S3C2410_NFCONF);
456         ctrl |= S3C2410_NFCONF_INITECC;
457         writel(ctrl, info->regs + S3C2410_NFCONF);
458 }
459
460 static void s3c2412_nand_enable_hwecc(struct mtd_info *mtd, int mode)
461 {
462         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
463         unsigned long ctrl;
464
465         ctrl = readl(info->regs + S3C2440_NFCONT);
466         writel(ctrl | S3C2412_NFCONT_INIT_MAIN_ECC, info->regs + S3C2440_NFCONT);
467 }
468
469 static void s3c2440_nand_enable_hwecc(struct mtd_info *mtd, int mode)
470 {
471         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
472         unsigned long ctrl;
473
474         ctrl = readl(info->regs + S3C2440_NFCONT);
475         writel(ctrl | S3C2440_NFCONT_INITECC, info->regs + S3C2440_NFCONT);
476 }
477
478 static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
479 {
480         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
481
482         ecc_code[0] = readb(info->regs + S3C2410_NFECC + 0);
483         ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
484         ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
485
486         pr_debug("%s: returning ecc %02x%02x%02x\n", __func__,
487                  ecc_code[0], ecc_code[1], ecc_code[2]);
488
489         return 0;
490 }
491
492 static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
493 {
494         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
495         unsigned long ecc = readl(info->regs + S3C2412_NFMECC0);
496
497         ecc_code[0] = ecc;
498         ecc_code[1] = ecc >> 8;
499         ecc_code[2] = ecc >> 16;
500
501         pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
502
503         return 0;
504 }
505
506 static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
507 {
508         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
509         unsigned long ecc = readl(info->regs + S3C2440_NFMECC0);
510
511         ecc_code[0] = ecc;
512         ecc_code[1] = ecc >> 8;
513         ecc_code[2] = ecc >> 16;
514
515         pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff);
516
517         return 0;
518 }
519
520 /* over-ride the standard functions for a little more speed. We can
521  * use read/write block to move the data buffers to/from the controller
522 */
523
524 static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
525 {
526         struct nand_chip *this = mtd->priv;
527         readsb(this->IO_ADDR_R, buf, len);
528 }
529
530 static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
531 {
532         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
533         readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
534 }
535
536 static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
537 {
538         struct nand_chip *this = mtd->priv;
539         writesb(this->IO_ADDR_W, buf, len);
540 }
541
542 static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
543 {
544         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
545         writesl(info->regs + S3C2440_NFDATA, buf, len / 4);
546 }
547
548 /* cpufreq driver support */
549
550 #ifdef CONFIG_CPU_FREQ
551
552 static int s3c2410_nand_cpufreq_transition(struct notifier_block *nb,
553                                           unsigned long val, void *data)
554 {
555         struct s3c2410_nand_info *info;
556         unsigned long newclk;
557
558         info = container_of(nb, struct s3c2410_nand_info, freq_transition);
559         newclk = clk_get_rate(info->clk);
560
561         if ((val == CPUFREQ_POSTCHANGE && newclk < info->clk_rate) ||
562             (val == CPUFREQ_PRECHANGE && newclk > info->clk_rate)) {
563                 s3c2410_nand_setrate(info);
564         }
565
566         return 0;
567 }
568
569 static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
570 {
571         info->freq_transition.notifier_call = s3c2410_nand_cpufreq_transition;
572
573         return cpufreq_register_notifier(&info->freq_transition,
574                                          CPUFREQ_TRANSITION_NOTIFIER);
575 }
576
577 static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
578 {
579         cpufreq_unregister_notifier(&info->freq_transition,
580                                     CPUFREQ_TRANSITION_NOTIFIER);
581 }
582
583 #else
584 static inline int s3c2410_nand_cpufreq_register(struct s3c2410_nand_info *info)
585 {
586         return 0;
587 }
588
589 static inline void s3c2410_nand_cpufreq_deregister(struct s3c2410_nand_info *info)
590 {
591 }
592 #endif
593
594 /* device management functions */
595
596 static int s3c2410_nand_remove(struct platform_device *pdev)
597 {
598         struct s3c2410_nand_info *info = to_nand_info(pdev);
599
600         platform_set_drvdata(pdev, NULL);
601
602         if (info == NULL)
603                 return 0;
604
605         s3c2410_nand_cpufreq_deregister(info);
606
607         /* Release all our mtds  and their partitions, then go through
608          * freeing the resources used
609          */
610
611         if (info->mtds != NULL) {
612                 struct s3c2410_nand_mtd *ptr = info->mtds;
613                 int mtdno;
614
615                 for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) {
616                         pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
617                         nand_release(&ptr->mtd);
618                 }
619
620                 kfree(info->mtds);
621         }
622
623         /* free the common resources */
624
625         if (info->clk != NULL && !IS_ERR(info->clk)) {
626                 if (!allow_clk_stop(info))
627                         clk_disable(info->clk);
628                 clk_put(info->clk);
629         }
630
631         if (info->regs != NULL) {
632                 iounmap(info->regs);
633                 info->regs = NULL;
634         }
635
636         if (info->area != NULL) {
637                 release_resource(info->area);
638                 kfree(info->area);
639                 info->area = NULL;
640         }
641
642         kfree(info);
643
644         return 0;
645 }
646
647 #ifdef CONFIG_MTD_PARTITIONS
648 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
649                                       struct s3c2410_nand_mtd *mtd,
650                                       struct s3c2410_nand_set *set)
651 {
652         if (set == NULL)
653                 return add_mtd_device(&mtd->mtd);
654
655         if (set->nr_partitions > 0 && set->partitions != NULL) {
656                 return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
657         }
658
659         return add_mtd_device(&mtd->mtd);
660 }
661 #else
662 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
663                                       struct s3c2410_nand_mtd *mtd,
664                                       struct s3c2410_nand_set *set)
665 {
666         return add_mtd_device(&mtd->mtd);
667 }
668 #endif
669
670 /* s3c2410_nand_init_chip
671  *
672  * init a single instance of an chip
673 */
674
675 static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
676                                    struct s3c2410_nand_mtd *nmtd,
677                                    struct s3c2410_nand_set *set)
678 {
679         struct nand_chip *chip = &nmtd->chip;
680         void __iomem *regs = info->regs;
681
682         chip->write_buf    = s3c2410_nand_write_buf;
683         chip->read_buf     = s3c2410_nand_read_buf;
684         chip->select_chip  = s3c2410_nand_select_chip;
685         chip->chip_delay   = 50;
686         chip->priv         = nmtd;
687         chip->options      = 0;
688         chip->controller   = &info->controller;
689
690         switch (info->cpu_type) {
691         case TYPE_S3C2410:
692                 chip->IO_ADDR_W = regs + S3C2410_NFDATA;
693                 info->sel_reg   = regs + S3C2410_NFCONF;
694                 info->sel_bit   = S3C2410_NFCONF_nFCE;
695                 chip->cmd_ctrl  = s3c2410_nand_hwcontrol;
696                 chip->dev_ready = s3c2410_nand_devready;
697                 break;
698
699         case TYPE_S3C2440:
700                 chip->IO_ADDR_W = regs + S3C2440_NFDATA;
701                 info->sel_reg   = regs + S3C2440_NFCONT;
702                 info->sel_bit   = S3C2440_NFCONT_nFCE;
703                 chip->cmd_ctrl  = s3c2440_nand_hwcontrol;
704                 chip->dev_ready = s3c2440_nand_devready;
705                 chip->read_buf  = s3c2440_nand_read_buf;
706                 chip->write_buf = s3c2440_nand_write_buf;
707                 break;
708
709         case TYPE_S3C2412:
710                 chip->IO_ADDR_W = regs + S3C2440_NFDATA;
711                 info->sel_reg   = regs + S3C2440_NFCONT;
712                 info->sel_bit   = S3C2412_NFCONT_nFCE0;
713                 chip->cmd_ctrl  = s3c2440_nand_hwcontrol;
714                 chip->dev_ready = s3c2412_nand_devready;
715
716                 if (readl(regs + S3C2410_NFCONF) & S3C2412_NFCONF_NANDBOOT)
717                         dev_info(info->device, "System booted from NAND\n");
718
719                 break;
720         }
721
722         chip->IO_ADDR_R = chip->IO_ADDR_W;
723
724         nmtd->info         = info;
725         nmtd->mtd.priv     = chip;
726         nmtd->mtd.owner    = THIS_MODULE;
727         nmtd->set          = set;
728
729         if (hardware_ecc) {
730                 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
731                 chip->ecc.correct   = s3c2410_nand_correct_data;
732                 chip->ecc.mode      = NAND_ECC_HW;
733
734                 switch (info->cpu_type) {
735                 case TYPE_S3C2410:
736                         chip->ecc.hwctl     = s3c2410_nand_enable_hwecc;
737                         chip->ecc.calculate = s3c2410_nand_calculate_ecc;
738                         break;
739
740                 case TYPE_S3C2412:
741                         chip->ecc.hwctl     = s3c2412_nand_enable_hwecc;
742                         chip->ecc.calculate = s3c2412_nand_calculate_ecc;
743                         break;
744
745                 case TYPE_S3C2440:
746                         chip->ecc.hwctl     = s3c2440_nand_enable_hwecc;
747                         chip->ecc.calculate = s3c2440_nand_calculate_ecc;
748                         break;
749
750                 }
751         } else {
752                 chip->ecc.mode      = NAND_ECC_SOFT;
753         }
754
755         if (set->ecc_layout != NULL)
756                 chip->ecc.layout = set->ecc_layout;
757
758         if (set->disable_ecc)
759                 chip->ecc.mode  = NAND_ECC_NONE;
760 }
761
762 /* s3c2410_nand_update_chip
763  *
764  * post-probe chip update, to change any items, such as the
765  * layout for large page nand
766  */
767
768 static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
769                                      struct s3c2410_nand_mtd *nmtd)
770 {
771         struct nand_chip *chip = &nmtd->chip;
772
773         dev_dbg(info->device, "chip %p => page shift %d\n",
774                 chip, chip->page_shift);
775
776         if (hardware_ecc) {
777                 /* change the behaviour depending on wether we are using
778                  * the large or small page nand device */
779
780                 if (chip->page_shift > 10) {
781                         chip->ecc.size      = 256;
782                         chip->ecc.bytes     = 3;
783                 } else {
784                         chip->ecc.size      = 512;
785                         chip->ecc.bytes     = 3;
786                         chip->ecc.layout    = &nand_hw_eccoob;
787                 }
788         }
789 }
790
791 /* s3c2410_nand_probe
792  *
793  * called by device layer when it finds a device matching
794  * one our driver can handled. This code checks to see if
795  * it can allocate all necessary resources then calls the
796  * nand layer to look for devices
797 */
798
799 static int s3c24xx_nand_probe(struct platform_device *pdev,
800                               enum s3c_cpu_type cpu_type)
801 {
802         struct s3c2410_platform_nand *plat = to_nand_plat(pdev);
803         struct s3c2410_nand_info *info;
804         struct s3c2410_nand_mtd *nmtd;
805         struct s3c2410_nand_set *sets;
806         struct resource *res;
807         int err = 0;
808         int size;
809         int nr_sets;
810         int setno;
811
812         pr_debug("s3c2410_nand_probe(%p)\n", pdev);
813
814         info = kmalloc(sizeof(*info), GFP_KERNEL);
815         if (info == NULL) {
816                 dev_err(&pdev->dev, "no memory for flash info\n");
817                 err = -ENOMEM;
818                 goto exit_error;
819         }
820
821         memzero(info, sizeof(*info));
822         platform_set_drvdata(pdev, info);
823
824         spin_lock_init(&info->controller.lock);
825         init_waitqueue_head(&info->controller.wq);
826
827         /* get the clock source and enable it */
828
829         info->clk = clk_get(&pdev->dev, "nand");
830         if (IS_ERR(info->clk)) {
831                 dev_err(&pdev->dev, "failed to get clock\n");
832                 err = -ENOENT;
833                 goto exit_error;
834         }
835
836         clk_enable(info->clk);
837
838         /* allocate and map the resource */
839
840         /* currently we assume we have the one resource */
841         res  = pdev->resource;
842         size = res->end - res->start + 1;
843
844         info->area = request_mem_region(res->start, size, pdev->name);
845
846         if (info->area == NULL) {
847                 dev_err(&pdev->dev, "cannot reserve register region\n");
848                 err = -ENOENT;
849                 goto exit_error;
850         }
851
852         info->device     = &pdev->dev;
853         info->platform   = plat;
854         info->regs       = ioremap(res->start, size);
855         info->cpu_type   = cpu_type;
856
857         if (info->regs == NULL) {
858                 dev_err(&pdev->dev, "cannot reserve register region\n");
859                 err = -EIO;
860                 goto exit_error;
861         }
862
863         dev_dbg(&pdev->dev, "mapped registers at %p\n", info->regs);
864
865         /* initialise the hardware */
866
867         err = s3c2410_nand_inithw(info);
868         if (err != 0)
869                 goto exit_error;
870
871         sets = (plat != NULL) ? plat->sets : NULL;
872         nr_sets = (plat != NULL) ? plat->nr_sets : 1;
873
874         info->mtd_count = nr_sets;
875
876         /* allocate our information */
877
878         size = nr_sets * sizeof(*info->mtds);
879         info->mtds = kmalloc(size, GFP_KERNEL);
880         if (info->mtds == NULL) {
881                 dev_err(&pdev->dev, "failed to allocate mtd storage\n");
882                 err = -ENOMEM;
883                 goto exit_error;
884         }
885
886         memzero(info->mtds, size);
887
888         /* initialise all possible chips */
889
890         nmtd = info->mtds;
891
892         for (setno = 0; setno < nr_sets; setno++, nmtd++) {
893                 pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);
894
895                 s3c2410_nand_init_chip(info, nmtd, sets);
896
897                 nmtd->scan_res = nand_scan_ident(&nmtd->mtd,
898                                                  (sets) ? sets->nr_chips : 1);
899
900                 if (nmtd->scan_res == 0) {
901                         s3c2410_nand_update_chip(info, nmtd);
902                         nand_scan_tail(&nmtd->mtd);
903                         s3c2410_nand_add_partition(info, nmtd, sets);
904                 }
905
906                 if (sets != NULL)
907                         sets++;
908         }
909
910         err = s3c2410_nand_cpufreq_register(info);
911         if (err < 0) {
912                 dev_err(&pdev->dev, "failed to init cpufreq support\n");
913                 goto exit_error;
914         }
915
916         if (allow_clk_stop(info)) {
917                 dev_info(&pdev->dev, "clock idle support enabled\n");
918                 clk_disable(info->clk);
919         }
920
921         pr_debug("initialised ok\n");
922         return 0;
923
924  exit_error:
925         s3c2410_nand_remove(pdev);
926
927         if (err == 0)
928                 err = -EINVAL;
929         return err;
930 }
931
932 /* PM Support */
933 #ifdef CONFIG_PM
934
935 static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm)
936 {
937         struct s3c2410_nand_info *info = platform_get_drvdata(dev);
938
939         if (info) {
940                 info->save_sel = readl(info->sel_reg);
941
942                 /* For the moment, we must ensure nFCE is high during
943                  * the time we are suspended. This really should be
944                  * handled by suspending the MTDs we are using, but
945                  * that is currently not the case. */
946
947                 writel(info->save_sel | info->sel_bit, info->sel_reg);
948
949                 if (!allow_clk_stop(info))
950                         clk_disable(info->clk);
951         }
952
953         return 0;
954 }
955
956 static int s3c24xx_nand_resume(struct platform_device *dev)
957 {
958         struct s3c2410_nand_info *info = platform_get_drvdata(dev);
959         unsigned long sel;
960
961         if (info) {
962                 clk_enable(info->clk);
963                 s3c2410_nand_inithw(info);
964
965                 /* Restore the state of the nFCE line. */
966
967                 sel = readl(info->sel_reg);
968                 sel &= ~info->sel_bit;
969                 sel |= info->save_sel & info->sel_bit;
970                 writel(sel, info->sel_reg);
971
972                 if (allow_clk_stop(info))
973                         clk_disable(info->clk);
974         }
975
976         return 0;
977 }
978
979 #else
980 #define s3c24xx_nand_suspend NULL
981 #define s3c24xx_nand_resume NULL
982 #endif
983
984 /* driver device registration */
985
986 static int s3c2410_nand_probe(struct platform_device *dev)
987 {
988         return s3c24xx_nand_probe(dev, TYPE_S3C2410);
989 }
990
991 static int s3c2440_nand_probe(struct platform_device *dev)
992 {
993         return s3c24xx_nand_probe(dev, TYPE_S3C2440);
994 }
995
996 static int s3c2412_nand_probe(struct platform_device *dev)
997 {
998         return s3c24xx_nand_probe(dev, TYPE_S3C2412);
999 }
1000
1001 static struct platform_driver s3c2410_nand_driver = {
1002         .probe          = s3c2410_nand_probe,
1003         .remove         = s3c2410_nand_remove,
1004         .suspend        = s3c24xx_nand_suspend,
1005         .resume         = s3c24xx_nand_resume,
1006         .driver         = {
1007                 .name   = "s3c2410-nand",
1008                 .owner  = THIS_MODULE,
1009         },
1010 };
1011
1012 static struct platform_driver s3c2440_nand_driver = {
1013         .probe          = s3c2440_nand_probe,
1014         .remove         = s3c2410_nand_remove,
1015         .suspend        = s3c24xx_nand_suspend,
1016         .resume         = s3c24xx_nand_resume,
1017         .driver         = {
1018                 .name   = "s3c2440-nand",
1019                 .owner  = THIS_MODULE,
1020         },
1021 };
1022
1023 static struct platform_driver s3c2412_nand_driver = {
1024         .probe          = s3c2412_nand_probe,
1025         .remove         = s3c2410_nand_remove,
1026         .suspend        = s3c24xx_nand_suspend,
1027         .resume         = s3c24xx_nand_resume,
1028         .driver         = {
1029                 .name   = "s3c2412-nand",
1030                 .owner  = THIS_MODULE,
1031         },
1032 };
1033
1034 static int __init s3c2410_nand_init(void)
1035 {
1036         printk("S3C24XX NAND Driver, (c) 2004 Simtec Electronics\n");
1037
1038         platform_driver_register(&s3c2412_nand_driver);
1039         platform_driver_register(&s3c2440_nand_driver);
1040         return platform_driver_register(&s3c2410_nand_driver);
1041 }
1042
1043 static void __exit s3c2410_nand_exit(void)
1044 {
1045         platform_driver_unregister(&s3c2412_nand_driver);
1046         platform_driver_unregister(&s3c2440_nand_driver);
1047         platform_driver_unregister(&s3c2410_nand_driver);
1048 }
1049
1050 module_init(s3c2410_nand_init);
1051 module_exit(s3c2410_nand_exit);
1052
1053 MODULE_LICENSE("GPL");
1054 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
1055 MODULE_DESCRIPTION("S3C24XX MTD NAND driver");
1056 MODULE_ALIAS("platform:s3c2410-nand");
1057 MODULE_ALIAS("platform:s3c2412-nand");
1058 MODULE_ALIAS("platform:s3c2440-nand");