1/*
2 * Flash memory access on SA11x0 based devices
3 *
4 * (C) 2000 Nicolas Pitre <nico@cam.org>
5 *
6 * $Id: sa1100-flash.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang Exp $
7 */
8
9#include <linux/config.h>
10#include <linux/module.h>
11#include <linux/types.h>
12#include <linux/ioport.h>
13#include <linux/kernel.h>
14
15#include <linux/mtd/mtd.h>
16#include <linux/mtd/map.h>
17#include <linux/mtd/partitions.h>
18
19#include <asm/hardware.h>
20#include <asm/io.h>
21
22
23#ifndef CONFIG_ARCH_SA1100
24#error This is for SA1100 architecture only
25#endif
26
27
28#define WINDOW_ADDR 0xe8000000
29
30static __u8 sa1100_read8(struct map_info *map, unsigned long ofs)
31{
32	return readb(map->map_priv_1 + ofs);
33}
34
35static __u16 sa1100_read16(struct map_info *map, unsigned long ofs)
36{
37	return readw(map->map_priv_1 + ofs);
38}
39
40static __u32 sa1100_read32(struct map_info *map, unsigned long ofs)
41{
42	return readl(map->map_priv_1 + ofs);
43}
44
45static void sa1100_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
46{
47	memcpy(to, (void *)(map->map_priv_1 + from), len);
48}
49
50static void sa1100_write8(struct map_info *map, __u8 d, unsigned long adr)
51{
52	writeb(d, map->map_priv_1 + adr);
53}
54
55static void sa1100_write16(struct map_info *map, __u16 d, unsigned long adr)
56{
57	writew(d, map->map_priv_1 + adr);
58}
59
60static void sa1100_write32(struct map_info *map, __u32 d, unsigned long adr)
61{
62	writel(d, map->map_priv_1 + adr);
63}
64
65static void sa1100_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
66{
67	memcpy((void *)(map->map_priv_1 + to), from, len);
68}
69
70static struct map_info sa1100_map = {
71	name:		"SA1100 flash",
72	read8:		sa1100_read8,
73	read16:		sa1100_read16,
74	read32:		sa1100_read32,
75	copy_from:	sa1100_copy_from,
76	write8:		sa1100_write8,
77	write16:	sa1100_write16,
78	write32:	sa1100_write32,
79	copy_to:	sa1100_copy_to,
80
81	map_priv_1:	WINDOW_ADDR,
82	map_priv_2:	-1,
83};
84
85
86/*
87 * Here are partition information for all known SA1100-based devices.
88 * See include/linux/mtd/partitions.h for definition of the mtd_partition
89 * structure.
90 *
91 * The *_max_flash_size is the maximum possible mapped flash size which
92 * is not necessarily the actual flash size.  It must be no more than
93 * the value specified in the "struct map_desc *_io_desc" mapping
94 * definition for the corresponding machine.
95 *
96 * Please keep these in alphabetical order, and formatted as per existing
97 * entries.  Thanks.
98 */
99
100#ifdef CONFIG_SA1100_ADSBITSY
101#define ADSBITSY_FLASH_SIZE		0x02000000
102static struct mtd_partition adsbitsy_partitions[] = {
103	{
104		name:		"bootROM",
105		size:		0x80000,
106		offset:		0,
107		mask_flags:	MTD_WRITEABLE,  /* force read-only */
108	}, {
109		name:		"zImage",
110		size:		0x100000,
111		offset:		MTDPART_OFS_APPEND,
112		mask_flags:	MTD_WRITEABLE,  /* force read-only */
113	}, {
114		name:		"ramdisk.gz",
115		size:		0x300000,
116		offset:		MTDPART_OFS_APPEND,
117		mask_flags:	MTD_WRITEABLE,  /* force read-only */
118	}, {
119		name:		"User FS",
120		size:		MTDPART_SIZ_FULL,
121		offset:		MTDPART_OFS_APPEND,
122	}
123};
124#endif
125
126#ifdef CONFIG_SA1100_ASSABET
127/* Phase 4 Assabet has two 28F160B3 flash parts in bank 0: */
128#define ASSABET4_FLASH_SIZE		0x00400000
129static struct mtd_partition assabet4_partitions[] = {
130	{
131		name:		"bootloader",
132		size:		0x00020000,
133		offset:		0,
134		mask_flags:	MTD_WRITEABLE,
135	}, {
136		name:		"bootloader params",
137		size:		0x00020000,
138		offset:		MTDPART_OFS_APPEND,
139		mask_flags:	MTD_WRITEABLE,
140	}, {
141		name:		"jffs",
142		size:		MTDPART_SIZ_FULL,
143		offset:		MTDPART_OFS_APPEND,
144	}
145};
146
147/* Phase 5 Assabet has two 28F128J3A flash parts in bank 0: */
148#define ASSABET5_FLASH_SIZE		0x02000000
149static struct mtd_partition assabet5_partitions[] = {
150	{
151		name:		"bootloader",
152		size:		0x00040000,
153		offset:		0,
154		mask_flags:	MTD_WRITEABLE,
155	}, {
156		name:		"bootloader params",
157		size:		0x00040000,
158		offset:		MTDPART_OFS_APPEND,
159		mask_flags:	MTD_WRITEABLE,
160	}, {
161		name:		"jffs",
162		size:		MTDPART_SIZ_FULL,
163		offset:		MTDPART_OFS_APPEND,
164	}
165};
166
167#define ASSABET_FLASH_SIZE	ASSABET5_FLASH_SIZE
168#define assabet_partitions	assabet5_partitions
169#endif
170
171#ifdef CONFIG_SA1100_BADGE4
172
173/*
174 * 1 x Intel 28F320C3BA100 Advanced+ Boot Block Flash (32 Mi bit)
175 *   Eight 4 KiW Parameter Bottom Blocks (64 KiB)
176 *   Sixty-three 32 KiW Main Blocks (4032 Ki b)
177 */
178#define BADGE4_FLASH_SIZE		0x00400000
179static struct mtd_partition badge4_partitions[] = {
180	{
181		name:		"BLOB boot loader",
182		offset:		0,
183		size:		0x0000A000
184	}, {
185		name:		"params",
186		offset:		MTDPART_OFS_APPEND,
187		size:		0x00006000
188	}, {
189		name:		"kernel",
190		offset:		MTDPART_OFS_APPEND,
191		size:		0x00100000
192	}, {
193		name:		"root",
194		offset:		MTDPART_OFS_APPEND,
195		size:		MTDPART_SIZ_FULL
196	}
197};
198
199#endif
200
201
202#ifdef CONFIG_SA1100_CERF
203#ifdef CONFIG_SA1100_CERF_FLASH_32MB
204#define CERF_FLASH_SIZE			0x02000000
205static struct mtd_partition cerf_partitions[] = {
206	{
207		name:		"firmware",
208		size:		0x00040000,
209		offset:		0,
210	}, {
211		name:		"params",
212		size:		0x00040000,
213		offset:		0x00040000,
214	}, {
215		name:		"kernel",
216		size:		0x00100000,
217		offset:		0x00080000,
218	}, {
219		name:		"rootdisk",
220		size:		0x01E80000,
221		offset:		0x00180000,
222	}
223};
224#elif defined CONFIG_SA1100_CERF_FLASH_16MB
225#define CERF_FLASH_SIZE			0x01000000
226static struct mtd_partition cerf_partitions[] = {
227	{
228		name:		"firmware",
229		size:		0x00020000,
230		offset:		0,
231	}, {
232		name:		"params",
233		size:		0x00020000,
234		offset:		0x00020000,
235	}, {
236		name:		"kernel",
237		size:		0x00100000,
238		offset:		0x00040000,
239	}, {
240		name:		"rootdisk",
241		size:		0x00EC0000,
242		offset:		0x00140000,
243	}
244};
245#elif defined CONFIG_SA1100_CERF_FLASH_8MB
246#   error "Unwritten type definition"
247#else
248#   error "Undefined memory orientation for CERF in sa1100-flash.c"
249#endif
250#endif
251
252#ifdef CONFIG_SA1100_CONSUS
253#define CONSUS_FLASH_SIZE		0x02000000
254static struct mtd_partition consus_partitions[] = {
255	{
256		name:		"Consus boot firmware",
257		offset:		0,
258		size:		0x00040000,
259		mask_flags:	MTD_WRITABLE, /* force read-only */
260	}, {
261		name:		"Consus kernel",
262		offset:		0x00040000,
263		size:		0x00100000,
264		mask_flags:	0,
265	}, {
266		name:		"Consus disk",
267		offset:		0x00140000,
268		/* The rest (up to 16M) for jffs.  We could put 0 and
269		   make it find the size automatically, but right now
270		   i have 32 megs.  jffs will use all 32 megs if given
271		   the chance, and this leads to horrible problems
272		   when you try to re-flash the image because blob
273		   won't erase the whole partition. */
274		size:		0x01000000 - 0x00140000,
275		mask_flags:	0,
276	}, {
277		/* this disk is a secondary disk, which can be used as
278		   needed, for simplicity, make it the size of the other
279		   consus partition, although realistically it could be
280		   the remainder of the disk (depending on the file
281		   system used) */
282		 name:		"Consus disk2",
283		 offset:	0x01000000,
284		 size:		0x01000000 - 0x00140000,
285		 mask_flags:	0,
286	}
287};
288#endif
289
290#ifdef CONFIG_SA1100_FLEXANET
291/* Flexanet has two 28F128J3A flash parts in bank 0: */
292#define FLEXANET_FLASH_SIZE		0x02000000
293static struct mtd_partition flexanet_partitions[] = {
294	{
295		name:		"bootloader",
296		size:		0x00040000,
297		offset:		0,
298		mask_flags:	MTD_WRITEABLE,
299	}, {
300		name:		"bootloader params",
301		size:		0x00040000,
302		offset:		MTDPART_OFS_APPEND,
303		mask_flags:	MTD_WRITEABLE,
304	}, {
305		name:		"kernel",
306		size:		0x000C0000,
307		offset:		MTDPART_OFS_APPEND,
308		mask_flags:	MTD_WRITEABLE,
309	}, {
310		name:		"altkernel",
311		size:		0x000C0000,
312		offset:		MTDPART_OFS_APPEND,
313		mask_flags:	MTD_WRITEABLE,
314	}, {
315		name:		"root",
316		size:		0x00400000,
317		offset:		MTDPART_OFS_APPEND,
318		mask_flags:	MTD_WRITEABLE,
319	}, {
320		name:		"free1",
321		size:		0x00300000,
322		offset:		MTDPART_OFS_APPEND,
323		mask_flags:	MTD_WRITEABLE,
324	}, {
325		name:		"free2",
326		size:		0x00300000,
327		offset:		MTDPART_OFS_APPEND,
328		mask_flags:	MTD_WRITEABLE,
329	}, {
330		name:		"free3",
331		size:		MTDPART_SIZ_FULL,
332		offset:		MTDPART_OFS_APPEND,
333		mask_flags:	MTD_WRITEABLE,
334	}
335};
336#endif
337
338#ifdef CONFIG_SA1100_FREEBIRD
339#define FREEBIRD_FLASH_SIZE		0x02000000
340static struct mtd_partition freebird_partitions[] = {
341#if CONFIG_SA1100_FREEBIRD_NEW
342	{
343		name:		"firmware",
344		size:		0x00040000,
345		offset:		0,
346		mask_flags:	MTD_WRITEABLE,  /* force read-only */
347	}, {
348		name:		"kernel",
349		size:		0x00080000,
350		offset:		0x00040000,
351	}, {
352		name:		"params",
353		size:		0x00040000,
354		offset:		0x000C0000,
355	}, {
356		name:		"initrd",
357		size:		0x00100000,
358		offset:		0x00100000,
359	}, {
360		name:		"root cramfs",
361		size:		0x00300000,
362		offset:		0x00200000,
363	}, {
364		name:		"usr cramfs",
365		size:		0x00C00000,
366		offset:		0x00500000,
367	}, {
368		name:		"local",
369		size:		MTDPART_SIZ_FULL,
370		offset:		0x01100000,
371	}
372#else
373	{
374		size:		0x00040000,
375		offset:		0,
376	}, {
377		size:		0x000c0000,
378		offset:		MTDPART_OFS_APPEND,
379	}, {
380		size:		0x00400000,
381		offset:		MTDPART_OFS_APPEND,
382	}, {
383		size:		MTDPART_SIZ_FULL,
384		offset:		MTDPART_OFS_APPEND,
385	}
386#endif
387};
388#endif
389
390#ifdef CONFIG_SA1100_FRODO
391/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
392#define FRODO_FLASH_SIZE		0x02000000
393static struct mtd_partition frodo_partitions[] =
394{
395	{
396		name:		"bootloader",
397		size:		0x00040000,
398		offset:		0x00000000,
399		mask_flags:	MTD_WRITEABLE
400	}, {
401		name:		"bootloader params",
402		size:		0x00040000,
403		offset:		MTDPART_OFS_APPEND,
404		mask_flags:	MTD_WRITEABLE
405	}, {
406		name:		"kernel",
407		size:		0x00100000,
408		offset:		MTDPART_OFS_APPEND,
409		mask_flags:	MTD_WRITEABLE
410	}, {
411		name:		"ramdisk",
412		size:		0x00400000,
413		offset:		MTDPART_OFS_APPEND,
414		mask_flags:	MTD_WRITEABLE
415	}, {
416		name:		"file system",
417		size:		MTDPART_SIZ_FULL,
418		offset:		MTDPART_OFS_APPEND
419	}
420};
421#endif
422
423#ifdef CONFIG_SA1100_GRAPHICSCLIENT
424#define GRAPHICSCLIENT_FLASH_SIZE	0x02000000
425static struct mtd_partition graphicsclient_partitions[] = {
426	{
427		name:		"zImage",
428		size:		0x100000,
429		offset:		0,
430		mask_flags:	MTD_WRITEABLE,  /* force read-only */
431	}, {
432		name:		"ramdisk.gz",
433		size:		0x300000,
434		offset:		MTDPART_OFS_APPEND,
435		mask_flags:	MTD_WRITEABLE,  /* force read-only */
436	}, {
437		name:		"User FS",
438		size:		MTDPART_SIZ_FULL,
439		offset:		MTDPART_OFS_APPEND,
440	}
441};
442#endif
443
444#ifdef CONFIG_SA1100_GRAPHICSMASTER
445#define GRAPHICSMASTER_FLASH_SIZE	0x01000000
446static struct mtd_partition graphicsmaster_partitions[] = {
447	{
448		name:		"zImage",
449		size:		0x100000,
450		offset:		0,
451		mask_flags:	MTD_WRITEABLE,  /* force read-only */
452	},
453	{
454		name:		"ramdisk.gz",
455		size:		0x300000,
456		offset:		MTDPART_OFS_APPEND,
457		mask_flags:	MTD_WRITEABLE,  /* force read-only */
458	},
459	{
460		name:		"User FS",
461		size:		MTDPART_SIZ_FULL,
462		offset:		MTDPART_OFS_APPEND,
463	}
464};
465#endif
466
467#ifdef CONFIG_SA1100_H3600
468#define H3600_FLASH_SIZE		0x02000000
469static struct mtd_partition h3600_partitions[] = {
470	{
471		name:		"H3600 boot firmware",
472		size:		0x00040000,
473		offset:		0,
474		mask_flags:	MTD_WRITEABLE,  /* force read-only */
475	}, {
476		name:		"H3600 kernel",
477		size:		0x00080000,
478		offset:		0x00040000,
479	}, {
480		name:		"H3600 params",
481		size:		0x00040000,
482		offset:		0x000C0000,
483	}, {
484#ifdef CONFIG_JFFS2_FS
485		name:		"H3600 root jffs2",
486		size:		MTDPART_SIZ_FULL,
487		offset:		0x00100000,
488#else
489		name:		"H3600 initrd",
490		size:		0x00100000,
491		offset:		0x00100000,
492	}, {
493		name:		"H3600 root cramfs",
494		size:		0x00300000,
495		offset:		0x00200000,
496	}, {
497		name:		"H3600 usr cramfs",
498		size:		0x00800000,
499		offset:		0x00500000,
500	}, {
501		name:		"H3600 usr local",
502		size:		MTDPART_SIZ_FULL,
503		offset:		0x00d00000,
504#endif
505	}
506};
507
508static void h3600_set_vpp(struct map_info *map, int vpp)
509{
510	assign_h3600_egpio(IPAQ_EGPIO_VPP_ON, vpp);
511}
512#endif
513
514#ifdef CONFIG_SA1100_HUW_WEBPANEL
515#define HUW_WEBPANEL_FLASH_SIZE		0x01000000
516static struct mtd_partition huw_webpanel_partitions[] = {
517	{
518		name:		"Loader",
519		size:		0x00040000,
520		offset:		0,
521	}, {
522		name:		"Sector 1",
523		size:		0x00040000,
524		offset:		MTDPART_OFS_APPEND,
525	}, {
526		size:		MTDPART_SIZ_FULL,
527		offset:		MTDPART_OFS_APPEND,
528	}
529};
530#endif
531
532#ifdef CONFIG_SA1100_JORNADA720
533#define JORNADA720_FLASH_SIZE		0x02000000
534static struct mtd_partition jornada720_partitions[] = {
535	{
536		name:		"JORNADA720 boot firmware",
537		size:		0x00040000,
538		offset:		0,
539		mask_flags:	MTD_WRITEABLE,  /* force read-only */
540	}, {
541		name:		"JORNADA720 kernel",
542		size:		0x000c0000,
543		offset:		0x00040000,
544	}, {
545		name:		"JORNADA720 params",
546		size:		0x00040000,
547		offset:		0x00100000,
548	}, {
549		name:		"JORNADA720 initrd",
550		size:		0x00100000,
551		offset:		0x00140000,
552	}, {
553		name:		"JORNADA720 root cramfs",
554		size:		0x00300000,
555		offset:		0x00240000,
556	}, {
557		name:		"JORNADA720 usr cramfs",
558		size:		0x00800000,
559		offset:		0x00540000,
560	}, {
561		name:		"JORNADA720 usr local",
562		size:		0  /* will expand to the end of the flash */
563		offset:		0x00d00000,
564	}
565};
566
567static void jornada720_set_vpp(int vpp)
568{
569	if (vpp)
570		PPSR |= 0x80;
571	else
572		PPSR &= ~0x80;
573	PPDR |= 0x80;
574}
575
576#endif
577
578#ifdef CONFIG_SA1100_PANGOLIN
579#define PANGOLIN_FLASH_SIZE		0x04000000
580static struct mtd_partition pangolin_partitions[] = {
581	{
582		name:		"boot firmware",
583		size:		0x00080000,
584		offset:		0x00000000,
585		mask_flags:	MTD_WRITEABLE,  /* force read-only */
586	}, {
587		name:		"kernel",
588		size:		0x00100000,
589		offset:		0x00080000,
590	}, {
591		name:		"initrd",
592		size:		0x00280000,
593		offset:		0x00180000,
594	}, {
595		name:		"initrd-test",
596		size:		0x03C00000,
597		offset:		0x00400000,
598	}
599};
600#endif
601
602#ifdef CONFIG_SA1100_PT_SYSTEM3
603/* erase size is 0x40000 == 256k partitions have to have this boundary */
604#define SYSTEM3_FLASH_SIZE		0x01000000
605static struct mtd_partition system3_partitions[] = {
606	{
607		name:		"BLOB",
608		size:		0x00040000,
609		offset:		0x00000000,
610		mask_flags:	MTD_WRITEABLE,  /* force read-only */
611	}, {
612		name:		"config",
613		size:		0x00040000,
614		offset:		MTDPART_OFS_APPEND,
615	}, {
616		name:		"kernel",
617		size:		0x00100000,
618		offset:		MTDPART_OFS_APPEND,
619	}, {
620		name:		"root",
621		size:		MTDPART_SIZ_FULL,
622		offset:		MTDPART_OFS_APPEND,
623	}
624};
625#endif
626
627#ifdef CONFIG_SA1100_SHANNON
628#define SHANNON_FLASH_SIZE		0x00400000
629static struct mtd_partition shannon_partitions[] = {
630	{
631		name: "BLOB boot loader",
632		offset: 0,
633		size: 0x20000
634	},
635	{
636		name: "kernel",
637		offset: MTDPART_OFS_APPEND,
638		size: 0xe0000
639	},
640	{
641		name: "initrd",
642		offset: MTDPART_OFS_APPEND,
643		size: MTDPART_SIZ_FULL
644	}
645};
646
647#endif
648
649#ifdef CONFIG_SA1100_SHERMAN
650#define SHERMAN_FLASH_SIZE		0x02000000
651static struct mtd_partition sherman_partitions[] = {
652	{
653		size:		0x50000,
654		offset:		0,
655	}, {
656		size:		0x70000,
657		offset:		MTDPART_OFS_APPEND,
658	}, {
659		size:		0x600000,
660		offset:		MTDPART_OFS_APPEND,
661	}, {
662		size:		0xA0000,
663		offset:		MTDPART_OFS_APPEND,
664	}
665};
666#endif
667
668#ifdef CONFIG_SA1100_SIMPAD
669#define SIMPAD_FLASH_SIZE		0x02000000
670static struct mtd_partition simpad_partitions[] = {
671	{
672		name:		"SIMpad boot firmware",
673		size:		0x00080000,
674		offset:		0,
675		mask_flags:	MTD_WRITEABLE,  /* force read-only */
676	}, {
677		name:		"SIMpad kernel",
678		size:		0x00100000,
679		offset:		0x00080000,
680	}, {
681#ifdef CONFIG_JFFS2_FS
682		name:		"SIMpad root jffs2",
683		size:		MTDPART_SIZ_FULL,
684		offset:		0x00180000,
685#else
686		name:		"SIMpad initrd",
687		size:		0x00300000,
688		offset:		0x00180000,
689	}, {
690		name:		"SIMpad root cramfs",
691		size:		0x00300000,
692		offset:		0x00480000,
693	}, {
694		name:		"SIMpad usr cramfs",
695		size:		0x005c0000,
696		offset:		0x00780000,
697	}, {
698		name:		"SIMpad usr local",
699		size:		MTDPART_SIZ_FULL,
700		offset:		0x00d40000,
701#endif
702	}
703};
704#endif /* CONFIG_SA1100_SIMPAD */
705
706#ifdef CONFIG_SA1100_STORK
707#define STORK_FLASH_SIZE		0x02000000
708static struct mtd_partition stork_partitions[] = {
709	{
710		name:		"STORK boot firmware",
711		size:		0x00040000,
712		offset:		0,
713		mask_flags:	MTD_WRITEABLE,  /* force read-only */
714	}, {
715		name:		"STORK params",
716		size:		0x00040000,
717		offset:		0x00040000,
718	}, {
719		name:		"STORK kernel",
720		size:		0x00100000,
721		offset:		0x00080000,
722	}, {
723#ifdef CONFIG_JFFS2_FS
724		name:		"STORK root jffs2",
725		offset:		0x00180000,
726		size:		MTDPART_SIZ_FULL,
727#else
728		name:		"STORK initrd",
729		size:		0x00100000,
730		offset:		0x00180000,
731	}, {
732		name:		"STORK root cramfs",
733		size:		0x00300000,
734		offset:		0x00280000,
735	}, {
736		name:		"STORK usr cramfs",
737		size:		0x00800000,
738		offset:		0x00580000,
739	}, {
740		name:		"STORK usr local",
741		offset:		0x00d80000,
742		size:		MTDPART_SIZ_FULL,
743#endif
744	}
745};
746#endif
747
748#ifdef CONFIG_SA1100_YOPY
749#define YOPY_FLASH_SIZE			0x08000000
750static struct mtd_partition yopy_partitions[] = {
751	{
752		name:		"boot firmware",
753		size:		0x00040000,
754		offset:		0x00000000,
755		mask_flags:	MTD_WRITEABLE,  /* force read-only */
756	}, {
757		name:		"kernel",
758		size:		0x00080000,
759		offset:		0x00080000,
760	}, {
761		name:		"initrd",
762		size:		0x00300000,
763		offset:		0x00100000,
764	}, {
765		name:		"root",
766		size:		0x01000000,
767		offset:		0x00400000,
768	}
769};
770#endif
771
772extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
773extern int parse_bootldr_partitions(struct mtd_info *master, struct mtd_partition **pparts);
774
775static struct mtd_partition *parsed_parts;
776static struct mtd_info *mymtd;
777
778int __init sa1100_mtd_init(void)
779{
780	struct mtd_partition *parts;
781	int nb_parts = 0, ret;
782	int parsed_nr_parts = 0;
783	const char *part_type;
784	unsigned long base = -1UL;
785
786	/* Default flash buswidth */
787	sa1100_map.buswidth = (MSC0 & MSC_RBW) ? 2 : 4;
788
789	/*
790	 * Static partition definition selection
791	 */
792	part_type = "static";
793
794#ifdef CONFIG_SA1100_ADSBITSY
795	if (machine_is_adsbitsy()) {
796		parts = adsbitsy_partitions;
797		nb_parts = ARRAY_SIZE(adsbitsy_partitions);
798		sa1100_map.size = ADSBITSY_FLASH_SIZE;
799		sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2 : 4;
800	}
801#endif
802#ifdef CONFIG_SA1100_ASSABET
803	if (machine_is_assabet()) {
804		parts = assabet_partitions;
805		nb_parts = ARRAY_SIZE(assabet_partitions);
806		sa1100_map.size = ASSABET_FLASH_SIZE;
807	}
808#endif
809#ifdef CONFIG_SA1100_BADGE4
810	if (machine_is_badge4()) {
811		parts = badge4_partitions;
812		nb_parts = ARRAY_SIZE(badge4_partitions);
813		sa1100_map.size = BADGE4_FLASH_SIZE;
814	}
815#endif
816#ifdef CONFIG_SA1100_CERF
817	if (machine_is_cerf()) {
818		parts = cerf_partitions;
819		nb_parts = ARRAY_SIZE(cerf_partitions);
820		sa1100_map.size = CERF_FLASH_SIZE;
821	}
822#endif
823#ifdef CONFIG_SA1100_CONSUS
824	if (machine_is_consus()) {
825		parts = consus_partitions;
826		nb_parts = ARRAY_SIZE(consus_partitions);
827		sa1100_map.size = CONSUS_FLASH_SIZE;
828	}
829#endif
830#ifdef CONFIG_SA1100_FLEXANET
831	if (machine_is_flexanet()) {
832		parts = flexanet_partitions;
833		nb_parts = ARRAY_SIZE(flexanet_partitions);
834		sa1100_map.size = FLEXANET_FLASH_SIZE;
835	}
836#endif
837#ifdef CONFIG_SA1100_FREEBIRD
838	if (machine_is_freebird()) {
839		parts = freebird_partitions;
840		nb_parts = ARRAY_SIZE(freebird_partitions);
841		sa1100_map.size = FREEBIRD_FLASH_SIZE;
842	}
843#endif
844#ifdef CONFIG_SA1100_FRODO
845	if (machine_is_frodo()) {
846		parts = frodo_partitions;
847		nb_parts = ARRAY_SIZE(frodo_partitions);
848		sa1100_map.size = FRODO_FLASH_SIZE;
849		base = 0x00000000;
850	}
851#ifdef CONFIG_SA1100_GRAPHICSCLIENT
852	if (machine_is_graphicsclient()) {
853		parts = graphicsclient_partitions;
854		nb_parts = ARRAY_SIZE(graphicsclient_partitions);
855		sa1100_map.size = GRAPHICSCLIENT_FLASH_SIZE;
856		sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2:4;
857	}
858#endif
859#ifdef CONFIG_SA1100_GRAPHICSMASTER
860	if (machine_is_graphicsmaster()) {
861		parts = graphicsmaster_partitions;
862		nb_parts = ARRAY_SIZE(graphicsmaster_partitions);
863		sa1100_map.size = GRAPHICSMASTER_FLASH_SIZE;
864		sa1100_map.buswidth = (MSC1 & MSC_RBW) ? 2:4;
865	}
866#endif
867#ifdef CONFIG_SA1100_H3600
868	if (machine_is_h3600()) {
869		parts = h3600_partitions;
870		nb_parts = ARRAY_SIZE(h3600_partitions);
871		sa1100_map.size = H3600_FLASH_SIZE;
872		sa1100_map.set_vpp = h3600_set_vpp;
873	}
874#endif
875#ifdef CONFIG_SA1100_HUW_WEBPANEL
876	if (machine_is_huw_webpanel()) {
877		parts = huw_webpanel_partitions;
878		nb_parts = ARRAY_SIZE(huw_webpanel_partitions);
879		sa1100_map.size = HUW_WEBPANEL_FLASH_SIZE;
880	}
881#endif
882#ifdef CONFIG_SA1100_JORNADA720
883	if (machine_is_jornada720()) {
884		parts = jornada720_partitions;
885		nb_parts = ARRAY_SIZE(jornada720_partitions);
886		sa1100_map.size = JORNADA720_FLASH_SIZE;
887		sa1100_map.set_vpp = jornada720_set_vpp;
888	}
889#endif
890#ifdef CONFIG_SA1100_PANGOLIN
891	if (machine_is_pangolin()) {
892		parts = pangolin_partitions;
893		nb_parts = ARRAY_SIZE(pangolin_partitions);
894		sa1100_map.size = PANGOLIN_FLASH_SIZE;
895	}
896#endif
897#ifdef CONFIG_SA1100_PT_SYSTEM3
898	if (machine_is_pt_system3()) {
899		parts = system3_partitions;
900		nb_parts = ARRAY_SIZE(system3_partitions);
901		sa1100_map.size = SYSTEM3_FLASH_SIZE;
902	}
903#endif
904#ifdef CONFIG_SA1100_SHANNON
905	if (machine_is_shannon()) {
906		parts = shannon_partitions;
907		nb_parts = ARRAY_SIZE(shannon_partitions);
908		sa1100_map.size = SHANNON_FLASH_SIZE;
909	}
910#endif
911#ifdef CONFIG_SA1100_SHERMAN
912	if (machine_is_sherman()) {
913		parts = sherman_partitions;
914		nb_parts = ARRAY_SIZE(sherman_partitions);
915		sa1100_map.size = SHERMAN_FLASH_SIZE;
916	}
917#endif
918#ifdef CONFIG_SA1100_SIMPAD
919	if (machine_is_simpad()) {
920		parts = simpad_partitions;
921		nb_parts = ARRAY_SIZE(simpad_partitions);
922		sa1100_map.size = SIMPAD_FLASH_SIZE;
923	}
924#endif
925#ifdef CONFIG_SA1100_STORK
926	if (machine_is_stork()) {
927		parts = stork_partitions;
928		nb_parts = ARRAY_SIZE(stork_partitions);
929		sa1100_map.size = STORK_FLASH_SIZE;
930	}
931#endif
932#ifdef CONFIG_SA1100_YOPY
933	if (machine_is_yopy()) {
934		parts = yopy_partitions;
935		nb_parts = ARRAY_SIZE(yopy_partitions);
936		sa1100_map.size = YOPY_FLASH_SIZE;
937	}
938#endif
939
940	/*
941	 * For simple flash devices, use ioremap to map the flash.
942	 */
943	if (base != (unsigned long)-1) {
944		if (!request_mem_region(base, sa1100_map.size, "flash"))
945			return -EBUSY;
946		sa1100_map.map_priv_2 = base;
947		sa1100_map.map_priv_1 = (unsigned long)
948				ioremap(base, sa1100_map.size);
949		ret = -ENOMEM;
950		if (!sa1100_map.map_priv_1)
951			goto out_err;
952	}
953
954	/*
955	 * Now let's probe for the actual flash.  Do it here since
956	 * specific machine settings might have been set above.
957	 */
958	printk(KERN_NOTICE "SA1100 flash: probing %d-bit flash bus\n", sa1100_map.buswidth*8);
959	mymtd = do_map_probe("cfi_probe", &sa1100_map);
960	ret = -ENXIO;
961	if (!mymtd)
962		goto out_err;
963	mymtd->module = THIS_MODULE;
964
965	/*
966	 * Dynamic partition selection stuff (might override the static ones)
967	 */
968#ifdef CONFIG_MTD_REDBOOT_PARTS
969	if (parsed_nr_parts == 0) {
970		int ret = parse_redboot_partitions(mymtd, &parsed_parts);
971
972		if (ret > 0) {
973			part_type = "RedBoot";
974			parsed_nr_parts = ret;
975		}
976	}
977#endif
978#ifdef CONFIG_MTD_BOOTLDR_PARTS
979	if (parsed_nr_parts == 0) {
980		int ret = parse_bootldr_partitions(mymtd, &parsed_parts);
981		if (ret > 0) {
982			part_type = "Compaq bootldr";
983			parsed_nr_parts = ret;
984		}
985	}
986#endif
987
988	if (parsed_nr_parts > 0) {
989		parts = parsed_parts;
990		nb_parts = parsed_nr_parts;
991	}
992
993	if (nb_parts == 0) {
994		printk(KERN_NOTICE "SA1100 flash: no partition info available, registering whole flash at once\n");
995		add_mtd_device(mymtd);
996	} else {
997		printk(KERN_NOTICE "Using %s partition definition\n", part_type);
998		add_mtd_partitions(mymtd, parts, nb_parts);
999	}
1000	return 0;
1001
1002 out_err:
1003	if (sa1100_map.map_priv_2 != -1) {
1004		iounmap((void *)sa1100_map.map_priv_1);
1005		release_mem_region(sa1100_map.map_priv_2, sa1100_map.size);
1006	}
1007	return ret;
1008}
1009
1010static void __exit sa1100_mtd_cleanup(void)
1011{
1012	if (mymtd) {
1013		del_mtd_partitions(mymtd);
1014		map_destroy(mymtd);
1015		if (parsed_parts)
1016			kfree(parsed_parts);
1017	}
1018	if (sa1100_map.map_priv_2 != -1) {
1019		iounmap((void *)sa1100_map.map_priv_1);
1020		release_mem_region(sa1100_map.map_priv_2, sa1100_map.size);
1021	}
1022}
1023
1024module_init(sa1100_mtd_init);
1025module_exit(sa1100_mtd_cleanup);
1026
1027MODULE_AUTHOR("Nicolas Pitre");
1028MODULE_DESCRIPTION("SA1100 CFI map driver");
1029MODULE_LICENSE("GPL");
1030