Statistics
| Branch: | Revision:

root / hw / block / onenand.c @ 7162bdea

History | View | Annotate | Download (24.8 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/hw.h"
23
#include "hw/block/flash.h"
24
#include "hw/irq.h"
25
#include "sysemu/blockdev.h"
26
#include "exec/memory.h"
27
#include "exec/address-spaces.h"
28
#include "hw/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, OBJECT(s), "onenand",
117
                       0x10000 << s->shift);
118
    memory_region_add_subregion(&s->container, 0, &s->iomem);
119
    memory_region_init_alias(&s->mapped_ram, OBJECT(s), "onenand-mapped-ram",
120
                             &s->ram, 0x0200 << s->shift,
121
                             0xbe00 << s->shift);
122
    memory_region_add_subregion_overlap(&s->container,
123
                                        0x0200 << s->shift,
124
                                        &s->mapped_ram,
125
                                        1);
126
}
127

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

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

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

    
164
static const VMStateDescription vmstate_onenand = {
165
    .name = "onenand",
166
    .version_id = 1,
167
    .minimum_version_id = 1,
168
    .minimum_version_id_old = 1,
169
    .pre_save = onenand_pre_save,
170
    .post_load = onenand_post_load,
171
    .fields = (VMStateField[]) {
172
        VMSTATE_UINT8(current_direction, OneNANDState),
173
        VMSTATE_INT32(cycle, OneNANDState),
174
        VMSTATE_INT32(otpmode, OneNANDState),
175
        VMSTATE_UINT16_ARRAY(addr, OneNANDState, 8),
176
        VMSTATE_UINT16_ARRAY(unladdr, OneNANDState, 8),
177
        VMSTATE_INT32(bufaddr, OneNANDState),
178
        VMSTATE_INT32(count, OneNANDState),
179
        VMSTATE_UINT16(command, OneNANDState),
180
        VMSTATE_UINT16_ARRAY(config, OneNANDState, 2),
181
        VMSTATE_UINT16(status, OneNANDState),
182
        VMSTATE_UINT16(intstatus, OneNANDState),
183
        VMSTATE_UINT16(wpstatus, OneNANDState),
184
        VMSTATE_INT32(secs_cur, OneNANDState),
185
        VMSTATE_PARTIAL_VBUFFER(blockwp, OneNANDState, blocks),
186
        VMSTATE_UINT8(ecc.cp, OneNANDState),
187
        VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2),
188
        VMSTATE_UINT16(ecc.count, OneNANDState),
189
        VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0,
190
            ((64 + 2) << PAGE_SHIFT)),
191
        VMSTATE_END_OF_LIST()
192
    }
193
};
194

    
195
/* Hot reset (Reset OneNAND command) or warm reset (RP pin low) */
196
static void onenand_reset(OneNANDState *s, int cold)
197
{
198
    memset(&s->addr, 0, sizeof(s->addr));
199
    s->command = 0;
200
    s->count = 1;
201
    s->bufaddr = 0;
202
    s->config[0] = 0x40c0;
203
    s->config[1] = 0x0000;
204
    onenand_intr_update(s);
205
    qemu_irq_raise(s->rdy);
206
    s->status = 0x0000;
207
    s->intstatus = cold ? 0x8080 : 0x8010;
208
    s->unladdr[0] = 0;
209
    s->unladdr[1] = 0;
210
    s->wpstatus = 0x0002;
211
    s->cycle = 0;
212
    s->otpmode = 0;
213
    s->bdrv_cur = s->bdrv;
214
    s->current = s->image;
215
    s->secs_cur = s->secs;
216

    
217
    if (cold) {
218
        /* Lock the whole flash */
219
        memset(s->blockwp, ONEN_LOCK_LOCKED, s->blocks);
220

    
221
        if (s->bdrv_cur && bdrv_read(s->bdrv_cur, 0, s->boot[0], 8) < 0) {
222
            hw_error("%s: Loading the BootRAM failed.\n", __func__);
223
        }
224
    }
225
}
226

    
227
static void onenand_system_reset(DeviceState *dev)
228
{
229
    onenand_reset(FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(dev)), 1);
