diff options
-rw-r--r-- | drivers/mtd/nand/raw/nand_onfi.c | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand_timings.c | 41 | ||||
-rw-r--r-- | include/linux/mtd/onfi.h | 2 |
3 files changed, 44 insertions, 0 deletions
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c index f7a4a0573fe7..8e4677f2ba76 100644 --- a/drivers/mtd/nand/raw/nand_onfi.c +++ b/drivers/mtd/nand/raw/nand_onfi.c @@ -315,6 +315,7 @@ int nand_onfi_detect(struct nand_chip *chip) onfi->tBERS = le16_to_cpu(p->t_bers); onfi->tR = le16_to_cpu(p->t_r); onfi->tCCS = le16_to_cpu(p->t_ccs); + onfi->fast_tCAD = p->nvddr_nvddr2_features & BIT(0); onfi->sdr_timing_modes = le16_to_cpu(p->sdr_timing_modes); if (p->features & ONFI_FEATURE_NV_DDR) onfi->nvddr_timing_modes = p->nvddr_timing_modes; diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c index fb483e696cb9..8eaa132c3900 100644 --- a/drivers/mtd/nand/raw/nand_timings.c +++ b/drivers/mtd/nand/raw/nand_timings.c @@ -637,6 +637,45 @@ static void onfi_fill_sdr_interface_config(struct nand_chip *chip, } /** + * onfi_fill_nvddr_interface_config - Initialize a NVDDR interface config from a + * given ONFI mode + * @chip: The NAND chip + * @iface: The interface configuration to fill + * @timing_mode: The ONFI timing mode + */ +static void onfi_fill_nvddr_interface_config(struct nand_chip *chip, + struct nand_interface_config *iface, + unsigned int timing_mode) +{ + struct onfi_params *onfi = chip->parameters.onfi; + + if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_nvddr_timings))) + return; + + *iface = onfi_nvddr_timings[timing_mode]; + + /* + * Initialize timings that cannot be deduced from timing mode: + * tPROG, tBERS, tR, tCCS and tCAD. + * These information are part of the ONFI parameter page. + */ + if (onfi) { + struct nand_nvddr_timings *timings = &iface->timings.nvddr; + + /* microseconds -> picoseconds */ + timings->tPROG_max = 1000000ULL * onfi->tPROG; + timings->tBERS_max = 1000000ULL * onfi->tBERS; + timings->tR_max = 1000000ULL * onfi->tR; + + /* nanoseconds -> picoseconds */ + timings->tCCS_min = 1000UL * onfi->tCCS; + + if (onfi->fast_tCAD) + timings->tCAD_min = 25000; + } +} + +/** * onfi_fill_interface_config - Initialize an interface config from a given * ONFI mode * @chip: The NAND chip @@ -651,4 +690,6 @@ void onfi_fill_interface_config(struct nand_chip *chip, { if (type == NAND_SDR_IFACE) return onfi_fill_sdr_interface_config(chip, iface, timing_mode); + else + return onfi_fill_nvddr_interface_config(chip, iface, timing_mode); } diff --git a/include/linux/mtd/onfi.h b/include/linux/mtd/onfi.h index 14e66a49557e..a9677bf1e47e 100644 --- a/include/linux/mtd/onfi.h +++ b/include/linux/mtd/onfi.h @@ -162,6 +162,7 @@ struct onfi_ext_param_page { * @tBERS: Block erase time * @tR: Page read time * @tCCS: Change column setup time + * @fast_tCAD: Command/Address/Data slow or fast delay (NV-DDR only) * @sdr_timing_modes: Supported asynchronous/SDR timing modes * @nvddr_timing_modes: Supported source synchronous/NV-DDR timing modes * @vendor_revision: Vendor specific revision number @@ -173,6 +174,7 @@ struct onfi_params { u16 tBERS; u16 tR; u16 tCCS; + bool fast_tCAD; u16 sdr_timing_modes; u16 nvddr_timing_modes; u16 vendor_revision; |