source: src/linux/universal/linux-3.10/drivers/mtd/devices/wzrag300nh_flash.c @ 31660

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

use new squashfs in all kernels

File size: 23.8 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 "ar7100.h"
20#include "wzrag300nh_flash.h"
21
22#include <linux/proc_fs.h>
23
24/* this is passed in as a boot parameter by bootloader */
25extern int __ath_flash_size;
26
27#undef  AR7100_FLASH_MAX_BANKS
28#define AR7100_FLASH_MAX_BANKS  2
29/*
30 * statics
31 */
32static void ar7100_spi_write_enable(unsigned int cs);
33static void ar7100_spi_poll(unsigned int cs);
34static void ar7100_spi_fast_read(unsigned int cs, uint32_t addr, uint8_t *data, int len);
35static void ar7100_spi_read(unsigned int cs, uint32_t addr, uint8_t *data, int len);
36static void ar7100_spi_write_page(uint32_t addr, uint8_t *data, int len);
37static void ar7100_spi_sector_erase(uint32_t addr);
38
39
40
41static  __u32   _s_lastaddr     = 0;
42static  __u32   _f_lastwrite= 0;
43static  __u32   _f_init         = 1;
44static  __u32   _f_on           = 0;
45static  __u32   _s_jiffies      = 0;
46#define _S_OALASTADDR_MASK      0xFFFFC000      //16KBytes
47
48#define IS_NEW_SEQUENCE(F_WRITE)                ( ((F_WRITE)==0 && _f_lastwrite) || (jiffies-_s_jiffies)>(HZ/10) )
49
50#define DBGMSG(S)       do { printk(KERN_DEBUG "%s[%08lX]::%s\n", __FUNCTION__, jiffies, (S)); } while(0)
51
52#if 0// defined(CONFIG_MACH_AR7100)
53//#include      "asm/mach-ar7100/ar7100.h"
54#define DIAG_GPIO_NO                    (1<<1)
55#define DIAG_INIT(F_WRITE)              do { if(IS_NEW_SEQUENCE(F_WRITE)){_f_on=0;} while(_f_init) { ar7100_reg_rmw_set(AR7100_GPIO_OE, DIAG_GPIO_NO); _f_init=0; } } while(0)
56#define DIAG_ON()                               do { ar7100_reg_wr(AR7100_GPIO_CLEAR, DIAG_GPIO_NO); _s_jiffies=jiffies; } while(0)
57#define DIAG_OFF()                              do { ar7100_reg_wr(AR7100_GPIO_SET, DIAG_GPIO_NO); _s_jiffies=jiffies; } while(0)
58#define DIAG_BLINK()                    do { _f_on = (_f_on+1) & 0x1; if (_f_on) DIAG_ON(); else DIAG_OFF(); } while(0)
59
60#else   //defined  CONFIG_AR9100
61#define DIAG_GPIO_NO                    (1<<1)
62#define DIAG_INIT(F_WRITE)              do {  } while(0)
63#define DIAG_ON()                               do {  } while(0)
64#define DIAG_OFF()                              do {  } while(0)
65#define DIAG_BLINK()                    do {  } while(0)
66#endif  //defined  CONFIG_AR9100
67
68#define down mutex_lock
69#define up mutex_unlock
70#define init_MUTEX mutex_init
71#define DECLARE_MUTEX(a) struct mutex a
72
73
74static DECLARE_MUTEX(ar7100_flash_sem);
75
76/* GLOBAL FUNCTIONS */
77void
78ar7100_flash_spi_down(void) {
79  down(&ar7100_flash_sem);
80}
81
82void
83ar7100_flash_spi_up(void) {
84  up(&ar7100_flash_sem);
85}
86
87EXPORT_SYMBOL(ar7100_flash_spi_down);
88EXPORT_SYMBOL(ar7100_flash_spi_up);
89
90u_int32_t       g_buffalo_clock_div     = 3;
91u_int32_t       g_buffalo_current_div;
92
93static  u_int32_t       ar7100_cpu_freq = 0, ar7100_ahb_freq, ar7100_ddr_freq;
94
95static  void    get_ahb_clock(void)
96{
97    uint32_t pll, pll_div, cpu_div, ahb_div, ddr_div, freq;
98    pll = ar7100_reg_rd(AR7100_PLL_CONFIG);
99
100    pll_div  = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
101    freq     = pll_div * 40000000;
102    cpu_div  = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
103    ddr_div  = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
104    ahb_div  = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1)*2;
105
106    ar7100_cpu_freq = freq/cpu_div;
107    ar7100_ddr_freq = freq/ddr_div;
108    ar7100_ahb_freq = ar7100_cpu_freq/ahb_div;
109}
110
111static void     buffalo_spi_clock_update()
112{
113        if (g_buffalo_clock_div != g_buffalo_current_div) {
114                if (g_buffalo_clock_div>=0 && g_buffalo_clock_div<64) {
115                        u_int32_t       last_value;
116                        unsigned long flags;
117                        ar7100_flash_spi_down();
118
119
120                        ar7100_reg_wr(AR7100_SPI_FS, 1);
121
122                        last_value      = ar7100_reg_rd(AR7100_SPI_CLOCK) & 0x3f;
123
124                        //      write value
125                        ar7100_reg_wr_nf(AR7100_SPI_CLOCK, 0x40 | (g_buffalo_clock_div & 0x3f));
126                        g_buffalo_current_div   = ar7100_reg_rd(AR7100_SPI_CLOCK) & 0x3f;
127
128
129#define         AR7100_SPI_CMD_WRITE_SR 0x1
130                        ar7100_spi_write_enable(0);
131                        ar7100_spi_bit_banger(0, AR7100_SPI_CMD_WRITE_SR);
132                        ar7100_spi_bit_banger(0, 0x0);
133                        ar7100_spi_go(0);
134                        ar7100_spi_poll(0);
135
136                        ar7100_reg_wr(AR7100_SPI_FS, 0);
137
138#if     0
139                        {
140                                unsigned long flags;
141                                //      disable interrupts
142                                local_irq_save(flags);
143                                local_irq_disable();
144
145
146                                ar7100_reg_wr_nf(AR7100_PLL_CONFIG, (ar7100_reg_rd(AR7100_PLL_CONFIG) & (~((unsigned int)PLL_CONFIG_LOCKED_MASK))));
147                                ar7100_reg_wr_nf(AR7100_CPU_CLOCK_CONTROL, CLOCK_CONTROL_RST_SWITCH_MASK|CLOCK_CONTROL_CLOCK_SWITCH_MASK);
148                                ar7100_reg_rmw_clear(AR7100_CPU_CLOCK_CONTROL, CLOCK_CONTROL_RST_SWITCH_MASK);
149
150
151                                //      wait
152                                for ( ; 0==(ar7100_reg_rd(AR7100_PLL_CONFIG) & PLL_CONFIG_LOCKED_MASK) ; )
153                                        ;
154
155
156                                //      enable interrupts
157                                local_irq_enable();
158                                local_irq_restore(flags);
159                        }
160#endif
161
162
163
164                        //      read-back
165                        printk("SPI clock changed %d --> %d\n", ar7100_ahb_freq / (2 << last_value), ar7100_ahb_freq / (2 << g_buffalo_current_div));
166
167                        ar7100_flash_spi_up();
168                }
169        }
170}
171
172//
173//      for BUFFALO debug
174//
175static  int     atoi(const char *p)
176{
177        int             ret             = 0;
178        int             minus   = 0;
179        do      {
180                if (p==NULL)
181                        break;
182
183                for (; *p==' ' ; p++)
184                        ;
185
186                if (*p=='-') {
187                        minus   = 1;
188                        p++;
189                }
190
191                for (; p && *p>='0' && *p<='9' ; p++)
192                        ret     = (ret * 10) + (*p - '0');
193        } while(0);
194
195        return  (minus ? -ret : ret);
196}
197
198
199
200#define AR7100_FLASH_SIZE_2MB          (2*1024*1024)
201#define AR7100_FLASH_SIZE_4MB          (4*1024*1024)
202#define AR7100_FLASH_SIZE_8MB          (8*1024*1024)
203#define AR7100_FLASH_SIZE_16MB         (16*1024*1024)
204#define AR7100_FLASH_PG_SIZE_256B       256
205#ifndef ST25P28
206#define AR7100_FLASH_SECTOR_SIZE_64KB  (64*1024)
207#else
208#define AR7100_FLASH_SECTOR_SIZE_256KB  (256*1024)
209#endif
210
211#define AR7100_FLASH_SIZE_12MB         (12*1024*1024)
212#define AR7100_FLASH_SIZE_32MB         (32*1024*1024)
213
214#define AR7100_FLASH_NAME               "ar7100-nor0"
215/*
216 * bank geometry
217 */
218typedef struct ar7100_flash_geom {
219        const char *name;
220        u_int8_t         chip_id[3];
221    uint32_t     size;
222    uint32_t     sector_size;
223    uint32_t     nsectors;
224    uint32_t     pgsize;
225}ar7100_flash_geom_t;
226
227ar7100_flash_geom_t g_flash_geom_tbl[] = {
228                                        //      chip-id                                 dev-size        blk-siz         n-sec   page-siz
229          {     "S25FL064P",    { 0x01, 0x02, 0x16 },   0x00800000,     0x10000,           0,    256    }               //S25FL064P
230        , {     "M25P64V6P",    { 0x20, 0x20, 0x17 },   0x00800000,     0x10000,           0,    256    }               //S25FL064P
231        , {     "MX25L64-45E",  { 0xc2, 0x20, 0x17 },   0x00800000,     0x10000,           0,    256    }               //MX25L64-45E
232        , {     "MX25L128-45E", { 0xc2, 0x20, 0x18 },   0x01000000,     0x10000,           0,    256    }               //MX25L128-45E
233        , {     "W25Q128BV",    { 0xef, 0x40, 0x18 },   0x01000000,     0x10000,           0,    256    }               //W25Q128BV
234        , {     "S25FL128P",    { 0x01, 0x20, 0x18 },   0x01000000,     0x10000,           0,    256    }               //S25FL128P
235        , {     NULL,                   { 0x00, 0x00, 0x00 },   0x00000000,     0x00000,           0,      0    }               //dummy
236};
237
238ar7100_flash_geom_t     g_flash_geoms[AR7100_FLASH_MAX_BANKS];
239
240
241
242
243static struct mtd_partition dir_parts[] = {
244      {name: "RedBoot", offset: 0, size:0x50000,},
245      {name: "linux", offset: 0x60000, size:0x1f90000,},
246      {name: "rootfs", offset: 0x0, size:0x2b0000,},
247      {name: "ddwrt", offset: 0x0, size:0x2b0000,},
248      {name: "nvram", offset: 0x3d0000, size:0x10000,},
249      {name: "FIS directory", offset: 0x3e0000, size:0x10000,},
250      {name: "board_config", offset: 0x3f0000, size:0x10000,},
251      {name: "fullflash", offset: 0x3f0000, size:0x10000,},
252      {name: "uboot-env", offset: 0x40000, size:0x10000,},
253      {name:NULL,},
254};
255
256         
257static int
258ar7100_flash_probe()
259{
260    return 0;
261}
262
263static int
264ar7100_flash_erase(struct mtd_info *mtd,struct erase_info *instr)
265{
266    int nsect, s_curr, s_last;
267    uint64_t res;
268
269    if (instr->addr + instr->len > mtd->size) return (-EINVAL);
270
271    ar7100_flash_spi_down();
272
273
274        res = instr->len;
275        do_div(res, mtd->erasesize);
276        nsect = res;
277
278        if (((uint32_t)instr->len) % mtd->erasesize)
279                nsect++;
280
281
282        res = instr->addr;
283        do_div(res,mtd->erasesize);
284        s_curr = res;
285        s_last  = s_curr + nsect;
286
287    do {
288
289        ar7100_spi_sector_erase(s_curr * AR7100_SPI_SECTOR_SIZE);
290
291    } while (++s_curr < s_last);
292
293    ar7100_spi_done();
294
295
296    ar7100_flash_spi_up();
297
298    if (instr->callback) {
299        instr->state |= MTD_ERASE_DONE;
300        instr->callback (instr);
301    }
302
303
304
305    return 0;
306}
307
308static unsigned int     ar7100_spi_get_cs(unsigned int addr)
309{
310        if (g_flash_geoms[0].size) {
311                return  (g_flash_geoms[0].size <= addr);
312        } else {
313                return  (g_flash_geoms[1].size);
314        }
315}
316
317static int
318ar7100_flash_read_dmc(unsigned int cs, void *buf, size_t len)
319{
320        u_int8_t        *data   = buf;
321        size_t          i;
322        ar7100_flash_spi_down();
323
324        ar7100_reg_wr_nf(AR7100_SPI_FS, 1);
325        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);
326        ar7100_spi_bit_banger(cs,AR7100_SPI_CMD_READ_DMC);
327        ar7100_spi_delay_8(cs);
328//      ar7100_spi_delay_8(cs);
329//      ar7100_spi_delay_8(cs);
330
331        for (i=0; i<len ; i++, data++) {
332                ar7100_spi_delay_8(cs);
333                *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
334        }
335
336        ar7100_spi_done();
337
338        {
339                u_int8_t        msg[256];
340                size_t          msglen=0;
341                for (i=0 ; i<len ; i++) {
342                        if ((i%16)==0) {
343                                if (msglen)     printk("%s\n", msg);
344                                memset(msg,0,sizeof(msg));
345                                msglen  = sprintf(msg, "%04X : %02X", i, data[i]);
346                        } else {
347                                msglen  += sprintf(msg+msglen, " %02X", data[i]);
348                        }
349                }
350                if (msglen)     printk("%s\n", msg);
351        }
352
353        ar7100_flash_spi_up();
354
355        return  0;
356}
357
358static int
359ar7100_flash_read_manid(unsigned int cs, void *buf, size_t len)
360{
361        u_int8_t        *data   = buf;
362        size_t          i;
363        ar7100_flash_spi_down();
364
365        ar7100_reg_wr_nf(AR7100_SPI_FS, 1);
366        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);
367        ar7100_spi_bit_banger(cs,AR7100_SPI_CMD_READ_MANID);
368        ar7100_spi_send_addr(cs,0);
369//      ar7100_spi_delay_8(cs);
370
371        for (i=0; i<len ; i++, data++) {
372                ar7100_spi_delay_8(cs);
373                *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
374        }
375
376        ar7100_spi_done();
377
378        {
379                u_int8_t        msg[256];
380                size_t          msglen=0;
381                for (i=0, data=buf ; i<len ; i++) {
382                        if ((i%16)==0) {
383                                if (msglen)     printk("%s\n", msg);
384                                memset(msg,0,sizeof(msg));
385                                msglen  = sprintf(msg, "%04X : %02X", i, data[i]);
386                        } else {
387                                msglen  += sprintf(msg+msglen, " %02X", data[i]);
388                        }
389                }
390                if (msglen)     printk("%s\n", msg);
391        }
392
393        ar7100_flash_spi_up();
394
395        return  0;
396}
397
398static int
399ar7100_flash_read_id(unsigned int cs, void *buf, size_t len)
400{
401        u_int8_t        *data   = buf;
402        size_t          i;
403        ar7100_flash_spi_down();
404
405        ar7100_reg_wr_nf(AR7100_SPI_FS, 1);
406        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);
407        ar7100_spi_bit_banger(cs,AR7100_SPI_CMD_READ_ID);
408//      ar7100_spi_delay_8(cs);
409//      ar7100_spi_delay_8(cs);
410//      ar7100_spi_delay_8(cs);
411
412        for (i=0; i<len ; i++, data++) {
413                ar7100_spi_delay_8(cs);
414                *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
415        }
416
417        ar7100_spi_done();
418
419        {
420                u_int8_t        msg[256];
421                size_t          msglen=0;
422                for (data=buf, i=0 ; i<len ; i++) {
423                        if ((i%16)==0) {
424                                if (msglen)     printk("%s\n", msg);
425                                memset(msg,0,sizeof(msg));
426                                msglen  = sprintf(msg, "%04X : %02X", i, data[i]);
427                        } else {
428                                msglen  += sprintf(msg+msglen, " %02X", data[i]);
429                        }
430                }
431                if (msglen)     printk("%s\n", msg);
432        }
433
434        ar7100_flash_spi_up();
435
436        return  0;
437}
438
439static int
440ar7100_flash_read(struct mtd_info *mtd, loff_t from, size_t len,
441                  size_t *retlen ,u_char *buf)
442{
443    uint32_t addr0, addr1;
444    size_t      len0, len1;
445
446    if (!len) return (0);
447    if (from + len > mtd->size) return (-EINVAL);
448
449
450    ar7100_flash_spi_down();
451
452    if (ar7100_spi_get_cs(from)) {
453        len0    = 0;
454        addr0   = 0;
455        len1    = len;
456        addr1   = (from - g_flash_geoms[0].size) | 0xbe000000;
457    } else if (ar7100_spi_get_cs(from+len)) {
458        len0    = g_flash_geoms[0].size - from;
459        addr0   = from | 0xbf000000;
460        len1    = len - len0;
461        addr1   = 0xbe000000;
462    } else {
463        len0    = len;
464        addr0   = from | 0xbf000000;
465        len1    = 0;
466        addr1   = 0;
467    }
468        if (len0)       memcpy(buf, (uint8_t *)(addr0), len0);
469//      if (len1)       memcpy(buf+len0, (uint8_t *)(addr1), len1);
470//      if (len0)       ar7100_spi_fast_read(0, addr0, buf, len0);
471        if (len1)       ar7100_spi_fast_read(1, addr1, buf+len0, len1);
472//      if (len0)       ar7100_spi_read(0, addr0, buf, len0);
473//      if (len1)       ar7100_spi_read(1, addr1, buf+len0, len1);
474//      if (len1) {
475//              if (addr1 < 0xbe200000)  ar7100_spi_read(1, addr1, buf+len0, len1);
476//              else                                     ar7100_spi_fast_read(1, addr1, buf+len0, len1);
477//      }
478
479    *retlen = len;
480
481    ar7100_flash_spi_up();
482
483    return 0;
484}
485
486static int
487ar7100_flash_write (struct mtd_info *mtd, loff_t to, size_t len,
488                    size_t *retlen, const u_char *buf)
489{
490    int total = 0, len_this_lp, bytes_this_page;
491    uint32_t addr = 0;
492    u_char *mem;
493
494
495    ar7100_flash_spi_down();
496
497
498    while(total < len) {
499        mem              = buf + total;
500        addr             = to  + total;
501        bytes_this_page  = AR7100_SPI_PAGE_SIZE - (addr % AR7100_SPI_PAGE_SIZE);
502        len_this_lp      = min((len - total), bytes_this_page);
503
504
505        ar7100_spi_write_page(addr, mem, len_this_lp);
506        total += len_this_lp;
507
508    }
509
510    ar7100_spi_done();
511
512
513    ar7100_flash_spi_up();
514
515    *retlen = len;
516
517
518    return 0;
519}
520
521
522/*
523 * sets up flash_info and returns size of FLASH (bytes)
524 */
525static int __init ar7100_flash_init (void)
526{
527    int i, np;
528    ar7100_flash_geom_t *geom;
529    struct mtd_info *mtd;
530    struct mtd_partition *mtd_parts;
531    uint8_t index;
532
533    init_MUTEX(&ar7100_flash_sem);
534
535    //  enable cs#1
536    ar7100_reg_rmw_set(0xb8040028, (1 << 12));
537
538        //      enable clock changing
539        get_ahb_clock();
540//      buffalo_spi_clock_update();
541
542
543        printk("check spi banks %d\n", AR7100_FLASH_MAX_BANKS);
544
545
546        for(i = 0; i < AR7100_FLASH_MAX_BANKS; i++) {
547                u_int8_t        chip_id[3];
548                int                     j;
549
550                struct {                                                                                //      offset
551                        u_int8_t        man_id;                                                 //      00h
552                        u_int8_t        dev_id_0;                                               //      01h
553                        u_int8_t        dev_id_1;                                               //      02h
554                        u_int8_t        dev_id_2;                                               //      03h
555                        u_int8_t        pad1[0x10 - 0x04];                              //      04h - 0fh
556                        u_int8_t        qry[3];                                                 //      10h - 12h
557                        u_int8_t        cmdset_id[2];                                   //      13h - 14h
558                        u_int8_t        addr_table[2];                                  //      15h - 16h
559                        u_int8_t        oem_cmdset_id[2];                               //      17h - 18h
560                        u_int8_t        oem_addr_table[2];                              //      19h - 1ah
561                        u_int8_t        VccMin;                                                 //      1bh
562                        u_int8_t        VccMax;                                                 //      1ch
563                        u_int8_t        VppMin;                                                 //      1dh
564                        u_int8_t        VppMax;                                                 //      1eh
565                        u_int8_t        WordWriteTimeoutTyp;                    //      1fh
566                        u_int8_t        BufWriteTimeoutTyp;                             //      20h
567                        u_int8_t        BlockEraseTimeoutTyp;                   //      21h
568                        u_int8_t        ChipEraseTimeoutTyp;                    //      22h
569                        u_int8_t        WordWriteTimeoutMax;                    //      23h
570                        u_int8_t        BufWriteTimeoutMax;                             //      24h
571                        u_int8_t        BlockEraseTimeoutMax;                   //      25h
572                        u_int8_t        ChipEraseTimeoutMax;                    //      26h
573                        u_int8_t        DevSize;                                                //      27h
574                        u_int16_t       InterfaceDesc;                                  //      28h - 29h
575                        u_int16_t       MaxBufWriteSize;                                //      2ah - 2bh
576                        u_int8_t        NumEraseRegions;                                //      2ch
577                        struct {
578                                u_int8_t        nEraseNum;                                      //      2dh, 31h, 35h, 39h
579                                u_int8_t        nEraseSiz0;                                     //      2eh, 32h, 36h, 3ah
580                                u_int8_t        nEraseSiz1;                                     //      2fh, 33h, 37h, 3bh
581                                u_int8_t        nEraseSiz2;                                     //      30h, 34h, 38h, 3ch
582                        } EraseRegionInfo[4];
583                        u_int8_t        pad2[0x40 - 0x3d];                              //      3dh - 3fh
584                        u_int8_t        pri[3];                                                 //      40h - 42h
585                        u_int8_t        MajVer;                                                 //      43h
586                        u_int8_t        MinVer;                                                 //      44h
587                        u_int8_t        SupportUnlock;                                  //      45h
588                        u_int8_t        SupportEraseSuspend;                    //      46h
589                        u_int8_t        SupportSectorProtect;                   //      47h
590                        u_int8_t        SupportSectorUnprotect;                 //      48h
591                        u_int8_t        TypeSectorProtect;                              //      49h
592                        u_int8_t        TypeSimulaneousOpe;                             //      4ah
593                        u_int8_t        TypeBurstMode;                                  //      4bh
594                        u_int8_t        TypePageMode;                                   //      4ch
595                        u_int8_t        AccSupplyMin;                                   //      4dh
596                        u_int8_t        AccSupplyMax;                                   //      4eh
597                        u_int8_t        WriteProtection;                                //      4fh
598                        u_int8_t        SupportProgramSuspend;                  //      50h
599                } cfi_buf;
600
601#if     0
602                struct  {
603                        u_int32_t       dmc_signature;                                  //      00h - 03h       0x50444653
604                        u_int8_t        dmc_MinVer;
605                        u_int8_t        dmc_MajVer;
606                        u_int8_t        nHeader;                                                //      06h
607                        u_int8_t        pad1[1];                                                //      07h
608                        u_int8_t        ;                                                               //      00h
609                        u_int8_t        ;                                                               //      00h
610                        u_int8_t        ;                                                               //      00h
611                        u_int8_t        ;                                                               //      00h
612                        u_int8_t        ;                                                               //      00h
613                        u_int8_t        ;                                                               //      00h
614                        u_int8_t        ;                                                               //      00h
615                        u_int8_t        ;                                                               //      00h
616                        u_int8_t        ;                                                               //      00h
617
618                } dmc_buf;
619#endif
620
621                memset(&chip_id[0], 0, sizeof(chip_id));
622                ar7100_flash_read_id(i, &chip_id[0], sizeof(chip_id));
623
624                for (j=0 ; j<sizeof(g_flash_geom_tbl)/sizeof(g_flash_geom_tbl[0]) ; j++) {
625                        if (memcmp(g_flash_geom_tbl[j].chip_id, chip_id, sizeof(g_flash_geom_tbl[j].chip_id))==0) {
626                                if (g_flash_geom_tbl[j].name) {
627                                        printk("found %s device on bank#%d\n", g_flash_geom_tbl[j].name, i);
628                                        g_flash_geoms[i]        = g_flash_geom_tbl[j];
629                                        if (g_flash_geoms[i].sector_size!=0 && g_flash_geoms[i].nsectors==0)
630                                                g_flash_geoms[i].nsectors       = g_flash_geoms[i].size / g_flash_geoms[i].sector_size;
631                                        break;
632                                }
633                        }
634                }
635
636#if     0
637                ar7100_flash_read_manid(i, &cfi_buf, sizeof(cfi_buf));
638                memset(&cfi_buf, 0, sizeof(cfi_buf));
639                ar7100_flash_read_id(i, &cfi_buf, sizeof(cfi_buf));
640                if (cfi_buf.qry[0]=='Q' && cfi_buf.qry[1]=='R' && cfi_buf.qry[2]=='Y') {
641                        g_flash_geoms[i].size                   = 2 << cfi_buf.DevSize;
642                        g_flash_geoms[i].sector_size    = 64 * 1024;
643                        g_flash_geoms[i].nsectors               = g_flash_geoms[i].size / g_flash_geoms[i].sector_size;
644                        g_flash_geoms[i].pgsize                 = 2 << cfi_buf.MaxBufWriteSize;
645                }
646#endif
647        }
648        printk("SPI flash size total:%d Mbytes\n", (g_flash_geoms[0].size + g_flash_geoms[1].size) >> 20);
649
650        mtd         =  kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
651        if (!mtd) {
652                printk("Cant allocate mtd stuff\n");
653                return -1;
654        }
655        memset(mtd, 0, sizeof(struct mtd_info));
656
657        mtd->name               =   AR7100_FLASH_NAME;
658        mtd->type               =   MTD_NORFLASH;
659        mtd->flags              =   (MTD_CAP_NORFLASH|MTD_WRITEABLE);
660        mtd->size               =   g_flash_geoms[0].size + g_flash_geoms[1].size;
661        mtd->erasesize          =   g_flash_geoms[0].sector_size;
662        mtd->numeraseregions    =   0;
663        mtd->eraseregions       =   NULL;
664        mtd->owner              =   THIS_MODULE;
665        mtd->_erase              =   ar7100_flash_erase;
666        mtd->_read               =   ar7100_flash_read;
667        mtd->_write              =   ar7100_flash_write;
668        mtd->priv                               = g_flash_geoms;
669        int offset = 0;
670        struct squashfs_super_block *sb;
671
672        char buf[512];
673        int retlen;
674        unsigned int rootsize,len;
675
676                while ((offset + mtd->erasesize) < mtd->size) {
677                        mtd_read(mtd,offset,512,&retlen,&buf[0]);
678                        if (*((__u32 *)buf) == SQUASHFS_MAGIC_SWAP) {
679                                printk(KERN_EMERG "\nfound squashfs at %X\n",offset);
680                                sb = (struct squashfs_super_block *)buf;
681                                dir_parts[2].offset = offset;
682
683                                dir_parts[2].size = sb->bytes_used;
684                                len = dir_parts[2].offset + dir_parts[2].size;
685                                len += (mtd->erasesize - 1);
686                                len &= ~(mtd->erasesize - 1);
687                                dir_parts[2].size = (len & 0x1ffffff) - dir_parts[2].offset;
688                                dir_parts[3].offset = dir_parts[2].offset + dir_parts[2].size;
689                                dir_parts[6].offset = mtd->size - mtd->erasesize;       // board config
690                                dir_parts[6].size = mtd->erasesize;
691                                dir_parts[5].offset = dir_parts[6].offset;      //fis config
692                                dir_parts[5].size = mtd->erasesize;
693                                dir_parts[4].offset = dir_parts[5].offset - mtd->erasesize;     //nvram
694                                dir_parts[4].size = mtd->erasesize;
695                                dir_parts[3].size = dir_parts[4].offset - dir_parts[3].offset;
696                                rootsize = dir_parts[4].offset - offset;        //size of rootfs aligned to nvram offset
697                                dir_parts[1].size = (dir_parts[2].offset -dir_parts[1].offset) + rootsize;
698                                break;
699                        }
700                offset+=4096;
701                }
702                dir_parts[7].offset = 0;        // linux + nvram = phy size
703                dir_parts[7].size = mtd->size;  // linux + nvram = phy size
704                add_mtd_partitions(mtd, dir_parts, 9);
705
706    return 0;
707}
708
709static void __exit ar7100_flash_exit(void)
710{
711    /*
712     * nothing to do
713     */
714}
715
716
717/*
718 * Primitives to implement flash operations
719 */
720static void
721ar7100_spi_write_enable(unsigned int cs) 
722{
723    ar7100_reg_wr_nf(AR7100_SPI_FS, 1);                 
724    ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
725    ar7100_spi_bit_banger(cs,AR7100_SPI_CMD_WREN);             
726    ar7100_spi_go(cs);
727}
728
729static void
730ar7100_spi_read(unsigned int cs, uint32_t addr, uint8_t *data, int len)
731{
732
733        if (cs) {
734#if     1
735                ar7100_reg_wr_nf(AR7100_SPI_FS, 1);                 
736                for (; len>0 ; len--, addr++, data++) {
737                        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
738                        ar7100_spi_bit_banger_1(0x3);       
739                        ar7100_spi_send_addr(cs,addr);
740                        ar7100_spi_delay_8(cs);
741                        *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
742                }
743                ar7100_spi_done();
744#else
745#if     0
746                //      Ʊ€ž·ë²Ì
747                ar7100_reg_wr_nf(AR7100_SPI_FS, 1);                 
748        for (; len>0 ; len--, data++) {
749                ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
750                ar7100_spi_bit_banger_1(0x3);       
751                        ar7100_spi_send_addr(cs,addr);
752                        ar7100_spi_delay_8(cs);
753                        *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
754        }
755        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
756                ar7100_spi_done();
757#else
758                ar7100_reg_wr_nf(AR7100_SPI_FS, 1);                 
759        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
760        ar7100_spi_bit_banger_1(0x3);       
761                ar7100_spi_send_addr(cs,addr);
762                ar7100_spi_delay_8(cs);
763        for (; len>0 ; len--, data++) {
764                        *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
765        }
766        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
767                ar7100_spi_done();
768#endif
769#endif
770        } else {
771                ar7100_reg_wr_nf(AR7100_SPI_FS, 1);                 
772        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
773        ar7100_spi_bit_banger_0(0x3);       
774                ar7100_spi_send_addr(cs,addr);
775                ar7100_spi_delay_8(cs);
776        for (; len>0 ; len--, data++) {
777                        *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
778        }
779                ar7100_spi_done();
780        }
781}
782
783static void
784ar7100_spi_fast_read(unsigned int cs, uint32_t addr, uint8_t *data, int len)
785{
786
787        if (cs) {
788                ar7100_reg_wr_nf(AR7100_SPI_FS, 1);                 
789                ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
790                ar7100_spi_bit_banger_1(AR7100_SPI_CMD_FAST_READ);       
791                ar7100_spi_send_addr(cs,addr);
792                ar7100_spi_delay_8(cs);
793                for (; len>0 ; len--, data++) {
794                        ar7100_spi_delay_8(cs);
795                        *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
796                }
797                ar7100_spi_done();
798#if             0               //OK pattern
799                ar7100_reg_wr_nf(AR7100_SPI_FS, 1);                 
800                for (; len>0 ; len--, addr++, data++) {
801                        ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
802                        ar7100_spi_bit_banger_1(AR7100_SPI_CMD_FAST_READ);       
803                        ar7100_spi_send_addr(cs,addr);
804                        ar7100_spi_delay_8(cs);
805                        ar7100_spi_delay_8(cs);
806                        *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
807                }
808                ar7100_spi_done();
809#endif  //CONFIG_BUFFALO
810
811        } else {
812                ar7100_reg_wr_nf(AR7100_SPI_FS, 1);                 
813                ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
814                ar7100_spi_bit_banger_0(AR7100_SPI_CMD_FAST_READ);       
815                ar7100_spi_send_addr(cs,addr);
816                ar7100_spi_delay_8(cs);
817                for (; len>0 ; len--, data++) {
818                        ar7100_spi_delay_8(cs);
819                        *data   = (uint8_t)ar7100_reg_rd(AR7100_SPI_RD_STATUS);
820                }
821                ar7100_spi_done();
822        }
823}
824
825static void
826ar7100_spi_poll(unsigned int cs)   
827{
828    int rd;                                                 
829
830        if (cs) {
831            do {
832                ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
833                ar7100_spi_bit_banger_1(AR7100_SPI_CMD_RD_STATUS);       
834                ar7100_spi_delay_8(cs);
835                rd = (ar7100_reg_rd(AR7100_SPI_RD_STATUS) & 1);               
836            }while(rd);
837        } else {
838            do {
839                ar7100_reg_wr_nf(AR7100_SPI_WRITE, AR7100_SPI_CS_DIS);     
840                ar7100_spi_bit_banger_0(AR7100_SPI_CMD_RD_STATUS);       
841                ar7100_spi_delay_8(cs);
842                rd = (ar7100_reg_rd(AR7100_SPI_RD_STATUS) & 1);               
843            }while(rd);
844        }
845}
846
847static void
848ar7100_spi_write_page(uint32_t addr, uint8_t *data, int len)
849{
850    int i;
851    uint8_t ch;
852    unsigned int cs = ar7100_spi_get_cs(addr);
853
854    ar7100_spi_write_enable(cs);
855    ar7100_spi_bit_banger(cs,AR7100_SPI_CMD_PAGE_PROG);
856    ar7100_spi_send_addr(cs,addr);
857
858    if (cs) {
859            for(i = 0; i < len; i++) {
860                ch = *(data + i);
861                ar7100_spi_bit_banger_1(ch);
862            }
863    } else {
864            for(i = 0; i < len; i++) {
865                ch = *(data + i);
866                ar7100_spi_bit_banger_0(ch);
867            }
868    }
869
870
871    ar7100_spi_go(cs);
872    ar7100_spi_poll(cs);
873}
874
875static void
876ar7100_spi_sector_erase(uint32_t addr)
877{
878    unsigned int cs = ar7100_spi_get_cs(addr);
879    ar7100_spi_write_enable(cs);
880    ar7100_spi_bit_banger(cs,AR7100_SPI_CMD_SECTOR_ERASE);
881    ar7100_spi_send_addr(cs,addr);
882    ar7100_spi_go(cs);
883    ar7100_spi_poll(cs);
884}
885
886module_init(ar7100_flash_init);
887module_exit(ar7100_flash_exit);
Note: See TracBrowser for help on using the repository browser.