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