diff options
-rw-r--r-- | sys/dev/nand/nand.c | 2 | ||||
-rw-r--r-- | sys/dev/nand/nand.h | 16 | ||||
-rw-r--r-- | 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..62c61610 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); } |