230
}
231

    
232
static inline int onenand_load_main(OneNANDState *s, int sec, int secn,
233
                void *dest)
234
{
235
    if (s->bdrv_cur)
236
        return bdrv_read(s->bdrv_cur, sec, dest, secn) < 0;
237
    else if (sec + secn > s->secs_cur)
238
        return 1;
239

    
240
    memcpy(dest, s->current + (sec << 9), secn << 9);
241

    
242
    return 0;
243
}
244

    
245
static inline int onenand_prog_main(OneNANDState *s, int sec, int secn,
246
                void *src)
247
{
248
    int result = 0;
249

    
250
    if (secn > 0) {
251
        uint32_t size = (uint32_t)secn * 512;
252
        const uint8_t *sp = (const uint8_t *)src;
253
        uint8_t *dp = 0;
254
        if (s->bdrv_cur) {
255
            dp = g_malloc(size);
256
            if (!dp || bdrv_read(s->bdrv_cur, sec, dp, secn) < 0) {
257
                result = 1;
258
            }
259
        } else {
260
            if (sec + secn > s->secs_cur) {
261
                result = 1;
262
            } else {
263
                dp = (uint8_t *)s->current + (sec << 9);
264
            }
265
        }
266
        if (!result) {
267
            uint32_t i;
268
            for (i = 0; i < size; i++) {
269
                dp[i] &= sp[i];
270
            }
271
            if (s->bdrv_cur) {
272
                result = bdrv_write(s->bdrv_cur, sec, dp, secn) < 0;
273
            }
274
        }
275
        if (dp && s->bdrv_cur) {
276
            g_free(dp);
277
        }
278
    }
279

    
280
    return result;
281
}
282

    
283
static inline int onenand_load_spare(OneNANDState *s, int sec, int secn,
284
                void *dest)
285
{
286
    uint8_t buf[512];
287

    
288
    if (s->bdrv_cur) {
289
        if (bdrv_read(s->bdrv_cur, s->secs_cur + (sec >> 5), buf, 1) < 0)
290
            return 1;
291
        memcpy(dest, buf + ((sec & 31) << 4), secn << 4);
292
    } else if (sec + secn > s->secs_cur)
293
        return 1;
294
    else
295
        memcpy(dest, s->current + (s->secs_cur << 9) + (sec << 4), secn << 4);
296
 
297
    return 0;
298
}
299

    
300
static inline int onenand_prog_spare(OneNANDState *s, int sec, int secn,
301
                void *src)
