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