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