302
{
303
    int result = 0;
304
    if (secn > 0) {
305
        const uint8_t *sp = (const uint8_t *)src;
306
        uint8_t *dp = 0, *dpp = 0;
307
        if (s->bdrv_cur) {
308
            dp = g_malloc(512);
309
            if (!dp || bdrv_read(s->bdrv_cur,
310
                                 s->secs_cur + (sec >> 5),
311
                                 dp, 1) < 0) {
312
                result = 1;
313
            } else {
314
                dpp = dp + ((sec & 31) << 4);
315
            }
316
        } else {
317
            if (sec + secn > s->secs_cur) {
318
                result = 1;
319
            } else {
320
                dpp = s->current + (s->secs_cur << 9) + (sec << 4);
321
            }
322
        }
323
        if (!result) {
324
            uint32_t i;
325
            for (i = 0; i < (secn << 4); i++) {
326
                dpp[i] &= sp[i];
327
            }
328
            if (s->bdrv_cur) {
329
                result = bdrv_write(s->bdrv_cur, s->secs_cur + (sec >> 5),
330
                                    dp, 1) < 0;
331
            }
332
        }
333
        if (dp) {
334
            g_free(dp);
335
        }
336
    }
337
    return result;
338
}
339

    
340
static inline int onenand_erase(OneNANDState *s, int sec, int num)
341
{
342
    uint8_t *blankbuf, *tmpbuf;
343
    blankbuf = g_malloc(512);
344
    if (!blankbuf) {
345
        return 1;
346
    }
347
    tmpbuf = g_malloc(512);
348
    if (!tmpbuf) {
349
        g_free(blankbuf);
350
        return 1;
351
    }
352
    memset(blankbuf, 0xff, 512);
353
    for (; num > 0; num--, sec++) {
354
        if (s->bdrv_cur) {
355
            int erasesec = s->secs_cur + (sec >> 5);
356
            if (bdrv_write(s->bdrv_cur, sec, blankbuf, 1) < 0) {
357
                goto fail;
358
            }
359
            if (bdrv_read(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
360
                goto fail;
361
            }
362
            memcpy(tmpbuf + ((sec & 31) << 4), blankbuf, 1 << 4);
363
            if (bdrv_write(s->bdrv_cur, erasesec, tmpbuf, 1) < 0) {
364
                goto fail;
365
            }
366
        } else {
367
            if (sec + 1 > s->secs_cur) {
368
                goto fail;
369
            }
370
            memcpy(s->current + (sec << 9), blankbuf, 512);
371
            memcpy(s->current + (s->secs_cur << 9) + (sec << 4),
372
                   blankbuf, 1 << 4);
373
        }
374
    }
375

    
376
    g_free(tmpbuf);
377
    g_free(blankbuf);
378
    return 0;
379

    
380
fail:
381
    g_free(tmpbuf);
382
    g_free(blankbuf);
383
    return 1;
384
}
385

    
386
static void onenand_command(OneNANDState *s)
387
{
388
    int b;
389
    int sec;
390
    void *buf;
391
#define SETADDR(block, page)                        \
392
    sec = (s->addr[page] & 3) +                        \
393
            ((((s->addr[page] >> 2) & 0x3f) +        \
394
              (((s->addr[block] & 0xfff) |        \
395
                (s->addr[block] >> 15 ?                \
396
                 s->density_mask : 0)) << 6)) << (PAGE_SHIFT - 9));
397
#define SETBUF_M()                                \
398
    buf = (s->bufaddr & 8) ?                        \
399
            s->data[(s->bufaddr >> 2) & 1][0] : s->boot[0];        \
400
    buf += (s->bufaddr & 3) << 9;
401
#define SETBUF_S()                                \
402
    buf = (s->bufaddr & 8) ?                        \
403
            s->data[(s->bufaddr >> 2) & 1][1] : s->boot[1];        \
404
    buf += (s->bufaddr & 3) << 4;
405

    
406
    switch (s->command) {
407
    case 0x00:        /* Load single/multiple sector data unit into buffer */
408
        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
409

    
410
        SETBUF_M()
411
        if (onenand_load_main(s, sec, s->count, buf))
412
            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
413

    
414
#if 0
415
        SETBUF_S()
416
        if (onenand_load_spare(s, sec, s->count, buf))
417
            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
418
#endif
419

    
420
        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
421
         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
422
         * then we need two split the read/write into two chunks.
423
         */
424
        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
425
        break;
426
    case 0x13:        /* Load single/multiple spare sector into buffer */
427
        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
428

    
429
        SETBUF_S()
430
        if (onenand_load_spare(s, sec, s->count, buf))
431
            s->status |= ONEN_ERR_CMD | ONEN_ERR_LOAD;
432

    
433
        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
434
         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
435
         * then we need two split the read/write into two chunks.
436
         */
437
        s->intstatus |= ONEN_INT | ONEN_INT_LOAD;
438
        break;
439
    case 0x80:        /* Program single/multiple sector data unit from buffer */
440
        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
441

    
442
        SETBUF_M()
443
        if (onenand_prog_main(s, sec, s->count, buf))
444
            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
445

    
446
#if 0
447
        SETBUF_S()
448
        if (onenand_prog_spare(s, sec, s->count, buf))
449
            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
450
#endif
451

    
452
        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
453
         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
454
         * then we need two split the read/write into two chunks.
455
         */
456
        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
457
        break;
458
    case 0x1a:        /* Program single/multiple spare area sector from buffer */
459
        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
460

    
461
        SETBUF_S()
462
        if (onenand_prog_spare(s, sec, s->count, buf))
463
            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
464

    
465
        /* TODO: if (s->bufaddr & 3) + s->count was > 4 (2k-pages)
466
         * or    if (s->bufaddr & 1) + s->count was > 2 (1k-pages)
467
         * then we need two split the read/write into two chunks.
468
         */
469
        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
470
        break;
471
    case 0x1b:        /* Copy-back program */
472
        SETBUF_S()
473

    
474
        SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
475
        if (onenand_load_main(s, sec, s->count, buf))
476
            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
477

    
478
        SETADDR(ONEN_BUF_DEST_BLOCK, ONEN_BUF_DEST_PAGE)
479
        if (onenand_prog_main(s, sec, s->count, buf))
480
            s->status |= ONEN_ERR_CMD | ONEN_ERR_PROG;
481

    
482
        /* TODO: spare areas */
483

    
484
        s->intstatus |= ONEN_INT | ONEN_INT_PROG;
485
        break;
486

    
487
    case 0x23:        /* Unlock NAND array block(s) */
488
        s->intstatus |= ONEN_INT;
489

    
490
        /* XXX the previous (?) area should be locked automatically */
491
        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
492
            if (b >= s->blocks) {
493
                s->status |= ONEN_ERR_CMD;
494
                break;
495
            }
496
            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
497
                break;
498

    
499
            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
500
        }
501
        break;
502
    case 0x27:        /* Unlock All NAND array blocks */
503
        s->intstatus |= ONEN_INT;
504

    
505
        for (b = 0; b < s->blocks; b ++) {
506
            if (b >= s->blocks) {
507
                s->status |= ONEN_ERR_CMD;
508
                break;
509
            }
510
            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
511
                break;
512

    
513
            s->wpstatus = s->blockwp[b] = ONEN_LOCK_UNLOCKED;
514
        }
515
        break;
516

    
517
    case 0x2a:        /* Lock NAND array block(s) */
518
        s->intstatus |= ONEN_INT;
519

    
520
        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
521
            if (b >= s->blocks) {
522
                s->status |= ONEN_ERR_CMD;
523
                break;
524
            }
525
            if (s->blockwp[b] == ONEN_LOCK_LOCKTIGHTEN)
526
                break;
527

    
528
            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKED;
529
        }
530
        break;
531
    case 0x2c:        /* Lock-tight NAND array block(s) */
532
        s->intstatus |= ONEN_INT;
533

    
534
        for (b = s->unladdr[0]; b <= s->unladdr[1]; b ++) {
535
            if (b >= s->blocks) {
536
                s->status |= ONEN_ERR_CMD;
537
                break;
538
            }
539
            if (s->blockwp[b] == ONEN_LOCK_UNLOCKED)
540
                continue;
541

    
542
            s->wpstatus = s->blockwp[b] = ONEN_LOCK_LOCKTIGHTEN;
543
        }
544
        break;
545

    
546
    case 0x71:        /* Erase-Verify-Read */
547
        s->intstatus |= ONEN_INT;
548
        break;
549
    case 0x95:        /* Multi-block erase */
550
        qemu_irq_pulse(s->intr);
551
        /* Fall through.  */
552
    case 0x94:        /* Block erase */
553
        sec = ((s->addr[ONEN_BUF_BLOCK] & 0xfff) |
554
                        (s->addr[ONEN_BUF_BLOCK] >> 15 ? s->density_mask : 0))
555
                << (BLOCK_SHIFT - 9);
556
        if (onenand_erase(s, sec, 1 << (BLOCK_SHIFT - 9)))
557
            s->status |= ONEN_ERR_CMD | ONEN_ERR_ERASE;
558

    
559
        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
560
        break;
561
    case 0xb0:        /* Erase suspend */
562
        break;
563
    case 0x30:        /* Erase resume */
564
        s->intstatus |= ONEN_INT | ONEN_INT_ERASE;
565
        break;
566

    
567
    case 0xf0:        /* Reset NAND Flash core */
568
        onenand_reset(s, 0);
569
        break;
570
    case 0xf3:        /* Reset OneNAND */
571
        onenand_reset(s, 0);
572
        break;
573

    
574
    case 0x65:        /* OTP Access */
575
        s->intstatus |= ONEN_INT;
576
        s->bdrv_cur = NULL;
577
        s->current = s->otp;
578
        s->secs_cur = 1 << (BLOCK_SHIFT - 9);
579
        s->addr[ONEN_BUF_BLOCK] = 0;
580
        s->otpmode = 1;
581
        break;
582

    
583
    default:
584
        s->status |= ONEN_ERR_CMD;
585
        s->intstatus |= ONEN_INT;
586
        fprintf(stderr, "%s: unknown OneNAND command %x\n",
587
                        __func__, s->command);
588
    }
