source: src/linux/sl2312/linux-2.6.23/drivers/mtd/maps/sl2312-flash-cfi.c @ 9980

Last change on this file since 9980 was 9980, checked in by BrainSlayer, 5 years ago

delete broken commit

File size: 9.4 KB
Line 
1/*======================================================================
2
3   This program is free software; you can redistribute it and/or modify
4   it under the terms of the GNU General Public License as published by
5   the Free Software Foundation; either version 2 of the License, or
6   (at your option) any later version.
7
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   GNU General Public License for more details.
12
13   You should have received a copy of the GNU General Public License
14   along with this program; if not, write to the Free Software
15   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16======================================================================*/
17
18#include <linux/module.h>
19#include <linux/types.h>
20#include <linux/kernel.h>
21#include <linux/slab.h>
22#include <linux/ioport.h>
23#include <linux/init.h>
24#include <linux/string.h>
25
26#include <linux/mtd/mtd.h>
27#include <linux/mtd/map.h>
28#include <linux/mtd/partitions.h>
29
30#include <asm/hardware.h>
31#include <asm/io.h>
32#include <asm/system.h>
33#include <asm/arch/sl2312.h>
34#include <linux/mtd/kvctl.h>
35#include "sl2312_flashmap.h"
36
37
38//extern int parse_afs_partitions(struct mtd_info *, struct mtd_partition **);
39
40/* the base address of FLASH control register */
41#define FLASH_CONTROL_BASE_ADDR     (IO_ADDRESS(SL2312_FLASH_CTRL_BASE))
42#define SL2312_GLOBAL_BASE_ADDR     (IO_ADDRESS(SL2312_GLOBAL_BASE))
43
44/* define read/write register utility */
45#define FLASH_READ_REG(offset)                  (__raw_readl(offset+FLASH_CONTROL_BASE_ADDR))
46#define FLASH_WRITE_REG(offset,val)     (__raw_writel(val,offset+FLASH_CONTROL_BASE_ADDR))
47
48/* the offset of FLASH control register */
49enum EMAC_REGISTER {
50        FLASH_ID        = 0x0000,
51        FLASH_STATUS    = 0x0008,
52        FLASH_TYPE      = 0x000c,
53        FLASH_ACCESS    = 0x0020,
54        FLASH_ADDRESS   = 0x0024,
55        FLASH_DATA              = 0x0028,
56        FLASH_TIMING    = 0x002c,
57};
58
59//#define FLASH_BASE    FLASH_CONTROL_BASE_ADDR
60//#define FLASH_SIZE    0x00800000 //INTEGRATOR_FLASH_SIZE
61
62//#define FLASH_PART_SIZE 8388608
63
64static unsigned int flash_indirect_access = 0;
65
66#ifdef CONFIG_SL2312_SHARE_PIN
67static unsigned int chip_en = 0x00000000;
68
69void sl2312flash_enable_parallel_flash(void)
70{
71    unsigned int    reg_val;
72
73    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
74    reg_val = reg_val & 0xfffffffd;
75    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
76    return;
77}
78
79void sl2312flash_disable_parallel_flash(void)
80{
81    unsigned int    reg_val;
82
83    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
84    reg_val = reg_val | 0x00000002;
85    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
86    return;
87}
88#endif
89
90
91static struct map_info sl2312flash_map =
92{
93        name:           "SL2312 CFI Flash",
94        size:       FLASH_SIZE,
95        bankwidth:   2,
96        //bankwidth:   1, //for 8 bits width
97    phys:       SL2312_FLASH_BASE,
98};
99
100static struct mtd_info *mtd;
101#if 0
102static struct mtd_partition sl2312_partitions[] = {
103        /* boot code */
104        {
105                name: "bootloader",
106                offset: 0x00000000,
107                size: 0x20000,
108//              mask_flags: MTD_WRITEABLE,
109        },
110        /* kernel image */
111        {
112                name: "kerel image",
113                offset: 0x00020000,
114                size: 0x2E0000
115        },
116        /* All else is writable (e.g. JFFS) */
117        {
118                name: "user data",
119                offset: 0x00300000,
120                size: 0x00100000,
121        }
122};
123#endif
124
125
126
127static int __init sl2312flash_init(void)
128{
129        struct mtd_partition *parts;
130        int nr_parts = 0;
131        int ret;
132#ifndef CONFIG_SL2312_SHARE_PIN
133    unsigned int    reg_val;
134#endif
135
136    printk("SL2312 MTD Driver Init.......\n");
137
138#ifndef CONFIG_SL2312_SHARE_PIN
139        /* enable flash */
140    reg_val = readl(SL2312_GLOBAL_BASE_ADDR + 0x30);
141    reg_val = reg_val & 0xfffffffd;
142    writel(reg_val,SL2312_GLOBAL_BASE_ADDR + 0x30);
143#else
144    sl2312flash_enable_parallel_flash();      /* enable Parallel FLASH */
145#endif
146    FLASH_WRITE_REG(FLASH_ACCESS,0x00004000); /* parallel flash direct access mode */
147    ret = FLASH_READ_REG(FLASH_ACCESS);
148    if (ret == 0x00004000)
149    {
150        flash_indirect_access = 0;  /* parallel flash direct access */
151    }
152    else
153    {
154        flash_indirect_access = 1;  /* parallel flash indirect access */
155    }
156
157        /*
158         * Also, the CFI layer automatically works out what size
159         * of chips we have, and does the necessary identification
160         * for us automatically.
161         */
162#ifdef CONFIG_GEMINI_IPI
163        sl2312flash_map.virt = FLASH_VBASE;//(unsigned int *)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
164#else
165        sl2312flash_map.virt = (unsigned int *)ioremap(SL2312_FLASH_BASE, FLASH_SIZE);
166#endif
167        //printk("sl2312flash_map.virt  = %08x\n",(unsigned int)sl2312flash_map.virt);
168
169//      simple_map_init(&sl2312flash_map);
170
171        mtd = do_map_probe("cfi_probe", &sl2312flash_map);
172        if (!mtd)
173        {
174#ifdef CONFIG_SL2312_SHARE_PIN
175        sl2312flash_disable_parallel_flash();      /* disable Parallel FLASH */
176#endif
177                return -ENXIO;
178        }
179        mtd->owner = THIS_MODULE;
180//    mtd->erase = flash_erase;
181//    mtd->read = flash_read;
182//    mtd->write = flash_write;
183
184    parts = sl2312_partitions;
185        nr_parts = sizeof(sl2312_partitions)/sizeof(*parts);
186        ret = add_mtd_partitions(mtd, parts, nr_parts);
187        /*If we got an error, free all resources.*/
188        if (ret < 0) {
189                del_mtd_partitions(mtd);
190                map_destroy(mtd);
191        }
192#ifdef CONFIG_SL2312_SHARE_PIN
193    sl2312flash_disable_parallel_flash();      /* disable Parallel FLASH */
194#endif
195    printk("SL2312 MTD Driver Init Success ......\n");
196        return ret;
197}
198
199static void __exit sl2312flash_exit(void)
200{
201        if (mtd) {
202                del_mtd_partitions(mtd);
203                map_destroy(mtd);
204        }
205
206        if (sl2312flash_map.virt) {
207            iounmap((void *)sl2312flash_map.virt);
208            sl2312flash_map.virt = 0;
209        }
210}
211
212char chrtohex(char c)
213{
214  char val;
215  if ((c >= '0') && (c <= '9'))
216  {
217    val = c - '0';
218    return val;
219  }
220  else if ((c >= 'a') && (c <= 'f'))
221  {
222    val = 10 + (c - 'a');
223    return val;
224  }
225  else if ((c >= 'A') && (c <= 'F'))
226  {
227    val = 10 + (c - 'A');
228    return val;
229  }
230  printk("<1>Error number\n");
231  return 0;
232}
233
234
235int get_vlaninfo(vlaninfo* vlan)
236{
237        vctl_mheader head;
238        vctl_entry entry;
239        struct mtd_info *mymtd=NULL;
240        int i, j, loc = 0;
241        char *payload=0, *tmp1, *tmp2, tmp3[9];
242        size_t retlen;
243
244        #ifdef CONFIG_SL2312_SHARE_PIN
245        sl2312flash_enable_parallel_flash();
246        #endif
247        for(i=0;i<MAX_MTD_DEVICES;i++)
248        {
249                mymtd=get_mtd_device(NULL,i);
250                //    printk("mymtd->name: %s\n", mymtd->name);
251                if(mymtd && !strcmp(mymtd->name,"VCTL"))
252                {
253                        //      printk("%s\n", mymtd->name);
254                        break;
255                }
256        }
257        if( i >= MAX_MTD_DEVICES)
258        {
259                printk("Can't find version control\n");
260                #ifdef CONFIG_SL2312_SHARE_PIN
261                sl2312flash_disable_parallel_flash();
262                #endif
263                return 0;
264        }
265
266        if (!mymtd | !mymtd->read)
267        {
268                printk("<1>Can't read Version Configuration\n");
269                #ifdef CONFIG_SL2312_SHARE_PIN
270                sl2312flash_disable_parallel_flash();
271                #endif
272                return 0;
273        }
274
275        mymtd->read(mymtd, 0, VCTL_HEAD_SIZE, &retlen, (u_char*)&head);
276        //  printk("entry header: %c%c%c%c\n", head.header[0], head.header[1], head.header[2], head.header[3]);
277        //  printk("entry number: %x\n", head.entry_num);
278        if ( strncmp(head.header, "FLFM", 4) )
279        {
280                printk("VCTL is a erase block\n");
281                #ifdef CONFIG_SL2312_SHARE_PIN
282                sl2312flash_disable_parallel_flash();
283                #endif
284                return 0;
285        }
286        loc += retlen;
287        for (i = 0; i < head.entry_num; i++)
288        {
289                mymtd->read(mymtd, loc, VCTL_ENTRY_LEN, &retlen, (u_char*)&entry);
290                //    printk("type: %x\n", entry.type);
291                //    printk("size: %x\n", entry.size);
292                strncpy(tmp3, entry.header, 4);
293                if (entry.type == VCT_VLAN)
294                {
295                        for (j = 0; j < 6 ; j++)
296                        {
297                                vlan[0].mac[j] = 0;
298                                vlan[1].mac[j] = 0;
299                        }
300                        vlan[0].vlanid = 1;
301                        vlan[1].vlanid = 2;
302                        vlan[0].vlanmap = 0x7F;
303                        vlan[1].vlanmap = 0x80;
304
305                        payload = (char *)kmalloc(entry.size - VCTL_ENTRY_LEN, GFP_KERNEL);
306                        loc += VCTL_ENTRY_LEN;
307                        mymtd->read(mymtd, loc, entry.size - VCTL_ENTRY_LEN, &retlen, payload);
308                        //      printk("%s\n", payload);
309                        tmp1 = strstr(payload, "MAC1:");
310                        tmp2 = strstr(payload, "MAC2:");
311                        if(!tmp1||!tmp2){
312                                kfree(payload);
313                                #ifdef CONFIG_SL2312_SHARE_PIN
314                                sl2312flash_disable_parallel_flash();
315                                #endif
316                                printk("Error VCTL format!!\n");
317                                return 0;
318                        }
319                        tmp1 += 7;
320                        tmp2 += 7;
321
322
323                        for (j = 0; j < 6; j++)
324                        {
325                                vlan[0].mac[j] = chrtohex(tmp1[2*j])*16 + chrtohex(tmp1[(2*j)+1]);
326                                vlan[1].mac[j] = chrtohex(tmp2[2*j])*16 + chrtohex(tmp2[(2*j)+1]);
327                        }
328                        tmp1 = strstr(payload, "ID1:");
329                        tmp2 = strstr(payload, "ID2:");
330                        tmp1 += 4;
331                        tmp2 += 4;
332                        vlan[0].vlanid = tmp1[0] - '0';
333                        vlan[1].vlanid = tmp2[0] - '0';
334                        tmp1 = strstr(payload, "MAP1:");
335                        tmp2 = strstr(payload, "MAP2:");
336                        tmp1 += 7;
337                        tmp2 += 7;
338                        vlan[0].vlanmap = chrtohex(tmp1[0]) * 16 + chrtohex(tmp1[1]);
339                        vlan[1].vlanmap = chrtohex(tmp2[0]) * 16 + chrtohex(tmp2[1]);
340                        //  printk("Vlan1 id:%x map:%02x mac:%x%x%x%x%x%x\n", vlan[0].vlanid, vlan[0].vlanmap, vlan[0].mac[0], vlan[0].mac[1], vlan[0].mac[2], vlan[0].mac[3], vlan[0].mac[4], vlan[0].mac[5]);
341                        //  printk("Vlan2 id:%x map:%02x mac:%x%x%x%x%x%x\n", vlan[1].vlanid, vlan[1].vlanmap, vlan[1].mac[0], vlan[1].mac[1], vlan[1].mac[2], vlan[1].mac[3], vlan[1].mac[4], vlan[1].mac[5]);
342                        break;
343                }
344                loc += entry.size;
345        }
346        if ( entry.type == VCT_VLAN )
347        {
348                #ifdef CONFIG_SL2312_SHARE_PIN
349                sl2312flash_disable_parallel_flash();
350                #endif
351                kfree(payload);
352                return 1;
353        }
354        if (i >= head.entry_num)
355        printk("Can't find vlan information\n");
356        #ifdef CONFIG_SL2312_SHARE_PIN
357        sl2312flash_disable_parallel_flash();
358        #endif
359        return 0;
360}
361
362EXPORT_SYMBOL(get_vlaninfo);
363
364
365module_init(sl2312flash_init);
366module_exit(sl2312flash_exit);
367
368MODULE_AUTHOR("Storlink Ltd");
369MODULE_DESCRIPTION("CFI map driver");
370MODULE_LICENSE("GPL");
Note: See TracBrowser for help on using the repository browser.