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 /* SST flash_info mfr_flag. Used to specify SST byte programming. */
12 #define SST_WRITE BIT(0)
14 #define SST26VF_CR_BPNV BIT(3)
16 static int sst26vf_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
21 static int sst26vf_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
25 /* We only support unlocking the entire flash array. */
26 if (ofs != 0 || len != nor->params->size)
29 ret = spi_nor_read_cr(nor, nor->bouncebuf);
33 if (!(nor->bouncebuf[0] & SST26VF_CR_BPNV)) {
34 dev_dbg(nor->dev, "Any block has been permanently locked\n");
38 return spi_nor_global_block_unlock(nor);
41 static int sst26vf_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
46 static const struct spi_nor_locking_ops sst26vf_locking_ops = {
48 .unlock = sst26vf_unlock,
49 .is_locked = sst26vf_is_locked,
52 static void sst26vf_late_init(struct spi_nor *nor)
54 nor->params->locking_ops = &sst26vf_locking_ops;
57 static const struct spi_nor_fixups sst26vf_fixups = {
58 .late_init = sst26vf_late_init,
61 static const struct flash_info sst_parts[] = {
62 /* SST -- large erase sizes are "overlays", "sectors" are 4K */
63 { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8)
64 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
65 NO_SFDP_FLAGS(SECT_4K)
66 MFR_FLAGS(SST_WRITE) },
67 { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16)
68 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
69 NO_SFDP_FLAGS(SECT_4K)
70 MFR_FLAGS(SST_WRITE) },
71 { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32)
72 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
73 NO_SFDP_FLAGS(SECT_4K)
74 MFR_FLAGS(SST_WRITE) },
75 { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64)
76 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
77 NO_SFDP_FLAGS(SECT_4K)
78 MFR_FLAGS(SST_WRITE) },
79 { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128)
80 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_4BIT_BP |
81 SPI_NOR_SWP_IS_VOLATILE)
82 NO_SFDP_FLAGS(SECT_4K) },
83 { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1)
84 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
85 NO_SFDP_FLAGS(SECT_4K)
86 MFR_FLAGS(SST_WRITE) },
87 { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2)
88 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
89 NO_SFDP_FLAGS(SECT_4K)
90 MFR_FLAGS(SST_WRITE) },
91 { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4)
92 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
93 NO_SFDP_FLAGS(SECT_4K)
94 MFR_FLAGS(SST_WRITE) },
95 { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4)
96 FLAGS(SPI_NOR_HAS_LOCK)
97 NO_SFDP_FLAGS(SECT_4K) },
98 { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8)
99 FLAGS(SPI_NOR_HAS_LOCK)
100 NO_SFDP_FLAGS(SECT_4K) },
101 { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8)
102 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
103 NO_SFDP_FLAGS(SECT_4K)
104 MFR_FLAGS(SST_WRITE) },
105 { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16)
106 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
107 NO_SFDP_FLAGS(SECT_4K)
108 MFR_FLAGS(SST_WRITE) },
109 { "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32)
110 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ |
111 SPI_NOR_QUAD_READ) },
112 { "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32)
113 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ) },
114 { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128)
115 FLAGS(SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
116 NO_SFDP_FLAGS(SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
117 .fixups = &sst26vf_fixups },
120 static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
121 size_t *retlen, const u_char *buf)
123 struct spi_nor *nor = mtd_to_spi_nor(mtd);
127 dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
129 ret = spi_nor_lock_and_prep(nor);
133 ret = spi_nor_write_enable(nor);
137 nor->sst_write_second = false;
139 /* Start write from odd address. */
141 nor->program_opcode = SPINOR_OP_BP;
143 /* write one byte. */
144 ret = spi_nor_write_data(nor, to, 1, buf);
147 WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
148 ret = spi_nor_wait_till_ready(nor);
156 /* Write out most of the data here. */
157 for (; actual < len - 1; actual += 2) {
158 nor->program_opcode = SPINOR_OP_AAI_WP;
160 /* write two bytes. */
161 ret = spi_nor_write_data(nor, to, 2, buf + actual);
164 WARN(ret != 2, "While writing 2 bytes written %i bytes\n", ret);
165 ret = spi_nor_wait_till_ready(nor);
169 nor->sst_write_second = true;
171 nor->sst_write_second = false;
173 ret = spi_nor_write_disable(nor);
177 ret = spi_nor_wait_till_ready(nor);
181 /* Write out trailing byte if it exists. */
183 ret = spi_nor_write_enable(nor);
187 nor->program_opcode = SPINOR_OP_BP;
188 ret = spi_nor_write_data(nor, to, 1, buf + actual);
191 WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
192 ret = spi_nor_wait_till_ready(nor);
198 ret = spi_nor_write_disable(nor);
202 spi_nor_unlock_and_unprep(nor);
206 static void sst_late_init(struct spi_nor *nor)
208 if (nor->info->mfr_flags & SST_WRITE)
209 nor->mtd._write = sst_write;
212 static const struct spi_nor_fixups sst_fixups = {
213 .late_init = sst_late_init,
216 const struct spi_nor_manufacturer spi_nor_sst = {
219 .nparts = ARRAY_SIZE(sst_parts),
220 .fixups = &sst_fixups,