589

    
590
    onenand_intr_update(s);
591
}
592

    
593
static uint64_t onenand_read(void *opaque, hwaddr addr,
594
                             unsigned size)
595
{
596
    OneNANDState *s = (OneNANDState *) opaque;
597
    int offset = addr >> s->shift;
598

    
599
    switch (offset) {
600
    case 0x0000 ... 0xc000:
601
        return lduw_le_p(s->boot[0] + addr);
602

    
603
    case 0xf000:        /* Manufacturer ID */
604
        return s->id.man;
605
    case 0xf001:        /* Device ID */
606
        return s->id.dev;
607
    case 0xf002:        /* Version ID */
608
        return s->id.ver;
609
    /* TODO: get the following values from a real chip!  */
610
    case 0xf003:        /* Data Buffer size */
611
        return 1 << PAGE_SHIFT;
612
    case 0xf004:        /* Boot Buffer size */
613
        return 0x200;
614
    case 0xf005:        /* Amount of buffers */
615
        return 1 | (2 << 8);
616
    case 0xf006:        /* Technology */
617
        return 0;
618

    
619
    case 0xf100 ... 0xf107:        /* Start addresses */
620
        return s->addr[offset - 0xf100];
621

    
622
    case 0xf200:        /* Start buffer */
623
        return (s->bufaddr << 8) | ((s->count - 1) & (1 << (PAGE_SHIFT - 10)));
624

    
625
    case 0xf220:        /* Command */
626
        return s->command;
627
    case 0xf221:        /* System Configuration 1 */
628
        return s->config[0] & 0xffe0;
629
    case 0xf222:        /* System Configuration 2 */
630
        return s->config[1];
631

    
632
    case 0xf240:        /* Controller Status */
633
        return s->status;
634
    case 0xf241:        /* Interrupt */
635
        return s->intstatus;
636
    case 0xf24c:        /* Unlock Start Block Address */
637
        return s->unladdr[0];
638
    case 0xf24d:        /* Unlock End Block Address */
639
        return s->unladdr[1];
640
    case 0xf24e:        /* Write Protection Status */
641
        return s->wpstatus;
642

    
643
    case 0xff00:        /* ECC Status */
644
        return 0x00;
645
    case 0xff01:        /* ECC Result of main area data */
646
    case 0xff02:        /* ECC Result of spare area data */
647
    case 0xff03:        /* ECC Result of main area data */
648
    case 0xff04:        /* ECC Result of spare area data */
649
        hw_error("%s: imeplement ECC\n", __FUNCTION__);
650
        return 0x0000;
651
    }
652

    
653
    fprintf(stderr, "%s: unknown OneNAND register %x\n",
654
                    __FUNCTION__, offset);
655
    return 0;
656
}
657

    
658
static void onenand_write(void *opaque, hwaddr addr,
659
                          uint64_t value, unsigned size)
