1 | /* |
2 | * ST M25P80 emulator. Emulate all SPI flash devices based on the m25p80 command |
3 | * set. Known devices table current as of Jun/2012 and taken from linux. |
4 | * See drivers/mtd/devices/m25p80.c. |
5 | * |
6 | * Copyright (C) 2011 Edgar E. Iglesias <edgar.iglesias@gmail.com> |
7 | * Copyright (C) 2012 Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com> |
8 | * Copyright (C) 2012 PetaLogix |
9 | * |
10 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License as |
12 | * published by the Free Software Foundation; either version 2 or |
13 | * (at your option) a later version of the License. |
14 | * |
15 | * This program is distributed in the hope that it will be useful, |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | * GNU General Public License for more details. |
19 | * |
20 | * You should have received a copy of the GNU General Public License along |
21 | * with this program; if not, see <http://www.gnu.org/licenses/>. |
22 | */ |
23 | |
24 | #include "qemu/osdep.h" |
25 | #include "qemu/units.h" |
26 | #include "sysemu/block-backend.h" |
27 | #include "hw/qdev-properties.h" |
28 | #include "hw/ssi/ssi.h" |
29 | #include "migration/vmstate.h" |
30 | #include "qemu/bitops.h" |
31 | #include "qemu/log.h" |
32 | #include "qemu/module.h" |
33 | #include "qemu/error-report.h" |
34 | #include "qapi/error.h" |
35 | |
36 | #ifndef M25P80_ERR_DEBUG |
37 | #define M25P80_ERR_DEBUG 0 |
38 | #endif |
39 | |
40 | #define DB_PRINT_L(level, ...) do { \ |
41 | if (M25P80_ERR_DEBUG > (level)) { \ |
42 | fprintf(stderr, ": %s: ", __func__); \ |
43 | fprintf(stderr, ## __VA_ARGS__); \ |
44 | } \ |
45 | } while (0) |
46 | |
47 | /* Fields for FlashPartInfo->flags */ |
48 | |
49 | /* erase capabilities */ |
50 | #define ER_4K 1 |
51 | #define ER_32K 2 |
52 | /* set to allow the page program command to write 0s back to 1. Useful for |
53 | * modelling EEPROM with SPI flash command set |
54 | */ |
55 | #define EEPROM 0x100 |
56 | |
57 | /* 16 MiB max in 3 byte address mode */ |
58 | #define MAX_3BYTES_SIZE 0x1000000 |
59 | |
60 | #define SPI_NOR_MAX_ID_LEN 6 |
61 | |
62 | typedef struct FlashPartInfo { |
63 | const char *part_name; |
64 | /* |
65 | * This array stores the ID bytes. |
66 | * The first three bytes are the JEDIC ID. |
67 | * JEDEC ID zero means "no ID" (mostly older chips). |
68 | */ |
69 | uint8_t id[SPI_NOR_MAX_ID_LEN]; |
70 | uint8_t id_len; |
71 | /* there is confusion between manufacturers as to what a sector is. In this |
72 | * device model, a "sector" is the size that is erased by the ERASE_SECTOR |
73 | * command (opcode 0xd8). |
74 | */ |
75 | uint32_t sector_size; |
76 | uint32_t n_sectors; |
77 | uint32_t page_size; |
78 | uint16_t flags; |
79 | /* |
80 | * Big sized spi nor are often stacked devices, thus sometime |
81 | * replace chip erase with die erase. |
82 | * This field inform how many die is in the chip. |
83 | */ |
84 | uint8_t die_cnt; |
85 | } FlashPartInfo; |
86 | |
87 | /* adapted from linux */ |
88 | /* Used when the "_ext_id" is two bytes at most */ |
89 | #define INFO(_part_name, _jedec_id, _ext_id, _sector_size, _n_sectors, _flags)\ |
90 | .part_name = _part_name,\ |
91 | .id = {\ |
92 | ((_jedec_id) >> 16) & 0xff,\ |
93 | ((_jedec_id) >> 8) & 0xff,\ |
94 | (_jedec_id) & 0xff,\ |
95 | ((_ext_id) >> 8) & 0xff,\ |
96 | (_ext_id) & 0xff,\ |
97 | },\ |
98 | .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),\ |
99 | .sector_size = (_sector_size),\ |
100 | .n_sectors = (_n_sectors),\ |
101 | .page_size = 256,\ |
102 | .flags = (_flags),\ |
103 | .die_cnt = 0 |
104 | |
105 | #define INFO6(_part_name, _jedec_id, _ext_id, _sector_size, _n_sectors, _flags)\ |
106 | .part_name = _part_name,\ |
107 | .id = {\ |
108 | ((_jedec_id) >> 16) & 0xff,\ |
109 | ((_jedec_id) >> 8) & 0xff,\ |
110 | (_jedec_id) & 0xff,\ |
111 | ((_ext_id) >> 16) & 0xff,\ |
112 | ((_ext_id) >> 8) & 0xff,\ |
113 | (_ext_id) & 0xff,\ |
114 | },\ |
115 | .id_len = 6,\ |
116 | .sector_size = (_sector_size),\ |
117 | .n_sectors = (_n_sectors),\ |
118 | .page_size = 256,\ |
119 | .flags = (_flags),\ |
120 | .die_cnt = 0 |
121 | |
122 | #define INFO_STACKED(_part_name, _jedec_id, _ext_id, _sector_size, _n_sectors,\ |
123 | _flags, _die_cnt)\ |
124 | .part_name = _part_name,\ |
125 | .id = {\ |
126 | ((_jedec_id) >> 16) & 0xff,\ |
127 | ((_jedec_id) >> 8) & 0xff,\ |
128 | (_jedec_id) & 0xff,\ |
129 | ((_ext_id) >> 8) & 0xff,\ |
130 | (_ext_id) & 0xff,\ |
131 | },\ |
132 | .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),\ |
133 | .sector_size = (_sector_size),\ |
134 | .n_sectors = (_n_sectors),\ |
135 | .page_size = 256,\ |
136 | .flags = (_flags),\ |
137 | .die_cnt = _die_cnt |
138 | |
139 | #define JEDEC_NUMONYX 0x20 |
140 | #define JEDEC_WINBOND 0xEF |
141 | #define JEDEC_SPANSION 0x01 |
142 | |
143 | /* Numonyx (Micron) Configuration register macros */ |
144 | #define VCFG_DUMMY 0x1 |
145 | #define VCFG_WRAP_SEQUENTIAL 0x2 |
146 | #define NVCFG_XIP_MODE_DISABLED (7 << 9) |
147 | #define NVCFG_XIP_MODE_MASK (7 << 9) |
148 | #define VCFG_XIP_MODE_ENABLED (1 << 3) |
149 | #define CFG_DUMMY_CLK_LEN 4 |
150 | #define NVCFG_DUMMY_CLK_POS 12 |
151 | #define VCFG_DUMMY_CLK_POS 4 |
152 | #define EVCFG_OUT_DRIVER_STRENGTH_DEF 7 |
153 | #define EVCFG_VPP_ACCELERATOR (1 << 3) |
154 | #define EVCFG_RESET_HOLD_ENABLED (1 << 4) |
155 | #define NVCFG_DUAL_IO_MASK (1 << 2) |
156 | #define EVCFG_DUAL_IO_ENABLED (1 << 6) |
157 | #define NVCFG_QUAD_IO_MASK (1 << 3) |
158 | #define EVCFG_QUAD_IO_ENABLED (1 << 7) |
159 | #define NVCFG_4BYTE_ADDR_MASK (1 << 0) |
160 | #define NVCFG_LOWER_SEGMENT_MASK (1 << 1) |
161 | |
162 | /* Numonyx (Micron) Flag Status Register macros */ |
163 | #define FSR_4BYTE_ADDR_MODE_ENABLED 0x1 |
164 | #define FSR_FLASH_READY (1 << 7) |
165 | |
166 | /* Spansion configuration registers macros. */ |
167 | #define SPANSION_QUAD_CFG_POS 0 |
168 | #define SPANSION_QUAD_CFG_LEN 1 |
169 | #define SPANSION_DUMMY_CLK_POS 0 |
170 | #define SPANSION_DUMMY_CLK_LEN 4 |
171 | #define SPANSION_ADDR_LEN_POS 7 |
172 | #define SPANSION_ADDR_LEN_LEN 1 |
173 | |
174 | /* |
175 | * Spansion read mode command length in bytes, |
176 | * the mode is currently not supported. |
177 | */ |
178 | |
179 | #define SPANSION_CONTINUOUS_READ_MODE_CMD_LEN 1 |
180 | #define WINBOND_CONTINUOUS_READ_MODE_CMD_LEN 1 |
181 | |
182 | static const FlashPartInfo known_devices[] = { |
183 | /* Atmel -- some are (confusingly) marketed as "DataFlash" */ |
184 | { INFO("at25fs010" , 0x1f6601, 0, 32 << 10, 4, ER_4K) }, |
185 | { INFO("at25fs040" , 0x1f6604, 0, 64 << 10, 8, ER_4K) }, |
186 | |
187 | { INFO("at25df041a" , 0x1f4401, 0, 64 << 10, 8, ER_4K) }, |
188 | { INFO("at25df321a" , 0x1f4701, 0, 64 << 10, 64, ER_4K) }, |
189 | { INFO("at25df641" , 0x1f4800, 0, 64 << 10, 128, ER_4K) }, |
190 | |
191 | { INFO("at26f004" , 0x1f0400, 0, 64 << 10, 8, ER_4K) }, |
192 | { INFO("at26df081a" , 0x1f4501, 0, 64 << 10, 16, ER_4K) }, |
193 | { INFO("at26df161a" , 0x1f4601, 0, 64 << 10, 32, ER_4K) }, |
194 | { INFO("at26df321" , 0x1f4700, 0, 64 << 10, 64, ER_4K) }, |
195 | |
196 | { INFO("at45db081d" , 0x1f2500, 0, 64 << 10, 16, ER_4K) }, |
197 | |
198 | /* Atmel EEPROMS - it is assumed, that don't care bit in command |
199 | * is set to 0. Block protection is not supported. |
200 | */ |
201 | { INFO("at25128a-nonjedec" , 0x0, 0, 1, 131072, EEPROM) }, |
202 | { INFO("at25256a-nonjedec" , 0x0, 0, 1, 262144, EEPROM) }, |
203 | |
204 | /* EON -- en25xxx */ |
205 | { INFO("en25f32" , 0x1c3116, 0, 64 << 10, 64, ER_4K) }, |
206 | { INFO("en25p32" , 0x1c2016, 0, 64 << 10, 64, 0) }, |
207 | { INFO("en25q32b" , 0x1c3016, 0, 64 << 10, 64, 0) }, |
208 | { INFO("en25p64" , 0x1c2017, 0, 64 << 10, 128, 0) }, |
209 | { INFO("en25q64" , 0x1c3017, 0, 64 << 10, 128, ER_4K) }, |
210 | |
211 | /* GigaDevice */ |
212 | { INFO("gd25q32" , 0xc84016, 0, 64 << 10, 64, ER_4K) }, |
213 | { INFO("gd25q64" , 0xc84017, 0, 64 << 10, 128, ER_4K) }, |
214 | |
215 | /* Intel/Numonyx -- xxxs33b */ |
216 | { INFO("160s33b" , 0x898911, 0, 64 << 10, 32, 0) }, |
217 | { INFO("320s33b" , 0x898912, 0, 64 << 10, 64, 0) }, |
218 | { INFO("640s33b" , 0x898913, 0, 64 << 10, 128, 0) }, |
219 | { INFO("n25q064" , 0x20ba17, 0, 64 << 10, 128, 0) }, |
220 | |
221 | /* Macronix */ |
222 | { INFO("mx25l2005a" , 0xc22012, 0, 64 << 10, 4, ER_4K) }, |
223 | { INFO("mx25l4005a" , 0xc22013, 0, 64 << 10, 8, ER_4K) }, |
224 | { INFO("mx25l8005" , 0xc22014, 0, 64 << 10, 16, 0) }, |
225 | { INFO("mx25l1606e" , 0xc22015, 0, 64 << 10, 32, ER_4K) }, |
226 | { INFO("mx25l3205d" , 0xc22016, 0, 64 << 10, 64, 0) }, |
227 | { INFO("mx25l6405d" , 0xc22017, 0, 64 << 10, 128, 0) }, |
228 | { INFO("mx25l12805d" , 0xc22018, 0, 64 << 10, 256, 0) }, |
229 | { INFO("mx25l12855e" , 0xc22618, 0, 64 << 10, 256, 0) }, |
230 | { INFO("mx25l25635e" , 0xc22019, 0, 64 << 10, 512, 0) }, |
231 | { INFO("mx25l25655e" , 0xc22619, 0, 64 << 10, 512, 0) }, |
232 | { INFO("mx66u51235f" , 0xc2253a, 0, 64 << 10, 1024, ER_4K | ER_32K) }, |
233 | { INFO("mx66u1g45g" , 0xc2253b, 0, 64 << 10, 2048, ER_4K | ER_32K) }, |
234 | { INFO("mx66l1g45g" , 0xc2201b, 0, 64 << 10, 2048, ER_4K | ER_32K) }, |
235 | |
236 | /* Micron */ |
237 | { INFO("n25q032a11" , 0x20bb16, 0, 64 << 10, 64, ER_4K) }, |
238 | { INFO("n25q032a13" , 0x20ba16, 0, 64 << 10, 64, ER_4K) }, |
239 | { INFO("n25q064a11" , 0x20bb17, 0, 64 << 10, 128, ER_4K) }, |
240 | { INFO("n25q064a13" , 0x20ba17, 0, 64 << 10, 128, ER_4K) }, |
241 | { INFO("n25q128a11" , 0x20bb18, 0, 64 << 10, 256, ER_4K) }, |
242 | { INFO("n25q128a13" , 0x20ba18, 0, 64 << 10, 256, ER_4K) }, |
243 | { INFO("n25q256a11" , 0x20bb19, 0, 64 << 10, 512, ER_4K) }, |
244 | { INFO("n25q256a13" , 0x20ba19, 0, 64 << 10, 512, ER_4K) }, |
245 | { INFO("n25q512a11" , 0x20bb20, 0, 64 << 10, 1024, ER_4K) }, |
246 | { INFO("n25q512a13" , 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, |
247 | { INFO("n25q128" , 0x20ba18, 0, 64 << 10, 256, 0) }, |
248 | { INFO("n25q256a" , 0x20ba19, 0, 64 << 10, 512, ER_4K) }, |
249 | { INFO("n25q512a" , 0x20ba20, 0, 64 << 10, 1024, ER_4K) }, |
250 | { INFO_STACKED("n25q00" , 0x20ba21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, |
251 | { INFO_STACKED("n25q00a" , 0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) }, |
252 | { INFO_STACKED("mt25ql01g" , 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, |
253 | { INFO_STACKED("mt25qu01g" , 0x20bb21, 0x1040, 64 << 10, 2048, ER_4K, 2) }, |
254 | |
255 | /* Spansion -- single (large) sector size only, at least |
256 | * for the chips listed here (without boot sectors). |
257 | */ |
258 | { INFO("s25sl032p" , 0x010215, 0x4d00, 64 << 10, 64, ER_4K) }, |
259 | { INFO("s25sl064p" , 0x010216, 0x4d00, 64 << 10, 128, ER_4K) }, |
260 | { INFO("s25fl256s0" , 0x010219, 0x4d00, 256 << 10, 128, 0) }, |
261 | { INFO("s25fl256s1" , 0x010219, 0x4d01, 64 << 10, 512, 0) }, |
262 | { INFO6("s25fl512s" , 0x010220, 0x4d0080, 256 << 10, 256, 0) }, |
263 | { INFO6("s70fl01gs" , 0x010221, 0x4d0080, 256 << 10, 512, 0) }, |
264 | { INFO("s25sl12800" , 0x012018, 0x0300, 256 << 10, 64, 0) }, |
265 | { INFO("s25sl12801" , 0x012018, 0x0301, 64 << 10, 256, 0) }, |
266 | { INFO("s25fl129p0" , 0x012018, 0x4d00, 256 << 10, 64, 0) }, |
267 | { INFO("s25fl129p1" , 0x012018, 0x4d01, 64 << 10, 256, 0) }, |
268 | { INFO("s25sl004a" , 0x010212, 0, 64 << 10, 8, 0) }, |
269 | { INFO("s25sl008a" , 0x010213, 0, 64 << 10, 16, 0) }, |
270 | { INFO("s25sl016a" , 0x010214, 0, 64 << 10, 32, 0) }, |
271 | { INFO("s25sl032a" , 0x010215, 0, 64 << 10, 64, 0) }, |
272 | { INFO("s25sl064a" , 0x010216, 0, 64 << 10, 128, 0) }, |
273 | { INFO("s25fl016k" , 0xef4015, 0, 64 << 10, 32, ER_4K | ER_32K) }, |
274 | { INFO("s25fl064k" , 0xef4017, 0, 64 << 10, 128, ER_4K | ER_32K) }, |
275 | |
276 | /* Spansion -- boot sectors support */ |
277 | { INFO6("s25fs512s" , 0x010220, 0x4d0081, 256 << 10, 256, 0) }, |
278 | { INFO6("s70fs01gs" , 0x010221, 0x4d0081, 256 << 10, 512, 0) }, |
279 | |
280 | /* SST -- large erase sizes are "overlays", "sectors" are 4<< 10 */ |
281 | { INFO("sst25vf040b" , 0xbf258d, 0, 64 << 10, 8, ER_4K) }, |
282 | { INFO("sst25vf080b" , 0xbf258e, 0, 64 << 10, 16, ER_4K) }, |
283 | { INFO("sst25vf016b" , 0xbf2541, 0, 64 << 10, 32, ER_4K) }, |
284 | { INFO("sst25vf032b" , 0xbf254a, 0, 64 << 10, 64, ER_4K) }, |
285 | { INFO("sst25wf512" , 0xbf2501, 0, 64 << 10, 1, ER_4K) }, |
286 | { INFO("sst25wf010" , 0xbf2502, 0, 64 << 10, 2, ER_4K) }, |
287 | { INFO("sst25wf020" , 0xbf2503, 0, 64 << 10, 4, ER_4K) }, |
288 | { INFO("sst25wf040" , 0xbf2504, 0, 64 << 10, 8, ER_4K) }, |
289 | { INFO("sst25wf080" , 0xbf2505, 0, 64 << 10, 16, ER_4K) }, |
290 | |
291 | /* ST Microelectronics -- newer production may have feature updates */ |
292 | { INFO("m25p05" , 0x202010, 0, 32 << 10, 2, 0) }, |
293 | { INFO("m25p10" , 0x202011, 0, 32 << 10, 4, 0) }, |
294 | { INFO("m25p20" , 0x202012, 0, 64 << 10, 4, 0) }, |
295 | { INFO("m25p40" , 0x202013, 0, 64 << 10, 8, 0) }, |
296 | { INFO("m25p80" , 0x202014, 0, 64 << 10, 16, 0) }, |
297 | { INFO("m25p16" , 0x202015, 0, 64 << 10, 32, 0) }, |
298 | { INFO("m25p32" , 0x202016, 0, 64 << 10, 64, 0) }, |
299 | { INFO("m25p64" , 0x202017, 0, 64 << 10, 128, 0) }, |
300 | { INFO("m25p128" , 0x202018, 0, 256 << 10, 64, 0) }, |
301 | { INFO("n25q032" , 0x20ba16, 0, 64 << 10, 64, 0) }, |
302 | |
303 | { INFO("m45pe10" , 0x204011, 0, 64 << 10, 2, 0) }, |
304 | { INFO("m45pe80" , 0x204014, 0, 64 << 10, 16, 0) }, |
305 | { INFO("m45pe16" , 0x204015, 0, 64 << 10, 32, 0) }, |
306 | |
307 | { INFO("m25pe20" , 0x208012, 0, 64 << 10, 4, 0) }, |
308 | { INFO("m25pe80" , 0x208014, 0, 64 << 10, 16, 0) }, |
309 | { INFO("m25pe16" , 0x208015, 0, 64 << 10, 32, ER_4K) }, |
310 | |
311 | { INFO("m25px32" , 0x207116, 0, 64 << 10, 64, ER_4K) }, |
312 | { INFO("m25px32-s0" , 0x207316, 0, 64 << 10, 64, ER_4K) }, |
313 | { INFO("m25px32-s1" , 0x206316, 0, 64 << 10, 64, ER_4K) }, |
314 | { INFO("m25px64" , 0x207117, 0, 64 << 10, 128, 0) }, |
315 | |
316 | /* Winbond -- w25x "blocks" are 64k, "sectors" are 4KiB */ |
317 | { INFO("w25x10" , 0xef3011, 0, 64 << 10, 2, ER_4K) }, |
318 | { INFO("w25x20" , 0xef3012, 0, 64 << 10, 4, ER_4K) }, |
319 | { INFO("w25x40" , 0xef3013, 0, 64 << 10, 8, ER_4K) }, |
320 | { INFO("w25x80" , 0xef3014, 0, 64 << 10, 16, ER_4K) }, |
321 | { INFO("w25x16" , 0xef3015, 0, 64 << 10, 32, ER_4K) }, |
322 | { INFO("w25x32" , 0xef3016, 0, 64 << 10, 64, ER_4K) }, |
323 | { INFO("w25q32" , 0xef4016, 0, 64 << 10, 64, ER_4K) }, |
324 | { INFO("w25q32dw" , 0xef6016, 0, 64 << 10, 64, ER_4K) }, |
325 | { INFO("w25x64" , 0xef3017, 0, 64 << 10, 128, ER_4K) }, |
326 | { INFO("w25q64" , 0xef4017, 0, 64 << 10, 128, ER_4K) }, |
327 | { INFO("w25q80" , 0xef5014, 0, 64 << 10, 16, ER_4K) }, |
328 | { INFO("w25q80bl" , 0xef4014, 0, 64 << 10, 16, ER_4K) }, |
329 | { INFO("w25q256" , 0xef4019, 0, 64 << 10, 512, ER_4K) }, |
330 | }; |
331 | |
332 | typedef enum { |
333 | NOP = 0, |
334 | WRSR = 0x1, |
335 | WRDI = 0x4, |
336 | RDSR = 0x5, |
337 | WREN = 0x6, |
338 | BRRD = 0x16, |
339 | BRWR = 0x17, |
340 | JEDEC_READ = 0x9f, |
341 | BULK_ERASE_60 = 0x60, |
342 | BULK_ERASE = 0xc7, |
343 | READ_FSR = 0x70, |
344 | RDCR = 0x15, |
345 | |
346 | READ = 0x03, |
347 | READ4 = 0x13, |
348 | FAST_READ = 0x0b, |
349 | FAST_READ4 = 0x0c, |
350 | DOR = 0x3b, |
351 | DOR4 = 0x3c, |
352 | QOR = 0x6b, |
353 | QOR4 = 0x6c, |
354 | DIOR = 0xbb, |
355 | DIOR4 = 0xbc, |
356 | QIOR = 0xeb, |
357 | QIOR4 = 0xec, |
358 | |
359 | PP = 0x02, |
360 | PP4 = 0x12, |
361 | PP4_4 = 0x3e, |
362 | DPP = 0xa2, |
363 | QPP = 0x32, |
364 | QPP_4 = 0x34, |
365 | RDID_90 = 0x90, |
366 | RDID_AB = 0xab, |
367 | |
368 | ERASE_4K = 0x20, |
369 | ERASE4_4K = 0x21, |
370 | ERASE_32K = 0x52, |
371 | ERASE4_32K = 0x5c, |
372 | ERASE_SECTOR = 0xd8, |
373 | ERASE4_SECTOR = 0xdc, |
374 | |
375 | EN_4BYTE_ADDR = 0xB7, |
376 | EX_4BYTE_ADDR = 0xE9, |
377 | |
378 | EXTEND_ADDR_READ = 0xC8, |
379 | EXTEND_ADDR_WRITE = 0xC5, |
380 | |
381 | RESET_ENABLE = 0x66, |
382 | RESET_MEMORY = 0x99, |
383 | |
384 | /* |
385 | * Micron: 0x35 - enable QPI |
386 | * Spansion: 0x35 - read control register |
387 | */ |
388 | RDCR_EQIO = 0x35, |
389 | RSTQIO = 0xf5, |
390 | |
391 | RNVCR = 0xB5, |
392 | WNVCR = 0xB1, |
393 | |
394 | RVCR = 0x85, |
395 | WVCR = 0x81, |
396 | |
397 | REVCR = 0x65, |
398 | WEVCR = 0x61, |
399 | |
400 | DIE_ERASE = 0xC4, |
401 | } FlashCMD; |
402 | |
403 | typedef enum { |
404 | STATE_IDLE, |
405 | STATE_PAGE_PROGRAM, |
406 | STATE_READ, |
407 | STATE_COLLECTING_DATA, |
408 | STATE_COLLECTING_VAR_LEN_DATA, |
409 | STATE_READING_DATA, |
410 | } CMDState; |
411 | |
412 | typedef enum { |
413 | MAN_SPANSION, |
414 | MAN_MACRONIX, |
415 | MAN_NUMONYX, |
416 | MAN_WINBOND, |
417 | MAN_SST, |
418 | MAN_GENERIC, |
419 | } Manufacturer; |
420 | |
421 | #define M25P80_INTERNAL_DATA_BUFFER_SZ 16 |
422 | |
423 | typedef struct Flash { |
424 | SSISlave parent_obj; |
425 | |
426 | BlockBackend *blk; |
427 | |
428 | uint8_t *storage; |
429 | uint32_t size; |
430 | int page_size; |
431 | |
432 | uint8_t state; |
433 | uint8_t data[M25P80_INTERNAL_DATA_BUFFER_SZ]; |
434 | uint32_t len; |
435 | uint32_t pos; |
436 | bool data_read_loop; |
437 | uint8_t needed_bytes; |
438 | uint8_t cmd_in_progress; |
439 | uint32_t cur_addr; |
440 | uint32_t nonvolatile_cfg; |
441 | /* Configuration register for Macronix */ |
442 | uint32_t volatile_cfg; |
443 | uint32_t enh_volatile_cfg; |
444 | /* Spansion cfg registers. */ |
445 | uint8_t spansion_cr1nv; |
446 | uint8_t spansion_cr2nv; |
447 | uint8_t spansion_cr3nv; |
448 | uint8_t spansion_cr4nv; |
449 | uint8_t spansion_cr1v; |
450 | uint8_t spansion_cr2v; |
451 | uint8_t spansion_cr3v; |
452 | uint8_t spansion_cr4v; |
453 | bool write_enable; |
454 | bool four_bytes_address_mode; |
455 | bool reset_enable; |
456 | bool quad_enable; |
457 | uint8_t ear; |
458 | |
459 | int64_t dirty_page; |
460 | |
461 | const FlashPartInfo *pi; |
462 | |
463 | } Flash; |
464 | |
465 | typedef struct M25P80Class { |
466 | SSISlaveClass parent_class; |
467 | FlashPartInfo *pi; |
468 | } M25P80Class; |
469 | |
470 | #define TYPE_M25P80 "m25p80-generic" |
471 | #define M25P80(obj) \ |
472 | OBJECT_CHECK(Flash, (obj), TYPE_M25P80) |
473 | #define M25P80_CLASS(klass) \ |
474 | OBJECT_CLASS_CHECK(M25P80Class, (klass), TYPE_M25P80) |
475 | #define M25P80_GET_CLASS(obj) \ |
476 | OBJECT_GET_CLASS(M25P80Class, (obj), TYPE_M25P80) |
477 | |
478 | static inline Manufacturer get_man(Flash *s) |
479 | { |
480 | switch (s->pi->id[0]) { |
481 | case 0x20: |
482 | return MAN_NUMONYX; |
483 | case 0xEF: |
484 | return MAN_WINBOND; |
485 | case 0x01: |
486 | return MAN_SPANSION; |
487 | case 0xC2: |
488 | return MAN_MACRONIX; |
489 | case 0xBF: |
490 | return MAN_SST; |
491 | default: |
492 | return MAN_GENERIC; |
493 | } |
494 | } |
495 | |
496 | static void blk_sync_complete(void *opaque, int ret) |
497 | { |
498 | QEMUIOVector *iov = opaque; |
499 | |
500 | qemu_iovec_destroy(iov); |
501 | g_free(iov); |
502 | |
503 | /* do nothing. Masters do not directly interact with the backing store, |
504 | * only the working copy so no mutexing required. |
505 | */ |
506 | } |
507 | |
508 | static void flash_sync_page(Flash *s, int page) |
509 | { |
510 | QEMUIOVector *iov; |
511 | |
512 | if (!s->blk || blk_is_read_only(s->blk)) { |
513 | return; |
514 | } |
515 | |
516 | iov = g_new(QEMUIOVector, 1); |
517 | qemu_iovec_init(iov, 1); |
518 | qemu_iovec_add(iov, s->storage + page * s->pi->page_size, |
519 | s->pi->page_size); |
520 | blk_aio_pwritev(s->blk, page * s->pi->page_size, iov, 0, |
521 | blk_sync_complete, iov); |
522 | } |
523 | |
524 | static inline void flash_sync_area(Flash *s, int64_t off, int64_t len) |
525 | { |
526 | QEMUIOVector *iov; |
527 | |
528 | if (!s->blk || blk_is_read_only(s->blk)) { |
529 | return; |
530 | } |
531 | |
532 | assert(!(len % BDRV_SECTOR_SIZE)); |
533 | iov = g_new(QEMUIOVector, 1); |
534 | qemu_iovec_init(iov, 1); |
535 | qemu_iovec_add(iov, s->storage + off, len); |
536 | blk_aio_pwritev(s->blk, off, iov, 0, blk_sync_complete, iov); |
537 | } |
538 | |
539 | static void flash_erase(Flash *s, int offset, FlashCMD cmd) |
540 | { |
541 | uint32_t len; |
542 | uint8_t capa_to_assert = 0; |
543 | |
544 | switch (cmd) { |
545 | case ERASE_4K: |
546 | case ERASE4_4K: |
547 | len = 4 * KiB; |
548 | capa_to_assert = ER_4K; |
549 | break; |
550 | case ERASE_32K: |
551 | case ERASE4_32K: |
552 | len = 32 * KiB; |
553 | capa_to_assert = ER_32K; |
554 | break; |
555 | case ERASE_SECTOR: |
556 | case ERASE4_SECTOR: |
557 | len = s->pi->sector_size; |
558 | break; |
559 | case BULK_ERASE: |
560 | len = s->size; |
561 | break; |
562 | case DIE_ERASE: |
563 | if (s->pi->die_cnt) { |
564 | len = s->size / s->pi->die_cnt; |
565 | offset = offset & (~(len - 1)); |
566 | } else { |
567 | qemu_log_mask(LOG_GUEST_ERROR, "M25P80: die erase is not supported" |
568 | " by device\n" ); |
569 | return; |
570 | } |
571 | break; |
572 | default: |
573 | abort(); |
574 | } |
575 | |
576 | DB_PRINT_L(0, "offset = %#x, len = %d\n" , offset, len); |
577 | if ((s->pi->flags & capa_to_assert) != capa_to_assert) { |
578 | qemu_log_mask(LOG_GUEST_ERROR, "M25P80: %d erase size not supported by" |
579 | " device\n" , len); |
580 | } |
581 | |
582 | if (!s->write_enable) { |
583 | qemu_log_mask(LOG_GUEST_ERROR, "M25P80: erase with write protect!\n" ); |
584 | return; |
585 | } |
586 | memset(s->storage + offset, 0xff, len); |
587 | flash_sync_area(s, offset, len); |
588 | } |
589 | |
590 | static inline void flash_sync_dirty(Flash *s, int64_t newpage) |
591 | { |
592 | if (s->dirty_page >= 0 && s->dirty_page != newpage) { |
593 | flash_sync_page(s, s->dirty_page); |
594 | s->dirty_page = newpage; |
595 | } |
596 | } |
597 | |
598 | static inline |
599 | void flash_write8(Flash *s, uint32_t addr, uint8_t data) |
600 | { |
601 | uint32_t page = addr / s->pi->page_size; |
602 | uint8_t prev = s->storage[s->cur_addr]; |
603 | |
604 | if (!s->write_enable) { |
605 | qemu_log_mask(LOG_GUEST_ERROR, "M25P80: write with write protect!\n" ); |
606 | } |
607 | |
608 | if ((prev ^ data) & data) { |
609 | DB_PRINT_L(1, "programming zero to one! addr=%" PRIx32 " %" PRIx8 |
610 | " -> %" PRIx8 "\n" , addr, prev, data); |
611 | } |
612 | |
613 | if (s->pi->flags & EEPROM) { |
614 | s->storage[s->cur_addr] = data; |
615 | } else { |
616 | s->storage[s->cur_addr] &= data; |
617 | } |
618 | |
619 | flash_sync_dirty(s, page); |
620 | s->dirty_page = page; |
621 | } |
622 | |
623 | static inline int get_addr_length(Flash *s) |
624 | { |
625 | /* check if eeprom is in use */ |
626 | if (s->pi->flags == EEPROM) { |
627 | return 2; |
628 | } |
629 | |
630 | switch (s->cmd_in_progress) { |
631 | case PP4: |
632 | case PP4_4: |
633 | case QPP_4: |
634 | case READ4: |
635 | case QIOR4: |
636 | case ERASE4_4K: |
637 | case ERASE4_32K: |
638 | case ERASE4_SECTOR: |
639 | case FAST_READ4: |
640 | case DOR4: |
641 | case QOR4: |
642 | case DIOR4: |
643 | return 4; |
644 | default: |
645 | return s->four_bytes_address_mode ? 4 : 3; |
646 | } |
647 | } |
648 | |
649 | static void complete_collecting_data(Flash *s) |
650 | { |
651 | int i, n; |
652 | |
653 | n = get_addr_length(s); |
654 | s->cur_addr = (n == 3 ? s->ear : 0); |
655 | for (i = 0; i < n; ++i) { |
656 | s->cur_addr <<= 8; |
657 | s->cur_addr |= s->data[i]; |
658 | } |
659 | |
660 | s->cur_addr &= s->size - 1; |
661 | |
662 | s->state = STATE_IDLE; |
663 | |
664 | switch (s->cmd_in_progress) { |
665 | case DPP: |
666 | case QPP: |
667 | case QPP_4: |
668 | case PP: |
669 | case PP4: |
670 | case PP4_4: |
671 | s->state = STATE_PAGE_PROGRAM; |
672 | break; |
673 | case READ: |
674 | case READ4: |
675 | case FAST_READ: |
676 | case FAST_READ4: |
677 | case DOR: |
678 | case DOR4: |
679 | case QOR: |
680 | case QOR4: |
681 | case DIOR: |
682 | case DIOR4: |
683 | case QIOR: |
684 | case QIOR4: |
685 | s->state = STATE_READ; |
686 | break; |
687 | case ERASE_4K: |
688 | case ERASE4_4K: |
689 | case ERASE_32K: |
690 | case ERASE4_32K: |
691 | case ERASE_SECTOR: |
692 | case ERASE4_SECTOR: |
693 | case DIE_ERASE: |
694 | flash_erase(s, s->cur_addr, s->cmd_in_progress); |
695 | break; |
696 | case WRSR: |
697 | switch (get_man(s)) { |
698 | case MAN_SPANSION: |
699 | s->quad_enable = !!(s->data[1] & 0x02); |
700 | break; |
701 | case MAN_MACRONIX: |
702 | s->quad_enable = extract32(s->data[0], 6, 1); |
703 | if (s->len > 1) { |
704 | s->volatile_cfg = s->data[1]; |
705 | s->four_bytes_address_mode = extract32(s->data[1], 5, 1); |
706 | } |
707 | break; |
708 | default: |
709 | break; |
710 | } |
711 | if (s->write_enable) { |
712 | s->write_enable = false; |
713 | } |
714 | break; |
715 | case BRWR: |
716 | case EXTEND_ADDR_WRITE: |
717 | s->ear = s->data[0]; |
718 | break; |
719 | case WNVCR: |
720 | s->nonvolatile_cfg = s->data[0] | (s->data[1] << 8); |
721 | break; |
722 | case WVCR: |
723 | s->volatile_cfg = s->data[0]; |
724 | break; |
725 | case WEVCR: |
726 | s->enh_volatile_cfg = s->data[0]; |
727 | break; |
728 | case RDID_90: |
729 | case RDID_AB: |
730 | if (get_man(s) == MAN_SST) { |
731 | if (s->cur_addr <= 1) { |
732 | if (s->cur_addr) { |
733 | s->data[0] = s->pi->id[2]; |
734 | s->data[1] = s->pi->id[0]; |
735 | } else { |
736 | s->data[0] = s->pi->id[0]; |
737 | s->data[1] = s->pi->id[2]; |
738 | } |
739 | s->pos = 0; |
740 | s->len = 2; |
741 | s->data_read_loop = true; |
742 | s->state = STATE_READING_DATA; |
743 | } else { |
744 | qemu_log_mask(LOG_GUEST_ERROR, |
745 | "M25P80: Invalid read id address\n" ); |
746 | } |
747 | } else { |
748 | qemu_log_mask(LOG_GUEST_ERROR, |
749 | "M25P80: Read id (command 0x90/0xAB) is not supported" |
750 | " by device\n" ); |
751 | } |
752 | break; |
753 | default: |
754 | break; |
755 | } |
756 | } |
757 | |
758 | static void reset_memory(Flash *s) |
759 | { |
760 | s->cmd_in_progress = NOP; |
761 | s->cur_addr = 0; |
762 | s->ear = 0; |
763 | s->four_bytes_address_mode = false; |
764 | s->len = 0; |
765 | s->needed_bytes = 0; |
766 | s->pos = 0; |
767 | s->state = STATE_IDLE; |
768 | s->write_enable = false; |
769 | s->reset_enable = false; |
770 | s->quad_enable = false; |
771 | |
772 | switch (get_man(s)) { |
773 | case MAN_NUMONYX: |
774 | s->volatile_cfg = 0; |
775 | s->volatile_cfg |= VCFG_DUMMY; |
776 | s->volatile_cfg |= VCFG_WRAP_SEQUENTIAL; |
777 | if ((s->nonvolatile_cfg & NVCFG_XIP_MODE_MASK) |
778 | != NVCFG_XIP_MODE_DISABLED) { |
779 | s->volatile_cfg |= VCFG_XIP_MODE_ENABLED; |
780 | } |
781 | s->volatile_cfg |= deposit32(s->volatile_cfg, |
782 | VCFG_DUMMY_CLK_POS, |
783 | CFG_DUMMY_CLK_LEN, |
784 | extract32(s->nonvolatile_cfg, |
785 | NVCFG_DUMMY_CLK_POS, |
786 | CFG_DUMMY_CLK_LEN) |
787 | ); |
788 | |
789 | s->enh_volatile_cfg = 0; |
790 | s->enh_volatile_cfg |= EVCFG_OUT_DRIVER_STRENGTH_DEF; |
791 | s->enh_volatile_cfg |= EVCFG_VPP_ACCELERATOR; |
792 | s->enh_volatile_cfg |= EVCFG_RESET_HOLD_ENABLED; |
793 | if (s->nonvolatile_cfg & NVCFG_DUAL_IO_MASK) { |
794 | s->enh_volatile_cfg |= EVCFG_DUAL_IO_ENABLED; |
795 | } |
796 | if (s->nonvolatile_cfg & NVCFG_QUAD_IO_MASK) { |
797 | s->enh_volatile_cfg |= EVCFG_QUAD_IO_ENABLED; |
798 | } |
799 | if (!(s->nonvolatile_cfg & NVCFG_4BYTE_ADDR_MASK)) { |
800 | s->four_bytes_address_mode = true; |
801 | } |
802 | if (!(s->nonvolatile_cfg & NVCFG_LOWER_SEGMENT_MASK)) { |
803 | s->ear = s->size / MAX_3BYTES_SIZE - 1; |
804 | } |
805 | break; |
806 | case MAN_MACRONIX: |
807 | s->volatile_cfg = 0x7; |
808 | break; |
809 | case MAN_SPANSION: |
810 | s->spansion_cr1v = s->spansion_cr1nv; |
811 | s->spansion_cr2v = s->spansion_cr2nv; |
812 | s->spansion_cr3v = s->spansion_cr3nv; |
813 | s->spansion_cr4v = s->spansion_cr4nv; |
814 | s->quad_enable = extract32(s->spansion_cr1v, |
815 | SPANSION_QUAD_CFG_POS, |
816 | SPANSION_QUAD_CFG_LEN |
817 | ); |
818 | s->four_bytes_address_mode = extract32(s->spansion_cr2v, |
819 | SPANSION_ADDR_LEN_POS, |
820 | SPANSION_ADDR_LEN_LEN |
821 | ); |
822 | break; |
823 | default: |
824 | break; |
825 | } |
826 | |
827 | DB_PRINT_L(0, "Reset done.\n" ); |
828 | } |
829 | |
830 | static void decode_fast_read_cmd(Flash *s) |
831 | { |
832 | s->needed_bytes = get_addr_length(s); |
833 | switch (get_man(s)) { |
834 | /* Dummy cycles - modeled with bytes writes instead of bits */ |
835 | case MAN_WINBOND: |
836 | s->needed_bytes += 8; |
837 | break; |
838 | case MAN_NUMONYX: |
839 | s->needed_bytes += extract32(s->volatile_cfg, 4, 4); |
840 | break; |
841 | case MAN_MACRONIX: |
842 | if (extract32(s->volatile_cfg, 6, 2) == 1) { |
843 | s->needed_bytes += 6; |
844 | } else { |
845 | s->needed_bytes += 8; |
846 | } |
847 | break; |
848 | case MAN_SPANSION: |
849 | s->needed_bytes += extract32(s->spansion_cr2v, |
850 | SPANSION_DUMMY_CLK_POS, |
851 | SPANSION_DUMMY_CLK_LEN |
852 | ); |
853 | break; |
854 | default: |
855 | break; |
856 | } |
857 | s->pos = 0; |
858 | s->len = 0; |
859 | s->state = STATE_COLLECTING_DATA; |
860 | } |
861 | |
862 | static void decode_dio_read_cmd(Flash *s) |
863 | { |
864 | s->needed_bytes = get_addr_length(s); |
865 | /* Dummy cycles modeled with bytes writes instead of bits */ |
866 | switch (get_man(s)) { |
867 | case MAN_WINBOND: |
868 | s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN; |
869 | break; |
870 | case MAN_SPANSION: |
871 | s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN; |
872 | s->needed_bytes += extract32(s->spansion_cr2v, |
873 | SPANSION_DUMMY_CLK_POS, |
874 | SPANSION_DUMMY_CLK_LEN |
875 | ); |
876 | break; |
877 | case MAN_NUMONYX: |
878 | s->needed_bytes += extract32(s->volatile_cfg, 4, 4); |
879 | break; |
880 | case MAN_MACRONIX: |
881 | switch (extract32(s->volatile_cfg, 6, 2)) { |
882 | case 1: |
883 | s->needed_bytes += 6; |
884 | break; |
885 | case 2: |
886 | s->needed_bytes += 8; |
887 | break; |
888 | default: |
889 | s->needed_bytes += 4; |
890 | break; |
891 | } |
892 | break; |
893 | default: |
894 | break; |
895 | } |
896 | s->pos = 0; |
897 | s->len = 0; |
898 | s->state = STATE_COLLECTING_DATA; |
899 | } |
900 | |
901 | static void decode_qio_read_cmd(Flash *s) |
902 | { |
903 | s->needed_bytes = get_addr_length(s); |
904 | /* Dummy cycles modeled with bytes writes instead of bits */ |
905 | switch (get_man(s)) { |
906 | case MAN_WINBOND: |
907 | s->needed_bytes += WINBOND_CONTINUOUS_READ_MODE_CMD_LEN; |
908 | s->needed_bytes += 4; |
909 | break; |
910 | case MAN_SPANSION: |
911 | s->needed_bytes += SPANSION_CONTINUOUS_READ_MODE_CMD_LEN; |
912 | s->needed_bytes += extract32(s->spansion_cr2v, |
913 | SPANSION_DUMMY_CLK_POS, |
914 | SPANSION_DUMMY_CLK_LEN |
915 | ); |
916 | break; |
917 | case MAN_NUMONYX: |
918 | s->needed_bytes += extract32(s->volatile_cfg, 4, 4); |
919 | break; |
920 | case MAN_MACRONIX: |
921 | switch (extract32(s->volatile_cfg, 6, 2)) { |
922 | case 1: |
923 | s->needed_bytes += 4; |
924 | break; |
925 | case 2: |
926 | s->needed_bytes += 8; |
927 | break; |
928 | default: |
929 | s->needed_bytes += 6; |
930 | break; |
931 | } |
932 | break; |
933 | default: |
934 | break; |
935 | } |
936 | s->pos = 0; |
937 | s->len = 0; |
938 | s->state = STATE_COLLECTING_DATA; |
939 | } |
940 | |
941 | static void decode_new_cmd(Flash *s, uint32_t value) |
942 | { |
943 | s->cmd_in_progress = value; |
944 | int i; |
945 | DB_PRINT_L(0, "decoded new command:%x\n" , value); |
946 | |
947 | if (value != RESET_MEMORY) { |
948 | s->reset_enable = false; |
949 | } |
950 | |
951 | switch (value) { |
952 | |
953 | case ERASE_4K: |
954 | case ERASE4_4K: |
955 | case ERASE_32K: |
956 | case ERASE4_32K: |
957 | case ERASE_SECTOR: |
958 | case ERASE4_SECTOR: |
959 | case READ: |
960 | case READ4: |
961 | case DPP: |
962 | case QPP: |
963 | case QPP_4: |
964 | case PP: |
965 | case PP4: |
966 | case PP4_4: |
967 | case DIE_ERASE: |
968 | case RDID_90: |
969 | case RDID_AB: |
970 | s->needed_bytes = get_addr_length(s); |
971 | s->pos = 0; |
972 | s->len = 0; |
973 | s->state = STATE_COLLECTING_DATA; |
974 | break; |
975 | |
976 | case FAST_READ: |
977 | case FAST_READ4: |
978 | case DOR: |
979 | case DOR4: |
980 | case QOR: |
981 | case QOR4: |
982 | decode_fast_read_cmd(s); |
983 | break; |
984 | |
985 | case DIOR: |
986 | case DIOR4: |
987 | decode_dio_read_cmd(s); |
988 | break; |
989 | |
990 | case QIOR: |
991 | case QIOR4: |
992 | decode_qio_read_cmd(s); |
993 | break; |
994 | |
995 | case WRSR: |
996 | if (s->write_enable) { |
997 | switch (get_man(s)) { |
998 | case MAN_SPANSION: |
999 | s->needed_bytes = 2; |
1000 | s->state = STATE_COLLECTING_DATA; |
1001 | break; |
1002 | case MAN_MACRONIX: |
1003 | s->needed_bytes = 2; |
1004 | s->state = STATE_COLLECTING_VAR_LEN_DATA; |
1005 | break; |
1006 | default: |
1007 | s->needed_bytes = 1; |
1008 | s->state = STATE_COLLECTING_DATA; |
1009 | } |
1010 | s->pos = 0; |
1011 | } |
1012 | break; |
1013 | |
1014 | case WRDI: |
1015 | s->write_enable = false; |
1016 | break; |
1017 | case WREN: |
1018 | s->write_enable = true; |
1019 | break; |
1020 | |
1021 | case RDSR: |
1022 | s->data[0] = (!!s->write_enable) << 1; |
1023 | if (get_man(s) == MAN_MACRONIX) { |
1024 | s->data[0] |= (!!s->quad_enable) << 6; |
1025 | } |
1026 | s->pos = 0; |
1027 | s->len = 1; |
1028 | s->data_read_loop = true; |
1029 | s->state = STATE_READING_DATA; |
1030 | break; |
1031 | |
1032 | case READ_FSR: |
1033 | s->data[0] = FSR_FLASH_READY; |
1034 | if (s->four_bytes_address_mode) { |
1035 | s->data[0] |= FSR_4BYTE_ADDR_MODE_ENABLED; |
1036 | } |
1037 | s->pos = 0; |
1038 | s->len = 1; |
1039 | s->data_read_loop = true; |
1040 | s->state = STATE_READING_DATA; |
1041 | break; |
1042 | |
1043 | case JEDEC_READ: |
1044 | DB_PRINT_L(0, "populated jedec code\n" ); |
1045 | for (i = 0; i < s->pi->id_len; i++) { |
1046 | s->data[i] = s->pi->id[i]; |
1047 | } |
1048 | |
1049 | s->len = s->pi->id_len; |
1050 | s->pos = 0; |
1051 | s->state = STATE_READING_DATA; |
1052 | break; |
1053 | |
1054 | case RDCR: |
1055 | s->data[0] = s->volatile_cfg & 0xFF; |
1056 | s->data[0] |= (!!s->four_bytes_address_mode) << 5; |
1057 | s->pos = 0; |
1058 | s->len = 1; |
1059 | s->state = STATE_READING_DATA; |
1060 | break; |
1061 | |
1062 | case BULK_ERASE_60: |
1063 | case BULK_ERASE: |
1064 | if (s->write_enable) { |
1065 | DB_PRINT_L(0, "chip erase\n" ); |
1066 | flash_erase(s, 0, BULK_ERASE); |
1067 | } else { |
1068 | qemu_log_mask(LOG_GUEST_ERROR, "M25P80: chip erase with write " |
1069 | "protect!\n" ); |
1070 | } |
1071 | break; |
1072 | case NOP: |
1073 | break; |
1074 | case EN_4BYTE_ADDR: |
1075 | s->four_bytes_address_mode = true; |
1076 | break; |
1077 | case EX_4BYTE_ADDR: |
1078 | s->four_bytes_address_mode = false; |
1079 | break; |
1080 | case BRRD: |
1081 | case EXTEND_ADDR_READ: |
1082 | s->data[0] = s->ear; |
1083 | s->pos = 0; |
1084 | s->len = 1; |
1085 | s->state = STATE_READING_DATA; |
1086 | break; |
1087 | case BRWR: |
1088 | case EXTEND_ADDR_WRITE: |
1089 | if (s->write_enable) { |
1090 | s->needed_bytes = 1; |
1091 | s->pos = 0; |
1092 | s->len = 0; |
1093 | s->state = STATE_COLLECTING_DATA; |
1094 | } |
1095 | break; |
1096 | case RNVCR: |
1097 | s->data[0] = s->nonvolatile_cfg & 0xFF; |
1098 | s->data[1] = (s->nonvolatile_cfg >> 8) & 0xFF; |
1099 | s->pos = 0; |
1100 | s->len = 2; |
1101 | s->state = STATE_READING_DATA; |
1102 | break; |
1103 | case WNVCR: |
1104 | if (s->write_enable && get_man(s) == MAN_NUMONYX) { |
1105 | s->needed_bytes = 2; |
1106 | s->pos = 0; |
1107 | s->len = 0; |
1108 | s->state = STATE_COLLECTING_DATA; |
1109 | } |
1110 | break; |
1111 | case RVCR: |
1112 | s->data[0] = s->volatile_cfg & 0xFF; |
1113 | s->pos = 0; |
1114 | s->len = 1; |
1115 | s->state = STATE_READING_DATA; |
1116 | break; |
1117 | case WVCR: |
1118 | if (s->write_enable) { |
1119 | s->needed_bytes = 1; |
1120 | s->pos = 0; |
1121 | s->len = 0; |
1122 | s->state = STATE_COLLECTING_DATA; |
1123 | } |
1124 | break; |
1125 | case REVCR: |
1126 | s->data[0] = s->enh_volatile_cfg & 0xFF; |
1127 | s->pos = 0; |
1128 | s->len = 1; |
1129 | s->state = STATE_READING_DATA; |
1130 | break; |
1131 | case WEVCR: |
1132 | if (s->write_enable) { |
1133 | s->needed_bytes = 1; |
1134 | s->pos = 0; |
1135 | s->len = 0; |
1136 | s->state = STATE_COLLECTING_DATA; |
1137 | } |
1138 | break; |
1139 | case RESET_ENABLE: |
1140 | s->reset_enable = true; |
1141 | break; |
1142 | case RESET_MEMORY: |
1143 | if (s->reset_enable) { |
1144 | reset_memory(s); |
1145 | } |
1146 | break; |
1147 | case RDCR_EQIO: |
1148 | switch (get_man(s)) { |
1149 | case MAN_SPANSION: |
1150 | s->data[0] = (!!s->quad_enable) << 1; |
1151 | s->pos = 0; |
1152 | s->len = 1; |
1153 | s->state = STATE_READING_DATA; |
1154 | break; |
1155 | case MAN_MACRONIX: |
1156 | s->quad_enable = true; |
1157 | break; |
1158 | default: |
1159 | break; |
1160 | } |
1161 | break; |
1162 | case RSTQIO: |
1163 | s->quad_enable = false; |
1164 | break; |
1165 | default: |
1166 | qemu_log_mask(LOG_GUEST_ERROR, "M25P80: Unknown cmd %x\n" , value); |
1167 | break; |
1168 | } |
1169 | } |
1170 | |
1171 | static int m25p80_cs(SSISlave *ss, bool select) |
1172 | { |
1173 | Flash *s = M25P80(ss); |
1174 | |
1175 | if (select) { |
1176 | if (s->state == STATE_COLLECTING_VAR_LEN_DATA) { |
1177 | complete_collecting_data(s); |
1178 | } |
1179 | s->len = 0; |
1180 | s->pos = 0; |
1181 | s->state = STATE_IDLE; |
1182 | flash_sync_dirty(s, -1); |
1183 | s->data_read_loop = false; |
1184 | } |
1185 | |
1186 | DB_PRINT_L(0, "%sselect\n" , select ? "de" : "" ); |
1187 | |
1188 | return 0; |
1189 | } |
1190 | |
1191 | static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) |
1192 | { |
1193 | Flash *s = M25P80(ss); |
1194 | uint32_t r = 0; |
1195 | |
1196 | switch (s->state) { |
1197 | |
1198 | case STATE_PAGE_PROGRAM: |
1199 | DB_PRINT_L(1, "page program cur_addr=%#" PRIx32 " data=%" PRIx8 "\n" , |
1200 | s->cur_addr, (uint8_t)tx); |
1201 | flash_write8(s, s->cur_addr, (uint8_t)tx); |
1202 | s->cur_addr = (s->cur_addr + 1) & (s->size - 1); |
1203 | break; |
1204 | |
1205 | case STATE_READ: |
1206 | r = s->storage[s->cur_addr]; |
1207 | DB_PRINT_L(1, "READ 0x%" PRIx32 "=%" PRIx8 "\n" , s->cur_addr, |
1208 | (uint8_t)r); |
1209 | s->cur_addr = (s->cur_addr + 1) & (s->size - 1); |
1210 | break; |
1211 | |
1212 | case STATE_COLLECTING_DATA: |
1213 | case STATE_COLLECTING_VAR_LEN_DATA: |
1214 | |
1215 | if (s->len >= M25P80_INTERNAL_DATA_BUFFER_SZ) { |
1216 | qemu_log_mask(LOG_GUEST_ERROR, |
1217 | "M25P80: Write overrun internal data buffer. " |
1218 | "SPI controller (QEMU emulator or guest driver) " |
1219 | "is misbehaving\n" ); |
1220 | s->len = s->pos = 0; |
1221 | s->state = STATE_IDLE; |
1222 | break; |
1223 | } |
1224 | |
1225 | s->data[s->len] = (uint8_t)tx; |
1226 | s->len++; |
1227 | |
1228 | if (s->len == s->needed_bytes) { |
1229 | complete_collecting_data(s); |
1230 | } |
1231 | break; |
1232 | |
1233 | case STATE_READING_DATA: |
1234 | |
1235 | if (s->pos >= M25P80_INTERNAL_DATA_BUFFER_SZ) { |
1236 | qemu_log_mask(LOG_GUEST_ERROR, |
1237 | "M25P80: Read overrun internal data buffer. " |
1238 | "SPI controller (QEMU emulator or guest driver) " |
1239 | "is misbehaving\n" ); |
1240 | s->len = s->pos = 0; |
1241 | s->state = STATE_IDLE; |
1242 | break; |
1243 | } |
1244 | |
1245 | r = s->data[s->pos]; |
1246 | s->pos++; |
1247 | if (s->pos == s->len) { |
1248 | s->pos = 0; |
1249 | if (!s->data_read_loop) { |
1250 | s->state = STATE_IDLE; |
1251 | } |
1252 | } |
1253 | break; |
1254 | |
1255 | default: |
1256 | case STATE_IDLE: |
1257 | decode_new_cmd(s, (uint8_t)tx); |
1258 | break; |
1259 | } |
1260 | |
1261 | return r; |
1262 | } |
1263 | |
1264 | static void m25p80_realize(SSISlave *ss, Error **errp) |
1265 | { |
1266 | Flash *s = M25P80(ss); |
1267 | M25P80Class *mc = M25P80_GET_CLASS(s); |
1268 | int ret; |
1269 | |
1270 | s->pi = mc->pi; |
1271 | |
1272 | s->size = s->pi->sector_size * s->pi->n_sectors; |
1273 | s->dirty_page = -1; |
1274 | |
1275 | if (s->blk) { |
1276 | uint64_t perm = BLK_PERM_CONSISTENT_READ | |
1277 | (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE); |
1278 | ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp); |
1279 | if (ret < 0) { |
1280 | return; |
1281 | } |
1282 | |
1283 | DB_PRINT_L(0, "Binding to IF_MTD drive\n" ); |
1284 | s->storage = blk_blockalign(s->blk, s->size); |
1285 | |
1286 | if (blk_pread(s->blk, 0, s->storage, s->size) != s->size) { |
1287 | error_setg(errp, "failed to read the initial flash content" ); |
1288 | return; |
1289 | } |
1290 | } else { |
1291 | DB_PRINT_L(0, "No BDRV - binding to RAM\n" ); |
1292 | s->storage = blk_blockalign(NULL, s->size); |
1293 | memset(s->storage, 0xFF, s->size); |
1294 | } |
1295 | } |
1296 | |
1297 | static void m25p80_reset(DeviceState *d) |
1298 | { |
1299 | Flash *s = M25P80(d); |
1300 | |
1301 | reset_memory(s); |
1302 | } |
1303 | |
1304 | static int m25p80_pre_save(void *opaque) |
1305 | { |
1306 | flash_sync_dirty((Flash *)opaque, -1); |
1307 | |
1308 | return 0; |
1309 | } |
1310 | |
1311 | static Property m25p80_properties[] = { |
1312 | /* This is default value for Micron flash */ |
1313 | DEFINE_PROP_UINT32("nonvolatile-cfg" , Flash, nonvolatile_cfg, 0x8FFF), |
1314 | DEFINE_PROP_UINT8("spansion-cr1nv" , Flash, spansion_cr1nv, 0x0), |
1315 | DEFINE_PROP_UINT8("spansion-cr2nv" , Flash, spansion_cr2nv, 0x8), |
1316 | DEFINE_PROP_UINT8("spansion-cr3nv" , Flash, spansion_cr3nv, 0x2), |
1317 | DEFINE_PROP_UINT8("spansion-cr4nv" , Flash, spansion_cr4nv, 0x10), |
1318 | DEFINE_PROP_DRIVE("drive" , Flash, blk), |
1319 | DEFINE_PROP_END_OF_LIST(), |
1320 | }; |
1321 | |
1322 | static int m25p80_pre_load(void *opaque) |
1323 | { |
1324 | Flash *s = (Flash *)opaque; |
1325 | |
1326 | s->data_read_loop = false; |
1327 | return 0; |
1328 | } |
1329 | |
1330 | static bool m25p80_data_read_loop_needed(void *opaque) |
1331 | { |
1332 | Flash *s = (Flash *)opaque; |
1333 | |
1334 | return s->data_read_loop; |
1335 | } |
1336 | |
1337 | static const VMStateDescription vmstate_m25p80_data_read_loop = { |
1338 | .name = "m25p80/data_read_loop" , |
1339 | .version_id = 1, |
1340 | .minimum_version_id = 1, |
1341 | .needed = m25p80_data_read_loop_needed, |
1342 | .fields = (VMStateField[]) { |
1343 | VMSTATE_BOOL(data_read_loop, Flash), |
1344 | VMSTATE_END_OF_LIST() |
1345 | } |
1346 | }; |
1347 | |
1348 | static const VMStateDescription vmstate_m25p80 = { |
1349 | .name = "m25p80" , |
1350 | .version_id = 0, |
1351 | .minimum_version_id = 0, |
1352 | .pre_save = m25p80_pre_save, |
1353 | .pre_load = m25p80_pre_load, |
1354 | .fields = (VMStateField[]) { |
1355 | VMSTATE_UINT8(state, Flash), |
1356 | VMSTATE_UINT8_ARRAY(data, Flash, M25P80_INTERNAL_DATA_BUFFER_SZ), |
1357 | VMSTATE_UINT32(len, Flash), |
1358 | VMSTATE_UINT32(pos, Flash), |
1359 | VMSTATE_UINT8(needed_bytes, Flash), |
1360 | VMSTATE_UINT8(cmd_in_progress, Flash), |
1361 | VMSTATE_UINT32(cur_addr, Flash), |
1362 | VMSTATE_BOOL(write_enable, Flash), |
1363 | VMSTATE_BOOL(reset_enable, Flash), |
1364 | VMSTATE_UINT8(ear, Flash), |
1365 | VMSTATE_BOOL(four_bytes_address_mode, Flash), |
1366 | VMSTATE_UINT32(nonvolatile_cfg, Flash), |
1367 | VMSTATE_UINT32(volatile_cfg, Flash), |
1368 | VMSTATE_UINT32(enh_volatile_cfg, Flash), |
1369 | VMSTATE_BOOL(quad_enable, Flash), |
1370 | VMSTATE_UINT8(spansion_cr1nv, Flash), |
1371 | VMSTATE_UINT8(spansion_cr2nv, Flash), |
1372 | VMSTATE_UINT8(spansion_cr3nv, Flash), |
1373 | VMSTATE_UINT8(spansion_cr4nv, Flash), |
1374 | VMSTATE_END_OF_LIST() |
1375 | }, |
1376 | .subsections = (const VMStateDescription * []) { |
1377 | &vmstate_m25p80_data_read_loop, |
1378 | NULL |
1379 | } |
1380 | }; |
1381 | |
1382 | static void m25p80_class_init(ObjectClass *klass, void *data) |
1383 | { |
1384 | DeviceClass *dc = DEVICE_CLASS(klass); |
1385 | SSISlaveClass *k = SSI_SLAVE_CLASS(klass); |
1386 | M25P80Class *mc = M25P80_CLASS(klass); |
1387 | |
1388 | k->realize = m25p80_realize; |
1389 | k->transfer = m25p80_transfer8; |
1390 | k->set_cs = m25p80_cs; |
1391 | k->cs_polarity = SSI_CS_LOW; |
1392 | dc->vmsd = &vmstate_m25p80; |
1393 | dc->props = m25p80_properties; |
1394 | dc->reset = m25p80_reset; |
1395 | mc->pi = data; |
1396 | } |
1397 | |
1398 | static const TypeInfo m25p80_info = { |
1399 | .name = TYPE_M25P80, |
1400 | .parent = TYPE_SSI_SLAVE, |
1401 | .instance_size = sizeof(Flash), |
1402 | .class_size = sizeof(M25P80Class), |
1403 | .abstract = true, |
1404 | }; |
1405 | |
1406 | static void m25p80_register_types(void) |
1407 | { |
1408 | int i; |
1409 | |
1410 | type_register_static(&m25p80_info); |
1411 | for (i = 0; i < ARRAY_SIZE(known_devices); ++i) { |
1412 | TypeInfo ti = { |
1413 | .name = known_devices[i].part_name, |
1414 | .parent = TYPE_M25P80, |
1415 | .class_init = m25p80_class_init, |
1416 | .class_data = (void *)&known_devices[i], |
1417 | }; |
1418 | type_register(&ti); |
1419 | } |
1420 | } |
1421 | |
1422 | type_init(m25p80_register_types) |
1423 | |