cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nand_timings.c (18920B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  Copyright (C) 2014 Free Electrons
      4 *
      5 *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
      6 */
      7#include <linux/kernel.h>
      8#include <linux/err.h>
      9#include <linux/export.h>
     10
     11#include "internals.h"
     12
     13#define ONFI_DYN_TIMING_MAX U16_MAX
     14
     15/*
     16 * For non-ONFI chips we use the highest possible value for tPROG and tBERS.
     17 * tR and tCCS will take the default values precised in the ONFI specification
     18 * for timing mode 0, respectively 200us and 500ns.
     19 *
     20 * These four values are tweaked to be more accurate in the case of ONFI chips.
     21 */
     22static const struct nand_interface_config onfi_sdr_timings[] = {
     23	/* Mode 0 */
     24	{
     25		.type = NAND_SDR_IFACE,
     26		.timings.mode = 0,
     27		.timings.sdr = {
     28			.tCCS_min = 500000,
     29			.tR_max = 200000000,
     30			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
     31			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
     32			.tADL_min = 400000,
     33			.tALH_min = 20000,
     34			.tALS_min = 50000,
     35			.tAR_min = 25000,
     36			.tCEA_max = 100000,
     37			.tCEH_min = 20000,
     38			.tCH_min = 20000,
     39			.tCHZ_max = 100000,
     40			.tCLH_min = 20000,
     41			.tCLR_min = 20000,
     42			.tCLS_min = 50000,
     43			.tCOH_min = 0,
     44			.tCS_min = 70000,
     45			.tDH_min = 20000,
     46			.tDS_min = 40000,
     47			.tFEAT_max = 1000000,
     48			.tIR_min = 10000,
     49			.tITC_max = 1000000,
     50			.tRC_min = 100000,
     51			.tREA_max = 40000,
     52			.tREH_min = 30000,
     53			.tRHOH_min = 0,
     54			.tRHW_min = 200000,
     55			.tRHZ_max = 200000,
     56			.tRLOH_min = 0,
     57			.tRP_min = 50000,
     58			.tRR_min = 40000,
     59			.tRST_max = 250000000000ULL,
     60			.tWB_max = 200000,
     61			.tWC_min = 100000,
     62			.tWH_min = 30000,
     63			.tWHR_min = 120000,
     64			.tWP_min = 50000,
     65			.tWW_min = 100000,
     66		},
     67	},
     68	/* Mode 1 */
     69	{
     70		.type = NAND_SDR_IFACE,
     71		.timings.mode = 1,
     72		.timings.sdr = {
     73			.tCCS_min = 500000,
     74			.tR_max = 200000000,
     75			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
     76			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
     77			.tADL_min = 400000,
     78			.tALH_min = 10000,
     79			.tALS_min = 25000,
     80			.tAR_min = 10000,
     81			.tCEA_max = 45000,
     82			.tCEH_min = 20000,
     83			.tCH_min = 10000,
     84			.tCHZ_max = 50000,
     85			.tCLH_min = 10000,
     86			.tCLR_min = 10000,
     87			.tCLS_min = 25000,
     88			.tCOH_min = 15000,
     89			.tCS_min = 35000,
     90			.tDH_min = 10000,
     91			.tDS_min = 20000,
     92			.tFEAT_max = 1000000,
     93			.tIR_min = 0,
     94			.tITC_max = 1000000,
     95			.tRC_min = 50000,
     96			.tREA_max = 30000,
     97			.tREH_min = 15000,
     98			.tRHOH_min = 15000,
     99			.tRHW_min = 100000,
    100			.tRHZ_max = 100000,
    101			.tRLOH_min = 0,
    102			.tRP_min = 25000,
    103			.tRR_min = 20000,
    104			.tRST_max = 500000000,
    105			.tWB_max = 100000,
    106			.tWC_min = 45000,
    107			.tWH_min = 15000,
    108			.tWHR_min = 80000,
    109			.tWP_min = 25000,
    110			.tWW_min = 100000,
    111		},
    112	},
    113	/* Mode 2 */
    114	{
    115		.type = NAND_SDR_IFACE,
    116		.timings.mode = 2,
    117		.timings.sdr = {
    118			.tCCS_min = 500000,
    119			.tR_max = 200000000,
    120			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    121			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    122			.tADL_min = 400000,
    123			.tALH_min = 10000,
    124			.tALS_min = 15000,
    125			.tAR_min = 10000,
    126			.tCEA_max = 30000,
    127			.tCEH_min = 20000,
    128			.tCH_min = 10000,
    129			.tCHZ_max = 50000,
    130			.tCLH_min = 10000,
    131			.tCLR_min = 10000,
    132			.tCLS_min = 15000,
    133			.tCOH_min = 15000,
    134			.tCS_min = 25000,
    135			.tDH_min = 5000,
    136			.tDS_min = 15000,
    137			.tFEAT_max = 1000000,
    138			.tIR_min = 0,
    139			.tITC_max = 1000000,
    140			.tRC_min = 35000,
    141			.tREA_max = 25000,
    142			.tREH_min = 15000,
    143			.tRHOH_min = 15000,
    144			.tRHW_min = 100000,
    145			.tRHZ_max = 100000,
    146			.tRLOH_min = 0,
    147			.tRR_min = 20000,
    148			.tRST_max = 500000000,
    149			.tWB_max = 100000,
    150			.tRP_min = 17000,
    151			.tWC_min = 35000,
    152			.tWH_min = 15000,
    153			.tWHR_min = 80000,
    154			.tWP_min = 17000,
    155			.tWW_min = 100000,
    156		},
    157	},
    158	/* Mode 3 */
    159	{
    160		.type = NAND_SDR_IFACE,
    161		.timings.mode = 3,
    162		.timings.sdr = {
    163			.tCCS_min = 500000,
    164			.tR_max = 200000000,
    165			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    166			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    167			.tADL_min = 400000,
    168			.tALH_min = 5000,
    169			.tALS_min = 10000,
    170			.tAR_min = 10000,
    171			.tCEA_max = 25000,
    172			.tCEH_min = 20000,
    173			.tCH_min = 5000,
    174			.tCHZ_max = 50000,
    175			.tCLH_min = 5000,
    176			.tCLR_min = 10000,
    177			.tCLS_min = 10000,
    178			.tCOH_min = 15000,
    179			.tCS_min = 25000,
    180			.tDH_min = 5000,
    181			.tDS_min = 10000,
    182			.tFEAT_max = 1000000,
    183			.tIR_min = 0,
    184			.tITC_max = 1000000,
    185			.tRC_min = 30000,
    186			.tREA_max = 20000,
    187			.tREH_min = 10000,
    188			.tRHOH_min = 15000,
    189			.tRHW_min = 100000,
    190			.tRHZ_max = 100000,
    191			.tRLOH_min = 0,
    192			.tRP_min = 15000,
    193			.tRR_min = 20000,
    194			.tRST_max = 500000000,
    195			.tWB_max = 100000,
    196			.tWC_min = 30000,
    197			.tWH_min = 10000,
    198			.tWHR_min = 80000,
    199			.tWP_min = 15000,
    200			.tWW_min = 100000,
    201		},
    202	},
    203	/* Mode 4 */
    204	{
    205		.type = NAND_SDR_IFACE,
    206		.timings.mode = 4,
    207		.timings.sdr = {
    208			.tCCS_min = 500000,
    209			.tR_max = 200000000,
    210			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    211			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    212			.tADL_min = 400000,
    213			.tALH_min = 5000,
    214			.tALS_min = 10000,
    215			.tAR_min = 10000,
    216			.tCEA_max = 25000,
    217			.tCEH_min = 20000,
    218			.tCH_min = 5000,
    219			.tCHZ_max = 30000,
    220			.tCLH_min = 5000,
    221			.tCLR_min = 10000,
    222			.tCLS_min = 10000,
    223			.tCOH_min = 15000,
    224			.tCS_min = 20000,
    225			.tDH_min = 5000,
    226			.tDS_min = 10000,
    227			.tFEAT_max = 1000000,
    228			.tIR_min = 0,
    229			.tITC_max = 1000000,
    230			.tRC_min = 25000,
    231			.tREA_max = 20000,
    232			.tREH_min = 10000,
    233			.tRHOH_min = 15000,
    234			.tRHW_min = 100000,
    235			.tRHZ_max = 100000,
    236			.tRLOH_min = 5000,
    237			.tRP_min = 12000,
    238			.tRR_min = 20000,
    239			.tRST_max = 500000000,
    240			.tWB_max = 100000,
    241			.tWC_min = 25000,
    242			.tWH_min = 10000,
    243			.tWHR_min = 80000,
    244			.tWP_min = 12000,
    245			.tWW_min = 100000,
    246		},
    247	},
    248	/* Mode 5 */
    249	{
    250		.type = NAND_SDR_IFACE,
    251		.timings.mode = 5,
    252		.timings.sdr = {
    253			.tCCS_min = 500000,
    254			.tR_max = 200000000,
    255			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    256			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    257			.tADL_min = 400000,
    258			.tALH_min = 5000,
    259			.tALS_min = 10000,
    260			.tAR_min = 10000,
    261			.tCEA_max = 25000,
    262			.tCEH_min = 20000,
    263			.tCH_min = 5000,
    264			.tCHZ_max = 30000,
    265			.tCLH_min = 5000,
    266			.tCLR_min = 10000,
    267			.tCLS_min = 10000,
    268			.tCOH_min = 15000,
    269			.tCS_min = 15000,
    270			.tDH_min = 5000,
    271			.tDS_min = 7000,
    272			.tFEAT_max = 1000000,
    273			.tIR_min = 0,
    274			.tITC_max = 1000000,
    275			.tRC_min = 20000,
    276			.tREA_max = 16000,
    277			.tREH_min = 7000,
    278			.tRHOH_min = 15000,
    279			.tRHW_min = 100000,
    280			.tRHZ_max = 100000,
    281			.tRLOH_min = 5000,
    282			.tRP_min = 10000,
    283			.tRR_min = 20000,
    284			.tRST_max = 500000000,
    285			.tWB_max = 100000,
    286			.tWC_min = 20000,
    287			.tWH_min = 7000,
    288			.tWHR_min = 80000,
    289			.tWP_min = 10000,
    290			.tWW_min = 100000,
    291		},
    292	},
    293};
    294
    295static const struct nand_interface_config onfi_nvddr_timings[] = {
    296	/* Mode 0 */
    297	{
    298		.type = NAND_NVDDR_IFACE,
    299		.timings.mode = 0,
    300		.timings.nvddr = {
    301			.tCCS_min = 500000,
    302			.tR_max = 200000000,
    303			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    304			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    305			.tAC_min = 3000,
    306			.tAC_max = 25000,
    307			.tADL_min = 400000,
    308			.tCAD_min = 45000,
    309			.tCAH_min = 10000,
    310			.tCALH_min = 10000,
    311			.tCALS_min = 10000,
    312			.tCAS_min = 10000,
    313			.tCEH_min = 20000,
    314			.tCH_min = 10000,
    315			.tCK_min = 50000,
    316			.tCS_min = 35000,
    317			.tDH_min = 5000,
    318			.tDQSCK_min = 3000,
    319			.tDQSCK_max = 25000,
    320			.tDQSD_min = 0,
    321			.tDQSD_max = 18000,
    322			.tDQSHZ_max = 20000,
    323			.tDQSQ_max = 5000,
    324			.tDS_min = 5000,
    325			.tDSC_min = 50000,
    326			.tFEAT_max = 1000000,
    327			.tITC_max = 1000000,
    328			.tQHS_max = 6000,
    329			.tRHW_min = 100000,
    330			.tRR_min = 20000,
    331			.tRST_max = 500000000,
    332			.tWB_max = 100000,
    333			.tWHR_min = 80000,
    334			.tWRCK_min = 20000,
    335			.tWW_min = 100000,
    336		},
    337	},
    338	/* Mode 1 */
    339	{
    340		.type = NAND_NVDDR_IFACE,
    341		.timings.mode = 1,
    342		.timings.nvddr = {
    343			.tCCS_min = 500000,
    344			.tR_max = 200000000,
    345			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    346			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    347			.tAC_min = 3000,
    348			.tAC_max = 25000,
    349			.tADL_min = 400000,
    350			.tCAD_min = 45000,
    351			.tCAH_min = 5000,
    352			.tCALH_min = 5000,
    353			.tCALS_min = 5000,
    354			.tCAS_min = 5000,
    355			.tCEH_min = 20000,
    356			.tCH_min = 5000,
    357			.tCK_min = 30000,
    358			.tCS_min = 25000,
    359			.tDH_min = 2500,
    360			.tDQSCK_min = 3000,
    361			.tDQSCK_max = 25000,
    362			.tDQSD_min = 0,
    363			.tDQSD_max = 18000,
    364			.tDQSHZ_max = 20000,
    365			.tDQSQ_max = 2500,
    366			.tDS_min = 3000,
    367			.tDSC_min = 30000,
    368			.tFEAT_max = 1000000,
    369			.tITC_max = 1000000,
    370			.tQHS_max = 3000,
    371			.tRHW_min = 100000,
    372			.tRR_min = 20000,
    373			.tRST_max = 500000000,
    374			.tWB_max = 100000,
    375			.tWHR_min = 80000,
    376			.tWRCK_min = 20000,
    377			.tWW_min = 100000,
    378		},
    379	},
    380	/* Mode 2 */
    381	{
    382		.type = NAND_NVDDR_IFACE,
    383		.timings.mode = 2,
    384		.timings.nvddr = {
    385			.tCCS_min = 500000,
    386			.tR_max = 200000000,
    387			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    388			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    389			.tAC_min = 3000,
    390			.tAC_max = 25000,
    391			.tADL_min = 400000,
    392			.tCAD_min = 45000,
    393			.tCAH_min = 4000,
    394			.tCALH_min = 4000,
    395			.tCALS_min = 4000,
    396			.tCAS_min = 4000,
    397			.tCEH_min = 20000,
    398			.tCH_min = 4000,
    399			.tCK_min = 20000,
    400			.tCS_min = 15000,
    401			.tDH_min = 1700,
    402			.tDQSCK_min = 3000,
    403			.tDQSCK_max = 25000,
    404			.tDQSD_min = 0,
    405			.tDQSD_max = 18000,
    406			.tDQSHZ_max = 20000,
    407			.tDQSQ_max = 1700,
    408			.tDS_min = 2000,
    409			.tDSC_min = 20000,
    410			.tFEAT_max = 1000000,
    411			.tITC_max = 1000000,
    412			.tQHS_max = 2000,
    413			.tRHW_min = 100000,
    414			.tRR_min = 20000,
    415			.tRST_max = 500000000,
    416			.tWB_max = 100000,
    417			.tWHR_min = 80000,
    418			.tWRCK_min = 20000,
    419			.tWW_min = 100000,
    420		},
    421	},
    422	/* Mode 3 */
    423	{
    424		.type = NAND_NVDDR_IFACE,
    425		.timings.mode = 3,
    426		.timings.nvddr = {
    427			.tCCS_min = 500000,
    428			.tR_max = 200000000,
    429			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    430			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    431			.tAC_min = 3000,
    432			.tAC_max = 25000,
    433			.tADL_min = 400000,
    434			.tCAD_min = 45000,
    435			.tCAH_min = 3000,
    436			.tCALH_min = 3000,
    437			.tCALS_min = 3000,
    438			.tCAS_min = 3000,
    439			.tCEH_min = 20000,
    440			.tCH_min = 3000,
    441			.tCK_min = 15000,
    442			.tCS_min = 15000,
    443			.tDH_min = 1300,
    444			.tDQSCK_min = 3000,
    445			.tDQSCK_max = 25000,
    446			.tDQSD_min = 0,
    447			.tDQSD_max = 18000,
    448			.tDQSHZ_max = 20000,
    449			.tDQSQ_max = 1300,
    450			.tDS_min = 1500,
    451			.tDSC_min = 15000,
    452			.tFEAT_max = 1000000,
    453			.tITC_max = 1000000,
    454			.tQHS_max = 1500,
    455			.tRHW_min = 100000,
    456			.tRR_min = 20000,
    457			.tRST_max = 500000000,
    458			.tWB_max = 100000,
    459			.tWHR_min = 80000,
    460			.tWRCK_min = 20000,
    461			.tWW_min = 100000,
    462		},
    463	},
    464	/* Mode 4 */
    465	{
    466		.type = NAND_NVDDR_IFACE,
    467		.timings.mode = 4,
    468		.timings.nvddr = {
    469			.tCCS_min = 500000,
    470			.tR_max = 200000000,
    471			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    472			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    473			.tAC_min = 3000,
    474			.tAC_max = 25000,
    475			.tADL_min = 400000,
    476			.tCAD_min = 45000,
    477			.tCAH_min = 2500,
    478			.tCALH_min = 2500,
    479			.tCALS_min = 2500,
    480			.tCAS_min = 2500,
    481			.tCEH_min = 20000,
    482			.tCH_min = 2500,
    483			.tCK_min = 12000,
    484			.tCS_min = 15000,
    485			.tDH_min = 1100,
    486			.tDQSCK_min = 3000,
    487			.tDQSCK_max = 25000,
    488			.tDQSD_min = 0,
    489			.tDQSD_max = 18000,
    490			.tDQSHZ_max = 20000,
    491			.tDQSQ_max = 1000,
    492			.tDS_min = 1100,
    493			.tDSC_min = 12000,
    494			.tFEAT_max = 1000000,
    495			.tITC_max = 1000000,
    496			.tQHS_max = 1200,
    497			.tRHW_min = 100000,
    498			.tRR_min = 20000,
    499			.tRST_max = 500000000,
    500			.tWB_max = 100000,
    501			.tWHR_min = 80000,
    502			.tWRCK_min = 20000,
    503			.tWW_min = 100000,
    504		},
    505	},
    506	/* Mode 5 */
    507	{
    508		.type = NAND_NVDDR_IFACE,
    509		.timings.mode = 5,
    510		.timings.nvddr = {
    511			.tCCS_min = 500000,
    512			.tR_max = 200000000,
    513			.tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    514			.tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
    515			.tAC_min = 3000,
    516			.tAC_max = 25000,
    517			.tADL_min = 400000,
    518			.tCAD_min = 45000,
    519			.tCAH_min = 2000,
    520			.tCALH_min = 2000,
    521			.tCALS_min = 2000,
    522			.tCAS_min = 2000,
    523			.tCEH_min = 20000,
    524			.tCH_min = 2000,
    525			.tCK_min = 10000,
    526			.tCS_min = 15000,
    527			.tDH_min = 900,
    528			.tDQSCK_min = 3000,
    529			.tDQSCK_max = 25000,
    530			.tDQSD_min = 0,
    531			.tDQSD_max = 18000,
    532			.tDQSHZ_max = 20000,
    533			.tDQSQ_max = 850,
    534			.tDS_min = 900,
    535			.tDSC_min = 10000,
    536			.tFEAT_max = 1000000,
    537			.tITC_max = 1000000,
    538			.tQHS_max = 1000,
    539			.tRHW_min = 100000,
    540			.tRR_min = 20000,
    541			.tRST_max = 500000000,
    542			.tWB_max = 100000,
    543			.tWHR_min = 80000,
    544			.tWRCK_min = 20000,
    545			.tWW_min = 100000,
    546		},
    547	},
    548};
    549
    550/* All NAND chips share the same reset data interface: SDR mode 0 */
    551const struct nand_interface_config *nand_get_reset_interface_config(void)
    552{
    553	return &onfi_sdr_timings[0];
    554}
    555
    556/**
    557 * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
    558 *                              set of timings
    559 * @spec_timings: the timings to challenge
    560 */
    561unsigned int
    562onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
    563{
    564	const struct nand_sdr_timings *onfi_timings;
    565	int mode;
    566
    567	for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
    568		onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
    569
    570		if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
    571		    spec_timings->tADL_min <= onfi_timings->tADL_min &&
    572		    spec_timings->tALH_min <= onfi_timings->tALH_min &&
    573		    spec_timings->tALS_min <= onfi_timings->tALS_min &&
    574		    spec_timings->tAR_min <= onfi_timings->tAR_min &&
    575		    spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
    576		    spec_timings->tCH_min <= onfi_timings->tCH_min &&
    577		    spec_timings->tCLH_min <= onfi_timings->tCLH_min &&
    578		    spec_timings->tCLR_min <= onfi_timings->tCLR_min &&
    579		    spec_timings->tCLS_min <= onfi_timings->tCLS_min &&
    580		    spec_timings->tCOH_min <= onfi_timings->tCOH_min &&
    581		    spec_timings->tCS_min <= onfi_timings->tCS_min &&
    582		    spec_timings->tDH_min <= onfi_timings->tDH_min &&
    583		    spec_timings->tDS_min <= onfi_timings->tDS_min &&
    584		    spec_timings->tIR_min <= onfi_timings->tIR_min &&
    585		    spec_timings->tRC_min <= onfi_timings->tRC_min &&
    586		    spec_timings->tREH_min <= onfi_timings->tREH_min &&
    587		    spec_timings->tRHOH_min <= onfi_timings->tRHOH_min &&
    588		    spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
    589		    spec_timings->tRLOH_min <= onfi_timings->tRLOH_min &&
    590		    spec_timings->tRP_min <= onfi_timings->tRP_min &&
    591		    spec_timings->tRR_min <= onfi_timings->tRR_min &&
    592		    spec_timings->tWC_min <= onfi_timings->tWC_min &&
    593		    spec_timings->tWH_min <= onfi_timings->tWH_min &&
    594		    spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
    595		    spec_timings->tWP_min <= onfi_timings->tWP_min &&
    596		    spec_timings->tWW_min <= onfi_timings->tWW_min)
    597			return mode;
    598	}
    599
    600	return 0;
    601}
    602
    603/**
    604 * onfi_find_closest_nvddr_mode - Derive the closest ONFI NVDDR timing mode
    605 *                                given a set of timings
    606 * @spec_timings: the timings to challenge
    607 */
    608unsigned int
    609onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings)
    610{
    611	const struct nand_nvddr_timings *onfi_timings;
    612	int mode;
    613
    614	for (mode = ARRAY_SIZE(onfi_nvddr_timings) - 1; mode > 0; mode--) {
    615		onfi_timings = &onfi_nvddr_timings[mode].timings.nvddr;
    616
    617		if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
    618		    spec_timings->tAC_min <= onfi_timings->tAC_min &&
    619		    spec_timings->tADL_min <= onfi_timings->tADL_min &&
    620		    spec_timings->tCAD_min <= onfi_timings->tCAD_min &&
    621		    spec_timings->tCAH_min <= onfi_timings->tCAH_min &&
    622		    spec_timings->tCALH_min <= onfi_timings->tCALH_min &&
    623		    spec_timings->tCALS_min <= onfi_timings->tCALS_min &&
    624		    spec_timings->tCAS_min <= onfi_timings->tCAS_min &&
    625		    spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
    626		    spec_timings->tCH_min <= onfi_timings->tCH_min &&
    627		    spec_timings->tCK_min <= onfi_timings->tCK_min &&
    628		    spec_timings->tCS_min <= onfi_timings->tCS_min &&
    629		    spec_timings->tDH_min <= onfi_timings->tDH_min &&
    630		    spec_timings->tDQSCK_min <= onfi_timings->tDQSCK_min &&
    631		    spec_timings->tDQSD_min <= onfi_timings->tDQSD_min &&
    632		    spec_timings->tDS_min <= onfi_timings->tDS_min &&
    633		    spec_timings->tDSC_min <= onfi_timings->tDSC_min &&
    634		    spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
    635		    spec_timings->tRR_min <= onfi_timings->tRR_min &&
    636		    spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
    637		    spec_timings->tWRCK_min <= onfi_timings->tWRCK_min &&
    638		    spec_timings->tWW_min <= onfi_timings->tWW_min)
    639			return mode;
    640	}
    641
    642	return 0;
    643}
    644
    645/*
    646 * onfi_fill_sdr_interface_config - Initialize a SDR interface config from a
    647 *                                  given ONFI mode
    648 * @chip: The NAND chip
    649 * @iface: The interface configuration to fill
    650 * @timing_mode: The ONFI timing mode
    651 */
    652static void onfi_fill_sdr_interface_config(struct nand_chip *chip,
    653					   struct nand_interface_config *iface,
    654					   unsigned int timing_mode)
    655{
    656	struct onfi_params *onfi = chip->parameters.onfi;
    657
    658	if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
    659		return;
    660
    661	*iface = onfi_sdr_timings[timing_mode];
    662
    663	/*
    664	 * Initialize timings that cannot be deduced from timing mode:
    665	 * tPROG, tBERS, tR and tCCS.
    666	 * These information are part of the ONFI parameter page.
    667	 */
    668	if (onfi) {
    669		struct nand_sdr_timings *timings = &iface->timings.sdr;
    670
    671		/* microseconds -> picoseconds */
    672		timings->tPROG_max = 1000000ULL * onfi->tPROG;
    673		timings->tBERS_max = 1000000ULL * onfi->tBERS;
    674		timings->tR_max = 1000000ULL * onfi->tR;
    675
    676		/* nanoseconds -> picoseconds */
    677		timings->tCCS_min = 1000UL * onfi->tCCS;
    678	}
    679}
    680
    681/**
    682 * onfi_fill_nvddr_interface_config - Initialize a NVDDR interface config from a
    683 *                                    given ONFI mode
    684 * @chip: The NAND chip
    685 * @iface: The interface configuration to fill
    686 * @timing_mode: The ONFI timing mode
    687 */
    688static void onfi_fill_nvddr_interface_config(struct nand_chip *chip,
    689					     struct nand_interface_config *iface,
    690					     unsigned int timing_mode)
    691{
    692	struct onfi_params *onfi = chip->parameters.onfi;
    693
    694	if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_nvddr_timings)))
    695		return;
    696
    697	*iface = onfi_nvddr_timings[timing_mode];
    698
    699	/*
    700	 * Initialize timings that cannot be deduced from timing mode:
    701	 * tPROG, tBERS, tR, tCCS and tCAD.
    702	 * These information are part of the ONFI parameter page.
    703	 */
    704	if (onfi) {
    705		struct nand_nvddr_timings *timings = &iface->timings.nvddr;
    706
    707		/* microseconds -> picoseconds */
    708		timings->tPROG_max = 1000000ULL * onfi->tPROG;
    709		timings->tBERS_max = 1000000ULL * onfi->tBERS;
    710		timings->tR_max = 1000000ULL * onfi->tR;
    711
    712		/* nanoseconds -> picoseconds */
    713		timings->tCCS_min = 1000UL * onfi->tCCS;
    714
    715		if (onfi->fast_tCAD)
    716			timings->tCAD_min = 25000;
    717	}
    718}
    719
    720/**
    721 * onfi_fill_interface_config - Initialize an interface config from a given
    722 *                              ONFI mode
    723 * @chip: The NAND chip
    724 * @iface: The interface configuration to fill
    725 * @type: The interface type
    726 * @timing_mode: The ONFI timing mode
    727 */
    728void onfi_fill_interface_config(struct nand_chip *chip,
    729				struct nand_interface_config *iface,
    730				enum nand_interface_type type,
    731				unsigned int timing_mode)
    732{
    733	if (type == NAND_SDR_IFACE)
    734		return onfi_fill_sdr_interface_config(chip, iface, timing_mode);
    735	else
    736		return onfi_fill_nvddr_interface_config(chip, iface, timing_mode);
    737}