source: src/linux/universal/linux-4.9/drivers/mtd/maps/ar531x_flash.c @ 31646

Last change on this file since 31646 was 31646, checked in by brainslayer, 3 months ago

its big endian

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