This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / mtd / nand / tx4938ndfmc.c
1 /*
2  * drivers/mtd/nand/tx4938ndfmc.c
3  *
4  *  Overview:
5  *   This is a device driver for the NAND flash device connected to
6  *   TX4938 internal NAND Memory Controller.
7  *   TX4938 NDFMC is almost same as TX4925 NDFMC, but register size are 64 bit.
8  *
9  * Author: source@mvista.com
10  *
11  * Based on spia.c by Steven J. Hill
12  *
13  * $Id: tx4938ndfmc.c,v 1.2 2004/03/27 19:55:53 gleixner Exp $
14  *
15  * Copyright (C) 2000-2001 Toshiba Corporation 
16  *
17  * 2003 (c) MontaVista Software, Inc. This file is licensed under the
18  * terms of the GNU General Public License version 2. This program is
19  * licensed "as is" without any warranty of any kind, whether express
20  * or implied.
21  */
22 #include <linux/config.h>
23 #include <linux/slab.h>
24 #include <linux/init.h>
25 #include <linux/module.h>
26 #include <linux/mtd/mtd.h>
27 #include <linux/mtd/nand.h>
28 #include <linux/mtd/nand_ecc.h>
29 #include <linux/mtd/partitions.h>
30 #include <asm/io.h>
31 #include <asm/bootinfo.h>
32 #include <linux/delay.h>
33 #include <asm/tx4938/rbtx4938.h>
34
35 extern struct nand_oobinfo jffs2_oobinfo;
36
37 /*
38  * MTD structure for TX4938 NDFMC
39  */
40 static struct mtd_info *tx4938ndfmc_mtd;
41
42 /*
43  * Define partitions for flash device
44  */
45 #define flush_wb()      (void)tx4938_ndfmcptr->mcr;
46
47 #define NUM_PARTITIONS          3
48 #define NUMBER_OF_CIS_BLOCKS    24
49 #define SIZE_OF_BLOCK           0x00004000
50 #define NUMBER_OF_BLOCK_PER_ZONE 1024
51 #define SIZE_OF_ZONE            (NUMBER_OF_BLOCK_PER_ZONE * SIZE_OF_BLOCK)
52 #ifndef CONFIG_MTD_CMDLINE_PARTS
53 /*
54  * You can use the following sample of MTD partitions 
55  * on the NAND Flash Memory 32MB or more.
56  *
57  * The following figure shows the image of the sample partition on
58  * the 32MB NAND Flash Memory. 
59  *
60  *   Block No.
61  *    0 +-----------------------------+ ------
62  *      |             CIS             |   ^
63  *   24 +-----------------------------+   |
64  *      |         kernel image        |   | Zone 0
65  *      |                             |   |
66  *      +-----------------------------+   |
67  * 1023 |         unused area         |   v
68  *      +-----------------------------+ ------
69  * 1024 |            JFFS2            |   ^
70  *      |                             |   |
71  *      |                             |   | Zone 1
72  *      |                             |   |
73  *      |                             |   |
74  *      |                             |   v
75  * 2047 +-----------------------------+ ------
76  *
77  */
78 static struct mtd_partition partition_info[NUM_PARTITIONS] = {
79         {
80                 .name = "RBTX4938 CIS Area",
81                 .offset =  0,
82                 .size =    (NUMBER_OF_CIS_BLOCKS * SIZE_OF_BLOCK),
83                 .mask_flags  = MTD_WRITEABLE    /* This partition is NOT writable */
84         },
85         {
86                 .name = "RBTX4938 kernel image",
87                 .offset =  MTDPART_OFS_APPEND,
88                 .size =    8 * 0x00100000,      /* 8MB (Depends on size of kernel image) */
89                 .mask_flags  = MTD_WRITEABLE    /* This partition is NOT writable */
90         },
91         {
92                 .name = "Root FS (JFFS2)",
93                 .offset =  (0 + SIZE_OF_ZONE),    /* start address of next zone */
94                 .size =    MTDPART_SIZ_FULL
95         },
96 };
97 #endif
98
99 static void tx4938ndfmc_hwcontrol(struct mtd_info *mtd, int cmd)
100 {
101         switch (cmd) {
102                 case NAND_CTL_SETCLE:
103                         tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CLE;
104                         break;
105                 case NAND_CTL_CLRCLE:
106                         tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CLE;
107                         break;
108                 case NAND_CTL_SETALE:
109                         tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_ALE;
110                         break;
111                 case NAND_CTL_CLRALE:
112                         tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_ALE;
113                         break;
114                 /* TX4938_NDFMCR_CE bit is 0:high 1:low */
115                 case NAND_CTL_SETNCE:
116                         tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_CE;
117                         break;
118                 case NAND_CTL_CLRNCE:
119                         tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_CE;
120                         break;
121                 case NAND_CTL_SETWP:
122                         tx4938_ndfmcptr->mcr |= TX4938_NDFMCR_WE;
123                         break;
124                 case NAND_CTL_CLRWP:
125                         tx4938_ndfmcptr->mcr &= ~TX4938_NDFMCR_WE;
126                         break;
127         }
128 }
129 static int tx4938ndfmc_dev_ready(struct mtd_info *mtd)
130 {
131         flush_wb();
132         return !(tx4938_ndfmcptr->sr & TX4938_NDFSR_BUSY);
133 }
134 static void tx4938ndfmc_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
135 {
136         u32 mcr = tx4938_ndfmcptr->mcr;
137         mcr &= ~TX4938_NDFMCR_ECC_ALL;
138         tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;
139         tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_READ;
140         ecc_code[1] = tx4938_ndfmcptr->dtr;
141         ecc_code[0] = tx4938_ndfmcptr->dtr;
142         ecc_code[2] = tx4938_ndfmcptr->dtr;
143         tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;
144 }
145 static void tx4938ndfmc_enable_hwecc(struct mtd_info *mtd, int mode)
146 {
147         u32 mcr = tx4938_ndfmcptr->mcr;
148         mcr &= ~TX4938_NDFMCR_ECC_ALL;
149         tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_RESET;
150         tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_OFF;
151         tx4938_ndfmcptr->mcr = mcr | TX4938_NDFMCR_ECC_ON;
152 }
153
154 static u_char tx4938ndfmc_nand_read_byte(struct mtd_info *mtd)
155 {
156         struct nand_chip *this = mtd->priv;
157         return tx4938_read_nfmc(this->IO_ADDR_R);
158 }
159
160 static void tx4938ndfmc_nand_write_byte(struct mtd_info *mtd, u_char byte)
161 {
162         struct nand_chip *this = mtd->priv;
163         tx4938_write_nfmc(byte, this->IO_ADDR_W);
164 }
165
166 static void tx4938ndfmc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
167 {
168         int i;
169         struct nand_chip *this = mtd->priv;
170
171         for (i=0; i<len; i++)
172                 tx4938_write_nfmc(buf[i], this->IO_ADDR_W);
173 }
174
175 static void tx4938ndfmc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
176 {
177         int i;
178         struct nand_chip *this = mtd->priv;
179
180         for (i=0; i<len; i++)
181                 buf[i] = tx4938_read_nfmc(this->IO_ADDR_R);
182 }
183
184 static int tx4938ndfmc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
185 {
186         int i;
187         struct nand_chip *this = mtd->priv;
188
189         for (i=0; i<len; i++)
190                 if (buf[i] != tx4938_read_nfmc(this->IO_ADDR_R))
191                         return -EFAULT;
192
193         return 0;
194 }
195
196 /*
197  * Send command to NAND device
198  */
199 static void tx4938ndfmc_nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr)
200 {
201         register struct nand_chip *this = mtd->priv;
202
203         /* Begin command latch cycle */
204         this->hwcontrol(mtd, NAND_CTL_SETCLE);
205         /*
206          * Write out the command to the device.
207          */
208         if (command == NAND_CMD_SEQIN) {
209                 int readcmd;
210
211                 if (column >= mtd->oobblock) {
212                         /* OOB area */
213                         column -= mtd->oobblock;
214                         readcmd = NAND_CMD_READOOB;
215                 } else if (column < 256) {
216                         /* First 256 bytes --> READ0 */
217                         readcmd = NAND_CMD_READ0;
218                 } else {
219                         column -= 256;
220                         readcmd = NAND_CMD_READ1;
221                 }
222                 this->write_byte(mtd, readcmd);
223         }
224         this->write_byte(mtd, command);
225
226         /* Set ALE and clear CLE to start address cycle */
227         this->hwcontrol(mtd, NAND_CTL_CLRCLE);
228
229         if (column != -1 || page_addr != -1) {
230                 this->hwcontrol(mtd, NAND_CTL_SETALE);
231
232                 /* Serially input address */
233                 if (column != -1)
234                         this->write_byte(mtd, column);
235                 if (page_addr != -1) {
236                         this->write_byte(mtd, (unsigned char) (page_addr & 0xff));
237                         this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff));
238                         /* One more address cycle for higher density devices */
239                         if (mtd->size & 0x0c000000) 
240                                 this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f));
241                 }
242                 /* Latch in address */
243                 this->hwcontrol(mtd, NAND_CTL_CLRALE);
244         }
245         
246         /* 
247          * program and erase have their own busy handlers 
248          * status and sequential in needs no delay
249         */
250         switch (command) {
251                         
252         case NAND_CMD_PAGEPROG:
253                 /* Turn off WE */
254                 this->hwcontrol (mtd, NAND_CTL_CLRWP);
255                 return;
256
257         case NAND_CMD_SEQIN:
258                 /* Turn on WE */
259                 this->hwcontrol (mtd, NAND_CTL_SETWP);
260                 return;
261
262         case NAND_CMD_ERASE1:
263         case NAND_CMD_ERASE2:
264         case NAND_CMD_STATUS:
265                 return;
266
267         case NAND_CMD_RESET:
268                 if (this->dev_ready)    
269                         break;
270                 this->hwcontrol(mtd, NAND_CTL_SETCLE);
271                 this->write_byte(mtd, NAND_CMD_STATUS);
272                 this->hwcontrol(mtd, NAND_CTL_CLRCLE);
273                 while ( !(this->read_byte(mtd) & 0x40));
274                 return;
275
276         /* This applies to read commands */     
277         default:
278                 /* 
279                  * If we don't have access to the busy pin, we apply the given
280                  * command delay
281                 */
282                 if (!this->dev_ready) {
283                         udelay (this->chip_delay);
284                         return;
285                 }       
286         }
287         
288         /* wait until command is processed */
289         while (!this->dev_ready(mtd));
290 }
291
292 #ifdef CONFIG_MTD_CMDLINE_PARTS
293 extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, char *);
294 #endif
295 /*
296  * Main initialization routine
297  */
298 int __init tx4938ndfmc_init (void)
299 {
300         struct nand_chip *this;
301         int bsprt = 0, hold = 0xf, spw = 0xf;
302         int protected = 0;
303
304         if ((*rbtx4938_piosel_ptr & 0x0c) != 0x08) {
305                 printk("TX4938 NDFMC: disabled by IOC PIOSEL\n");
306                 return -ENODEV;
307         }
308         bsprt = 1;
309         hold = 2;
310         spw = 9 - 1;    /* 8 GBUSCLK = 80ns (@ GBUSCLK 100MHz) */
311
312         if ((tx4938_ccfgptr->pcfg &
313              (TX4938_PCFG_ATA_SEL|TX4938_PCFG_ISA_SEL|TX4938_PCFG_NDF_SEL))
314             != TX4938_PCFG_NDF_SEL) {
315                 printk("TX4938 NDFMC: disabled by PCFG.\n");
316                 return -ENODEV;
317         }
318
319         /* reset NDFMC */
320         tx4938_ndfmcptr->rstr |= TX4938_NDFRSTR_RST;
321         while (tx4938_ndfmcptr->rstr & TX4938_NDFRSTR_RST)
322                 ;
323         /* setup BusSeparete, Hold Time, Strobe Pulse Width */
324         tx4938_ndfmcptr->mcr = bsprt ? TX4938_NDFMCR_BSPRT : 0;
325         tx4938_ndfmcptr->spr = hold << 4 | spw;
326
327         /* Allocate memory for MTD device structure and private data */
328         tx4938ndfmc_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip),
329                                       GFP_KERNEL);
330         if (!tx4938ndfmc_mtd) {
331                 printk ("Unable to allocate TX4938 NDFMC MTD device structure.\n");
332                 return -ENOMEM;
333         }
334
335         /* Get pointer to private data */
336         this = (struct nand_chip *) (&tx4938ndfmc_mtd[1]);
337
338         /* Initialize structures */
339         memset((char *) tx4938ndfmc_mtd, 0, sizeof(struct mtd_info));
340         memset((char *) this, 0, sizeof(struct nand_chip));
341
342         /* Link the private data with the MTD structure */
343         tx4938ndfmc_mtd->priv = this;
344
345         /* Set address of NAND IO lines */
346         this->IO_ADDR_R = (unsigned long)&tx4938_ndfmcptr->dtr;
347         this->IO_ADDR_W = (unsigned long)&tx4938_ndfmcptr->dtr;
348         this->hwcontrol = tx4938ndfmc_hwcontrol;
349         this->dev_ready = tx4938ndfmc_dev_ready;
350         this->calculate_ecc = tx4938ndfmc_calculate_ecc;
351         this->correct_data = nand_correct_data;
352         this->enable_hwecc = tx4938ndfmc_enable_hwecc;
353         this->eccmode = NAND_ECC_HW3_256;
354         this->chip_delay = 100;
355         this->read_byte = tx4938ndfmc_nand_read_byte;
356         this->write_byte = tx4938ndfmc_nand_write_byte;
357         this->cmdfunc = tx4938ndfmc_nand_command;
358         this->write_buf = tx4938ndfmc_nand_write_buf;
359         this->read_buf = tx4938ndfmc_nand_read_buf;
360         this->verify_buf = tx4938ndfmc_nand_verify_buf;
361
362         /* Scan to find existance of the device */
363         if (nand_scan (tx4938ndfmc_mtd, 1)) {
364                 kfree (tx4938ndfmc_mtd);
365                 return -ENXIO;
366         }
367
368         /* Allocate memory for internal data buffer */
369         this->data_buf = kmalloc (sizeof(u_char) * (tx4938ndfmc_mtd->oobblock + tx4938ndfmc_mtd->oobsize), GFP_KERNEL);
370         if (!this->data_buf) {
371                 printk ("Unable to allocate NAND data buffer for TX4938.\n");
372                 kfree (tx4938ndfmc_mtd);
373                 return -ENOMEM;
374         }
375
376         if (protected) {
377                 printk(KERN_INFO "TX4938 NDFMC: write protected.\n");
378                 tx4938ndfmc_mtd->flags &= ~(MTD_WRITEABLE | MTD_ERASEABLE);
379         }
380
381 #ifdef CONFIG_MTD_CMDLINE_PARTS
382         {
383                 int mtd_parts_nb = 0;
384                 struct mtd_partition *mtd_parts = 0;
385                 mtd_parts_nb = parse_cmdline_partitions(tx4938ndfmc_mtd, &mtd_parts, "tx4938ndfmc");
386                 if (mtd_parts_nb > 0)
387                         add_mtd_partitions(tx4938ndfmc_mtd, mtd_parts, mtd_parts_nb);
388                 else
389                         add_mtd_device(tx4938ndfmc_mtd);
390         }
391 #else
392         add_mtd_partitions(tx4938ndfmc_mtd, partition_info, NUM_PARTITIONS );
393 #endif
394
395         return 0;
396 }
397 module_init(tx4938ndfmc_init);
398
399 /*
400  * Clean up routine
401  */
402 static void __exit tx4938ndfmc_cleanup (void)
403 {
404         struct nand_chip *this = (struct nand_chip *) tx4938ndfmc_mtd->priv;
405
406         /* Unregister the device */
407 #ifdef CONFIG_MTD_CMDLINE_PARTS
408         del_mtd_partitions(tx4938ndfmc_mtd);
409 #endif
410         del_mtd_device (tx4938ndfmc_mtd);
411
412         /* Free the MTD device structure */
413         kfree (tx4938ndfmc_mtd);
414
415         /* Free internal data buffer */
416         kfree (this->data_buf);
417 }
418 module_exit(tx4938ndfmc_cleanup);
419
420 MODULE_LICENSE("GPL");
421 MODULE_AUTHOR("Alice Hennessy <ahennessy@mvista.com>");
422 MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on TX4938 NDFMC");