660
{
661
    OneNANDState *s = (OneNANDState *) opaque;
662
    int offset = addr >> s->shift;
663
    int sec;
664

    
665
    switch (offset) {
666
    case 0x0000 ... 0x01ff:
667
    case 0x8000 ... 0x800f:
668
        if (s->cycle) {
669
            s->cycle = 0;
670

    
671
            if (value == 0x0000) {
672
                SETADDR(ONEN_BUF_BLOCK, ONEN_BUF_PAGE)
673
                onenand_load_main(s, sec,
674
                                1 << (PAGE_SHIFT - 9), s->data[0][0]);
675
                s->addr[ONEN_BUF_PAGE] += 4;
676
                s->addr[ONEN_BUF_PAGE] &= 0xff;
677
            }
678
            break;
679
        }
680

    
681
        switch (value) {
682
        case 0x00f0:        /* Reset OneNAND */
683
            onenand_reset(s, 0);
684
            break;
685

    
686
        case 0x00e0:        /* Load Data into Buffer */
687
            s->cycle = 1;
688
            break;
689

    
690
        case 0x0090:        /* Read Identification Data */
691
            memset(s->boot[0], 0, 3 << s->shift);
692
            s->boot[0][0 << s->shift] = s->id.man & 0xff;
693
            s->boot[0][1 << s->shift] = s->id.dev & 0xff;
694
            s->boot[0][2 << s->shift] = s->wpstatus & 0xff;
695
            break;
696

    
697
        default:
698
            fprintf(stderr, "%s: unknown OneNAND boot command %"PRIx64"\n",
699
                            __FUNCTION__, value);
700
        }
701
        break;
702

    
703
    case 0xf100 ... 0xf107:        /* Start addresses */
704
        s->addr[offset - 0xf100] = value;
705
        break;
706

    
707
    case 0xf200:        /* Start buffer */
708
        s->bufaddr = (value >> 8) & 0xf;
709
        if (PAGE_SHIFT == 11)
710
            s->count = (value & 3) ?: 4;
711
        else if (PAGE_SHIFT == 10)
712
            s->count = (value & 1) ?: 2;
713
        break;
714

    
715
    case 0xf220:        /* Command */
716
        if (s->intstatus & (1 << 15))
717
            break;
718
        s->command = value;
719
        onenand_command(s);
720
        break;
721
    case 0xf221:        /* System Configuration 1 */
722
        s->config[0] = value;
723
        onenand_intr_update(s);
724
        qemu_set_irq(s->rdy, (s->config[0] >> 7) & 1);
725
        break;
726
    case 0xf222:        /* System Configuration 2 */
727
        s->config[1] = value;
728
        break;
729

    
730
    case 0xf241:        /* Interrupt */
731
        s->intstatus &= value;
732
        if ((1 << 15) & ~s->intstatus)
733
            s->status &= ~(ONEN_ERR_CMD | ONEN_ERR_ERASE |
734
                            ONEN_ERR_PROG | ONEN_ERR_LOAD);
735
        onenand_intr_update(s);
736
        break;
737
    case 0xf24c:        /* Unlock Start Block Address */
738
        s->unladdr[0] = value & (s->blocks - 1);
739
        /* For some reason we have to set the end address to by default
740
         * be same as start because the software forgets to write anything
741
         * in there.  */
742
        s->unladdr[1] = value & (s->blocks - 1);
743
        break;
744
    case 0xf24d:        /* Unlock End Block Address */
745
        s->unladdr[1] = value & (s->blocks - 1);
746
        break;
747

    
748
    default:
749
        fprintf(stderr, "%s: unknown OneNAND register %x\n",
750
                        __FUNCTION__, offset);
751
    }
752
}
753

    
754
static const MemoryRegionOps onenand_ops = {
755
    .read = onenand_read,
756
    .write = onenand_write,
757
    .endianness = DEVICE_NATIVE_ENDIAN,
758
};
759

    
760
static int onenand_initfn(SysBusDevice *dev)
761
{
762
    OneNANDState *s = (OneNANDState *)dev;
763
    uint32_t size = 1 << (24 + ((s->id.dev >> 4) & 7));
764
    void *ram;
765
    s->base = (hwaddr)-1;
766
    s->rdy = NULL;
767
    s->blocks = size >> BLOCK_SHIFT;
768
    s->secs = size >> 9;
769
    s->blockwp = g_malloc(s->blocks);
770
    s->density_mask = (s->id.dev & 0x08)
771
        ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0;
772
    memory_region_init_io(&s->iomem, OBJECT(s), &onenand_ops, s, "onenand",
773
                          0x10000 << s->shift);
774
    if (!s->bdrv) {
775
        s->image = memset(g_malloc(size + (size >> 5)),
776
                          0xff, size + (size >> 5));
777
    } else {
778
        if (bdrv_is_read_only(s->bdrv)) {
779
            error_report("Can't use a read-only drive");
780
            return -1;
781
        }
782
        s->bdrv_cur = s->bdrv;
783
    }
784
    s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
785
                    0xff, (64 + 2) << PAGE_SHIFT);
