m25p80.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  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. #include "hw.h"
  24. #include "sysemu/blockdev.h"
  25. #include "ssi.h"
  26. #include "devices.h"
  27. #ifdef M25P80_ERR_DEBUG
  28. #define DB_PRINT(...) do { \
  29. fprintf(stderr, ": %s: ", __func__); \
  30. fprintf(stderr, ## __VA_ARGS__); \
  31. } while (0);
  32. #else
  33. #define DB_PRINT(...)
  34. #endif
  35. /* Fields for FlashPartInfo->flags */
  36. /* erase capabilities */
  37. #define ER_4K 1
  38. #define ER_32K 2
  39. /* set to allow the page program command to write 0s back to 1. Useful for
  40. * modelling EEPROM with SPI flash command set
  41. */
  42. #define WR_1 0x100
  43. typedef struct FlashPartInfo {
  44. const char *part_name;
  45. /* jedec code. (jedec >> 16) & 0xff is the 1st byte, >> 8 the 2nd etc */
  46. uint32_t jedec;
  47. /* extended jedec code */
  48. uint16_t ext_jedec;
  49. /* there is confusion between manufacturers as to what a sector is. In this
  50. * device model, a "sector" is the size that is erased by the ERASE_SECTOR
  51. * command (opcode 0xd8).
  52. */
  53. uint32_t sector_size;
  54. uint32_t n_sectors;
  55. uint32_t page_size;
  56. uint8_t flags;
  57. } FlashPartInfo;
  58. /* adapted from linux */
  59. #define INFO(_part_name, _jedec, _ext_jedec, _sector_size, _n_sectors, _flags)\
  60. .part_name = (_part_name),\
  61. .jedec = (_jedec),\
  62. .ext_jedec = (_ext_jedec),\
  63. .sector_size = (_sector_size),\
  64. .n_sectors = (_n_sectors),\
  65. .page_size = 256,\
  66. .flags = (_flags),\
  67. #define JEDEC_NUMONYX 0x20
  68. #define JEDEC_WINBOND 0xEF
  69. #define JEDEC_SPANSION 0x01
  70. static const FlashPartInfo known_devices[] = {
  71. /* Atmel -- some are (confusingly) marketed as "DataFlash" */
  72. { INFO("at25fs010", 0x1f6601, 0, 32 << 10, 4, ER_4K) },
  73. { INFO("at25fs040", 0x1f6604, 0, 64 << 10, 8, ER_4K) },
  74. { INFO("at25df041a", 0x1f4401, 0, 64 << 10, 8, ER_4K) },
  75. { INFO("at25df321a", 0x1f4701, 0, 64 << 10, 64, ER_4K) },
  76. { INFO("at25df641", 0x1f4800, 0, 64 << 10, 128, ER_4K) },
  77. { INFO("at26f004", 0x1f0400, 0, 64 << 10, 8, ER_4K) },
  78. { INFO("at26df081a", 0x1f4501, 0, 64 << 10, 16, ER_4K) },
  79. { INFO("at26df161a", 0x1f4601, 0, 64 << 10, 32, ER_4K) },
  80. { INFO("at26df321", 0x1f4700, 0, 64 << 10, 64, ER_4K) },
  81. /* EON -- en25xxx */
  82. { INFO("en25f32", 0x1c3116, 0, 64 << 10, 64, ER_4K) },
  83. { INFO("en25p32", 0x1c2016, 0, 64 << 10, 64, 0) },
  84. { INFO("en25q32b", 0x1c3016, 0, 64 << 10, 64, 0) },
  85. { INFO("en25p64", 0x1c2017, 0, 64 << 10, 128, 0) },
  86. /* Intel/Numonyx -- xxxs33b */
  87. { INFO("160s33b", 0x898911, 0, 64 << 10, 32, 0) },
  88. { INFO("320s33b", 0x898912, 0, 64 << 10, 64, 0) },
  89. { INFO("640s33b", 0x898913, 0, 64 << 10, 128, 0) },
  90. /* Macronix */
  91. { INFO("mx25l4005a", 0xc22013, 0, 64 << 10, 8, ER_4K) },
  92. { INFO("mx25l8005", 0xc22014, 0, 64 << 10, 16, 0) },
  93. { INFO("mx25l1606e", 0xc22015, 0, 64 << 10, 32, ER_4K) },
  94. { INFO("mx25l3205d", 0xc22016, 0, 64 << 10, 64, 0) },
  95. { INFO("mx25l6405d", 0xc22017, 0, 64 << 10, 128, 0) },
  96. { INFO("mx25l12805d", 0xc22018, 0, 64 << 10, 256, 0) },
  97. { INFO("mx25l12855e", 0xc22618, 0, 64 << 10, 256, 0) },
  98. { INFO("mx25l25635e", 0xc22019, 0, 64 << 10, 512, 0) },
  99. { INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) },
  100. /* Spansion -- single (large) sector size only, at least
  101. * for the chips listed here (without boot sectors).
  102. */
  103. { INFO("s25sl004a", 0x010212, 0, 64 << 10, 8, 0) },
  104. { INFO("s25sl008a", 0x010213, 0, 64 << 10, 16, 0) },
  105. { INFO("s25sl016a", 0x010214, 0, 64 << 10, 32, 0) },
  106. { INFO("s25sl032a", 0x010215, 0, 64 << 10, 64, 0) },
  107. { INFO("s25sl032p", 0x010215, 0x4d00, 64 << 10, 64, ER_4K) },
  108. { INFO("s25sl064a", 0x010216, 0, 64 << 10, 128, 0) },
  109. { INFO("s25fl256s0", 0x010219, 0x4d00, 256 << 10, 128, 0) },
  110. { INFO("s25fl256s1", 0x010219, 0x4d01, 64 << 10, 512, 0) },
  111. { INFO("s25fl512s", 0x010220, 0x4d00, 256 << 10, 256, 0) },
  112. { INFO("s70fl01gs", 0x010221, 0x4d00, 256 << 10, 256, 0) },
  113. { INFO("s25sl12800", 0x012018, 0x0300, 256 << 10, 64, 0) },
  114. { INFO("s25sl12801", 0x012018, 0x0301, 64 << 10, 256, 0) },
  115. { INFO("s25fl129p0", 0x012018, 0x4d00, 256 << 10, 64, 0) },
  116. { INFO("s25fl129p1", 0x012018, 0x4d01, 64 << 10, 256, 0) },
  117. { INFO("s25fl016k", 0xef4015, 0, 64 << 10, 32, ER_4K | ER_32K) },
  118. { INFO("s25fl064k", 0xef4017, 0, 64 << 10, 128, ER_4K | ER_32K) },
  119. /* SST -- large erase sizes are "overlays", "sectors" are 4<< 10 */
  120. { INFO("sst25vf040b", 0xbf258d, 0, 64 << 10, 8, ER_4K) },
  121. { INFO("sst25vf080b", 0xbf258e, 0, 64 << 10, 16, ER_4K) },
  122. { INFO("sst25vf016b", 0xbf2541, 0, 64 << 10, 32, ER_4K) },
  123. { INFO("sst25vf032b", 0xbf254a, 0, 64 << 10, 64, ER_4K) },
  124. { INFO("sst25wf512", 0xbf2501, 0, 64 << 10, 1, ER_4K) },
  125. { INFO("sst25wf010", 0xbf2502, 0, 64 << 10, 2, ER_4K) },
  126. { INFO("sst25wf020", 0xbf2503, 0, 64 << 10, 4, ER_4K) },
  127. { INFO("sst25wf040", 0xbf2504, 0, 64 << 10, 8, ER_4K) },
  128. /* ST Microelectronics -- newer production may have feature updates */
  129. { INFO("m25p05", 0x202010, 0, 32 << 10, 2, 0) },
  130. { INFO("m25p10", 0x202011, 0, 32 << 10, 4, 0) },
  131. { INFO("m25p20", 0x202012, 0, 64 << 10, 4, 0) },
  132. { INFO("m25p40", 0x202013, 0, 64 << 10, 8, 0) },
  133. { INFO("m25p80", 0x202014, 0, 64 << 10, 16, 0) },
  134. { INFO("m25p16", 0x202015, 0, 64 << 10, 32, 0) },
  135. { INFO("m25p32", 0x202016, 0, 64 << 10, 64, 0) },
  136. { INFO("m25p64", 0x202017, 0, 64 << 10, 128, 0) },
  137. { INFO("m25p128", 0x202018, 0, 256 << 10, 64, 0) },
  138. { INFO("m45pe10", 0x204011, 0, 64 << 10, 2, 0) },
  139. { INFO("m45pe80", 0x204014, 0, 64 << 10, 16, 0) },
  140. { INFO("m45pe16", 0x204015, 0, 64 << 10, 32, 0) },
  141. { INFO("m25pe80", 0x208014, 0, 64 << 10, 16, 0) },
  142. { INFO("m25pe16", 0x208015, 0, 64 << 10, 32, ER_4K) },
  143. { INFO("m25px32", 0x207116, 0, 64 << 10, 64, ER_4K) },
  144. { INFO("m25px32-s0", 0x207316, 0, 64 << 10, 64, ER_4K) },
  145. { INFO("m25px32-s1", 0x206316, 0, 64 << 10, 64, ER_4K) },
  146. { INFO("m25px64", 0x207117, 0, 64 << 10, 128, 0) },
  147. /* Winbond -- w25x "blocks" are 64k, "sectors" are 4KiB */
  148. { INFO("w25x10", 0xef3011, 0, 64 << 10, 2, ER_4K) },
  149. { INFO("w25x20", 0xef3012, 0, 64 << 10, 4, ER_4K) },
  150. { INFO("w25x40", 0xef3013, 0, 64 << 10, 8, ER_4K) },
  151. { INFO("w25x80", 0xef3014, 0, 64 << 10, 16, ER_4K) },
  152. { INFO("w25x16", 0xef3015, 0, 64 << 10, 32, ER_4K) },
  153. { INFO("w25x32", 0xef3016, 0, 64 << 10, 64, ER_4K) },
  154. { INFO("w25q32", 0xef4016, 0, 64 << 10, 64, ER_4K) },
  155. { INFO("w25x64", 0xef3017, 0, 64 << 10, 128, ER_4K) },
  156. { INFO("w25q64", 0xef4017, 0, 64 << 10, 128, ER_4K) },
  157. /* Numonyx -- n25q128 */
  158. { INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) },
  159. { },
  160. };
  161. typedef enum {
  162. NOP = 0,
  163. WRSR = 0x1,
  164. WRDI = 0x4,
  165. RDSR = 0x5,
  166. WREN = 0x6,
  167. JEDEC_READ = 0x9f,
  168. BULK_ERASE = 0xc7,
  169. READ = 0x3,
  170. FAST_READ = 0xb,
  171. DOR = 0x3b,
  172. QOR = 0x6b,
  173. DIOR = 0xbb,
  174. QIOR = 0xeb,
  175. PP = 0x2,
  176. DPP = 0xa2,
  177. QPP = 0x32,
  178. ERASE_4K = 0x20,
  179. ERASE_32K = 0x52,
  180. ERASE_SECTOR = 0xd8,
  181. } FlashCMD;
  182. typedef enum {
  183. STATE_IDLE,
  184. STATE_PAGE_PROGRAM,
  185. STATE_READ,
  186. STATE_COLLECTING_DATA,
  187. STATE_READING_DATA,
  188. } CMDState;
  189. typedef struct Flash {
  190. SSISlave ssidev;
  191. uint32_t r;
  192. BlockDriverState *bdrv;
  193. uint8_t *storage;
  194. uint32_t size;
  195. int page_size;
  196. uint8_t state;
  197. uint8_t data[16];
  198. uint32_t len;
  199. uint32_t pos;
  200. uint8_t needed_bytes;
  201. uint8_t cmd_in_progress;
  202. uint64_t cur_addr;
  203. bool write_enable;
  204. int64_t dirty_page;
  205. char *part_name;
  206. const FlashPartInfo *pi;
  207. } Flash;
  208. static void bdrv_sync_complete(void *opaque, int ret)
  209. {
  210. /* do nothing. Masters do not directly interact with the backing store,
  211. * only the working copy so no mutexing required.
  212. */
  213. }
  214. static void flash_sync_page(Flash *s, int page)
  215. {
  216. if (s->bdrv) {
  217. int bdrv_sector, nb_sectors;
  218. QEMUIOVector iov;
  219. bdrv_sector = (page * s->pi->page_size) / BDRV_SECTOR_SIZE;
  220. nb_sectors = DIV_ROUND_UP(s->pi->page_size, BDRV_SECTOR_SIZE);
  221. qemu_iovec_init(&iov, 1);
  222. qemu_iovec_add(&iov, s->storage + bdrv_sector * BDRV_SECTOR_SIZE,
  223. nb_sectors * BDRV_SECTOR_SIZE);
  224. bdrv_aio_writev(s->bdrv, bdrv_sector, &iov, nb_sectors,
  225. bdrv_sync_complete, NULL);
  226. }
  227. }
  228. static inline void flash_sync_area(Flash *s, int64_t off, int64_t len)
  229. {
  230. int64_t start, end, nb_sectors;
  231. QEMUIOVector iov;
  232. if (!s->bdrv) {
  233. return;
  234. }
  235. assert(!(len % BDRV_SECTOR_SIZE));
  236. start = off / BDRV_SECTOR_SIZE;
  237. end = (off + len) / BDRV_SECTOR_SIZE;
  238. nb_sectors = end - start;
  239. qemu_iovec_init(&iov, 1);
  240. qemu_iovec_add(&iov, s->storage + (start * BDRV_SECTOR_SIZE),
  241. nb_sectors * BDRV_SECTOR_SIZE);
  242. bdrv_aio_writev(s->bdrv, start, &iov, nb_sectors, bdrv_sync_complete, NULL);
  243. }
  244. static void flash_erase(Flash *s, int offset, FlashCMD cmd)
  245. {
  246. uint32_t len;
  247. uint8_t capa_to_assert = 0;
  248. switch (cmd) {
  249. case ERASE_4K:
  250. len = 4 << 10;
  251. capa_to_assert = ER_4K;
  252. break;
  253. case ERASE_32K:
  254. len = 32 << 10;
  255. capa_to_assert = ER_32K;
  256. break;
  257. case ERASE_SECTOR:
  258. len = s->pi->sector_size;
  259. break;
  260. case BULK_ERASE:
  261. len = s->size;
  262. break;
  263. default:
  264. abort();
  265. }
  266. DB_PRINT("offset = %#x, len = %d\n", offset, len);
  267. if ((s->pi->flags & capa_to_assert) != capa_to_assert) {
  268. hw_error("m25p80: %dk erase size not supported by device\n", len);
  269. }
  270. if (!s->write_enable) {
  271. DB_PRINT("erase with write protect!\n");
  272. return;
  273. }
  274. memset(s->storage + offset, 0xff, len);
  275. flash_sync_area(s, offset, len);
  276. }
  277. static inline void flash_sync_dirty(Flash *s, int64_t newpage)
  278. {
  279. if (s->dirty_page >= 0 && s->dirty_page != newpage) {
  280. flash_sync_page(s, s->dirty_page);
  281. s->dirty_page = newpage;
  282. }
  283. }
  284. static inline
  285. void flash_write8(Flash *s, uint64_t addr, uint8_t data)
  286. {
  287. int64_t page = addr / s->pi->page_size;
  288. uint8_t prev = s->storage[s->cur_addr];
  289. if (!s->write_enable) {
  290. DB_PRINT("write with write protect!\n");
  291. }
  292. if ((prev ^ data) & data) {
  293. DB_PRINT("programming zero to one! addr=%lx %x -> %x\n",
  294. addr, prev, data);
  295. }
  296. if (s->pi->flags & WR_1) {
  297. s->storage[s->cur_addr] = data;
  298. } else {
  299. s->storage[s->cur_addr] &= data;
  300. }
  301. flash_sync_dirty(s, page);
  302. s->dirty_page = page;
  303. }
  304. static void complete_collecting_data(Flash *s)
  305. {
  306. s->cur_addr = s->data[0] << 16;
  307. s->cur_addr |= s->data[1] << 8;
  308. s->cur_addr |= s->data[2];
  309. s->state = STATE_IDLE;
  310. switch (s->cmd_in_progress) {
  311. case DPP:
  312. case QPP:
  313. case PP:
  314. s->state = STATE_PAGE_PROGRAM;
  315. break;
  316. case READ:
  317. case FAST_READ:
  318. case DOR:
  319. case QOR:
  320. case DIOR:
  321. case QIOR:
  322. s->state = STATE_READ;
  323. break;
  324. case ERASE_4K:
  325. case ERASE_32K:
  326. case ERASE_SECTOR:
  327. flash_erase(s, s->cur_addr, s->cmd_in_progress);
  328. break;
  329. case WRSR:
  330. if (s->write_enable) {
  331. s->write_enable = false;
  332. }
  333. break;
  334. default:
  335. break;
  336. }
  337. }
  338. static void decode_new_cmd(Flash *s, uint32_t value)
  339. {
  340. s->cmd_in_progress = value;
  341. DB_PRINT("decoded new command:%x\n", value);
  342. switch (value) {
  343. case ERASE_4K:
  344. case ERASE_32K:
  345. case ERASE_SECTOR:
  346. case READ:
  347. case DPP:
  348. case QPP:
  349. case PP:
  350. s->needed_bytes = 3;
  351. s->pos = 0;
  352. s->len = 0;
  353. s->state = STATE_COLLECTING_DATA;
  354. break;
  355. case FAST_READ:
  356. case DOR:
  357. case QOR:
  358. s->needed_bytes = 4;
  359. s->pos = 0;
  360. s->len = 0;
  361. s->state = STATE_COLLECTING_DATA;
  362. break;
  363. case DIOR:
  364. switch ((s->pi->jedec >> 16) & 0xFF) {
  365. case JEDEC_WINBOND:
  366. case JEDEC_SPANSION:
  367. s->needed_bytes = 4;
  368. break;
  369. case JEDEC_NUMONYX:
  370. default:
  371. s->needed_bytes = 5;
  372. }
  373. s->pos = 0;
  374. s->len = 0;
  375. s->state = STATE_COLLECTING_DATA;
  376. break;
  377. case QIOR:
  378. switch ((s->pi->jedec >> 16) & 0xFF) {
  379. case JEDEC_WINBOND:
  380. case JEDEC_SPANSION:
  381. s->needed_bytes = 6;
  382. break;
  383. case JEDEC_NUMONYX:
  384. default:
  385. s->needed_bytes = 8;
  386. }
  387. s->pos = 0;
  388. s->len = 0;
  389. s->state = STATE_COLLECTING_DATA;
  390. break;
  391. case WRSR:
  392. if (s->write_enable) {
  393. s->needed_bytes = 1;
  394. s->pos = 0;
  395. s->len = 0;
  396. s->state = STATE_COLLECTING_DATA;
  397. }
  398. break;
  399. case WRDI:
  400. s->write_enable = false;
  401. break;
  402. case WREN:
  403. s->write_enable = true;
  404. break;
  405. case RDSR:
  406. s->data[0] = (!!s->write_enable) << 1;
  407. s->pos = 0;
  408. s->len = 1;
  409. s->state = STATE_READING_DATA;
  410. break;
  411. case JEDEC_READ:
  412. DB_PRINT("populated jedec code\n");
  413. s->data[0] = (s->pi->jedec >> 16) & 0xff;
  414. s->data[1] = (s->pi->jedec >> 8) & 0xff;
  415. s->data[2] = s->pi->jedec & 0xff;
  416. if (s->pi->ext_jedec) {
  417. s->data[3] = (s->pi->ext_jedec >> 8) & 0xff;
  418. s->data[4] = s->pi->ext_jedec & 0xff;
  419. s->len = 5;
  420. } else {
  421. s->len = 3;
  422. }
  423. s->pos = 0;
  424. s->state = STATE_READING_DATA;
  425. break;
  426. case BULK_ERASE:
  427. if (s->write_enable) {
  428. DB_PRINT("chip erase\n");
  429. flash_erase(s, 0, BULK_ERASE);
  430. } else {
  431. DB_PRINT("chip erase with write protect!\n");
  432. }
  433. break;
  434. case NOP:
  435. break;
  436. default:
  437. DB_PRINT("Unknown cmd %x\n", value);
  438. break;
  439. }
  440. }
  441. static int m25p80_cs(SSISlave *ss, bool select)
  442. {
  443. Flash *s = FROM_SSI_SLAVE(Flash, ss);
  444. if (select) {
  445. s->len = 0;
  446. s->pos = 0;
  447. s->state = STATE_IDLE;
  448. flash_sync_dirty(s, -1);
  449. }
  450. DB_PRINT("%sselect\n", select ? "de" : "");
  451. return 0;
  452. }
  453. static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx)
  454. {
  455. Flash *s = FROM_SSI_SLAVE(Flash, ss);
  456. uint32_t r = 0;
  457. switch (s->state) {
  458. case STATE_PAGE_PROGRAM:
  459. DB_PRINT("page program cur_addr=%lx data=%x\n", s->cur_addr,
  460. (uint8_t)tx);
  461. flash_write8(s, s->cur_addr, (uint8_t)tx);
  462. s->cur_addr++;
  463. break;
  464. case STATE_READ:
  465. r = s->storage[s->cur_addr];
  466. DB_PRINT("READ 0x%lx=%x\n", s->cur_addr, r);
  467. s->cur_addr = (s->cur_addr + 1) % s->size;
  468. break;
  469. case STATE_COLLECTING_DATA:
  470. s->data[s->len] = (uint8_t)tx;
  471. s->len++;
  472. if (s->len == s->needed_bytes) {
  473. complete_collecting_data(s);
  474. }
  475. break;
  476. case STATE_READING_DATA:
  477. r = s->data[s->pos];
  478. s->pos++;
  479. if (s->pos == s->len) {
  480. s->pos = 0;
  481. s->state = STATE_IDLE;
  482. }
  483. break;
  484. default:
  485. case STATE_IDLE:
  486. decode_new_cmd(s, (uint8_t)tx);
  487. break;
  488. }
  489. return r;
  490. }
  491. static int m25p80_init(SSISlave *ss)
  492. {
  493. DriveInfo *dinfo;
  494. Flash *s = FROM_SSI_SLAVE(Flash, ss);
  495. const FlashPartInfo *i;
  496. if (!s->part_name) { /* default to actual m25p80 if no partname given */
  497. s->part_name = (char *)"m25p80";
  498. }
  499. i = known_devices;
  500. for (i = known_devices;; i++) {
  501. assert(i);
  502. if (!i->part_name) {
  503. fprintf(stderr, "Unknown SPI flash part: \"%s\"\n", s->part_name);
  504. return 1;
  505. } else if (!strcmp(i->part_name, s->part_name)) {
  506. s->pi = i;
  507. break;
  508. }
  509. }
  510. s->size = s->pi->sector_size * s->pi->n_sectors;
  511. s->dirty_page = -1;
  512. s->storage = qemu_blockalign(s->bdrv, s->size);
  513. dinfo = drive_get_next(IF_MTD);
  514. if (dinfo && dinfo->bdrv) {
  515. DB_PRINT("Binding to IF_MTD drive\n");
  516. s->bdrv = dinfo->bdrv;
  517. /* FIXME: Move to late init */
  518. if (bdrv_read(s->bdrv, 0, s->storage, DIV_ROUND_UP(s->size,
  519. BDRV_SECTOR_SIZE))) {
  520. fprintf(stderr, "Failed to initialize SPI flash!\n");
  521. return 1;
  522. }
  523. } else {
  524. memset(s->storage, 0xFF, s->size);
  525. }
  526. return 0;
  527. }
  528. static void m25p80_pre_save(void *opaque)
  529. {
  530. flash_sync_dirty((Flash *)opaque, -1);
  531. }
  532. static const VMStateDescription vmstate_m25p80 = {
  533. .name = "xilinx_spi",
  534. .version_id = 1,
  535. .minimum_version_id = 1,
  536. .minimum_version_id_old = 1,
  537. .pre_save = m25p80_pre_save,
  538. .fields = (VMStateField[]) {
  539. VMSTATE_UINT8(state, Flash),
  540. VMSTATE_UINT8_ARRAY(data, Flash, 16),
  541. VMSTATE_UINT32(len, Flash),
  542. VMSTATE_UINT32(pos, Flash),
  543. VMSTATE_UINT8(needed_bytes, Flash),
  544. VMSTATE_UINT8(cmd_in_progress, Flash),
  545. VMSTATE_UINT64(cur_addr, Flash),
  546. VMSTATE_BOOL(write_enable, Flash),
  547. VMSTATE_END_OF_LIST()
  548. }
  549. };
  550. static Property m25p80_properties[] = {
  551. DEFINE_PROP_STRING("partname", Flash, part_name),
  552. DEFINE_PROP_END_OF_LIST(),
  553. };
  554. static void m25p80_class_init(ObjectClass *klass, void *data)
  555. {
  556. DeviceClass *dc = DEVICE_CLASS(klass);
  557. SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
  558. k->init = m25p80_init;
  559. k->transfer = m25p80_transfer8;
  560. k->set_cs = m25p80_cs;
  561. k->cs_polarity = SSI_CS_LOW;
  562. dc->props = m25p80_properties;
  563. dc->vmsd = &vmstate_m25p80;
  564. }
  565. static const TypeInfo m25p80_info = {
  566. .name = "m25p80",
  567. .parent = TYPE_SSI_SLAVE,
  568. .instance_size = sizeof(Flash),
  569. .class_init = m25p80_class_init,
  570. };
  571. static void m25p80_register_types(void)
  572. {
  573. type_register_static(&m25p80_info);
  574. }
  575. type_init(m25p80_register_types)