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