diff options
Diffstat (limited to 'drivers/mtd/devices/mtd_dataflash.c')
-rw-r--r-- | drivers/mtd/devices/mtd_dataflash.c | 214 |
1 files changed, 202 insertions, 12 deletions
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index 8bd0dea6885f..6dd9aff8bb2d 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -30,12 +30,10 @@ | |||
30 | * doesn't (yet) use these for any kind of i/o overlap or prefetching. | 30 | * doesn't (yet) use these for any kind of i/o overlap or prefetching. |
31 | * | 31 | * |
32 | * Sometimes DataFlash is packaged in MMC-format cards, although the | 32 | * Sometimes DataFlash is packaged in MMC-format cards, although the |
33 | * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash | 33 | * MMC stack can't (yet?) distinguish between MMC and DataFlash |
34 | * protocols during enumeration. | 34 | * protocols during enumeration. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #define CONFIG_DATAFLASH_WRITE_VERIFY | ||
38 | |||
39 | /* reads can bypass the buffers */ | 37 | /* reads can bypass the buffers */ |
40 | #define OP_READ_CONTINUOUS 0xE8 | 38 | #define OP_READ_CONTINUOUS 0xE8 |
41 | #define OP_READ_PAGE 0xD2 | 39 | #define OP_READ_PAGE 0xD2 |
@@ -80,7 +78,8 @@ | |||
80 | */ | 78 | */ |
81 | #define OP_READ_ID 0x9F | 79 | #define OP_READ_ID 0x9F |
82 | #define OP_READ_SECURITY 0x77 | 80 | #define OP_READ_SECURITY 0x77 |
83 | #define OP_WRITE_SECURITY 0x9A /* OTP bits */ | 81 | #define OP_WRITE_SECURITY_REVC 0x9A |
82 | #define OP_WRITE_SECURITY 0x9B /* revision D */ | ||
84 | 83 | ||
85 | 84 | ||
86 | struct dataflash { | 85 | struct dataflash { |
@@ -402,7 +401,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
402 | (void) dataflash_waitready(priv->spi); | 401 | (void) dataflash_waitready(priv->spi); |
403 | 402 | ||
404 | 403 | ||
405 | #ifdef CONFIG_DATAFLASH_WRITE_VERIFY | 404 | #ifdef CONFIG_MTD_DATAFLASH_VERIFY_WRITE |
406 | 405 | ||
407 | /* (3) Compare to Buffer1 */ | 406 | /* (3) Compare to Buffer1 */ |
408 | addr = pageaddr << priv->page_offset; | 407 | addr = pageaddr << priv->page_offset; |
@@ -431,7 +430,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
431 | } else | 430 | } else |
432 | status = 0; | 431 | status = 0; |
433 | 432 | ||
434 | #endif /* CONFIG_DATAFLASH_WRITE_VERIFY */ | 433 | #endif /* CONFIG_MTD_DATAFLASH_VERIFY_WRITE */ |
435 | 434 | ||
436 | remaining = remaining - writelen; | 435 | remaining = remaining - writelen; |
437 | pageaddr++; | 436 | pageaddr++; |
@@ -451,16 +450,192 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
451 | 450 | ||
452 | /* ......................................................................... */ | 451 | /* ......................................................................... */ |
453 | 452 | ||
453 | #ifdef CONFIG_MTD_DATAFLASH_OTP | ||
454 | |||
455 | static int dataflash_get_otp_info(struct mtd_info *mtd, | ||
456 | struct otp_info *info, size_t len) | ||
457 | { | ||
458 | /* Report both blocks as identical: bytes 0..64, locked. | ||
459 | * Unless the user block changed from all-ones, we can't | ||
460 | * tell whether it's still writable; so we assume it isn't. | ||
461 | */ | ||
462 | info->start = 0; | ||
463 | info->length = 64; | ||
464 | info->locked = 1; | ||
465 | return sizeof(*info); | ||
466 | } | ||
467 | |||
468 | static ssize_t otp_read(struct spi_device *spi, unsigned base, | ||
469 | uint8_t *buf, loff_t off, size_t len) | ||
470 | { | ||
471 | struct spi_message m; | ||
472 | size_t l; | ||
473 | uint8_t *scratch; | ||
474 | struct spi_transfer t; | ||
475 | int status; | ||
476 | |||
477 | if (off > 64) | ||
478 | return -EINVAL; | ||
479 | |||
480 | if ((off + len) > 64) | ||
481 | len = 64 - off; | ||
482 | if (len == 0) | ||
483 | return len; | ||
484 | |||
485 | spi_message_init(&m); | ||
486 | |||
487 | l = 4 + base + off + len; | ||
488 | scratch = kzalloc(l, GFP_KERNEL); | ||
489 | if (!scratch) | ||
490 | return -ENOMEM; | ||
491 | |||
492 | /* OUT: OP_READ_SECURITY, 3 don't-care bytes, zeroes | ||
493 | * IN: ignore 4 bytes, data bytes 0..N (max 127) | ||
494 | */ | ||
495 | scratch[0] = OP_READ_SECURITY; | ||
496 | |||
497 | memset(&t, 0, sizeof t); | ||
498 | t.tx_buf = scratch; | ||
499 | t.rx_buf = scratch; | ||
500 | t.len = l; | ||
501 | spi_message_add_tail(&t, &m); | ||
502 | |||
503 | dataflash_waitready(spi); | ||
504 | |||
505 | status = spi_sync(spi, &m); | ||
506 | if (status >= 0) { | ||
507 | memcpy(buf, scratch + 4 + base + off, len); | ||
508 | status = len; | ||
509 | } | ||
510 | |||
511 | kfree(scratch); | ||
512 | return status; | ||
513 | } | ||
514 | |||
515 | static int dataflash_read_fact_otp(struct mtd_info *mtd, | ||
516 | loff_t from, size_t len, size_t *retlen, u_char *buf) | ||
517 | { | ||
518 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
519 | int status; | ||
520 | |||
521 | /* 64 bytes, from 0..63 ... start at 64 on-chip */ | ||
522 | mutex_lock(&priv->lock); | ||
523 | status = otp_read(priv->spi, 64, buf, from, len); | ||
524 | mutex_unlock(&priv->lock); | ||
525 | |||
526 | if (status < 0) | ||
527 | return status; | ||
528 | *retlen = status; | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | static int dataflash_read_user_otp(struct mtd_info *mtd, | ||
533 | loff_t from, size_t len, size_t *retlen, u_char *buf) | ||
534 | { | ||
535 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
536 | int status; | ||
537 | |||
538 | /* 64 bytes, from 0..63 ... start at 0 on-chip */ | ||
539 | mutex_lock(&priv->lock); | ||
540 | status = otp_read(priv->spi, 0, buf, from, len); | ||
541 | mutex_unlock(&priv->lock); | ||
542 | |||
543 | if (status < 0) | ||
544 | return status; | ||
545 | *retlen = status; | ||
546 | return 0; | ||
547 | } | ||
548 | |||
549 | static int dataflash_write_user_otp(struct mtd_info *mtd, | ||
550 | loff_t from, size_t len, size_t *retlen, u_char *buf) | ||
551 | { | ||
552 | struct spi_message m; | ||
553 | const size_t l = 4 + 64; | ||
554 | uint8_t *scratch; | ||
555 | struct spi_transfer t; | ||
556 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
557 | int status; | ||
558 | |||
559 | if (len > 64) | ||
560 | return -EINVAL; | ||
561 | |||
562 | /* Strictly speaking, we *could* truncate the write ... but | ||
563 | * let's not do that for the only write that's ever possible. | ||
564 | */ | ||
565 | if ((from + len) > 64) | ||
566 | return -EINVAL; | ||
567 | |||
568 | /* OUT: OP_WRITE_SECURITY, 3 zeroes, 64 data-or-zero bytes | ||
569 | * IN: ignore all | ||
570 | */ | ||
571 | scratch = kzalloc(l, GFP_KERNEL); | ||
572 | if (!scratch) | ||
573 | return -ENOMEM; | ||
574 | scratch[0] = OP_WRITE_SECURITY; | ||
575 | memcpy(scratch + 4 + from, buf, len); | ||
576 | |||
577 | spi_message_init(&m); | ||
578 | |||
579 | memset(&t, 0, sizeof t); | ||
580 | t.tx_buf = scratch; | ||
581 | t.len = l; | ||
582 | spi_message_add_tail(&t, &m); | ||
583 | |||
584 | /* Write the OTP bits, if they've not yet been written. | ||
585 | * This modifies SRAM buffer1. | ||
586 | */ | ||
587 | mutex_lock(&priv->lock); | ||
588 | dataflash_waitready(priv->spi); | ||
589 | status = spi_sync(priv->spi, &m); | ||
590 | mutex_unlock(&priv->lock); | ||
591 | |||
592 | kfree(scratch); | ||
593 | |||
594 | if (status >= 0) { | ||
595 | status = 0; | ||
596 | *retlen = len; | ||
597 | } | ||
598 | return status; | ||
599 | } | ||
600 | |||
601 | static char *otp_setup(struct mtd_info *device, char revision) | ||
602 | { | ||
603 | device->get_fact_prot_info = dataflash_get_otp_info; | ||
604 | device->read_fact_prot_reg = dataflash_read_fact_otp; | ||
605 | device->get_user_prot_info = dataflash_get_otp_info; | ||
606 | device->read_user_prot_reg = dataflash_read_user_otp; | ||
607 | |||
608 | /* rev c parts (at45db321c and at45db1281 only!) use a | ||
609 | * different write procedure; not (yet?) implemented. | ||
610 | */ | ||
611 | if (revision > 'c') | ||
612 | device->write_user_prot_reg = dataflash_write_user_otp; | ||
613 | |||
614 | return ", OTP"; | ||
615 | } | ||
616 | |||
617 | #else | ||
618 | |||
619 | static char *otp_setup(struct mtd_info *device, char revision) | ||
620 | { | ||
621 | return " (OTP)"; | ||
622 | } | ||
623 | |||
624 | #endif | ||
625 | |||
626 | /* ......................................................................... */ | ||
627 | |||
454 | /* | 628 | /* |
455 | * Register DataFlash device with MTD subsystem. | 629 | * Register DataFlash device with MTD subsystem. |
456 | */ | 630 | */ |
457 | static int __devinit | 631 | static int __devinit |
458 | add_dataflash(struct spi_device *spi, char *name, | 632 | add_dataflash_otp(struct spi_device *spi, char *name, |
459 | int nr_pages, int pagesize, int pageoffset) | 633 | int nr_pages, int pagesize, int pageoffset, char revision) |
460 | { | 634 | { |
461 | struct dataflash *priv; | 635 | struct dataflash *priv; |
462 | struct mtd_info *device; | 636 | struct mtd_info *device; |
463 | struct flash_platform_data *pdata = spi->dev.platform_data; | 637 | struct flash_platform_data *pdata = spi->dev.platform_data; |
638 | char *otp_tag = ""; | ||
464 | 639 | ||
465 | priv = kzalloc(sizeof *priv, GFP_KERNEL); | 640 | priv = kzalloc(sizeof *priv, GFP_KERNEL); |
466 | if (!priv) | 641 | if (!priv) |
@@ -489,8 +664,12 @@ add_dataflash(struct spi_device *spi, char *name, | |||
489 | device->write = dataflash_write; | 664 | device->write = dataflash_write; |
490 | device->priv = priv; | 665 | device->priv = priv; |
491 | 666 | ||
492 | dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes\n", | 667 | if (revision >= 'c') |
493 | name, DIV_ROUND_UP(device->size, 1024), pagesize); | 668 | otp_tag = otp_setup(device, revision); |
669 | |||
670 | dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes%s\n", | ||
671 | name, DIV_ROUND_UP(device->size, 1024), | ||
672 | pagesize, otp_tag); | ||
494 | dev_set_drvdata(&spi->dev, priv); | 673 | dev_set_drvdata(&spi->dev, priv); |
495 | 674 | ||
496 | if (mtd_has_partitions()) { | 675 | if (mtd_has_partitions()) { |
@@ -519,6 +698,14 @@ add_dataflash(struct spi_device *spi, char *name, | |||
519 | return add_mtd_device(device) == 1 ? -ENODEV : 0; | 698 | return add_mtd_device(device) == 1 ? -ENODEV : 0; |
520 | } | 699 | } |
521 | 700 | ||
701 | static inline int __devinit | ||
702 | add_dataflash(struct spi_device *spi, char *name, | ||
703 | int nr_pages, int pagesize, int pageoffset) | ||
704 | { | ||
705 | return add_dataflash_otp(spi, name, nr_pages, pagesize, | ||
706 | pageoffset, 0); | ||
707 | } | ||
708 | |||
522 | struct flash_info { | 709 | struct flash_info { |
523 | char *name; | 710 | char *name; |
524 | 711 | ||
@@ -664,13 +851,16 @@ static int __devinit dataflash_probe(struct spi_device *spi) | |||
664 | * Try to detect dataflash by JEDEC ID. | 851 | * Try to detect dataflash by JEDEC ID. |
665 | * If it succeeds we know we have either a C or D part. | 852 | * If it succeeds we know we have either a C or D part. |
666 | * D will support power of 2 pagesize option. | 853 | * D will support power of 2 pagesize option. |
854 | * Both support the security register, though with different | ||
855 | * write procedures. | ||
667 | */ | 856 | */ |
668 | info = jedec_probe(spi); | 857 | info = jedec_probe(spi); |
669 | if (IS_ERR(info)) | 858 | if (IS_ERR(info)) |
670 | return PTR_ERR(info); | 859 | return PTR_ERR(info); |
671 | if (info != NULL) | 860 | if (info != NULL) |
672 | return add_dataflash(spi, info->name, info->nr_pages, | 861 | return add_dataflash_otp(spi, info->name, info->nr_pages, |
673 | info->pagesize, info->pageoffset); | 862 | info->pagesize, info->pageoffset, |
863 | (info->flags & SUP_POW2PS) ? 'd' : 'c'); | ||
674 | 864 | ||
675 | /* | 865 | /* |
676 | * Older chips support only legacy commands, identifing | 866 | * Older chips support only legacy commands, identifing |