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