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

Revision 11767, 5.6 kB (checked in by BrainSlayer, 8 months ago)

EOC5610 support (kernel flash map)

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
25 #ifdef CONFIG_MTD_PARTITIONS
26 #include <linux/mtd/partitions.h>
27 #define MTDID "ar531x"
28 #endif
29
30 #define WINDOW_ADDR 0xbe000000
31 #define WINDOW_SIZE 0x00800000
32
33
34 /* These ought to be somewhere common... */
35
36 #define AR531X_FLASHCTL 0x18400000
37
38 #define FLASHCTL_MW     0x30000000      /* Memory width */
39 #define FLASHCTL_MWx8   0x00000000      /* Memory width x8 */
40 #define FLASHCTL_MWx16  0x10000000      /* Memory width x16 */
41 #define FLASHCTL_MWx32  0x20000000      /* Memory width x32 (not supported) */
42
43 #define sysRegRead(phys) __raw_readl(KSEG1ADDR(phys))
44
45
46 static struct mtd_info *mymtd;
47
48 #ifdef CONFIG_MTD_PARTITIONS
49 static const char *probes []={"cmdlinepart",NULL};
50 #endif
51
52 struct map_info ar531x_map = {
53         name: "ar531x",
54         size: WINDOW_SIZE
55 };
56
57 #ifdef CONFIG_MTD_PARTITIONS
58 static struct mtd_partition *mtd_parts = 0;
59 static int                   mtd_parts_nb = 0;
60
61 struct img_info {
62         uint32_t lenght;
63         uint32_t CRC;
64         };
65
66 static struct mtd_partition ar531x_partitions[] = {
67         {
68                 name:           "RedBoot",
69                 size:           0x30000,                /* 64KB */
70                 offset:         0,
71         }, {
72                 name:           "linux",
73                 size:           0x7A0000,       
74                 offset:         0x30000,
75         }, {
76                 name:           "rootfs",
77                 size:           0x0,   
78                 offset:         MTDPART_OFS_APPEND,
79         }, {
80                 name:           "ddwrt",
81                 size:           0x0,   
82                 offset:         MTDPART_OFS_APPEND,
83         }, {
84                 name:           "nvram",
85                 size:           0x10000,       
86                 offset:         0x7D0000,
87         }, {
88                 name:           "FIS directory",
89                 size:           0x10000,       
90                 offset:         0x7E0000,
91         }, {
92                 name:           "board_config",
93                 size:           0x10000,                /* 64KB */
94                 offset:         0x7F0000,
95         }
96
97 };
98
99 #define NUM_PARTITIONS  (sizeof(ar531x_partitions)/sizeof(struct mtd_partition))
100 #endif
101
102
103
104 int __init init_ar531x(void)
105 {
106         static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", "map_rom", 0 };
107         const char **type;
108         unsigned int flashctl;
109         void *buf;
110         size_t  retlen;
111         int ret;
112         struct img_info *image_info;
113         struct squashfs_super_block *sb;
114         int len;               
115
116         /* This is nasty, but needed as the new AR2312-01 parts only
117          * have an 8 bit bus to the flash; others have 16
118          */
119
120         flashctl = sysRegRead(AR531X_FLASHCTL) & FLASHCTL_MW;
121
122         if (flashctl == FLASHCTL_MWx8)
123                 ar531x_map.bankwidth = 1;
124         else if (flashctl == FLASHCTL_MWx16)
125                 ar531x_map.bankwidth = 2;
126         else {
127                 printk(KERN_ERR "ar531x illegal flash buswidth (%#x)\n",
128                         flashctl);
129                 return -ENXIO;
130         }
131
132 //      printk(KERN_NOTICE "ar531x flash buswidth detected as %d\n",
133 //             ar531x_map.bankwidth);
134
135         /*
136          * Must make sure that WINDOW_ADDR is in kseg1 (uncached)
137          */
138         ar531x_map.map_priv_1 = (WINDOW_ADDR | KSEG1);
139
140         ar531x_map.phys = WINDOW_ADDR;
141         ar531x_map.virt = ioremap(WINDOW_ADDR,WINDOW_SIZE);
142        
143         if (!ar531x_map.virt) {
144             printk("Failed to ioremap\n");
145             return -EIO;
146         }
147
148         simple_map_init(&ar531x_map);
149
150         mymtd = 0;
151         type = rom_probe_types;
152         for(; !mymtd && *type; type++) {
153                 mymtd = do_map_probe(*type, &ar531x_map);
154         }
155         if (mymtd) {
156                 mymtd->owner = THIS_MODULE;
157 //              add_mtd_device(mymtd);
158                 printk(KERN_NOTICE "AR531x Flash device initialized: size 0x%x at 0x%x bankwidth 0x%x\n",
159                     mymtd->size, WINDOW_ADDR, ar531x_map.bankwidth);
160
161 #ifdef CONFIG_MTD_PARTITIONS
162                         if (buf) {
163                             int offset = 0x0;
164                             char *buf = (char*)0xbfc00000;
165                             while((offset+mymtd->erasesize)<mymtd->size)
166                             {
167                             if (*((__u32 *) buf) == SQUASHFS_MAGIC)
168                                     {
169                                         printk(KERN_EMERG "\nfound squashfs at %X\n",offset);
170                                         sb = (struct squashfs_super_block *) buf;
171                
172                                         ar531x_partitions[2].offset=offset;                                     
173                                         len = sb->bytes_used;
174                                         len +=  (mymtd->erasesize - 1);
175                                         len &= ~(mymtd->erasesize - 1);
176                                         ar531x_partitions[2].size = len;                                       
177                                         ar531x_partitions[3].offset=offset+ar531x_partitions[2].size;                                   
178                                         ar531x_partitions[3].size = ar531x_partitions[1].size-(ar531x_partitions[3].offset-0x30000);                                   
179                                         ar531x_partitions[6].offset=mymtd->size-mymtd->erasesize;
180                                         ar531x_partitions[5].offset=mymtd->size-(mymtd->erasesize*2);
181                                         ar531x_partitions[4].offset=mymtd->size-(mymtd->erasesize*3);
182                                         break;
183                                     }
184                             offset+=mymtd->erasesize;
185                             buf+=mymtd->erasesize;
186                             }
187                                 if (NUM_PARTITIONS != 0)
188                                 {
189                                     printk(KERN_NOTICE "Using ar531x DD-WRT partition definition\n");
190                                     add_mtd_partitions (mymtd, ar531x_partitions, NUM_PARTITIONS);
191                                 }
192
193                             }
194 #endif
195
196                 return 0;
197         }
198         iounmap ((void *)ar531x_map.virt);
199         return -ENXIO;
200 }
201
202 static void __exit cleanup_ar531x(void)
203 {
204         if (mymtd) {
205                 del_mtd_device(mymtd);
206                 map_destroy(mymtd);
207         }
208         if (ar531x_map.virt) {
209             iounmap ((void *)ar531x_map.virt);
210             ar531x_map.virt=0;
211         }
212 }
213
214 module_init(init_ar531x);
215 module_exit(cleanup_ar531x);
216
217
218 MODULE_LICENSE("GPL");
219 MODULE_AUTHOR("Tomas Dlabac");
220 MODULE_DESCRIPTION("Atheros AR531x MTD map driver");
Note: See TracBrowser for help on using the browser.