Statistics
| Branch: | Revision:

root / hw / onenand.c @ 1de7afc9

History | View | Annotate | Download (24.6 kB)

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 "exec/memory.h"
27
#include "exec/address-spaces.h"
28
#include "sysbus.h"
29
#include "qemu/error-report.h"
30

    
31
/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
32
#define PAGE_SHIFT        11
33

    
34
/* Fixed */
35
#define BLOCK_SHIFT        (PAGE_SHIFT + 6)
36

    
37
typedef struct {
38
    SysBusDevice busdev;
39
    struct {
40
        uint16_t man;
41
        uint16_t dev;
42
        uint16_t ver;
43
    } id;
44
    int shift;
45
    hwaddr base;
46
    qemu_irq intr;
47
    qemu_irq rdy;
48
    BlockDriverState *bdrv;
49
    BlockDriverState *bdrv_cur;
50
    uint8_t *image;
51
    uint8_t *otp;
52
    uint8_t *current;
53
    MemoryRegion ram;
54
    MemoryRegion mapped_ram;
55
    uint8_t current_direction;
56
    uint8_t *boot[2];
57
    uint8_t *data[2][2];
58
    MemoryRegion iomem;
59
    MemoryRegion container;
60
    int cycle;
61
    int otpmode;
62

    
63
    uint16_t addr[8];
64
    uint16_t unladdr[8];
65
    int bufaddr;
66
    int count;
67
    uint16_t command;
68
    uint16_t config[2];
69
    uint16_t status;
70
    uint16_t intstatus;
71
    uint16_t wpstatus;
72

    
73
    ECCState ecc;
74

    
75
    int density_mask;
76
    int secs;
77
    int secs_cur;
78
    int blocks;
79
    uint8_t *blockwp;
80
} OneNANDState;
81

    
82
enum {
83
    ONEN_BUF_BLOCK = 0,
84
    ONEN_BUF_BLOCK2 = 1,
85
    ONEN_BUF_DEST_BLOCK = 2,
86
    ONEN_BUF_DEST_PAGE = 3,
87
    ONEN_BUF_PAGE = 7,
88
};
89

    
90
enum {
91
    ONEN_ERR_CMD = 1 << 10,
92
    ONEN_ERR_ERASE = 1 << 11,
93
    ONEN_ERR_PROG = 1 << 12,
94
    ONEN_ERR_LOAD = 1 << 13,
95
};
96

    
97
enum {
98
    ONEN_INT_RESET = 1 << 4,
99
    ONEN_INT_ERASE = 1 << 5,
100
    ONEN_INT_PROG = 1 << 6,
101
    ONEN_INT_LOAD = 1 << 7,
102
    ONEN_INT = 1 << 15,
103
};
104

    
105
enum {
106
    ONEN_LOCK_LOCKTIGHTEN = 1 << 0,
107
    ONEN_LOCK_LOCKED = 1 << 1,
108
    ONEN_LOCK_UNLOCKED = 1 << 2,
109
};
110

    
111
static void onenand_mem_setup(OneNANDState *s)
112
{
113
    /* XXX: We should use IO_MEM_ROMD but we broke it earlier...
114
     * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to
115
     * write boot commands.  Also take note of the BWPS bit.  */
116
    memory_region_init(&s->container, "onenand", 0x10000 << s->shift);
117
    memory_region_add_subregion(&s->container, 0, &s->iomem);
118
    memory_region_init_alias(&s->mapped_ram, "onenand-mapped-ram",
119
                             &s->ram, 0x0200 << s->shift,
120
                             0xbe00 << s->shift);
121
    memory_region_add_subregion_overlap(&s->container,
122
                                        0x0200 << s->shift,
123
                                        &s->mapped_ram,
124
                                        1);
125
}
126

    
127
static void onenand_intr_update(OneNANDState *s)
128
{
129
    qemu_set_irq(s->intr, ((s->intstatus >> 15) ^ (~s->config[0] >> 6)) & 1);
130
}
131

    
132
static void onenand_pre_save(void *opaque)
133
{
134
    OneNANDState *s = opaque;
135
    if (s->current == s->otp) {
136
        s->current_direction = 1;
137
    } else if (s->current == s->image) {
138
        s->current_direction = 2;
139
    } else {
140
        s->current_direction = 0;
141
    }
142
}
143

    
144
static int onenand_post_load(void *opaque, int version_id)
145
{
146
    OneNANDState *s = opaque;
147
    switch (s->current_direction) {
148
    case 0:
149
        break;
150
    case 1:
151
        s->current = s->otp;
152
        break;
153
    case 2:
154
        s->current = s->image;
155
        break;
156
    default:
157
        return -1;
158
    }
159
    onenand_intr_update(s);
160
    return 0;
161
}
162

    
163
static const VMStateDescription vmstate_onenand = {
164
    .name = "onenand",
165
    .version_id = 1,
166
    .minimum_version_id = 1,
167
    .minimum_version_id_old = 1,
168
    .pre_save = onenand_pre_save,
169
    .post_load = onenand_post_load,
170
    .fields = (VMStateField[]) {
171
        VMSTATE_UINT8(current_direction, OneNANDState),
172
        VMSTATE_INT32(cycle, OneNANDState),
173
        VMSTATE_INT32(otpmode, OneNANDState),
174
        VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8),
175
        VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8),
176
        VMSTATE_INT32(bufaddr, OneNANDState),
177
        VMSTATE_INT32(count, OneNANDState),
178
        VMSTATE_UINT16(command, OneNANDState),
179
        VMSTATE_UINT16_ARRAY(config, OneNANDState, 2),
180
        VMSTATE_UINT16(status, OneNANDState),
181
        VMSTATE_UINT16(intstatus, OneNANDState),
182
        VMSTATE_UINT16(wpstatus, OneNANDState),
183
        VMSTATE_INT32(secs_cur, OneNANDState),
184
        VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks),
185
        VMSTATE_UINT8(ecc.cp, OneNANDState),
186
        VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
187
        VMSTATE_UINT16(ecc.count, OneNANDState),
188
        VMSTATE_BUFFER_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) < 0) {
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, hwaddr 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, hwaddr 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 = (hwaddr)-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)