Root/target/linux/rdc/files-2.6.30/arch/x86/mach-rdc321x/boards/ar525w.c

1/*
2 * ar525w RDC321x platform devices
3 *
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>
7 *
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.
12 *
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.
17 *
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.
22 *
23 */
24
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>
30
31#include <asm/rdc_boards.h>
32
33struct image_header {
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)) */
41    u32 reserved;
42};
43
44static struct gpio_led ar525w_leds[] = {
45    { .name = "rdc321x:dmz", .gpio = 1, .active_low = 1},
46};
47static struct gpio_button ar525w_btns[] = {
48    {
49        .gpio = 6,
50        .code = BTN_0,
51        .desc = "Reset",
52        .active_low = 1,
53    }
54};
55
56static 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,
121    0
122};
123
124static u32 __init crc32(u8 * buf, u32 len)
125{
126    register int i;
127    u32 sum;
128    register u32 s0;
129    s0 = ~0;
130    for (i = 0; i < len; i++) {
131        s0 = (s0 >> 8) ^ crctab[(u8) (s0 & 0xFF) ^ buf[i]];
132    }
133    sum = ~s0;
134    return sum;
135}
136
137static int __init fixup_ar525w_header(struct mtd_info *master, struct image_header *header)
138{
139    char *buffer;
140    int res;
141    u32 bufferlength = header->kernelsz + sizeof(struct image_header);
142    u32 len;
143    char crcbuf[0x400];
144
145    printk(KERN_INFO "Fixing up AR525W header, old image size: %u, new image size: %u\n",
146           header->imagesz, bufferlength);
147
148    buffer = vmalloc(bufferlength);
149    if (!buffer) {
150        printk(KERN_ERR "Can't allocate %u bytes\n", bufferlength);
151        return -ENOMEM;
152    }
153
154    res = master->read(master, 0x0, bufferlength, &len, buffer);
155    if (res || len != bufferlength)
156        goto out;
157
158    header = (struct image_header *) buffer;
159    header->imagesz = bufferlength;
160    header->checksum = 0;
161    header->fastcksum = 0;
162
163    memcpy(crcbuf, buffer, 0x100);
164    memcpy(crcbuf + 0x100, buffer + (bufferlength >> 1) - ((bufferlength & 0x6) >> 1), 0x100);
165    memcpy(crcbuf + 0x200, buffer + bufferlength - 0x200, 0x200);
166
167    header->fastcksum = crc32(crcbuf, sizeof(crcbuf));
168    header->checksum = crc32(buffer, bufferlength);
169
170    if (master->unlock)
171        master->unlock(master, 0, master->erasesize);
172    res = erase_write (master, 0, master->erasesize, buffer);
173    if (res)
174        printk(KERN_ERR "Can't rewrite image header\n");
175
176out:
177    vfree(buffer);
178    return res;
179}
180
181static int __init parse_ar525w_partitions(struct mtd_info *master, struct mtd_partition **pparts, unsigned long plat_data)
182{
183    struct image_header header;
184    int res;
185    size_t len;
186    struct mtd_partition *rdc_flash_parts;
187    struct rdc_platform_data *pdata = (struct rdc_platform_data *) plat_data;
188
189    if (master->size != 0x400000) //4MB
190        return -ENOSYS;
191
192    res = master->read(master, 0x0, sizeof(header), &len, (char *)&header);
193    if (res)
194        return res;
195
196    if (strncmp(header.magic, "GMTK", 4))
197        return -ENOSYS;
198
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);
201        return -EINVAL;
202    }
203
204    if (header.kernelsz + sizeof(header) != header.imagesz) {
205        res = fixup_ar525w_header(master, &header);
206        if (res)
207            return res;
208    }
209
210    rdc_flash_parts = kzalloc(sizeof(struct mtd_partition) * 3, GFP_KERNEL);
211
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;
221
222    *pparts = rdc_flash_parts;
223
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;
228
229    return 3;
230}
231
232static struct mtd_part_parser __initdata ar525w_parser = {
233    .owner = THIS_MODULE,
234    .parse_fn = parse_ar525w_partitions,
235    .name = "AR525W",
236};
237
238static int __init ar525w_setup(void)
239{
240    return register_mtd_parser(&ar525w_parser);
241}
242
243arch_initcall(ar525w_setup);
244

Archive Download this file



interactive