20 #include <linux/errno.h>
21 #include <linux/module.h>
22 #include <linux/device.h>
26 #include <linux/slab.h>
27 #include <linux/sched.h>
39 #define OPCODE_WREN 0x06
40 #define OPCODE_RDSR 0x05
41 #define OPCODE_WRSR 0x01
42 #define OPCODE_NORM_READ 0x03
43 #define OPCODE_FAST_READ 0x0b
44 #define OPCODE_PP 0x02
45 #define OPCODE_BE_4K 0x20
46 #define OPCODE_BE_32K 0x52
47 #define OPCODE_CHIP_ERASE 0xc7
48 #define OPCODE_SE 0xd8
49 #define OPCODE_RDID 0x9f
52 #define OPCODE_BP 0x02
53 #define OPCODE_WRDI 0x04
54 #define OPCODE_AAI_WP 0xad
57 #define OPCODE_EN4B 0xb7
58 #define OPCODE_EX4B 0xe9
61 #define OPCODE_BRWR 0x17
73 #define MAX_READY_WAIT_JIFFIES (40 * HZ)
74 #define MAX_CMD_SIZE 5
76 #ifdef CONFIG_M25PXX_USE_FAST_READ
77 #define OPCODE_READ OPCODE_FAST_READ
78 #define FAST_READ_DUMMY_BYTE 1
80 #define OPCODE_READ OPCODE_NORM_READ
81 #define FAST_READ_DUMMY_BYTE 0
84 #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16)
123 dev_err(&flash->
spi->dev,
"error %d reading SR\n",
140 return spi_write(flash->
spi, flash->
command, 2);
147 static inline int write_enable(
struct m25p *flash)
157 static inline int write_disable(
struct m25p *flash)
172 return spi_write(flash->
spi, flash->
command, 1);
176 flash->
command[1] = enable << 7;
177 return spi_write(flash->
spi, flash->
command, 2);
185 static int wait_till_ready(
struct m25p *flash)
187 unsigned long deadline;
210 static int erase_chip(
struct m25p *flash)
212 pr_debug(
"%s: %s %lldKiB\n", dev_name(&flash->
spi->dev), __func__,
213 (
long long)(flash->
mtd.size >> 10));
216 if (wait_till_ready(flash))
230 static void m25p_addr2cmd(
struct m25p *flash,
unsigned int addr,
u8 *
cmd)
234 cmd[2] = addr >> (flash->
addr_width * 8 - 16);
235 cmd[3] = addr >> (flash->
addr_width * 8 - 24);
236 cmd[4] = addr >> (flash->
addr_width * 8 - 32);
239 static int m25p_cmdsz(
struct m25p *flash)
252 pr_debug(
"%s: %s %dKiB at 0x%08x\n", dev_name(&flash->
spi->dev),
253 __func__, flash->
mtd.erasesize / 1024, offset);
256 if (wait_till_ready(flash))
264 m25p_addr2cmd(flash, offset, flash->
command);
266 spi_write(flash->
spi, flash->
command, m25p_cmdsz(flash));
283 struct m25p *flash = mtd_to_m25p(mtd);
287 pr_debug(
"%s: %s at 0x%llx, len %lld\n", dev_name(&flash->
spi->dev),
288 __func__, (
long long)instr->
addr,
289 (
long long)instr->
len);
301 if (len == flash->
mtd.size) {
302 if (erase_chip(flash)) {
316 if (erase_sector(flash, addr)) {
339 static int m25p80_read(
struct mtd_info *mtd, loff_t
from,
size_t len,
342 struct m25p *flash = mtd_to_m25p(mtd);
346 pr_debug(
"%s: %s from 0x%08x, len %zd\n", dev_name(&flash->
spi->dev),
347 __func__, (
u32)from, len);
349 spi_message_init(&
m);
358 spi_message_add_tail(&
t[0], &
m);
362 spi_message_add_tail(&
t[1], &
m);
367 if (wait_till_ready(flash)) {
380 m25p_addr2cmd(flash, from, flash->
command);
396 static int m25p80_write(
struct mtd_info *mtd, loff_t to,
size_t len,
397 size_t *retlen,
const u_char *buf)
399 struct m25p *flash = mtd_to_m25p(mtd);
404 pr_debug(
"%s: %s to 0x%08x, len %zd\n", dev_name(&flash->
spi->dev),
405 __func__, (
u32)to, len);
407 spi_message_init(&
m);
411 t[0].len = m25p_cmdsz(flash);
412 spi_message_add_tail(&
t[0], &
m);
415 spi_message_add_tail(&
t[1], &
m);
420 if (wait_till_ready(flash)) {
429 m25p_addr2cmd(flash, to, flash->
command);
431 page_offset = to & (flash->
page_size - 1);
434 if (page_offset + len <= flash->page_size) {
439 *retlen =
m.actual_length - m25p_cmdsz(flash);
449 *retlen =
m.actual_length - m25p_cmdsz(flash);
452 for (i = page_size; i < len; i +=
page_size) {
458 m25p_addr2cmd(flash, to + i, flash->
command);
460 t[1].tx_buf = buf +
i;
463 wait_till_ready(flash);
469 *retlen +=
m.actual_length - m25p_cmdsz(flash);
479 size_t *retlen,
const u_char *buf)
481 struct m25p *flash = mtd_to_m25p(mtd);
487 pr_debug(
"%s: %s to 0x%08x, len %zd\n", dev_name(&flash->
spi->dev),
488 __func__, (
u32)to, len);
490 spi_message_init(&
m);
494 t[0].len = m25p_cmdsz(flash);
495 spi_message_add_tail(&
t[0], &
m);
498 spi_message_add_tail(&
t[1], &
m);
503 ret = wait_till_ready(flash);
513 m25p_addr2cmd(flash, to, flash->
command);
518 ret = wait_till_ready(flash);
521 *retlen +=
m.actual_length - m25p_cmdsz(flash);
526 m25p_addr2cmd(flash, to, flash->
command);
529 cmd_sz = m25p_cmdsz(flash);
530 for (; actual < len - 1; actual += 2) {
534 t[1].tx_buf = buf + actual;
537 ret = wait_till_ready(flash);
540 *retlen +=
m.actual_length - cmd_sz;
544 write_disable(flash);
545 ret = wait_till_ready(flash);
553 m25p_addr2cmd(flash, to, flash->
command);
554 t[0].len = m25p_cmdsz(flash);
556 t[1].tx_buf = buf + actual;
559 ret = wait_till_ready(flash);
562 *retlen +=
m.actual_length - m25p_cmdsz(flash);
563 write_disable(flash);
596 #define M25P_NO_ERASE 0x02
599 #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
600 ((kernel_ulong_t)&(struct flash_info) { \
601 .jedec_id = (_jedec_id), \
602 .ext_id = (_ext_id), \
603 .sector_size = (_sector_size), \
604 .n_sectors = (_n_sectors), \
609 #define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \
610 ((kernel_ulong_t)&(struct flash_info) { \
611 .sector_size = (_sector_size), \
612 .n_sectors = (_n_sectors), \
613 .page_size = (_page_size), \
614 .addr_width = (_addr_width), \
615 .flags = M25P_NO_ERASE, \
624 {
"at25fs010",
INFO(0x1f6601, 0, 32 * 1024, 4,
SECT_4K) },
625 {
"at25fs040",
INFO(0x1f6604, 0, 64 * 1024, 8,
SECT_4K) },
627 {
"at25df041a",
INFO(0x1f4401, 0, 64 * 1024, 8,
SECT_4K) },
628 {
"at25df321a",
INFO(0x1f4701, 0, 64 * 1024, 64,
SECT_4K) },
629 {
"at25df641",
INFO(0x1f4800, 0, 64 * 1024, 128,
SECT_4K) },
631 {
"at26f004",
INFO(0x1f0400, 0, 64 * 1024, 8,
SECT_4K) },
632 {
"at26df081a",
INFO(0x1f4501, 0, 64 * 1024, 16,
SECT_4K) },
633 {
"at26df161a",
INFO(0x1f4601, 0, 64 * 1024, 32,
SECT_4K) },
634 {
"at26df321",
INFO(0x1f4700, 0, 64 * 1024, 64,
SECT_4K) },
636 {
"at45db081d",
INFO(0x1f2500, 0, 64 * 1024, 16,
SECT_4K) },
639 {
"en25f32",
INFO(0x1c3116, 0, 64 * 1024, 64,
SECT_4K) },
640 {
"en25p32",
INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
641 {
"en25q32b",
INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
642 {
"en25p64",
INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
643 {
"en25q64",
INFO(0x1c3017, 0, 64 * 1024, 128,
SECT_4K) },
646 {
"mr25h256",
CAT25_INFO( 32 * 1024, 1, 256, 2) },
649 {
"160s33b",
INFO(0x898911, 0, 64 * 1024, 32, 0) },
650 {
"320s33b",
INFO(0x898912, 0, 64 * 1024, 64, 0) },
651 {
"640s33b",
INFO(0x898913, 0, 64 * 1024, 128, 0) },
652 {
"n25q064",
INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
655 {
"mx25l2005a",
INFO(0xc22012, 0, 64 * 1024, 4,
SECT_4K) },
656 {
"mx25l4005a",
INFO(0xc22013, 0, 64 * 1024, 8,
SECT_4K) },
657 {
"mx25l8005",
INFO(0xc22014, 0, 64 * 1024, 16, 0) },
658 {
"mx25l1606e",
INFO(0xc22015, 0, 64 * 1024, 32,
SECT_4K) },
659 {
"mx25l3205d",
INFO(0xc22016, 0, 64 * 1024, 64, 0) },
660 {
"mx25l6405d",
INFO(0xc22017, 0, 64 * 1024, 128, 0) },
661 {
"mx25l12805d",
INFO(0xc22018, 0, 64 * 1024, 256, 0) },
662 {
"mx25l12855e",
INFO(0xc22618, 0, 64 * 1024, 256, 0) },
663 {
"mx25l25635e",
INFO(0xc22019, 0, 64 * 1024, 512, 0) },
664 {
"mx25l25655e",
INFO(0xc22619, 0, 64 * 1024, 512, 0) },
667 {
"n25q128",
INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
668 {
"n25q256a",
INFO(0x20ba19, 0, 64 * 1024, 512,
SECT_4K) },
673 {
"s25sl032p",
INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) },
674 {
"s25sl064p",
INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) },
675 {
"s25fl256s0",
INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
676 {
"s25fl256s1",
INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) },
677 {
"s25fl512s",
INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) },
678 {
"s70fl01gs",
INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
679 {
"s25sl12800",
INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
680 {
"s25sl12801",
INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
681 {
"s25fl129p0",
INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) },
682 {
"s25fl129p1",
INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) },
683 {
"s25sl004a",
INFO(0x010212, 0, 64 * 1024, 8, 0) },
684 {
"s25sl008a",
INFO(0x010213, 0, 64 * 1024, 16, 0) },
685 {
"s25sl016a",
INFO(0x010214, 0, 64 * 1024, 32, 0) },
686 {
"s25sl032a",
INFO(0x010215, 0, 64 * 1024, 64, 0) },
687 {
"s25sl064a",
INFO(0x010216, 0, 64 * 1024, 128, 0) },
688 {
"s25fl016k",
INFO(0xef4015, 0, 64 * 1024, 32,
SECT_4K) },
689 {
"s25fl064k",
INFO(0xef4017, 0, 64 * 1024, 128,
SECT_4K) },
692 {
"sst25vf040b",
INFO(0xbf258d, 0, 64 * 1024, 8,
SECT_4K) },
693 {
"sst25vf080b",
INFO(0xbf258e, 0, 64 * 1024, 16,
SECT_4K) },
694 {
"sst25vf016b",
INFO(0xbf2541, 0, 64 * 1024, 32,
SECT_4K) },
695 {
"sst25vf032b",
INFO(0xbf254a, 0, 64 * 1024, 64,
SECT_4K) },
696 {
"sst25wf512",
INFO(0xbf2501, 0, 64 * 1024, 1,
SECT_4K) },
697 {
"sst25wf010",
INFO(0xbf2502, 0, 64 * 1024, 2,
SECT_4K) },
698 {
"sst25wf020",
INFO(0xbf2503, 0, 64 * 1024, 4,
SECT_4K) },
699 {
"sst25wf040",
INFO(0xbf2504, 0, 64 * 1024, 8,
SECT_4K) },
702 {
"m25p05",
INFO(0x202010, 0, 32 * 1024, 2, 0) },
703 {
"m25p10",
INFO(0x202011, 0, 32 * 1024, 4, 0) },
704 {
"m25p20",
INFO(0x202012, 0, 64 * 1024, 4, 0) },
705 {
"m25p40",
INFO(0x202013, 0, 64 * 1024, 8, 0) },
706 {
"m25p80",
INFO(0x202014, 0, 64 * 1024, 16, 0) },
707 {
"m25p16",
INFO(0x202015, 0, 64 * 1024, 32, 0) },
708 {
"m25p32",
INFO(0x202016, 0, 64 * 1024, 64, 0) },
709 {
"m25p64",
INFO(0x202017, 0, 64 * 1024, 128, 0) },
710 {
"m25p128",
INFO(0x202018, 0, 256 * 1024, 64, 0) },
711 {
"n25q032",
INFO(0x20ba16, 0, 64 * 1024, 64, 0) },
713 {
"m25p05-nonjedec",
INFO(0, 0, 32 * 1024, 2, 0) },
714 {
"m25p10-nonjedec",
INFO(0, 0, 32 * 1024, 4, 0) },
715 {
"m25p20-nonjedec",
INFO(0, 0, 64 * 1024, 4, 0) },
716 {
"m25p40-nonjedec",
INFO(0, 0, 64 * 1024, 8, 0) },
717 {
"m25p80-nonjedec",
INFO(0, 0, 64 * 1024, 16, 0) },
718 {
"m25p16-nonjedec",
INFO(0, 0, 64 * 1024, 32, 0) },
719 {
"m25p32-nonjedec",
INFO(0, 0, 64 * 1024, 64, 0) },
720 {
"m25p64-nonjedec",
INFO(0, 0, 64 * 1024, 128, 0) },
721 {
"m25p128-nonjedec",
INFO(0, 0, 256 * 1024, 64, 0) },
723 {
"m45pe10",
INFO(0x204011, 0, 64 * 1024, 2, 0) },
724 {
"m45pe80",
INFO(0x204014, 0, 64 * 1024, 16, 0) },
725 {
"m45pe16",
INFO(0x204015, 0, 64 * 1024, 32, 0) },
727 {
"m25pe20",
INFO(0x208012, 0, 64 * 1024, 4, 0) },
728 {
"m25pe80",
INFO(0x208014, 0, 64 * 1024, 16, 0) },
729 {
"m25pe16",
INFO(0x208015, 0, 64 * 1024, 32,
SECT_4K) },
731 {
"m25px32",
INFO(0x207116, 0, 64 * 1024, 64,
SECT_4K) },
732 {
"m25px32-s0",
INFO(0x207316, 0, 64 * 1024, 64,
SECT_4K) },
733 {
"m25px32-s1",
INFO(0x206316, 0, 64 * 1024, 64,
SECT_4K) },
734 {
"m25px64",
INFO(0x207117, 0, 64 * 1024, 128, 0) },
737 {
"w25x10",
INFO(0xef3011, 0, 64 * 1024, 2,
SECT_4K) },
738 {
"w25x20",
INFO(0xef3012, 0, 64 * 1024, 4,
SECT_4K) },
739 {
"w25x40",
INFO(0xef3013, 0, 64 * 1024, 8,
SECT_4K) },
740 {
"w25x80",
INFO(0xef3014, 0, 64 * 1024, 16,
SECT_4K) },
741 {
"w25x16",
INFO(0xef3015, 0, 64 * 1024, 32,
SECT_4K) },
742 {
"w25x32",
INFO(0xef3016, 0, 64 * 1024, 64,
SECT_4K) },
743 {
"w25q32",
INFO(0xef4016, 0, 64 * 1024, 64,
SECT_4K) },
744 {
"w25q32dw",
INFO(0xef6016, 0, 64 * 1024, 64,
SECT_4K) },
745 {
"w25x64",
INFO(0xef3017, 0, 64 * 1024, 128,
SECT_4K) },
746 {
"w25q64",
INFO(0xef4017, 0, 64 * 1024, 128,
SECT_4K) },
747 {
"w25q80",
INFO(0xef5014, 0, 64 * 1024, 16,
SECT_4K) },
774 pr_debug(
"%s: error %d reading JEDEC ID\n",
775 dev_name(&spi->
dev), tmp);
784 ext_jedec =
id[3] << 8 |
id[4];
786 for (tmp = 0; tmp <
ARRAY_SIZE(m25p_ids) - 1; tmp++) {
791 return &m25p_ids[
tmp];
794 dev_err(&spi->
dev,
"unrecognized JEDEC id %06x\n", jedec);
813 #ifdef CONFIG_MTD_OF_PARTS
823 data = spi->
dev.platform_data;
824 if (data && data->
type) {
827 for (i = 0; i <
ARRAY_SIZE(m25p_ids) - 1; i++) {
828 plat_id = &m25p_ids[
i];
840 info = (
void *)id->driver_data;
845 jid = jedec_probe(spi);
848 }
else if (jid !=
id) {
859 info = (
void *)jid->driver_data;
888 if (data && data->
name)
891 flash->
mtd.name = dev_name(&spi->
dev);
894 flash->
mtd.writesize = 1;
897 flash->
mtd._erase = m25p80_erase;
898 flash->
mtd._read = m25p80_read;
904 flash->
mtd._write = m25p80_write;
909 flash->
mtd.erasesize = 4096;
919 flash->
mtd.dev.parent = &spi->
dev;
927 if (flash->
mtd.size > 0x1000000) {
929 set_4byte(flash, info->
jedec_id, 1);
935 (
long long)flash->
mtd.size >> 10);
937 pr_debug(
"mtd .name = %s, .size = 0x%llx (%lldMiB) "
938 ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
940 (
long long)flash->
mtd.size, (
long long)(flash->
mtd.size >> 20),
941 flash->
mtd.erasesize, flash->
mtd.erasesize / 1024,
942 flash->
mtd.numeraseregions);
944 if (flash->
mtd.numeraseregions)
945 for (i = 0; i < flash->
mtd.numeraseregions; i++)
946 pr_debug(
"mtd.eraseregions[%d] = { .offset = 0x%llx, "
947 ".erasesize = 0x%.8x (%uKiB), "
948 ".numblocks = %d }\n",
949 i, (
long long)flash->
mtd.eraseregions[i].offset,
950 flash->
mtd.eraseregions[i].erasesize,
951 flash->
mtd.eraseregions[i].erasesize / 1024,
952 flash->
mtd.eraseregions[i].numblocks);
984 .id_table = m25p_ids,