]> git.proxmox.com Git - mirror_qemu.git/blob - hw/pflash_cfi02.c
Allow a custom unlock address in CFI02 flash (Jan Kiszka).
[mirror_qemu.git] / hw / pflash_cfi02.c
1 /*
2 * CFI parallel flash with AMD command set emulation
3 *
4 * Copyright (c) 2005 Jocelyn Mayer
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * For now, this code can emulate flashes of 1, 2 or 4 bytes width.
23 * Supported commands/modes are:
24 * - flash read
25 * - flash write
26 * - flash ID read
27 * - sector erase
28 * - chip erase
29 * - unlock bypass command
30 * - CFI queries
31 *
32 * It does not support flash interleaving.
33 * It does not implement boot blocs with reduced size
34 * It does not implement software data protection as found in many real chips
35 * It does not implement erase suspend/resume commands
36 * It does not implement multiple sectors erase
37 */
38
39 #include "hw.h"
40 #include "flash.h"
41 #include "qemu-timer.h"
42 #include "block.h"
43
44 //#define PFLASH_DEBUG
45 #ifdef PFLASH_DEBUG
46 #define DPRINTF(fmt, args...) \
47 do { \
48 printf("PFLASH: " fmt , ##args); \
49 } while (0)
50 #else
51 #define DPRINTF(fmt, args...) do { } while (0)
52 #endif
53
54 struct pflash_t {
55 BlockDriverState *bs;
56 target_phys_addr_t base;
57 uint32_t sector_len;
58 uint32_t total_len;
59 int width;
60 int wcycle; /* if 0, the flash is read normally */
61 int bypass;
62 int ro;
63 uint8_t cmd;
64 uint8_t status;
65 uint16_t ident[4];
66 uint16_t unlock_addr[2];
67 uint8_t cfi_len;
68 uint8_t cfi_table[0x52];
69 QEMUTimer *timer;
70 ram_addr_t off;
71 int fl_mem;
72 void *storage;
73 };
74
75 static void pflash_timer (void *opaque)
76 {
77 pflash_t *pfl = opaque;
78
79 DPRINTF("%s: command %02x done\n", __func__, pfl->cmd);
80 /* Reset flash */
81 pfl->status ^= 0x80;
82 if (pfl->bypass) {
83 pfl->wcycle = 2;
84 } else {
85 cpu_register_physical_memory(pfl->base, pfl->total_len,
86 pfl->off | IO_MEM_ROMD | pfl->fl_mem);
87 pfl->wcycle = 0;
88 }
89 pfl->cmd = 0;
90 }
91
92 static uint32_t pflash_read (pflash_t *pfl, uint32_t offset, int width)
93 {
94 uint32_t boff;
95 uint32_t ret;
96 uint8_t *p;
97
98 DPRINTF("%s: offset " TARGET_FMT_lx "\n", __func__, offset);
99 ret = -1;
100 offset -= pfl->base;
101 boff = offset & 0xFF;
102 if (pfl->width == 2)
103 boff = boff >> 1;
104 else if (pfl->width == 4)
105 boff = boff >> 2;
106 switch (pfl->cmd) {
107 default:
108 /* This should never happen : reset state & treat it as a read*/
109 DPRINTF("%s: unknown command state: %x\n", __func__, pfl->cmd);
110 pfl->wcycle = 0;
111 pfl->cmd = 0;
112 case 0x80:
113 /* We accept reads during second unlock sequence... */
114 case 0x00:
115 flash_read:
116 /* Flash area read */
117 p = pfl->storage;
118 switch (width) {
119 case 1:
120 ret = p[offset];
121 // DPRINTF("%s: data offset %08x %02x\n", __func__, offset, ret);
122 break;
123 case 2:
124 #if defined(TARGET_WORDS_BIGENDIAN)
125 ret = p[offset] << 8;
126 ret |= p[offset + 1];
127 #else
128 ret = p[offset];
129 ret |= p[offset + 1] << 8;
130 #endif
131 // DPRINTF("%s: data offset %08x %04x\n", __func__, offset, ret);
132 break;
133 case 4:
134 #if defined(TARGET_WORDS_BIGENDIAN)
135 ret = p[offset] << 24;
136 ret |= p[offset + 1] << 16;
137 ret |= p[offset + 2] << 8;
138 ret |= p[offset + 3];
139 #else
140 ret = p[offset];
141 ret |= p[offset + 1] << 8;
142 ret |= p[offset + 2] << 16;
143 ret |= p[offset + 3] << 24;
144 #endif
145 // DPRINTF("%s: data offset %08x %08x\n", __func__, offset, ret);
146 break;
147 }
148 break;
149 case 0x90:
150 /* flash ID read */
151 switch (boff) {
152 case 0x00:
153 case 0x01:
154 ret = pfl->ident[boff & 0x01];
155 break;
156 case 0x02:
157 ret = 0x00; /* Pretend all sectors are unprotected */
158 break;
159 case 0x0E:
160 case 0x0F:
161 if (pfl->ident[2 + (boff & 0x01)] == (uint8_t)-1)
162 goto flash_read;
163 ret = pfl->ident[2 + (boff & 0x01)];
164 break;
165 default:
166 goto flash_read;
167 }
168 DPRINTF("%s: ID " TARGET_FMT_ld " %x\n", __func__, boff, ret);
169 break;
170 case 0xA0:
171 case 0x10:
172 case 0x30:
173 /* Status register read */
174 ret = pfl->status;
175 DPRINTF("%s: status %x\n", __func__, ret);
176 /* Toggle bit 6 */
177 pfl->status ^= 0x40;
178 break;
179 case 0x98:
180 /* CFI query mode */
181 if (boff > pfl->cfi_len)
182 ret = 0;
183 else
184 ret = pfl->cfi_table[boff];
185 break;
186 }
187
188 return ret;
189 }
190
191 /* update flash content on disk */
192 static void pflash_update(pflash_t *pfl, int offset,
193 int size)
194 {
195 int offset_end;
196 if (pfl->bs) {
197 offset_end = offset + size;
198 /* round to sectors */
199 offset = offset >> 9;
200 offset_end = (offset_end + 511) >> 9;
201 bdrv_write(pfl->bs, offset, pfl->storage + (offset << 9),
202 offset_end - offset);
203 }
204 }
205
206 static void pflash_write (pflash_t *pfl, uint32_t offset, uint32_t value,
207 int width)
208 {
209 uint32_t boff;
210 uint8_t *p;
211 uint8_t cmd;
212
213 /* WARNING: when the memory area is in ROMD mode, the offset is a
214 ram offset, not a physical address */
215 cmd = value;
216 if (pfl->cmd != 0xA0 && cmd == 0xF0) {
217 #if 0
218 DPRINTF("%s: flash reset asked (%02x %02x)\n",
219 __func__, pfl->cmd, cmd);
220 #endif
221 goto reset_flash;
222 }
223 DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d %d\n", __func__,
224 offset, value, width, pfl->wcycle);
225 if (pfl->wcycle == 0)
226 offset -= (uint32_t)(long)pfl->storage;
227 else
228 offset -= pfl->base;
229
230 DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d\n", __func__,
231 offset, value, width);
232 /* Set the device in I/O access mode */
233 cpu_register_physical_memory(pfl->base, pfl->total_len, pfl->fl_mem);
234 boff = offset & (pfl->sector_len - 1);
235 if (pfl->width == 2)
236 boff = boff >> 1;
237 else if (pfl->width == 4)
238 boff = boff >> 2;
239 switch (pfl->wcycle) {
240 case 0:
241 /* We're in read mode */
242 check_unlock0:
243 if (boff == 0x55 && cmd == 0x98) {
244 enter_CFI_mode:
245 /* Enter CFI query mode */
246 pfl->wcycle = 7;
247 pfl->cmd = 0x98;
248 return;
249 }
250 if (boff != pfl->unlock_addr[0] || cmd != 0xAA) {
251 DPRINTF("%s: unlock0 failed " TARGET_FMT_lx " %02x %04x\n",
252 __func__, boff, cmd, pfl->unlock_addr[0]);
253 goto reset_flash;
254 }
255 DPRINTF("%s: unlock sequence started\n", __func__);
256 break;
257 case 1:
258 /* We started an unlock sequence */
259 check_unlock1:
260 if (boff != pfl->unlock_addr[1] || cmd != 0x55) {
261 DPRINTF("%s: unlock1 failed " TARGET_FMT_lx " %02x\n", __func__,
262 boff, cmd);
263 goto reset_flash;
264 }
265 DPRINTF("%s: unlock sequence done\n", __func__);
266 break;
267 case 2:
268 /* We finished an unlock sequence */
269 if (!pfl->bypass && boff != pfl->unlock_addr[0]) {
270 DPRINTF("%s: command failed " TARGET_FMT_lx " %02x\n", __func__,
271 boff, cmd);
272 goto reset_flash;
273 }
274 switch (cmd) {
275 case 0x20:
276 pfl->bypass = 1;
277 goto do_bypass;
278 case 0x80:
279 case 0x90:
280 case 0xA0:
281 pfl->cmd = cmd;
282 DPRINTF("%s: starting command %02x\n", __func__, cmd);
283 break;
284 default:
285 DPRINTF("%s: unknown command %02x\n", __func__, cmd);
286 goto reset_flash;
287 }
288 break;
289 case 3:
290 switch (pfl->cmd) {
291 case 0x80:
292 /* We need another unlock sequence */
293 goto check_unlock0;
294 case 0xA0:
295 DPRINTF("%s: write data offset " TARGET_FMT_lx " %08x %d\n",
296 __func__, offset, value, width);
297 p = pfl->storage;
298 switch (width) {
299 case 1:
300 p[offset] &= value;
301 pflash_update(pfl, offset, 1);
302 break;
303 case 2:
304 #if defined(TARGET_WORDS_BIGENDIAN)
305 p[offset] &= value >> 8;
306 p[offset + 1] &= value;
307 #else
308 p[offset] &= value;
309 p[offset + 1] &= value >> 8;
310 #endif
311 pflash_update(pfl, offset, 2);
312 break;
313 case 4:
314 #if defined(TARGET_WORDS_BIGENDIAN)
315 p[offset] &= value >> 24;
316 p[offset + 1] &= value >> 16;
317 p[offset + 2] &= value >> 8;
318 p[offset + 3] &= value;
319 #else
320 p[offset] &= value;
321 p[offset + 1] &= value >> 8;
322 p[offset + 2] &= value >> 16;
323 p[offset + 3] &= value >> 24;
324 #endif
325 pflash_update(pfl, offset, 4);
326 break;
327 }
328 pfl->status = 0x00 | ~(value & 0x80);
329 /* Let's pretend write is immediate */
330 if (pfl->bypass)
331 goto do_bypass;
332 goto reset_flash;
333 case 0x90:
334 if (pfl->bypass && cmd == 0x00) {
335 /* Unlock bypass reset */
336 goto reset_flash;
337 }
338 /* We can enter CFI query mode from autoselect mode */
339 if (boff == 0x55 && cmd == 0x98)
340 goto enter_CFI_mode;
341 /* No break here */
342 default:
343 DPRINTF("%s: invalid write for command %02x\n",
344 __func__, pfl->cmd);
345 goto reset_flash;
346 }
347 case 4:
348 switch (pfl->cmd) {
349 case 0xA0:
350 /* Ignore writes while flash data write is occuring */
351 /* As we suppose write is immediate, this should never happen */
352 return;
353 case 0x80:
354 goto check_unlock1;
355 default:
356 /* Should never happen */
357 DPRINTF("%s: invalid command state %02x (wc 4)\n",
358 __func__, pfl->cmd);
359 goto reset_flash;
360 }
361 break;
362 case 5:
363 switch (cmd) {
364 case 0x10:
365 if (boff != pfl->unlock_addr[0]) {
366 DPRINTF("%s: chip erase: invalid address " TARGET_FMT_lx "\n",
367 __func__, offset);
368 goto reset_flash;
369 }
370 /* Chip erase */
371 DPRINTF("%s: start chip erase\n", __func__);
372 memset(pfl->storage, 0xFF, pfl->total_len);
373 pfl->status = 0x00;
374 pflash_update(pfl, 0, pfl->total_len);
375 /* Let's wait 5 seconds before chip erase is done */
376 qemu_mod_timer(pfl->timer,
377 qemu_get_clock(vm_clock) + (ticks_per_sec * 5));
378 break;
379 case 0x30:
380 /* Sector erase */
381 p = pfl->storage;
382 offset &= ~(pfl->sector_len - 1);
383 DPRINTF("%s: start sector erase at " TARGET_FMT_lx "\n", __func__,
384 offset);
385 memset(p + offset, 0xFF, pfl->sector_len);
386 pflash_update(pfl, offset, pfl->sector_len);
387 pfl->status = 0x00;
388 /* Let's wait 1/2 second before sector erase is done */
389 qemu_mod_timer(pfl->timer,
390 qemu_get_clock(vm_clock) + (ticks_per_sec / 2));
391 break;
392 default:
393 DPRINTF("%s: invalid command %02x (wc 5)\n", __func__, cmd);
394 goto reset_flash;
395 }
396 pfl->cmd = cmd;
397 break;
398 case 6:
399 switch (pfl->cmd) {
400 case 0x10:
401 /* Ignore writes during chip erase */
402 return;
403 case 0x30:
404 /* Ignore writes during sector erase */
405 return;
406 default:
407 /* Should never happen */
408 DPRINTF("%s: invalid command state %02x (wc 6)\n",
409 __func__, pfl->cmd);
410 goto reset_flash;
411 }
412 break;
413 case 7: /* Special value for CFI queries */
414 DPRINTF("%s: invalid write in CFI query mode\n", __func__);
415 goto reset_flash;
416 default:
417 /* Should never happen */
418 DPRINTF("%s: invalid write state (wc 7)\n", __func__);
419 goto reset_flash;
420 }
421 pfl->wcycle++;
422
423 return;
424
425 /* Reset flash */
426 reset_flash:
427 cpu_register_physical_memory(pfl->base, pfl->total_len,
428 pfl->off | IO_MEM_ROMD | pfl->fl_mem);
429 pfl->bypass = 0;
430 pfl->wcycle = 0;
431 pfl->cmd = 0;
432 return;
433
434 do_bypass:
435 pfl->wcycle = 2;
436 pfl->cmd = 0;
437 return;
438 }
439
440
441 static uint32_t pflash_readb (void *opaque, target_phys_addr_t addr)
442 {
443 return pflash_read(opaque, addr, 1);
444 }
445
446 static uint32_t pflash_readw (void *opaque, target_phys_addr_t addr)
447 {
448 pflash_t *pfl = opaque;
449
450 return pflash_read(pfl, addr, 2);
451 }
452
453 static uint32_t pflash_readl (void *opaque, target_phys_addr_t addr)
454 {
455 pflash_t *pfl = opaque;
456
457 return pflash_read(pfl, addr, 4);
458 }
459
460 static void pflash_writeb (void *opaque, target_phys_addr_t addr,
461 uint32_t value)
462 {
463 pflash_write(opaque, addr, value, 1);
464 }
465
466 static void pflash_writew (void *opaque, target_phys_addr_t addr,
467 uint32_t value)
468 {
469 pflash_t *pfl = opaque;
470
471 pflash_write(pfl, addr, value, 2);
472 }
473
474 static void pflash_writel (void *opaque, target_phys_addr_t addr,
475 uint32_t value)
476 {
477 pflash_t *pfl = opaque;
478
479 pflash_write(pfl, addr, value, 4);
480 }
481
482 static CPUWriteMemoryFunc *pflash_write_ops[] = {
483 &pflash_writeb,
484 &pflash_writew,
485 &pflash_writel,
486 };
487
488 static CPUReadMemoryFunc *pflash_read_ops[] = {
489 &pflash_readb,
490 &pflash_readw,
491 &pflash_readl,
492 };
493
494 /* Count trailing zeroes of a 32 bits quantity */
495 static int ctz32 (uint32_t n)
496 {
497 int ret;
498
499 ret = 0;
500 if (!(n & 0xFFFF)) {
501 ret += 16;
502 n = n >> 16;
503 }
504 if (!(n & 0xFF)) {
505 ret += 8;
506 n = n >> 8;
507 }
508 if (!(n & 0xF)) {
509 ret += 4;
510 n = n >> 4;
511 }
512 if (!(n & 0x3)) {
513 ret += 2;
514 n = n >> 2;
515 }
516 if (!(n & 0x1)) {
517 ret++;
518 n = n >> 1;
519 }
520 #if 0 /* This is not necessary as n is never 0 */
521 if (!n)
522 ret++;
523 #endif
524
525 return ret;
526 }
527
528 pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off,
529 BlockDriverState *bs, uint32_t sector_len,
530 int nb_blocs, int width,
531 uint16_t id0, uint16_t id1,
532 uint16_t id2, uint16_t id3,
533 uint16_t unlock_addr0, uint16_t unlock_addr1)
534 {
535 pflash_t *pfl;
536 int32_t total_len;
537
538 total_len = sector_len * nb_blocs;
539 /* XXX: to be fixed */
540 #if 0
541 if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) &&
542 total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024))
543 return NULL;
544 #endif
545 pfl = qemu_mallocz(sizeof(pflash_t));
546 if (pfl == NULL)
547 return NULL;
548 pfl->storage = phys_ram_base + off;
549 pfl->fl_mem = cpu_register_io_memory(0, pflash_read_ops, pflash_write_ops,
550 pfl);
551 pfl->off = off;
552 cpu_register_physical_memory(base, total_len,
553 off | pfl->fl_mem | IO_MEM_ROMD);
554 pfl->bs = bs;
555 if (pfl->bs) {
556 /* read the initial flash content */
557 bdrv_read(pfl->bs, 0, pfl->storage, total_len >> 9);
558 }
559 #if 0 /* XXX: there should be a bit to set up read-only,
560 * the same way the hardware does (with WP pin).
561 */
562 pfl->ro = 1;
563 #else
564 pfl->ro = 0;
565 #endif
566 pfl->timer = qemu_new_timer(vm_clock, pflash_timer, pfl);
567 pfl->base = base;
568 pfl->sector_len = sector_len;
569 pfl->total_len = total_len;
570 pfl->width = width;
571 pfl->wcycle = 0;
572 pfl->cmd = 0;
573 pfl->status = 0;
574 pfl->ident[0] = id0;
575 pfl->ident[1] = id1;
576 pfl->ident[2] = id2;
577 pfl->ident[3] = id3;
578 pfl->unlock_addr[0] = unlock_addr0;
579 pfl->unlock_addr[1] = unlock_addr1;
580 /* Hardcoded CFI table (mostly from SG29 Spansion flash) */
581 pfl->cfi_len = 0x52;
582 /* Standard "QRY" string */
583 pfl->cfi_table[0x10] = 'Q';
584 pfl->cfi_table[0x11] = 'R';
585 pfl->cfi_table[0x12] = 'Y';
586 /* Command set (AMD/Fujitsu) */
587 pfl->cfi_table[0x13] = 0x02;
588 pfl->cfi_table[0x14] = 0x00;
589 /* Primary extended table address (none) */
590 pfl->cfi_table[0x15] = 0x00;
591 pfl->cfi_table[0x16] = 0x00;
592 /* Alternate command set (none) */
593 pfl->cfi_table[0x17] = 0x00;
594 pfl->cfi_table[0x18] = 0x00;
595 /* Alternate extended table (none) */
596 pfl->cfi_table[0x19] = 0x00;
597 pfl->cfi_table[0x1A] = 0x00;
598 /* Vcc min */
599 pfl->cfi_table[0x1B] = 0x27;
600 /* Vcc max */
601 pfl->cfi_table[0x1C] = 0x36;
602 /* Vpp min (no Vpp pin) */
603 pfl->cfi_table[0x1D] = 0x00;
604 /* Vpp max (no Vpp pin) */
605 pfl->cfi_table[0x1E] = 0x00;
606 /* Reserved */
607 pfl->cfi_table[0x1F] = 0x07;
608 /* Timeout for min size buffer write (16 µs) */
609 pfl->cfi_table[0x20] = 0x04;
610 /* Typical timeout for block erase (512 ms) */
611 pfl->cfi_table[0x21] = 0x09;
612 /* Typical timeout for full chip erase (4096 ms) */
613 pfl->cfi_table[0x22] = 0x0C;
614 /* Reserved */
615 pfl->cfi_table[0x23] = 0x01;
616 /* Max timeout for buffer write */
617 pfl->cfi_table[0x24] = 0x04;
618 /* Max timeout for block erase */
619 pfl->cfi_table[0x25] = 0x0A;
620 /* Max timeout for chip erase */
621 pfl->cfi_table[0x26] = 0x0D;
622 /* Device size */
623 pfl->cfi_table[0x27] = ctz32(total_len) + 1;
624 /* Flash device interface (8 & 16 bits) */
625 pfl->cfi_table[0x28] = 0x02;
626 pfl->cfi_table[0x29] = 0x00;
627 /* Max number of bytes in multi-bytes write */
628 /* XXX: disable buffered write as it's not supported */
629 // pfl->cfi_table[0x2A] = 0x05;
630 pfl->cfi_table[0x2A] = 0x00;
631 pfl->cfi_table[0x2B] = 0x00;
632 /* Number of erase block regions (uniform) */
633 pfl->cfi_table[0x2C] = 0x01;
634 /* Erase block region 1 */
635 pfl->cfi_table[0x2D] = nb_blocs - 1;
636 pfl->cfi_table[0x2E] = (nb_blocs - 1) >> 8;
637 pfl->cfi_table[0x2F] = sector_len >> 8;
638 pfl->cfi_table[0x30] = sector_len >> 16;
639
640 return pfl;
641 }