Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *  drivers/mtd/nand/au1550nd.c
  3  *
  4  *  Copyright (C) 2004 Embedded Edge, LLC
  5  *
  6  * $Id: au1550nd.c,v 1.11 2004/11/04 12:53:10 gleixner Exp $
  7  *
  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.
 11  *
 12  */
 13 
 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>
 21 
 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
 40 
 41 /*
 42  * MTD structure for NAND controller
 43  */
 44 static struct mtd_info *au1550_mtd = NULL;
 45 static void __iomem *p_nand;
 46 static int nand_width = 1; /* default x8*/
 47 
 48 #define NAND_CS 1
 49 
 50 /*
 51  * Define partitions for flash device
 52  */
 53 const static struct mtd_partition partition_info[] = {
 54 #ifdef CONFIG_MIPS_PB1550
 55 #define NUM_PARTITIONS            2
 56         { 
 57                 .name = "Pb1550 NAND FS 0",
 58                 .offset = 0,
 59                 .size = 8*1024*1024 
 60         },
 61         { 
 62                 .name = "Pb1550 NAND FS 1",
 63                 .offset =  MTDPART_OFS_APPEND,
 64                 .size =    MTDPART_SIZ_FULL
 65         }
 66 #endif
 67 #ifdef CONFIG_MIPS_DB1550
 68 #define NUM_PARTITIONS            2
 69         { 
 70                 .name = "Db1550 NAND FS 0",
 71                 .offset = 0,
 72                 .size = 8*1024*1024 
 73         },
 74         { 
 75                 .name = "Db1550 NAND FS 1",
 76                 .offset =  MTDPART_OFS_APPEND,
 77                 .size =    MTDPART_SIZ_FULL
 78         }
 79 #endif
 80 };
 81 
 82 
 83 /**
 84  * au_read_byte -  read one byte from the chip
 85  * @mtd:        MTD device structure
 86  *
 87  *  read function for 8bit buswith
 88  */
 89 static u_char au_read_byte(struct mtd_info *mtd)
 90 {
 91         struct nand_chip *this = mtd->priv;
 92         u_char ret = readb(this->IO_ADDR_R);
 93         au_sync();
 94         return ret;
 95 }
 96 
 97 /**
 98  * au_write_byte -  write one byte to the chip
 99  * @mtd:        MTD device structure
100  * @byte:       pointer to data byte to write
101  *
102  *  write function for 8it buswith
103  */
104 static void au_write_byte(struct mtd_info *mtd, u_char byte)
105 {
106         struct nand_chip *this = mtd->priv;
107         writeb(byte, this->IO_ADDR_W);
108         au_sync();
109 }
110 
111 /**
112  * au_read_byte16 -  read one byte endianess aware from the chip
113  * @mtd:        MTD device structure
114  *
115  *  read function for 16bit buswith with 
116  * endianess conversion
117  */
118 static u_char au_read_byte16(struct mtd_info *mtd)
119 {
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;
124 }
125 
126 /**
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
130  *
131  *  write function for 16bit buswith with
132  * endianess conversion
133  */
134 static void au_write_byte16(struct mtd_info *mtd, u_char byte)
135 {
136         struct nand_chip *this = mtd->priv;
137         writew(le16_to_cpu((u16) byte), this->IO_ADDR_W);
138         au_sync();
139 }
140 
141 /**
142  * au_read_word -  read one word from the chip
143  * @mtd:        MTD device structure
144  *
145  *  read function for 16bit buswith without 
146  * endianess conversion
147  */
148 static u16 au_read_word(struct mtd_info *mtd)
149 {
150         struct nand_chip *this = mtd->priv;
151         u16 ret = readw(this->IO_ADDR_R);
152         au_sync();
153         return ret;
154 }
155 
156 /**
157  * au_write_word -  write one word to the chip
158  * @mtd:        MTD device structure
159  * @word:       data word to write
160  *
161  *  write function for 16bit buswith without 
162  * endianess conversion
163  */
164 static void au_write_word(struct mtd_info *mtd, u16 word)
165 {
166         struct nand_chip *this = mtd->priv;
167         writew(word, this->IO_ADDR_W);
168         au_sync();
169 }
170 
171 /**
172  * au_write_buf -  write buffer to chip
173  * @mtd:        MTD device structure
174  * @buf:        data buffer
175  * @len:        number of bytes to write
176  *
177  *  write function for 8bit buswith
178  */
179 static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
180 {
181         int i;
182         struct nand_chip *this = mtd->priv;
183 
184         for (i=0; i<len; i++) {
185                 writeb(buf[i], this->IO_ADDR_W);
186                 au_sync();
187         }
188 }
189 
190 /**
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
195  *
196  *  read function for 8bit buswith
197  */
198 static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
199 {
200         int i;
201         struct nand_chip *this = mtd->priv;
202 
203         for (i=0; i<len; i++) {
204                 buf[i] = readb(this->IO_ADDR_R);
205                 au_sync();      
206         }
207 }
208 
209 /**
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
214  *
215  *  verify function for 8bit buswith
216  */
217 static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
218 {
219         int i;
220         struct nand_chip *this = mtd->priv;
221 
222         for (i=0; i<len; i++) {
223                 if (buf[i] != readb(this->IO_ADDR_R))
224                         return -EFAULT;
225                 au_sync();
226         }
227 
228         return 0;
229 }
230 
231 /**
232  * au_write_buf16 -  write buffer to chip
233  * @mtd:        MTD device structure
234  * @buf:        data buffer
235  * @len:        number of bytes to write
236  *
237  *  write function for 16bit buswith
238  */
239 static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
240 {
241         int i;
242         struct nand_chip *this = mtd->priv;
243         u16 *p = (u16 *) buf;
244         len >>= 1;
245         
246         for (i=0; i<len; i++) {
247                 writew(p[i], this->IO_ADDR_W);
248                 au_sync();
249         }
250                 
251 }
252 
253 /**
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
258  *
259  *  read function for 16bit buswith
260  */
261 static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
262 {
263         int i;
264         struct nand_chip *this = mtd->priv;
265         u16 *p = (u16 *) buf;
266         len >>= 1;
267 
268         for (i=0; i<len; i++) {
269                 p[i] = readw(this->IO_ADDR_R);
270                 au_sync();
271         }
272 }
273 
274 /**
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
279  *
280  *  verify function for 16bit buswith
281  */
282 static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
283 {
284         int i;
285         struct nand_chip *this = mtd->priv;
286         u16 *p = (u16 *) buf;
287         len >>= 1;
288 
289         for (i=0; i<len; i++) {
290                 if (p[i] != readw(this->IO_ADDR_R))
291                         return -EFAULT;
292                 au_sync();
293         }
294         return 0;
295 }
296 
297 
298 static void au1550_hwcontrol(struct mtd_info *mtd, int cmd)
299 {
300         register struct nand_chip *this = mtd->priv;
301 
302         switch(cmd){
303 
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;
306 
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;
314 
315         case NAND_CTL_SETNCE: 
316                 /* assert (force assert) chip enable */
317                 au_writel((1<<(4+NAND_CS)) , MEM_STNDCTL); break;
318                 break;
319 
320         case NAND_CTL_CLRNCE: 
321                 /* deassert chip enable */
322                 au_writel(0, MEM_STNDCTL); break;
323                 break;
324         }
325 
326         this->IO_ADDR_R = this->IO_ADDR_W;
327         
328         /* Drain the writebuffer */
329         au_sync();
330 }
331 
332 int au1550_device_ready(struct mtd_info *mtd)
333 {
334         int ret = (au_readl(MEM_STSTAT) & 0x1) ? 1 : 0;
335         au_sync();
336         return ret;
337 }
338 
339 /*
340  * Main initialization routine
341  */
342 int __init au1550_init (void)
343 {
344         struct nand_chip *this;
345         u16 boot_swapboot = 0; /* default value */
346         int retval;
347 
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;
354         }
355 
356         /* Get pointer to private data */
357         this = (struct nand_chip *) (&au1550_mtd[1]);
358 
359         /* Initialize structures */
360         memset((char *) au1550_mtd, 0, sizeof(struct mtd_info));
361         memset((char *) this, 0, sizeof(struct nand_chip));
362 
363         /* Link the private data with the MTD structure */
364         au1550_mtd->priv = this;
365 
366 
367         /* MEM_STNDCTL: disable ints, disable nand boot */
368         au_writel(0, MEM_STNDCTL);
369 
370 #ifdef CONFIG_MIPS_PB1550
371         /* set gpio206 high */
372         au_writel(au_readl(GPIO2_DIR) & ~(1<<6), GPIO2_DIR);
373 
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;
397         }
398 #endif
399 
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();
404 
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();
411 
412         p_nand = ioremap(NAND_PHYS_ADDR, 0x1000);
413 
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;
420 
421         this->options = NAND_NO_AUTOINCR;
422 
423         if (!nand_width)
424                 this->options |= NAND_BUSWIDTH_16;
425 
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;
433 
434         /* Scan to find existence of the device */
435         if (nand_scan (au1550_mtd, 1)) {
436                 retval = -ENXIO;
437                 goto outio;
438         }
439 
440         /* Register the partitions */
441         add_mtd_partitions(au1550_mtd, partition_info, NUM_PARTITIONS);
442 
443         return 0;
444 
445  outio:
446         iounmap ((void *)p_nand);
447         
448  outmem:
449         kfree (au1550_mtd);
450         return retval;
451 }
452 
453 module_init(au1550_init);
454 
455 /*
456  * Clean up routine
457  */
458 #ifdef MODULE
459 static void __exit au1550_cleanup (void)
460 {
461         struct nand_chip *this = (struct nand_chip *) &au1550_mtd[1];
462 
463         /* Release resources, unregister device */
464         nand_release (au1550_mtd);
465 
466         /* Free the MTD device structure */
467         kfree (au1550_mtd);
468 
469         /* Unmap */
470         iounmap ((void *)p_nand);
471 }
472 module_exit(au1550_cleanup);
473 #endif
474 
475 MODULE_LICENSE("GPL");
476 MODULE_AUTHOR("Embedded Edge, LLC");
477 MODULE_DESCRIPTION("Board-specific glue layer for NAND flash on Pb1550 board");
478 
  This page was automatically generated by the LXR engine.