From patchwork Fri Jul 15 14:58:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 2728 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 480A123F42 for ; Fri, 15 Jul 2011 15:26:52 +0000 (UTC) Received: from mail-qy0-f173.google.com (mail-qy0-f173.google.com [209.85.216.173]) by fiordland.canonical.com (Postfix) with ESMTP id EDAB3A18493 for ; Fri, 15 Jul 2011 15:26:51 +0000 (UTC) Received: by mail-qy0-f173.google.com with SMTP id 10so558872qyk.11 for ; Fri, 15 Jul 2011 08:26:51 -0700 (PDT) Received: by 10.229.217.3 with SMTP id hk3mr3090437qcb.38.1310743611665; Fri, 15 Jul 2011 08:26:51 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.229.217.78 with SMTP id hl14cs51265qcb; Fri, 15 Jul 2011 08:26:50 -0700 (PDT) Received: by 10.216.60.17 with SMTP id t17mr3252341wec.29.1310743610094; Fri, 15 Jul 2011 08:26:50 -0700 (PDT) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk [81.2.115.146]) by mx.google.com with ESMTPS id s13si2874560wec.139.2011.07.15.08.26.49 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 15 Jul 2011 08:26:49 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) client-ip=81.2.115.146; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 81.2.115.146 as permitted sender) smtp.mail=pm215@archaic.org.uk Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.72) (envelope-from ) id 1QhjqU-0000QX-J3; Fri, 15 Jul 2011 15:58:26 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Riku Voipio , =?UTF-8?q?Juha=20Riihim=C3=A4ki?= , andrzej zaborowski , Markus Armbruster Subject: [PATCH 06/12] hw/nand: qdevify Date: Fri, 15 Jul 2011 15:58:20 +0100 Message-Id: <1310741906-1606-7-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1310741906-1606-1-git-send-email-peter.maydell@linaro.org> References: <1310741906-1606-1-git-send-email-peter.maydell@linaro.org> MIME-Version: 1.0 From: Juha Riihimäki Qdevify the NAND device. Signed-off-by: Juha Riihimäki [Riku Voipio: Fixes and restructuring patchset] Signed-off-by: Riku Voipio [Peter Maydell: More fixes and cleanups for upstream submission] Signed-off-by: Peter Maydell --- hw/axis_dev88.c | 2 +- hw/flash.h | 14 ++--- hw/nand.c | 164 +++++++++++++++++++++++++++++++------------------------ hw/spitz.c | 2 +- hw/tc6393xb.c | 2 +- 5 files changed, 102 insertions(+), 82 deletions(-) diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c index de1f5a5..e0a8c14 100644 --- a/hw/axis_dev88.c +++ b/hw/axis_dev88.c @@ -37,7 +37,7 @@ struct nand_state_t { - NANDFlashState *nand; + DeviceState *nand; unsigned int rdy:1; unsigned int ale:1; unsigned int cle:1; diff --git a/hw/flash.h b/hw/flash.h index 132ad29..43260ce 100644 --- a/hw/flash.h +++ b/hw/flash.h @@ -18,15 +18,13 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base, ram_addr_t off, int be); /* nand.c */ -typedef struct NANDFlashState NANDFlashState; -NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id); -void nand_done(NANDFlashState *s); -void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale, +DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id); +void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale, uint8_t ce, uint8_t wp, uint8_t gnd); -void nand_getpins(NANDFlashState *s, int *rb); -void nand_setio(NANDFlashState *s, uint32_t value); -uint32_t nand_getio(NANDFlashState *s); -uint32_t nand_getbuswidth(NANDFlashState *s); +void nand_getpins(DeviceState *dev, int *rb); +void nand_setio(DeviceState *dev, uint32_t value); +uint32_t nand_getio(DeviceState *dev); +uint32_t nand_getbuswidth(DeviceState *dev); #define NAND_MFR_TOSHIBA 0x98 #define NAND_MFR_SAMSUNG 0xec diff --git a/hw/nand.c b/hw/nand.c index d068eb6..2f5a40e 100644 --- a/hw/nand.c +++ b/hw/nand.c @@ -18,6 +18,7 @@ # include "hw.h" # include "flash.h" # include "blockdev.h" +# include "sysbus.h" # define NAND_CMD_READ0 0x00 # define NAND_CMD_READ1 0x01 @@ -47,7 +48,9 @@ # define MAX_PAGE 0x800 # define MAX_OOB 0x40 +typedef struct NANDFlashState NANDFlashState; struct NANDFlashState { + SysBusDevice busdev; uint8_t manf_id, chip_id; uint8_t buswidth; /* in BYTES */ int size, pages; @@ -215,8 +218,9 @@ static const struct { [0xc5] = { 2048, 16, 0, 0, LP_OPTIONS16 }, }; -static void nand_reset(NANDFlashState *s) +static void nand_reset(DeviceState *dev) { + NANDFlashState *s = FROM_SYSBUS(NANDFlashState, sysbus_from_qdev(dev)); s->cmd = NAND_CMD_READ0; s->addr = 0; s->addrlen = 0; @@ -270,7 +274,7 @@ static void nand_command(NANDFlashState *s) break; case NAND_CMD_RESET: - nand_reset(s); + nand_reset(&s->busdev.qdev); break; case NAND_CMD_PAGEPROGRAM1: @@ -354,15 +358,84 @@ static const VMStateDescription vmstate_nand = { } }; +static int nand_device_init(SysBusDevice *dev) +{ + int pagesize; + NANDFlashState *s = FROM_SYSBUS(NANDFlashState, dev); + s->buswidth = nand_flash_ids[s->chip_id].width >> 3; + s->size = nand_flash_ids[s->chip_id].size << 20; + if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) { + s->page_shift = 11; + s->erase_shift = 6; + } else { + s->page_shift = nand_flash_ids[s->chip_id].page_shift; + s->erase_shift = nand_flash_ids[s->chip_id].erase_shift; + } + + switch (1 << s->page_shift) { + case 256: + nand_init_256(s); + break; + case 512: + nand_init_512(s); + break; + case 2048: + nand_init_2048(s); + break; + default: + hw_error("%s: Unsupported NAND block size.\n", __func__); + } + + pagesize = 1 << s->oob_shift; + s->mem_oob = 1; + if (s->bdrv && bdrv_getlength(s->bdrv) >= + (s->pages << s->page_shift) + (s->pages << s->oob_shift)) { + pagesize = 0; + s->mem_oob = 0; + } + + if (!s->bdrv) { + pagesize += 1 << s->page_shift; + } + if (pagesize) { + s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize), + 0xff, s->pages * pagesize); + } + /* Give s->ioaddr a sane value in case we save state before it is used. */ + s->ioaddr = s->io; + + return 0; +} + +static SysBusDeviceInfo nand_info = { + .init = nand_device_init, + .qdev.name = "nand", + .qdev.size = sizeof(NANDFlashState), + .qdev.reset = nand_reset, + .qdev.vmsd = &vmstate_nand, + .qdev.props = (Property[]) { + DEFINE_PROP_UINT8("manufacturer_id", NANDFlashState, manf_id, 0), + DEFINE_PROP_UINT8("chip_id", NANDFlashState, chip_id, 0), + DEFINE_PROP_DRIVE("drive", NANDFlashState, bdrv), + DEFINE_PROP_END_OF_LIST() + } +}; + +static void nand_create_device(void) +{ + sysbus_register_withprop(&nand_info); +} + /* * Chip inputs are CLE, ALE, CE, WP, GND and eight I/O pins. Chip * outputs are R/B and eight I/O pins. * * CE, WP and R/B are active low. */ -void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale, +void nand_setpins(DeviceState *dev, uint8_t cle, uint8_t ale, uint8_t ce, uint8_t wp, uint8_t gnd) { + NANDFlashState *s = (NANDFlashState *)dev; s->cle = cle; s->ale = ale; s->ce = ce; @@ -374,15 +447,15 @@ void nand_setpins(NANDFlashState *s, uint8_t cle, uint8_t ale, s->status &= ~NAND_IOSTATUS_UNPROTCT; } -void nand_getpins(NANDFlashState *s, int *rb) +void nand_getpins(DeviceState *dev, int *rb) { *rb = 1; } -void nand_setio(NANDFlashState *s, uint32_t value) +void nand_setio(DeviceState *dev, uint32_t value) { int i; - + NANDFlashState *s = (NANDFlashState *)dev; if (!s->ce && s->cle) { if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) { if (s->cmd == NAND_CMD_READ0 && value == NAND_CMD_LPREAD2) @@ -482,10 +555,11 @@ void nand_setio(NANDFlashState *s, uint32_t value) } } -uint32_t nand_getio(NANDFlashState *s) +uint32_t nand_getio(DeviceState *dev) { int offset; uint32_t x = 0; + NANDFlashState *s = (NANDFlashState *)dev; /* Allow sequential reading */ if (!s->iolen && s->cmd == NAND_CMD_READ0) { @@ -516,82 +590,30 @@ uint32_t nand_getio(NANDFlashState *s) return x; } -uint32_t nand_getbuswidth(NANDFlashState *s) +uint32_t nand_getbuswidth(DeviceState *dev) { + NANDFlashState *s = (NANDFlashState *)dev; return s->buswidth << 3; } -NANDFlashState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id) +DeviceState *nand_init(BlockDriverState *bdrv, int manf_id, int chip_id) { - int pagesize; - NANDFlashState *s; - + DeviceState *dev; if (nand_flash_ids[chip_id].size == 0) { hw_error("%s: Unsupported NAND chip ID.\n", __FUNCTION__); } - - s = (NANDFlashState *) qemu_mallocz(sizeof(NANDFlashState)); - s->bdrv = bdrv; - s->manf_id = manf_id; - s->chip_id = chip_id; - s->buswidth = nand_flash_ids[s->chip_id].width >> 3; - s->size = nand_flash_ids[s->chip_id].size << 20; - if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) { - s->page_shift = 11; - s->erase_shift = 6; - } else { - s->page_shift = nand_flash_ids[s->chip_id].page_shift; - s->erase_shift = nand_flash_ids[s->chip_id].erase_shift; + dev = qdev_create(NULL, "nand"); + qdev_prop_set_uint8(dev, "manufacturer_id", manf_id); + qdev_prop_set_uint8(dev, "chip_id", chip_id); + if (bdrv) { + qdev_prop_set_drive_nofail(dev, "drive", bdrv); } - switch (1 << s->page_shift) { - case 256: - nand_init_256(s); - break; - case 512: - nand_init_512(s); - break; - case 2048: - nand_init_2048(s); - break; - default: - hw_error("%s: Unsupported NAND block size.\n", __FUNCTION__); - } - - pagesize = 1 << s->oob_shift; - s->mem_oob = 1; - if (s->bdrv && bdrv_getlength(s->bdrv) >= - (s->pages << s->page_shift) + (s->pages << s->oob_shift)) { - pagesize = 0; - s->mem_oob = 0; - } - - if (!s->bdrv) - pagesize += 1 << s->page_shift; - if (pagesize) - s->storage = (uint8_t *) memset(qemu_malloc(s->pages * pagesize), - 0xff, s->pages * pagesize); - /* Give s->ioaddr a sane value in case we save state before it - is used. */ - s->ioaddr = s->io; - - vmstate_register(NULL, -1, &vmstate_nand, s); - - return s; + qdev_init_nofail(dev); + return dev; } -void nand_done(NANDFlashState *s) -{ - if (s->bdrv) { - bdrv_close(s->bdrv); - bdrv_delete(s->bdrv); - } - - if (!s->bdrv || s->mem_oob) - qemu_free(s->storage); - - qemu_free(s); -} +device_init(nand_create_device) #else diff --git a/hw/spitz.c b/hw/spitz.c index 78e9c34..c05b5f7 100644 --- a/hw/spitz.c +++ b/hw/spitz.c @@ -48,7 +48,7 @@ typedef struct { SysBusDevice busdev; - NANDFlashState *nand; + DeviceState *nand; uint8_t ctl; uint8_t manf_id; uint8_t chip_id; diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c index 4de0819..a1c48bf 100644 --- a/hw/tc6393xb.c +++ b/hw/tc6393xb.c @@ -118,7 +118,7 @@ struct TC6393xbState { } nand; int nand_enable; uint32_t nand_phys; - NANDFlashState *flash; + DeviceState *flash; ECCState ecc; DisplayState *ds;