svn commit: r258200 - head/sys/dev/nand
Ian Lepore
ian at FreeBSD.org
Fri Nov 15 23:41:33 UTC 2013
Author: ian
Date: Fri Nov 15 23:41:32 2013
New Revision: 258200
URL: http://svnweb.freebsd.org/changeset/base/258200
Log:
ONFI parameters are little-endian, hence we must take care to convert them
to native endianness. We must also pay attention to unaligned accesses.
Copy the interesting parameters to a new struct so the rest of the code can
forget about these problems.
Submitted by: Kristof Provost <kristof at sigsegv.be> (cleanup) and me (orig).
Modified:
head/sys/dev/nand/nand.c
head/sys/dev/nand/nand.h
head/sys/dev/nand/nand_generic.c
Modified: head/sys/dev/nand/nand.c
==============================================================================
--- head/sys/dev/nand/nand.c Fri Nov 15 23:37:33 2013 (r258199)
+++ head/sys/dev/nand/nand.c Fri Nov 15 23:41:32 2013 (r258200)
@@ -115,7 +115,7 @@ nand_init(struct nand_softc *nand, devic
}
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;
Modified: head/sys/dev/nand/nand.h
==============================================================================
--- head/sys/dev/nand/nand.h Fri Nov 15 23:37:33 2013 (r258199)
+++ head/sys/dev/nand/nand.h Fri Nov 15 23:41:32 2013 (r258200)
@@ -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,
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);
Modified: head/sys/dev/nand/nand_generic.c
==============================================================================
--- head/sys/dev/nand/nand_generic.c Fri Nov 15 23:37:33 2013 (r258199)
+++ head/sys/dev/nand/nand_generic.c Fri Nov 15 23:41:32 2013 (r258200)
@@ -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,
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 *ch
* 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);
}
More information about the svn-src-head
mailing list