source: src/linux/universal/linux-4.9/drivers/mtd/maps/ralink-flash.c @ 31630

Last change on this file since 31630 was 31630, checked in by brainslayer, 7 weeks ago

new fs is compatible with standard squashfs, just smaller

File size: 13.3 KB
Line 
1/* ralink-flash.c
2 *
3 * Steven Liu <steven_liu@ralinktech.com.tw>:
4 *   - initial approach
5 *
6 * Winfred Lu <winfred_lu@ralinktech.com.tw>:
7 *   - 32MB flash support for RT3052
8 */
9
10#include <linux/module.h>
11#include <linux/types.h>
12#include <linux/init.h>
13#include <linux/kernel.h>
14#include <linux/slab.h>
15
16#include <asm/io.h>
17#include <linux/mtd/mtd.h>
18#include <linux/mtd/map.h>
19#include <linux/mtd/concat.h>
20#include <linux/mtd/partitions.h>
21#include <linux/vmalloc.h>
22#include <linux/magic.h>
23#include <linux/err.h>
24#include <asm/rt2880/rt_mmap.h>
25#include "../mtdcore.h"
26
27
28
29#ifdef CONFIG_RT2880_FLASH_8M
30        /* marklin 20080605 : return read mode for ST */
31extern void Flash_SetModeRead(void);
32#endif
33
34#ifndef CONFIG_RT2880_FLASH_32M
35#define WINDOW_ADDR             CONFIG_MTD_PHYSMAP_START
36#define WINDOW_SIZE             CONFIG_MTD_PHYSMAP_LEN
37#else
38#define WINDOW_ADDR_0           CONFIG_MTD_PHYSMAP_START
39#define WINDOW_ADDR_1           0xBB000000
40#define WINDOW_SIZE             (CONFIG_MTD_PHYSMAP_LEN / 2)
41#endif
42
43#define BUSWIDTH                CONFIG_MTD_PHYSMAP_BUSWIDTH
44static struct mtd_info *merged_mtd=NULL;
45static struct mtd_info *concat_mtd=NULL;
46
47
48#ifndef CONFIG_RT2880_FLASH_32M
49
50#if defined(CONFIG_RT2880_ASIC) && defined(CONFIG_RT2880_FLASH_8M)
51#define NUM_FLASH_BANKS 1
52
53static struct map_info ralink_map[] = {
54        {
55        .name = "Ralink SoC physically mapped flash bank 1",
56        .bankwidth = BUSWIDTH,
57        .size = CONFIG_MTD_PHYSMAP_LEN,
58        .phys = CONFIG_MTD_PHYSMAP_START
59        },
60};
61
62#else
63#define NUM_FLASH_BANKS 1
64
65static struct map_info ralink_map[] = {
66        {
67        .name = "Ralink SoC physically mapped flash",
68        .bankwidth = BUSWIDTH,
69        .size = CONFIG_MTD_PHYSMAP_LEN,
70        .phys = CONFIG_MTD_PHYSMAP_START
71        },
72};
73#endif
74
75
76#else
77#define NUM_FLASH_BANKS 2
78static struct map_info ralink_map[] = {
79        {
80        .name = "Ralink SoC physically mapped flash bank 0",
81        .bankwidth = BUSWIDTH,
82        .size = WINDOW_SIZE,
83        .phys = WINDOW_ADDR_0
84        },
85        {
86        .name = "Ralink SoC physically mapped flash bank 1",
87        .bankwidth = BUSWIDTH,
88        .size = WINDOW_SIZE,
89        .phys = WINDOW_ADDR_1
90        }
91};
92#endif
93static struct mtd_info *ralink_mtd[NUM_FLASH_BANKS];
94
95#if defined (CONFIG_RT2880_FLASH_32M) && defined (CONFIG_RALINK_RT3052_MP2)
96static struct mtd_partition rt2880_partitions[] = {
97        {
98                name:           "Bootloader",  /* mtdblock0 */
99                size:           0x40000,  /* 192K */
100                offset:         0,
101        }, {
102#ifdef CONFIG_RT2880_ROOTFS_IN_FLASH
103                name:           "Kernel", /* mtdblock3 */
104                size:           CONFIG_MTD_KERNEL_PART_SIZ,
105                offset:         MTDPART_OFS_APPEND,
106        }, {
107                name:           "RootFS", /* mtdblock4 */
108                size:           (0x2000000 - 0x80000 - CONFIG_MTD_KERNEL_PART_SIZ),
109                offset:         MTDPART_OFS_APPEND,
110        }, {
111#else //CONFIG_RT2880_ROOTFS_IN_RAM
112                name:           "Kernel", /* mtdblock3 */
113                size:           (0x2000000 - 0x80000),
114                offset:         MTDPART_OFS_APPEND,
115        }, {
116#endif
117                name:           "Config", /* mtdblock1 */
118                size:           0x20000,  /* 128K */
119                offset:         MTDPART_OFS_APPEND,
120                mask_flags:     MTD_WRITEABLE  /* force read-only */
121        }, {
122                name:           "Factory", /* mtdblock2 */
123                size:           0x20000,  /* 128K */
124                offset:         MTDPART_OFS_APPEND,
125                mask_flags:     MTD_WRITEABLE  /* force read-only */
126        }
127};
128#elif CONFIG_RT2880_FLASH_8M
129static struct mtd_partition rt2880_partitions[] = {
130        {
131                name:           "uboot",  /* mtdblock0 */
132                size:           0x30000,  /* 192K */
133                offset:         0x400000,
134        }, {
135                name:           "uboot-config", /* mtdblock1 */
136                size:           0x10000,  /* 64K */
137                offset:         MTDPART_OFS_APPEND,
138                mask_flags:     0x400000  /* force read-only */
139        }, {
140                name:           "factory-defaults", /* mtdblock2 */
141                size:           0x10000,  /* 64K */
142                offset:         MTDPART_OFS_APPEND,
143                mask_flags:     0x400000  /* force read-only */
144        }, {
145                name:           "linux", /* mtdblock3 */
146                size:           CONFIG_MTD_KERNEL_PART_SIZ,
147                offset:         0x450000,
148        }, {
149                name:           "rootfs", /* mtdblock4 */
150                size:           MTDPART_SIZ_FULL,
151                offset:         MTDPART_OFS_APPEND,
152        }, {
153                name:           "nvram", /* mtdblock4 */
154                size:           0x10000,
155                offset:         0x7e0000,
156        }};
157
158
159#else //not 32M flash
160static struct mtd_partition rt2880_partitions[] = {
161        {
162                name:           "uboot",  /* mtdblock0 */
163                size:           0x30000,  /* 192K */
164                offset:         0,
165        }, {
166                name:           "uboot-config", /* mtdblock1 */
167                size:           0x10000,  /* 64K */
168                offset:         MTDPART_OFS_APPEND,
169                mask_flags:     0  /* force read-only */
170        }, {
171                name:           "factory-defaults", /* mtdblock2 */
172                size:           0x10000,  /* 64K */
173                offset:         MTDPART_OFS_APPEND,
174                mask_flags:     0  /* force read-only */
175        }
176#ifdef CONFIG_MTD_AR670W
177, {
178                name:           "linux", /* mtdblock3 */
179                size:           CONFIG_MTD_KERNEL_PART_SIZ,
180                offset:         0x40000,
181        },
182#else
183, {
184                name:           "linux", /* mtdblock3 */
185                size:           CONFIG_MTD_KERNEL_PART_SIZ,
186                offset:         0x50000,
187        },
188#endif
189            {
190                name:           "rootfs", /* mtdblock4 */
191                size:           MTDPART_SIZ_FULL,
192                offset:         MTDPART_OFS_APPEND,
193        }, {
194                name:           "nvram", /* mtdblock4 */
195                size:           0x10000,
196                offset:         0x3f0000,
197        }};
198#endif
199
200
201static int ralink_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
202{
203        return 0;
204}
205
206static int ralink_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
207{
208        return 0;
209}
210#define BOOT_FROM_NOR   0
211#define BOOT_FROM_NAND  2
212#define BOOT_FROM_SPI   3
213
214
215int ra_check_flash_type(void)
216{
217
218    uint8_t Id[10];
219    int syscfg=0;
220    int boot_from=0;
221    int chip_mode=0;
222
223    memset(Id, 0, sizeof(Id));
224    strncpy(Id, (char *)RALINK_SYSCTL_BASE, 6);
225    syscfg = (*((int *)(RALINK_SYSCTL_BASE + 0x10)));
226    printk(KERN_INFO "system type: %s\n",Id);
227    if((strcmp(Id,"RT3052")==0) || (strcmp(Id, "RT3350")==0)) {
228        boot_from = (syscfg >> 16) & 0x3;
229        switch(boot_from)
230        {
231        case 0:
232        case 1:
233            boot_from=BOOT_FROM_NOR;
234            break;
235        case 2:
236            boot_from=BOOT_FROM_NAND;
237            break;
238        case 3:
239            boot_from=BOOT_FROM_SPI;
240            break;
241        }
242    }else if(strcmp(Id,"RT3883")==0) {
243        boot_from = (syscfg >> 4) & 0x3;
244        switch(boot_from)
245        {
246        case 0:
247        case 1:
248            boot_from=BOOT_FROM_NOR;
249            break;
250        case 2:
251        case 3:
252            chip_mode = syscfg & 0xF;
253            if((chip_mode==0) || (chip_mode==7)) {
254                boot_from = BOOT_FROM_SPI;
255            }else if(chip_mode==8) {
256                boot_from = BOOT_FROM_NAND;
257            }else {
258                printk("unknow chip_mode=%d\n",chip_mode);
259            }
260            break;
261        }
262    }else if(strcmp(Id,"RT3352")==0) {
263        boot_from = BOOT_FROM_SPI;
264    }else if(strcmp(Id,"RT5350")==0) {
265        boot_from = BOOT_FROM_SPI;
266    }else if(strcmp(Id,"RT2880")==0) {
267        boot_from = BOOT_FROM_NOR;
268    } else {
269        printk("%s: %s is not supported\n",__FUNCTION__, Id);
270    }
271    printk(KERN_INFO "boot type: %d\n",boot_from);
272    return boot_from;
273
274
275}
276
277
278int __init rt2880_mtd_init(void)
279{
280        int ret = -ENXIO;
281        int i, found = 0;
282
283        if(ra_check_flash_type()!=BOOT_FROM_NOR) { /* NOR */
284            return 0;
285        }
286
287        for (i = 0; i < NUM_FLASH_BANKS; i++) {
288                printk(KERN_NOTICE "ralink flash device: 0x%x at 0x%x\n",
289                                ralink_map[i].size, ralink_map[i].phys);
290
291                ralink_map[i].virt = ioremap(ralink_map[i].phys, ralink_map[i].size);
292                if (!ralink_map[i].virt) {
293                        printk("Failed to ioremap\n");
294                        return -EIO;
295                }
296                simple_map_init(&ralink_map[i]);
297                ralink_mtd[i] = do_map_probe("cfi_probe", &ralink_map[i]);
298                if (ralink_mtd[i]) {
299                        ralink_mtd[i]->owner = THIS_MODULE;
300                        ralink_mtd[i]->_lock = ralink_lock;
301                        ralink_mtd[i]->_unlock = ralink_unlock;
302                        ++found;
303                }
304                else
305                        iounmap(ralink_map[i].virt);
306        }
307        if (found == NUM_FLASH_BANKS) {
308#ifdef CONFIG_RT2880_FLASH_32M
309                merged_mtd = mtd_concat_create(ralink_mtd, NUM_FLASH_BANKS,
310                                "Ralink Merged Flash");
311                ret = add_mtd_partitions(merged_mtd, rt2880_partitions,
312                                ARRAY_SIZE(rt2880_partitions));
313#else
314#ifdef CONFIG_MTD_ESR6650
315int nvramsize = ralink_mtd[0]->erasesize*2;
316                int offset = 0;
317#elif CONFIG_EAP9550
318int nvramsize = ralink_mtd[0]->erasesize*2;
319                int offset = 0;
320#elif CONFIG_RT2880_FLASH_8M
321/* marklin 20080605 : return read mode for ST */
322Flash_SetModeRead();
323int nvramsize = ralink_mtd[0]->erasesize*2;
324                int offset = 0x400000;
325#else
326int nvramsize = ralink_mtd[0]->erasesize;
327                int offset = 0;
328#endif
329                char *buf = vmalloc(4096);
330                            while((offset+ralink_mtd[0]->erasesize)<ralink_mtd[0]->size)
331                            {
332                            int retlen;
333                            mtd_read(ralink_mtd[0],offset,4, &retlen, buf);
334//                          printk(KERN_EMERG "%X: %c %c %c %c\n",offset,buf[0],buf[1],buf[2],buf[3]);
335                            if (*((__u32 *) buf) == SQUASHFS_MAGIC)
336                                    {
337                                        printk(KERN_EMERG "\nfound squashfs at %X\n",offset);
338#ifdef CONFIG_RT2880_FLASH_8M
339                                        rt2880_partitions[3].size=(((ralink_mtd[0]->size)-nvramsize)-0x450000);                                 
340                                        rt2880_partitions[4].offset=offset;                                     
341                                        rt2880_partitions[4].size = rt2880_partitions[3].size-(offset-0x450000);                                       
342#else
343#ifdef CONFIG_MTD_AR670W
344                                        rt2880_partitions[3].size=(((ralink_mtd[0]->size)-nvramsize)-0x40000);                                 
345                                        rt2880_partitions[4].offset=offset;                                     
346                                        rt2880_partitions[4].size = rt2880_partitions[3].size-(offset-0x40000);                                 
347#else
348                                        rt2880_partitions[3].size=(((ralink_mtd[0]->size)-nvramsize)-0x50000);                                 
349                                        rt2880_partitions[4].offset=offset;                                     
350                                        rt2880_partitions[4].size = rt2880_partitions[3].size-(offset-0x50000);                                 
351#endif
352#endif
353                                        rt2880_partitions[5].offset=ralink_mtd[0]->size-nvramsize;                                     
354                                        rt2880_partitions[5].size = ralink_mtd[0]->erasesize;                                   
355                                        break;
356                                    }
357                            offset+=4096;
358                            }
359                vfree(buf);
360                ret = add_mtd_partitions(ralink_mtd[0], rt2880_partitions,ARRAY_SIZE(rt2880_partitions));
361#endif
362                if (ret) {
363                        for (i = 0; i < NUM_FLASH_BANKS; i++)
364                                iounmap(ralink_map[i].virt);
365                        return ret;
366                }
367        }
368        else {
369                printk("Error: %d flash device was found\n", found);
370                return -ENXIO;
371        }
372        return 0;
373}
374
375static void __exit rt2880_mtd_cleanup(void)
376{
377        int i;
378
379        if (merged_mtd) {
380                del_mtd_device(merged_mtd);
381                mtd_concat_destroy(merged_mtd);
382        }
383        for (i = 0; i < NUM_FLASH_BANKS; i++) {
384                if (ralink_mtd[i])
385                        map_destroy(ralink_mtd[i]);
386                if (ralink_map[i].virt) {
387                        iounmap(ralink_map[i].virt);
388                        ralink_map[i].virt = NULL;
389                }
390        }
391}
392
393module_init(rt2880_mtd_init);
394module_exit(rt2880_mtd_cleanup);
395
396MODULE_AUTHOR("Steven Liu <steven_liu@ralinktech.com.tw>");
397MODULE_DESCRIPTION("Ralink APSoC Flash Map");
398MODULE_LICENSE("GPL");
399
400
401/*
402 * Flash API: ra_mtd_read, ra_mtd_write
403 * Arguments:
404 *   - num: specific the mtd number
405 *   - to/from: the offset to read from or written to
406 *   - len: length
407 *   - buf: data to be read/written
408 * Returns:
409 *   - return -errno if failed
410 *   - return the number of bytes read/written if successed
411 */
412int ra_mtd_write(int num, loff_t to, size_t len, const u_char *buf)
413{
414        int ret = -1;
415        size_t rdlen, wrlen;
416        struct mtd_info *mtd;
417        struct erase_info ei;
418        u_char *bak = NULL;
419//      printk(KERN_EMERG "writing to partition %d, offset %d, len %d\n",num,to,len);
420#ifdef CONFIG_RT2880_FLASH_8M
421        /* marklin 20080605 : return read mode for ST */
422        Flash_SetModeRead();
423#endif
424
425        mtd = get_mtd_device(NULL, num);
426        if (IS_ERR(mtd))
427                return (int)mtd;
428        if (len > mtd->erasesize) {
429                put_mtd_device(mtd);
430                return -E2BIG;
431        }
432
433        bak = kmalloc(mtd->erasesize, GFP_KERNEL);
434        if (bak == NULL) {
435                put_mtd_device(mtd);
436                return -ENOMEM;
437        }
438
439        ret = mtd_read(mtd, 0, mtd->erasesize, &rdlen, bak);
440        if (ret != 0) {
441                put_mtd_device(mtd);
442                kfree(bak);
443                return ret;
444        }
445        if (rdlen != mtd->erasesize)
446                printk(KERN_EMERG "warning: ra_mtd_write: rdlen is not equal to erasesize\n");
447
448        memcpy(bak + to, buf, len);
449
450        ei.mtd = mtd;
451        ei.callback = NULL;
452        ei.addr = 0;
453        ei.len = mtd->erasesize;
454        ei.priv = 0;
455        ret = mtd_erase(mtd, &ei);
456        if (ret != 0) {
457                put_mtd_device(mtd);
458                kfree(bak);
459                return ret;
460        }
461
462        ret = mtd_write(mtd, 0, mtd->erasesize, &wrlen, bak);
463
464        put_mtd_device(mtd);
465        kfree(bak);
466#ifdef CONFIG_RT2880_FLASH_8M
467        /* marklin 20080605 : return read mode for ST */
468        Flash_SetModeRead();
469#endif
470        return ret;
471}
472
473int ra_mtd_read(int num, loff_t from, size_t len, u_char *buf)
474{
475        int ret;
476        size_t rdlen;
477        struct mtd_info *mtd;
478#ifdef CONFIG_RT2880_FLASH_8M
479        /* marklin 20080605 : return read mode for ST */
480        Flash_SetModeRead();
481#endif
482//      printk(KERN_EMERG "reading from partition %d, offset %d, len %d\n",num,from,len);
483        mtd = get_mtd_device(NULL, num);
484        if (IS_ERR(mtd))
485                return (int)mtd;
486
487        ret = mtd_read(mtd, from, len, &rdlen, buf);
488        if (rdlen != len)
489                printk(KERN_EMERG "warning: ra_mtd_read: rdlen is not equal to len\n");
490
491        put_mtd_device(mtd);
492        return ret;
493}
494
495EXPORT_SYMBOL(ra_mtd_write);
496EXPORT_SYMBOL(ra_mtd_read);
Note: See TracBrowser for help on using the repository browser.