aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices/m25p80.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/devices/m25p80.c')
-rw-r--r--drivers/mtd/devices/m25p80.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 4eeeb2d7f6ea..5b6b0728be21 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -565,6 +565,96 @@ time_out:
565 return ret; 565 return ret;
566} 566}
567 567
568static int m25p80_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
569{
570 struct m25p *flash = mtd_to_m25p(mtd);
571 uint32_t offset = ofs;
572 uint8_t status_old, status_new;
573 int res = 0;
574
575 mutex_lock(&flash->lock);
576 /* Wait until finished previous command */
577 if (wait_till_ready(flash)) {
578 res = 1;
579 goto err;
580 }
581
582 status_old = read_sr(flash);
583
584 if (offset < flash->mtd.size-(flash->mtd.size/2))
585 status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0;
586 else if (offset < flash->mtd.size-(flash->mtd.size/4))
587 status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
588 else if (offset < flash->mtd.size-(flash->mtd.size/8))
589 status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
590 else if (offset < flash->mtd.size-(flash->mtd.size/16))
591 status_new = (status_old & ~(SR_BP0|SR_BP1)) | SR_BP2;
592 else if (offset < flash->mtd.size-(flash->mtd.size/32))
593 status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
594 else if (offset < flash->mtd.size-(flash->mtd.size/64))
595 status_new = (status_old & ~(SR_BP2|SR_BP0)) | SR_BP1;
596 else
597 status_new = (status_old & ~(SR_BP2|SR_BP1)) | SR_BP0;
598
599 /* Only modify protection if it will not unlock other areas */
600 if ((status_new&(SR_BP2|SR_BP1|SR_BP0)) >
601 (status_old&(SR_BP2|SR_BP1|SR_BP0))) {
602 write_enable(flash);
603 if (write_sr(flash, status_new) < 0) {
604 res = 1;
605 goto err;
606 }
607 }
608
609err: mutex_unlock(&flash->lock);
610 return res;
611}
612
613static int m25p80_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
614{
615 struct m25p *flash = mtd_to_m25p(mtd);
616 uint32_t offset = ofs;
617 uint8_t status_old, status_new;
618 int res = 0;
619
620 mutex_lock(&flash->lock);
621 /* Wait until finished previous command */
622 if (wait_till_ready(flash)) {
623 res = 1;
624 goto err;
625 }
626
627 status_old = read_sr(flash);
628
629 if (offset+len > flash->mtd.size-(flash->mtd.size/64))
630 status_new = status_old & ~(SR_BP2|SR_BP1|SR_BP0);
631 else if (offset+len > flash->mtd.size-(flash->mtd.size/32))
632 status_new = (status_old & ~(SR_BP2|SR_BP1)) | SR_BP0;
633 else if (offset+len > flash->mtd.size-(flash->mtd.size/16))
634 status_new = (status_old & ~(SR_BP2|SR_BP0)) | SR_BP1;
635 else if (offset+len > flash->mtd.size-(flash->mtd.size/8))
636 status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
637 else if (offset+len > flash->mtd.size-(flash->mtd.size/4))
638 status_new = (status_old & ~(SR_BP0|SR_BP1)) | SR_BP2;
639 else if (offset+len > flash->mtd.size-(flash->mtd.size/2))
640 status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
641 else
642 status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
643
644 /* Only modify protection if it will not lock other areas */
645 if ((status_new&(SR_BP2|SR_BP1|SR_BP0)) <
646 (status_old&(SR_BP2|SR_BP1|SR_BP0))) {
647 write_enable(flash);
648 if (write_sr(flash, status_new) < 0) {
649 res = 1;
650 goto err;
651 }
652 }
653
654err: mutex_unlock(&flash->lock);
655 return res;
656}
657
568/****************************************************************************/ 658/****************************************************************************/
569 659
570/* 660/*
@@ -642,6 +732,10 @@ static const struct spi_device_id m25p_ids[] = {
642 /* Everspin */ 732 /* Everspin */
643 { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) }, 733 { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) },
644 734
735 /* GigaDevice */
736 { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) },
737 { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) },
738
645 /* Intel/Numonyx -- xxxs33b */ 739 /* Intel/Numonyx -- xxxs33b */
646 { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, 740 { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
647 { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, 741 { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
@@ -899,6 +993,12 @@ static int m25p_probe(struct spi_device *spi)
899 flash->mtd._erase = m25p80_erase; 993 flash->mtd._erase = m25p80_erase;
900 flash->mtd._read = m25p80_read; 994 flash->mtd._read = m25p80_read;
901 995
996 /* flash protection support for STmicro chips */
997 if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) {
998 flash->mtd._lock = m25p80_lock;
999 flash->mtd._unlock = m25p80_unlock;
1000 }
1001
902 /* sst flash chips use AAI word program */ 1002 /* sst flash chips use AAI word program */
903 if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) 1003 if (JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
904 flash->mtd._write = sst_write; 1004 flash->mtd._write = sst_write;