Add support for Atheros SoC (used in Fonera, Meraki) - Merry Christmas, everybody :)
[openwrt/svn-archive/archive.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