786
    memory_region_init_ram(&s->ram, OBJECT(s), "onenand.ram",
787
                           0xc000 << s->shift);
788
    vmstate_register_ram_global(&s->ram);
789
    ram = memory_region_get_ram_ptr(&s->ram);
790
    s->boot[0] = ram + (0x0000 << s->shift);
791
    s->boot[1] = ram + (0x8000 << s->shift);
792
    s->data[0][0] = ram + ((0x0200 + (0 << (PAGE_SHIFT - 1))) << s->shift);
793
    s->data[0][1] = ram + ((0x8010 + (0 << (PAGE_SHIFT - 6))) << s->shift);
794
    s->data[1][0] = ram + ((0x0200 + (1 << (PAGE_SHIFT - 1))) << s->shift);
795
    s->data[1][1] = ram + ((0x8010 + (1 << (PAGE_SHIFT - 6))) << s->shift);
796
    onenand_mem_setup(s);
797
    sysbus_init_irq(dev, &s->intr);
798
    sysbus_init_mmio(dev, &s->container);
799
    vmstate_register(&dev->qdev,
800
                     ((s->shift & 0x7f) << 24)
801
                     | ((s->id.man & 0xff) << 16)
802
                     | ((s->id.dev & 0xff) << 8)
803
                     | (s->id.ver & 0xff),
804
                     &vmstate_onenand, s);
