diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/mtd/maps/nettel.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/mtd/maps/nettel.c')
-rw-r--r-- | drivers/mtd/maps/nettel.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/drivers/mtd/maps/nettel.c b/drivers/mtd/maps/nettel.c new file mode 100644 index 000000000000..61be5a4148c9 --- /dev/null +++ b/drivers/mtd/maps/nettel.c | |||
@@ -0,0 +1,496 @@ | |||
1 | /****************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * nettel.c -- mappings for NETtel/SecureEdge/SnapGear (x86) boards. | ||
5 | * | ||
6 | * (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com) | ||
7 | * (C) Copyright 2001-2002, SnapGear (www.snapgear.com) | ||
8 | * | ||
9 | * $Id: nettel.c,v 1.10 2005/01/05 17:11:29 dwmw2 Exp $ | ||
10 | */ | ||
11 | |||
12 | /****************************************************************************/ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/mtd/mtd.h> | ||
19 | #include <linux/mtd/map.h> | ||
20 | #include <linux/mtd/partitions.h> | ||
21 | #include <linux/mtd/cfi.h> | ||
22 | #include <linux/reboot.h> | ||
23 | #include <asm/io.h> | ||
24 | |||
25 | /****************************************************************************/ | ||
26 | |||
27 | #define INTEL_BUSWIDTH 1 | ||
28 | #define AMD_WINDOW_MAXSIZE 0x00200000 | ||
29 | #define AMD_BUSWIDTH 1 | ||
30 | |||
31 | /* | ||
32 | * PAR masks and shifts, assuming 64K pages. | ||
33 | */ | ||
34 | #define SC520_PAR_ADDR_MASK 0x00003fff | ||
35 | #define SC520_PAR_ADDR_SHIFT 16 | ||
36 | #define SC520_PAR_TO_ADDR(par) \ | ||
37 | (((par)&SC520_PAR_ADDR_MASK) << SC520_PAR_ADDR_SHIFT) | ||
38 | |||
39 | #define SC520_PAR_SIZE_MASK 0x01ffc000 | ||
40 | #define SC520_PAR_SIZE_SHIFT 2 | ||
41 | #define SC520_PAR_TO_SIZE(par) \ | ||
42 | ((((par)&SC520_PAR_SIZE_MASK) << SC520_PAR_SIZE_SHIFT) + (64*1024)) | ||
43 | |||
44 | #define SC520_PAR(cs, addr, size) \ | ||
45 | ((cs) | \ | ||
46 | ((((size)-(64*1024)) >> SC520_PAR_SIZE_SHIFT) & SC520_PAR_SIZE_MASK) | \ | ||
47 | (((addr) >> SC520_PAR_ADDR_SHIFT) & SC520_PAR_ADDR_MASK)) | ||
48 | |||
49 | #define SC520_PAR_BOOTCS 0x8a000000 | ||
50 | #define SC520_PAR_ROMCS1 0xaa000000 | ||
51 | #define SC520_PAR_ROMCS2 0xca000000 /* Cache disabled, 64K page */ | ||
52 | |||
53 | static void *nettel_mmcrp = NULL; | ||
54 | |||
55 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
56 | static struct mtd_info *intel_mtd; | ||
57 | #endif | ||
58 | static struct mtd_info *amd_mtd; | ||
59 | |||
60 | /****************************************************************************/ | ||
61 | |||
62 | /****************************************************************************/ | ||
63 | |||
64 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
65 | static struct map_info nettel_intel_map = { | ||
66 | .name = "SnapGear Intel", | ||
67 | .size = 0, | ||
68 | .bankwidth = INTEL_BUSWIDTH, | ||
69 | }; | ||
70 | |||
71 | static struct mtd_partition nettel_intel_partitions[] = { | ||
72 | { | ||
73 | .name = "SnapGear kernel", | ||
74 | .offset = 0, | ||
75 | .size = 0x000e0000 | ||
76 | }, | ||
77 | { | ||
78 | .name = "SnapGear filesystem", | ||
79 | .offset = 0x00100000, | ||
80 | }, | ||
81 | { | ||
82 | .name = "SnapGear config", | ||
83 | .offset = 0x000e0000, | ||
84 | .size = 0x00020000 | ||
85 | }, | ||
86 | { | ||
87 | .name = "SnapGear Intel", | ||
88 | .offset = 0 | ||
89 | }, | ||
90 | { | ||
91 | .name = "SnapGear BIOS Config", | ||
92 | .offset = 0x007e0000, | ||
93 | .size = 0x00020000 | ||
94 | }, | ||
95 | { | ||
96 | .name = "SnapGear BIOS", | ||
97 | .offset = 0x007e0000, | ||
98 | .size = 0x00020000 | ||
99 | }, | ||
100 | }; | ||
101 | #endif | ||
102 | |||
103 | static struct map_info nettel_amd_map = { | ||
104 | .name = "SnapGear AMD", | ||
105 | .size = AMD_WINDOW_MAXSIZE, | ||
106 | .bankwidth = AMD_BUSWIDTH, | ||
107 | }; | ||
108 | |||
109 | static struct mtd_partition nettel_amd_partitions[] = { | ||
110 | { | ||
111 | .name = "SnapGear BIOS config", | ||
112 | .offset = 0x000e0000, | ||
113 | .size = 0x00010000 | ||
114 | }, | ||
115 | { | ||
116 | .name = "SnapGear BIOS", | ||
117 | .offset = 0x000f0000, | ||
118 | .size = 0x00010000 | ||
119 | }, | ||
120 | { | ||
121 | .name = "SnapGear AMD", | ||
122 | .offset = 0 | ||
123 | }, | ||
124 | { | ||
125 | .name = "SnapGear high BIOS", | ||
126 | .offset = 0x001f0000, | ||
127 | .size = 0x00010000 | ||
128 | } | ||
129 | }; | ||
130 | |||
131 | #define NUM_AMD_PARTITIONS \ | ||
132 | (sizeof(nettel_amd_partitions)/sizeof(nettel_amd_partitions[0])) | ||
133 | |||
134 | /****************************************************************************/ | ||
135 | |||
136 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
137 | |||
138 | /* | ||
139 | * Set the Intel flash back to read mode since some old boot | ||
140 | * loaders don't. | ||
141 | */ | ||
142 | static int nettel_reboot_notifier(struct notifier_block *nb, unsigned long val, void *v) | ||
143 | { | ||
144 | struct cfi_private *cfi = nettel_intel_map.fldrv_priv; | ||
145 | unsigned long b; | ||
146 | |||
147 | /* Make sure all FLASH chips are put back into read mode */ | ||
148 | for (b = 0; (b < nettel_intel_partitions[3].size); b += 0x100000) { | ||
149 | cfi_send_gen_cmd(0xff, 0x55, b, &nettel_intel_map, cfi, | ||
150 | cfi->device_type, NULL); | ||
151 | } | ||
152 | return(NOTIFY_OK); | ||
153 | } | ||
154 | |||
155 | static struct notifier_block nettel_notifier_block = { | ||
156 | nettel_reboot_notifier, NULL, 0 | ||
157 | }; | ||
158 | |||
159 | /* | ||
160 | * Erase the configuration file system. | ||
161 | * Used to support the software reset button. | ||
162 | */ | ||
163 | static void nettel_erasecallback(struct erase_info *done) | ||
164 | { | ||
165 | wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; | ||
166 | wake_up(wait_q); | ||
167 | } | ||
168 | |||
169 | static struct erase_info nettel_erase; | ||
170 | |||
171 | int nettel_eraseconfig(void) | ||
172 | { | ||
173 | struct mtd_info *mtd; | ||
174 | DECLARE_WAITQUEUE(wait, current); | ||
175 | wait_queue_head_t wait_q; | ||
176 | int ret; | ||
177 | |||
178 | init_waitqueue_head(&wait_q); | ||
179 | mtd = get_mtd_device(NULL, 2); | ||
180 | if (mtd) { | ||
181 | nettel_erase.mtd = mtd; | ||
182 | nettel_erase.callback = nettel_erasecallback; | ||
183 | nettel_erase.callback = NULL; | ||
184 | nettel_erase.addr = 0; | ||
185 | nettel_erase.len = mtd->size; | ||
186 | nettel_erase.priv = (u_long) &wait_q; | ||
187 | nettel_erase.priv = 0; | ||
188 | |||
189 | set_current_state(TASK_INTERRUPTIBLE); | ||
190 | add_wait_queue(&wait_q, &wait); | ||
191 | |||
192 | ret = MTD_ERASE(mtd, &nettel_erase); | ||
193 | if (ret) { | ||
194 | set_current_state(TASK_RUNNING); | ||
195 | remove_wait_queue(&wait_q, &wait); | ||
196 | put_mtd_device(mtd); | ||
197 | return(ret); | ||
198 | } | ||
199 | |||
200 | schedule(); /* Wait for erase to finish. */ | ||
201 | remove_wait_queue(&wait_q, &wait); | ||
202 | |||
203 | put_mtd_device(mtd); | ||
204 | } | ||
205 | |||
206 | return(0); | ||
207 | } | ||
208 | |||
209 | #else | ||
210 | |||
211 | int nettel_eraseconfig(void) | ||
212 | { | ||
213 | return(0); | ||
214 | } | ||
215 | |||
216 | #endif | ||
217 | |||
218 | /****************************************************************************/ | ||
219 | |||
220 | int __init nettel_init(void) | ||
221 | { | ||
222 | volatile unsigned long *amdpar; | ||
223 | unsigned long amdaddr, maxsize; | ||
224 | int num_amd_partitions=0; | ||
225 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
226 | volatile unsigned long *intel0par, *intel1par; | ||
227 | unsigned long orig_bootcspar, orig_romcs1par; | ||
228 | unsigned long intel0addr, intel0size; | ||
229 | unsigned long intel1addr, intel1size; | ||
230 | int intelboot, intel0cs, intel1cs; | ||
231 | int num_intel_partitions; | ||
232 | #endif | ||
233 | int rc = 0; | ||
234 | |||
235 | nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096); | ||
236 | if (nettel_mmcrp == NULL) { | ||
237 | printk("SNAPGEAR: failed to disable MMCR cache??\n"); | ||
238 | return(-EIO); | ||
239 | } | ||
240 | |||
241 | /* Set CPU clock to be 33.000MHz */ | ||
242 | *((unsigned char *) (nettel_mmcrp + 0xc64)) = 0x01; | ||
243 | |||
244 | amdpar = (volatile unsigned long *) (nettel_mmcrp + 0xc4); | ||
245 | |||
246 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
247 | intelboot = 0; | ||
248 | intel0cs = SC520_PAR_ROMCS1; | ||
249 | intel0par = (volatile unsigned long *) (nettel_mmcrp + 0xc0); | ||
250 | intel1cs = SC520_PAR_ROMCS2; | ||
251 | intel1par = (volatile unsigned long *) (nettel_mmcrp + 0xbc); | ||
252 | |||
253 | /* | ||
254 | * Save the CS settings then ensure ROMCS1 and ROMCS2 are off, | ||
255 | * otherwise they might clash with where we try to map BOOTCS. | ||
256 | */ | ||
257 | orig_bootcspar = *amdpar; | ||
258 | orig_romcs1par = *intel0par; | ||
259 | *intel0par = 0; | ||
260 | *intel1par = 0; | ||
261 | #endif | ||
262 | |||
263 | /* | ||
264 | * The first thing to do is determine if we have a separate | ||
265 | * boot FLASH device. Typically this is a small (1 to 2MB) | ||
266 | * AMD FLASH part. It seems that device size is about the | ||
267 | * only way to tell if this is the case... | ||
268 | */ | ||
269 | amdaddr = 0x20000000; | ||
270 | maxsize = AMD_WINDOW_MAXSIZE; | ||
271 | |||
272 | *amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize); | ||
273 | __asm__ ("wbinvd"); | ||
274 | |||
275 | nettel_amd_map.phys = amdaddr; | ||
276 | nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize); | ||
277 | if (!nettel_amd_map.virt) { | ||
278 | printk("SNAPGEAR: failed to ioremap() BOOTCS\n"); | ||
279 | return(-EIO); | ||
280 | } | ||
281 | simple_map_init(&nettel_amd_map); | ||
282 | |||
283 | if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) { | ||
284 | printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n", | ||
285 | amd_mtd->size>>10); | ||
286 | |||
287 | amd_mtd->owner = THIS_MODULE; | ||
288 | |||
289 | /* The high BIOS partition is only present for 2MB units */ | ||
290 | num_amd_partitions = NUM_AMD_PARTITIONS; | ||
291 | if (amd_mtd->size < AMD_WINDOW_MAXSIZE) | ||
292 | num_amd_partitions--; | ||
293 | /* Don't add the partition until after the primary INTEL's */ | ||
294 | |||
295 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
296 | /* | ||
297 | * Map the Intel flash into memory after the AMD | ||
298 | * It has to start on a multiple of maxsize. | ||
299 | */ | ||
300 | maxsize = SC520_PAR_TO_SIZE(orig_romcs1par); | ||
301 | if (maxsize < (32 * 1024 * 1024)) | ||
302 | maxsize = (32 * 1024 * 1024); | ||
303 | intel0addr = amdaddr + maxsize; | ||
304 | #endif | ||
305 | } else { | ||
306 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
307 | /* INTEL boot FLASH */ | ||
308 | intelboot++; | ||
309 | |||
310 | if (!orig_romcs1par) { | ||
311 | intel0cs = SC520_PAR_BOOTCS; | ||
312 | intel0par = (volatile unsigned long *) | ||
313 | (nettel_mmcrp + 0xc4); | ||
314 | intel1cs = SC520_PAR_ROMCS1; | ||
315 | intel1par = (volatile unsigned long *) | ||
316 | (nettel_mmcrp + 0xc0); | ||
317 | |||
318 | intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar); | ||
319 | maxsize = SC520_PAR_TO_SIZE(orig_bootcspar); | ||
320 | } else { | ||
321 | /* Kernel base is on ROMCS1, not BOOTCS */ | ||
322 | intel0cs = SC520_PAR_ROMCS1; | ||
323 | intel0par = (volatile unsigned long *) | ||
324 | (nettel_mmcrp + 0xc0); | ||
325 | intel1cs = SC520_PAR_BOOTCS; | ||
326 | intel1par = (volatile unsigned long *) | ||
327 | (nettel_mmcrp + 0xc4); | ||
328 | |||
329 | intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par); | ||
330 | maxsize = SC520_PAR_TO_SIZE(orig_romcs1par); | ||
331 | } | ||
332 | |||
333 | /* Destroy useless AMD MTD mapping */ | ||
334 | amd_mtd = NULL; | ||
335 | iounmap(nettel_amd_map.virt); | ||
336 | nettel_amd_map.virt = NULL; | ||
337 | #else | ||
338 | /* Only AMD flash supported */ | ||
339 | return(-ENXIO); | ||
340 | #endif | ||
341 | } | ||
342 | |||
343 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
344 | /* | ||
345 | * We have determined the INTEL FLASH configuration, so lets | ||
346 | * go ahead and probe for them now. | ||
347 | */ | ||
348 | |||
349 | /* Set PAR to the maximum size */ | ||
350 | if (maxsize < (32 * 1024 * 1024)) | ||
351 | maxsize = (32 * 1024 * 1024); | ||
352 | *intel0par = SC520_PAR(intel0cs, intel0addr, maxsize); | ||
353 | |||
354 | /* Turn other PAR off so the first probe doesn't find it */ | ||
355 | *intel1par = 0; | ||
356 | |||
357 | /* Probe for the the size of the first Intel flash */ | ||
358 | nettel_intel_map.size = maxsize; | ||
359 | nettel_intel_map.phys = intel0addr; | ||
360 | nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); | ||
361 | if (!nettel_intel_map.virt) { | ||
362 | printk("SNAPGEAR: failed to ioremap() ROMCS1\n"); | ||
363 | return(-EIO); | ||
364 | } | ||
365 | simple_map_init(&nettel_intel_map); | ||
366 | |||
367 | intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); | ||
368 | if (!intel_mtd) { | ||
369 | iounmap(nettel_intel_map.virt); | ||
370 | return(-ENXIO); | ||
371 | } | ||
372 | |||
373 | /* Set PAR to the detected size */ | ||
374 | intel0size = intel_mtd->size; | ||
375 | *intel0par = SC520_PAR(intel0cs, intel0addr, intel0size); | ||
376 | |||
377 | /* | ||
378 | * Map second Intel FLASH right after first. Set its size to the | ||
379 | * same maxsize used for the first Intel FLASH. | ||
380 | */ | ||
381 | intel1addr = intel0addr + intel0size; | ||
382 | *intel1par = SC520_PAR(intel1cs, intel1addr, maxsize); | ||
383 | __asm__ ("wbinvd"); | ||
384 | |||
385 | maxsize += intel0size; | ||
386 | |||
387 | /* Delete the old map and probe again to do both chips */ | ||
388 | map_destroy(intel_mtd); | ||
389 | intel_mtd = NULL; | ||
390 | iounmap(nettel_intel_map.virt); | ||
391 | |||
392 | nettel_intel_map.size = maxsize; | ||
393 | nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize); | ||
394 | if (!nettel_intel_map.virt) { | ||
395 | printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n"); | ||
396 | return(-EIO); | ||
397 | } | ||
398 | |||
399 | intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map); | ||
400 | if (! intel_mtd) { | ||
401 | iounmap((void *) nettel_intel_map.virt); | ||
402 | return(-ENXIO); | ||
403 | } | ||
404 | |||
405 | intel1size = intel_mtd->size - intel0size; | ||
406 | if (intel1size > 0) { | ||
407 | *intel1par = SC520_PAR(intel1cs, intel1addr, intel1size); | ||
408 | __asm__ ("wbinvd"); | ||
409 | } else { | ||
410 | *intel1par = 0; | ||
411 | } | ||
412 | |||
413 | printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n", | ||
414 | (intel_mtd->size >> 10)); | ||
415 | |||
416 | intel_mtd->owner = THIS_MODULE; | ||
417 | |||
418 | #ifndef CONFIG_BLK_DEV_INITRD | ||
419 | ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1); | ||
420 | #endif | ||
421 | |||
422 | num_intel_partitions = sizeof(nettel_intel_partitions) / | ||
423 | sizeof(nettel_intel_partitions[0]); | ||
424 | |||
425 | if (intelboot) { | ||
426 | /* | ||
427 | * Adjust offset and size of last boot partition. | ||
428 | * Must allow for BIOS region at end of FLASH. | ||
429 | */ | ||
430 | nettel_intel_partitions[1].size = (intel0size + intel1size) - | ||
431 | (1024*1024 + intel_mtd->erasesize); | ||
432 | nettel_intel_partitions[3].size = intel0size + intel1size; | ||
433 | nettel_intel_partitions[4].offset = | ||
434 | (intel0size + intel1size) - intel_mtd->erasesize; | ||
435 | nettel_intel_partitions[4].size = intel_mtd->erasesize; | ||
436 | nettel_intel_partitions[5].offset = | ||
437 | nettel_intel_partitions[4].offset; | ||
438 | nettel_intel_partitions[5].size = | ||
439 | nettel_intel_partitions[4].size; | ||
440 | } else { | ||
441 | /* No BIOS regions when AMD boot */ | ||
442 | num_intel_partitions -= 2; | ||
443 | } | ||
444 | rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions, | ||
445 | num_intel_partitions); | ||
446 | #endif | ||
447 | |||
448 | if (amd_mtd) { | ||
449 | rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions, | ||
450 | num_amd_partitions); | ||
451 | } | ||
452 | |||
453 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
454 | register_reboot_notifier(&nettel_notifier_block); | ||
455 | #endif | ||
456 | |||
457 | return(rc); | ||
458 | } | ||
459 | |||
460 | /****************************************************************************/ | ||
461 | |||
462 | void __exit nettel_cleanup(void) | ||
463 | { | ||
464 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
465 | unregister_reboot_notifier(&nettel_notifier_block); | ||
466 | #endif | ||
467 | if (amd_mtd) { | ||
468 | del_mtd_partitions(amd_mtd); | ||
469 | map_destroy(amd_mtd); | ||
470 | } | ||
471 | if (nettel_amd_map.virt) { | ||
472 | iounmap(nettel_amd_map.virt); | ||
473 | nettel_amd_map.virt = NULL; | ||
474 | } | ||
475 | #ifdef CONFIG_MTD_CFI_INTELEXT | ||
476 | if (intel_mtd) { | ||
477 | del_mtd_partitions(intel_mtd); | ||
478 | map_destroy(intel_mtd); | ||
479 | } | ||
480 | if (nettel_intel_map.virt) { | ||
481 | iounmap(nettel_intel_map.virt); | ||
482 | nettel_intel_map.virt = 0; | ||
483 | } | ||
484 | #endif | ||
485 | } | ||
486 | |||
487 | /****************************************************************************/ | ||
488 | |||
489 | module_init(nettel_init); | ||
490 | module_exit(nettel_cleanup); | ||
491 | |||
492 | MODULE_LICENSE("GPL"); | ||
493 | MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>"); | ||
494 | MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support"); | ||
495 | |||
496 | /****************************************************************************/ | ||