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