1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2005, Intec Automation Inc.
4 * Copyright (C) 2014, Freescale Semiconductor, Inc.
7 #include <linux/mtd/spi-nor.h>
11 static const struct flash_info sst_parts
[] = {
12 /* SST -- large erase sizes are "overlays", "sectors" are 4K */
13 { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8,
14 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
15 { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16,
16 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
17 { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32,
18 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
19 { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64,
20 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
21 { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128,
22 SECT_4K
| SPI_NOR_4BIT_BP
| SPI_NOR_HAS_LOCK
|
23 SPI_NOR_SWP_IS_VOLATILE
) },
24 { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1,
25 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
26 { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2,
27 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
28 { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4,
29 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
30 { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K
| SPI_NOR_HAS_LOCK
) },
31 { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K
| SPI_NOR_HAS_LOCK
) },
32 { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8,
33 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
34 { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16,
35 SECT_4K
| SST_WRITE
| SPI_NOR_HAS_LOCK
| SPI_NOR_SWP_IS_VOLATILE
) },
36 { "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32,
37 SECT_4K
| SPI_NOR_DUAL_READ
|
39 { "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32,
40 SECT_4K
| SPI_NOR_DUAL_READ
) },
41 { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128,
42 SECT_4K
| SPI_NOR_DUAL_READ
|
46 static int sst_write(struct mtd_info
*mtd
, loff_t to
, size_t len
,
47 size_t *retlen
, const u_char
*buf
)
49 struct spi_nor
*nor
= mtd_to_spi_nor(mtd
);
53 dev_dbg(nor
->dev
, "to 0x%08x, len %zd\n", (u32
)to
, len
);
55 ret
= spi_nor_lock_and_prep(nor
);
59 ret
= spi_nor_write_enable(nor
);
63 nor
->sst_write_second
= false;
65 /* Start write from odd address. */
67 nor
->program_opcode
= SPINOR_OP_BP
;
70 ret
= spi_nor_write_data(nor
, to
, 1, buf
);
73 WARN(ret
!= 1, "While writing 1 byte written %i bytes\n", ret
);
74 ret
= spi_nor_wait_till_ready(nor
);
82 /* Write out most of the data here. */
83 for (; actual
< len
- 1; actual
+= 2) {
84 nor
->program_opcode
= SPINOR_OP_AAI_WP
;
86 /* write two bytes. */
87 ret
= spi_nor_write_data(nor
, to
, 2, buf
+ actual
);
90 WARN(ret
!= 2, "While writing 2 bytes written %i bytes\n", ret
);
91 ret
= spi_nor_wait_till_ready(nor
);
95 nor
->sst_write_second
= true;
97 nor
->sst_write_second
= false;
99 ret
= spi_nor_write_disable(nor
);
103 ret
= spi_nor_wait_till_ready(nor
);
107 /* Write out trailing byte if it exists. */
109 ret
= spi_nor_write_enable(nor
);
113 nor
->program_opcode
= SPINOR_OP_BP
;
114 ret
= spi_nor_write_data(nor
, to
, 1, buf
+ actual
);
117 WARN(ret
!= 1, "While writing 1 byte written %i bytes\n", ret
);
118 ret
= spi_nor_wait_till_ready(nor
);
124 ret
= spi_nor_write_disable(nor
);
128 spi_nor_unlock_and_unprep(nor
);
132 static void sst_post_sfdp_fixups(struct spi_nor
*nor
)
134 if (nor
->info
->flags
& SST_WRITE
)
135 nor
->mtd
._write
= sst_write
;
138 static const struct spi_nor_fixups sst_fixups
= {
139 .post_sfdp
= sst_post_sfdp_fixups
,
142 const struct spi_nor_manufacturer spi_nor_sst
= {
145 .nparts
= ARRAY_SIZE(sst_parts
),
146 .fixups
= &sst_fixups
,