[TG3]: Add tagged status support.
[linux-2.6/verdex.git] / drivers / mtd / nand / au1550nd.c
blob4c7719ce3f4835abc09a55a45cbb0c5473caf569
1 /*
2 * drivers/mtd/nand/au1550nd.c
4 * Copyright (C) 2004 Embedded Edge, LLC
6 * $Id: au1550nd.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 #include <linux/slab.h>
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/mtd/mtd.h>
18 #include <linux/mtd/nand.h>
19 #include <linux/mtd/partitions.h>
20 #include <asm/io.h>
22 /* fixme: this is ugly */
23 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 0)
24 #include <asm/mach-au1x00/au1000.h>
25 #ifdef CONFIG_MIPS_PB1550
26 #include <asm/mach-pb1x00/pb1550.h>
27 #endif
28 #ifdef CONFIG_MIPS_DB1550
29 #include <asm/mach-db1x00/db1x00.h>
30 #endif
31 #else
32 #include <asm/au1000.h>
33 #ifdef CONFIG_MIPS_PB1550
34 #include <asm/pb1550.h>
35 #endif
36 #ifdef CONFIG_MIPS_DB1550
37 #include <asm/db1x00.h>
38 #endif
39 #endif
42 * MTD structure for NAND controller
44 static struct mtd_info *au1550_mtd = NULL;
45 static void __iomem *p_nand;
46 static int nand_width = 1; /* default x8*/
48 #define NAND_CS 1
51 * Define partitions for flash device
53 const static struct mtd_partition partition_info[] = {
54 #ifdef CONFIG_MIPS_PB1550
55 #define NUM_PARTITIONS 2
57 .name = "Pb1550 NAND FS 0",
58 .offset = 0,
59 .size = 8*1024*1024
62 .name = "Pb1550 NAND FS 1",
63 .offset = MTDPART_OFS_APPEND,
64 .size = MTDPART_SIZ_FULL
66 #endif
67 #ifdef CONFIG_MIPS_DB1550
68 #define NUM_PARTITIONS 2
70 .name = "Db1550 NAND FS 0",
71 .offset = 0,
72 .size = 8*1024*1024
75 .name = "Db1550 NAND FS 1",
76 .offset = MTDPART_OFS_APPEND,
77 .size = MTDPART_SIZ_FULL
79 #endif
83 /**
84 * au_read_byte - read one byte from the chip
85 * @mtd: MTD device structure
87 * read function for 8bit buswith
89 static u_char au_read_byte(struct mtd_info *mtd)
91 struct nand_chip *this = mtd->priv;
92 u_char ret = readb(this->IO_ADDR_R);
93 au_sync();
94 return ret;
97 /**
98 * au_write_byte - write one byte to the chip
99 * @mtd: MTD device structure
100 * @byte: pointer to data byte to write
102 * write function for 8it buswith
104 static void au_write_byte(struct mtd_info *mtd, u_char byte)
106 struct nand_chip *this = mtd->priv;
107 writeb(byte, this->IO_ADDR_W);
108 au_sync();
112 * au_read_byte16 - read one byte endianess aware from the chip
113 * @mtd: MTD device structure
115 * read function for 16bit buswith with
116 * endianess conversion
118 static u_char au_read_byte16(struct mtd_info *mtd)
120 struct nand_chip *this = mtd->priv;
121 u_char ret = (u_char) cpu_to_le16(readw(this->IO_ADDR_R));
122 au_sync();
123 return ret;
127 * au_write_byte16 - write one byte endianess aware to the chip
128 * @mtd: MTD device structure
129 * @byte: pointer to data byte to write
131 * write function for 16bit buswith with
132 * endianess conversion
134 static void au_write_byte16(struct mtd_info *mtd, u_char byte)
136 struct nand_chip *this = mtd->priv;
137 writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
138 au_sync();
142 * au_read_word - read one word from the chip
143 * @mtd: MTD device structure
145 * read function for 16bit buswith without
146 * endianess conversion
148 static u16 au_read_word(struct mtd_info *mtd)
150 struct nand_chip *this = mtd->priv;
151 u16 ret = readw(this->IO_ADDR_R);
152 au_sync();
153 return ret;
157 * au_write_word - write one word to the chip
158 * @mtd: MTD device structure
159 * @word: data word to write
161 * write function for 16bit buswith without
162 * endianess conversion
164 static void au_write_word(struct mtd_info *mtd, u16 word)
166 struct nand_chip *this = mtd->priv;
167 writew(word, this->IO_ADDR_W);
168 au_sync();
172 * au_write_buf - write buffer to chip
173 * @mtd: MTD device structure
174 * @buf: data buffer
175 * @len: number of bytes to write
177 * write function for 8bit buswith
179 static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
181 int i;
182 struct nand_chip *this = mtd->priv;
184 for (i=0; i<len; i++) {
185 writeb(buf[i], this->IO_ADDR_W);
186 au_sync();
191 * au_read_buf - read chip data into buffer
192 * @mtd: MTD device structure
193 * @buf: buffer to store date
194 * @len: number of bytes to read
196 * read function for 8bit buswith
198 static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
200 int i;
201 struct nand_chip *this = mtd->priv;
203 for (i=0; i<len; i++) {
204 buf[i] = readb(this->IO_ADDR_R);
205 au_sync();
210 * au_verify_buf - Verify chip data against buffer
211 * @mtd: MTD device structure
212 * @buf: buffer containing the data to compare
213 * @len: number of bytes to compare
215 * verify function for 8bit buswith
217 static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
219 int i;
220 struct nand_chip *this = mtd->priv;
222 for (i=0; i<len; i++) {
223 if (buf[i] != readb(this->IO_ADDR_R))
224 return -EFAULT;
225 au_sync();
228 return 0;
232 * au_write_buf16 - write buffer to chip
233 * @mtd: MTD device structure
234 * @buf: data buffer
235 * @len: number of bytes to write
237 * write function for 16bit buswith
239 static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
241 int i;
242 struct nand_chip *this = mtd->priv;
243 u16 *p = (u16 *) buf;
244 len >>= 1;
246 for (i=0; i<len; i++) {
247 writew(p[i], this->IO_ADDR_W);
248 au_sync();
254 * au_read_buf16 - read chip data into buffer
255 * @mtd: MTD device structure
256 * @buf: buffer to store date
257 * @len: number of bytes to read
259 * read function for 16bit buswith
261 static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
263 int i;
264 struct nand_chip *this = mtd->priv;
265 u16 *p = (u16 *) buf;
266 len >>= 1;
268 for (i=0; i<len; i++) {
269 p[i] = readw(this->IO_ADDR_R);
270 au_sync();
275 * au_verify_buf16 - Verify chip data against buffer
276 * @mtd: MTD device structure
277 * @buf: buffer containing the data to compare
278 * @len: number of bytes to compare
280 * verify function for 16bit buswith
282 static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
284 int i;
285 struct nand_chip *this = mtd->priv;
286 u16 *p = (u16 *) buf;
287 len >>= 1;
289 for (i=0; i<len; i++) {
290 if (p[i] != readw(this->IO_ADDR_R))
291 return -EFAULT;
292 au_sync();
294 return 0;
298 static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
300 register struct nand_chip *this = mtd->priv;
302 switch(cmd){
304 case NAND_CTL_SETCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_CMD; break;
305 case NAND_CTL_CLRCLE: this->IO_ADDR_W = p_nand + MEM_STNAND_DATA; break;
307 case NAND_CTL_SETALE: this->IO_ADDR_W = p_nand + MEM_STNAND_ADDR; break;
308 case NAND_CTL_CLRALE:
309 this->IO_ADDR_W = p_nand + MEM_STNAND_DATA;
310 /* FIXME: Nobody knows why this is neccecary,
311 * but it works only that way */
312 udelay(1);
313 break;
315 case NAND_CTL_SETNCE:
316 /* assert (force assert) chip enable */
317 au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break;
318 break;
320 case NAND_CTL_CLRNCE:
321 /* deassert chip enable */
322 au_writel(0, MEM_STNDCTL); break;
323 break;
326 this->IO_ADDR_R = this->IO_ADDR_W;
328 /* Drain the writebuffer */
329 au_sync();
332 int au1550_device_ready(struct mtd_info *mtd)
334 int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
335 au_sync();
336 return ret;
340 * Main initialization routine
342 int __init au1550_init (void)
344 struct nand_chip *this;
345 u16 boot_swapboot = 0; /* default value */
346 int retval;
348 /* Allocate memory for MTD device structure and private data */
349 au1550_mtd = kmalloc (sizeof(struct mtd_info) +
350 sizeof (struct nand_chip), GFP_KERNEL);
351 if (!au1550_mtd) {
352 printk ("Unable to allocate NAND MTD dev structure.\n");
353 return -ENOMEM;
356 /* Get pointer to private data */
357 this = (struct nand_chip *) (&au1550_mtd[1]);
359 /* Initialize structures */
360 memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));
361 memset((char *) this, 0, sizeof(struct nand_chip));
363 /* Link the private data with the MTD structure */
364 au1550_mtd->priv = this;
367 /* MEM_STNDCTL: disable ints, disable nand boot */
368 au_writel(0, MEM_STNDCTL);
370 #ifdef CONFIG_MIPS_PB1550
371 /* set gpio206 high */
372 au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
374 boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) |
375 ((bcsr->status >> 6) & 0x1);
376 switch (boot_swapboot) {
377 case 0:
378 case 2:
379 case 8:
380 case 0xC:
381 case 0xD:
382 /* x16 NAND Flash */
383 nand_width = 0;
384 break;
385 case 1:
386 case 9:
387 case 3:
388 case 0xE:
389 case 0xF:
390 /* x8 NAND Flash */
391 nand_width = 1;
392 break;
393 default:
394 printk("Pb1550 NAND: bad boot:swap\n");
395 retval = -EINVAL;
396 goto outmem;
398 #endif
400 /* Configure RCE1 - should be done by YAMON */
401 au_writel(0x5 | (nand_width << 22), 0xB4001010); /* MEM_STCFG1 */
402 au_writel(NAND_TIMING, 0xB4001014); /* MEM_STTIME1 */
403 au_sync();
405 /* setup and enable chip select, MEM_STADDR1 */
406 /* we really need to decode offsets only up till 0x20 */
407 au_writel((1<<28) | (NAND_PHYS_ADDR>>4) |
408 (((NAND_PHYS_ADDR + 0x1000)-1) & (0x3fff<<18)>>18),
409 MEM_STADDR1);
410 au_sync();
412 p_nand = ioremap(NAND_PHYS_ADDR, 0x1000);
414 /* Set address of hardware control function */
415 this->hwcontrol = au1550_hwcontrol;
416 this->dev_ready = au1550_device_ready;
417 /* 30 us command delay time */
418 this->chip_delay = 30;
419 this->eccmode = NAND_ECC_SOFT;
421 this->options = NAND_NO_AUTOINCR;
423 if (!nand_width)
424 this->options |= NAND_BUSWIDTH_16;
426 this->read_byte = (!nand_width) ? au_read_byte16 : au_read_byte;
427 this->write_byte = (!nand_width) ? au_write_byte16 : au_write_byte;
428 this->write_word = au_write_word;
429 this->read_word = au_read_word;
430 this->write_buf = (!nand_width) ? au_write_buf16 : au_write_buf;
431 this->read_buf = (!nand_width) ? au_read_buf16 : au_read_buf;
432 this->verify_buf = (!nand_width) ? au_verify_buf16 : au_verify_buf;
434 /* Scan to find existence of the device */
435 if (nand_scan (au1550_mtd, 1)) {
436 retval = -ENXIO;
437 goto outio;
440 /* Register the partitions */
441 add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS);
443 return 0;
445 outio:
446 iounmap ((void *)p_nand);
448 outmem:
449 kfree (au1550_mtd);
450 return retval;
453 module_init(au1550_init);
456 * Clean up routine
458 #ifdef MODULE
459 static void __exit au1550_cleanup (void)
461 struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];
463 /* Release resources, unregister device */
464 nand_release (au1550_mtd);
466 /* Free the MTD device structure */
467 kfree (au1550_mtd);
469 /* Unmap */
470 iounmap ((void *)p_nand);
472 module_exit(au1550_cleanup);
473 #endif
475 MODULE_LICENSE("GPL");
476 MODULE_AUTHOR("Embedded Edge, LLC");
477 MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");