root/src/linux/ar531x/linux-2.6.23/drivers/mtd/maps/eoc5610_flash.c

Revision 12400, 7.0 kB (checked in by BrainSlayer, 5 months ago)

more flexible EOC5610 partition layout, small performance increase by module remapping, lzma decoder speed improvements

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