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