This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / mtd / maps / pb1550-flash.c
1 /*
2  * Flash memory access on Alchemy Pb1550 board
3  * 
4  * $Id: pb1550-flash.c,v 1.4 2004/07/14 17:45:40 dwmw2 Exp $
5  *
6  * (C) 2004 Embedded Edge, LLC, based on pb1550-flash.c:
7  * (C) 2003 Pete Popov <ppopov@pacbell.net>
8  * 
9  */
10
11 #include <linux/config.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16
17 #include <linux/mtd/mtd.h>
18 #include <linux/mtd/map.h>
19 #include <linux/mtd/partitions.h>
20
21 #include <asm/io.h>
22 #include <asm/au1000.h>
23 #include <asm/pb1550.h>
24
25 #ifdef  DEBUG_RW
26 #define DBG(x...)       printk(x)
27 #else
28 #define DBG(x...)       
29 #endif
30
31 static unsigned long window_addr;
32 static unsigned long window_size;
33
34
35 static struct map_info pb1550_map = {
36         .name = "Pb1550 flash",
37 };
38
39 static unsigned char flash_bankwidth = 4;
40
41 /* 
42  * Support only 64MB NOR Flash parts
43  */
44
45 #ifdef PB1550_BOTH_BANKS
46 /* both banks will be used. Combine the first bank and the first 
47  * part of the second bank together into a single jffs/jffs2
48  * partition.
49  */
50 static struct mtd_partition pb1550_partitions[] = {
51         /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
52          * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
53          * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
54          */
55         {
56                 .name = "User FS",
57                 .size =   (0x1FC00000 - 0x18000000),
58                 .offset = 0x0000000
59         },{
60                 .name = "yamon",
61                 .size = 0x0100000,
62                 .offset = MTDPART_OFS_APPEND,
63                 .mask_flags = MTD_WRITEABLE
64         },{
65                 .name = "raw kernel",
66                 .size = (0x300000 - 0x40000), /* last 256KB is yamon env */
67                 .offset = MTDPART_OFS_APPEND,
68         }
69 };
70 #elif defined(PB1550_BOOT_ONLY)
71 static struct mtd_partition pb1550_partitions[] = {
72         /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
73          * 1C00 0000 1FFF FFFF CE0 64MB Boot NOR Flash
74          */
75         {
76                 .name = "User FS",
77                 .size =   0x03c00000,
78                 .offset = 0x0000000
79         },{
80                 .name = "yamon",
81                 .size = 0x0100000,
82                 .offset = MTDPART_OFS_APPEND,
83                 .mask_flags = MTD_WRITEABLE
84         },{
85                 .name = "raw kernel",
86                 .size = (0x300000-0x40000), /* last 256KB is yamon env */
87                 .offset = MTDPART_OFS_APPEND,
88         }
89 };
90 #elif defined(PB1550_USER_ONLY)
91 static struct mtd_partition pb1550_partitions[] = {
92         /* assume boot[2:0]:swap is '0000' or '1000', which translates to:
93          * 1800 0000 1BFF FFFF CE0 64MB Param NOR Flash
94          */
95         {
96                 .name = "User FS",
97                 .size = (0x4000000 - 0x200000), /* reserve 2MB for raw kernel */
98                 .offset = 0x0000000
99         },{
100                 .name = "raw kernel",
101                 .size = MTDPART_SIZ_FULL,
102                 .offset = MTDPART_OFS_APPEND,
103         }
104 };
105 #else
106 #error MTD_PB1550 define combo error /* should never happen */
107 #endif
108
109 #define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
110
111 static struct mtd_info *mymtd;
112
113 /*
114  * Probe the flash density and setup window address and size
115  * based on user CONFIG options. There are times when we don't
116  * want the MTD driver to be probing the boot or user flash,
117  * so having the option to enable only one bank is important.
118  */
119 int setup_flash_params(void)
120 {
121         u16 boot_swapboot;
122         boot_swapboot = (au_readl(MEM_STSTAT) & (0x7<<1)) | 
123                 ((bcsr->status >> 6)  & 0x1);
124         printk("Pb1550 MTD: boot:swap %d\n", boot_swapboot);
125
126         switch (boot_swapboot) {
127                 case 0: /* 512Mbit devices, both enabled */
128                 case 1: 
129                 case 8:
130                 case 9: 
131 #if defined(PB1550_BOTH_BANKS)
132                         window_addr = 0x18000000;
133                         window_size = 0x8000000; 
134 #elif defined(PB1550_BOOT_ONLY)
135                         window_addr = 0x1C000000;
136                         window_size = 0x4000000; 
137 #else /* USER ONLY */
138                         window_addr = 0x1E000000;
139                         window_size = 0x4000000; 
140 #endif
141                         break;
142                 case 0xC:
143                 case 0xD:
144                 case 0xE:
145                 case 0xF: 
146                         /* 64 MB Boot NOR Flash is disabled */
147                         /* and the start address is moved to 0x0C00000 */
148                         window_addr = 0x0C000000;
149                         window_size = 0x4000000; 
150                 default:
151                         printk("Pb1550 MTD: unsupported boot:swap setting\n");
152                         return 1;
153         }
154         return 0;
155 }
156
157 int __init pb1550_mtd_init(void)
158 {
159         struct mtd_partition *parts;
160         int nb_parts = 0;
161         
162         /* Default flash bankwidth */
163         pb1550_map.bankwidth = flash_bankwidth;
164
165         if (setup_flash_params()) 
166                 return -ENXIO;
167
168         /*
169          * Static partition definition selection
170          */
171         parts = pb1550_partitions;
172         nb_parts = NB_OF(pb1550_partitions);
173         pb1550_map.size = window_size;
174
175         /*
176          * Now let's probe for the actual flash.  Do it here since
177          * specific machine settings might have been set above.
178          */
179         printk(KERN_NOTICE "Pb1550 flash: probing %d-bit flash bus\n", 
180                         pb1550_map.bankwidth*8);
181         pb1550_map.virt = 
182                 (unsigned long)ioremap(window_addr, window_size);
183         mymtd = do_map_probe("cfi_probe", &pb1550_map);
184         if (!mymtd) return -ENXIO;
185         mymtd->owner = THIS_MODULE;
186
187         add_mtd_partitions(mymtd, parts, nb_parts);
188         return 0;
189 }
190
191 static void __exit pb1550_mtd_cleanup(void)
192 {
193         if (mymtd) {
194                 del_mtd_partitions(mymtd);
195                 map_destroy(mymtd);
196         }
197 }
198
199 module_init(pb1550_mtd_init);
200 module_exit(pb1550_mtd_cleanup);
201
202 MODULE_AUTHOR("Embedded Edge, LLC");
203 MODULE_DESCRIPTION("Pb1550 mtd map driver");
204 MODULE_LICENSE("GPL");