Add support for Atheros SoC (used in Fonera, Meraki) - Merry Christmas, everybody :)
[openwrt.git] / target / linux / atheros-2.6 / patches / 110-spiflash.patch
1 diff -urN linux.old/drivers/mtd/devices/Kconfig linux.dev/drivers/mtd/devices/Kconfig
2 --- linux.old/drivers/mtd/devices/Kconfig       2006-11-29 22:57:37.000000000 +0100
3 +++ linux.dev/drivers/mtd/devices/Kconfig       2006-12-15 00:03:11.000000000 +0100
4 @@ -68,6 +68,10 @@
5           used for program and data storage.  Set up your spi devices
6           with the right board-specific platform data.
7  
8 +config MTD_SPIFLASH
9 +       tristate "Atheros AR2315/6/7 SPI Flash support"
10 +       depends on MTD && AR531X_COBRA
11 +
12  config MTD_SLRAM
13         tristate "Uncached system RAM"
14         depends on MTD
15 diff -urN linux.old/drivers/mtd/devices/Makefile linux.dev/drivers/mtd/devices/Makefile
16 --- linux.old/drivers/mtd/devices/Makefile      2006-11-29 22:57:37.000000000 +0100
17 +++ linux.dev/drivers/mtd/devices/Makefile      2006-12-15 00:03:11.000000000 +0100
18 @@ -17,3 +17,4 @@
19  obj-$(CONFIG_MTD_BLOCK2MTD)    += block2mtd.o
20  obj-$(CONFIG_MTD_DATAFLASH)    += mtd_dataflash.o
21  obj-$(CONFIG_MTD_M25P80)       += m25p80.o
22 +obj-$(CONFIG_MTD_SPIFLASH)     += spiflash.o
23 diff -urN linux.old/drivers/mtd/devices/spiflash.c linux.dev/drivers/mtd/devices/spiflash.c
24 --- linux.old/drivers/mtd/devices/spiflash.c    1970-01-01 01:00:00.000000000 +0100
25 +++ linux.dev/drivers/mtd/devices/spiflash.c    2006-12-15 08:26:11.000000000 +0100
26 @@ -0,0 +1,595 @@
27 +
28 +/*
29 + * MTD driver for the SPI Flash Memory support.
30 + *
31 + * Copyright (c) 2005-2006 Atheros Communications Inc.
32 + * Copyright (C) 2006 FON Technology, SL.
33 + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
34 + * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
35 + *
36 + * This code is free software; you can redistribute it and/or modify
37 + * it under the terms of the GNU General Public License version 2 as
38 + * published by the Free Software Foundation.
39 + *
40 + */
41 +
42 +/*===========================================================================
43 +** !!!!  VERY IMPORTANT NOTICE !!!!  FLASH DATA STORED IN LITTLE ENDIAN FORMAT
44 +**
45 +** This module contains the Serial Flash access routines for the Atheros SOC.
46 +** The Atheros SOC integrates a SPI flash controller that is used to access
47 +** serial flash parts. The SPI flash controller executes in "Little Endian"
48 +** mode. THEREFORE, all WRITES and READS from the MIPS CPU must be
49 +** BYTESWAPPED! The SPI Flash controller hardware by default performs READ
50 +** ONLY byteswapping when accessed via the SPI Flash Alias memory region
51 +** (Physical Address 0x0800_0000 - 0x0fff_ffff). The data stored in the
52 +** flash sectors is stored in "Little Endian" format.
53 +**
54 +** The spiflash_write() routine performs byteswapping on all write
55 +** operations.
56 +**===========================================================================*/
57 +
58 +#include <linux/kernel.h>
59 +#include <linux/module.h>
60 +#include <linux/types.h>
61 +#include <linux/version.h>
62 +#include <linux/errno.h>
63 +#include <linux/slab.h>
64 +#include <linux/mtd/mtd.h>
65 +#include <linux/mtd/partitions.h>
66 +#include <linux/squashfs_fs.h>
67 +#include <linux/root_dev.h>
68 +#include <asm/delay.h>
69 +#include <asm/io.h>
70 +#include "spiflash.h"
71 +
72 +/* debugging */
73 +/* #define SPIFLASH_DEBUG */
74 +
75 +#ifndef __BIG_ENDIAN
76 +#error This driver currently only works with big endian CPU.
77 +#endif
78 +
79 +#define MAX_PARTS 32
80 +
81 +static char module_name[] = "spiflash";
82 +
83 +#define MIN(a,b)        ((a) < (b) ? (a) : (b))
84 +#define FALSE  0
85 +#define TRUE   1
86 +
87 +#define ROOTFS_NAME    "rootfs"
88 +
89 +static __u32 spiflash_regread32(int reg);
90 +static void spiflash_regwrite32(int reg, __u32 data);
91 +static __u32 spiflash_sendcmd (int op);
92 +
93 +static void __init spidata_init(void);
94 +int __init spiflash_init (void);
95 +void __exit spiflash_exit (void);
96 +static int spiflash_probe (void);
97 +static int spiflash_erase (struct mtd_info *mtd,struct erase_info *instr);
98 +static int spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf);
99 +static int spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf);
100 +
101 +/* Flash configuration table */
102 +struct flashconfig {
103 +    __u32 byte_cnt;
104 +    __u32 sector_cnt;
105 +    __u32 sector_size;
106 +    __u32 cs_addrmask;
107 +} flashconfig_tbl[MAX_FLASH] =
108 +    {
109 +        { 0, 0, 0, 0},
110 +        { STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, STM_1MB_SECTOR_SIZE, 0x0},
111 +        { STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, STM_2MB_SECTOR_SIZE, 0x0},
112 +        { STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, STM_4MB_SECTOR_SIZE, 0x0},
113 +        { STM_8MB_BYTE_COUNT, STM_8MB_SECTOR_COUNT, STM_8MB_SECTOR_SIZE, 0x0}
114 +    };
115 +
116 +/* Mapping of generic opcodes to STM serial flash opcodes */
117 +struct opcodes {
118 +    __u16 code;
119 +    __s8 tx_cnt;
120 +    __s8 rx_cnt;
121 +} stm_opcodes[] = {
122 +        {STM_OP_WR_ENABLE, 1, 0},
123 +        {STM_OP_WR_DISABLE, 1, 0},
124 +        {STM_OP_RD_STATUS, 1, 1},
125 +        {STM_OP_WR_STATUS, 1, 0},
126 +        {STM_OP_RD_DATA, 4, 4},
127 +        {STM_OP_FAST_RD_DATA, 1, 0},
128 +        {STM_OP_PAGE_PGRM, 8, 0},
129 +        {STM_OP_SECTOR_ERASE, 4, 0},
130 +        {STM_OP_BULK_ERASE, 1, 0},
131 +        {STM_OP_DEEP_PWRDOWN, 1, 0},
132 +        {STM_OP_RD_SIG, 4, 1}
133 +};
134 +
135 +/* Driver private data structure */
136 +struct spiflash_data {
137 +       struct  mtd_info       *mtd;    
138 +       struct  mtd_partition  *parsed_parts;     /* parsed partitions */
139 +       void    *spiflash_readaddr; /* memory mapped data for read  */
140 +       void    *spiflash_mmraddr;  /* memory mapped register space */
141 +       spinlock_t mutex;
142 +};
143 +
144 +static struct spiflash_data *spidata;
145 +
146 +extern int parse_redboot_partitions(struct mtd_info *master, struct mtd_partition **pparts);
147 +
148 +/***************************************************************************************************/
149 +
150 +static __u32
151 +spiflash_regread32(int reg)
152 +{
153 +       volatile __u32 *data = (__u32 *)(spidata->spiflash_mmraddr + reg);
154 +
155 +       return (*data);
156 +}
157 +
158 +static void 
159 +spiflash_regwrite32(int reg, __u32 data)
160 +{
161 +       volatile __u32 *addr = (__u32 *)(spidata->spiflash_mmraddr + reg);
162 +
163 +       *addr = data;
164 +       return;
165 +}
166 +
167 +static __u32 
168 +spiflash_sendcmd (int op)
169 +{
170 +        __u32 reg;
171 +        __u32 mask;
172 +       struct opcodes *ptr_opcode;
173 +
174 +       ptr_opcode = &stm_opcodes[op];
175 +
176 +       do {
177 +               reg = spiflash_regread32(SPI_FLASH_CTL);
178 +       } while (reg & SPI_CTL_BUSY);
179 +
180 +       spiflash_regwrite32(SPI_FLASH_OPCODE, ptr_opcode->code);
181 +
182 +       reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt |
183 +               (ptr_opcode->rx_cnt << 4) | SPI_CTL_START;
184 +
185 +       spiflash_regwrite32(SPI_FLASH_CTL, reg);
186
187 +       if (ptr_opcode->rx_cnt > 0) {
188 +               do {
189 +                       reg = spiflash_regread32(SPI_FLASH_CTL);
190 +               } while (reg & SPI_CTL_BUSY);
191 +
192 +               reg = (__u32) spiflash_regread32(SPI_FLASH_DATA);
193 +
194 +               switch (ptr_opcode->rx_cnt) {
195 +               case 1:
196 +                       mask = 0x000000ff;
197 +                       break;
198 +               case 2:
199 +                       mask = 0x0000ffff;
200 +                       break;
201 +               case 3:
202 +                       mask = 0x00ffffff;
203 +                       break;
204 +               default:
205 +                       mask = 0xffffffff;
206 +                       break;
207 +               }
208 +
209 +               reg &= mask;
210 +       }
211 +       else {
212 +                       reg = 0;
213 +       }
214 +
215 +       return reg;
216 +}
217 +
218 +/* Probe SPI flash device
219 + * Function returns 0 for failure.
220 + * and flashconfig_tbl array index for success.
221 + */
222 +static int 
223 +spiflash_probe (void)
224 +{
225 +       __u32 sig;
226 +       int flash_size;
227 +
228 +       if (!spidata)
229 +               spidata_init();
230 +       
231 +       if (!spidata) /* init failed */
232 +               return 0;
233 +
234 +       /* Read the signature on the flash device */
235 +       sig = spiflash_sendcmd(SPI_RD_SIG);
236 +
237 +       switch (sig) {
238 +       case STM_8MBIT_SIGNATURE:
239 +               flash_size = FLASH_1MB;
240 +               break;
241 +        case STM_16MBIT_SIGNATURE:
242 +               flash_size = FLASH_2MB;
243 +               break;
244 +        case STM_32MBIT_SIGNATURE:
245 +               flash_size = FLASH_4MB;
246 +               break;
247 +        case STM_64MBIT_SIGNATURE:
248 +               flash_size = FLASH_8MB;
249 +               break;
250 +        default:
251 +               printk (KERN_WARNING "%s: Read of flash device signature failed!\n", module_name);
252 +               return (0);
253 +       }
254 +
255 +       return (flash_size);
256 +}
257 +
258 +
259 +static int 
260 +spiflash_erase (struct mtd_info *mtd,struct erase_info *instr)
261 +{
262 +       struct opcodes *ptr_opcode;
263 +       __u32 temp, reg;
264 +       int finished = FALSE;
265 +
266 +#ifdef SPIFLASH_DEBUG
267 +       printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len);
268 +#endif
269 +
270 +       /* sanity checks */
271 +       if (instr->addr + instr->len > mtd->size) return (-EINVAL);
272 +
273 +       ptr_opcode = &stm_opcodes[SPI_SECTOR_ERASE];
274 +
275 +       temp = ((__u32)instr->addr << 8) | (__u32)(ptr_opcode->code);
276 +       spin_lock(&spidata->mutex);
277 +       spiflash_sendcmd(SPI_WRITE_ENABLE);
278 +       do {
279 +               schedule();
280 +               reg = spiflash_regread32(SPI_FLASH_CTL);
281 +       } while (reg & SPI_CTL_BUSY);
282 +
283 +       spiflash_regwrite32(SPI_FLASH_OPCODE, temp);
284 +
285 +       reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | ptr_opcode->tx_cnt | SPI_CTL_START;
286 +       spiflash_regwrite32(SPI_FLASH_CTL, reg);
287 +
288 +       do {
289 +               schedule();
290 +               reg = spiflash_sendcmd(SPI_RD_STATUS);
291 +               if (!(reg & SPI_STATUS_WIP)) {
292 +                       finished = TRUE;
293 +               }
294 +       } while (!finished);
295 +       spin_unlock(&spidata->mutex);
296 +
297 +       instr->state = MTD_ERASE_DONE;
298 +       if (instr->callback) instr->callback (instr);
299 +
300 +#ifdef SPIFLASH_DEBUG
301 +       printk (KERN_DEBUG "%s return\n",__FUNCTION__);
302 +#endif
303 +       return (0);
304 +}
305 +
306 +static int 
307 +spiflash_read (struct mtd_info *mtd, loff_t from,size_t len,size_t *retlen,u_char *buf)
308 +{
309 +       u_char  *read_addr;
310 +
311 +#ifdef SPIFLASH_DEBUG
312 +       printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,(int)len);  
313 +#endif
314 +
315 +       /* sanity checks */
316 +       if (!len) return (0);
317 +       if (from + len > mtd->size) return (-EINVAL);
318 +       
319 +
320 +       /* we always read len bytes */
321 +       *retlen = len;
322 +
323 +       read_addr = (u_char *)(spidata->spiflash_readaddr + from);
324 +       spin_lock(&spidata->mutex);
325 +       memcpy(buf, read_addr, len);
326 +       spin_unlock(&spidata->mutex);
327 +
328 +       return (0);
329 +}
330 +
331 +static int 
332 +spiflash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen,const u_char *buf)
333 +{
334 +       int done = FALSE, page_offset, bytes_left, finished;
335 +       __u32 xact_len, spi_data = 0, opcode, reg;
336 +
337 +#ifdef SPIFLASH_DEBUG
338 +       printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len); 
339 +#endif
340 +
341 +       *retlen = 0;
342 +       
343 +       /* sanity checks */
344 +       if (!len) return (0);
345 +       if (to + len > mtd->size) return (-EINVAL);
346 +       
347 +       opcode = stm_opcodes[SPI_PAGE_PROGRAM].code;
348 +       bytes_left = len;
349 +       
350 +       while (done == FALSE) {
351 +               xact_len = MIN(bytes_left, sizeof(__u32));
352 +
353 +               /* 32-bit writes cannot span across a page boundary
354 +                * (256 bytes). This types of writes require two page
355 +                * program operations to handle it correctly. The STM part
356 +                * will write the overflow data to the beginning of the
357 +                * current page as opposed to the subsequent page.
358 +                */
359 +               page_offset = (to & (STM_PAGE_SIZE - 1)) + xact_len;
360 +
361 +               if (page_offset > STM_PAGE_SIZE) {
362 +                       xact_len -= (page_offset - STM_PAGE_SIZE);
363 +               }
364 +
365 +               spin_lock(&spidata->mutex);
366 +               spiflash_sendcmd(SPI_WRITE_ENABLE);
367 +
368 +               do {
369 +                       schedule();
370 +                       reg = spiflash_regread32(SPI_FLASH_CTL);
371 +               } while (reg & SPI_CTL_BUSY);
372 +       
373 +               switch (xact_len) {
374 +                       case 1:
375 +                               spi_data = (u32) ((u8) *buf);
376 +                               break;
377 +                       case 2:
378 +                               spi_data = (buf[1] << 8) | buf[0];
379 +                               break;
380 +                       case 3:
381 +                               spi_data = (buf[2] << 16) | (buf[1] << 8) | buf[0];
382 +                               break;
383 +                       case 4:
384 +                               spi_data = (buf[3] << 24) | (buf[2] << 16) | 
385 +                                                       (buf[1] << 8) | buf[0];
386 +                               break;
387 +                       default:
388 +                               printk("spiflash_write: default case\n");
389 +                               break;
390 +               }
391 +
392 +               spiflash_regwrite32(SPI_FLASH_DATA, spi_data);
393 +               opcode = (opcode & SPI_OPCODE_MASK) | ((__u32)to << 8);
394 +               spiflash_regwrite32(SPI_FLASH_OPCODE, opcode);
395 +
396 +               reg = (reg & ~SPI_CTL_TX_RX_CNT_MASK) | (xact_len + 4) | SPI_CTL_START;
397 +               spiflash_regwrite32(SPI_FLASH_CTL, reg);
398 +               finished = FALSE;
399 +               
400 +               do {
401 +                       schedule();
402 +                       reg = spiflash_sendcmd(SPI_RD_STATUS);
403 +                       if (!(reg & SPI_STATUS_WIP)) {
404 +                               finished = TRUE;
405 +                       }
406 +               } while (!finished);
407 +               spin_unlock(&spidata->mutex);
408 +
409 +               bytes_left -= xact_len;
410 +               to += xact_len;
411 +               buf += xact_len;
412 +
413 +               *retlen += xact_len;
414 +
415 +               if (bytes_left == 0) {
416 +                       done = TRUE;
417 +               }
418 +       }
419 +
420 +       return (0);
421 +}
422 +
423 +static void __init spidata_init(void)
424 +{
425 +       if (spidata)
426 +               return;
427 +                       
428 +       spidata = kmalloc(sizeof(struct spiflash_data), GFP_KERNEL);
429 +       spin_lock_init(&spidata->mutex);
430 +
431 +       if (!spidata)
432 +               return;
433 +
434 +       spidata->spiflash_mmraddr = ioremap_nocache(SPI_FLASH_MMR, SPI_FLASH_MMR_SIZE);
435 +       
436 +       if (!spidata->spiflash_mmraddr) {
437 +               printk (KERN_WARNING "%s: Failed to map flash device\n", module_name);
438 +               kfree(spidata);
439 +               spidata = NULL;
440 +       }
441 +}
442 +
443 +#ifdef CONFIG_MTD_PARTITIONS
444 +static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
445 +#endif
446 +
447 +int __init 
448 +spiflash_init (void)
449 +{
450 +       int result = -1, i, j;
451 +       u32 len;
452 +       int index, num_parts;
453 +       struct mtd_info *mtd;
454 +       struct  mtd_partition  *mtd_parts;
455 +       char *buf;
456 +       struct mtd_partition *part;
457 +       struct squashfs_super_block *sb;
458 +       u32 config_start;
459 +
460 +       spidata_init();
461 +
462 +       if (!spidata)
463 +               return (-ENXIO);
464 +       
465 +       mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
466 +       if (!mtd) {
467 +               kfree(spidata);
468 +               return (-ENXIO);
469 +       }
470 +       
471 +       printk ("MTD driver for SPI flash.\n");
472 +       printk ("%s: Probing for Serial flash ...\n", module_name);
473 +       if (!(index = spiflash_probe ())) {
474 +       printk (KERN_WARNING "%s: Found no serial flash device\n", module_name);
475 +               kfree(mtd);
476 +               kfree(spidata);
477 +       return (-ENXIO);
478 +       }
479 +
480 +       printk ("%s: Found SPI serial Flash.\n", module_name);
481 +
482 +       spidata->spiflash_readaddr = ioremap_nocache(SPI_FLASH_READ, flashconfig_tbl[index].byte_cnt);
483 +       if (!spidata->spiflash_readaddr) {
484 +                       printk (KERN_WARNING "%s: Failed to map flash device\n", module_name);
485 +               kfree(mtd);
486 +               kfree(spidata);
487 +                       return (-ENXIO);
488 +       }
489 +
490 +       mtd->name = module_name;
491 +       mtd->type = MTD_NORFLASH;
492 +       mtd->flags = (MTD_CAP_NORFLASH|MTD_WRITEABLE);
493 +       mtd->size = flashconfig_tbl[index].byte_cnt;
494 +       mtd->erasesize = flashconfig_tbl[index].sector_size;
495 +       mtd->writesize = 1;
496 +       mtd->numeraseregions = 0;
497 +       mtd->eraseregions = NULL;
498 +       mtd->erase = spiflash_erase;
499 +       mtd->read = spiflash_read;
500 +       mtd->write = spiflash_write;
501 +       mtd->owner = THIS_MODULE;
502 +
503 +#ifdef SPIFLASH_DEBUG
504 +       printk (KERN_DEBUG
505 +                  "mtd->name = %s\n"
506 +                  "mtd->size = 0x%.8x (%uM)\n"
507 +                  "mtd->erasesize = 0x%.8x (%uK)\n"
508 +                  "mtd->numeraseregions = %d\n",
509 +                  mtd->name,
510 +                  mtd->size, mtd->size / (1024*1024),
511 +                  mtd->erasesize, mtd->erasesize / 1024,
512 +                  mtd->numeraseregions);
513 +
514 +       if (mtd->numeraseregions) {
515 +               for (result = 0; result < mtd->numeraseregions; result++) {
516 +                       printk (KERN_DEBUG
517 +                          "\n\n"
518 +                          "mtd->eraseregions[%d].offset = 0x%.8x\n"
519 +                          "mtd->eraseregions[%d].erasesize = 0x%.8x (%uK)\n"
520 +                          "mtd->eraseregions[%d].numblocks = %d\n",
521 +                          result,mtd->eraseregions[result].offset,
522 +                          result,mtd->eraseregions[result].erasesize,mtd->eraseregions[result].erasesize / 1024,
523 +                          result,mtd->eraseregions[result].numblocks);
524 +               }
525 +       }
526 +#endif
527 +
528 +       /* parse redboot partitions */
529 +       num_parts = parse_mtd_partitions(mtd, part_probe_types, &spidata->parsed_parts, 0);
530 +
531 +       mtd_parts = kzalloc(sizeof(struct mtd_partition) * MAX_PARTS, GFP_KERNEL);
532 +       buf = kmalloc(mtd->erasesize, GFP_KERNEL);
533 +       sb = (struct squashfs_super_block *) buf;
534 +       for (i = j = 0; i < num_parts; i++, j++) {
535 +               part = &mtd_parts[j];
536 +               memcpy(part, &spidata->parsed_parts[i], sizeof(struct mtd_partition));
537 +               
538 +               if (!strcmp(part->name, ROOTFS_NAME)) {
539 +                       /* create the root device */
540 +                       ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, i);
541 +
542 +                       part->size -= mtd->erasesize;
543 +                       config_start = part->offset + part->size;
544 +
545 +                       while ((mtd->read(mtd, part->offset, mtd->erasesize, &len, buf) == 0) &&
546 +                                       (len == mtd->erasesize) &&
547 +                                       (*((u32 *) buf) == SQUASHFS_MAGIC) &&
548 +                                       (sb->bytes_used > 0)) {
549 +                                       
550 +                               /* this is squashfs, allocate another partition starting from the end of filesystem data */
551 +                               memcpy(&mtd_parts[j + 1], part, sizeof(struct mtd_partition));
552 +                       
553 +                               len = (u32) sb->bytes_used;
554 +                               len += (part->offset & 0x000fffff);
555 +                               len +=  (mtd->erasesize - 1);
556 +                               len &= ~(mtd->erasesize - 1);
557 +                               len -= (part->offset & 0x000fffff);
558 +
559 +                               if (len + mtd->erasesize > part->size)
560 +                                       break;
561 +
562 +                               part = &mtd_parts[++j];
563 +                               
564 +                               part->offset += len;
565 +                               part->size -= len;
566 +
567 +                               part->name = kmalloc(10, GFP_KERNEL);
568 +                               sprintf(part->name, "rootfs%d", j - i);
569 +                       }
570 +               }
571 +               if (!strcmp(part->name, "RedBoot config")) {
572 +                       /* add anoterh partition for the board config data */
573 +                       memcpy(&mtd_parts[j + 1], part, sizeof(struct mtd_partition));
574 +                       j++;
575 +                       part = &mtd_parts[j];
576 +                       part->offset += part->size;
577 +                       part->size = mtd->erasesize;
578 +                       
579 +                       part->name = kmalloc(16, GFP_KERNEL);
580 +                       sprintf(part->name, "board_config");
581 +               }
582 +       }
583 +       num_parts += j - i;
584 +       kfree(buf);
585 +
586 +#ifdef SPIFLASH_DEBUG
587 +       printk (KERN_DEBUG "Found %d redboot partitions\n", num_parts);
588 +#endif
589 +       if (num_parts) {
590 +               result = add_mtd_partitions(mtd, mtd_parts, num_parts);
591 +       } else {
592 +#ifdef SPIFLASH_DEBUG
593 +               printk (KERN_DEBUG "Did not find any redboot partitions\n");
594 +#endif
595 +               kfree(mtd);
596 +               kfree(spidata);
597 +                       return (-ENXIO);
598 +       }
599 +
600 +       spidata->mtd = mtd;
601 +
602 +       return (result);
603 +}
604 +
605 +void __exit 
606 +spiflash_exit (void)
607 +{
608 +       if (spidata && spidata->parsed_parts) {
609 +               del_mtd_partitions (spidata->mtd);
610 +               kfree(spidata->mtd);
611 +               kfree(spidata);
612 +       }
613 +}
614 +
615 +module_init (spiflash_init);
616 +module_exit (spiflash_exit);
617 +
618 +MODULE_LICENSE("GPL");
619 +MODULE_AUTHOR("Atheros Communications Inc");
620 +MODULE_DESCRIPTION("MTD driver for SPI Flash on Atheros SOC");
621 +
622 diff -urN linux.old/drivers/mtd/devices/spiflash.h linux.dev/drivers/mtd/devices/spiflash.h
623 --- linux.old/drivers/mtd/devices/spiflash.h    1970-01-01 01:00:00.000000000 +0100
624 +++ linux.dev/drivers/mtd/devices/spiflash.h    2006-12-15 06:59:43.000000000 +0100
625 @@ -0,0 +1,124 @@
626 +/*
627 + * SPI Flash Memory support header file.
628 + *
629 + * $Id: //depot/sw/releases/linuxsrc/src/kernels/mips-linux-2.4.25/drivers/mtd/devices/spiflash.h#3 $
630 + *
631 + *
632 + * Copyright (c) 2005, Atheros Communications Inc.
633 + * Copyright (C) 2006 FON Technology, SL.
634 + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
635 + *
636 + * This code is free software; you can redistribute it and/or modify
637 + * it under the terms of the GNU General Public License version 2 as
638 + * published by the Free Software Foundation.
639 + *
640 + */
641 +#define FLASH_1MB  1
642 +#define FLASH_2MB  2
643 +#define FLASH_4MB  3
644 +#define FLASH_8MB  4
645 +#define MAX_FLASH  5
646 +
647 +#define STM_PAGE_SIZE           256
648 +
649 +#define SPI_WRITE_ENABLE    0
650 +#define SPI_WRITE_DISABLE   1
651 +#define SPI_RD_STATUS       2
652 +#define SPI_WR_STATUS       3
653 +#define SPI_RD_DATA         4
654 +#define SPI_FAST_RD_DATA    5
655 +#define SPI_PAGE_PROGRAM    6
656 +#define SPI_SECTOR_ERASE    7
657 +#define SPI_BULK_ERASE      8
658 +#define SPI_DEEP_PWRDOWN    9
659 +#define SPI_RD_SIG          10
660 +#define SPI_MAX_OPCODES     11
661 +
662 +#define SFI_WRITE_BUFFER_SIZE   4
663 +#define SFI_FLASH_ADDR_MASK     0x00ffffff
664 +
665 +#define STM_8MBIT_SIGNATURE     0x13
666 +#define STM_M25P80_BYTE_COUNT   1048576
667 +#define STM_M25P80_SECTOR_COUNT 16
668 +#define STM_M25P80_SECTOR_SIZE  0x10000
669 +
670 +#define STM_16MBIT_SIGNATURE    0x14
671 +#define STM_M25P16_BYTE_COUNT   2097152
672 +#define STM_M25P16_SECTOR_COUNT 32
673 +#define STM_M25P16_SECTOR_SIZE  0x10000
674 +
675 +#define STM_32MBIT_SIGNATURE    0x15
676 +#define STM_M25P32_BYTE_COUNT   4194304
677 +#define STM_M25P32_SECTOR_COUNT 64
678 +#define STM_M25P32_SECTOR_SIZE  0x10000
679 +
680 +#define STM_64MBIT_SIGNATURE    0x16
681 +#define STM_M25P64_BYTE_COUNT   8388608
682 +#define STM_M25P64_SECTOR_COUNT 128
683 +#define STM_M25P64_SECTOR_SIZE  0x10000
684 +
685 +#define STM_1MB_BYTE_COUNT   STM_M25P80_BYTE_COUNT
686 +#define STM_1MB_SECTOR_COUNT STM_M25P80_SECTOR_COUNT
687 +#define STM_1MB_SECTOR_SIZE  STM_M25P80_SECTOR_SIZE
688 +#define STM_2MB_BYTE_COUNT   STM_M25P16_BYTE_COUNT
689 +#define STM_2MB_SECTOR_COUNT STM_M25P16_SECTOR_COUNT
690 +#define STM_2MB_SECTOR_SIZE  STM_M25P16_SECTOR_SIZE
691 +#define STM_4MB_BYTE_COUNT   STM_M25P32_BYTE_COUNT
692 +#define STM_4MB_SECTOR_COUNT STM_M25P32_SECTOR_COUNT
693 +#define STM_4MB_SECTOR_SIZE  STM_M25P32_SECTOR_SIZE
694 +#define STM_8MB_BYTE_COUNT   STM_M25P64_BYTE_COUNT
695 +#define STM_8MB_SECTOR_COUNT STM_M25P64_SECTOR_COUNT
696 +#define STM_8MB_SECTOR_SIZE  STM_M25P64_SECTOR_SIZE
697 +
698 +/*
699 + * ST Microelectronics Opcodes for Serial Flash
700 + */
701 +
702 +#define STM_OP_WR_ENABLE       0x06     /* Write Enable */
703 +#define STM_OP_WR_DISABLE      0x04     /* Write Disable */
704 +#define STM_OP_RD_STATUS       0x05     /* Read Status */
705 +#define STM_OP_WR_STATUS       0x01     /* Write Status */
706 +#define STM_OP_RD_DATA         0x03     /* Read Data */
707 +#define STM_OP_FAST_RD_DATA    0x0b     /* Fast Read Data */
708 +#define STM_OP_PAGE_PGRM       0x02     /* Page Program */
709 +#define STM_OP_SECTOR_ERASE    0xd8     /* Sector Erase */
710 +#define STM_OP_BULK_ERASE      0xc7     /* Bulk Erase */
711 +#define STM_OP_DEEP_PWRDOWN    0xb9     /* Deep Power-Down Mode */
712 +#define STM_OP_RD_SIG          0xab     /* Read Electronic Signature */
713 +
714 +#define STM_STATUS_WIP       0x01       /* Write-In-Progress */
715 +#define STM_STATUS_WEL       0x02       /* Write Enable Latch */
716 +#define STM_STATUS_BP0       0x04       /* Block Protect 0 */
717 +#define STM_STATUS_BP1       0x08       /* Block Protect 1 */
718 +#define STM_STATUS_BP2       0x10       /* Block Protect 2 */
719 +#define STM_STATUS_SRWD      0x80       /* Status Register Write Disable */
720 +
721 +/*
722 + * SPI Flash Interface Registers
723 + */
724 +#define AR531XPLUS_SPI_READ     0x08000000
725 +#define AR531XPLUS_SPI_MMR      0x11300000
726 +#define AR531XPLUS_SPI_MMR_SIZE 12
727 +
728 +#define AR531XPLUS_SPI_CTL      0x00
729 +#define AR531XPLUS_SPI_OPCODE   0x04
730 +#define AR531XPLUS_SPI_DATA     0x08
731 +
732 +#define SPI_FLASH_READ          AR531XPLUS_SPI_READ
733 +#define SPI_FLASH_MMR           AR531XPLUS_SPI_MMR
734 +#define SPI_FLASH_MMR_SIZE      AR531XPLUS_SPI_MMR_SIZE
735 +#define SPI_FLASH_CTL           AR531XPLUS_SPI_CTL
736 +#define SPI_FLASH_OPCODE        AR531XPLUS_SPI_OPCODE
737 +#define SPI_FLASH_DATA          AR531XPLUS_SPI_DATA
738 +
739 +#define SPI_CTL_START           0x00000100
740 +#define SPI_CTL_BUSY            0x00010000
741 +#define SPI_CTL_TXCNT_MASK      0x0000000f
742 +#define SPI_CTL_RXCNT_MASK      0x000000f0
743 +#define SPI_CTL_TX_RX_CNT_MASK  0x000000ff
744 +#define SPI_CTL_SIZE_MASK       0x00060000
745 +
746 +#define SPI_CTL_CLK_SEL_MASK    0x03000000
747 +#define SPI_OPCODE_MASK         0x000000ff
748 +
749 +#define SPI_STATUS_WIP         STM_STATUS_WIP
750