UPSTREAM: mtd: nand: convert ONFI mode into data interface
struct nand_data_interface is the designated type to pass to the NAND drivers to configure the timing. To simplify further patches convert the onfi_sdr_timings array from type struct nand_sdr_timings nand_data_interface. Change-Id: I9c9422bf02986844e3f6b57381ca62ed9c5a66b7 Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> [Linux commit: b1dd3ca203fccd111926c3f6ac59bf903ec62b05] Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com> Signed-off-by: Jon Lin <jon.lin@rock-chips.com> (cherry picked from commit 46deff57da190fee1a902ecfbf951cd4cfe8494e)
This commit is contained in:
parent
2b17534304
commit
e56ea81c67
|
|
@ -12,10 +12,12 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mtd/nand.h>
|
#include <linux/mtd/nand.h>
|
||||||
|
|
||||||
static const struct nand_sdr_timings onfi_sdr_timings[] = {
|
static const struct nand_data_interface onfi_sdr_timings[] = {
|
||||||
/* Mode 0 */
|
/* Mode 0 */
|
||||||
{
|
{
|
||||||
.tADL_min = 200000,
|
.type = NAND_SDR_IFACE,
|
||||||
|
.timings.sdr = {
|
||||||
|
.tADL_min = 400000,
|
||||||
.tALH_min = 20000,
|
.tALH_min = 20000,
|
||||||
.tALS_min = 50000,
|
.tALS_min = 50000,
|
||||||
.tAR_min = 25000,
|
.tAR_min = 25000,
|
||||||
|
|
@ -41,18 +43,21 @@ static const struct nand_sdr_timings onfi_sdr_timings[] = {
|
||||||
.tRHZ_max = 200000,
|
.tRHZ_max = 200000,
|
||||||
.tRLOH_min = 0,
|
.tRLOH_min = 0,
|
||||||
.tRP_min = 50000,
|
.tRP_min = 50000,
|
||||||
|
.tRR_min = 40000,
|
||||||
.tRST_max = 250000000000ULL,
|
.tRST_max = 250000000000ULL,
|
||||||
.tWB_max = 200000,
|
.tWB_max = 200000,
|
||||||
.tRR_min = 40000,
|
|
||||||
.tWC_min = 100000,
|
.tWC_min = 100000,
|
||||||
.tWH_min = 30000,
|
.tWH_min = 30000,
|
||||||
.tWHR_min = 120000,
|
.tWHR_min = 120000,
|
||||||
.tWP_min = 50000,
|
.tWP_min = 50000,
|
||||||
.tWW_min = 100000,
|
.tWW_min = 100000,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
/* Mode 1 */
|
/* Mode 1 */
|
||||||
{
|
{
|
||||||
.tADL_min = 100000,
|
.type = NAND_SDR_IFACE,
|
||||||
|
.timings.sdr = {
|
||||||
|
.tADL_min = 400000,
|
||||||
.tALH_min = 10000,
|
.tALH_min = 10000,
|
||||||
.tALS_min = 25000,
|
.tALS_min = 25000,
|
||||||
.tAR_min = 10000,
|
.tAR_min = 10000,
|
||||||
|
|
@ -87,9 +92,12 @@ static const struct nand_sdr_timings onfi_sdr_timings[] = {
|
||||||
.tWP_min = 25000,
|
.tWP_min = 25000,
|
||||||
.tWW_min = 100000,
|
.tWW_min = 100000,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
/* Mode 2 */
|
/* Mode 2 */
|
||||||
{
|
{
|
||||||
.tADL_min = 100000,
|
.type = NAND_SDR_IFACE,
|
||||||
|
.timings.sdr = {
|
||||||
|
.tADL_min = 400000,
|
||||||
.tALH_min = 10000,
|
.tALH_min = 10000,
|
||||||
.tALS_min = 15000,
|
.tALS_min = 15000,
|
||||||
.tAR_min = 10000,
|
.tAR_min = 10000,
|
||||||
|
|
@ -124,9 +132,12 @@ static const struct nand_sdr_timings onfi_sdr_timings[] = {
|
||||||
.tWP_min = 17000,
|
.tWP_min = 17000,
|
||||||
.tWW_min = 100000,
|
.tWW_min = 100000,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
/* Mode 3 */
|
/* Mode 3 */
|
||||||
{
|
{
|
||||||
.tADL_min = 100000,
|
.type = NAND_SDR_IFACE,
|
||||||
|
.timings.sdr = {
|
||||||
|
.tADL_min = 400000,
|
||||||
.tALH_min = 5000,
|
.tALH_min = 5000,
|
||||||
.tALS_min = 10000,
|
.tALS_min = 10000,
|
||||||
.tAR_min = 10000,
|
.tAR_min = 10000,
|
||||||
|
|
@ -161,9 +172,12 @@ static const struct nand_sdr_timings onfi_sdr_timings[] = {
|
||||||
.tWP_min = 15000,
|
.tWP_min = 15000,
|
||||||
.tWW_min = 100000,
|
.tWW_min = 100000,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
/* Mode 4 */
|
/* Mode 4 */
|
||||||
{
|
{
|
||||||
.tADL_min = 70000,
|
.type = NAND_SDR_IFACE,
|
||||||
|
.timings.sdr = {
|
||||||
|
.tADL_min = 400000,
|
||||||
.tALH_min = 5000,
|
.tALH_min = 5000,
|
||||||
.tALS_min = 10000,
|
.tALS_min = 10000,
|
||||||
.tAR_min = 10000,
|
.tAR_min = 10000,
|
||||||
|
|
@ -198,9 +212,12 @@ static const struct nand_sdr_timings onfi_sdr_timings[] = {
|
||||||
.tWP_min = 12000,
|
.tWP_min = 12000,
|
||||||
.tWW_min = 100000,
|
.tWW_min = 100000,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
/* Mode 5 */
|
/* Mode 5 */
|
||||||
{
|
{
|
||||||
.tADL_min = 70000,
|
.type = NAND_SDR_IFACE,
|
||||||
|
.timings.sdr = {
|
||||||
|
.tADL_min = 400000,
|
||||||
.tALH_min = 5000,
|
.tALH_min = 5000,
|
||||||
.tALS_min = 10000,
|
.tALS_min = 10000,
|
||||||
.tAR_min = 10000,
|
.tAR_min = 10000,
|
||||||
|
|
@ -235,6 +252,7 @@ static const struct nand_sdr_timings onfi_sdr_timings[] = {
|
||||||
.tWP_min = 10000,
|
.tWP_min = 10000,
|
||||||
.tWW_min = 100000,
|
.tWW_min = 100000,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -247,6 +265,35 @@ const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
|
||||||
if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
|
if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
return &onfi_sdr_timings[mode];
|
return &onfi_sdr_timings[mode].timings.sdr;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
|
EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* onfi_init_data_interface - [NAND Interface] Initialize a data interface from
|
||||||
|
* given ONFI mode
|
||||||
|
* @iface: The data interface to be initialized
|
||||||
|
* @mode: The ONFI timing mode
|
||||||
|
*/
|
||||||
|
int onfi_init_data_interface(struct nand_chip *chip,
|
||||||
|
struct nand_data_interface *iface,
|
||||||
|
enum nand_data_interface_type type,
|
||||||
|
int timing_mode)
|
||||||
|
{
|
||||||
|
if (type != NAND_SDR_IFACE)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*iface = onfi_sdr_timings[timing_mode];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: initialize timings that cannot be deduced from timing mode:
|
||||||
|
* tR, tPROG, tCCS, ...
|
||||||
|
* These information are part of the ONFI parameter page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(onfi_init_data_interface);
|
||||||
|
|
|
||||||
|
|
@ -584,6 +584,123 @@ struct nand_buffers {
|
||||||
ARCH_DMA_MINALIGN)];
|
ARCH_DMA_MINALIGN)];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct nand_sdr_timings - SDR NAND chip timings
|
||||||
|
*
|
||||||
|
* This struct defines the timing requirements of a SDR NAND chip.
|
||||||
|
* These information can be found in every NAND datasheets and the timings
|
||||||
|
* meaning are described in the ONFI specifications:
|
||||||
|
* www.onfi.org/~/media/ONFI/specs/onfi_3_1_spec.pdf (chapter 4.15 Timing
|
||||||
|
* Parameters)
|
||||||
|
*
|
||||||
|
* All these timings are expressed in picoseconds.
|
||||||
|
*
|
||||||
|
* @tALH_min: ALE hold time
|
||||||
|
* @tADL_min: ALE to data loading time
|
||||||
|
* @tALS_min: ALE setup time
|
||||||
|
* @tAR_min: ALE to RE# delay
|
||||||
|
* @tCEA_max: CE# access time
|
||||||
|
* @tCEH_min: CE# high hold time
|
||||||
|
* @tCH_min: CE# hold time
|
||||||
|
* @tCHZ_max: CE# high to output hi-Z
|
||||||
|
* @tCLH_min: CLE hold time
|
||||||
|
* @tCLR_min: CLE to RE# delay
|
||||||
|
* @tCLS_min: CLE setup time
|
||||||
|
* @tCOH_min: CE# high to output hold
|
||||||
|
* @tCS_min: CE# setup time
|
||||||
|
* @tDH_min: Data hold time
|
||||||
|
* @tDS_min: Data setup time
|
||||||
|
* @tFEAT_max: Busy time for Set Features and Get Features
|
||||||
|
* @tIR_min: Output hi-Z to RE# low
|
||||||
|
* @tITC_max: Interface and Timing Mode Change time
|
||||||
|
* @tRC_min: RE# cycle time
|
||||||
|
* @tREA_max: RE# access time
|
||||||
|
* @tREH_min: RE# high hold time
|
||||||
|
* @tRHOH_min: RE# high to output hold
|
||||||
|
* @tRHW_min: RE# high to WE# low
|
||||||
|
* @tRHZ_max: RE# high to output hi-Z
|
||||||
|
* @tRLOH_min: RE# low to output hold
|
||||||
|
* @tRP_min: RE# pulse width
|
||||||
|
* @tRR_min: Ready to RE# low (data only)
|
||||||
|
* @tRST_max: Device reset time, measured from the falling edge of R/B# to the
|
||||||
|
* rising edge of R/B#.
|
||||||
|
* @tWB_max: WE# high to SR[6] low
|
||||||
|
* @tWC_min: WE# cycle time
|
||||||
|
* @tWH_min: WE# high hold time
|
||||||
|
* @tWHR_min: WE# high to RE# low
|
||||||
|
* @tWP_min: WE# pulse width
|
||||||
|
* @tWW_min: WP# transition to WE# low
|
||||||
|
*/
|
||||||
|
struct nand_sdr_timings {
|
||||||
|
u32 tALH_min;
|
||||||
|
u32 tADL_min;
|
||||||
|
u32 tALS_min;
|
||||||
|
u32 tAR_min;
|
||||||
|
u32 tCEA_max;
|
||||||
|
u32 tCEH_min;
|
||||||
|
u32 tCH_min;
|
||||||
|
u32 tCHZ_max;
|
||||||
|
u32 tCLH_min;
|
||||||
|
u32 tCLR_min;
|
||||||
|
u32 tCLS_min;
|
||||||
|
u32 tCOH_min;
|
||||||
|
u32 tCS_min;
|
||||||
|
u32 tDH_min;
|
||||||
|
u32 tDS_min;
|
||||||
|
u32 tFEAT_max;
|
||||||
|
u32 tIR_min;
|
||||||
|
u32 tITC_max;
|
||||||
|
u32 tRC_min;
|
||||||
|
u32 tREA_max;
|
||||||
|
u32 tREH_min;
|
||||||
|
u32 tRHOH_min;
|
||||||
|
u32 tRHW_min;
|
||||||
|
u32 tRHZ_max;
|
||||||
|
u32 tRLOH_min;
|
||||||
|
u32 tRP_min;
|
||||||
|
u32 tRR_min;
|
||||||
|
u64 tRST_max;
|
||||||
|
u32 tWB_max;
|
||||||
|
u32 tWC_min;
|
||||||
|
u32 tWH_min;
|
||||||
|
u32 tWHR_min;
|
||||||
|
u32 tWP_min;
|
||||||
|
u32 tWW_min;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum nand_data_interface_type - NAND interface timing type
|
||||||
|
* @NAND_SDR_IFACE: Single Data Rate interface
|
||||||
|
*/
|
||||||
|
enum nand_data_interface_type {
|
||||||
|
NAND_SDR_IFACE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct nand_data_interface - NAND interface timing
|
||||||
|
* @type: type of the timing
|
||||||
|
* @timings: The timing, type according to @type
|
||||||
|
*/
|
||||||
|
struct nand_data_interface {
|
||||||
|
enum nand_data_interface_type type;
|
||||||
|
union {
|
||||||
|
struct nand_sdr_timings sdr;
|
||||||
|
} timings;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nand_get_sdr_timings - get SDR timing from data interface
|
||||||
|
* @conf: The data interface
|
||||||
|
*/
|
||||||
|
static inline const struct nand_sdr_timings *
|
||||||
|
nand_get_sdr_timings(const struct nand_data_interface *conf)
|
||||||
|
{
|
||||||
|
if (conf->type != NAND_SDR_IFACE)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
return &conf->timings.sdr;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct nand_chip - NAND Private Flash Chip Data
|
* struct nand_chip - NAND Private Flash Chip Data
|
||||||
* @mtd: MTD device registered to the MTD framework
|
* @mtd: MTD device registered to the MTD framework
|
||||||
|
|
@ -1004,6 +1121,11 @@ static inline int onfi_get_sync_timing_mode(struct nand_chip *chip)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int onfi_init_data_interface(struct nand_chip *chip,
|
||||||
|
struct nand_data_interface *iface,
|
||||||
|
enum nand_data_interface_type type,
|
||||||
|
int timing_mode);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if it is a SLC nand.
|
* Check if it is a SLC nand.
|
||||||
* The !nand_is_slc() can be used to check the MLC/TLC nand chips.
|
* The !nand_is_slc() can be used to check the MLC/TLC nand chips.
|
||||||
|
|
@ -1046,55 +1168,6 @@ void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len);
|
||||||
void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len);
|
void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len);
|
||||||
uint8_t nand_read_byte(struct mtd_info *mtd);
|
uint8_t nand_read_byte(struct mtd_info *mtd);
|
||||||
|
|
||||||
/*
|
|
||||||
* struct nand_sdr_timings - SDR NAND chip timings
|
|
||||||
*
|
|
||||||
* This struct defines the timing requirements of a SDR NAND chip.
|
|
||||||
* These informations can be found in every NAND datasheets and the timings
|
|
||||||
* meaning are described in the ONFI specifications:
|
|
||||||
* www.onfi.org/~/media/ONFI/specs/onfi_3_1_spec.pdf (chapter 4.15 Timing
|
|
||||||
* Parameters)
|
|
||||||
*
|
|
||||||
* All these timings are expressed in picoseconds.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct nand_sdr_timings {
|
|
||||||
u32 tALH_min;
|
|
||||||
u32 tADL_min;
|
|
||||||
u32 tALS_min;
|
|
||||||
u32 tAR_min;
|
|
||||||
u32 tCEA_max;
|
|
||||||
u32 tCEH_min;
|
|
||||||
u32 tCH_min;
|
|
||||||
u32 tCHZ_max;
|
|
||||||
u32 tCLH_min;
|
|
||||||
u32 tCLR_min;
|
|
||||||
u32 tCLS_min;
|
|
||||||
u32 tCOH_min;
|
|
||||||
u32 tCS_min;
|
|
||||||
u32 tDH_min;
|
|
||||||
u32 tDS_min;
|
|
||||||
u32 tFEAT_max;
|
|
||||||
u32 tIR_min;
|
|
||||||
u32 tITC_max;
|
|
||||||
u32 tRC_min;
|
|
||||||
u32 tREA_max;
|
|
||||||
u32 tREH_min;
|
|
||||||
u32 tRHOH_min;
|
|
||||||
u32 tRHW_min;
|
|
||||||
u32 tRHZ_max;
|
|
||||||
u32 tRLOH_min;
|
|
||||||
u32 tRP_min;
|
|
||||||
u32 tRR_min;
|
|
||||||
u64 tRST_max;
|
|
||||||
u32 tWB_max;
|
|
||||||
u32 tWC_min;
|
|
||||||
u32 tWH_min;
|
|
||||||
u32 tWHR_min;
|
|
||||||
u32 tWP_min;
|
|
||||||
u32 tWW_min;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* get timing characteristics from ONFI timing mode. */
|
/* get timing characteristics from ONFI timing mode. */
|
||||||
const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
|
const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue