source: src/linux/universal/linux-3.5/drivers/mtd/devices/spiflash_selfmap.c @ 31660

Last change on this file since 31660 was 31660, checked in by brainslayer, 13 days ago

use new squashfs in all kernels

File size: 24.4 KB
Line 
1
2/*
3 * MTD driver for the SPI Flash Memory support.
4 *
5 * Copyright (c) 2005-2006 Atheros Communications Inc.
6 * Copyright (C) 2006-2007 FON Technology, SL.
7 * Copyright (C) 2006-2007 Imre Kaloz <kaloz@openwrt.org>
8 * Copyright (C) 2006-2007 Felix Fietkau <nbd@openwrt.org>
9 * Copyright (C) 2008 Sebastian Gottschall <s.gottschall@newmedia-net.de>
10 *
11 * This code is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 */
16
17/*===========================================================================
18** !!!!  VERY IMPORTANT NOTICE !!!!  FLASH DATA STORED IN LITTLE ENDIAN FORMAT
19**
20** This module contains the Serial Flash access routines for the Atheros SOC.
21** The Atheros SOC integrates a SPI flash controller that is used to access
22** serial flash parts. The SPI flash controller executes in "Little Endian"
23** mode. THEREFORE, all WRITES and READS from the MIPS CPU must be
24** BYTESWAPPED! The SPI Flash controller hardware by default performs READ
25** ONLY byteswapping when accessed via the SPI Flash Alias memory region
26** (Physical Address 0x0800_0000 - 0x0fff_ffff). The data stored in the
27** flash sectors is stored in "Little Endian" format.
28**
29** The spiflash_write() routine performs byteswapping on all write
30** operations.
31**===========================================================================*/
32
33#include <linux/kernel.h>
34#include <linux/module.h>
35#include <linux/types.h>
36#include <linux/version.h>
37#include <linux/errno.h>
38#include <linux/slab.h>
39#include <linux/mtd/mtd.h>
40#include <linux/mtd/partitions.h>
41#include <linux/platform_device.h>
42#include <linux/sched.h>
43#include <linux/squashfs_fs.h>
44#include <linux/root_dev.h>
45#include <linux/vmalloc.h>
46#include <linux/squashfs_fs.h>
47#include <linux/delay.h>
48#include <linux/proc_fs.h>
49#include <asm/delay.h>
50#include <asm/io.h>
51#include "spiflash.h"
52#include "../mtdcore.h"
53
54#ifndef __BIG_ENDIAN
55#error This driver currently only works with big endian CPU.
56#endif
57
58#define MAX_PARTS 32
59
60#define SPIFLASH "spiflash: "
61
62#define MIN(a,b)        ((a) < (b) ? (a) : (b))
63
64#define busy_wait(condition, wait) \
65        do { \
66                while (condition) { \
67                        spin_unlock_bh(&spidata->mutex); \
68                        if (wait > 1) \
69                                msleep(wait); \
70                        else if ((wait == 1) && need_resched()) \
71                                schedule(); \
72                        else \
73                                udelay(1); \
74                        spin_lock_bh(&spidata->mutex); \
75                } \
76        } while (0)
77               
78
79static __u32 spiflash_regread32(int reg);
80static void spiflash_regwrite32(int reg, __u32 data);
81static __u32 spiflash_sendcmd (int op, u32 addr);
82
83int __init spiflash_init (void);
84void __exit spiflash_exit (void);
85static int spiflash_probe_chip (void);
86static int spiflash_erase (struct mtd_info *mtd,struct erase_info *instr);
87static int spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf);
88static int spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf);
89
90/* Flash configuration table */
91struct flashconfig {
92    __u32 byte_cnt;
93    __u32 sector_cnt;
94    __u32 sector_size;
95    __u32 cs_addrmask;
96} flashconfig_tbl[MAX_FLASH] =
97    {
98        { 0, 0, 0, 0},
99        { STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, STM_1MB_SECTOR_SIZE, 0x0},
100        { STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, STM_2MB_SECTOR_SIZE, 0x0},
101        { STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, STM_4MB_SECTOR_SIZE, 0x0},
102        { STM_8MB_BYTE_COUNT, STM_8MB_SECTOR_COUNT, STM_8MB_SECTOR_SIZE, 0x0},
103        { STM_16MB_BYTE_COUNT, STM_16MB_SECTOR_COUNT, STM_16MB_SECTOR_SIZE, 0x0}
104    };
105
106/* Mapping of generic opcodes to STM serial flash opcodes */
107#define SPI_WRITE_ENABLE    0
108#define SPI_WRITE_DISABLE   1
109#define SPI_RD_STATUS       2
110#define SPI_WR_STATUS       3
111#define SPI_RD_DATA         4
112#define SPI_FAST_RD_DATA    5
113#define SPI_PAGE_PROGRAM    6
114#define SPI_SECTOR_ERASE    7
115#define SPI_BULK_ERASE      8
116#define SPI_DEEP_PWRDOWN    9
117#define SPI_RD_SIG          10
118#define SPI_MAX_OPCODES     11
119
120struct opcodes {
121    __u16 code;
122    __s8 tx_cnt;
123    __s8 rx_cnt;
124} stm_opcodes[] = {
125        {STM_OP_WR_ENABLE, 1, 0},
126        {STM_OP_WR_DISABLE, 1, 0},
127        {STM_OP_RD_STATUS, 1, 1},
128        {STM_OP_WR_STATUS, 1, 0},
129        {STM_OP_RD_DATA, 4, 4},
130        {STM_OP_FAST_RD_DATA, 5, 0},
131        {STM_OP_PAGE_PGRM, 8, 0},
132        {STM_OP_SECTOR_ERASE, 4, 0},
133        {STM_OP_BULK_ERASE, 1, 0},
134        {STM_OP_DEEP_PWRDOWN, 1, 0},
135        {STM_OP_RD_SIG, 4, 1},
136};
137
138/* Driver private data structure */
139struct spiflash_data {
140        struct  mtd_info       *mtd;   
141        struct  mtd_partition  *parsed_parts;     /* parsed partitions */
142        void    *readaddr; /* memory mapped data for read  */
143        void    *mmraddr;  /* memory mapped register space */
144        wait_queue_head_t wq;
145        spinlock_t mutex;
146        int state;
147};
148enum {
149        FL_READY,
150        FL_READING,
151        FL_ERASING,
152        FL_WRITING,
153        FL_SPI
154};
155
156static struct mtd_partition dir_parts[] = {
157        { name: "RedBoot", offset: 0, size: 0x30000, },//, mask_flags: MTD_WRITEABLE, },
158        { name: "linux", offset: 0x30000, size: 0x390000, },
159        { name: "rootfs", offset: 0x0, size: 0x2b0000,}, //must be detected
160        { name: "ddwrt", offset: 0x0, size: 0x2b0000,}, //must be detected
161        { name: "nvram", offset: 0x3d0000, size: 0x10000, },
162        { name: "FIS directory", offset: 0x3e0000, size: 0x10000, },
163        { name: "board_config", offset: 0x3f0000, size: 0x10000, },
164        { name: "fullflash", offset: 0x3f0000, size: 0x10000, },
165        { name: NULL, },
166};
167
168
169
170static struct spiflash_data *spidata;
171
172extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
173
174
175
176
177/***************************************************************************************************/
178
179static __u32
180spiflash_regread32(int reg)
181{
182        volatile __u32 *data = (__u32 *)(spidata->mmraddr + reg);
183
184        return (*data);
185}
186
187static void
188spiflash_regwrite32(int reg, __u32 data)
189{
190        volatile __u32 *addr = (__u32 *)(spidata->mmraddr + reg);
191
192        *addr = data;
193        return;
194}
195
196
197static __u32
198spiflash_sendcmd (int op, u32 addr)
199{
200         u32 reg;
201         u32 mask;
202        struct opcodes *ptr_opcode;
203
204        ptr_opcode = &stm_opcodes[op];
205        busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0);
206        spiflash_regwrite32(SPI_FLASH_OPCODE, ((u32) ptr_opcode->code) | (addr << 8));
207
208        reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt |
209                (ptr_opcode->rx_cnt << 4) | SPI_CTL_START;
210
211        spiflash_regwrite32(SPI_FLASH_CTL, reg);
212        busy_wait(spiflash_regread32(SPI_FLASH_CTL) & SPI_CTL_BUSY, 0);
213 
214        if (!ptr_opcode->rx_cnt)
215                return 0;
216
217        reg = (__u32) spiflash_regread32(SPI_FLASH_DATA);
218
219        switch (ptr_opcode->rx_cnt) {
220        case 1:
221                        mask = 0x000000ff;
222                        break;
223        case 2:
224                        mask = 0x0000ffff;
225                        break;
226        case 3:
227                        mask = 0x00ffffff;
228                        break;
229        default:
230                        mask = 0xffffffff;
231                        break;
232        }
233        reg &= mask;
234
235        return reg;
236}
237
238
239
240/* Probe SPI flash device
241 * Function returns 0 for failure.
242 * and flashconfig_tbl array index for success.
243 */
244static int
245spiflash_probe_chip (void)
246{
247        __u32 sig;
248        int flash_size;
249       
250        /* Read the signature on the flash device */
251        spin_lock_bh(&spidata->mutex);
252        sig = spiflash_sendcmd(SPI_RD_SIG, 0);
253        spin_unlock_bh(&spidata->mutex);
254
255        switch (sig) {
256        case STM_8MBIT_SIGNATURE:
257                flash_size = FLASH_1MB;
258                break;
259        case STM_16MBIT_SIGNATURE:
260                flash_size = FLASH_2MB;
261                break;
262        case STM_32MBIT_SIGNATURE:
263                flash_size = FLASH_4MB;
264                break;
265        case STM_64MBIT_SIGNATURE:
266                flash_size = FLASH_8MB;
267                break;
268        case STM_128MBIT_SIGNATURE:
269                flash_size = FLASH_16MB;
270                break;
271        default:
272                printk (KERN_WARNING SPIFLASH "Read of flash device signature failed!\n");
273                return (0);
274        }
275
276        return (flash_size);
277}
278
279
280/* wait until the flash chip is ready and grab a lock */
281static int spiflash_wait_ready(int state)
282{
283        DECLARE_WAITQUEUE(wait, current);
284
285retry:
286        spin_lock_bh(&spidata->mutex);
287        if (spidata->state != FL_READY) {
288                set_current_state(TASK_UNINTERRUPTIBLE);
289                add_wait_queue(&spidata->wq, &wait);
290                spin_unlock_bh(&spidata->mutex);
291                schedule();
292                remove_wait_queue(&spidata->wq, &wait);
293               
294                if(signal_pending(current))
295                        return 0;
296
297       
298                goto retry;
299        }
300        spidata->state = state;
301
302        return 1;
303}
304
305static inline void spiflash_done(void)
306{
307        spidata->state = FL_READY;
308        spin_unlock_bh(&spidata->mutex);
309        wake_up(&spidata->wq);
310}
311
312#ifdef CONFIG_MTD_SPIFLASH_PP
313static void sysGpioCtrlInput(int gpio_bit)
314{
315        unsigned int tmpVal;
316        tmpVal = *(volatile int *)(0xb1000098);
317        tmpVal &= ~(1<<gpio_bit);
318        tmpVal |=(0<<gpio_bit);
319        *(volatile int *)(0xb1000098) = tmpVal; 
320}
321
322static void sysGpioCtrlOutput(int gpio_bit)
323{
324        unsigned int tmpVal;
325        tmpVal = *(volatile int *)(0xb1000098);
326        tmpVal &= ~(1<<gpio_bit);
327        tmpVal |=(1<<gpio_bit);
328        *(volatile int *)(0xb1000098) = tmpVal; 
329}
330
331static void sysGpioSet(int gpio_bit, int val)
332{
333    unsigned int reg;
334
335    reg = *(volatile int *)(0xb1000090);
336    reg &= ~(1 << gpio_bit);
337    reg |= (val&1) << gpio_bit;
338    *(volatile int *)(0xb1000090) = reg;
339}
340
341#endif
342
343static int
344spiflash_erase (struct mtd_info *mtd,struct erase_info *instr)
345{
346        struct opcodes *ptr_opcode;
347        __u32 temp, reg;
348        int finished = 0;
349        unsigned int addr = instr->addr;
350#ifdef CONFIG_MTD_SPIFLASH_PP
351        sysGpioCtrlOutput(CONFIG_MTD_SPIFLASH_PP_GPIO); /* set GPIO_0 as output */
352
353        sysGpioSet(CONFIG_MTD_SPIFLASH_PP_GPIO, 1);     /* drive low GPIO_0     */
354#endif
355#ifdef SPIFLASH_DEBUG
356        printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
357#endif
358
359        /* sanity checks */
360        if (instr->addr + instr->len > mtd->size) return (-EINVAL);
361        if (!spiflash_wait_ready(FL_ERASING))
362                return -EINTR;
363for (addr=instr->addr;addr<instr->addr+instr->len;addr+=mtd->erasesize)
364{
365
366        ptr_opcode = &stm_opcodes[SPI_SECTOR_ERASE];
367
368        temp = ((__u32)addr << 8) | (__u32)(ptr_opcode->code);
369        spiflash_sendcmd(SPI_WRITE_ENABLE,0);
370        busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0);
371
372        spiflash_regwrite32(SPI_FLASH_OPCODE, temp);
373
374        reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | SPI_CTL_START;
375        spiflash_regwrite32(SPI_FLASH_CTL, reg);
376
377        busy_wait(spiflash_sendcmd(SPI_RD_STATUS, 0) & SPI_STATUS_WIP, 20);
378}
379        spiflash_done();
380
381        instr->state = MTD_ERASE_DONE;
382        if (instr->callback) instr->callback (instr);
383#ifdef SPIFLASH_DEBUG
384        printk (KERN_DEBUG "%s return\n",__FUNCTION__);
385#endif
386        return (0);
387}
388
389static int
390spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf)
391{
392        u8 *read_addr;
393       
394        /* sanity checks */
395        if (!len) return (0);
396        if (from + len > mtd->size) return (-EINVAL);
397       
398        /* we always read len bytes */
399        *retlen = len;
400
401        if (!spiflash_wait_ready(FL_READING))
402                return -EINTR;
403        read_addr = (u8 *)(spidata->readaddr + from);
404        memcpy(buf, read_addr, len);
405        spiflash_done();
406
407        return 0;
408}
409
410static int
411spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
412{
413        u32 opcode, bytes_left;
414
415        *retlen = 0;
416
417        /* sanity checks */
418        if (!len) return (0);
419        if (to + len > mtd->size) return (-EINVAL);
420       
421        opcode = stm_opcodes[SPI_PAGE_PROGRAM].code;
422        bytes_left = len;
423       
424        do {
425                u32 xact_len, reg, page_offset, spi_data = 0;
426
427                xact_len = MIN(bytes_left, sizeof(__u32));
428
429                /* 32-bit writes cannot span across a page boundary
430                 * (256 bytes). This types of writes require two page
431                 * program operations to handle it correctly. The STM part
432                 * will write the overflow data to the beginning of the
433                 * current page as opposed to the subsequent page.
434                 */
435                page_offset = (to & (STM_PAGE_SIZE - 1)) + xact_len;
436
437                if (page_offset > STM_PAGE_SIZE) {
438                        xact_len -= (page_offset - STM_PAGE_SIZE);
439                }
440
441                if (!spiflash_wait_ready(FL_WRITING))
442                        return -EINTR;
443
444                spiflash_sendcmd(SPI_WRITE_ENABLE, 0);
445                switch (xact_len) {
446                        case 1:
447                                spi_data = (u32) ((u8) *buf);
448                                break;
449                        case 2:
450                                spi_data = (buf[1] << 8) | buf[0];
451                                break;
452                        case 3:
453                                spi_data = (buf[2] << 16) | (buf[1] << 8) | buf[0];
454                                break;
455                        case 4:
456                                spi_data = (buf[3] << 24) | (buf[2] << 16) |
457                                                        (buf[1] << 8) | buf[0];
458                                break;
459                        default:
460                                spi_data = 0;
461                                break;
462                }
463
464                spiflash_regwrite32(SPI_FLASH_DATA, spi_data);
465                opcode = (opcode & SPI_OPCODE_MASK) | ((__u32)to << 8);
466                spiflash_regwrite32(SPI_FLASH_OPCODE, opcode);
467
468                reg = spiflash_regread32(SPI_FLASH_CTL);
469                reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | (xact_len + 4) | SPI_CTL_START;
470                spiflash_regwrite32(SPI_FLASH_CTL, reg);
471
472                /* give the chip some time before we start busy waiting */
473                spin_unlock_bh(&spidata->mutex);
474                schedule();
475                spin_lock_bh(&spidata->mutex);
476
477                busy_wait(spiflash_sendcmd(SPI_RD_STATUS, 0) & SPI_STATUS_WIP, 0);
478                spiflash_done();
479
480                bytes_left -= xact_len;
481                to += xact_len;
482                buf += xact_len;
483
484                *retlen += xact_len;
485        } while (bytes_left != 0);
486
487        return 0;
488}
489
490#ifdef CONFIG_MTD_SPIFLASH_PP
491#define FALSE   0
492#define TRUE    1
493
494
495
496#ifndef cpu2le32
497#define cpu2le32(x)                  \
498    ((((x) & 0x000000ffUL) << 24) |  \
499     (((x) & 0x0000ff00UL) << 8)  |  \
500     (((x) & 0x00ff0000UL) >> 8)  |  \
501     (((x) & 0xff000000UL) >> 24))
502#endif
503
504
505
506
507
508static int
509spiflash_write_page (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
510{
511        int finished;
512        __u32 xact_len, spi_data = 0;
513        __u32 opcode, sf_opcode, reg;
514        __u32 flashAddr;
515        __u32 spi_data_swapped;
516        __u32  pagesToWrite, lastByteInPage, i, j;
517        __u32  beginPage, beginOffset, beginRemain, endPage, endOffset;
518        __u32 toggle = 0;
519        __u32 totalCount = 0;
520       
521       
522       
523        *retlen = 0;
524#ifdef SPIFLASH_DEBUG
525        printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len);
526#endif 
527        /* sanity checks */
528        if (!len) return (0);
529        if (to + len > mtd->size) return (-EINVAL);
530        flashAddr = (__u32)to;
531        sf_opcode = stm_opcodes[SPI_PAGE_PROGRAM].code;
532        lastByteInPage= STM_PAGE_SIZE -1;
533        beginPage= ((unsigned int)flashAddr) / STM_PAGE_SIZE;
534        beginOffset= ((unsigned int)flashAddr) % STM_PAGE_SIZE;
535        beginRemain= STM_PAGE_SIZE - beginOffset;
536
537        endPage= ((unsigned int)flashAddr + len - 1) / STM_PAGE_SIZE;
538        endOffset= ((unsigned int)flashAddr + len - 1) % STM_PAGE_SIZE;
539
540        pagesToWrite= endPage - beginPage + 1;
541        if( (beginPage != endPage) && (endOffset != lastByteInPage) )
542        {
543            /* The end offset write to middle of a page */
544            pagesToWrite --;
545        }
546
547        if( beginOffset | (len < STM_PAGE_SIZE) )
548        {
549               /* write from the middle of a page */
550                xact_len = MIN(len, beginRemain);
551                spiflash_write(mtd, (loff_t)flashAddr, xact_len, retlen, buf);
552//                printk("beginOffset flashAddr = 0x%08x len =%d  bytes beginRemain  =%d bytes retlen = %d bytes\n", flashAddr, len, beginRemain, *retlen);
553                flashAddr += xact_len;
554                buf += xact_len;
555                pagesToWrite --;
556        }
557
558        /*********** 256-byte Page program *************/       
559        if( pagesToWrite )
560        {
561//            printk("pagesToWrite\n");
562            for(i=0; i<pagesToWrite; i++)   /* write page(256 bytes) by page */
563            {               
564               (void) spiflash_sendcmd(SPI_WRITE_ENABLE,0);
565                busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0);
566
567                spi_data = (__u32) *((__u32 *) buf);
568                spi_data = cpu2le32(spi_data);
569                if (!spiflash_wait_ready(FL_WRITING))
570                    return -EINTR;
571
572                local_irq_disable();
573                sysGpioCtrlOutput(CONFIG_MTD_SPIFLASH_PP_GPIO); /* set GPIO_0 as output */
574
575                sysGpioSet(CONFIG_MTD_SPIFLASH_PP_GPIO, 0);     /* drive low GPIO_0     */
576
577                spiflash_regwrite32(SPI_FLASH_DATA, spi_data);
578                opcode = (sf_opcode & SPI_OPCODE_MASK) | ((__u32) flashAddr << 8);
579                spiflash_regwrite32( SPI_FLASH_OPCODE, opcode );
580                reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | 0x8 | SPI_CTL_START;
581                spiflash_regwrite32(AR531XPLUS_SPI_CTL, reg);
582                buf += 4;
583
584                for(j=0; j<31; j++)   /* 32 loops, each loop writes 4 bytes */
585                {
586            //      Set_Led( DIAGNOSTIC_LED, toggle);
587                    if((j%3) == 0)     
588                       toggle ^= 1;
589                    do {
590                            reg = spiflash_regread32(SPI_FLASH_CTL);
591                    } while (reg & SPI_CTL_BUSY);
592
593                    spi_data = (__u32) *((__u32 *) buf);
594                    spi_data = cpu2le32(spi_data);
595                    spi_data_swapped = (((spi_data >> 8) & 0xff) << 24) | (((spi_data >> 24) & 0xff) << 8) | (spi_data & 0x00ff00ff);
596
597                    spiflash_regwrite32(SPI_FLASH_OPCODE, spi_data_swapped );
598
599                    buf += 4;
600
601                    spi_data = (__u32) *((__u32 *) buf);
602                    spi_data = cpu2le32(spi_data);
603                    spiflash_regwrite32(SPI_FLASH_DATA, spi_data );
604                    reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | 0x8 | SPI_CTL_START;
605                    spiflash_regwrite32(SPI_FLASH_CTL, reg);
606                   
607                    buf += 4;
608
609                }
610                busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0);
611
612                spi_data = (__u32) *((__u32 *) buf);
613                spi_data = cpu2le32(spi_data);
614                spi_data_swapped = (((spi_data >> 8) & 0xff) << 24) | (((spi_data >> 24) & 0xff) << 8) | (spi_data & 0x00ff00ff);
615                spiflash_regwrite32( SPI_FLASH_OPCODE, spi_data_swapped );
616                reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | 0x4 | SPI_CTL_START;
617                spiflash_regwrite32(SPI_FLASH_CTL, reg);
618
619                buf += 4;
620                busy_wait((reg = spiflash_regread32(SPI_FLASH_CTL)) & SPI_CTL_BUSY, 0);
621
622                sysGpioSet(CONFIG_MTD_SPIFLASH_PP_GPIO, 1);   /* drive high GPIO_0 */
623                local_irq_enable();
624                spiflash_done();
625
626                finished = FALSE;
627               
628                flashAddr += STM_PAGE_SIZE;
629                *retlen += STM_PAGE_SIZE;
630                do {
631                        udelay(10);
632                        reg = spiflash_sendcmd(SPI_RD_STATUS,0);
633                        if (!(reg & SPI_STATUS_WIP)) {
634                                finished = TRUE;
635                        }
636                } while (!finished);   
637                       
638            }
639        }
640        totalCount = *retlen;
641
642        /************* 256-byte Page program ***************/     
643       
644        if( (beginPage != endPage) && (endOffset != lastByteInPage) )/* write to middle of a page */
645        {
646//            printk("endOffset flashAddr = 0x%08x len =%d bytes cur = 0x%08x\n", flashAddr, endOffset + 1,totalCount);         
647            spiflash_write(mtd, (loff_t)flashAddr, endOffset + 1, retlen, buf);
648            totalCount += *retlen;
649            *retlen  = 0;         
650        }
651        *retlen = totalCount;
652    return (0);
653       
654}
655
656
657#endif
658
659#ifdef CONFIG_MTD
660static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
661#endif
662struct fis_image_desc {
663    unsigned char name[16];      // Null terminated name
664    unsigned long flash_base;    // Address within FLASH of image
665    unsigned long mem_base;      // Address in memory where it executes
666    unsigned long size;          // Length of image
667    unsigned long entry_point;   // Execution entry point
668    unsigned long data_length;   // Length of actual data
669    unsigned char _pad[256-(16+7*sizeof(unsigned long))];
670    unsigned long desc_cksum;    // Checksum over image descriptor
671    unsigned long file_cksum;    // Checksum over image data
672};
673
674#define SCANCOUNT 5
675static unsigned int redboot_offset(unsigned int highoffset,unsigned int erasesize)
676{
677unsigned int copy=highoffset;
678int c=SCANCOUNT;
679while((c--)>0)
680{
681highoffset-=erasesize;
682unsigned char *p=(unsigned char *)highoffset;
683if (!strncmp(p,"RedBoot",7))
684    {
685    return highoffset;
686    }
687}
688return copy-erasesize;
689}
690
691static int spiflash_probe(struct platform_device *pdev)
692{
693        int offset=0;
694        int ret,retlen;
695        int result = -1;
696        int index, num_parts;
697        struct mtd_info *mtd;
698        char *buf;
699        struct fis_image_desc *fis; 
700        unsigned char *p;
701        struct squashfs_super_block *sb;
702        size_t rootsize;
703        size_t len;
704        spidata->mmraddr = ioremap_nocache(SPI_FLASH_MMR, SPI_FLASH_MMR_SIZE);
705        spin_lock_init(&spidata->mutex);
706        init_waitqueue_head(&spidata->wq);
707        spidata->state = FL_READY;
708       
709        if (!spidata->mmraddr) {
710                printk (KERN_WARNING SPIFLASH "Failed to map flash device\n");
711                kfree(spidata);
712                spidata = NULL;
713        }
714
715        mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
716        if (!mtd) {
717                kfree(spidata);
718                return -ENXIO;
719        }
720       
721        if (!(index = spiflash_probe_chip())) {
722        printk (KERN_WARNING SPIFLASH "Found no serial flash device\n");
723                goto error;
724        }
725
726        spidata->readaddr = ioremap_nocache(SPI_FLASH_READ, flashconfig_tbl[index].byte_cnt);
727        if (!spidata->readaddr) {
728                printk (KERN_WARNING SPIFLASH "Failed to map flash device\n");
729                goto error;
730        }
731
732        mtd->name = "spiflash";
733        mtd->type = MTD_NORFLASH;
734        mtd->flags = (MTD_CAP_NORFLASH|MTD_WRITEABLE);
735        mtd->size = flashconfig_tbl[index].byte_cnt;
736        mtd->erasesize = flashconfig_tbl[index].sector_size;
737        mtd->writesize = 1;
738        mtd->numeraseregions = 0;
739        mtd->eraseregions = NULL;
740        mtd->_erase = spiflash_erase;
741        mtd->_read = spiflash_read;
742#ifdef CONFIG_MTD_SPIFLASH_PP
743        mtd->_write = spiflash_write_page;
744#else
745        mtd->_write = spiflash_write;
746#endif
747        mtd->owner = THIS_MODULE;
748        printk(KERN_EMERG "scanning for root partition\n");
749       
750        offset = 0;
751        buf = 0xa8000000;
752        int compex=0;
753                if (!strncmp((char*)(buf+0x26da),"myloram.bin",11))
754                    {
755                    printk(KERN_EMERG "Compex device detected\n");
756                    dir_parts[0].size=0x20000;
757                    dir_parts[0].offset=0;
758                    dir_parts[7].size=mtd->size;
759                    dir_parts[7].offset = 0;
760                    dir_parts[6].size=mtd->erasesize;
761                    dir_parts[6].offset = mtd->size-mtd->erasesize;
762                    compex=1;
763                    }
764
765
766        while((offset+mtd->erasesize)<mtd->size)
767            {
768//          printk(KERN_EMERG "[0x%08X]\n",offset);
769            if (*((__u32 *) buf) == SQUASHFS_MAGIC_SWAP)
770                {
771                printk(KERN_EMERG "\nfound squashfs at %X\n",offset);
772                sb = (struct squashfs_super_block *) buf;
773                dir_parts[2].offset = offset;
774               
775                dir_parts[2].size = sb->bytes_used;
776                len = dir_parts[2].offset + dir_parts[2].size;
777                len +=  (mtd->erasesize - 1);
778                len &= ~(mtd->erasesize - 1);
779                dir_parts[2].size = (len&0xffffff) - dir_parts[2].offset;
780                dir_parts[3].offset = dir_parts[2].offset + dir_parts[2].size;
781               
782                dir_parts[6].offset = mtd->size-mtd->erasesize; // board config
783                dir_parts[6].size = mtd->erasesize;
784                dir_parts[5].offset = redboot_offset(0xa8000000+mtd->size,mtd->erasesize)-0xa8000000; //dir_parts[6].offset-mtd->erasesize; //fis config
785                dir_parts[5].size = mtd->erasesize;
786                dir_parts[4].offset = dir_parts[5].offset-mtd->erasesize; //nvram
787                dir_parts[4].size = mtd->erasesize;
788                dir_parts[3].size = dir_parts[4].offset - dir_parts[3].offset;
789                rootsize = dir_parts[4].offset-offset; //size of rootfs aligned to nvram offset
790                //now scan for linux offset
791                if (compex)
792                {
793                dir_parts[1].offset=0x20000;
794                dir_parts[1].size=(dir_parts[2].offset-dir_parts[1].offset)+rootsize;           
795                break;
796                }else{
797                p=(unsigned char*)(0xa8000000+dir_parts[5].offset);
798                fis = (struct fis_image_desc*)p;
799                while(1)
800                {
801                if (fis->name[0]==0xff)
802                    {
803                    goto def;
804                    }
805                if (!strcmp(fis->name,"RedBoot"))
806                    {
807                    printk(KERN_EMERG "found RedBoot partition at [0x%08lX]\n",fis->flash_base);
808                    dir_parts[0].size=fis->size;
809                    dir_parts[7].offset=0;
810                    dir_parts[1].offset=fis->size;
811                    }
812                if (!strcmp(fis->name,"linux") || !strncmp(fis->name,"vmlinux",7) || !strcmp(fis->name,"kernel"))
813                    {
814                    printk(KERN_EMERG "found linux partition at [0x%08lX]\n",fis->flash_base);
815                    if (dir_parts[2].offset==dir_parts[1].offset) // image begins with rootfs instead of kernel
816                        dir_parts[1].size=fis->size+rootsize;               
817                    else
818                        dir_parts[1].size=(dir_parts[2].offset-dir_parts[1].offset)+rootsize;
819                    dir_parts[7].size=mtd->size; // linux + nvram = phy size
820                    }
821                p+=sizeof(struct fis_image_desc);
822                fis = (struct fis_image_desc*)p;
823                }
824                break;
825                }
826                }
827            offset+=mtd->erasesize;
828            buf+=mtd->erasesize;
829            }
830        def:;
831        result = add_mtd_partitions(mtd, dir_parts, 8);
832        spidata->mtd = mtd;
833       
834        return (result);
835       
836error:
837        kfree(mtd);
838        kfree(spidata);
839        return -ENXIO;
840}
841
842static int spiflash_remove (struct platform_device *pdev)
843{
844        del_mtd_partitions (spidata->mtd);
845        kfree(spidata->mtd);
846        return 0;
847}
848
849struct platform_driver spiflash_driver = {
850        .driver.name = "spiflash",
851        .probe = spiflash_probe,
852        .remove = spiflash_remove,
853};
854
855int __init
856spiflash_init (void)
857{
858        spidata = kmalloc(sizeof(struct spiflash_data), GFP_KERNEL);
859        if (!spidata)
860                return (-ENXIO);
861
862        spin_lock_init(&spidata->mutex);
863        platform_driver_register(&spiflash_driver);
864
865        return 0;
866}
867
868void __exit
869spiflash_exit (void)
870{
871        kfree(spidata);
872}
873
874module_init (spiflash_init);
875module_exit (spiflash_exit);
876
877MODULE_LICENSE("GPL");
878MODULE_AUTHOR("OpenWrt.org, Atheros Communications Inc");
879MODULE_DESCRIPTION("MTD driver for SPI Flash on Atheros SOC");
880
Note: See TracBrowser for help on using the repository browser.