source: src/linux/universal/linux-3.5/drivers/mtd/maps/eoc5610_flash.c @ 31660

Last change on this file since 31660 was 31660, checked in by brainslayer, 13 days ago

use new squashfs in all kernels

File size: 6.9 KB
Line 
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2006-2007 Tomas Dlabac <tomas@dlabac.net>
7*/
8
9/*
10 *
11 *  Normal mappings of chips in physical memory
12 */
13
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/kernel.h>
17#include <asm/io.h>
18#include <linux/mtd/mtd.h>
19#include <linux/mtd/map.h>
20#include <linux/init.h>
21#include <linux/vmalloc.h>
22#include <linux/squashfs_fs.h>
23
24#include <linux/mtd/partitions.h>
25#define MTDID "ar531x"
26#include "../mtdcore.h"
27
28#define WINDOW_ADDR 0xbe000000
29#define WINDOW_SIZE 0x00800000
30
31/* These ought to be somewhere common... */
32
33#define AR531X_FLASHCTL 0x18400000
34
35#define FLASHCTL_MW     0x30000000      /* Memory width */
36#define FLASHCTL_MWx8   0x00000000      /* Memory width x8 */
37#define FLASHCTL_MWx16  0x10000000      /* Memory width x16 */
38#define FLASHCTL_MWx32  0x20000000      /* Memory width x32 (not supported) */
39
40#define sysRegRead(phys) __raw_readl(KSEG1ADDR(phys))
41
42static struct mtd_info *mymtd;
43
44static const char *probes[] = { "cmdlinepart", NULL };
45
46struct map_info ar531x_map = {
47      name:"ar531x",
48      size:WINDOW_SIZE
49};
50
51static struct mtd_partition *mtd_parts = 0;
52static int mtd_parts_nb = 0;
53
54struct img_info {
55        uint32_t lenght;
56        uint32_t CRC;
57};
58
59static struct mtd_partition dir_parts[] = {
60        {
61              name:"RedBoot",
62              size:0x30000,     /* 64KB */
63              offset:0,
64         }, {
65              name:"linux",
66              size:0x7A0000,
67              offset:0x30000,
68             }, {
69              name:"rootfs",
70              size:0x0,
71              offset:MTDPART_OFS_APPEND,
72                 }, {
73              name: "ddwrt",
74              size: 0x0,
75              offset:MTDPART_OFS_APPEND,
76                     }, {
77              name:      "nvram",
78              size:      0x10000,
79              offset:    0x7D0000,
80                         }, {
81              name:          "FIS directory",
82              size:          0x10000,
83              offset:        0x7E0000,
84                             }, {
85              name:              "board_config",
86              size:              0x10000,       /* 64KB */
87              offset:            0x7F0000,
88                                 }
89        , {
90              name:"fullflash",
91              size:0x800000,    /* 64KB */
92              offset:0x000000,
93           }
94};
95
96struct fis_image_desc {
97        unsigned char name[16]; // Null terminated name
98        unsigned long flash_base;       // Address within FLASH of image
99        unsigned long mem_base; // Address in memory where it executes
100        unsigned long size;     // Length of image
101        unsigned long entry_point;      // Execution entry point
102        unsigned long data_length;      // Length of actual data
103        unsigned char _pad[256 - (16 + 7 * sizeof(unsigned long))];
104        unsigned long desc_cksum;       // Checksum over image descriptor
105        unsigned long file_cksum;       // Checksum over image data
106};
107
108#define NUM_PARTITIONS  (sizeof(dir_parts)/sizeof(struct mtd_partition))
109
110int __init init_ar531x(void)
111{
112        static const char *rom_probe_types[] =
113            { "cfi_probe", "jedec_probe", "map_rom", 0 };
114        const char **type;
115        unsigned int flashctl;
116        void *buf;
117        size_t retlen;
118        int ret;
119        unsigned char *p;
120        struct fis_image_desc *fis;
121        struct img_info *image_info;
122        struct squashfs_super_block *sb;
123        int len;
124        size_t rootsize;
125
126        /* This is nasty, but needed as the new AR2312-01 parts only
127         * have an 8 bit bus to the flash; others have 16
128         */
129
130        flashctl = sysRegRead(AR531X_FLASHCTL) & FLASHCTL_MW;
131
132        if (flashctl == FLASHCTL_MWx8)
133                ar531x_map.bankwidth = 1;
134        else if (flashctl == FLASHCTL_MWx16)
135                ar531x_map.bankwidth = 2;
136        else {
137                printk(KERN_ERR "ar531x illegal flash buswidth (%#x)\n",
138                       flashctl);
139                return -ENXIO;
140        }
141
142//      printk(KERN_NOTICE "ar531x flash buswidth detected as %d\n",
143//             ar531x_map.bankwidth);
144
145        /*
146         * Must make sure that WINDOW_ADDR is in kseg1 (uncached)
147         */
148        ar531x_map.map_priv_1 = (WINDOW_ADDR | KSEG1);
149
150        ar531x_map.phys = WINDOW_ADDR;
151        ar531x_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
152
153        if (!ar531x_map.virt) {
154                printk("Failed to ioremap\n");
155                return -EIO;
156        }
157
158        simple_map_init(&ar531x_map);
159
160        mymtd = 0;
161        type = rom_probe_types;
162        for (; !mymtd && *type; type++) {
163                mymtd = do_map_probe(*type, &ar531x_map);
164        }
165        if (mymtd) {
166                mymtd->owner = THIS_MODULE;
167//              add_mtd_device(mymtd);
168                printk(KERN_NOTICE
169                       "AR531x Flash device initialized: size 0x%x at 0x%x bankwidth 0x%x\n",
170                       mymtd->size, WINDOW_ADDR, ar531x_map.bankwidth);
171
172#ifdef CONFIG_MTD
173                 {
174                        int offset = 0x0;
175                        unsigned char *buf = (unsigned char *)0xbe000000;
176                        while ((offset + mymtd->erasesize) < mymtd->size) {
177                                if (*((__u32 *)buf) == SQUASHFS_MAGIC_SWAP) {
178                                        printk(KERN_EMERG
179                                               "\nfound squashfs at %X\n",
180                                               offset);
181                                        sb = (struct squashfs_super_block *)buf;
182
183                                        dir_parts[2].offset = offset;
184                                        len = sb->bytes_used;
185                                        len += (mymtd->erasesize - 1);
186                                        len &= ~(mymtd->erasesize - 1);
187                                        dir_parts[2].size = len;
188                                        dir_parts[3].offset =
189                                            offset + dir_parts[2].size;
190                                        dir_parts[3].size =
191                                            dir_parts[1].size -
192                                            (dir_parts[3].offset -
193                                             0x30000);
194                                        dir_parts[6].offset =
195                                            mymtd->size - mymtd->erasesize;
196                                        dir_parts[5].offset =
197                                            mymtd->size -
198                                            (mymtd->erasesize * 2);
199                                        dir_parts[4].offset =
200                                            mymtd->size -
201                                            (mymtd->erasesize * 3);
202                                        rootsize = dir_parts[4].offset - offset;        //size of rootfs aligned to nvram offset
203
204                                        p = (unsigned char *)(0xbe000000 +
205                                                              dir_parts[5].
206                                                              offset);
207                                        fis = (struct fis_image_desc *)p;
208                                        while (1) {
209                                                if (fis->name[0] == 0xff) {
210                                                        goto def;
211                                                }
212                                                if (!strcmp
213                                                    (fis->name, "RedBoot")) {
214                                                        printk(KERN_EMERG
215                                                               "found RedBoot partition at [0x%08lX]\n",
216                                                               fis->flash_base);
217                                                        dir_parts[0].size =
218                                                            fis->size;
219                                                        dir_parts[7].offset = 0;
220                                                }
221                                                if (!strcmp(fis->name, "linux")
222                                                    || !strncmp(fis->name,
223                                                                "vmlinux", 7)
224                                                    || !strcmp(fis->name,
225                                                               "kernel")) {
226                                                        printk(KERN_EMERG
227                                                               "found linux partition at [0x%08lX]\n",
228                                                               fis->flash_base);
229                                                        dir_parts[1].offset =
230                                                            fis->
231                                                            flash_base & (mymtd->
232                                                                          size -
233                                                                          1);
234                                                        dir_parts[1].size =
235                                                            (dir_parts[2].
236                                                             offset -
237                                                             dir_parts[1].
238                                                             offset) + rootsize;
239                                                        dir_parts[7].size = mymtd->size;        // linux + nvram = phy size
240                                                }
241                                                p += sizeof(struct
242                                                            fis_image_desc);
243                                                fis =
244                                                    (struct fis_image_desc *)p;
245                                        }
246                                        break;
247                                }
248                                offset += mymtd->erasesize;
249                                buf += mymtd->erasesize;
250                        }
251                        def:;
252                        if (NUM_PARTITIONS != 0) {
253                                printk(KERN_NOTICE
254                                       "Using ar531x DD-WRT partition definition\n");
255                                add_mtd_partitions(mymtd, dir_parts,
256                                                   NUM_PARTITIONS);
257                        }
258
259                }
260#endif
261
262                return 0;
263        }
264        iounmap((void *)ar531x_map.virt);
265        return -ENXIO;
266}
267
268static void __exit cleanup_ar531x(void)
269{
270        if (mymtd) {
271                del_mtd_device(mymtd);
272                map_destroy(mymtd);
273        }
274        if (ar531x_map.virt) {
275                iounmap((void *)ar531x_map.virt);
276                ar531x_map.virt = 0;
277        }
278}
279
280module_init(init_ar531x);
281module_exit(cleanup_ar531x);
282
283MODULE_LICENSE("GPL");
284MODULE_AUTHOR("Tomas Dlabac");
285MODULE_DESCRIPTION("Atheros AR531x MTD map driver");
Note: See TracBrowser for help on using the repository browser.