1 /****************************************************************************/
3 * Flash memory access on uClinux SnapGear like devices
4 * Copyright (C) 2001-2002, David McCullough <davidm@snapgear.com>
6 /****************************************************************************/
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/reboot.h>
14 #include <linux/mtd/mtd.h>
15 #include <linux/mtd/nftl.h>
16 #include <linux/mtd/map.h>
17 #include <linux/mtd/partitions.h>
18 #include <linux/mtd/cfi.h>
22 #include <linux/major.h>
23 #include <linux/root_dev.h>
25 #include <linux/init.h>
27 #include <asm/delay.h>
29 /****************************************************************************/
31 #define NB_OF(x) (sizeof(x)/sizeof(x[0]))
33 #define SIZE_128K (1 * 128 * 1024)
34 #define SIZE_1MB (1 * 1024 * 1024)
35 #define SIZE_2MB (2 * 1024 * 1024)
36 #define SIZE_4MB (4 * 1024 * 1024)
37 #define SIZE_8MB (8 * 1024 * 1024)
38 #define SIZE_16MB (16 * 1024 * 1024)
40 #ifdef CONFIG_COLDFIRE
41 #define FLASH_BASE 0xf0000000
46 #define FLASH_BASE 0x00000000
50 /****************************************************************************/
52 static struct map_info nettel_flash_map
= {
56 static struct map_info nettel_ram_map
= {
60 static struct mtd_info
*ram_mtdinfo
;
61 static struct mtd_info
*flash_mtdinfo
;
63 /****************************************************************************/
65 static struct mtd_partition nettel_romfs
[] = {
69 #define NUM_PARTITIONS (sizeof(nettel_romfs) / sizeof(nettel_romfs[0]))
71 /****************************************************************************/
73 * The layout of our flash, note the order of the names, this
74 * means we use the same major/minor for the same purpose on all
75 * layouts (when possible)
78 static struct mtd_partition nettel_128k
[] = {
79 { .name
= "Bootloader", .offset
= 0x00000000, .size
= 0x00004000 },
80 { .name
= "Bootargs", .offset
= 0x00004000, .size
= 0x00004000 },
81 { .name
= "MAC", .offset
= 0x00008000, .size
= 0x00004000 },
82 { .name
= "Config", .offset
= 0x00010000, .size
= 0x00010000 },
83 { .name
= "Spare", .offset
= 0x0000c000, .size
= 0x00004000 },
84 { .name
= "Flash", .offset
= 0 }
87 static struct mtd_partition nettel_1mb
[] = {
88 { .name
= "Bootloader", .offset
= 0x00000000, .size
= 0x00004000 },
89 { .name
= "Bootargs", .offset
= 0x00004000, .size
= 0x00002000 },
90 { .name
= "MAC", .offset
= 0x00006000, .size
= 0x00002000 },
91 { .name
= "Config", .offset
= 0x000f0000, .size
= 0x00010000 },
92 { .name
= "Spare", .offset
= 0x00008000, .size
= 0x00008000 },
93 { .name
= "Image", .offset
= 0x00010000, .size
= 0x000e0000 },
94 { .name
= "Flash", .offset
= 0 }
97 static struct mtd_partition nettel_2mb
[] = {
98 { .name
= "Bootloader", .offset
= 0x00000000, .size
= 0x00004000 },
99 { .name
= "Bootargs", .offset
= 0x00004000, .size
= 0x00002000 },
100 { .name
= "MAC", .offset
= 0x00006000, .size
= 0x00002000 },
101 { .name
= "Config", .offset
= 0x00010000, .size
= 0x00010000 },
102 { .name
= "Spare", .offset
= 0x00008000, .size
= 0x00008000 },
103 { .name
= "Image", .offset
= 0x00020000, .size
= 0x001e0000 },
104 { .name
= "Flash", .offset
= 0 }
107 #ifdef CONFIG_SH_SECUREEDGE5410
109 static struct mtd_partition nettel_4mb
[] = {
110 { .name
= "Boot data", .offset
= 0x00000000, .size
= 0x00020000 },
111 { .name
= "Config", .offset
= 0x00020000, .size
= 0x00040000 },
112 { .name
= "Image", .offset
= 0x00060000, .size
= 0x00000000 },
113 { .name
= "Flash", .offset
= 0 }
116 static struct mtd_partition nettel_8mb
[] = {
117 { .name
= "Boot data", .offset
= 0x00000000, .size
= 0x00020000 },
118 { .name
= "Config", .offset
= 0x00020000, .size
= 0x00080000 },
119 { .name
= "Image", .offset
= 0x000a0000, .size
= 0x00000000 },
120 { .name
= "Flash", .offset
= 0 }
125 static struct mtd_partition nettel_4mb
[] = {
126 { .name
= "Bootloader", .offset
= 0x00000000, .size
= 0x00004000 },
127 { .name
= "Bootargs", .offset
= 0x00004000, .size
= 0x00002000 },
128 { .name
= "MAC", .offset
= 0x00006000, .size
= 0x00002000 },
129 { .name
= "Config", .offset
= 0x00010000, .size
= 0x00010000 },
130 { .name
= "Spare", .offset
= 0x00008000, .size
= 0x00008000 },
131 { .name
= "Image", .offset
= 0x00020000, .size
= 0x001e0000 },
132 { .name
= "Flash", .offset
= 0x00000000, .size
= 0x00200000 },
133 { .name
= "Image2", .offset
= 0x00220000, .size
= 0x001e0000 },
134 { .name
= "Flash2", .offset
= 0 }
137 static struct mtd_partition nettel_8mb
[] = {
138 { .name
= "Bootloader", .offset
= 0x00000000, .size
= 0x00020000 },
139 { .name
= "Bootargs", .offset
= 0x00020000, .size
= 0x00020000 },
140 { .name
= "MAC", .offset
= 0x00040000, .size
= 0x00020000 },
141 { .name
= "Config", .offset
= 0x00080000, .size
= 0x00080000 },
142 { .name
= "Spare", .offset
= 0x00060000, .size
= 0x00020000 },
143 { .name
= "Image", .offset
= 0x00100000, .size
= 0x00700000 },
144 { .name
= "Flash", .offset
= 0 }
149 static struct mtd_partition nettel_16mb
[] = {
150 { .name
= "Boot data", .offset
= 0x00000000, .size
= 0x00020000 },
151 { .name
= "Config", .offset
= 0x00020000, .size
= 0x00100000 },
152 { .name
= "Image", .offset
= 0x00120000, .size
= 0x00000000 },
153 { .name
= "Flash", .offset
= 0 }
156 /****************************************************************************/
158 * Find the MTD device with the given name
161 static struct mtd_info
*get_mtd_named(char *name
)
164 struct mtd_info
*mtd
;
166 for (i
= 0; i
< MAX_MTD_DEVICES
; i
++) {
167 mtd
= get_mtd_device(NULL
, i
);
169 if (strcmp(mtd
->name
, name
) == 0)
177 /****************************************************************************/
178 #ifdef CONFIG_MTD_CFI_INTELEXT
180 * Set the Intel flash back to read mode as MTD may leave it in command mode
183 static int nettel_reboot_notifier(
184 struct notifier_block
*nb
,
188 struct cfi_private
*cfi
= nettel_flash_map
.fldrv_priv
;
191 for (i
= 0; cfi
&& i
< cfi
->numchips
; i
++)
192 cfi_send_gen_cmd(0xff, 0x55, cfi
->chips
[i
].start
, &nettel_flash_map
,
193 cfi
, cfi
->device_type
, NULL
);
198 static struct notifier_block nettel_notifier_block
= {
199 nettel_reboot_notifier
, NULL
, 0
204 /****************************************************************************/
207 nettel_point(struct mtd_info
*mtd
, loff_t from
, size_t len
,
208 size_t *retlen
, u_char
**mtdbuf
)
210 struct map_info
*map
= (struct map_info
*) mtd
->priv
;
211 *mtdbuf
= (u_char
*) (map
->map_priv_1
+ (int)from
);
216 /****************************************************************************/
219 nettel_probe(int ram
, unsigned long addr
, int size
, int buswidth
)
221 struct mtd_info
*mymtd
;
222 struct map_info
*map_ptr
;
225 map_ptr
= &nettel_ram_map
;
227 map_ptr
= &nettel_flash_map
;
229 map_ptr
->buswidth
= buswidth
;
230 map_ptr
->map_priv_2
= addr
;
231 map_ptr
->phys
= addr
;
232 map_ptr
->size
= size
;
234 printk(KERN_NOTICE
"SnapGear %s probe(0x%lx,%d,%d): %lx at %lx\n",
235 ram
? "ram" : "flash",
236 addr
, size
, buswidth
, map_ptr
->size
, map_ptr
->map_priv_2
);
238 map_ptr
->virt
= (unsigned long)
239 ioremap_nocache(map_ptr
->map_priv_2
, map_ptr
->size
);
241 if (!map_ptr
->virt
) {
242 printk("Failed to ioremap_nocache\n");
246 simple_map_init(map_ptr
);
248 mymtd
= do_map_probe("cfi_probe", map_ptr
);
250 mymtd
= do_map_probe("jedec_probe", map_ptr
);
252 mymtd
= do_map_probe("map_ram", map_ptr
);
255 iounmap((void *)map_ptr
->map_priv_1
);
259 mymtd
->owner
= THIS_MODULE
;
260 mymtd
->point
= nettel_point
;
261 mymtd
->priv
= map_ptr
;
265 add_mtd_partitions(mymtd
, nettel_romfs
, NB_OF(nettel_romfs
));
269 flash_mtdinfo
= mymtd
;
272 add_mtd_partitions(mymtd
, nettel_128k
, NB_OF(nettel_128k
));
275 add_mtd_partitions(mymtd
, nettel_1mb
, NB_OF(nettel_1mb
));
278 add_mtd_partitions(mymtd
, nettel_2mb
, NB_OF(nettel_2mb
));
281 add_mtd_partitions(mymtd
, nettel_4mb
, NB_OF(nettel_4mb
));
284 add_mtd_partitions(mymtd
, nettel_8mb
, NB_OF(nettel_8mb
));
287 add_mtd_partitions(mymtd
, nettel_16mb
, NB_OF(nettel_16mb
));
294 /****************************************************************************/
296 int __init
nettel_mtd_init(void)
299 struct mtd_info
*mtd
;
300 #ifdef CONFIG_COLDFIRE
305 * I hate this ifdef stuff, but our HW doesn't always have
306 * the same chipsize as the map that we use
308 #if defined(CONFIG_FLASH16MB) || defined(CONFIG_FLASHAUTO)
310 rc
= nettel_probe(0, FLASH_BASE
, SIZE_16MB
, BUS_WIDTH
);
313 #if defined(CONFIG_FLASH8MB) || defined(CONFIG_FLASHAUTO)
315 rc
= nettel_probe(0, FLASH_BASE
, SIZE_8MB
, BUS_WIDTH
);
318 #if defined(CONFIG_FLASH4MB) || defined(CONFIG_FLASHAUTO)
320 rc
= nettel_probe(0, FLASH_BASE
, SIZE_4MB
, BUS_WIDTH
);
323 #if defined(CONFIG_FLASH2MB) || defined(CONFIG_FLASHAUTO)
325 rc
= nettel_probe(0, FLASH_BASE
, SIZE_2MB
, BUS_WIDTH
);
328 #if defined(CONFIG_FLASH1MB) || defined(CONFIG_FLASHAUTO)
330 rc
= nettel_probe(0, FLASH_BASE
, SIZE_1MB
, BUS_WIDTH
);
333 #if defined(CONFIG_FLASH128K) || defined(CONFIG_FLASHAUTO)
335 rc
= nettel_probe(0, FLASH_BASE
, SIZE_128K
, BUS_WIDTH
);
338 #ifdef CONFIG_COLDFIRE
340 * Map in the filesystem from RAM last so that, if the filesystem
341 * is not in RAM for some reason we do not change the minor/major
342 * for the flash devices
344 #ifndef CONFIG_ROMFS_FROM_ROM
345 if (0 != nettel_probe(1, (unsigned long) &_ebss
,
346 PAGE_ALIGN(* (unsigned long *)((&_ebss
) + 8)), 4))
347 printk("Failed to probe RAM filesystem\n");
350 unsigned long start_area
;
351 unsigned char *sp
, *ep
;
354 start_area
= (unsigned long) &_ebss
;
356 if (strncmp((char *) start_area
, "-rom1fs-", 8) != 0) {
357 mtd
= get_mtd_named("Image");
358 if (mtd
&& mtd
->point
) {
359 if ((*mtd
->point
)(mtd
, 0, mtd
->size
, &len
, &sp
) == 0) {
361 while (sp
< ep
&& strncmp(sp
, "-rom1fs-", 8) != 0)
364 start_area
= (unsigned long) sp
;
370 if (0 != nettel_probe(1, start_area
,
371 PAGE_ALIGN(* (unsigned long *)(start_area
+ 8)), 4))
372 printk("Failed to probe RAM filesystem\n");
376 mtd
= get_mtd_named("Romfs");
378 ROOT_DEV
= MKDEV(MTD_BLOCK_MAJOR
, mtd
->index
);
381 printk("%s: Failed to find & make root filesystem\n", __FUNCTION__
);
384 #ifdef CONFIG_SH_SECUREEDGE5410
388 char *cp
= (char *) &_end
;
390 memcpy(&magic
, cp
, sizeof(magic
));
391 if (memcmp(cp
, "-rom1fs-", 8) == 0) {
393 nettel_probe(1, (unsigned long) cp
,
394 PAGE_ALIGN(* (unsigned long *)(cp
+ 8)), 4);
395 mtd
= get_mtd_named("Romfs");
397 ROOT_DEV
= MKDEV(MTD_BLOCK_MAJOR
, mtd
->index
);
400 printk("%s: Failed to find & make romfs root filesystem\n",
402 } else if (magic
== 0x28cd3d45) {
404 nettel_probe(1, (unsigned long) cp
,
405 PAGE_ALIGN(* (unsigned long *)(cp
+ 4)), 4);
406 mtd
= get_mtd_named("Romfs");
408 ROOT_DEV
= MKDEV(MTD_BLOCK_MAJOR
, mtd
->index
);
411 printk("%s: Failed to find & make cramfs root filesystem\n",
414 #if defined(CONFIG_NFTL) || defined(CONFIG_INFTL)
415 ROOT_DEV
= MKDEV(NFTL_MAJOR
, 1);
417 mtd
= get_mtd_named("Image");
419 ROOT_DEV
= MKDEV(MTD_BLOCK_MAJOR
, mtd
->index
);
427 #ifdef CONFIG_MTD_CFI_INTELEXT
428 register_reboot_notifier(&nettel_notifier_block
);
434 /****************************************************************************/
436 static void __exit
nettel_mtd_cleanup(void)
439 del_mtd_partitions(flash_mtdinfo
);
440 map_destroy(flash_mtdinfo
);
441 flash_mtdinfo
= NULL
;
444 del_mtd_partitions(ram_mtdinfo
);
445 map_destroy(ram_mtdinfo
);
448 if (nettel_ram_map
.map_priv_1
) {
449 iounmap((void *)nettel_ram_map
.map_priv_1
);
450 nettel_ram_map
.map_priv_1
= 0;
452 if (nettel_flash_map
.map_priv_1
) {
453 iounmap((void *)nettel_flash_map
.map_priv_1
);
454 nettel_flash_map
.map_priv_1
= 0;
458 /****************************************************************************/
460 module_init(nettel_mtd_init
);
461 module_exit(nettel_mtd_cleanup
);
463 MODULE_LICENSE("GPL");
464 MODULE_AUTHOR("David McCullough <davidm@snapgear.com>");
465 MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support for uClinux");
467 /****************************************************************************/