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