1 /****************************************************************************/
3 * Flash memory access on uClinux SnapGear like devices
4 * Copyright (C) 2001-2002, David McCullough <davidm@snapgear.com>
6 /****************************************************************************/
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/kernel.h>
11 #include <linux/reboot.h>
13 #include <linux/mtd/mtd.h>
14 #include <linux/mtd/nftl.h>
15 #include <linux/mtd/map.h>
16 #include <linux/mtd/partitions.h>
17 #include <linux/mtd/cfi.h>
21 #include <linux/major.h>
22 #include <linux/root_dev.h>
24 #include <linux/init.h>
26 #include <asm/delay.h>
27 #include <asm/sections.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
->bankwidth
= 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
= ioremap_nocache(map_ptr
->map_priv_2
, map_ptr
->size
);
240 if (!map_ptr
->virt
) {
241 printk("Failed to ioremap_nocache\n");
245 simple_map_init(map_ptr
);
247 mymtd
= do_map_probe("cfi_probe", map_ptr
);
249 mymtd
= do_map_probe("jedec_probe", map_ptr
);
251 mymtd
= do_map_probe("map_ram", map_ptr
);
254 iounmap((void *)map_ptr
->map_priv_1
);
258 mymtd
->owner
= THIS_MODULE
;
259 mymtd
->point
= nettel_point
;
260 mymtd
->priv
= map_ptr
;
264 add_mtd_partitions(mymtd
, nettel_romfs
, NB_OF(nettel_romfs
));
268 flash_mtdinfo
= mymtd
;
271 add_mtd_partitions(mymtd
, nettel_128k
, NB_OF(nettel_128k
));
274 add_mtd_partitions(mymtd
, nettel_1mb
, NB_OF(nettel_1mb
));
277 add_mtd_partitions(mymtd
, nettel_2mb
, NB_OF(nettel_2mb
));
280 add_mtd_partitions(mymtd
, nettel_4mb
, NB_OF(nettel_4mb
));
283 add_mtd_partitions(mymtd
, nettel_8mb
, NB_OF(nettel_8mb
));
286 add_mtd_partitions(mymtd
, nettel_16mb
, NB_OF(nettel_16mb
));
293 /****************************************************************************/
295 int __init
nettel_mtd_init(void)
298 struct mtd_info
*mtd
;
299 #ifdef CONFIG_COLDFIRE
304 * I hate this ifdef stuff, but our HW doesn't always have
305 * the same chipsize as the map that we use
307 #if defined(CONFIG_FLASH16MB) || defined(CONFIG_FLASHAUTO)
309 rc
= nettel_probe(0, FLASH_BASE
, SIZE_16MB
, BUS_WIDTH
);
312 #if defined(CONFIG_FLASH8MB) || defined(CONFIG_FLASHAUTO)
314 rc
= nettel_probe(0, FLASH_BASE
, SIZE_8MB
, BUS_WIDTH
);
317 #if defined(CONFIG_FLASH4MB) || defined(CONFIG_FLASHAUTO)
319 rc
= nettel_probe(0, FLASH_BASE
, SIZE_4MB
, BUS_WIDTH
);
322 #if defined(CONFIG_FLASH2MB) || defined(CONFIG_FLASHAUTO)
324 rc
= nettel_probe(0, FLASH_BASE
, SIZE_2MB
, BUS_WIDTH
);
327 #if defined(CONFIG_FLASH1MB) || defined(CONFIG_FLASHAUTO)
329 rc
= nettel_probe(0, FLASH_BASE
, SIZE_1MB
, BUS_WIDTH
);
332 #if defined(CONFIG_FLASH128K) || defined(CONFIG_FLASHAUTO)
334 rc
= nettel_probe(0, FLASH_BASE
, SIZE_128K
, BUS_WIDTH
);
337 #ifdef CONFIG_COLDFIRE
339 * Map in the filesystem from RAM last so that, if the filesystem
340 * is not in RAM for some reason we do not change the minor/major
341 * for the flash devices
343 #ifndef CONFIG_ROMFS_FROM_ROM
344 if (0 != nettel_probe(1, (unsigned long) &_ebss
,
345 PAGE_ALIGN(* (unsigned long *)((&_ebss
) + 8)), 4))
346 printk("Failed to probe RAM filesystem\n");
349 unsigned long start_area
;
350 unsigned char *sp
, *ep
;
353 start_area
= (unsigned long) &_ebss
;
355 if (strncmp((char *) start_area
, "-rom1fs-", 8) != 0) {
356 mtd
= get_mtd_named("Image");
357 if (mtd
&& mtd
->point
) {
358 if ((*mtd
->point
)(mtd
, 0, mtd
->size
, &len
, &sp
) == 0) {
360 while (sp
< ep
&& strncmp(sp
, "-rom1fs-", 8) != 0)
363 start_area
= (unsigned long) sp
;
369 if (0 != nettel_probe(1, start_area
,
370 PAGE_ALIGN(* (unsigned long *)(start_area
+ 8)), 4))
371 printk("Failed to probe RAM filesystem\n");
375 mtd
= get_mtd_named("Romfs");
377 ROOT_DEV
= MKDEV(MTD_BLOCK_MAJOR
, mtd
->index
);
380 printk("%s: Failed to find & make root filesystem\n", __FUNCTION__
);
383 #ifdef CONFIG_SH_SECUREEDGE5410
384 #if defined(CONFIG_NFTL) || defined(CONFIG_INFTL)
385 ROOT_DEV
= MKDEV(NFTL_MAJOR
, 1);
387 mtd
= get_mtd_named("Image");
389 ROOT_DEV
= MKDEV(MTD_BLOCK_MAJOR
, mtd
->index
);
395 #ifdef CONFIG_MTD_CFI_INTELEXT
396 register_reboot_notifier(&nettel_notifier_block
);
402 /****************************************************************************/
404 static void __exit
nettel_mtd_cleanup(void)
407 del_mtd_partitions(flash_mtdinfo
);
408 map_destroy(flash_mtdinfo
);
409 flash_mtdinfo
= NULL
;
412 del_mtd_partitions(ram_mtdinfo
);
413 map_destroy(ram_mtdinfo
);
416 if (nettel_ram_map
.map_priv_1
) {
417 iounmap((void *)nettel_ram_map
.map_priv_1
);
418 nettel_ram_map
.map_priv_1
= 0;
420 if (nettel_flash_map
.map_priv_1
) {
421 iounmap((void *)nettel_flash_map
.map_priv_1
);
422 nettel_flash_map
.map_priv_1
= 0;
426 /****************************************************************************/
428 module_init(nettel_mtd_init
);
429 module_exit(nettel_mtd_cleanup
);
431 MODULE_LICENSE("GPL");
432 MODULE_AUTHOR("David McCullough <davidm@snapgear.com>");
433 MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support for uClinux");
435 /****************************************************************************/