1 /*******************************************************************
2 * Simple Flash mapping for RDC3210 *
5 * Dante Su (dante_su@gemtek.com.tw) *
6 * Copyright (C) 2005 Gemtek Corporation *
7 *******************************************************************/
9 #include <linux/module.h>
10 #include <linux/types.h>
11 #include <linux/kernel.h>
13 #include <linux/mtd/mtd.h>
14 #include <linux/mtd/map.h>
15 #include <linux/mtd/partitions.h>
16 #include <linux/config.h>
18 #ifndef RDC3210_STATIC_MAP
19 #define RDC3210_STATIC_MAP 0
21 #ifndef RDC3210_FACTORY_DFLT
22 #define RDC3210_FACTORY_DFLT 0
24 #ifndef RDC3210_USING_JFFS2
25 #define RDC3210_USING_JFFS2 1
28 #define WINDOW_ADDR 0xFFC00000
29 #define WINDOW_SIZE 0x00400000
33 /* Dante: linked from linux-2.4.x/drivers/mtd/chips/flashdrv.c */
34 extern int flashdrv_get_size(void);
35 extern int flashdrv_get_sector(int addr
);
36 extern int flashdrv_get_sector_addr(int sector
);
37 extern int flashdrv_get_sector_size(int sector
);
39 static struct mtd_info
*rdc3210_mtd
;
41 __u8
rdc3210_map_read8(struct map_info
*map
, unsigned long ofs
)
43 return *(__u8
*)(map
->map_priv_1
+ ofs
);
46 __u16
rdc3210_map_read16(struct map_info
*map
, unsigned long ofs
)
48 return *(__u16
*)(map
->map_priv_1
+ ofs
);
51 __u32
rdc3210_map_read32(struct map_info
*map
, unsigned long ofs
)
53 return *(__u32
*)(map
->map_priv_1
+ ofs
);
56 void rdc3210_map_write8(struct map_info
*map
, __u8 d
, unsigned long adr
)
58 *(__u8
*)(map
->map_priv_1
+ adr
) = d
;
61 void rdc3210_map_write16(struct map_info
*map
, __u16 d
, unsigned long adr
)
63 *(__u16
*)(map
->map_priv_1
+ adr
) = d
;
66 void rdc3210_map_write32(struct map_info
*map
, __u32 d
, unsigned long adr
)
68 *(__u32
*)(map
->map_priv_1
+ adr
) = d
;
71 void rdc3210_map_copy_from(struct map_info
*map
, void *to
, unsigned long from
, ssize_t len
)
74 u16
*dst
= (u16
*)(to
);
75 u16
*src
= (u16
*)(map
->map_priv_1
+ from
);
77 for(i
= 0; i
< (len
/ 2); ++i
)
82 printk("# WARNNING!!! rdc3210_map_copy_from has odd length\n");
83 //dst[len - 1] = B0(src[i]);
87 void rdc3210_map_copy_to(struct map_info
*map
, void *to
, unsigned long from
, ssize_t len
)
90 u16
*dst
= (u16
*)(map
->map_priv_1
+ to
);
91 u16
*src
= (u16
*)(from
);
93 for(i
= 0; i
< (len
/ 2); ++i
)
98 printk("# WARNNING!!! rdc3210_map_copy_from has odd length\n");
99 //dst[len - 1] = B0(src[i]);
103 struct map_info rdc3210_map
=
105 name
: "RDC3210 Flash",
108 read8
: rdc3210_map_read8
,
109 read16
: rdc3210_map_read16
,
110 read32
: rdc3210_map_read32
,
111 copy_from
: rdc3210_map_copy_from
,
112 write8
: rdc3210_map_write8
,
113 write16
: rdc3210_map_write16
,
114 write32
: rdc3210_map_write32
,
115 copy_to
: rdc3210_map_copy_to
,
118 /* Dante: This is the default static mapping, however this is nothing but a hint. (Say dynamic mapping) */
119 static struct mtd_partition rdc3210_parts
[] =
121 { name
: "linux", offset
: 0, size
: 0x003C0000 }, /* 3840 KB = (Kernel + ROMFS) = (768 KB + 3072 KB) */
122 { name
: "romfs", offset
: 0x000C0000, size
: 0x00300000 }, /* 3072 KB */
123 { name
: "nvram", offset
: 0x003C0000, size
: 0x00010000 }, /* 64 KB */
124 #if RDC3210_STATIC_MAP || RDC3210_FACTORY_DFLT
125 { name
: "factory", offset
: 0x003D0000, size
: 0x00010000 }, /* 64 KB */
127 { name
: "bootldr", offset
: 0x003E0000, size
: 0x00020000 }, /* 128 KB */
130 #if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)
131 #define init_rdc3210_map init_module
132 #define cleanup_rdc3210_map cleanup_module
135 mod_init_t
init_rdc3210_map(void)
137 printk(KERN_NOTICE
"flash device: %x at %x\n", WINDOW_SIZE
, WINDOW_ADDR
);
139 rdc3210_map
.map_priv_1
= ioremap(WINDOW_ADDR
, WINDOW_SIZE
);
141 if (!rdc3210_map
.map_priv_1
)
143 printk("Failed to ioremap\n");
146 rdc3210_mtd
= do_map_probe("cfi_probe", &rdc3210_map
);
147 #if RDC3210_STATIC_MAP /* Dante: This is for fixed map */
150 rdc3210_mtd
->module
= THIS_MODULE
;
151 add_mtd_partitions(rdc3210_mtd
, rdc3210_parts
, sizeof(rdc3210_parts
)/sizeof(rdc3210_parts
[0]));
154 #else /* Dante: This is for dynamic mapping */
156 #include <gemtek/sysdep.h>
157 #include <gemtek/imghdr.h>
161 #if RDC3210_USING_JFFS2
162 unsigned int tmp
, tmp2
= rdc3210_mtd
->erasesize
;
164 unsigned int tmp
, tmp2
= 32;
168 hdr
= (gt_imghdr_t
*)(rdc3210_map
.map_priv_1
);
170 if(memcmp(hdr
->magic
, GTIMG_MAGIC
, 4))
172 printk("Invalid MAGIC for Firmware Image!!!\n");
176 #if RDC3210_FACTORY_DFLT
177 /* 1. Adjust Redboot */
178 tmp
= flashdrv_get_size() - rdc3210_parts
[4].size
;
179 rdc3210_parts
[4].offset
= flashdrv_get_sector_addr(flashdrv_get_sector(tmp
));
180 rdc3210_parts
[4].size
= flashdrv_get_size() - rdc3210_parts
[4].offset
;
182 /* 2. Adjust NVRAM */
183 tmp
-= rdc3210_parts
[3].size
;
184 rdc3210_parts
[3].offset
= flashdrv_get_sector_addr(flashdrv_get_sector(tmp
));
185 rdc3210_parts
[3].size
= rdc3210_parts
[4].offset
- rdc3210_parts
[3].offset
;
187 /* 3. Adjust Factory Default */
188 tmp
-= rdc3210_parts
[2].size
;
189 rdc3210_parts
[2].offset
= flashdrv_get_sector_addr(flashdrv_get_sector(tmp
));
190 rdc3210_parts
[2].size
= rdc3210_parts
[3].offset
- rdc3210_parts
[2].offset
;
192 /* 4. Adjust Linux (Kernel + ROMFS) */
193 rdc3210_parts
[0].size
= rdc3210_parts
[2].offset
- rdc3210_parts
[0].offset
;
195 /* 5. Adjust ROMFS */
196 tmp
= hdr
->kernelsz
+ sizeof(gt_imghdr_t
);
197 rdc3210_parts
[1].offset
= rdc3210_parts
[0].offset
+ (((tmp
/ tmp2
) + ((tmp
% tmp2
) ? 1 : 0)) * tmp2
);
198 rdc3210_parts
[1].size
= rdc3210_parts
[2].offset
- rdc3210_parts
[1].offset
;
200 /* 1. Adjust Redboot */
201 tmp
= flashdrv_get_size() - rdc3210_parts
[3].size
;
202 rdc3210_parts
[3].offset
= flashdrv_get_sector_addr(flashdrv_get_sector(tmp
));
203 rdc3210_parts
[3].size
= flashdrv_get_size() - rdc3210_parts
[3].offset
;
205 /* 2. Adjust NVRAM */
206 tmp
-= rdc3210_parts
[2].size
;
207 rdc3210_parts
[2].offset
= flashdrv_get_sector_addr(flashdrv_get_sector(tmp
));
208 rdc3210_parts
[2].size
= rdc3210_parts
[3].offset
- rdc3210_parts
[2].offset
;
210 /* 4. Adjust Linux (Kernel + ROMFS) */
211 rdc3210_parts
[0].size
= rdc3210_parts
[2].offset
- rdc3210_parts
[0].offset
;
213 /* 5. Adjust ROMFS */
214 tmp
= hdr
->kernelsz
+ sizeof(gt_imghdr_t
);
215 rdc3210_parts
[1].offset
= rdc3210_parts
[0].offset
+ (((tmp
/ tmp2
) + ((tmp
% tmp2
) ? 1 : 0)) * tmp2
);
216 rdc3210_parts
[1].size
= rdc3210_parts
[2].offset
- rdc3210_parts
[1].offset
;
219 rdc3210_mtd
->module
= THIS_MODULE
;
220 add_mtd_partitions(rdc3210_mtd
, rdc3210_parts
, sizeof(rdc3210_parts
)/sizeof(rdc3210_parts
[0]));
225 iounmap((void *)rdc3210_map
.map_priv_1
);
229 mod_exit_t
cleanup_rdc3210_map(void)
233 del_mtd_partitions(rdc3210_mtd
);
234 map_destroy(rdc3210_mtd
);
237 if (rdc3210_map
.map_priv_1
)
239 iounmap((void *)rdc3210_map
.map_priv_1
);
240 rdc3210_map
.map_priv_1
= NULL
;
244 module_init(init_rdc3210_map
);
245 module_exit(cleanup_rdc3210_map
);