2 * ar525w RDC321x platform devices
4 * Copyright (C) 2007-2009 OpenWrt.org
5 * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org>
6 * Copyright (C) 2008-2009 Daniel Gimpelevich <daniel@gimpelevich.san-francisco.ca.us>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
25 #include <linux/init.h>
26 #include <linux/mtd/physmap.h>
27 #include <linux/input.h>
28 #include <linux/vmalloc.h>
29 #include <linux/mtd/mtd.h>
31 #include <asm/rdc_boards.h>
34 char magic
[4]; /* ASICII: GMTK */
35 u32 checksum
; /* CRC32 */
36 u32 version
; /* x.x.x.x */
37 u32 kernelsz
; /* The size of the kernel image */
38 u32 imagesz
; /* The length of this image file ( kernel + romfs + this header) */
39 u32 pid
; /* Product ID */
40 u32 fastcksum
; /* Partial CRC32 on (First(256), medium(256), last(512)) */
44 static struct gpio_led ar525w_leds
[] = {
45 { .name
= "rdc321x:dmz", .gpio
= 1, .active_low
= 1},
47 static struct gpio_button ar525w_btns
[] = {
56 static u32 __initdata crctab
[257] = {
57 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
58 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
59 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
60 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
61 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
62 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
63 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
64 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
65 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
66 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
67 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
68 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
69 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
70 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
71 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
72 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
73 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
74 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
75 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
76 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
77 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
78 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
79 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
80 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
81 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
82 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
83 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
84 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
85 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
86 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
87 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
88 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
89 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
90 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
91 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
92 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
93 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
94 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
95 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
96 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
97 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
98 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
99 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
100 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
101 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
102 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
103 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
104 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
105 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
106 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
107 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
108 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
109 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
110 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
111 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
112 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
113 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
114 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
115 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
116 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
117 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
118 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
119 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
120 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
124 static u32 __init
crc32(u8
* buf
, u32 len
)
130 for (i
= 0; i
< len
; i
++) {
131 s0
= (s0
>> 8) ^ crctab
[(u8
) (s0
& 0xFF) ^ buf
[i
]];
137 static int __init
fixup_ar525w_header(struct mtd_info
*master
, struct image_header
*header
)
141 u32 bufferlength
= header
->kernelsz
+ sizeof(struct image_header
);
145 printk(KERN_INFO
"Fixing up AR525W header, old image size: %u, new image size: %u\n",
146 header
->imagesz
, bufferlength
);
148 buffer
= vmalloc(bufferlength
);
150 printk(KERN_ERR
"Can't allocate %u bytes\n", bufferlength
);
154 res
= master
->read(master
, 0x0, bufferlength
, &len
, buffer
);
155 if (res
|| len
!= bufferlength
)
158 header
= (struct image_header
*) buffer
;
159 header
->imagesz
= bufferlength
;
160 header
->checksum
= 0;
161 header
->fastcksum
= 0;
163 memcpy(crcbuf
, buffer
, 0x100);
164 memcpy(crcbuf
+ 0x100, buffer
+ (bufferlength
>> 1) - ((bufferlength
& 0x6) >> 1), 0x100);
165 memcpy(crcbuf
+ 0x200, buffer
+ bufferlength
- 0x200, 0x200);
167 header
->fastcksum
= crc32(crcbuf
, sizeof(crcbuf
));
168 header
->checksum
= crc32(buffer
, bufferlength
);
171 master
->unlock(master
, 0, master
->erasesize
);
172 res
= erase_write (master
, 0, master
->erasesize
, buffer
);
174 printk(KERN_ERR
"Can't rewrite image header\n");
181 static int __init
parse_ar525w_partitions(struct mtd_info
*master
, struct mtd_partition
**pparts
, unsigned long plat_data
)
183 struct image_header header
;
186 struct mtd_partition
*rdc_flash_parts
;
187 struct rdc_platform_data
*pdata
= (struct rdc_platform_data
*) plat_data
;
189 if (master
->size
!= 0x400000) //4MB
192 res
= master
->read(master
, 0x0, sizeof(header
), &len
, (char *)&header
);
196 if (strncmp(header
.magic
, "GMTK", 4))
199 if (header
.kernelsz
> 0x400000 || header
.kernelsz
< master
->erasesize
) {
200 printk(KERN_ERR
"AR525W image header found, but seems corrupt, kernel size %u\n", header
.kernelsz
);
204 if (header
.kernelsz
+ sizeof(header
) != header
.imagesz
) {
205 res
= fixup_ar525w_header(master
, &header
);
210 rdc_flash_parts
= kzalloc(sizeof(struct mtd_partition
) * 3, GFP_KERNEL
);
212 rdc_flash_parts
[0].name
= "firmware";
213 rdc_flash_parts
[0].offset
= 0x0;
214 rdc_flash_parts
[0].size
= 0x3E0000;
215 rdc_flash_parts
[1].name
= "rootfs";
216 rdc_flash_parts
[1].offset
= header
.kernelsz
+ sizeof(header
);
217 rdc_flash_parts
[1].size
= rdc_flash_parts
[0].size
- rdc_flash_parts
[1].offset
;
218 rdc_flash_parts
[2].name
= "bootloader";
219 rdc_flash_parts
[2].offset
= 0x3E0000;
220 rdc_flash_parts
[2].size
= 0x20000;
222 *pparts
= rdc_flash_parts
;
224 pdata
->led_data
.num_leds
= ARRAY_SIZE(ar525w_leds
);
225 pdata
->led_data
.leds
= ar525w_leds
;
226 pdata
->button_data
.nbuttons
= ARRAY_SIZE(ar525w_btns
);
227 pdata
->button_data
.buttons
= ar525w_btns
;
232 static struct mtd_part_parser __initdata ar525w_parser
= {
233 .owner
= THIS_MODULE
,
234 .parse_fn
= parse_ar525w_partitions
,
238 static int __init
ar525w_setup(void)
240 return register_mtd_parser(&ar525w_parser
);
243 arch_initcall(ar525w_setup
);