Date: Wed, 13 Nov 2013 23:32:39 +0100 From: kristof@sigsegv.be To: Ian Lepore <ian@FreeBSD.org> Cc: Grzegorz Bernacki <gber@FreeBSD.org>, freebsd-embedded@FreeBSD.org Subject: [PATCH 4/5] Unpack (align) and decode (endian) the values in the onfi_params struct. Message-ID: <1384381960-98851-5-git-send-email-kristof@sigsegv.be> 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>
next in thread | previous in thread | raw e-mail | index | archive | help
From: Kristof Provost <kristof@sigsegv.be> 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 <sys/proc.h> #include <sys/bus.h> #include <sys/conf.h> +#include <sys/endian.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/rman.h> @@ -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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1384381960-98851-5-git-send-email-kristof>