source: src/linux/universal/linux-3.10/drivers/mtd/devices/ar7240_flash.c @ 31672

Last change on this file since 31672 was 31672, checked in by brainslayer, 2 weeks ago

fix fs detection

File size: 16.2 KB
Line 
1/*
2 * This file contains glue for Atheros ar7100 spi flash interface
3 * Primitives are ar7100_spi_*
4 * mtd flash implements are ar7100_flash_*
5 */
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/types.h>
9#include <linux/errno.h>
10#include <linux/slab.h>
11#include <linux/mtd/mtd.h>
12#include <linux/mtd/partitions.h>
13#include "../mtdcore.h"
14#include <asm/delay.h>
15#include <asm/io.h>
16#include <linux/semaphore.h>
17#include <linux/squashfs_fs.h>
18
19#include "ar7240.h"
20#include "ar7240_flash.h"
21
22#define AR7240_SPI_CMD_WRITE_SR         0x01
23
24#define MXIC_JEDEC_ID        0xc2
25#define ATMEL_JEDEC_ID        0x1f
26#define SST_JEDEC_ID        0x20
27#define INTEL_JEDEC_ID        0x89
28#define WINB_JEDEC_ID        0xef
29
30
31#define MXIC_ENSO            0xb1
32#define MXIC_EXSO            0xc1
33
34
35
36
37//#define ATH_SST_FLASH 1
38/* this is passed in as a boot parameter by bootloader */
39//extern int __ath_flash_size;
40
41/*
42 * statics
43 */
44static void ar7240_spi_write_enable(void);
45static void ar7240_spi_poll(void);
46#if !defined(ATH_SST_FLASH)
47static void ar7240_spi_write_page(uint32_t addr, uint8_t * data, int len);
48#endif
49static void ar7240_spi_sector_erase(uint32_t addr);
50
51#define down mutex_lock
52#define up mutex_unlock
53#define init_MUTEX mutex_init
54#define DECLARE_MUTEX(a) struct mutex a
55
56static DECLARE_MUTEX(ar7240_flash_sem);
57
58/* GLOBAL FUNCTIONS */
59void ar7240_flash_spi_down(void)
60{
61//printk(KERN_EMERG "spi down\n");
62        down(&ar7240_flash_sem);
63}
64
65void ar7240_flash_spi_up(void)
66{
67//printk(KERN_EMERG "spi up\n");
68        up(&ar7240_flash_sem);
69}
70
71EXPORT_SYMBOL(ar7240_flash_spi_down);
72EXPORT_SYMBOL(ar7240_flash_spi_up);
73
74#define AR7240_FLASH_SIZE_2MB          (2*1024*1024)
75#define AR7240_FLASH_SIZE_4MB          (4*1024*1024)
76#define AR7240_FLASH_SIZE_8MB          (8*1024*1024)
77#define AR7240_FLASH_SIZE_16MB          (16*1024*1024)
78#ifndef ST25P28
79#define AR7240_FLASH_SECTOR_SIZE_64KB  (64*1024)
80#else
81#define AR7240_FLASH_SECTOR_SIZE_256KB  (256*1024)
82#endif
83#define AR7240_FLASH_SECTOR_SIZE_64KB  (64*1024)
84#define AR7240_FLASH_PG_SIZE_256B       256
85#define AR7240_FLASH_NAME               "ar7240-nor0"
86/*
87 * bank geometry
88 */
89typedef struct ar7240_flash_geom {
90        uint32_t size;
91        uint32_t sector_size;
92        uint32_t nsectors;
93        uint32_t pgsize;
94} ar7240_flash_geom_t;
95
96ar7240_flash_geom_t flash_geom_tbl[AR7240_FLASH_MAX_BANKS] = {
97        {
98#ifdef CONFIG_MTD_FLASH_16MB
99         .size = AR7240_FLASH_SIZE_16MB,
100#elif CONFIG_MTD_FLASH_8MB
101         .size = AR7240_FLASH_SIZE_8MB,
102#else
103         .size = AR7240_FLASH_SIZE_4MB,
104#endif
105         .sector_size = AR7240_FLASH_SECTOR_SIZE_64KB,
106         .pgsize = AR7240_FLASH_PG_SIZE_256B}
107};
108
109static int ar7240_flash_probe(void)
110{
111        return 0;
112}
113
114static int zcom=0;
115static int nocalibration=0;
116static unsigned int zcomoffset = 0;
117int guessbootsize(void *offset, unsigned int maxscan)
118{
119        unsigned int i,a;
120        unsigned char *ofsb = (unsigned char *)offset;
121        unsigned int *ofs = (unsigned int *)offset;
122        maxscan -= 0x20000;
123        maxscan /= 4;
124        zcom=0;
125        if (!strncmp((char *)(ofsb + 0x29da), "myloram.bin", 11) || !strncmp((char *)(ofsb + 0x2aba), "myloram.bin", 11)) {
126                printk(KERN_EMERG "compex WP72E detected\n");
127                nocalibration=1;
128                return 0x30000; // compex, lzma image
129        }
130
131        for (i = 0; i < maxscan; i += 16384) {
132                if (ofs[i] == 0x6d000080) {
133                        printk(KERN_EMERG "redboot or compatible detected\n");
134                        return 0x70000; // redboot, lzma image
135                }
136                if (ofs[i] == 0x5ea3a417) {
137                        printk(KERN_EMERG "alpha SEAMA found\n");
138                        return i * 4;   // redboot, lzma image
139                }
140                if (ofs[i] == 0x27051956) {
141                        printk(KERN_EMERG "uboot detected\n");
142                        return i * 4;   // uboot, lzma image
143                }
144                if (ofs[i] == 0x77617061) {
145                        printk(KERN_EMERG "DAP3662 bootloader\n");
146                        return 0x70000; // uboot, lzma image
147                }
148                if (ofs[i] == 0x7761706e) {
149                        printk(KERN_EMERG "DAP2230 bootloader\n");
150                        return 0x70000; // uboot, lzma image
151                }
152                if (ofs[i] == 0x32303033) {
153                        printk(KERN_EMERG "WNR2000 uboot detected\n");
154                        return 0x50000; // uboot, lzma image
155                }
156                if (ofs[i] == 0x32323030) {
157                        printk(KERN_EMERG "WNR2200 uboot detected\n");
158                        return 0x50000; // uboot, lzma image
159                }
160                if (ofs[i] == 0x01000000 && ofs[i+1] == 0x44442d57) {
161                        printk(KERN_EMERG "tplink uboot detected\n");
162                        return i * 4;   // uboot, lzma image
163                }
164                if (ofs[i + 15] == 0x27051956) {
165                        printk(KERN_EMERG "WRT160NL uboot detected\n");
166                        return i * 4;   // uboot, lzma image
167                }
168                if (ofs[i] == SQUASHFS_MAGIC_SWAP) {
169                        printk(KERN_EMERG "ZCom quirk found\n");
170                        zcom=1;
171                        for (a = i; a < maxscan; a += 16384) {
172                                        if (ofs[a] == 0x27051956) {
173                                            printk(KERN_EMERG "ZCom quirk kernel offset %d\n",a*4);
174                                            zcomoffset = a * 4;
175                                        }
176       
177                        }
178                        return i * 4;   // filesys starts earlier
179                }
180               
181        }
182        return -1;
183}
184
185static unsigned int guessflashsize(void *base)
186{
187        unsigned int size;
188        unsigned int *guess = (unsigned int *)base;
189        unsigned int max = 16 << 20;
190//check 3 patterns since we can't write.
191        unsigned int p1 = guess[0];
192        unsigned int p2 = guess[4096];
193        unsigned int p3 = guess[8192];
194        unsigned int c1;
195        unsigned int c2;
196        unsigned int c3;
197        for (size = 2 << 20; size <= (max >> 1); size <<= 1) {
198                unsigned int ofs = size / 4;
199                c1 = guess[ofs];
200                c2 = guess[ofs + 4096];
201                c3 = guess[ofs + 8192];
202                if (p1 == c1 && p2 == c2 && p3 == c3)   // mirror found
203                {
204                        break;
205                }
206        }
207        printk(KERN_EMERG "guessed flashsize = %dM\n", size >> 20);
208        return size;
209
210}
211
212static void
213ar7240_spi_flash_unblock(void)
214{
215        ar7240_spi_write_enable();
216        ar7240_spi_bit_banger(AR7240_SPI_CMD_WRITE_SR);
217        ar7240_spi_bit_banger(0x0);
218        ar7240_spi_go();
219        ar7240_spi_poll();
220}
221
222/*
223Before we claim the SPI driver we need to clean up any work in progress we have
224pre-empted from user-space SPI or other SPI device drivers.
225*/
226static int
227ar7424_flash_spi_reset(void) {
228        /* Enable SPI writes and retrieved flash JEDEC ID */
229        u_int32_t mfrid = 0;
230        ar7240_reg_wr_nf(AR7240_SPI_FS, 1);
231        ar7240_spi_poll();
232        ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
233        ar7240_spi_bit_banger(AR7240_SPI_CMD_RDID);
234        ar7240_spi_bit_banger(0x0);
235        ar7240_spi_bit_banger(0x0);
236        ar7240_spi_bit_banger(0x0);
237        mfrid = ar7240_reg_rd(AR7240_SPI_RD_STATUS) & 0x00ffffff;
238        ar7240_spi_go();
239        /* If this is an MXIC flash, be sure we are not in secure area */
240       
241        mfrid >>=16;
242        if(mfrid == MXIC_JEDEC_ID) {
243                /* Exit secure area of MXIC (in case we're in it) */
244                ar7240_spi_bit_banger(MXIC_EXSO);
245                ar7240_spi_go();
246        }
247        ar7240_spi_poll();
248        if(mfrid == MXIC_JEDEC_ID || mfrid == ATMEL_JEDEC_ID || mfrid == WINB_JEDEC_ID || mfrid == INTEL_JEDEC_ID || mfrid == SST_JEDEC_ID) {
249                    ar7240_spi_flash_unblock(); // required to unblock software protection mode by ubiquiti (consider that gpl did not release this in theires gpl sources. likelly to fuck up developers)
250        }
251        ar7240_reg_wr(AR7240_SPI_FS, 0);
252}
253
254
255static int ar7240_flash_erase(struct mtd_info *mtd, struct erase_info *instr)
256{
257        int nsect, s_curr, s_last;
258        uint64_t  res;
259        if (instr->addr + instr->len > mtd->size) {
260                return (-EINVAL);
261        }
262//    MY_WRITE(0xb8040028, (ar7240_reg_rd(0xb8040028) | 0x48002));
263
264//    MY_WRITE(0xb8040008, 0x2f);
265
266        ar7240_flash_spi_down();
267        preempt_disable();
268        ar7424_flash_spi_reset();
269
270        res = instr->len;
271        do_div(res, mtd->erasesize);
272        nsect = res;
273        if (((uint32_t)instr->len) % mtd->erasesize)
274                nsect++;
275
276        res = instr->addr;
277        do_div(res,mtd->erasesize);
278        s_curr = res;
279        s_last = s_curr + nsect;
280
281        do {
282                ar7240_spi_sector_erase(s_curr * AR7240_SPI_SECTOR_SIZE);
283        } while (++s_curr < s_last);
284
285        ar7240_spi_done();
286
287        preempt_enable();
288        ar7240_flash_spi_up();
289
290        if (instr->callback) {
291                instr->state = MTD_ERASE_DONE;
292                instr->callback(instr);
293        }
294        return 0;
295}
296
297static int
298ar7240_flash_read(struct mtd_info *mtd, loff_t from, size_t len,
299                  size_t *retlen, u_char * buf)
300{
301        uint32_t addr = from | 0xbf000000;
302
303//      printk(KERN_EMERG "read block %X:%X\n",from,len);
304        if (!len)
305                return (0);
306        if (from + len > mtd->size)
307                return (-EINVAL);
308
309//      ar7240_flash_spi_down();
310        preempt_disable();
311        ar7424_flash_spi_reset();
312
313        memcpy(buf, (uint8_t *) (addr), len);
314        *retlen = len;
315
316        preempt_enable();
317//      ar7240_flash_spi_up();
318//      printk(KERN_EMERG "read block %X:%X done\n",from,len);
319
320        return 0;
321}
322
323#if defined(ATH_SST_FLASH)
324static int
325ar7240_flash_write(struct mtd_info *mtd, loff_t dst, size_t len,
326                   size_t * retlen, const u_char * src)
327{
328        uint32_t val;
329
330        //printk("write len: %lu dst: 0x%x src: %p\n", len, dst, src);
331
332        *retlen = len;
333
334        for (; len; len--, dst++, src++) {
335                ar7240_spi_write_enable();      // dont move this above 'for'
336                ar7240_spi_bit_banger(AR7240_SPI_CMD_PAGE_PROG);
337                ar7240_spi_send_addr(dst);
338
339                val = *src & 0xff;
340                ar7240_spi_bit_banger(val);
341
342                ar7240_spi_go();
343                ar7240_spi_poll();
344        }
345        /*
346         * Disable the Function Select
347         * Without this we can't re-read the written data
348         */
349        ar7240_reg_wr(AR7240_SPI_FS, 0);
350
351        if (len) {
352                *retlen -= len;
353                return -EIO;
354        }
355        return 0;
356}
357#else
358static int
359ar7240_flash_write(struct mtd_info *mtd, loff_t to, size_t len,
360                   size_t *retlen, const u_char *buf)
361{
362        int total = 0, len_this_lp, bytes_this_page;
363        uint32_t addr = 0;
364        u_char *mem;
365
366        ar7240_flash_spi_down();
367        preempt_disable();
368        ar7424_flash_spi_reset();
369
370        while (total < len) {
371                mem = (u_char *) (buf + total);
372                addr = to + total;
373                bytes_this_page =
374                    AR7240_SPI_PAGE_SIZE - (addr % AR7240_SPI_PAGE_SIZE);
375                len_this_lp = min(((int)len - total), bytes_this_page);
376
377                ar7240_spi_write_page(addr, mem, len_this_lp);
378                total += len_this_lp;
379        }
380
381        ar7240_spi_done();
382
383        preempt_enable();
384        ar7240_flash_spi_up();
385
386        *retlen = len;
387        return 0;
388}
389#endif
390
391static struct mtd_partition dir_parts[] = {
392#ifdef CONFIG_MTD_FLASH_16MB
393      {name: "RedBoot", offset: 0x30000, size:0x10000,},
394        //, mask_flags: MTD_WRITEABLE, },
395      {name: "linux", offset: 0x50000, size:0xf90000,},
396#elif CONFIG_MTD_FLASH_8MB
397      {name: "RedBoot", offset: 0x30000, size:0x10000,},
398        //, mask_flags: MTD_WRITEABLE, },
399      {name: "linux", offset: 0x50000, size:0x790000,},
400#else
401      {name: "RedBoot", offset: 0, size:0x40000,},
402        //, mask_flags: MTD_WRITEABLE, },
403      {name: "linux", offset: 0x40000, size:0x3a0000,},
404#endif
405      {name: "rootfs", offset: 0x0, size:0x2b0000,},
406        //must be detected
407      {name: "ddwrt", offset: 0x0, size:0x2b0000,},
408        //must be detected
409      {name: "nvram", offset: 0x3d0000, size:0x10000,},
410      {name: "board_config", offset: 0x3f0000, size:0x10000,},
411      {name: "fullflash", offset: 0x3f0000, size:0x10000,},
412      {name: "fullboot", offset: 0, size:0x30000,},
413      {name: "uboot-env", offset: 0x40000, size:0x10000,},
414      {name:NULL,},
415};
416
417struct fis_image_desc {
418        unsigned char name[16]; // Null terminated name
419        unsigned long flash_base;       // Address within FLASH of image
420        unsigned long mem_base; // Address in memory where it executes
421        unsigned long size;     // Length of image
422        unsigned long entry_point;      // Execution entry point
423        unsigned long data_length;      // Length of actual data
424        unsigned char _pad[256 - (16 + 7 * sizeof(unsigned long))];
425        unsigned long desc_cksum;       // Checksum over image descriptor
426        unsigned long file_cksum;       // Checksum over image data
427};
428
429/*
430 * sets up flash_info and returns size of FLASH (bytes)
431 */
432static int __init ar7240_flash_init(void)
433{
434        int i;
435        ar7240_flash_geom_t *geom;
436        struct mtd_info *mtd;
437        uint8_t index;
438        int result = -1;
439        char *buf;
440        int offset = 0;
441        struct squashfs_super_block *sb;
442        size_t rootsize;
443        size_t len;
444        int fsize;
445        int inc=0;
446        init_MUTEX(&ar7240_flash_sem);
447
448
449#if defined(ATH_SST_FLASH)
450        ar7240_reg_wr_nf(AR7240_SPI_CLOCK, 0x3);
451        ar7240_reg_wr(AR7240_SPI_FS, 0);
452        ar7240_spi_flash_unblock();
453#else
454#ifndef CONFIG_WASP_SUPPORT
455        ar7240_reg_wr_nf(AR7240_SPI_CLOCK, 0x43);
456#endif
457#endif
458        buf = (char *)0xbf000000;
459        fsize = guessflashsize(buf);
460        for (i = 0; i < AR7240_FLASH_MAX_BANKS; i++) {
461
462                index = ar7240_flash_probe();
463                geom = &flash_geom_tbl[index];
464
465                /* set flash size to value from bootloader if it passed valid value */
466                /* otherwise use the default 4MB.                                   */
467                //if (__ath_flash_size >= 4 && __ath_flash_size <= 16)
468                //    geom->size = __ath_flash_size * 1024 * 1024;
469
470                mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
471                if (!mtd) {
472                        printk("Cant allocate mtd stuff\n");
473                        return -1;
474                }
475                memset(mtd, 0, sizeof(struct mtd_info));
476
477                mtd->name = AR7240_FLASH_NAME;
478                mtd->type = MTD_NORFLASH;
479                mtd->flags = (MTD_CAP_NORFLASH | MTD_WRITEABLE);
480                mtd->size = fsize;
481                mtd->erasesize = geom->sector_size;
482                mtd->numeraseregions = 0;
483                mtd->eraseregions = NULL;
484                mtd->owner = THIS_MODULE;
485                mtd->_erase = ar7240_flash_erase;
486                mtd->_read = ar7240_flash_read;
487                mtd->_write = ar7240_flash_write;
488
489                printk(KERN_EMERG "scanning for root partition\n");
490
491                offset = 0;
492
493                int guess = guessbootsize(buf, mtd->size);
494                if (guess > 0) {
495                        printk(KERN_EMERG "guessed bootloader size = %X\n",
496                               guess);
497                        dir_parts[0].offset = 0;
498                        dir_parts[0].size = guess;                     
499                        dir_parts[7].size = guess;
500                        dir_parts[1].offset = guess;
501                        dir_parts[1].size = 0;
502                        dir_parts[8].offset = guess - mtd->erasesize;
503                        dir_parts[8].size = mtd->erasesize;
504                }
505                while ((offset + mtd->erasesize) < mtd->size) {
506//                      printk(KERN_EMERG "[0x%08X] = [0x%08X]!=[0x%08X]\n",offset,*((unsigned int *) buf),SQUASHFS_MAGIC);
507                        __u32 *check2 = (__u32 *)&buf[0x60];   
508                        __u32 *check3 = (__u32 *)&buf[0xc0];   
509                        if (*((__u32 *)buf) == SQUASHFS_MAGIC_SWAP || *check2 == SQUASHFS_MAGIC_SWAP || *check3 == SQUASHFS_MAGIC_SWAP) {
510                                printk(KERN_EMERG "\nfound squashfs at %X\n",
511                                       offset);
512                                if (*check2 == SQUASHFS_MAGIC_SWAP) {
513                                    buf+=0x60;
514                                    offset +=0x60;
515                                    inc = 0x60;
516                                }
517                                if (*check3 == SQUASHFS_MAGIC_SWAP) {
518                                    buf+=0xC0;
519                                    offset +=0xC0;
520                                    inc = 0xc0;
521                                }
522                                sb = (struct squashfs_super_block *)buf;
523                                dir_parts[2].offset = offset;
524
525                               
526                                dir_parts[2].size = le64_to_cpu(sb->bytes_used);
527                                size_t origlen = dir_parts[2].offset + dir_parts[2].size;
528                               
529                                len = dir_parts[2].offset + dir_parts[2].size;
530                                len += (mtd->erasesize - 1);
531                                len &= ~(mtd->erasesize - 1);
532                                printk(KERN_INFO "adjusted length %X, original length %X\n",len,origlen);
533                                if ((len - (inc + 4096)) < origlen)
534                                        len += mtd->erasesize;
535                                dir_parts[2].size = (len & 0x1ffffff) - dir_parts[2].offset;
536                               
537                                dir_parts[3].offset =
538                                    dir_parts[2].offset + dir_parts[2].size;
539
540                                dir_parts[5].offset = mtd->size - mtd->erasesize;       //fis config
541                                dir_parts[5].size = mtd->erasesize;
542                                #if (defined(CONFIG_DIR825C1) && !defined(CONFIG_WDR4300) && !defined(CONFIG_WR1043V2) && !defined(CONFIG_WR841V8) && !defined(CONFIG_UBNTXW)) || defined(CONFIG_DIR862)
543                                dir_parts[4].offset = dir_parts[5].offset - (mtd->erasesize*2); //nvram
544                                dir_parts[4].size = mtd->erasesize;
545                                #else
546                                dir_parts[4].offset = dir_parts[5].offset - (mtd->erasesize - (nocalibration * mtd->erasesize));        //nvram
547                                dir_parts[4].size = mtd->erasesize;
548                                #endif
549                                dir_parts[3].size =
550                                    dir_parts[4].offset - dir_parts[3].offset;
551                                rootsize = dir_parts[4].offset - offset;        //size of rootfs aligned to nvram offset
552                                dir_parts[1].size =
553                                    (dir_parts[2].offset -
554                                     dir_parts[1].offset) + rootsize;
555                                //now scan for linux offset
556                                break;
557                        }
558                        offset += 4096;
559                        buf += 4096;
560                }
561                dir_parts[6].offset = 0;        // linux + nvram = phy size
562                dir_parts[6].size = mtd->size;  // linux + nvram = phy size
563                result = add_mtd_partitions(mtd, dir_parts, 9);
564        }
565
566        return 0;
567}
568
569static void __exit ar7240_flash_exit(void)
570{
571        /*
572         * nothing to do
573         */
574}
575
576/*
577 * Primitives to implement flash operations
578 */
579static void ar7240_spi_write_enable()
580{
581        ar7240_reg_wr_nf(AR7240_SPI_FS, 1);
582        ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
583        ar7240_spi_bit_banger(AR7240_SPI_CMD_WREN);
584        ar7240_spi_go();
585}
586
587static void ar7240_spi_poll()
588{
589        int rd;
590
591        do {
592                ar7240_reg_wr_nf(AR7240_SPI_WRITE, AR7240_SPI_CS_DIS);
593                ar7240_spi_bit_banger(AR7240_SPI_CMD_RD_STATUS);
594                ar7240_spi_delay_8();
595                rd = (ar7240_reg_rd(AR7240_SPI_RD_STATUS) & 1);
596        } while (rd);
597}
598
599static void ar7240_spi_write_page(uint32_t addr, uint8_t * data, int len)
600{
601        int i;
602        uint8_t ch;
603
604        ar7240_spi_write_enable();
605        ar7240_spi_bit_banger(AR7240_SPI_CMD_PAGE_PROG);
606        ar7240_spi_send_addr(addr);
607
608        for (i = 0; i < len; i++) {
609                ch = *(data + i);
610                ar7240_spi_bit_banger(ch);
611        }
612
613        ar7240_spi_go();
614        ar7240_spi_poll();
615}
616
617static void ar7240_spi_sector_erase(uint32_t addr)
618{
619        ar7240_spi_write_enable();
620        ar7240_spi_bit_banger(AR7240_SPI_CMD_SECTOR_ERASE);
621        ar7240_spi_send_addr(addr);
622        ar7240_spi_go();
623//    display(0x7d);
624        ar7240_spi_poll();
625}
626
627module_init(ar7240_flash_init);
628module_exit(ar7240_flash_exit);
Note: See TracBrowser for help on using the repository browser.