805
    return 0;
806
}
807

    
808
static Property onenand_properties[] = {
809
    DEFINE_PROP_UINT16("manufacturer_id", OneNANDState, id.man, 0),
810
    DEFINE_PROP_UINT16("device_id", OneNANDState, id.dev, 0),
811
    DEFINE_PROP_UINT16("version_id", OneNANDState, id.ver, 0),
812
    DEFINE_PROP_INT32("shift", OneNANDState, shift, 0),
813
    DEFINE_PROP_DRIVE("drive", OneNANDState, bdrv),
814
    DEFINE_PROP_END_OF_LIST(),
815
};
816

    
817
static void onenand_class_init(ObjectClass *klass, void *data)
818
{
819
    DeviceClass *dc = DEVICE_CLASS(klass);
820
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
821

    
822
    k->init = onenand_initfn;
823
    dc->reset = onenand_system_reset;
824
    dc->props = onenand_properties;
825
}
826

    
827
static const TypeInfo onenand_info = {
828
    .name          = "onenand",
829
    .parent        = TYPE_SYS_BUS_DEVICE,
830
    .instance_size = sizeof(OneNANDState),
831
    .class_init    = onenand_class_init,
832
};
833

    
834
static void onenand_register_types(void)
835
{
836
    type_register_static(&onenand_info);
837
}
838

    
839
void *onenand_raw_otp(DeviceState *onenand_device)
840
{
841
    return FROM_SYSBUS(OneNANDState, SYS_BUS_DEVICE(onenand_device))->otp;
842
}
843

    
844
type_init(onenand_register_types)