xref: /linux/drivers/mtd/maps/nettel.c (revision de2fe5e07d58424bc286fff3fd3c1b0bf933cd58)
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.12 2005/11/29 14:30:00 gleixner 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 ARRAY_SIZE(nettel_amd_partitions)
132 
133 /****************************************************************************/
134 
135 #ifdef CONFIG_MTD_CFI_INTELEXT
136 
137 /*
138  *	Set the Intel flash back to read mode since some old boot
139  *	loaders don't.
140  */
141 static int nettel_reboot_notifier(struct notifier_block *nb, unsigned long val, void *v)
142 {
143 	struct cfi_private *cfi = nettel_intel_map.fldrv_priv;
144 	unsigned long b;
145 
146 	/* Make sure all FLASH chips are put back into read mode */
147 	for (b = 0; (b < nettel_intel_partitions[3].size); b += 0x100000) {
148 		cfi_send_gen_cmd(0xff, 0x55, b, &nettel_intel_map, cfi,
149 			cfi->device_type, NULL);
150 	}
151 	return(NOTIFY_OK);
152 }
153 
154 static struct notifier_block nettel_notifier_block = {
155 	nettel_reboot_notifier, NULL, 0
156 };
157 
158 /*
159  *	Erase the configuration file system.
160  *	Used to support the software reset button.
161  */
162 static void nettel_erasecallback(struct erase_info *done)
163 {
164 	wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
165 	wake_up(wait_q);
166 }
167 
168 static struct erase_info nettel_erase;
169 
170 int nettel_eraseconfig(void)
171 {
172 	struct mtd_info *mtd;
173 	DECLARE_WAITQUEUE(wait, current);
174 	wait_queue_head_t wait_q;
175 	int ret;
176 
177 	init_waitqueue_head(&wait_q);
178 	mtd = get_mtd_device(NULL, 2);
179 	if (mtd) {
180 		nettel_erase.mtd = mtd;
181 		nettel_erase.callback = nettel_erasecallback;
182 		nettel_erase.callback = NULL;
183 		nettel_erase.addr = 0;
184 		nettel_erase.len = mtd->size;
185 		nettel_erase.priv = (u_long) &wait_q;
186 		nettel_erase.priv = 0;
187 
188 		set_current_state(TASK_INTERRUPTIBLE);
189 		add_wait_queue(&wait_q, &wait);
190 
191 		ret = MTD_ERASE(mtd, &nettel_erase);
192 		if (ret) {
193 			set_current_state(TASK_RUNNING);
194 			remove_wait_queue(&wait_q, &wait);
195 			put_mtd_device(mtd);
196 			return(ret);
197 		}
198 
199 		schedule();  /* Wait for erase to finish. */
200 		remove_wait_queue(&wait_q, &wait);
201 
202 		put_mtd_device(mtd);
203 	}
204 
205 	return(0);
206 }
207 
208 #else
209 
210 int nettel_eraseconfig(void)
211 {
212 	return(0);
213 }
214 
215 #endif
216 
217 /****************************************************************************/
218 
219 int __init nettel_init(void)
220 {
221 	volatile unsigned long *amdpar;
222 	unsigned long amdaddr, maxsize;
223 	int num_amd_partitions=0;
224 #ifdef CONFIG_MTD_CFI_INTELEXT
225 	volatile unsigned long *intel0par, *intel1par;
226 	unsigned long orig_bootcspar, orig_romcs1par;
227 	unsigned long intel0addr, intel0size;
228 	unsigned long intel1addr, intel1size;
229 	int intelboot, intel0cs, intel1cs;
230 	int num_intel_partitions;
231 #endif
232 	int rc = 0;
233 
234 	nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096);
235 	if (nettel_mmcrp == NULL) {
236 		printk("SNAPGEAR: failed to disable MMCR cache??\n");
237 		return(-EIO);
238 	}
239 
240 	/* Set CPU clock to be 33.000MHz */
241 	*((unsigned char *) (nettel_mmcrp + 0xc64)) = 0x01;
242 
243 	amdpar = (volatile unsigned long *) (nettel_mmcrp + 0xc4);
244 
245 #ifdef CONFIG_MTD_CFI_INTELEXT
246 	intelboot = 0;
247 	intel0cs = SC520_PAR_ROMCS1;
248 	intel0par = (volatile unsigned long *) (nettel_mmcrp + 0xc0);
249 	intel1cs = SC520_PAR_ROMCS2;
250 	intel1par = (volatile unsigned long *) (nettel_mmcrp + 0xbc);
251 
252 	/*
253 	 *	Save the CS settings then ensure ROMCS1 and ROMCS2 are off,
254 	 *	otherwise they might clash with where we try to map BOOTCS.
255 	 */
256 	orig_bootcspar = *amdpar;
257 	orig_romcs1par = *intel0par;
258 	*intel0par = 0;
259 	*intel1par = 0;
260 #endif
261 
262 	/*
263 	 *	The first thing to do is determine if we have a separate
264 	 *	boot FLASH device. Typically this is a small (1 to 2MB)
265 	 *	AMD FLASH part. It seems that device size is about the
266 	 *	only way to tell if this is the case...
267 	 */
268 	amdaddr = 0x20000000;
269 	maxsize = AMD_WINDOW_MAXSIZE;
270 
271 	*amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize);
272 	__asm__ ("wbinvd");
273 
274 	nettel_amd_map.phys = amdaddr;
275 	nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize);
276 	if (!nettel_amd_map.virt) {
277 		printk("SNAPGEAR: failed to ioremap() BOOTCS\n");
278 		return(-EIO);
279 	}
280 	simple_map_init(&nettel_amd_map);
281 
282 	if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) {
283 		printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n",
284 			amd_mtd->size>>10);
285 
286 		amd_mtd->owner = THIS_MODULE;
287 
288 		/* The high BIOS partition is only present for 2MB units */
289 		num_amd_partitions = NUM_AMD_PARTITIONS;
290 		if (amd_mtd->size < AMD_WINDOW_MAXSIZE)
291 			num_amd_partitions--;
292 		/* Don't add the partition until after the primary INTEL's */
293 
294 #ifdef CONFIG_MTD_CFI_INTELEXT
295 		/*
296 		 *	Map the Intel flash into memory after the AMD
297 		 *	It has to start on a multiple of maxsize.
298 		 */
299 		maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
300 		if (maxsize < (32 * 1024 * 1024))
301 			maxsize = (32 * 1024 * 1024);
302 		intel0addr = amdaddr + maxsize;
303 #endif
304 	} else {
305 #ifdef CONFIG_MTD_CFI_INTELEXT
306 		/* INTEL boot FLASH */
307 		intelboot++;
308 
309 		if (!orig_romcs1par) {
310 			intel0cs = SC520_PAR_BOOTCS;
311 			intel0par = (volatile unsigned long *)
312 				(nettel_mmcrp + 0xc4);
313 			intel1cs = SC520_PAR_ROMCS1;
314 			intel1par = (volatile unsigned long *)
315 				(nettel_mmcrp + 0xc0);
316 
317 			intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar);
318 			maxsize = SC520_PAR_TO_SIZE(orig_bootcspar);
319 		} else {
320 			/* Kernel base is on ROMCS1, not BOOTCS */
321 			intel0cs = SC520_PAR_ROMCS1;
322 			intel0par = (volatile unsigned long *)
323 				(nettel_mmcrp + 0xc0);
324 			intel1cs = SC520_PAR_BOOTCS;
325 			intel1par = (volatile unsigned long *)
326 				(nettel_mmcrp + 0xc4);
327 
328 			intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par);
329 			maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
330 		}
331 
332 		/* Destroy useless AMD MTD mapping */
333 		amd_mtd = NULL;
334 		iounmap(nettel_amd_map.virt);
335 		nettel_amd_map.virt = NULL;
336 #else
337 		/* Only AMD flash supported */
338 		return(-ENXIO);
339 #endif
340 	}
341 
342 #ifdef CONFIG_MTD_CFI_INTELEXT
343 	/*
344 	 *	We have determined the INTEL FLASH configuration, so lets
345 	 *	go ahead and probe for them now.
346 	 */
347 
348 	/* Set PAR to the maximum size */
349 	if (maxsize < (32 * 1024 * 1024))
350 		maxsize = (32 * 1024 * 1024);
351 	*intel0par = SC520_PAR(intel0cs, intel0addr, maxsize);
352 
353 	/* Turn other PAR off so the first probe doesn't find it */
354 	*intel1par = 0;
355 
356 	/* Probe for the the size of the first Intel flash */
357 	nettel_intel_map.size = maxsize;
358 	nettel_intel_map.phys = intel0addr;
359 	nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
360 	if (!nettel_intel_map.virt) {
361 		printk("SNAPGEAR: failed to ioremap() ROMCS1\n");
362 		return(-EIO);
363 	}
364 	simple_map_init(&nettel_intel_map);
365 
366 	intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
367 	if (!intel_mtd) {
368 		iounmap(nettel_intel_map.virt);
369 		return(-ENXIO);
370 	}
371 
372 	/* Set PAR to the detected size */
373 	intel0size = intel_mtd->size;
374 	*intel0par = SC520_PAR(intel0cs, intel0addr, intel0size);
375 
376 	/*
377 	 *	Map second Intel FLASH right after first. Set its size to the
378 	 *	same maxsize used for the first Intel FLASH.
379 	 */
380 	intel1addr = intel0addr + intel0size;
381 	*intel1par = SC520_PAR(intel1cs, intel1addr, maxsize);
382 	__asm__ ("wbinvd");
383 
384 	maxsize += intel0size;
385 
386 	/* Delete the old map and probe again to do both chips */
387 	map_destroy(intel_mtd);
388 	intel_mtd = NULL;
389 	iounmap(nettel_intel_map.virt);
390 
391 	nettel_intel_map.size = maxsize;
392 	nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
393 	if (!nettel_intel_map.virt) {
394 		printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n");
395 		return(-EIO);
396 	}
397 
398 	intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
399 	if (! intel_mtd) {
400 		iounmap((void *) nettel_intel_map.virt);
401 		return(-ENXIO);
402 	}
403 
404 	intel1size = intel_mtd->size - intel0size;
405 	if (intel1size > 0) {
406 		*intel1par = SC520_PAR(intel1cs, intel1addr, intel1size);
407 		__asm__ ("wbinvd");
408 	} else {
409 		*intel1par = 0;
410 	}
411 
412 	printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n",
413 		(intel_mtd->size >> 10));
414 
415 	intel_mtd->owner = THIS_MODULE;
416 
417 #ifndef CONFIG_BLK_DEV_INITRD
418 	ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
419 #endif
420 
421 	num_intel_partitions = sizeof(nettel_intel_partitions) /
422 		sizeof(nettel_intel_partitions[0]);
423 
424 	if (intelboot) {
425 		/*
426 		 *	Adjust offset and size of last boot partition.
427 		 *	Must allow for BIOS region at end of FLASH.
428 		 */
429 		nettel_intel_partitions[1].size = (intel0size + intel1size) -
430 			(1024*1024 + intel_mtd->erasesize);
431 		nettel_intel_partitions[3].size = intel0size + intel1size;
432 		nettel_intel_partitions[4].offset =
433 			(intel0size + intel1size) - intel_mtd->erasesize;
434 		nettel_intel_partitions[4].size = intel_mtd->erasesize;
435 		nettel_intel_partitions[5].offset =
436 			nettel_intel_partitions[4].offset;
437 		nettel_intel_partitions[5].size =
438 			nettel_intel_partitions[4].size;
439 	} else {
440 		/* No BIOS regions when AMD boot */
441 		num_intel_partitions -= 2;
442 	}
443 	rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions,
444 		num_intel_partitions);
445 #endif
446 
447 	if (amd_mtd) {
448 		rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions,
449 			num_amd_partitions);
450 	}
451 
452 #ifdef CONFIG_MTD_CFI_INTELEXT
453 	register_reboot_notifier(&nettel_notifier_block);
454 #endif
455 
456 	return(rc);
457 }
458 
459 /****************************************************************************/
460 
461 void __exit nettel_cleanup(void)
462 {
463 #ifdef CONFIG_MTD_CFI_INTELEXT
464 	unregister_reboot_notifier(&nettel_notifier_block);
465 #endif
466 	if (amd_mtd) {
467 		del_mtd_partitions(amd_mtd);
468 		map_destroy(amd_mtd);
469 	}
470 	if (nettel_amd_map.virt) {
471 		iounmap(nettel_amd_map.virt);
472 		nettel_amd_map.virt = NULL;
473 	}
474 #ifdef CONFIG_MTD_CFI_INTELEXT
475 	if (intel_mtd) {
476 		del_mtd_partitions(intel_mtd);
477 		map_destroy(intel_mtd);
478 	}
479 	if (nettel_intel_map.virt) {
480 		iounmap(nettel_intel_map.virt);
481 		nettel_intel_map.virt = NULL;
482 	}
483 #endif
484 }
485 
486 /****************************************************************************/
487 
488 module_init(nettel_init);
489 module_exit(nettel_cleanup);
490 
491 MODULE_LICENSE("GPL");
492 MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
493 MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support");
494 
495 /****************************************************************************/
496