]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Flash memory access on Alchemy Pb1550 board | |
3 | * | |
4 | * $Id: pb1550-flash.c,v 1.6 2004/11/04 13:24:15 gleixner 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 = ioremap(window_addr, window_size); | |
182 | mymtd = do_map_probe("cfi_probe", &pb1550_map); | |
183 | if (!mymtd) return -ENXIO; | |
184 | mymtd->owner = THIS_MODULE; | |
185 | ||
186 | add_mtd_partitions(mymtd, parts, nb_parts); | |
187 | return 0; | |
188 | } | |
189 | ||
190 | static void __exit pb1550_mtd_cleanup(void) | |
191 | { | |
192 | if (mymtd) { | |
193 | del_mtd_partitions(mymtd); | |
194 | map_destroy(mymtd); | |
195 | } | |
196 | } | |
197 | ||
198 | module_init(pb1550_mtd_init); | |
199 | module_exit(pb1550_mtd_cleanup); | |
200 | ||
201 | MODULE_AUTHOR("Embedded Edge, LLC"); | |
202 | MODULE_DESCRIPTION("Pb1550 mtd map driver"); | |
203 | MODULE_LICENSE("GPL"); |