aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMike Lavender <mike@steroidmicros.com>2006-01-08 16:34:27 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-13 19:29:55 -0500
commit2f9f762879015d738a5ec2ac8a16be94b3a4a06d (patch)
tree73efe8bcdb970ee9c815c08358fb707b46aab983 /drivers
parent9904f22a7202c6b54e96b0cc9870817013c350a1 (diff)
[PATCH] spi: M25 series SPI flash
This was originally a driver for the ST M25P80 SPI flash. It's been updated slightly to handle other M25P series chips. For many of these chips, the specific type could be probed, but for now this just requires static setup with flash_platform_data that lists the chip type (size, format) and any default partitioning to use. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Mike Lavender <mike@steroidmicros.com> Cc: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/devices/Kconfig8
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/m25p80.c580
3 files changed, 589 insertions, 0 deletions
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 84f2eb1fae02..5038e90ceb12 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -55,6 +55,14 @@ config MTD_DATAFLASH
55 Sometimes DataFlash chips are packaged inside MMC-format 55 Sometimes DataFlash chips are packaged inside MMC-format
56 cards; at this writing, the MMC stack won't handle those. 56 cards; at this writing, the MMC stack won't handle those.
57 57
58config MTD_M25P80
59 tristate "Support for M25 SPI Flash"
60 depends on MTD && SPI_MASTER && EXPERIMENTAL
61 help
62 This enables access to ST M25P80 and similar SPI flash chips,
63 used for program and data storage. Set up your spi devices
64 with the right board-specific platform data.
65
58config MTD_SLRAM 66config MTD_SLRAM
59 tristate "Uncached system RAM" 67 tristate "Uncached system RAM"
60 depends on MTD 68 depends on MTD
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index cd8d8074b5b6..7c5ed2178380 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -24,3 +24,4 @@ obj-$(CONFIG_MTD_LART) += lart.o
24obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o 24obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o
25obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o 25obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
26obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o 26obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
27obj-$(CONFIG_MTD_M25P80) += m25p80.o
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
new file mode 100644
index 000000000000..71a072103a7f
--- /dev/null
+++ b/drivers/mtd/devices/m25p80.c
@@ -0,0 +1,580 @@
1/*
2 * MTD SPI driver for ST M25Pxx flash chips
3 *
4 * Author: Mike Lavender, mike@steroidmicros.com
5 *
6 * Copyright (c) 2005, Intec Automation Inc.
7 *
8 * Some parts are based on lart.c by Abraham Van Der Merwe
9 *
10 * Cleaned up and generalized based on mtd_dataflash.c
11 *
12 * This code is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/init.h>
19#include <linux/module.h>
20#include <linux/device.h>
21#include <linux/interrupt.h>
22#include <linux/interrupt.h>
23#include <linux/mtd/mtd.h>
24#include <linux/mtd/partitions.h>
25#include <linux/spi/spi.h>
26#include <linux/spi/flash.h>
27
28#include <asm/semaphore.h>
29
30
31/* NOTE: AT 25F and SST 25LF series are very similar,
32 * but commands for sector erase and chip id differ...
33 */
34
35#define FLASH_PAGESIZE 256
36
37/* Flash opcodes. */
38#define OPCODE_WREN 6 /* Write enable */
39#define OPCODE_RDSR 5 /* Read status register */
40#define OPCODE_READ 3 /* Read data bytes */
41#define OPCODE_PP 2 /* Page program */
42#define OPCODE_SE 0xd8 /* Sector erase */
43#define OPCODE_RES 0xab /* Read Electronic Signature */
44#define OPCODE_RDID 0x9f /* Read JEDEC ID */
45
46/* Status Register bits. */
47#define SR_WIP 1 /* Write in progress */
48#define SR_WEL 2 /* Write enable latch */
49#define SR_BP0 4 /* Block protect 0 */
50#define SR_BP1 8 /* Block protect 1 */
51#define SR_BP2 0x10 /* Block protect 2 */
52#define SR_SRWD 0x80 /* SR write protect */
53
54/* Define max times to check status register before we give up. */
55#define MAX_READY_WAIT_COUNT 100000
56
57
58#ifdef CONFIG_MTD_PARTITIONS
59#define mtd_has_partitions() (1)
60#else
61#define mtd_has_partitions() (0)
62#endif
63
64/****************************************************************************/
65
66struct m25p {
67 struct spi_device *spi;
68 struct semaphore lock;
69 struct mtd_info mtd;
70 unsigned partitioned;
71 u8 command[4];
72};
73
74static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
75{
76 return container_of(mtd, struct m25p, mtd);
77}
78
79/****************************************************************************/
80
81/*
82 * Internal helper functions
83 */
84
85/*
86 * Read the status register, returning its value in the location
87 * Return the status register value.
88 * Returns negative if error occurred.
89 */
90static int read_sr(struct m25p *flash)
91{
92 ssize_t retval;
93 u8 code = OPCODE_RDSR;
94 u8 val;
95
96 retval = spi_write_then_read(flash->spi, &code, 1, &val, 1);
97
98 if (retval < 0) {
99 dev_err(&flash->spi->dev, "error %d reading SR\n",
100 (int) retval);
101 return retval;
102 }
103
104 return val;
105}
106
107
108/*
109 * Set write enable latch with Write Enable command.
110 * Returns negative if error occurred.
111 */
112static inline int write_enable(struct m25p *flash)
113{
114 u8 code = OPCODE_WREN;
115
116 return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
117}
118
119
120/*
121 * Service routine to read status register until ready, or timeout occurs.
122 * Returns non-zero if error.
123 */
124static int wait_till_ready(struct m25p *flash)
125{
126 int count;
127 int sr;
128
129 /* one chip guarantees max 5 msec wait here after page writes,
130 * but potentially three seconds (!) after page erase.
131 */
132 for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
133 if ((sr = read_sr(flash)) < 0)
134 break;
135 else if (!(sr & SR_WIP))
136 return 0;
137
138 /* REVISIT sometimes sleeping would be best */
139 }
140
141 return 1;
142}
143
144
145/*
146 * Erase one sector of flash memory at offset ``offset'' which is any
147 * address within the sector which should be erased.
148 *
149 * Returns 0 if successful, non-zero otherwise.
150 */
151static int erase_sector(struct m25p *flash, u32 offset)
152{
153 DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id,
154 __FUNCTION__, offset);
155
156 /* Wait until finished previous write command. */
157 if (wait_till_ready(flash))
158 return 1;
159
160 /* Send write enable, then erase commands. */
161 write_enable(flash);
162
163 /* Set up command buffer. */
164 flash->command[0] = OPCODE_SE;
165 flash->command[1] = offset >> 16;
166 flash->command[2] = offset >> 8;
167 flash->command[3] = offset;
168
169 spi_write(flash->spi, flash->command, sizeof(flash->command));
170
171 return 0;
172}
173
174/****************************************************************************/
175
176/*
177 * MTD implementation
178 */
179
180/*
181 * Erase an address range on the flash chip. The address range may extend
182 * one or more erase sectors. Return an error is there is a problem erasing.
183 */
184static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
185{
186 struct m25p *flash = mtd_to_m25p(mtd);
187 u32 addr,len;
188
189 DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
190 flash->spi->dev.bus_id, __FUNCTION__, "at",
191 (u32)instr->addr, instr->len);
192
193 /* sanity checks */
194 if (instr->addr + instr->len > flash->mtd.size)
195 return -EINVAL;
196 if ((instr->addr % mtd->erasesize) != 0
197 || (instr->len % mtd->erasesize) != 0) {
198 return -EINVAL;
199 }
200
201 addr = instr->addr;
202 len = instr->len;
203
204 down(&flash->lock);
205
206 /* now erase those sectors */
207 while (len) {
208 if (erase_sector(flash, addr)) {
209 instr->state = MTD_ERASE_FAILED;
210 up(&flash->lock);
211 return -EIO;
212 }
213
214 addr += mtd->erasesize;
215 len -= mtd->erasesize;
216 }
217
218 up(&flash->lock);
219
220 instr->state = MTD_ERASE_DONE;
221 mtd_erase_callback(instr);
222
223 return 0;
224}
225
226/*
227 * Read an address range from the flash chip. The address range
228 * may be any size provided it is within the physical boundaries.
229 */
230static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
231 size_t *retlen, u_char *buf)
232{
233 struct m25p *flash = mtd_to_m25p(mtd);
234 struct spi_transfer t[2];
235 struct spi_message m;
236
237 DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
238 flash->spi->dev.bus_id, __FUNCTION__, "from",
239 (u32)from, len);
240
241 /* sanity checks */
242 if (!len)
243 return 0;
244
245 if (from + len > flash->mtd.size)
246 return -EINVAL;
247
248 down(&flash->lock);
249
250 /* Wait till previous write/erase is done. */
251 if (wait_till_ready(flash)) {
252 /* REVISIT status return?? */
253 up(&flash->lock);
254 return 1;
255 }
256
257 memset(t, 0, (sizeof t));
258
259 /* NOTE: OPCODE_FAST_READ (if available) is faster... */
260
261 /* Set up the write data buffer. */
262 flash->command[0] = OPCODE_READ;
263 flash->command[1] = from >> 16;
264 flash->command[2] = from >> 8;
265 flash->command[3] = from;
266
267 /* Byte count starts at zero. */
268 if (retlen)
269 *retlen = 0;
270
271 t[0].tx_buf = flash->command;
272 t[0].len = sizeof(flash->command);
273
274 t[1].rx_buf = buf;
275 t[1].len = len;
276
277 m.transfers = t;
278 m.n_transfer = 2;
279
280 spi_sync(flash->spi, &m);
281
282 *retlen = m.actual_length - sizeof(flash->command);
283
284 up(&flash->lock);
285
286 return 0;
287}
288
289/*
290 * Write an address range to the flash chip. Data must be written in
291 * FLASH_PAGESIZE chunks. The address range may be any size provided
292 * it is within the physical boundaries.
293 */
294static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
295 size_t *retlen, const u_char *buf)
296{
297 struct m25p *flash = mtd_to_m25p(mtd);
298 u32 page_offset, page_size;
299 struct spi_transfer t[2];
300 struct spi_message m;
301
302 DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
303 flash->spi->dev.bus_id, __FUNCTION__, "to",
304 (u32)to, len);
305
306 if (retlen)
307 *retlen = 0;
308
309 /* sanity checks */
310 if (!len)
311 return(0);
312
313 if (to + len > flash->mtd.size)
314 return -EINVAL;
315
316 down(&flash->lock);
317
318 /* Wait until finished previous write command. */
319 if (wait_till_ready(flash))
320 return 1;
321
322 write_enable(flash);
323
324 memset(t, 0, (sizeof t));
325
326 /* Set up the opcode in the write buffer. */
327 flash->command[0] = OPCODE_PP;
328 flash->command[1] = to >> 16;
329 flash->command[2] = to >> 8;
330 flash->command[3] = to;
331
332 t[0].tx_buf = flash->command;
333 t[0].len = sizeof(flash->command);
334
335 m.transfers = t;
336 m.n_transfer = 2;
337
338 /* what page do we start with? */
339 page_offset = to % FLASH_PAGESIZE;
340
341 /* do all the bytes fit onto one page? */
342 if (page_offset + len <= FLASH_PAGESIZE) {
343 t[1].tx_buf = buf;
344 t[1].len = len;
345
346 spi_sync(flash->spi, &m);
347
348 *retlen = m.actual_length - sizeof(flash->command);
349 } else {
350 u32 i;
351
352 /* the size of data remaining on the first page */
353 page_size = FLASH_PAGESIZE - page_offset;
354
355 t[1].tx_buf = buf;
356 t[1].len = page_size;
357 spi_sync(flash->spi, &m);
358
359 *retlen = m.actual_length - sizeof(flash->command);
360
361 /* write everything in PAGESIZE chunks */
362 for (i = page_size; i < len; i += page_size) {
363 page_size = len - i;
364 if (page_size > FLASH_PAGESIZE)
365 page_size = FLASH_PAGESIZE;
366
367 /* write the next page to flash */
368 flash->command[1] = (to + i) >> 16;
369 flash->command[2] = (to + i) >> 8;
370 flash->command[3] = (to + i);
371
372 t[1].tx_buf = buf + i;
373 t[1].len = page_size;
374
375 wait_till_ready(flash);
376
377 write_enable(flash);
378
379 spi_sync(flash->spi, &m);
380
381 *retlen += m.actual_length - sizeof(flash->command);
382 }
383 }
384
385 up(&flash->lock);
386
387 return 0;
388}
389
390
391/****************************************************************************/
392
393/*
394 * SPI device driver setup and teardown
395 */
396
397struct flash_info {
398 char *name;
399 u8 id;
400 u16 jedec_id;
401 unsigned sector_size;
402 unsigned n_sectors;
403};
404
405static struct flash_info __devinitdata m25p_data [] = {
406 /* REVISIT: fill in JEDEC ids, for parts that have them */
407 { "m25p05", 0x05, 0x0000, 32 * 1024, 2 },
408 { "m25p10", 0x10, 0x0000, 32 * 1024, 4 },
409 { "m25p20", 0x11, 0x0000, 64 * 1024, 4 },
410 { "m25p40", 0x12, 0x0000, 64 * 1024, 8 },
411 { "m25p80", 0x13, 0x0000, 64 * 1024, 16 },
412 { "m25p16", 0x14, 0x0000, 64 * 1024, 32 },
413 { "m25p32", 0x15, 0x0000, 64 * 1024, 64 },
414 { "m25p64", 0x16, 0x2017, 64 * 1024, 128 },
415};
416
417/*
418 * board specific setup should have ensured the SPI clock used here
419 * matches what the READ command supports, at least until this driver
420 * understands FAST_READ (for clocks over 25 MHz).
421 */
422static int __devinit m25p_probe(struct spi_device *spi)
423{
424 struct flash_platform_data *data;
425 struct m25p *flash;
426 struct flash_info *info;
427 unsigned i;
428
429 /* Platform data helps sort out which chip type we have, as
430 * well as how this board partitions it.
431 */
432 data = spi->dev.platform_data;
433 if (!data || !data->type) {
434 /* FIXME some chips can identify themselves with RES
435 * or JEDEC get-id commands. Try them ...
436 */
437 DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n",
438 flash->spi->dev.bus_id);
439 return -ENODEV;
440 }
441
442 for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) {
443 if (strcmp(data->type, info->name) == 0)
444 break;
445 }
446 if (i == ARRAY_SIZE(m25p_data)) {
447 DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n",
448 flash->spi->dev.bus_id, data->type);
449 return -ENODEV;
450 }
451
452 flash = kzalloc(sizeof *flash, SLAB_KERNEL);
453 if (!flash)
454 return -ENOMEM;
455
456 flash->spi = spi;
457 init_MUTEX(&flash->lock);
458 dev_set_drvdata(&spi->dev, flash);
459
460 if (data->name)
461 flash->mtd.name = data->name;
462 else
463 flash->mtd.name = spi->dev.bus_id;
464
465 flash->mtd.type = MTD_NORFLASH;
466 flash->mtd.flags = MTD_CAP_NORFLASH;
467 flash->mtd.size = info->sector_size * info->n_sectors;
468 flash->mtd.erasesize = info->sector_size;
469 flash->mtd.erase = m25p80_erase;
470 flash->mtd.read = m25p80_read;
471 flash->mtd.write = m25p80_write;
472
473 dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
474 flash->mtd.size / 1024);
475
476 DEBUG(MTD_DEBUG_LEVEL2,
477 "mtd .name = %s, .size = 0x%.8x (%uM) "
478 ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n",
479 flash->mtd.name,
480 flash->mtd.size, flash->mtd.size / (1024*1024),
481 flash->mtd.erasesize, flash->mtd.erasesize / 1024,
482 flash->mtd.numeraseregions);
483
484 if (flash->mtd.numeraseregions)
485 for (i = 0; i < flash->mtd.numeraseregions; i++)
486 DEBUG(MTD_DEBUG_LEVEL2,
487 "mtd.eraseregions[%d] = { .offset = 0x%.8x, "
488 ".erasesize = 0x%.8x (%uK), "
489 ".numblocks = %d }\n",
490 i, flash->mtd.eraseregions[i].offset,
491 flash->mtd.eraseregions[i].erasesize,
492 flash->mtd.eraseregions[i].erasesize / 1024,
493 flash->mtd.eraseregions[i].numblocks);
494
495
496 /* partitions should match sector boundaries; and it may be good to
497 * use readonly partitions for writeprotected sectors (BP2..BP0).
498 */
499 if (mtd_has_partitions()) {
500 struct mtd_partition *parts = NULL;
501 int nr_parts = 0;
502
503#ifdef CONFIG_MTD_CMDLINE_PARTS
504 static const char *part_probes[] = { "cmdlinepart", NULL, };
505
506 nr_parts = parse_mtd_partitions(&flash->mtd,
507 part_probes, &parts, 0);
508#endif
509
510 if (nr_parts <= 0 && data && data->parts) {
511 parts = data->parts;
512 nr_parts = data->nr_parts;
513 }
514
515 if (nr_parts > 0) {
516 for (i = 0; i < data->nr_parts; i++) {
517 DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
518 "{.name = %s, .offset = 0x%.8x, "
519 ".size = 0x%.8x (%uK) }\n",
520 i, data->parts[i].name,
521 data->parts[i].offset,
522 data->parts[i].size,
523 data->parts[i].size / 1024);
524 }
525 flash->partitioned = 1;
526 return add_mtd_partitions(&flash->mtd, parts, nr_parts);
527 }
528 } else if (data->nr_parts)
529 dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
530 data->nr_parts, data->name);
531
532 return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0;
533}
534
535
536static int __devexit m25p_remove(struct spi_device *spi)
537{
538 struct m25p *flash = dev_get_drvdata(&spi->dev);
539 int status;
540
541 /* Clean up MTD stuff. */
542 if (mtd_has_partitions() && flash->partitioned)
543 status = del_mtd_partitions(&flash->mtd);
544 else
545 status = del_mtd_device(&flash->mtd);
546 if (status == 0)
547 kfree(flash);
548 return 0;
549}
550
551
552static struct spi_driver m25p80_driver = {
553 .driver = {
554 .name = "m25p80",
555 .bus = &spi_bus_type,
556 .owner = THIS_MODULE,
557 },
558 .probe = m25p_probe,
559 .remove = __devexit_p(m25p_remove),
560};
561
562
563static int m25p80_init(void)
564{
565 return spi_register_driver(&m25p80_driver);
566}
567
568
569static void m25p80_exit(void)
570{
571 spi_unregister_driver(&m25p80_driver);
572}
573
574
575module_init(m25p80_init);
576module_exit(m25p80_exit);
577
578MODULE_LICENSE("GPL");
579MODULE_AUTHOR("Mike Lavender");
580MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips");