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