From owner-freebsd-embedded@FreeBSD.ORG Wed Nov 13 22:32:45 2013 Return-Path: Delivered-To: freebsd-embedded@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id C7C5F4D1; Wed, 13 Nov 2013 22:32:45 +0000 (UTC) Received: from venus.codepro.be (venus.codepro.be [IPv6:2a01:4f8:162:1127::2]) (using TLSv1 with cipher ADH-CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 5725225CC; Wed, 13 Nov 2013 22:32:45 +0000 (UTC) Received: from adrastea.jupiter.sigsegv.be (unknown [IPv6:2a02:1811:2000:701:1b:9fff:fe00:160b]) by venus.codepro.be (Postfix) with ESMTPSA id D567F9B2D; Wed, 13 Nov 2013 23:32:43 +0100 (CET) Received: from sigsegv.be (unknown [10.0.2.251]) by adrastea.jupiter.sigsegv.be (Postfix) with ESMTP id 132934162; Wed, 13 Nov 2013 23:32:43 +0100 (CET) From: kristof@sigsegv.be To: Ian Lepore Subject: [PATCH 4/5] Unpack (align) and decode (endian) the values in the onfi_params struct. Date: Wed, 13 Nov 2013 23:32:39 +0100 Message-Id: <1384381960-98851-5-git-send-email-kristof@sigsegv.be> X-Mailer: git-send-email 1.7.10.3 In-Reply-To: <1384381960-98851-1-git-send-email-kristof@sigsegv.be> References: <1383782353.31172.183.camel@revolution.hippie.lan> <1384381960-98851-1-git-send-email-kristof@sigsegv.be> Cc: Grzegorz Bernacki , freebsd-embedded@FreeBSD.org X-BeenThere: freebsd-embedded@freebsd.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: Dedicated and Embedded Systems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 13 Nov 2013 22:32:45 -0000 From: Kristof Provost ONFI parameters are little-endian, hence we must take care to convert them to native endianness. We must also pay attention to unalligned accesses. Copy the interesting parameters to a new struct so the rest of the code can forget about these problems. --- sys/dev/nand/nand.c | 2 +- sys/dev/nand/nand.h | 16 +++++++++++++- sys/dev/nand/nand_generic.c | 51 +++++++++++++++++++++++++++---------------- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/sys/dev/nand/nand.c b/sys/dev/nand/nand.c index f46d0f0..902ff79 100644 --- a/sys/dev/nand/nand.c +++ b/sys/dev/nand/nand.c @@ -115,7 +115,7 @@ nand_init(struct nand_softc *nand, device_t dev, int ecc_mode, } void -nand_onfi_set_params(struct nand_chip *chip, struct onfi_params *params) +nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params) { struct chip_geom *cg; diff --git a/sys/dev/nand/nand.h b/sys/dev/nand/nand.h index d9bfad7..4fbe75c 100644 --- a/sys/dev/nand/nand.h +++ b/sys/dev/nand/nand.h @@ -235,6 +235,20 @@ struct onfi_params { }__attribute__((packed)); CTASSERT(sizeof(struct onfi_params) == 256); +struct onfi_chip_params { + uint8_t luns; + uint32_t blocks_per_lun; + uint32_t pages_per_block; + uint32_t bytes_per_page; + uint32_t spare_bytes_per_page; + uint16_t t_bers; + uint16_t t_prog; + uint16_t t_r; + uint16_t t_ccs; + uint16_t features; + uint8_t address_cycles; +}; + struct nand_ecc_data { int eccsize; /* Number of data bytes per ECC step */ int eccmode; @@ -367,7 +381,7 @@ void nand_init(struct nand_softc *nand, device_t dev, int ecc_mode, void nand_detach(struct nand_softc *nand); struct nand_params *nand_get_params(struct nand_id *id); -void nand_onfi_set_params(struct nand_chip *chip, struct onfi_params *params); +void nand_onfi_set_params(struct nand_chip *chip, struct onfi_chip_params *params); void nand_set_params(struct nand_chip *chip, struct nand_params *params); int nand_init_stat(struct nand_chip *chip); void nand_destroy_stat(struct nand_chip *chip); diff --git a/sys/dev/nand/nand_generic.c b/sys/dev/nand/nand_generic.c index 4ee8fdc..62c6161 100644 --- a/sys/dev/nand/nand_generic.c +++ b/sys/dev/nand/nand_generic.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -73,7 +74,7 @@ static int small_program_page(device_t, uint32_t, void *, uint32_t, uint32_t); static int small_program_oob(device_t, uint32_t, void *, uint32_t, uint32_t); static int onfi_is_blk_bad(device_t, uint32_t, uint8_t *); -static int onfi_read_parameter(struct nand_chip *, struct onfi_params *); +static int onfi_read_parameter(struct nand_chip *, struct onfi_chip_params *); static int nand_send_address(device_t, int32_t, int32_t, int8_t); @@ -206,7 +207,7 @@ generic_nand_attach(device_t dev) { struct nand_chip *chip; struct nandbus_ivar *ivar; - struct onfi_params *onfi_params; + struct onfi_chip_params *onfi_chip_params; device_t nandbus, nfc; int err; @@ -225,25 +226,24 @@ generic_nand_attach(device_t dev) chip->nand = device_get_softc(nfc); if (ivar->is_onfi) { - onfi_params = malloc(sizeof(struct onfi_params), + onfi_chip_params = malloc(sizeof(struct onfi_chip_params), M_NAND, M_WAITOK | M_ZERO); - if (onfi_params == NULL) - return (ENXIO); + if (onfi_chip_params == NULL) + return (ENOMEM); - if (onfi_read_parameter(chip, onfi_params)) { + if (onfi_read_parameter(chip, onfi_chip_params)) { nand_debug(NDBG_GEN,"Could not read parameter page!\n"); - free(onfi_params, M_NAND); + free(onfi_chip_params, M_NAND); return (ENXIO); } - nand_onfi_set_params(chip, onfi_params); + nand_onfi_set_params(chip, onfi_chip_params); /* Set proper column and row cycles */ - ivar->cols = (onfi_params->address_cycles >> 4) & 0xf; - ivar->rows = onfi_params->address_cycles & 0xf; - free(onfi_params, M_NAND); + ivar->cols = (onfi_chip_params->address_cycles >> 4) & 0xf; + ivar->rows = onfi_chip_params->address_cycles & 0xf; + free(onfi_chip_params, M_NAND); } else { - nand_set_params(chip, ivar->params); } @@ -340,9 +340,10 @@ onfi_crc(const void *buf, size_t buflen) } static int -onfi_read_parameter(struct nand_chip *chip, struct onfi_params *params) +onfi_read_parameter(struct nand_chip *chip, struct onfi_chip_params *chip_params) { device_t nandbus; + struct onfi_params params; int found, sigcount, trycopy; nand_debug(NDBG_GEN,"read parameter"); @@ -373,20 +374,32 @@ onfi_read_parameter(struct nand_chip *chip, struct onfi_params *params) * rule that the signature is valid if any 2 of the 4 bytes are correct. */ for (found= 0, trycopy = 0; !found && trycopy < 3; trycopy++) { - NANDBUS_READ_BUFFER(nandbus, params, sizeof(struct onfi_params)); - sigcount = params->signature[0] == 'O'; - sigcount += params->signature[1] == 'N'; - sigcount += params->signature[2] == 'F'; - sigcount += params->signature[3] == 'I'; + NANDBUS_READ_BUFFER(nandbus, ¶ms, sizeof(struct onfi_params)); + sigcount = params.signature[0] == 'O'; + sigcount += params.signature[1] == 'N'; + sigcount += params.signature[2] == 'F'; + sigcount += params.signature[3] == 'I'; if (sigcount < 2) continue; - if (onfi_crc(params, 254) != params->crc) + if (onfi_crc(¶ms, 254) != params.crc) continue; found = 1; } if (!found) return (ENXIO); + chip_params->luns = params.luns; + chip_params->blocks_per_lun = le32dec(¶ms.blocks_per_lun); + chip_params->pages_per_block = le32dec(¶ms.pages_per_block); + chip_params->bytes_per_page = le32dec(¶ms.bytes_per_page); + chip_params->spare_bytes_per_page = le32dec(¶ms.spare_bytes_per_page); + chip_params->t_bers = le16dec(¶ms.t_bers); + chip_params->t_prog = le16dec(¶ms.t_prog); + chip_params->t_r = le16dec(¶ms.t_r); + chip_params->t_ccs = le16dec(¶ms.t_ccs); + chip_params->features = le16dec(¶ms.features); + chip_params->address_cycles = params.address_cycles; + return (0); } -- 1.7.10.3