source: src/linux/universal/linux-4.9/drivers/mtd/devices/ar7240_flash.c @ 31630

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

new fs is compatible with standard squashfs, just smaller

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