mtd: rawnand: prepare the removal of the ONFI parameter page

The NAND chip parameter page is statically allocated within the
nand_chip structure, which reserves a lot of space. Even not ONFI nor
JEDEC chips have it embedded. Also, only a few parameters are actually
read from the parameter page after the detection.

ONFI-related parameters that will be used outside from the
identification function are stored in a separate onfi_parameters
structure embedded in nand_parameters, this small structure that
already hold generic parameters.

For now, the onfi_parameters structure is allocated statically. However,
after some deep rework in the NAND framework, it will be possible to do
dynamic allocations from the NAND identification phase, and this
strcuture will then be dynamically allocated when needed.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
This commit is contained in:
Miquel Raynal 2018-03-19 14:47:27 +01:00 коммит произвёл Boris Brezillon
Родитель f4531b2b19
Коммит a97421c753
5 изменённых файлов: 64 добавлений и 46 удалений

Просмотреть файл

@ -971,7 +971,7 @@ int gpmi_extra_init(struct gpmi_nand_data *this)
struct nand_chip *chip = &this->nand;
/* Enable the asynchronous EDO feature. */
if (GPMI_IS_MX6(this) && chip->onfi_version) {
if (GPMI_IS_MX6(this) && chip->parameters.onfi.version) {
int mode = onfi_get_async_timing_mode(chip);
/* We only support the timing mode 4 and mode 5. */

Просмотреть файл

@ -5126,17 +5126,17 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
/* Check version */
val = le16_to_cpu(p->revision);
if (val & (1 << 5))
chip->onfi_version = 23;
chip->parameters.onfi.version = 23;
else if (val & (1 << 4))
chip->onfi_version = 22;
chip->parameters.onfi.version = 22;
else if (val & (1 << 3))
chip->onfi_version = 21;
chip->parameters.onfi.version = 21;
else if (val & (1 << 2))
chip->onfi_version = 20;
chip->parameters.onfi.version = 20;
else if (val & (1 << 1))
chip->onfi_version = 10;
chip->parameters.onfi.version = 10;
if (!chip->onfi_version) {
if (!chip->parameters.onfi.version) {
pr_info("unsupported ONFI version: %d\n", val);
return 0;
}
@ -5166,14 +5166,14 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun);
chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun);
if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
if (le16_to_cpu(p->features) & ONFI_FEATURE_16_BIT_BUS)
chip->options |= NAND_BUSWIDTH_16;
if (p->ecc_bits != 0xff) {
chip->ecc_strength_ds = p->ecc_bits;
chip->ecc_step_ds = 512;
} else if (chip->onfi_version >= 21 &&
(onfi_feature(chip) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
} else if (chip->parameters.onfi.version >= 21 &&
(le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
/*
* The nand_flash_detect_ext_param_page() uses the
@ -5194,6 +5194,16 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
/* Save some parameters from the parameter page for future use */
if (le16_to_cpu(p->opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES)
chip->parameters.supports_set_get_features = true;
chip->parameters.onfi.tPROG = le16_to_cpu(p->t_prog);
chip->parameters.onfi.tBERS = le16_to_cpu(p->t_bers);
chip->parameters.onfi.tR = le16_to_cpu(p->t_r);
chip->parameters.onfi.tCCS = le16_to_cpu(p->t_ccs);
chip->parameters.onfi.async_timing_mode =
le16_to_cpu(p->async_timing_mode);
chip->parameters.onfi.vendor_revision =
le16_to_cpu(p->vendor_revision);
memcpy(chip->parameters.onfi.vendor, p->vendor,
sizeof(p->vendor));
return 1;
}
@ -5575,7 +5585,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
}
}
chip->onfi_version = 0;
chip->parameters.onfi.version = 0;
if (!type->name || !type->pagesize) {
/* Check if the chip is ONFI compliant */
if (nand_flash_detect_onfi(chip))

Просмотреть файл

@ -56,17 +56,14 @@ static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
*/
static int micron_nand_onfi_init(struct nand_chip *chip)
{
struct nand_onfi_params *p = &chip->onfi_params;
struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
struct nand_parameters *p = &chip->parameters;
struct nand_onfi_vendor_micron *micron = (void *)p->onfi.vendor;
if (!chip->onfi_version)
return 0;
if (chip->parameters.onfi.version && p->onfi.vendor_revision) {
chip->read_retries = micron->read_retry_options;
chip->setup_read_retry = micron_nand_setup_read_retry;
}
if (le16_to_cpu(p->vendor_revision) < 1)
return 0;
chip->read_retries = micron->read_retry_options;
chip->setup_read_retry = micron_nand_setup_read_retry;
return 0;
}
@ -207,7 +204,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = { 0, };
int ret;
if (chip->onfi_version == 0)
if (!chip->parameters.onfi.version)
return MICRON_ON_DIE_UNSUPPORTED;
if (chip->bits_per_cell != 1)
@ -239,7 +236,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
* Some Micron NANDs have an on-die ECC of 4/512, some other
* 8/512. We only support the former.
*/
if (chip->onfi_params.ecc_bits != 4)
if (chip->ecc_strength_ds != 4)
return MICRON_ON_DIE_UNSUPPORTED;
return MICRON_ON_DIE_SUPPORTED;

Просмотреть файл

@ -306,17 +306,17 @@ int onfi_fill_data_interface(struct nand_chip *chip,
* tR, tPROG, tCCS, ...
* These information are part of the ONFI parameter page.
*/
if (chip->onfi_version) {
struct nand_onfi_params *params = &chip->onfi_params;
if (chip->parameters.onfi.version) {
struct nand_parameters *params = &chip->parameters;
struct nand_sdr_timings *timings = &iface->timings.sdr;
/* microseconds -> picoseconds */
timings->tPROG_max = 1000000ULL * le16_to_cpu(params->t_prog);
timings->tBERS_max = 1000000ULL * le16_to_cpu(params->t_bers);
timings->tR_max = 1000000ULL * le16_to_cpu(params->t_r);
timings->tPROG_max = 1000000ULL * params->onfi.tPROG;
timings->tBERS_max = 1000000ULL * params->onfi.tBERS;
timings->tR_max = 1000000ULL * params->onfi.tR;
/* nanoseconds -> picoseconds */
timings->tCCS_min = 1000UL * le16_to_cpu(params->t_ccs);
timings->tCCS_min = 1000UL * params->onfi.tCCS;
}
return 0;

Просмотреть файл

@ -429,14 +429,41 @@ struct nand_jedec_params {
__le16 crc;
} __packed;
/**
* struct onfi_params - ONFI specific parameters that will be reused
* @version: ONFI version (BCD encoded), 0 if ONFI is not supported
* @tPROG: Page program time
* @tBERS: Block erase time
* @tR: Page read time
* @tCCS: Change column setup time
* @async_timing_mode: Supported asynchronous timing mode
* @vendor_revision: Vendor specific revision number
* @vendor: Vendor specific data
*/
struct onfi_params {
int version;
u16 tPROG;
u16 tBERS;
u16 tR;
u16 tCCS;
u16 async_timing_mode;
u16 vendor_revision;
u8 vendor[88];
};
/**
* struct nand_parameters - NAND generic parameters from the parameter page
* @model: Model name
* @supports_set_get_features: The NAND chip supports setting/getting features
* @onfi: ONFI specific parameters
*/
struct nand_parameters {
/* Generic parameters */
char model[100];
bool supports_set_get_features;
/* ONFI parameters */
struct onfi_params onfi;
};
/* The maximum expected count of bytes in the NAND ID sequence */
@ -1167,8 +1194,6 @@ int nand_op_parser_exec_op(struct nand_chip *chip,
* currently in data_buf.
* @subpagesize: [INTERN] holds the subpagesize
* @id: [INTERN] holds NAND ID
* @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded),
* non 0 if ONFI supported.
* @jedec_version: [INTERN] holds the chip JEDEC version (BCD encoded),
* non 0 if JEDEC supported.
* @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is
@ -1255,7 +1280,6 @@ struct nand_chip {
int badblockbits;
struct nand_id id;
int onfi_version;
int jedec_version;
union {
struct nand_onfi_params onfi_params;
@ -1548,26 +1572,13 @@ struct platform_nand_data {
struct platform_nand_ctrl ctrl;
};
/* return the supported features. */
static inline int onfi_feature(struct nand_chip *chip)
{
return chip->onfi_version ? le16_to_cpu(chip->onfi_params.features) : 0;
}
/* return the supported asynchronous timing mode. */
static inline int onfi_get_async_timing_mode(struct nand_chip *chip)
{
if (!chip->onfi_version)
if (!chip->parameters.onfi.version)
return ONFI_TIMING_MODE_UNKNOWN;
return le16_to_cpu(chip->onfi_params.async_timing_mode);
}
/* return the supported synchronous timing mode. */
static inline int onfi_get_sync_timing_mode(struct nand_chip *chip)
{
if (!chip->onfi_version)
return ONFI_TIMING_MODE_UNKNOWN;
return le16_to_cpu(chip->onfi_params.src_sync_timing_mode);
return chip->parameters.onfi.async_timing_mode;
}
int onfi_fill_data_interface(struct nand_chip *chip,