1 /* Flash mapping for Bifferboard, (c) bifferos@yahoo.co.uk
2 * Works with 1, 4 and 8MB flash versions
5 #include <linux/delay.h>
6 #include <linux/mtd/mtd.h>
7 #include <linux/mtd/map.h>
8 #include <linux/mtd/partitions.h>
10 #define DRV "bifferboard-flash: "
12 static struct mtd_info
*bb_mtd
= NULL
;
14 #define SIZE_BIFFBOOT 0x10000
15 #define SIZE_SECTOR 0x10000
16 #define SIZE_CONFIG 0x02000
17 #define SIZE_1MB 0x00100000
18 #define SIZE_4MB 0x00400000
19 #define SIZE_8MB 0x00800000
21 #define BASE_1MB 0xfff00000
22 #define BASE_4MB 0xffc00000
23 #define BASE_8MB 0xff800000
25 #define OFFS_KERNEL 0x6000
26 #define OFFS_CONFIG 0x4000
29 * Flash detection code. This is needed because the cfi_probe doesn't probe
30 * for the size correctly. You actually have to know the flash size before you
31 * call it, or so it seems. It does work correctly if you map the entire flash
32 * chip, but unsure of the implications for mapping more mem than exists.
35 static unsigned char ReadFlash(void* base
, u32 addr
)
37 unsigned char val
= *(volatile unsigned char *)(base
+addr
);
42 static void WriteFlash(void* base
, u32 addr
, unsigned short data
)
44 *(volatile unsigned short *)(base
+addr
) = data
;
47 static DEFINE_SPINLOCK(flash_lock
);
49 static u32
bb_detect(void)
54 /* for detection, map in just the 1MB device, 1st 64k is enough */
55 void* base
= ioremap_nocache(BASE_1MB
, 0x10000);
59 pr_err(DRV
"Failed to map flash for probing\n");
63 spin_lock_irqsave(&flash_lock
, flags
);
65 /* put flash in auto-detect mode */
66 WriteFlash(base
, 0xaaaa, 0xaaaa);
67 WriteFlash(base
, 0x5554, 0x5555);
68 WriteFlash(base
, 0xaaaa, 0x9090);
70 /* Read the auto-config data - 4 values in total */
71 ret
= ReadFlash(base
, 0x0000); ret
<<= 8;
72 ret
|= ReadFlash(base
, 0x0200); ret
<<= 8;
73 ret
|= ReadFlash(base
, 0x0003); ret
<<= 8;
74 ret
|= ReadFlash(base
, 0x0002);
76 /* exit the autodetect state */
77 WriteFlash(base
, 0x0000, 0xf0f0);
79 spin_unlock_irqrestore(&flash_lock
, flags
);
81 /* unmap it, it'll be re-mapped based on the detection */
88 static struct map_info bb_map
;
90 /* Update the map, using the detected flash signature. */
91 static int bb_adjust_map(unsigned long sig
, struct map_info
* m
)
102 m
->name
= "ENLV320B";
107 m
->name
= "ENLV640B";
118 /* adjust partition sizes, prior to adding the partition
119 * Values not specified by defines here are subject to replacement based on
120 * the real flash size. (0x00000000 being the exception, of course) */
122 static struct mtd_partition bb_parts
[] =
124 /* 0 */ { name
: "kernel", offset
: 0x00000000, size
: 0x000fa000 },
125 /* 1 */ { name
: "rootfs", offset
: MTDPART_OFS_APPEND
, size
: 0x002F0000 },
126 /* 2 */ { name
: "biffboot", offset
: MTDPART_OFS_APPEND
, size
: MTDPART_SIZ_FULL
, mask_flags
: MTD_WRITEABLE
},
130 /* returns the count of partitions to be used */
131 static ulong
bb_adjust_partitions(struct map_info
* m
)
133 /* Read the kernel offset value, 1036 bytes into the config block. */
134 u16 km_units
= *((u16
*)(m
->virt
+ OFFS_CONFIG
+ 1036));
135 u32 kernelmax
= 0x200000; /* Biffboot 2.7 or earlier default */
137 /* special-case 1MB devices, because there are fewer partitions */
138 if (m
->size
== SIZE_1MB
)
140 bb_parts
[0].size
= SIZE_1MB
- SIZE_BIFFBOOT
; /* kernel */
141 bb_parts
[1].name
= "biffboot"; /* biffboot */
142 bb_parts
[1].offset
= MTDPART_OFS_APPEND
; /* biffboot */
143 bb_parts
[1].size
= MTDPART_SIZ_FULL
; /* biffboot */
144 bb_parts
[1].mask_flags
= MTD_WRITEABLE
;
145 return 2; /* because there's no rootfs now */
149 if (km_units
> ((m
->size
-SIZE_BIFFBOOT
)/SIZE_SECTOR
))
151 pr_err(DRV
"config block has invalid kernelmax\n");
155 kernelmax
= km_units
* SIZE_SECTOR
;
158 bb_parts
[0].size
= kernelmax
;
161 bb_parts
[1].size
= m
->size
- kernelmax
- SIZE_BIFFBOOT
;
163 return 3; /* 3 partitions */
167 static int __init
init_bb_map(void)
170 ulong signature
= bb_detect();
175 pr_err(DRV
"Undetected flash chip");
179 ret
= bb_adjust_map(signature
, &bb_map
);
183 pr_err(DRV
"Unrecognised flash chip (signature: 0x%lx)\n", signature
);
187 bb_map
.virt
= ioremap_nocache(bb_map
.phys
, bb_map
.size
);
190 pr_err(DRV
"ioremap\n");
194 bb_mtd
= do_map_probe("cfi_probe", &bb_map
);
197 /* cfi_probe fails here for 1MB devices */
198 pr_err(DRV
"cfi_probe\n");
203 part_len
= bb_adjust_partitions(&bb_map
);
206 pr_err(DRV
"no partitions established");
211 bb_mtd
->owner
= THIS_MODULE
;
212 ret
= add_mtd_partitions(bb_mtd
, bb_parts
, part_len
);
215 pr_err(DRV
"add_mtd_partitions\n");
225 iounmap(bb_map
.virt
);
230 static void __exit
exit_bb_map(void)
232 del_mtd_partitions(bb_mtd
);
234 iounmap(bb_map
.virt
);
237 module_init(init_bb_map
);
238 module_exit(exit_bb_map
);
240 MODULE_LICENSE("GPL");
241 MODULE_AUTHOR("Bifferos <bifferos@yahoo.co.uk>");
242 MODULE_DESCRIPTION("MTD map driver for Bifferboard");
This page took 0.070166 seconds and 5 git commands to generate.