cb04b3c771e491cf559d0a1daaebae2a8636310f
[linux-block.git] / drivers / mtd / nand / s3c2410.c
1 /* linux/drivers/mtd/nand/s3c2410.c
2  *
3  * Copyright (c) 2004 Simtec Electronics
4  *      http://www.simtec.co.uk/products/SWLINUX/
5  *      Ben Dooks <ben@simtec.co.uk>
6  *
7  * Samsung S3C2410 NAND driver
8  *
9  * Changelog:
10  *      21-Sep-2004  BJD  Initial version
11  *      23-Sep-2004  BJD  Mulitple device support
12  *      28-Sep-2004  BJD  Fixed ECC placement for Hardware mode
13  *      12-Oct-2004  BJD  Fixed errors in use of platform data
14  *      18-Feb-2004  BJD  Fix sparse errors
15  *
16  * $Id: s3c2410.c,v 1.8 2005/02/18 14:46:12 bjd Exp $
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31 */
32
33 #include <config/mtd/nand/s3c2410/hwecc.h>
34 #include <config/mtd/nand/s3c2410/debug.h>
35
36 #ifdef CONFIG_MTD_NAND_S3C2410_DEBUG
37 #define DEBUG
38 #endif
39
40 #include <linux/module.h>
41 #include <linux/types.h>
42 #include <linux/init.h>
43 #include <linux/kernel.h>
44 #include <linux/string.h>
45 #include <linux/ioport.h>
46 #include <linux/device.h>
47 #include <linux/delay.h>
48 #include <linux/err.h>
49
50 #include <linux/mtd/mtd.h>
51 #include <linux/mtd/nand.h>
52 #include <linux/mtd/nand_ecc.h>
53 #include <linux/mtd/partitions.h>
54
55 #include <asm/io.h>
56 #include <asm/mach-types.h>
57 #include <asm/hardware/clock.h>
58
59 #include <asm/arch/regs-nand.h>
60 #include <asm/arch/nand.h>
61
62 #define PFX "s3c2410-nand: "
63
64 #ifdef CONFIG_MTD_NAND_S3C2410_HWECC
65 static int hardware_ecc = 1;
66 #else
67 static int hardware_ecc = 0;
68 #endif
69
70 /* new oob placement block for use with hardware ecc generation
71  */
72
73 static struct nand_oobinfo nand_hw_eccoob = {
74         .useecc         = MTD_NANDECC_AUTOPLACE,
75         .eccbytes       = 3,
76         .eccpos         = {0, 1, 2 },
77         .oobfree        = { {8, 8} }
78 };
79
80 /* controller and mtd information */
81
82 struct s3c2410_nand_info;
83
84 struct s3c2410_nand_mtd {
85         struct mtd_info                 mtd;
86         struct nand_chip                chip;
87         struct s3c2410_nand_set         *set;
88         struct s3c2410_nand_info        *info;
89         int                             scan_res;
90 };
91
92 /* overview of the s3c2410 nand state */
93
94 struct s3c2410_nand_info {
95         /* mtd info */
96         struct nand_hw_control          controller;
97         struct s3c2410_nand_mtd         *mtds;
98         struct s3c2410_platform_nand    *platform;
99
100         /* device info */
101         struct device                   *device;
102         struct resource                 *area;
103         struct clk                      *clk;
104         void __iomem                    *regs;
105         int                             mtd_count;
106 };
107
108 /* conversion functions */
109
110 static struct s3c2410_nand_mtd *s3c2410_nand_mtd_toours(struct mtd_info *mtd)
111 {
112         return container_of(mtd, struct s3c2410_nand_mtd, mtd);
113 }
114
115 static struct s3c2410_nand_info *s3c2410_nand_mtd_toinfo(struct mtd_info *mtd)
116 {
117         return s3c2410_nand_mtd_toours(mtd)->info;
118 }
119
120 static struct s3c2410_nand_info *to_nand_info(struct device *dev)
121 {
122         return dev_get_drvdata(dev);
123 }
124
125 static struct s3c2410_platform_nand *to_nand_plat(struct device *dev)
126 {
127         return dev->platform_data;
128 }
129
130 /* timing calculations */
131
132 #define NS_IN_KHZ 10000000
133
134 static int s3c2410_nand_calc_rate(int wanted, unsigned long clk, int max)
135 {
136         int result;
137
138         result = (wanted * NS_IN_KHZ) / clk;
139         result++;
140
141         pr_debug("result %d from %ld, %d\n", result, clk, wanted);
142
143         if (result > max) {
144                 printk("%d ns is too big for current clock rate %ld\n",
145                        wanted, clk);
146                 return -1;
147         }
148
149         if (result < 1)
150                 result = 1;
151
152         return result;
153 }
154
155 #define to_ns(ticks,clk) (((clk) * (ticks)) / NS_IN_KHZ)
156
157 /* controller setup */
158
159 static int s3c2410_nand_inithw(struct s3c2410_nand_info *info, 
160                                struct device *dev)
161 {
162         struct s3c2410_platform_nand *plat = to_nand_plat(dev);
163         unsigned int tacls, twrph0, twrph1;
164         unsigned long clkrate = clk_get_rate(info->clk);
165         unsigned long cfg;
166
167         /* calculate the timing information for the controller */
168
169         if (plat != NULL) {
170                 tacls = s3c2410_nand_calc_rate(plat->tacls, clkrate, 8);
171                 twrph0 = s3c2410_nand_calc_rate(plat->twrph0, clkrate, 8);
172                 twrph1 = s3c2410_nand_calc_rate(plat->twrph1, clkrate, 8);
173         } else {
174                 /* default timings */
175                 tacls = 8;
176                 twrph0 = 8;
177                 twrph1 = 8;
178         }
179         
180         if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
181                 printk(KERN_ERR PFX "cannot get timings suitable for board\n");
182                 return -EINVAL;
183         }
184
185         printk(KERN_INFO PFX "timing: Tacls %ldns, Twrph0 %ldns, Twrph1 %ldns\n",
186                to_ns(tacls, clkrate),
187                to_ns(twrph0, clkrate),
188                to_ns(twrph1, clkrate));
189
190         cfg  = S3C2410_NFCONF_EN;
191         cfg |= S3C2410_NFCONF_TACLS(tacls-1);
192         cfg |= S3C2410_NFCONF_TWRPH0(twrph0-1);
193         cfg |= S3C2410_NFCONF_TWRPH1(twrph1-1);
194
195         pr_debug(PFX "NF_CONF is 0x%lx\n", cfg);
196
197         writel(cfg, info->regs + S3C2410_NFCONF);
198         return 0;
199 }
200
201 /* select chip */
202
203 static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
204 {
205         struct s3c2410_nand_info *info;
206         struct s3c2410_nand_mtd *nmtd; 
207         struct nand_chip *this = mtd->priv;
208         unsigned long cur;
209
210         nmtd = this->priv;
211         info = nmtd->info;
212
213         cur = readl(info->regs + S3C2410_NFCONF);
214
215         if (chip == -1) {
216                 cur |= S3C2410_NFCONF_nFCE;
217         } else {
218                 if (chip > nmtd->set->nr_chips) {
219                         printk(KERN_ERR PFX "chip %d out of range\n", chip);
220                         return;
221                 }
222
223                 if (info->platform != NULL) {
224                         if (info->platform->select_chip != NULL)
225                                 (info->platform->select_chip)(nmtd->set, chip);
226                 }
227
228                 cur &= ~S3C2410_NFCONF_nFCE;
229         }
230
231         writel(cur, info->regs + S3C2410_NFCONF);
232 }
233
234 /* command and control functions */
235
236 static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
237 {
238         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
239         unsigned long cur;
240
241         switch (cmd) {
242         case NAND_CTL_SETNCE:
243                 cur = readl(info->regs + S3C2410_NFCONF);
244                 cur &= ~S3C2410_NFCONF_nFCE;
245                 writel(cur, info->regs + S3C2410_NFCONF);
246                 break;
247
248         case NAND_CTL_CLRNCE:
249                 cur = readl(info->regs + S3C2410_NFCONF);
250                 cur |= S3C2410_NFCONF_nFCE;
251                 writel(cur, info->regs + S3C2410_NFCONF);
252                 break;
253
254                 /* we don't need to implement these */
255         case NAND_CTL_SETCLE:
256         case NAND_CTL_CLRCLE:
257         case NAND_CTL_SETALE:
258         case NAND_CTL_CLRALE:
259                 pr_debug(PFX "s3c2410_nand_hwcontrol(%d) unusedn", cmd);
260                 break;
261         }
262 }
263
264 /* s3c2410_nand_command
265  *
266  * This function implements sending commands and the relevant address
267  * information to the chip, via the hardware controller. Since the
268  * S3C2410 generates the correct ALE/CLE signaling automatically, we
269  * do not need to use hwcontrol.
270 */
271
272 static void s3c2410_nand_command (struct mtd_info *mtd, unsigned command,
273                                   int column, int page_addr)
274 {
275         register struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
276         register struct nand_chip *this = mtd->priv;
277
278         /*
279          * Write out the command to the device.
280          */
281         if (command == NAND_CMD_SEQIN) {
282                 int readcmd;
283
284                 if (column >= mtd->oobblock) {
285                         /* OOB area */
286                         column -= mtd->oobblock;
287                         readcmd = NAND_CMD_READOOB;
288                 } else if (column < 256) {
289                         /* First 256 bytes --> READ0 */
290                         readcmd = NAND_CMD_READ0;
291                 } else {
292                         column -= 256;
293                         readcmd = NAND_CMD_READ1;
294                 }
295                 
296                 writeb(readcmd, info->regs + S3C2410_NFCMD);
297         }
298         writeb(command, info->regs + S3C2410_NFCMD);
299
300         /* Set ALE and clear CLE to start address cycle */
301
302         if (column != -1 || page_addr != -1) {
303
304                 /* Serially input address */
305                 if (column != -1) {
306                         /* Adjust columns for 16 bit buswidth */
307                         if (this->options & NAND_BUSWIDTH_16)
308                                 column >>= 1;
309                         writeb(column, info->regs + S3C2410_NFADDR);
310                 }
311                 if (page_addr != -1) {
312                         writeb((unsigned char) (page_addr), info->regs + S3C2410_NFADDR);
313                         writeb((unsigned char) (page_addr >> 8), info->regs + S3C2410_NFADDR);
314                         /* One more address cycle for higher density devices */
315                         if (this->chipsize & 0x0c000000) 
316                                 writeb((unsigned char) ((page_addr >> 16) & 0x0f),
317                                        info->regs + S3C2410_NFADDR);
318                 }
319                 /* Latch in address */
320         }
321         
322         /* 
323          * program and erase have their own busy handlers 
324          * status and sequential in needs no delay
325         */
326         switch (command) {
327                         
328         case NAND_CMD_PAGEPROG:
329         case NAND_CMD_ERASE1:
330         case NAND_CMD_ERASE2:
331         case NAND_CMD_SEQIN:
332         case NAND_CMD_STATUS:
333                 return;
334
335         case NAND_CMD_RESET:
336                 if (this->dev_ready)    
337                         break;
338
339                 udelay(this->chip_delay);
340                 writeb(NAND_CMD_STATUS, info->regs + S3C2410_NFCMD);
341
342                 while ( !(this->read_byte(mtd) & 0x40));
343                 return;
344
345         /* This applies to read commands */     
346         default:
347                 /* 
348                  * If we don't have access to the busy pin, we apply the given
349                  * command delay
350                 */
351                 if (!this->dev_ready) {
352                         udelay (this->chip_delay);
353                         return;
354                 }       
355         }
356         
357         /* Apply this short delay always to ensure that we do wait tWB in
358          * any case on any machine. */
359         ndelay (100);
360         /* wait until command is processed */
361         while (!this->dev_ready(mtd));
362 }
363
364
365 /* s3c2410_nand_devready()
366  *
367  * returns 0 if the nand is busy, 1 if it is ready
368 */
369
370 static int s3c2410_nand_devready(struct mtd_info *mtd)
371 {
372         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
373         
374         return readb(info->regs + S3C2410_NFSTAT) & S3C2410_NFSTAT_BUSY;
375 }
376
377 /* ECC handling functions */
378
379 static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
380                                      u_char *read_ecc, u_char *calc_ecc)
381 {
382         pr_debug("s3c2410_nand_correct_data(%p,%p,%p,%p)\n",
383                  mtd, dat, read_ecc, calc_ecc);
384
385         pr_debug("eccs: read %02x,%02x,%02x vs calc %02x,%02x,%02x\n",
386                  read_ecc[0], read_ecc[1], read_ecc[2],
387                  calc_ecc[0], calc_ecc[1], calc_ecc[2]);
388
389         if (read_ecc[0] == calc_ecc[0] &&
390             read_ecc[1] == calc_ecc[1] &&
391             read_ecc[2] == calc_ecc[2]) 
392                 return 0;
393
394         /* we curently have no method for correcting the error */
395
396         return -1;
397 }
398
399 static void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
400 {
401         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
402         unsigned long ctrl;
403
404         ctrl = readl(info->regs + S3C2410_NFCONF);
405         ctrl |= S3C2410_NFCONF_INITECC;
406         writel(ctrl, info->regs + S3C2410_NFCONF);
407 }
408
409 static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd,
410                                       const u_char *dat, u_char *ecc_code)
411 {
412         struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
413
414         ecc_code[0] = readb(info->regs + S3C2410_NFECC + 0);
415         ecc_code[1] = readb(info->regs + S3C2410_NFECC + 1);
416         ecc_code[2] = readb(info->regs + S3C2410_NFECC + 2);
417
418         pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n",
419                  ecc_code[0], ecc_code[1], ecc_code[2]);
420
421         return 0;
422 }
423
424
425 /* over-ride the standard functions for a little more speed? */
426
427 static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
428 {
429         struct nand_chip *this = mtd->priv;
430         readsb(this->IO_ADDR_R, buf, len);
431 }
432
433 static void s3c2410_nand_write_buf(struct mtd_info *mtd,
434                                    const u_char *buf, int len)
435 {
436         struct nand_chip *this = mtd->priv;
437         writesb(this->IO_ADDR_W, buf, len);
438 }
439
440 /* device management functions */
441
442 static int s3c2410_nand_remove(struct device *dev)
443 {
444         struct s3c2410_nand_info *info = to_nand_info(dev);
445
446         dev_set_drvdata(dev, NULL);
447
448         if (info == NULL) 
449                 return 0;
450
451         /* first thing we need to do is release all our mtds
452          * and their partitions, then go through freeing the
453          * resources used 
454          */
455         
456         if (info->mtds != NULL) {
457                 struct s3c2410_nand_mtd *ptr = info->mtds;
458                 int mtdno;
459
460                 for (mtdno = 0; mtdno < info->mtd_count; mtdno++, ptr++) {
461                         pr_debug("releasing mtd %d (%p)\n", mtdno, ptr);
462                         nand_release(&ptr->mtd);
463                 }
464
465                 kfree(info->mtds);
466         }
467
468         /* free the common resources */
469
470         if (info->clk != NULL && !IS_ERR(info->clk)) {
471                 clk_disable(info->clk);
472                 clk_unuse(info->clk);
473                 clk_put(info->clk);
474         }
475
476         if (info->regs != NULL) {
477                 iounmap(info->regs);
478                 info->regs = NULL;
479         }
480
481         if (info->area != NULL) {
482                 release_resource(info->area);
483                 kfree(info->area);
484                 info->area = NULL;
485         }
486
487         kfree(info);
488
489         return 0;
490 }
491
492 #ifdef CONFIG_MTD_PARTITIONS
493 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
494                                       struct s3c2410_nand_mtd *mtd,
495                                       struct s3c2410_nand_set *set)
496 {
497         if (set == NULL)
498                 return add_mtd_device(&mtd->mtd);
499
500         if (set->nr_partitions > 0 && set->partitions != NULL) {
501                 return add_mtd_partitions(&mtd->mtd,
502                                           set->partitions,
503                                           set->nr_partitions);
504         }
505
506         return add_mtd_device(&mtd->mtd);
507 }
508 #else
509 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
510                                       struct s3c2410_nand_mtd *mtd,
511                                       struct s3c2410_nand_set *set)
512 {
513         return add_mtd_device(&mtd->mtd);
514 }
515 #endif
516
517 /* s3c2410_nand_init_chip
518  *
519  * init a single instance of an chip 
520 */
521
522 static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
523                                    struct s3c2410_nand_mtd *nmtd,
524                                    struct s3c2410_nand_set *set)
525 {
526         struct nand_chip *chip = &nmtd->chip;
527
528         chip->IO_ADDR_R    = info->regs + S3C2410_NFDATA;
529         chip->IO_ADDR_W    = info->regs + S3C2410_NFDATA;
530         chip->hwcontrol    = s3c2410_nand_hwcontrol;
531         chip->dev_ready    = s3c2410_nand_devready;
532         chip->cmdfunc      = s3c2410_nand_command;
533         chip->write_buf    = s3c2410_nand_write_buf;
534         chip->read_buf     = s3c2410_nand_read_buf;
535         chip->select_chip  = s3c2410_nand_select_chip;
536         chip->chip_delay   = 50;
537         chip->priv         = nmtd;
538         chip->options      = 0;
539         chip->controller   = &info->controller;
540
541         nmtd->info         = info;
542         nmtd->mtd.priv     = chip;
543         nmtd->set          = set;
544
545         if (hardware_ecc) {
546                 chip->correct_data  = s3c2410_nand_correct_data;
547                 chip->enable_hwecc  = s3c2410_nand_enable_hwecc;
548                 chip->calculate_ecc = s3c2410_nand_calculate_ecc;
549                 chip->eccmode       = NAND_ECC_HW3_512;
550                 chip->autooob       = &nand_hw_eccoob;
551         } else {
552                 chip->eccmode       = NAND_ECC_SOFT;
553         }
554 }
555
556 /* s3c2410_nand_probe
557  *
558  * called by device layer when it finds a device matching
559  * one our driver can handled. This code checks to see if
560  * it can allocate all necessary resources then calls the
561  * nand layer to look for devices
562 */
563
564 static int s3c2410_nand_probe(struct device *dev)
565 {
566         struct platform_device *pdev = to_platform_device(dev);
567         struct s3c2410_platform_nand *plat = to_nand_plat(dev);
568         struct s3c2410_nand_info *info;
569         struct s3c2410_nand_mtd *nmtd;
570         struct s3c2410_nand_set *sets;
571         struct resource *res;
572         int err = 0;
573         int size;
574         int nr_sets;
575         int setno;
576
577         pr_debug("s3c2410_nand_probe(%p)\n", dev);
578
579         info = kmalloc(sizeof(*info), GFP_KERNEL);
580         if (info == NULL) {
581                 printk(KERN_ERR PFX "no memory for flash info\n");
582                 err = -ENOMEM;
583                 goto exit_error;
584         }
585
586         memzero(info, sizeof(*info));
587         dev_set_drvdata(dev, info);
588
589         spin_lock_init(&info->controller.lock);
590
591         /* get the clock source and enable it */
592
593         info->clk = clk_get(dev, "nand");
594         if (IS_ERR(info->clk)) {
595                 printk(KERN_ERR PFX "failed to get clock");
596                 err = -ENOENT;
597                 goto exit_error;
598         }
599
600         clk_use(info->clk);
601         clk_enable(info->clk);
602
603         /* allocate and map the resource */
604
605         res = pdev->resource;  /* assume that the flash has one resource */
606         size = res->end - res->start + 1;
607
608         info->area = request_mem_region(res->start, size, pdev->name);
609
610         if (info->area == NULL) {
611                 printk(KERN_ERR PFX "cannot reserve register region\n");
612                 err = -ENOENT;
613                 goto exit_error;
614         }
615
616         info->device = dev;
617         info->platform = plat;
618         info->regs = ioremap(res->start, size);
619
620         if (info->regs == NULL) {
621                 printk(KERN_ERR PFX "cannot reserve register region\n");
622                 err = -EIO;
623                 goto exit_error;
624         }               
625
626         printk(KERN_INFO PFX "mapped registers at %p\n", info->regs);
627
628         /* initialise the hardware */
629
630         err = s3c2410_nand_inithw(info, dev);
631         if (err != 0)
632                 goto exit_error;
633
634         sets = (plat != NULL) ? plat->sets : NULL;
635         nr_sets = (plat != NULL) ? plat->nr_sets : 1;
636
637         info->mtd_count = nr_sets;
638
639         /* allocate our information */
640
641         size = nr_sets * sizeof(*info->mtds);
642         info->mtds = kmalloc(size, GFP_KERNEL);
643         if (info->mtds == NULL) {
644                 printk(KERN_ERR PFX "failed to allocate mtd storage\n");
645                 err = -ENOMEM;
646                 goto exit_error;
647         }
648
649         memzero(info->mtds, size);
650
651         /* initialise all possible chips */
652
653         nmtd = info->mtds;
654
655         for (setno = 0; setno < nr_sets; setno++, nmtd++) {
656                 pr_debug("initialising set %d (%p, info %p)\n",
657                          setno, nmtd, info);
658                 
659                 s3c2410_nand_init_chip(info, nmtd, sets);
660
661                 nmtd->scan_res = nand_scan(&nmtd->mtd,
662                                            (sets) ? sets->nr_chips : 1);
663
664                 if (nmtd->scan_res == 0) {
665                         s3c2410_nand_add_partition(info, nmtd, sets);
666                 }
667
668                 if (sets != NULL)
669                         sets++;
670         }
671         
672         pr_debug("initialised ok\n");
673         return 0;
674
675  exit_error:
676         s3c2410_nand_remove(dev);
677
678         if (err == 0)
679                 err = -EINVAL;
680         return err;
681 }
682
683 static struct device_driver s3c2410_nand_driver = {
684         .name           = "s3c2410-nand",
685         .bus            = &platform_bus_type,
686         .probe          = s3c2410_nand_probe,
687         .remove         = s3c2410_nand_remove,
688 };
689
690 static int __init s3c2410_nand_init(void)
691 {
692         printk("S3C2410 NAND Driver, (c) 2004 Simtec Electronics\n");
693         return driver_register(&s3c2410_nand_driver);
694 }
695
696 static void __exit s3c2410_nand_exit(void)
697 {
698         driver_unregister(&s3c2410_nand_driver);
699 }
700
701 module_init(s3c2410_nand_init);
702 module_exit(s3c2410_nand_exit);
703
704 MODULE_LICENSE("GPL");
705 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
706 MODULE_DESCRIPTION("S3C2410 MTD NAND driver");