xref: /openbmc/qemu/hw/block/onenand.c (revision 56983463)
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/blockdev.h"
26 #include "exec/memory.h"
27 #include "exec/address-spaces.h"
28 #include "hw/sysbus.h"
29 #include "qemu/error-report.h"
30 
31 /* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
32 #define PAGE_SHIFT	11
33 
34 /* Fixed */
35 #define BLOCK_SHIFT	(PAGE_SHIFT + 6)
36 
37 typedef struct {
38     SysBusDevice busdev;
39     struct {
40         uint16_t man;
41         uint16_t dev;
42         uint16_t ver;
43     } id;
44     int shift;
45     hwaddr base;
46     qemu_irq intr;
47     qemu_irq rdy;
48     BlockDriverState *bdrv;
49     BlockDriverState *bdrv_cur;
50     uint8_t *image;
51     uint8_t *otp;
52     uint8_t *current;
53     MemoryRegion ram;
54     MemoryRegion mapped_ram;
55     uint8_t current_direction;
56     uint8_t *boot[2];
57     uint8_t *data[2][2];
58     MemoryRegion iomem;
59     MemoryRegion container;
60     int cycle;
61     int otpmode;
62 
63     uint16_t addr[8];
64     uint16_t unladdr[8];
65     int bufaddr;
66     int count;
67     uint16_t command;
68     uint16_t config[2];
69     uint16_t status;
70     uint16_t intstatus;
71     uint16_t wpstatus;
72 
73     ECCState ecc;
74 
75     int density_mask;
76     int secs;
77     int secs_cur;
78     int blocks;
79     uint8_t *blockwp;
80 } OneNANDState;
81 
82 enum {
83     ONEN_BUF_BLOCK = 0,
84     ONEN_BUF_BLOCK2 = 1,
85     ONEN_BUF_DEST_BLOCK = 2,
86     ONEN_BUF_DEST_PAGE = 3,
87     ONEN_BUF_PAGE = 7,
88 };
89 
90 enum {
91     ONEN_ERR_CMD = 1 << 10,
92     ONEN_ERR_ERASE = 1 << 11,
93     ONEN_ERR_PROG = 1 << 12,
94     ONEN_ERR_LOAD = 1 << 13,
95 };
96 
97 enum {
98     ONEN_INT_RESET = 1 << 4,
99     ONEN_INT_ERASE = 1 << 5,
100     ONEN_INT_PROG = 1 << 6,
101     ONEN_INT_LOAD = 1 << 7,
102     ONEN_INT = 1 << 15,
103 };
104 
105 enum {
106     ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
107     ONEN_LOCK_LOCKED = 1 << 1,
108     ONEN_LOCK_UNLOCKED = 1 << 2,
109 };
110 
111 static void onenand_mem_setup(OneNANDState *s)
112 {
113     /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
114      * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
115      * write boot commands.  Also take note of the BWPS bit.  */
116     memory_region_init(&s->container, OBJECT(s), "onenand",
117                        0x10000 << s->shift);
118     memory_region_add_subregion(&s->container, 0, &s->iomem);
119     memory_region_init_alias(&s->mapped_ram, OBJECT(s), "onenand-mapped-ram",
120                              &s->ram, 0x0200 << s->shift,
121                              0xbe00 << s->shift);
122     memory_region_add_subregion_overlap(&s->container,
123                                         0x0200 << s->shift,
124                                         &s->mapped_ram,
125                                         1);
126 }
127 
128 static void onenand_intr_update(OneNANDState *s)
129 {
130     qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
131 }
132 
133 static void onenand_pre_save(void *opaque)
134 {
135     OneNANDState *s = opaque;
136     if (s->current == s->otp) {
137         s->current_direction = 1;
138     } else if (s->current == s->image) {
139         s->current_direction = 2;
140     } else {
141         s->current_direction = 0;
142     }
143 }
144 
145 static int onenand_post_load(void *opaque, int version_id)
146 {
147     OneNANDState *s = opaque;
148     switch (s->current_direction) {
149     case 0:
150         break;
151     case 1:
152         s->current = s->otp;
153         break;
154     case 2:
155         s->current = s->image;
156         break;
157     default:
158         return -1;
159     }
160     onenand_intr_update(s);
161     return 0;
162 }
163 
164 static const VMStateDescription vmstate_onenand = {
165     .name = "onenand",
166     .version_id = 1,
167     .minimum_version_id = 1,
168     .minimum_version_id_old = 1,
169     .pre_save = onenand_pre_save,
170     .post_load = onenand_post_load,
171     .fields = (VMStateField[]) {
172         VMSTATE_UINT8(current_direction, OneNANDState),
173         VMSTATE_INT32(cycle, OneNANDState),
174         VMSTATE_INT32(otpmode, OneNANDState),
175         VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8),
176         VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8),
177         VMSTATE_INT32(bufaddr, OneNANDState),
178         VMSTATE_INT32(count, OneNANDState),
179         VMSTATE_UINT16(command, OneNANDState),
180         VMSTATE_UINT16_ARRAY(config, OneNANDState, 2),
181         VMSTATE_UINT16(status, OneNANDState),
182         VMSTATE_UINT16(intstatus, OneNANDState),
183         VMSTATE_UINT16(wpstatus, OneNANDState),
184         VMSTATE_INT32(secs_cur, OneNANDState),
185         VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks),
186         VMSTATE_UINT8(ecc.cp, OneNANDState),
187         VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
188         VMSTATE_UINT16(ecc.count, OneNANDState),
189         VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
190             ((64 + 2) << PAGE_SHIFT)),
191         VMSTATE_END_OF_LIST()
192     }
193 };
194 
195 /* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
196 static void onenand_reset(OneNANDState *s, int cold)
197 {
198     memset(&s->addr, 0, sizeof(s->addr));
199     s->command = 0;
200     s->count = 1;
201     s->bufaddr = 0;
202     s->config[0] = 0x40c0;
203     s->config[1] = 0x0000;
204     onenand_intr_update(s);
205     qemu_irq_raise(s->rdy);
206     s->status = 0x0000;
207     s->intstatus = cold ? 0x8080 : 0x8010;
208     s->unladdr[0] = 0;
209     s->unladdr[1] = 0;
210     s->wpstatus = 0x0002;
211     s->cycle = 0;
212     s->otpmode = 0;
213     s->bdrv_cur = s->bdrv;
214     s->current = s->image;
215     s->secs_cur = s->secs;
216 
217     if (cold) {
218         /* Lock the whole flash */
219         memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
220 
221         if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) {
222             hw_error("%s: Loading the BootRAM failed.\n", __func__);
223         }
224     }
225 }
226 
227 static void onenand_system_reset(DeviceState *dev)
228 {
229     onenand_reset(FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(dev)), 1);
230 }
231 
232 static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
233                 void *dest)
234 {
235     if (s->bdrv_cur)
236         return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
237     else if (sec + secn > s->secs_cur)
238         return 1;
239 
240     memcpy(dest, s->current + (sec << 9), secn << 9);
241 
242     return 0;
243 }
244 
245 static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
246                 void *src)
247 {
248     int result = 0;
249 
250     if (secn > 0) {
251         uint32_t size = (uint32_t)secn * 512;
252         const uint8_t *sp = (const uint8_t *)src;
253         uint8_t *dp = 0;
254         if (s->bdrv_cur) {
255             dp = g_malloc(size);
256             if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
257                 result = 1;
258             }
259         } else {
260             if (sec + secn > s->secs_cur) {
261                 result = 1;
262             } else {
263                 dp = (uint8_t *)s->current + (sec << 9);
264             }
265         }
266         if (!result) {
267             uint32_t i;
268             for (i = 0; i < size; i++) {
269                 dp[i] &= sp[i];
270             }
271             if (s->bdrv_cur) {
272                 result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
273             }
274         }
275         if (dp && s->bdrv_cur) {
276             g_free(dp);
277         }
278     }
279 
280     return result;
281 }
282 
283 static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
284                 void *dest)
285 {
286     uint8_t buf[512];
287 
288     if (s->bdrv_cur) {
289         if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
290             return 1;
291         memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
292     } else if (sec + secn > s->secs_cur)
293         return 1;
294     else
295         memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
296 
297     return 0;
298 }
299 
300 static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
301                 void *src)
302 {
303     int result = 0;
304     if (secn > 0) {
305         const uint8_t *sp = (const uint8_t *)src;
306         uint8_t *dp = 0, *dpp = 0;
307         if (s->bdrv_cur) {
308             dp = g_malloc(512);
309             if (!dp || bdrv_read(s->bdrv_cur,
310                                  s->secs_cur + (sec >> 5),
311                                  dp, 1) < 0) {
312                 result = 1;
313             } else {
314                 dpp = dp + ((sec & 31) << 4);
315             }
316         } else {
317             if (sec + secn > s->secs_cur) {
318                 result = 1;
319             } else {
320                 dpp = s->current + (s->secs_cur << 9) + (sec << 4);
321             }
322         }
323         if (!result) {
324             uint32_t i;
325             for (i = 0; i < (secn << 4); i++) {
326                 dpp[i] &= sp[i];
327             }
328             if (s->bdrv_cur) {
329                 result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
330                                     dp, 1) < 0;
331             }
332         }
333         if (dp) {
334             g_free(dp);
335         }
336     }
337     return result;
338 }
339 
340 static inline int onenand_erase(OneNANDState *s, int sec, int num)
341 {
342     uint8_t *blankbuf, *tmpbuf;
343     blankbuf = g_malloc(512);
344     if (!blankbuf) {
345         return 1;
346     }
347     tmpbuf = g_malloc(512);
348     if (!tmpbuf) {
349         g_free(blankbuf);
350         return 1;
351     }
352     memset(blankbuf, 0xff, 512);
353     for (; num > 0; num--, sec++) {
354         if (s->bdrv_cur) {
355             int erasesec = s->secs_cur + (sec >> 5);
356             if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1) < 0) {
357                 goto fail;
358             }
359             if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
360                 goto fail;
361             }
362             memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
363             if (bdrv_write(s->bdrv_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->bdrv_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 *dev)
761 {
762     OneNANDState *s = (OneNANDState *)dev;
763     uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
764     void *ram;
765     s->base = (hwaddr)-1;
766     s->rdy = NULL;
767     s->blocks = size >> BLOCK_SHIFT;
768     s->secs = size >> 9;
769     s->blockwp = g_malloc(s->blocks);
770     s->density_mask = (s->id.dev & 0x08)
771         ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
772     memory_region_init_io(&s->iomem, OBJECT(s), &onenand_ops, s, "onenand",
773                           0x10000 << s->shift);
774     if (!s->bdrv) {
775         s->image = memset(g_malloc(size + (size >> 5)),
776                           0xff, size + (size >> 5));
777     } else {
778         if (bdrv_is_read_only(s->bdrv)) {
779             error_report("Can't use a read-only drive");
780             return -1;
781         }
782         s->bdrv_cur = s->bdrv;
783     }
784     s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
785                     0xff, (64 + 2) << PAGE_SHIFT);
786     memory_region_init_ram(&s->ram, OBJECT(s), "onenand.ram",
787                            0xc000 << s->shift);
788     vmstate_register_ram_global(&s->ram);
789     ram = memory_region_get_ram_ptr(&s->ram);
790     s->boot[0] = ram + (0x0000 << s->shift);
791     s->boot[1] = ram + (0x8000 << s->shift);
792     s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
793     s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
794     s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
795     s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
796     onenand_mem_setup(s);
797     sysbus_init_irq(dev, &s->intr);
798     sysbus_init_mmio(dev, &s->container);
799     vmstate_register(&dev->qdev,
800                      ((s->shift & 0x7f) << 24)
801                      | ((s->id.man & 0xff) << 16)
802                      | ((s->id.dev & 0xff) << 8)
803                      | (s->id.ver & 0xff),
804                      &vmstate_onenand, s);
805     return 0;
806 }
807 
808 static Property onenand_properties[] = {
809     DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
810     DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
811     DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
812     DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
813     DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
814     DEFINE_PROP_END_OF_LIST(),
815 };
816 
817 static void onenand_class_init(ObjectClass *klass, void *data)
818 {
819     DeviceClass *dc = DEVICE_CLASS(klass);
820     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
821 
822     k->init = onenand_initfn;
823     dc->reset = onenand_system_reset;
824     dc->props = onenand_properties;
825 }
826 
827 static const TypeInfo onenand_info = {
828     .name          = "onenand",
829     .parent        = TYPE_SYS_BUS_DEVICE,
830     .instance_size = sizeof(OneNANDState),
831     .class_init    = onenand_class_init,
832 };
833 
834 static void onenand_register_types(void)
835 {
836     type_register_static(&onenand_info);
837 }
838 
839 void *onenand_raw_otp(DeviceState *onenand_device)
840 {
841     return FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(onenand_device))->otp;
842 }
843 
844 type_init(onenand_register_types)
845