[PATCH] spi: mtd dataflash driver

This is a conversion of the AT91rm9200 DataFlash MTD driver to use the
lightweight SPI framework, and no longer be AT91-specific. It compiles
down to less than 3KBytes on ARM.

The driver allows board-specific init code to provide platform_data with
the relevant MTD partitioning information, and hotplugs.

This version has been lightly tested. Its parent at91_dataflash driver has
been pretty well banged on, although kernel.org JFFS2 dataflash support was
acting broken the last time I tried it.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by David Brownell and committed by Greg Kroah-Hartman 1d6432fe ffa458c1

+659
+8
drivers/mtd/devices/Kconfig
··· 47 47 accelerator. Say Y here if you have a DECstation 5000/2x0 or a 48 48 DECsystem 5900 equipped with such a module. 49 49 50 + config MTD_DATAFLASH 51 + tristate "Support for AT45xxx DataFlash" 52 + depends on MTD && SPI_MASTER && EXPERIMENTAL 53 + help 54 + This enables access to AT45xxx DataFlash chips, using SPI. 55 + Sometimes DataFlash chips are packaged inside MMC-format 56 + cards; at this writing, the MMC stack won't handle those. 57 + 50 58 config MTD_SLRAM 51 59 tristate "Uncached system RAM" 52 60 depends on MTD
+1
drivers/mtd/devices/Makefile
··· 23 23 obj-$(CONFIG_MTD_LART) += lart.o 24 24 obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o 25 25 obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o 26 + obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
+623
drivers/mtd/devices/mtd_dataflash.c
··· 1 + /* 2 + * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework 3 + * 4 + * Largely derived from at91_dataflash.c: 5 + * Copyright (C) 2003-2005 SAN People (Pty) Ltd 6 + * 7 + * This program is free software; you can redistribute it and/or 8 + * modify it under the terms of the GNU General Public License 9 + * as published by the Free Software Foundation; either version 10 + * 2 of the License, or (at your option) any later version. 11 + */ 12 + #include <linux/config.h> 13 + #include <linux/module.h> 14 + #include <linux/init.h> 15 + #include <linux/slab.h> 16 + #include <linux/delay.h> 17 + #include <linux/device.h> 18 + #include <linux/spi/spi.h> 19 + #include <linux/spi/flash.h> 20 + 21 + #include <linux/mtd/mtd.h> 22 + #include <linux/mtd/partitions.h> 23 + 24 + 25 + /* 26 + * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in 27 + * each chip, which may be used for double buffered I/O; but this driver 28 + * doesn't (yet) use these for any kind of i/o overlap or prefetching. 29 + * 30 + * Sometimes DataFlash is packaged in MMC-format cards, although the 31 + * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash 32 + * protocols during enumeration. 33 + */ 34 + 35 + #define CONFIG_DATAFLASH_WRITE_VERIFY 36 + 37 + /* reads can bypass the buffers */ 38 + #define OP_READ_CONTINUOUS 0xE8 39 + #define OP_READ_PAGE 0xD2 40 + 41 + /* group B requests can run even while status reports "busy" */ 42 + #define OP_READ_STATUS 0xD7 /* group B */ 43 + 44 + /* move data between host and buffer */ 45 + #define OP_READ_BUFFER1 0xD4 /* group B */ 46 + #define OP_READ_BUFFER2 0xD6 /* group B */ 47 + #define OP_WRITE_BUFFER1 0x84 /* group B */ 48 + #define OP_WRITE_BUFFER2 0x87 /* group B */ 49 + 50 + /* erasing flash */ 51 + #define OP_ERASE_PAGE 0x81 52 + #define OP_ERASE_BLOCK 0x50 53 + 54 + /* move data between buffer and flash */ 55 + #define OP_TRANSFER_BUF1 0x53 56 + #define OP_TRANSFER_BUF2 0x55 57 + #define OP_MREAD_BUFFER1 0xD4 58 + #define OP_MREAD_BUFFER2 0xD6 59 + #define OP_MWERASE_BUFFER1 0x83 60 + #define OP_MWERASE_BUFFER2 0x86 61 + #define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ 62 + #define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ 63 + 64 + /* write to buffer, then write-erase to flash */ 65 + #define OP_PROGRAM_VIA_BUF1 0x82 66 + #define OP_PROGRAM_VIA_BUF2 0x85 67 + 68 + /* compare buffer to flash */ 69 + #define OP_COMPARE_BUF1 0x60 70 + #define OP_COMPARE_BUF2 0x61 71 + 72 + /* read flash to buffer, then write-erase to flash */ 73 + #define OP_REWRITE_VIA_BUF1 0x58 74 + #define OP_REWRITE_VIA_BUF2 0x59 75 + 76 + /* newer chips report JEDEC manufacturer and device IDs; chip 77 + * serial number and OTP bits; and per-sector writeprotect. 78 + */ 79 + #define OP_READ_ID 0x9F 80 + #define OP_READ_SECURITY 0x77 81 + #define OP_WRITE_SECURITY 0x9A /* OTP bits */ 82 + 83 + 84 + struct dataflash { 85 + u8 command[4]; 86 + char name[24]; 87 + 88 + unsigned partitioned:1; 89 + 90 + unsigned short page_offset; /* offset in flash address */ 91 + unsigned int page_size; /* of bytes per page */ 92 + 93 + struct semaphore lock; 94 + struct spi_device *spi; 95 + 96 + struct mtd_info mtd; 97 + }; 98 + 99 + #ifdef CONFIG_MTD_PARTITIONS 100 + #define mtd_has_partitions() (1) 101 + #else 102 + #define mtd_has_partitions() (0) 103 + #endif 104 + 105 + /* ......................................................................... */ 106 + 107 + /* 108 + * Return the status of the DataFlash device. 109 + */ 110 + static inline int dataflash_status(struct spi_device *spi) 111 + { 112 + /* NOTE: at45db321c over 25 MHz wants to write 113 + * a dummy byte after the opcode... 114 + */ 115 + return spi_w8r8(spi, OP_READ_STATUS); 116 + } 117 + 118 + /* 119 + * Poll the DataFlash device until it is READY. 120 + * This usually takes 5-20 msec or so; more for sector erase. 121 + */ 122 + static int dataflash_waitready(struct spi_device *spi) 123 + { 124 + int status; 125 + 126 + for (;;) { 127 + status = dataflash_status(spi); 128 + if (status < 0) { 129 + DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n", 130 + spi->dev.bus_id, status); 131 + status = 0; 132 + } 133 + 134 + if (status & (1 << 7)) /* RDY/nBSY */ 135 + return status; 136 + 137 + msleep(3); 138 + } 139 + } 140 + 141 + /* ......................................................................... */ 142 + 143 + /* 144 + * Erase pages of flash. 145 + */ 146 + static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) 147 + { 148 + struct dataflash *priv = (struct dataflash *)mtd->priv; 149 + struct spi_device *spi = priv->spi; 150 + struct spi_transfer x[1] = { { .tx_dma = 0, }, }; 151 + struct spi_message msg; 152 + unsigned blocksize = priv->page_size << 3; 153 + u8 *command; 154 + 155 + DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n", 156 + spi->dev.bus_id, 157 + instr->addr, instr->len); 158 + 159 + /* Sanity checks */ 160 + if ((instr->addr + instr->len) > mtd->size 161 + || (instr->len % priv->page_size) != 0 162 + || (instr->addr % priv->page_size) != 0) 163 + return -EINVAL; 164 + 165 + x[0].tx_buf = command = priv->command; 166 + x[0].len = 4; 167 + msg.transfers = x; 168 + msg.n_transfer = 1; 169 + 170 + down(&priv->lock); 171 + while (instr->len > 0) { 172 + unsigned int pageaddr; 173 + int status; 174 + int do_block; 175 + 176 + /* Calculate flash page address; use block erase (for speed) if 177 + * we're at a block boundary and need to erase the whole block. 178 + */ 179 + pageaddr = instr->addr / priv->page_size; 180 + do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize; 181 + pageaddr = pageaddr << priv->page_offset; 182 + 183 + command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; 184 + command[1] = (u8)(pageaddr >> 16); 185 + command[2] = (u8)(pageaddr >> 8); 186 + command[3] = 0; 187 + 188 + DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n", 189 + do_block ? "block" : "page", 190 + command[0], command[1], command[2], command[3], 191 + pageaddr); 192 + 193 + status = spi_sync(spi, &msg); 194 + (void) dataflash_waitready(spi); 195 + 196 + if (status < 0) { 197 + printk(KERN_ERR "%s: erase %x, err %d\n", 198 + spi->dev.bus_id, pageaddr, status); 199 + /* REVISIT: can retry instr->retries times; or 200 + * giveup and instr->fail_addr = instr->addr; 201 + */ 202 + continue; 203 + } 204 + 205 + if (do_block) { 206 + instr->addr += blocksize; 207 + instr->len -= blocksize; 208 + } else { 209 + instr->addr += priv->page_size; 210 + instr->len -= priv->page_size; 211 + } 212 + } 213 + up(&priv->lock); 214 + 215 + /* Inform MTD subsystem that erase is complete */ 216 + instr->state = MTD_ERASE_DONE; 217 + mtd_erase_callback(instr); 218 + 219 + return 0; 220 + } 221 + 222 + /* 223 + * Read from the DataFlash device. 224 + * from : Start offset in flash device 225 + * len : Amount to read 226 + * retlen : About of data actually read 227 + * buf : Buffer containing the data 228 + */ 229 + static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, 230 + size_t *retlen, u_char *buf) 231 + { 232 + struct dataflash *priv = (struct dataflash *)mtd->priv; 233 + struct spi_transfer x[2] = { { .tx_dma = 0, }, }; 234 + struct spi_message msg; 235 + unsigned int addr; 236 + u8 *command; 237 + int status; 238 + 239 + DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n", 240 + priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len)); 241 + 242 + *retlen = 0; 243 + 244 + /* Sanity checks */ 245 + if (!len) 246 + return 0; 247 + if (from + len > mtd->size) 248 + return -EINVAL; 249 + 250 + /* Calculate flash page/byte address */ 251 + addr = (((unsigned)from / priv->page_size) << priv->page_offset) 252 + + ((unsigned)from % priv->page_size); 253 + 254 + command = priv->command; 255 + 256 + DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", 257 + command[0], command[1], command[2], command[3]); 258 + 259 + x[0].tx_buf = command; 260 + x[0].len = 8; 261 + x[1].rx_buf = buf; 262 + x[1].len = len; 263 + msg.transfers = x; 264 + msg.n_transfer = 2; 265 + 266 + down(&priv->lock); 267 + 268 + /* Continuous read, max clock = f(car) which may be less than 269 + * the peak rate available. Some chips support commands with 270 + * fewer "don't care" bytes. Both buffers stay unchanged. 271 + */ 272 + command[0] = OP_READ_CONTINUOUS; 273 + command[1] = (u8)(addr >> 16); 274 + command[2] = (u8)(addr >> 8); 275 + command[3] = (u8)(addr >> 0); 276 + /* plus 4 "don't care" bytes */ 277 + 278 + status = spi_sync(priv->spi, &msg); 279 + up(&priv->lock); 280 + 281 + if (status >= 0) { 282 + *retlen = msg.actual_length - 8; 283 + status = 0; 284 + } else 285 + DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n", 286 + priv->spi->dev.bus_id, 287 + (unsigned)from, (unsigned)(from + len), 288 + status); 289 + return status; 290 + } 291 + 292 + /* 293 + * Write to the DataFlash device. 294 + * to : Start offset in flash device 295 + * len : Amount to write 296 + * retlen : Amount of data actually written 297 + * buf : Buffer containing the data 298 + */ 299 + static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, 300 + size_t * retlen, const u_char * buf) 301 + { 302 + struct dataflash *priv = (struct dataflash *)mtd->priv; 303 + struct spi_device *spi = priv->spi; 304 + struct spi_transfer x[2] = { { .tx_dma = 0, }, }; 305 + struct spi_message msg; 306 + unsigned int pageaddr, addr, offset, writelen; 307 + size_t remaining = len; 308 + u_char *writebuf = (u_char *) buf; 309 + int status = -EINVAL; 310 + u8 *command; 311 + 312 + DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n", 313 + spi->dev.bus_id, (unsigned)to, (unsigned)(to + len)); 314 + 315 + *retlen = 0; 316 + 317 + /* Sanity checks */ 318 + if (!len) 319 + return 0; 320 + if ((to + len) > mtd->size) 321 + return -EINVAL; 322 + 323 + x[0].tx_buf = command = priv->command; 324 + x[0].len = 4; 325 + msg.transfers = x; 326 + 327 + pageaddr = ((unsigned)to / priv->page_size); 328 + offset = ((unsigned)to % priv->page_size); 329 + if (offset + len > priv->page_size) 330 + writelen = priv->page_size - offset; 331 + else 332 + writelen = len; 333 + 334 + down(&priv->lock); 335 + while (remaining > 0) { 336 + DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n", 337 + pageaddr, offset, writelen); 338 + 339 + /* REVISIT: 340 + * (a) each page in a sector must be rewritten at least 341 + * once every 10K sibling erase/program operations. 342 + * (b) for pages that are already erased, we could 343 + * use WRITE+MWRITE not PROGRAM for ~30% speedup. 344 + * (c) WRITE to buffer could be done while waiting for 345 + * a previous MWRITE/MWERASE to complete ... 346 + * (d) error handling here seems to be mostly missing. 347 + * 348 + * Two persistent bits per page, plus a per-sector counter, 349 + * could support (a) and (b) ... we might consider using 350 + * the second half of sector zero, which is just one block, 351 + * to track that state. (On AT91, that sector should also 352 + * support boot-from-DataFlash.) 353 + */ 354 + 355 + addr = pageaddr << priv->page_offset; 356 + 357 + /* (1) Maybe transfer partial page to Buffer1 */ 358 + if (writelen != priv->page_size) { 359 + command[0] = OP_TRANSFER_BUF1; 360 + command[1] = (addr & 0x00FF0000) >> 16; 361 + command[2] = (addr & 0x0000FF00) >> 8; 362 + command[3] = 0; 363 + 364 + DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", 365 + command[0], command[1], command[2], command[3]); 366 + 367 + msg.n_transfer = 1; 368 + status = spi_sync(spi, &msg); 369 + if (status < 0) 370 + DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", 371 + spi->dev.bus_id, addr, status); 372 + 373 + (void) dataflash_waitready(priv->spi); 374 + } 375 + 376 + /* (2) Program full page via Buffer1 */ 377 + addr += offset; 378 + command[0] = OP_PROGRAM_VIA_BUF1; 379 + command[1] = (addr & 0x00FF0000) >> 16; 380 + command[2] = (addr & 0x0000FF00) >> 8; 381 + command[3] = (addr & 0x000000FF); 382 + 383 + DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n", 384 + command[0], command[1], command[2], command[3]); 385 + 386 + x[1].tx_buf = writebuf; 387 + x[1].len = writelen; 388 + msg.n_transfer = 2; 389 + status = spi_sync(spi, &msg); 390 + if (status < 0) 391 + DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", 392 + spi->dev.bus_id, addr, writelen, status); 393 + 394 + (void) dataflash_waitready(priv->spi); 395 + 396 + #ifdef CONFIG_DATAFLASH_WRITE_VERIFY 397 + 398 + /* (3) Compare to Buffer1 */ 399 + addr = pageaddr << priv->page_offset; 400 + command[0] = OP_COMPARE_BUF1; 401 + command[1] = (addr & 0x00FF0000) >> 16; 402 + command[2] = (addr & 0x0000FF00) >> 8; 403 + command[3] = 0; 404 + 405 + DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", 406 + command[0], command[1], command[2], command[3]); 407 + 408 + msg.n_transfer = 1; 409 + status = spi_sync(spi, &msg); 410 + if (status < 0) 411 + DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", 412 + spi->dev.bus_id, addr, status); 413 + 414 + status = dataflash_waitready(priv->spi); 415 + 416 + /* Check result of the compare operation */ 417 + if ((status & (1 << 6)) == 1) { 418 + printk(KERN_ERR "%s: compare page %u, err %d\n", 419 + spi->dev.bus_id, pageaddr, status); 420 + remaining = 0; 421 + status = -EIO; 422 + break; 423 + } else 424 + status = 0; 425 + 426 + #endif /* CONFIG_DATAFLASH_WRITE_VERIFY */ 427 + 428 + remaining = remaining - writelen; 429 + pageaddr++; 430 + offset = 0; 431 + writebuf += writelen; 432 + *retlen += writelen; 433 + 434 + if (remaining > priv->page_size) 435 + writelen = priv->page_size; 436 + else 437 + writelen = remaining; 438 + } 439 + up(&priv->lock); 440 + 441 + return status; 442 + } 443 + 444 + /* ......................................................................... */ 445 + 446 + /* 447 + * Register DataFlash device with MTD subsystem. 448 + */ 449 + static int __devinit 450 + add_dataflash(struct spi_device *spi, char *name, 451 + int nr_pages, int pagesize, int pageoffset) 452 + { 453 + struct dataflash *priv; 454 + struct mtd_info *device; 455 + struct flash_platform_data *pdata = spi->dev.platform_data; 456 + 457 + priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL); 458 + if (!priv) 459 + return -ENOMEM; 460 + 461 + init_MUTEX(&priv->lock); 462 + priv->spi = spi; 463 + priv->page_size = pagesize; 464 + priv->page_offset = pageoffset; 465 + 466 + /* name must be usable with cmdlinepart */ 467 + sprintf(priv->name, "spi%d.%d-%s", 468 + spi->master->bus_num, spi->chip_select, 469 + name); 470 + 471 + device = &priv->mtd; 472 + device->name = (pdata && pdata->name) ? pdata->name : priv->name; 473 + device->size = nr_pages * pagesize; 474 + device->erasesize = pagesize; 475 + device->owner = THIS_MODULE; 476 + device->type = MTD_DATAFLASH; 477 + device->flags = MTD_CAP_NORFLASH; 478 + device->erase = dataflash_erase; 479 + device->read = dataflash_read; 480 + device->write = dataflash_write; 481 + device->priv = priv; 482 + 483 + dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024); 484 + dev_set_drvdata(&spi->dev, priv); 485 + 486 + if (mtd_has_partitions()) { 487 + struct mtd_partition *parts; 488 + int nr_parts = 0; 489 + 490 + #ifdef CONFIG_MTD_CMDLINE_PARTS 491 + static const char *part_probes[] = { "cmdlinepart", NULL, }; 492 + 493 + nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0); 494 + #endif 495 + 496 + if (nr_parts <= 0 && pdata && pdata->parts) { 497 + parts = pdata->parts; 498 + nr_parts = pdata->nr_parts; 499 + } 500 + 501 + if (nr_parts > 0) { 502 + priv->partitioned = 1; 503 + return add_mtd_partitions(device, parts, nr_parts); 504 + } 505 + } else if (pdata->nr_parts) 506 + dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", 507 + pdata->nr_parts, device->name); 508 + 509 + return add_mtd_device(device) == 1 ? -ENODEV : 0; 510 + } 511 + 512 + /* 513 + * Detect and initialize DataFlash device: 514 + * 515 + * Device Density ID code #Pages PageSize Offset 516 + * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 517 + * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9 518 + * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 519 + * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 520 + * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 521 + * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 522 + * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 523 + * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 524 + */ 525 + static int __devinit dataflash_probe(struct spi_device *spi) 526 + { 527 + int status; 528 + 529 + status = dataflash_status(spi); 530 + if (status <= 0 || status == 0xff) { 531 + DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n", 532 + spi->dev.bus_id, status); 533 + if (status == 0xff) 534 + status = -ENODEV; 535 + return status; 536 + } 537 + 538 + /* if there's a device there, assume it's dataflash. 539 + * board setup should have set spi->max_speed_max to 540 + * match f(car) for continuous reads, mode 0 or 3. 541 + */ 542 + switch (status & 0x3c) { 543 + case 0x0c: /* 0 0 1 1 x x */ 544 + status = add_dataflash(spi, "AT45DB011B", 512, 264, 9); 545 + break; 546 + case 0x14: /* 0 1 0 1 x x */ 547 + status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9); 548 + break; 549 + case 0x1c: /* 0 1 1 1 x x */ 550 + status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9); 551 + break; 552 + case 0x24: /* 1 0 0 1 x x */ 553 + status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9); 554 + break; 555 + case 0x2c: /* 1 0 1 1 x x */ 556 + status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10); 557 + break; 558 + case 0x34: /* 1 1 0 1 x x */ 559 + status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10); 560 + break; 561 + case 0x38: /* 1 1 1 x x x */ 562 + case 0x3c: 563 + status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11); 564 + break; 565 + /* obsolete AT45DB1282 not (yet?) supported */ 566 + default: 567 + DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n", 568 + spi->dev.bus_id, status & 0x3c); 569 + status = -ENODEV; 570 + } 571 + 572 + if (status < 0) 573 + DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n", 574 + spi->dev.bus_id, status); 575 + 576 + return status; 577 + } 578 + 579 + static int __devexit dataflash_remove(struct spi_device *spi) 580 + { 581 + struct dataflash *flash = dev_get_drvdata(&spi->dev); 582 + int status; 583 + 584 + DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id); 585 + 586 + if (mtd_has_partitions() && flash->partitioned) 587 + status = del_mtd_partitions(&flash->mtd); 588 + else 589 + status = del_mtd_device(&flash->mtd); 590 + if (status == 0) 591 + kfree(flash); 592 + return status; 593 + } 594 + 595 + static struct spi_driver dataflash_driver = { 596 + .driver = { 597 + .name = "mtd_dataflash", 598 + .bus = &spi_bus_type, 599 + .owner = THIS_MODULE, 600 + }, 601 + 602 + .probe = dataflash_probe, 603 + .remove = __devexit_p(dataflash_remove), 604 + 605 + /* FIXME: investigate suspend and resume... */ 606 + }; 607 + 608 + static int __init dataflash_init(void) 609 + { 610 + return spi_register_driver(&dataflash_driver); 611 + } 612 + module_init(dataflash_init); 613 + 614 + static void __exit dataflash_exit(void) 615 + { 616 + spi_unregister_driver(&dataflash_driver); 617 + } 618 + module_exit(dataflash_exit); 619 + 620 + 621 + MODULE_LICENSE("GPL"); 622 + MODULE_AUTHOR("Andrew Victor, David Brownell"); 623 + MODULE_DESCRIPTION("MTD DataFlash driver");
+27
include/linux/spi/flash.h
··· 1 + #ifndef LINUX_SPI_FLASH_H 2 + #define LINUX_SPI_FLASH_H 3 + 4 + struct mtd_partition; 5 + 6 + /** 7 + * struct flash_platform_data: board-specific flash data 8 + * @name: optional flash device name (eg, as used with mtdparts=) 9 + * @parts: optional array of mtd_partitions for static partitioning 10 + * @nr_parts: number of mtd_partitions for static partitoning 11 + * 12 + * Board init code (in arch/.../mach-xxx/board-yyy.c files) can 13 + * provide information about SPI flash parts (such as DataFlash) to 14 + * help set up the device and its appropriate default partitioning. 15 + * 16 + * Note that for DataFlash, sizes for pages, blocks, and sectors are 17 + * rarely powers of two; and partitions should be sector-aligned. 18 + */ 19 + struct flash_platform_data { 20 + char *name; 21 + struct mtd_partition *parts; 22 + unsigned int nr_parts; 23 + 24 + /* we'll likely add more ... use JEDEC IDs, etc */ 25 + }; 26 + 27 + #endif