]> Git Repo - qemu.git/blob - hw/onenand.c
pseries: Under kvm use guest cpu = host cpu by default
[qemu.git] / hw / onenand.c
1 /*
2  * OneNAND flash memories emulation.
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Written by Andrzej Zaborowski <[email protected]>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 or
10  * (at your option) version 3 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "qemu-common.h"
22 #include "hw.h"
23 #include "flash.h"
24 #include "irq.h"
25 #include "blockdev.h"
26 #include "memory.h"
27 #include "exec-memory.h"
28 #include "sysbus.h"
29
30 /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
31 #define PAGE_SHIFT      11
32
33 /* Fixed */
34 #define BLOCK_SHIFT     (PAGE_SHIFT + 6)
35
36 typedef struct {
37     SysBusDevice busdev;
38     struct {
39         uint16_t man;
40         uint16_t dev;
41         uint16_t ver;
42     } id;
43     int shift;
44     target_phys_addr_t base;
45     qemu_irq intr;
46     qemu_irq rdy;
47     BlockDriverState *bdrv;
48     BlockDriverState *bdrv_cur;
49     uint8_t *image;
50     uint8_t *otp;
51     uint8_t *current;
52     MemoryRegion ram;
53     MemoryRegion mapped_ram;
54     uint8_t current_direction;
55     uint8_t *boot[2];
56     uint8_t *data[2][2];
57     MemoryRegion iomem;
58     MemoryRegion container;
59     int cycle;
60     int otpmode;
61
62     uint16_t addr[8];
63     uint16_t unladdr[8];
64     int bufaddr;
65     int count;
66     uint16_t command;
67     uint16_t config[2];
68     uint16_t status;
69     uint16_t intstatus;
70     uint16_t wpstatus;
71
72     ECCState ecc;
73
74     int density_mask;
75     int secs;
76     int secs_cur;
77     int blocks;
78     uint8_t *blockwp;
79 } OneNANDState;
80
81 enum {
82     ONEN_BUF_BLOCK = 0,
83     ONEN_BUF_BLOCK2 = 1,
84     ONEN_BUF_DEST_BLOCK = 2,
85     ONEN_BUF_DEST_PAGE = 3,
86     ONEN_BUF_PAGE = 7,
87 };
88
89 enum {
90     ONEN_ERR_CMD = 1 << 10,
91     ONEN_ERR_ERASE = 1 << 11,
92     ONEN_ERR_PROG = 1 << 12,
93     ONEN_ERR_LOAD = 1 << 13,
94 };
95
96 enum {
97     ONEN_INT_RESET = 1 << 4,
98     ONEN_INT_ERASE = 1 << 5,
99     ONEN_INT_PROG = 1 << 6,
100     ONEN_INT_LOAD = 1 << 7,
101     ONEN_INT = 1 << 15,
102 };
103
104 enum {
105     ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
106     ONEN_LOCK_LOCKED = 1 << 1,
107     ONEN_LOCK_UNLOCKED = 1 << 2,
108 };
109
110 static void onenand_mem_setup(OneNANDState *s)
111 {
112     /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
113      * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
114      * write boot commands.  Also take note of the BWPS bit.  */
115     memory_region_init(&s->container, "onenand", 0x10000 << s->shift);
116     memory_region_add_subregion(&s->container, 0, &s->iomem);
117     memory_region_init_alias(&s->mapped_ram, "onenand-mapped-ram",
118                              &s->ram, 0x0200 << s->shift,
119                              0xbe00 << s->shift);
120     memory_region_add_subregion_overlap(&s->container,
121                                         0x0200 << s->shift,
122                                         &s->mapped_ram,
123                                         1);
124 }
125
126 static void onenand_intr_update(OneNANDState *s)
127 {
128     qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
129 }
130
131 static void onenand_pre_save(void *opaque)
132 {
133     OneNANDState *s = opaque;
134     if (s->current == s->otp) {
135         s->current_direction = 1;
136     } else if (s->current == s->image) {
137         s->current_direction = 2;
138     } else {
139         s->current_direction = 0;
140     }
141 }
142
143 static int onenand_post_load(void *opaque, int version_id)
144 {
145     OneNANDState *s = opaque;
146     switch (s->current_direction) {
147     case 0:
148         break;
149     case 1:
150         s->current = s->otp;
151         break;
152     case 2:
153         s->current = s->image;
154         break;
155     default:
156         return -1;
157     }
158     onenand_intr_update(s);
159     return 0;
160 }
161
162 static const VMStateDescription vmstate_onenand = {
163     .name = "onenand",
164     .version_id = 1,
165     .minimum_version_id = 1,
166     .minimum_version_id_old = 1,
167     .pre_save = onenand_pre_save,
168     .post_load = onenand_post_load,
169     .fields = (VMStateField[]) {
170         VMSTATE_UINT8(current_direction, OneNANDState),
171         VMSTATE_INT32(cycle, OneNANDState),
172         VMSTATE_INT32(otpmode, OneNANDState),
173         VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8),
174         VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8),
175         VMSTATE_INT32(bufaddr, OneNANDState),
176         VMSTATE_INT32(count, OneNANDState),
177         VMSTATE_UINT16(command, OneNANDState),
178         VMSTATE_UINT16_ARRAY(config, OneNANDState, 2),
179         VMSTATE_UINT16(status, OneNANDState),
180         VMSTATE_UINT16(intstatus, OneNANDState),
181         VMSTATE_UINT16(wpstatus, OneNANDState),
182         VMSTATE_INT32(secs_cur, OneNANDState),
183         VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks),
184         VMSTATE_UINT8(ecc.cp, OneNANDState),
185         VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
186         VMSTATE_UINT16(ecc.count, OneNANDState),
187         VMSTATE_BUFFER_UNSAFE(otp, OneNANDState, 0, ((64 + 2) << PAGE_SHIFT)),
188         VMSTATE_END_OF_LIST()
189     }
190 };
191
192 /* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
193 static void onenand_reset(OneNANDState *s, int cold)
194 {
195     memset(&s->addr, 0, sizeof(s->addr));
196     s->command = 0;
197     s->count = 1;
198     s->bufaddr = 0;
199     s->config[0] = 0x40c0;
200     s->config[1] = 0x0000;
201     onenand_intr_update(s);
202     qemu_irq_raise(s->rdy);
203     s->status = 0x0000;
204     s->intstatus = cold ? 0x8080 : 0x8010;
205     s->unladdr[0] = 0;
206     s->unladdr[1] = 0;
207     s->wpstatus = 0x0002;
208     s->cycle = 0;
209     s->otpmode = 0;
210     s->bdrv_cur = s->bdrv;
211     s->current = s->image;
212     s->secs_cur = s->secs;
213
214     if (cold) {
215         /* Lock the whole flash */
216         memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
217
218         if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) {
219             hw_error("%s: Loading the BootRAM failed.\n", __func__);
220         }
221     }
222 }
223
224 static void onenand_system_reset(DeviceState *dev)
225 {
226     onenand_reset(FROM_SYSBUS(OneNANDState, sysbus_from_qdev(dev)), 1);
227 }
228
229 static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
230                 void *dest)
231 {
232     if (s->bdrv_cur)
233         return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
234     else if (sec + secn > s->secs_cur)
235         return 1;
236
237     memcpy(dest, s->current + (sec << 9), secn << 9);
238
239     return 0;
240 }
241
242 static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
243                 void *src)
244 {
245     int result = 0;
246
247     if (secn > 0) {
248         uint32_t size = (uint32_t)secn * 512;
249         const uint8_t *sp = (const uint8_t *)src;
250         uint8_t *dp = 0;
251         if (s->bdrv_cur) {
252             dp = g_malloc(size);
253             if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
254                 result = 1;
255             }
256         } else {
257             if (sec + secn > s->secs_cur) {
258                 result = 1;
259             } else {
260                 dp = (uint8_t *)s->current + (sec << 9);
261             }
262         }
263         if (!result) {
264             uint32_t i;
265             for (i = 0; i < size; i++) {
266                 dp[i] &= sp[i];
267             }
268             if (s->bdrv_cur) {
269                 result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
270             }
271         }
272         if (dp && s->bdrv_cur) {
273             g_free(dp);
274         }
275     }
276
277     return result;
278 }
279
280 static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
281                 void *dest)
282 {
283     uint8_t buf[512];
284
285     if (s->bdrv_cur) {
286         if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
287             return 1;
288         memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
289     } else if (sec + secn > s->secs_cur)
290         return 1;
291     else
292         memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
293  
294     return 0;
295 }
296
297 static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
298                 void *src)
299 {
300     int result = 0;
301     if (secn > 0) {
302         const uint8_t *sp = (const uint8_t *)src;
303         uint8_t *dp = 0, *dpp = 0;
304         if (s->bdrv_cur) {
305             dp = g_malloc(512);
306             if (!dp || bdrv_read(s->bdrv_cur,
307                                  s->secs_cur + (sec >> 5),
308                                  dp, 1) < 0) {
309                 result = 1;
310             } else {
311                 dpp = dp + ((sec & 31) << 4);
312             }
313         } else {
314             if (sec + secn > s->secs_cur) {
315                 result = 1;
316             } else {
317                 dpp = s->current + (s->secs_cur << 9) + (sec << 4);
318             }
319         }
320         if (!result) {
321             uint32_t i;
322             for (i = 0; i < (secn << 4); i++) {
323                 dpp[i] &= sp[i];
324             }
325             if (s->bdrv_cur) {
326                 result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
327                                     dp, 1) < 0;
328             }
329         }
330         if (dp) {
331             g_free(dp);
332         }
333     }
334     return result;
335 }
336
337 static inline int onenand_erase(OneNANDState *s, int sec, int num)
338 {
339     uint8_t *blankbuf, *tmpbuf;
340     blankbuf = g_malloc(512);
341     if (!blankbuf) {
342         return 1;
343     }
344     tmpbuf = g_malloc(512);
345     if (!tmpbuf) {
346         g_free(blankbuf);
347         return 1;
348     }
349     memset(blankbuf, 0xff, 512);
350     for (; num > 0; num--, sec++) {
351         if (s->bdrv_cur) {
352             int erasesec = s->secs_cur + (sec >> 5);
353             if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1)) {
354                 goto fail;
355             }
356             if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
357                 goto fail;
358             }
359             memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
360             if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
361                 goto fail;
362             }
363         } else {
364             if (sec + 1 > s->secs_cur) {
365                 goto fail;
366             }
367             memcpy(s->current + (sec << 9), blankbuf, 512);
368             memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
369                    blankbuf, 1 << 4);
370         }
371     }
372
373     g_free(tmpbuf);
374     g_free(blankbuf);
375     return 0;
376
377 fail:
378     g_free(tmpbuf);
379     g_free(blankbuf);
380     return 1;
381 }
382
383 static void onenand_command(OneNANDState *s)
384 {
385     int b;
386     int sec;
387     void *buf;
388 #define SETADDR(block, page)                    \
389     sec = (s->addr[page] & 3) +                 \
390             ((((s->addr[page] >> 2) & 0x3f) +   \
391               (((s->addr[block] & 0xfff) |      \
392                 (s->addr[block] >> 15 ?         \
393                  s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9));
394 #define SETBUF_M()                              \
395     buf = (s->bufaddr & 8) ?                    \
396             s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0];     \
397     buf += (s->bufaddr & 3) << 9;
398 #define SETBUF_S()                              \
399     buf = (s->bufaddr & 8) ?                    \
400             s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1];     \
401     buf += (s->bufaddr & 3) << 4;
402
403     switch (s->command) {
404     case 0x00:  /* Load single/multiple sector data unit into buffer */
405         SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
406
407         SETBUF_M()
408         if (onenand_load_main(s, sec, s->count, buf))
409             s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
410
411 #if 0
412         SETBUF_S()
413         if (onenand_load_spare(s, sec, s->count, buf))
414             s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
415 #endif
416
417         /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
418          * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
419          * then we need two split the read/write into two chunks.
420          */
421         s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
422         break;
423     case 0x13:  /* Load single/multiple spare sector into buffer */
424         SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
425
426         SETBUF_S()
427         if (onenand_load_spare(s, sec, s->count, buf))
428             s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
429
430         /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
431          * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
432          * then we need two split the read/write into two chunks.
433          */
434         s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
435         break;
436     case 0x80:  /* Program single/multiple sector data unit from buffer */
437         SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
438
439         SETBUF_M()
440         if (onenand_prog_main(s, sec, s->count, buf))
441             s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
442
443 #if 0
444         SETBUF_S()
445         if (onenand_prog_spare(s, sec, s->count, buf))
446             s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
447 #endif
448
449         /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
450          * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
451          * then we need two split the read/write into two chunks.
452          */
453         s->intstatus |= ONEN_INT | ONEN_INT_PROG;
454         break;
455     case 0x1a:  /* Program single/multiple spare area sector from buffer */
456         SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
457
458         SETBUF_S()
459         if (onenand_prog_spare(s, sec, s->count, buf))
460             s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
461
462         /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
463          * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
464          * then we need two split the read/write into two chunks.
465          */
466         s->intstatus |= ONEN_INT | ONEN_INT_PROG;
467         break;
468     case 0x1b:  /* Copy-back program */
469         SETBUF_S()
470
471         SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
472         if (onenand_load_main(s, sec, s->count, buf))
473             s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
474
475         SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE)
476         if (onenand_prog_main(s, sec, s->count, buf))
477             s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
478
479         /* TODO: spare areas */
480
481         s->intstatus |= ONEN_INT | ONEN_INT_PROG;
482         break;
483
484     case 0x23:  /* Unlock NAND array block(s) */
485         s->intstatus |= ONEN_INT;
486
487         /* XXX the previous (?) area should be locked automatically */
488         for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
489             if (b >= s->blocks) {
490                 s->status |= ONEN_ERR_CMD;
491                 break;
492             }
493             if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
494                 break;
495
496             s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
497         }
498         break;
499     case 0x27:  /* Unlock All NAND array blocks */
500         s->intstatus |= ONEN_INT;
501
502         for (b = 0; b < s->blocks; b ++) {
503             if (b >= s->blocks) {
504                 s->status |= ONEN_ERR_CMD;
505                 break;
506             }
507             if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
508                 break;
509
510             s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
511         }
512         break;
513
514     case 0x2a:  /* Lock NAND array block(s) */
515         s->intstatus |= ONEN_INT;
516
517         for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
518             if (b >= s->blocks) {
519                 s->status |= ONEN_ERR_CMD;
520                 break;
521             }
522             if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
523                 break;
524
525             s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED;
526         }
527         break;
528     case 0x2c:  /* Lock-tight NAND array block(s) */
529         s->intstatus |= ONEN_INT;
530
531         for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
532             if (b >= s->blocks) {
533                 s->status |= ONEN_ERR_CMD;
534                 break;
535             }
536             if (s->blockwp[b] == ONEN_LOCK_UNLOCKED)
537                 continue;
538
539             s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN;
540         }
541         break;
542
543     case 0x71:  /* Erase-Verify-Read */
544         s->intstatus |= ONEN_INT;
545         break;
546     case 0x95:  /* Multi-block erase */
547         qemu_irq_pulse(s->intr);
548         /* Fall through.  */
549     case 0x94:  /* Block erase */
550         sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) |
551                         (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0))
552                 << (BLOCK_SHIFT - 9);
553         if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9)))
554             s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE;
555
556         s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
557         break;
558     case 0xb0:  /* Erase suspend */
559         break;
560     case 0x30:  /* Erase resume */
561         s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
562         break;
563
564     case 0xf0:  /* Reset NAND Flash core */
565         onenand_reset(s, 0);
566         break;
567     case 0xf3:  /* Reset OneNAND */
568         onenand_reset(s, 0);
569         break;
570
571     case 0x65:  /* OTP Access */
572         s->intstatus |= ONEN_INT;
573         s->bdrv_cur = NULL;
574         s->current = s->otp;
575         s->secs_cur = 1 << (BLOCK_SHIFT - 9);
576         s->addr[ONEN_BUF_BLOCK] = 0;
577         s->otpmode = 1;
578         break;
579
580     default:
581         s->status |= ONEN_ERR_CMD;
582         s->intstatus |= ONEN_INT;
583         fprintf(stderr, "%s: unknown OneNAND command %x\n",
584                         __func__, s->command);
585     }
586
587     onenand_intr_update(s);
588 }
589
590 static uint64_t onenand_read(void *opaque, target_phys_addr_t addr,
591                              unsigned size)
592 {
593     OneNANDState *s = (OneNANDState *) opaque;
594     int offset = addr >> s->shift;
595
596     switch (offset) {
597     case 0x0000 ... 0xc000:
598         return lduw_le_p(s->boot[0] + addr);
599
600     case 0xf000:        /* Manufacturer ID */
601         return s->id.man;
602     case 0xf001:        /* Device ID */
603         return s->id.dev;
604     case 0xf002:        /* Version ID */
605         return s->id.ver;
606     /* TODO: get the following values from a real chip!  */
607     case 0xf003:        /* Data Buffer size */
608         return 1 << PAGE_SHIFT;
609     case 0xf004:        /* Boot Buffer size */
610         return 0x200;
611     case 0xf005:        /* Amount of buffers */
612         return 1 | (2 << 8);
613     case 0xf006:        /* Technology */
614         return 0;
615
616     case 0xf100 ... 0xf107:     /* Start addresses */
617         return s->addr[offset - 0xf100];
618
619     case 0xf200:        /* Start buffer */
620         return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10)));
621
622     case 0xf220:        /* Command */
623         return s->command;
624     case 0xf221:        /* System Configuration 1 */
625         return s->config[0] & 0xffe0;
626     case 0xf222:        /* System Configuration 2 */
627         return s->config[1];
628
629     case 0xf240:        /* Controller Status */
630         return s->status;
631     case 0xf241:        /* Interrupt */
632         return s->intstatus;
633     case 0xf24c:        /* Unlock Start Block Address */
634         return s->unladdr[0];
635     case 0xf24d:        /* Unlock End Block Address */
636         return s->unladdr[1];
637     case 0xf24e:        /* Write Protection Status */
638         return s->wpstatus;
639
640     case 0xff00:        /* ECC Status */
641         return 0x00;
642     case 0xff01:        /* ECC Result of main area data */
643     case 0xff02:        /* ECC Result of spare area data */
644     case 0xff03:        /* ECC Result of main area data */
645     case 0xff04:        /* ECC Result of spare area data */
646         hw_error("%s: imeplement ECC\n", __FUNCTION__);
647         return 0x0000;
648     }
649
650     fprintf(stderr, "%s: unknown OneNAND register %x\n",
651                     __FUNCTION__, offset);
652     return 0;
653 }
654
655 static void onenand_write(void *opaque, target_phys_addr_t addr,
656                           uint64_t value, unsigned size)
657 {
658     OneNANDState *s = (OneNANDState *) opaque;
659     int offset = addr >> s->shift;
660     int sec;
661
662     switch (offset) {
663     case 0x0000 ... 0x01ff:
664     case 0x8000 ... 0x800f:
665         if (s->cycle) {
666             s->cycle = 0;
667
668             if (value == 0x0000) {
669                 SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
670                 onenand_load_main(s, sec,
671                                 1 << (PAGE_SHIFT - 9), s->data[0][0]);
672                 s->addr[ONEN_BUF_PAGE] += 4;
673                 s->addr[ONEN_BUF_PAGE] &= 0xff;
674             }
675             break;
676         }
677
678         switch (value) {
679         case 0x00f0:    /* Reset OneNAND */
680             onenand_reset(s, 0);
681             break;
682
683         case 0x00e0:    /* Load Data into Buffer */
684             s->cycle = 1;
685             break;
686
687         case 0x0090:    /* Read Identification Data */
688             memset(s->boot[0], 0, 3 << s->shift);
689             s->boot[0][0 << s->shift] = s->id.man & 0xff;
690             s->boot[0][1 << s->shift] = s->id.dev & 0xff;
691             s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
692             break;
693
694         default:
695             fprintf(stderr, "%s: unknown OneNAND boot command %"PRIx64"\n",
696                             __FUNCTION__, value);
697         }
698         break;
699
700     case 0xf100 ... 0xf107:     /* Start addresses */
701         s->addr[offset - 0xf100] = value;
702         break;
703
704     case 0xf200:        /* Start buffer */
705         s->bufaddr = (value >> 8) & 0xf;
706         if (PAGE_SHIFT == 11)
707             s->count = (value & 3) ?: 4;
708         else if (PAGE_SHIFT == 10)
709             s->count = (value & 1) ?: 2;
710         break;
711
712     case 0xf220:        /* Command */
713         if (s->intstatus & (1 << 15))
714             break;
715         s->command = value;
716         onenand_command(s);
717         break;
718     case 0xf221:        /* System Configuration 1 */
719         s->config[0] = value;
720         onenand_intr_update(s);
721         qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1);
722         break;
723     case 0xf222:        /* System Configuration 2 */
724         s->config[1] = value;
725         break;
726
727     case 0xf241:        /* Interrupt */
728         s->intstatus &= value;
729         if ((1 << 15) & ~s->intstatus)
730             s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE |
731                             ONEN_ERR_PROG | ONEN_ERR_LOAD);
732         onenand_intr_update(s);
733         break;
734     case 0xf24c:        /* Unlock Start Block Address */
735         s->unladdr[0] = value & (s->blocks - 1);
736         /* For some reason we have to set the end address to by default
737          * be same as start because the software forgets to write anything
738          * in there.  */
739         s->unladdr[1] = value & (s->blocks - 1);
740         break;
741     case 0xf24d:        /* Unlock End Block Address */
742         s->unladdr[1] = value & (s->blocks - 1);
743         break;
744
745     default:
746         fprintf(stderr, "%s: unknown OneNAND register %x\n",
747                         __FUNCTION__, offset);
748     }
749 }
750
751 static const MemoryRegionOps onenand_ops = {
752     .read = onenand_read,
753     .write = onenand_write,
754     .endianness = DEVICE_NATIVE_ENDIAN,
755 };
756
757 static int onenand_initfn(SysBusDevice *dev)
758 {
759     OneNANDState *s = (OneNANDState *)dev;
760     uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
761     void *ram;
762     s->base = (target_phys_addr_t)-1;
763     s->rdy = NULL;
764     s->blocks = size >> BLOCK_SHIFT;
765     s->secs = size >> 9;
766     s->blockwp = g_malloc(s->blocks);
767     s->density_mask = (s->id.dev & 0x08)
768         ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
769     memory_region_init_io(&s->iomem, &onenand_ops, s, "onenand",
770                           0x10000 << s->shift);
771     if (!s->bdrv) {
772         s->image = memset(g_malloc(size + (size >> 5)),
773                           0xff, size + (size >> 5));
774     } else {
775         s->bdrv_cur = s->bdrv;
776     }
777     s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
778                     0xff, (64 + 2) << PAGE_SHIFT);
779     memory_region_init_ram(&s->ram, NULL, "onenand.ram", 0xc000 << s->shift);
780     ram = memory_region_get_ram_ptr(&s->ram);
781     s->boot[0] = ram + (0x0000 << s->shift);
782     s->boot[1] = ram + (0x8000 << s->shift);
783     s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
784     s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
785     s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
786     s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
787     onenand_mem_setup(s);
788     sysbus_init_irq(dev, &s->intr);
789     sysbus_init_mmio_region(dev, &s->container);
790     vmstate_register(&dev->qdev,
791                      ((s->shift & 0x7f) << 24)
792                      | ((s->id.man & 0xff) << 16)
793                      | ((s->id.dev & 0xff) << 8)
794                      | (s->id.ver & 0xff),
795                      &vmstate_onenand, s);
796     return 0;
797 }
798
799 static SysBusDeviceInfo onenand_info = {
800     .init = onenand_initfn,
801     .qdev.name = "onenand",
802     .qdev.size = sizeof(OneNANDState),
803     .qdev.reset = onenand_system_reset,
804     .qdev.props = (Property[]) {
805         DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
806         DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
807         DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
808         DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
809         DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
810         DEFINE_PROP_END_OF_LIST()
811     }
812 };
813
814 static void onenand_register_device(void)
815 {
816     sysbus_register_withprop(&onenand_info);
817 }
818
819 void *onenand_raw_otp(DeviceState *onenand_device)
820 {
821     return FROM_SYSBUS(OneNANDState, sysbus_from_qdev(onenand_device))->otp;
822 }
823
824 device_init(onenand_register_device)
This page took 0.070529 seconds and 4 git commands to generate.