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@sigsegv.be> (cleanup) and me (orig).
This commit is contained in:
parent
1b45c6cd53
commit
c3c04faa3a
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user