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.1.1.1 2007/08/03 18:52:44 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
56static void *nettel_mmcrp = NULL;
57
58#ifdef CONFIG_MTD_CFI_INTELEXT
59static struct mtd_info *intel_mtd;
60#endif
61static struct mtd_info *amd_mtd;
62
63/****************************************************************************/
64
65/****************************************************************************/
66
67#ifdef CONFIG_MTD_CFI_INTELEXT
68static struct map_info nettel_intel_map = {
69	.name = "SnapGear Intel",
70	.size = 0,
71	.bankwidth = INTEL_BUSWIDTH,
72};
73
74static 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
106static struct map_info nettel_amd_map = {
107	.name = "SnapGear AMD",
108	.size = AMD_WINDOW_MAXSIZE,
109	.bankwidth = AMD_BUSWIDTH,
110};
111
112static 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 */
144static 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
157static 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 */
165static 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
171static struct erase_info nettel_erase;
172
173int 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
213int nettel_eraseconfig(void)
214{
215	return(0);
216}
217
218#endif
219
220/****************************************************************************/
221
222int __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
466out_unmap1:
467	iounmap(nettel_intel_map.virt);
468#endif
469
470out_unmap2:
471	iounmap(nettel_mmcrp);
472	iounmap(nettel_amd_map.virt);
473
474	return(rc);
475
476}
477
478/****************************************************************************/
479
480void __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
511module_init(nettel_init);
512module_exit(nettel_cleanup);
513
514MODULE_LICENSE("GPL");
515MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
516MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support");
517
518/****************************************************************************/
519