Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Copyright (C) 2014 Free Electrons
0004  *
0005  *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
0006  */
0007 #include <linux/kernel.h>
0008 #include <linux/err.h>
0009 #include <linux/export.h>
0010 
0011 #include "internals.h"
0012 
0013 #define ONFI_DYN_TIMING_MAX U16_MAX
0014 
0015 /*
0016  * For non-ONFI chips we use the highest possible value for tPROG and tBERS.
0017  * tR and tCCS will take the default values precised in the ONFI specification
0018  * for timing mode 0, respectively 200us and 500ns.
0019  *
0020  * These four values are tweaked to be more accurate in the case of ONFI chips.
0021  */
0022 static const struct nand_interface_config onfi_sdr_timings[] = {
0023     /* Mode 0 */
0024     {
0025         .type = NAND_SDR_IFACE,
0026         .timings.mode = 0,
0027         .timings.sdr = {
0028             .tCCS_min = 500000,
0029             .tR_max = 200000000,
0030             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0031             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0032             .tADL_min = 400000,
0033             .tALH_min = 20000,
0034             .tALS_min = 50000,
0035             .tAR_min = 25000,
0036             .tCEA_max = 100000,
0037             .tCEH_min = 20000,
0038             .tCH_min = 20000,
0039             .tCHZ_max = 100000,
0040             .tCLH_min = 20000,
0041             .tCLR_min = 20000,
0042             .tCLS_min = 50000,
0043             .tCOH_min = 0,
0044             .tCS_min = 70000,
0045             .tDH_min = 20000,
0046             .tDS_min = 40000,
0047             .tFEAT_max = 1000000,
0048             .tIR_min = 10000,
0049             .tITC_max = 1000000,
0050             .tRC_min = 100000,
0051             .tREA_max = 40000,
0052             .tREH_min = 30000,
0053             .tRHOH_min = 0,
0054             .tRHW_min = 200000,
0055             .tRHZ_max = 200000,
0056             .tRLOH_min = 0,
0057             .tRP_min = 50000,
0058             .tRR_min = 40000,
0059             .tRST_max = 250000000000ULL,
0060             .tWB_max = 200000,
0061             .tWC_min = 100000,
0062             .tWH_min = 30000,
0063             .tWHR_min = 120000,
0064             .tWP_min = 50000,
0065             .tWW_min = 100000,
0066         },
0067     },
0068     /* Mode 1 */
0069     {
0070         .type = NAND_SDR_IFACE,
0071         .timings.mode = 1,
0072         .timings.sdr = {
0073             .tCCS_min = 500000,
0074             .tR_max = 200000000,
0075             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0076             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0077             .tADL_min = 400000,
0078             .tALH_min = 10000,
0079             .tALS_min = 25000,
0080             .tAR_min = 10000,
0081             .tCEA_max = 45000,
0082             .tCEH_min = 20000,
0083             .tCH_min = 10000,
0084             .tCHZ_max = 50000,
0085             .tCLH_min = 10000,
0086             .tCLR_min = 10000,
0087             .tCLS_min = 25000,
0088             .tCOH_min = 15000,
0089             .tCS_min = 35000,
0090             .tDH_min = 10000,
0091             .tDS_min = 20000,
0092             .tFEAT_max = 1000000,
0093             .tIR_min = 0,
0094             .tITC_max = 1000000,
0095             .tRC_min = 50000,
0096             .tREA_max = 30000,
0097             .tREH_min = 15000,
0098             .tRHOH_min = 15000,
0099             .tRHW_min = 100000,
0100             .tRHZ_max = 100000,
0101             .tRLOH_min = 0,
0102             .tRP_min = 25000,
0103             .tRR_min = 20000,
0104             .tRST_max = 500000000,
0105             .tWB_max = 100000,
0106             .tWC_min = 45000,
0107             .tWH_min = 15000,
0108             .tWHR_min = 80000,
0109             .tWP_min = 25000,
0110             .tWW_min = 100000,
0111         },
0112     },
0113     /* Mode 2 */
0114     {
0115         .type = NAND_SDR_IFACE,
0116         .timings.mode = 2,
0117         .timings.sdr = {
0118             .tCCS_min = 500000,
0119             .tR_max = 200000000,
0120             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0121             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0122             .tADL_min = 400000,
0123             .tALH_min = 10000,
0124             .tALS_min = 15000,
0125             .tAR_min = 10000,
0126             .tCEA_max = 30000,
0127             .tCEH_min = 20000,
0128             .tCH_min = 10000,
0129             .tCHZ_max = 50000,
0130             .tCLH_min = 10000,
0131             .tCLR_min = 10000,
0132             .tCLS_min = 15000,
0133             .tCOH_min = 15000,
0134             .tCS_min = 25000,
0135             .tDH_min = 5000,
0136             .tDS_min = 15000,
0137             .tFEAT_max = 1000000,
0138             .tIR_min = 0,
0139             .tITC_max = 1000000,
0140             .tRC_min = 35000,
0141             .tREA_max = 25000,
0142             .tREH_min = 15000,
0143             .tRHOH_min = 15000,
0144             .tRHW_min = 100000,
0145             .tRHZ_max = 100000,
0146             .tRLOH_min = 0,
0147             .tRR_min = 20000,
0148             .tRST_max = 500000000,
0149             .tWB_max = 100000,
0150             .tRP_min = 17000,
0151             .tWC_min = 35000,
0152             .tWH_min = 15000,
0153             .tWHR_min = 80000,
0154             .tWP_min = 17000,
0155             .tWW_min = 100000,
0156         },
0157     },
0158     /* Mode 3 */
0159     {
0160         .type = NAND_SDR_IFACE,
0161         .timings.mode = 3,
0162         .timings.sdr = {
0163             .tCCS_min = 500000,
0164             .tR_max = 200000000,
0165             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0166             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0167             .tADL_min = 400000,
0168             .tALH_min = 5000,
0169             .tALS_min = 10000,
0170             .tAR_min = 10000,
0171             .tCEA_max = 25000,
0172             .tCEH_min = 20000,
0173             .tCH_min = 5000,
0174             .tCHZ_max = 50000,
0175             .tCLH_min = 5000,
0176             .tCLR_min = 10000,
0177             .tCLS_min = 10000,
0178             .tCOH_min = 15000,
0179             .tCS_min = 25000,
0180             .tDH_min = 5000,
0181             .tDS_min = 10000,
0182             .tFEAT_max = 1000000,
0183             .tIR_min = 0,
0184             .tITC_max = 1000000,
0185             .tRC_min = 30000,
0186             .tREA_max = 20000,
0187             .tREH_min = 10000,
0188             .tRHOH_min = 15000,
0189             .tRHW_min = 100000,
0190             .tRHZ_max = 100000,
0191             .tRLOH_min = 0,
0192             .tRP_min = 15000,
0193             .tRR_min = 20000,
0194             .tRST_max = 500000000,
0195             .tWB_max = 100000,
0196             .tWC_min = 30000,
0197             .tWH_min = 10000,
0198             .tWHR_min = 80000,
0199             .tWP_min = 15000,
0200             .tWW_min = 100000,
0201         },
0202     },
0203     /* Mode 4 */
0204     {
0205         .type = NAND_SDR_IFACE,
0206         .timings.mode = 4,
0207         .timings.sdr = {
0208             .tCCS_min = 500000,
0209             .tR_max = 200000000,
0210             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0211             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0212             .tADL_min = 400000,
0213             .tALH_min = 5000,
0214             .tALS_min = 10000,
0215             .tAR_min = 10000,
0216             .tCEA_max = 25000,
0217             .tCEH_min = 20000,
0218             .tCH_min = 5000,
0219             .tCHZ_max = 30000,
0220             .tCLH_min = 5000,
0221             .tCLR_min = 10000,
0222             .tCLS_min = 10000,
0223             .tCOH_min = 15000,
0224             .tCS_min = 20000,
0225             .tDH_min = 5000,
0226             .tDS_min = 10000,
0227             .tFEAT_max = 1000000,
0228             .tIR_min = 0,
0229             .tITC_max = 1000000,
0230             .tRC_min = 25000,
0231             .tREA_max = 20000,
0232             .tREH_min = 10000,
0233             .tRHOH_min = 15000,
0234             .tRHW_min = 100000,
0235             .tRHZ_max = 100000,
0236             .tRLOH_min = 5000,
0237             .tRP_min = 12000,
0238             .tRR_min = 20000,
0239             .tRST_max = 500000000,
0240             .tWB_max = 100000,
0241             .tWC_min = 25000,
0242             .tWH_min = 10000,
0243             .tWHR_min = 80000,
0244             .tWP_min = 12000,
0245             .tWW_min = 100000,
0246         },
0247     },
0248     /* Mode 5 */
0249     {
0250         .type = NAND_SDR_IFACE,
0251         .timings.mode = 5,
0252         .timings.sdr = {
0253             .tCCS_min = 500000,
0254             .tR_max = 200000000,
0255             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0256             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0257             .tADL_min = 400000,
0258             .tALH_min = 5000,
0259             .tALS_min = 10000,
0260             .tAR_min = 10000,
0261             .tCEA_max = 25000,
0262             .tCEH_min = 20000,
0263             .tCH_min = 5000,
0264             .tCHZ_max = 30000,
0265             .tCLH_min = 5000,
0266             .tCLR_min = 10000,
0267             .tCLS_min = 10000,
0268             .tCOH_min = 15000,
0269             .tCS_min = 15000,
0270             .tDH_min = 5000,
0271             .tDS_min = 7000,
0272             .tFEAT_max = 1000000,
0273             .tIR_min = 0,
0274             .tITC_max = 1000000,
0275             .tRC_min = 20000,
0276             .tREA_max = 16000,
0277             .tREH_min = 7000,
0278             .tRHOH_min = 15000,
0279             .tRHW_min = 100000,
0280             .tRHZ_max = 100000,
0281             .tRLOH_min = 5000,
0282             .tRP_min = 10000,
0283             .tRR_min = 20000,
0284             .tRST_max = 500000000,
0285             .tWB_max = 100000,
0286             .tWC_min = 20000,
0287             .tWH_min = 7000,
0288             .tWHR_min = 80000,
0289             .tWP_min = 10000,
0290             .tWW_min = 100000,
0291         },
0292     },
0293 };
0294 
0295 static const struct nand_interface_config onfi_nvddr_timings[] = {
0296     /* Mode 0 */
0297     {
0298         .type = NAND_NVDDR_IFACE,
0299         .timings.mode = 0,
0300         .timings.nvddr = {
0301             .tCCS_min = 500000,
0302             .tR_max = 200000000,
0303             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0304             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0305             .tAC_min = 3000,
0306             .tAC_max = 25000,
0307             .tADL_min = 400000,
0308             .tCAD_min = 45000,
0309             .tCAH_min = 10000,
0310             .tCALH_min = 10000,
0311             .tCALS_min = 10000,
0312             .tCAS_min = 10000,
0313             .tCEH_min = 20000,
0314             .tCH_min = 10000,
0315             .tCK_min = 50000,
0316             .tCS_min = 35000,
0317             .tDH_min = 5000,
0318             .tDQSCK_min = 3000,
0319             .tDQSCK_max = 25000,
0320             .tDQSD_min = 0,
0321             .tDQSD_max = 18000,
0322             .tDQSHZ_max = 20000,
0323             .tDQSQ_max = 5000,
0324             .tDS_min = 5000,
0325             .tDSC_min = 50000,
0326             .tFEAT_max = 1000000,
0327             .tITC_max = 1000000,
0328             .tQHS_max = 6000,
0329             .tRHW_min = 100000,
0330             .tRR_min = 20000,
0331             .tRST_max = 500000000,
0332             .tWB_max = 100000,
0333             .tWHR_min = 80000,
0334             .tWRCK_min = 20000,
0335             .tWW_min = 100000,
0336         },
0337     },
0338     /* Mode 1 */
0339     {
0340         .type = NAND_NVDDR_IFACE,
0341         .timings.mode = 1,
0342         .timings.nvddr = {
0343             .tCCS_min = 500000,
0344             .tR_max = 200000000,
0345             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0346             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0347             .tAC_min = 3000,
0348             .tAC_max = 25000,
0349             .tADL_min = 400000,
0350             .tCAD_min = 45000,
0351             .tCAH_min = 5000,
0352             .tCALH_min = 5000,
0353             .tCALS_min = 5000,
0354             .tCAS_min = 5000,
0355             .tCEH_min = 20000,
0356             .tCH_min = 5000,
0357             .tCK_min = 30000,
0358             .tCS_min = 25000,
0359             .tDH_min = 2500,
0360             .tDQSCK_min = 3000,
0361             .tDQSCK_max = 25000,
0362             .tDQSD_min = 0,
0363             .tDQSD_max = 18000,
0364             .tDQSHZ_max = 20000,
0365             .tDQSQ_max = 2500,
0366             .tDS_min = 3000,
0367             .tDSC_min = 30000,
0368             .tFEAT_max = 1000000,
0369             .tITC_max = 1000000,
0370             .tQHS_max = 3000,
0371             .tRHW_min = 100000,
0372             .tRR_min = 20000,
0373             .tRST_max = 500000000,
0374             .tWB_max = 100000,
0375             .tWHR_min = 80000,
0376             .tWRCK_min = 20000,
0377             .tWW_min = 100000,
0378         },
0379     },
0380     /* Mode 2 */
0381     {
0382         .type = NAND_NVDDR_IFACE,
0383         .timings.mode = 2,
0384         .timings.nvddr = {
0385             .tCCS_min = 500000,
0386             .tR_max = 200000000,
0387             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0388             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0389             .tAC_min = 3000,
0390             .tAC_max = 25000,
0391             .tADL_min = 400000,
0392             .tCAD_min = 45000,
0393             .tCAH_min = 4000,
0394             .tCALH_min = 4000,
0395             .tCALS_min = 4000,
0396             .tCAS_min = 4000,
0397             .tCEH_min = 20000,
0398             .tCH_min = 4000,
0399             .tCK_min = 20000,
0400             .tCS_min = 15000,
0401             .tDH_min = 1700,
0402             .tDQSCK_min = 3000,
0403             .tDQSCK_max = 25000,
0404             .tDQSD_min = 0,
0405             .tDQSD_max = 18000,
0406             .tDQSHZ_max = 20000,
0407             .tDQSQ_max = 1700,
0408             .tDS_min = 2000,
0409             .tDSC_min = 20000,
0410             .tFEAT_max = 1000000,
0411             .tITC_max = 1000000,
0412             .tQHS_max = 2000,
0413             .tRHW_min = 100000,
0414             .tRR_min = 20000,
0415             .tRST_max = 500000000,
0416             .tWB_max = 100000,
0417             .tWHR_min = 80000,
0418             .tWRCK_min = 20000,
0419             .tWW_min = 100000,
0420         },
0421     },
0422     /* Mode 3 */
0423     {
0424         .type = NAND_NVDDR_IFACE,
0425         .timings.mode = 3,
0426         .timings.nvddr = {
0427             .tCCS_min = 500000,
0428             .tR_max = 200000000,
0429             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0430             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0431             .tAC_min = 3000,
0432             .tAC_max = 25000,
0433             .tADL_min = 400000,
0434             .tCAD_min = 45000,
0435             .tCAH_min = 3000,
0436             .tCALH_min = 3000,
0437             .tCALS_min = 3000,
0438             .tCAS_min = 3000,
0439             .tCEH_min = 20000,
0440             .tCH_min = 3000,
0441             .tCK_min = 15000,
0442             .tCS_min = 15000,
0443             .tDH_min = 1300,
0444             .tDQSCK_min = 3000,
0445             .tDQSCK_max = 25000,
0446             .tDQSD_min = 0,
0447             .tDQSD_max = 18000,
0448             .tDQSHZ_max = 20000,
0449             .tDQSQ_max = 1300,
0450             .tDS_min = 1500,
0451             .tDSC_min = 15000,
0452             .tFEAT_max = 1000000,
0453             .tITC_max = 1000000,
0454             .tQHS_max = 1500,
0455             .tRHW_min = 100000,
0456             .tRR_min = 20000,
0457             .tRST_max = 500000000,
0458             .tWB_max = 100000,
0459             .tWHR_min = 80000,
0460             .tWRCK_min = 20000,
0461             .tWW_min = 100000,
0462         },
0463     },
0464     /* Mode 4 */
0465     {
0466         .type = NAND_NVDDR_IFACE,
0467         .timings.mode = 4,
0468         .timings.nvddr = {
0469             .tCCS_min = 500000,
0470             .tR_max = 200000000,
0471             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0472             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0473             .tAC_min = 3000,
0474             .tAC_max = 25000,
0475             .tADL_min = 400000,
0476             .tCAD_min = 45000,
0477             .tCAH_min = 2500,
0478             .tCALH_min = 2500,
0479             .tCALS_min = 2500,
0480             .tCAS_min = 2500,
0481             .tCEH_min = 20000,
0482             .tCH_min = 2500,
0483             .tCK_min = 12000,
0484             .tCS_min = 15000,
0485             .tDH_min = 1100,
0486             .tDQSCK_min = 3000,
0487             .tDQSCK_max = 25000,
0488             .tDQSD_min = 0,
0489             .tDQSD_max = 18000,
0490             .tDQSHZ_max = 20000,
0491             .tDQSQ_max = 1000,
0492             .tDS_min = 1100,
0493             .tDSC_min = 12000,
0494             .tFEAT_max = 1000000,
0495             .tITC_max = 1000000,
0496             .tQHS_max = 1200,
0497             .tRHW_min = 100000,
0498             .tRR_min = 20000,
0499             .tRST_max = 500000000,
0500             .tWB_max = 100000,
0501             .tWHR_min = 80000,
0502             .tWRCK_min = 20000,
0503             .tWW_min = 100000,
0504         },
0505     },
0506     /* Mode 5 */
0507     {
0508         .type = NAND_NVDDR_IFACE,
0509         .timings.mode = 5,
0510         .timings.nvddr = {
0511             .tCCS_min = 500000,
0512             .tR_max = 200000000,
0513             .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0514             .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
0515             .tAC_min = 3000,
0516             .tAC_max = 25000,
0517             .tADL_min = 400000,
0518             .tCAD_min = 45000,
0519             .tCAH_min = 2000,
0520             .tCALH_min = 2000,
0521             .tCALS_min = 2000,
0522             .tCAS_min = 2000,
0523             .tCEH_min = 20000,
0524             .tCH_min = 2000,
0525             .tCK_min = 10000,
0526             .tCS_min = 15000,
0527             .tDH_min = 900,
0528             .tDQSCK_min = 3000,
0529             .tDQSCK_max = 25000,
0530             .tDQSD_min = 0,
0531             .tDQSD_max = 18000,
0532             .tDQSHZ_max = 20000,
0533             .tDQSQ_max = 850,
0534             .tDS_min = 900,
0535             .tDSC_min = 10000,
0536             .tFEAT_max = 1000000,
0537             .tITC_max = 1000000,
0538             .tQHS_max = 1000,
0539             .tRHW_min = 100000,
0540             .tRR_min = 20000,
0541             .tRST_max = 500000000,
0542             .tWB_max = 100000,
0543             .tWHR_min = 80000,
0544             .tWRCK_min = 20000,
0545             .tWW_min = 100000,
0546         },
0547     },
0548 };
0549 
0550 /* All NAND chips share the same reset data interface: SDR mode 0 */
0551 const struct nand_interface_config *nand_get_reset_interface_config(void)
0552 {
0553     return &onfi_sdr_timings[0];
0554 }
0555 
0556 /**
0557  * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
0558  *                              set of timings
0559  * @spec_timings: the timings to challenge
0560  */
0561 unsigned int
0562 onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
0563 {
0564     const struct nand_sdr_timings *onfi_timings;
0565     int mode;
0566 
0567     for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
0568         onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
0569 
0570         if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
0571             spec_timings->tADL_min <= onfi_timings->tADL_min &&
0572             spec_timings->tALH_min <= onfi_timings->tALH_min &&
0573             spec_timings->tALS_min <= onfi_timings->tALS_min &&
0574             spec_timings->tAR_min <= onfi_timings->tAR_min &&
0575             spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
0576             spec_timings->tCH_min <= onfi_timings->tCH_min &&
0577             spec_timings->tCLH_min <= onfi_timings->tCLH_min &&
0578             spec_timings->tCLR_min <= onfi_timings->tCLR_min &&
0579             spec_timings->tCLS_min <= onfi_timings->tCLS_min &&
0580             spec_timings->tCOH_min <= onfi_timings->tCOH_min &&
0581             spec_timings->tCS_min <= onfi_timings->tCS_min &&
0582             spec_timings->tDH_min <= onfi_timings->tDH_min &&
0583             spec_timings->tDS_min <= onfi_timings->tDS_min &&
0584             spec_timings->tIR_min <= onfi_timings->tIR_min &&
0585             spec_timings->tRC_min <= onfi_timings->tRC_min &&
0586             spec_timings->tREH_min <= onfi_timings->tREH_min &&
0587             spec_timings->tRHOH_min <= onfi_timings->tRHOH_min &&
0588             spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
0589             spec_timings->tRLOH_min <= onfi_timings->tRLOH_min &&
0590             spec_timings->tRP_min <= onfi_timings->tRP_min &&
0591             spec_timings->tRR_min <= onfi_timings->tRR_min &&
0592             spec_timings->tWC_min <= onfi_timings->tWC_min &&
0593             spec_timings->tWH_min <= onfi_timings->tWH_min &&
0594             spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
0595             spec_timings->tWP_min <= onfi_timings->tWP_min &&
0596             spec_timings->tWW_min <= onfi_timings->tWW_min)
0597             return mode;
0598     }
0599 
0600     return 0;
0601 }
0602 
0603 /**
0604  * onfi_find_closest_nvddr_mode - Derive the closest ONFI NVDDR timing mode
0605  *                                given a set of timings
0606  * @spec_timings: the timings to challenge
0607  */
0608 unsigned int
0609 onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings)
0610 {
0611     const struct nand_nvddr_timings *onfi_timings;
0612     int mode;
0613 
0614     for (mode = ARRAY_SIZE(onfi_nvddr_timings) - 1; mode > 0; mode--) {
0615         onfi_timings = &onfi_nvddr_timings[mode].timings.nvddr;
0616 
0617         if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
0618             spec_timings->tAC_min <= onfi_timings->tAC_min &&
0619             spec_timings->tADL_min <= onfi_timings->tADL_min &&
0620             spec_timings->tCAD_min <= onfi_timings->tCAD_min &&
0621             spec_timings->tCAH_min <= onfi_timings->tCAH_min &&
0622             spec_timings->tCALH_min <= onfi_timings->tCALH_min &&
0623             spec_timings->tCALS_min <= onfi_timings->tCALS_min &&
0624             spec_timings->tCAS_min <= onfi_timings->tCAS_min &&
0625             spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
0626             spec_timings->tCH_min <= onfi_timings->tCH_min &&
0627             spec_timings->tCK_min <= onfi_timings->tCK_min &&
0628             spec_timings->tCS_min <= onfi_timings->tCS_min &&
0629             spec_timings->tDH_min <= onfi_timings->tDH_min &&
0630             spec_timings->tDQSCK_min <= onfi_timings->tDQSCK_min &&
0631             spec_timings->tDQSD_min <= onfi_timings->tDQSD_min &&
0632             spec_timings->tDS_min <= onfi_timings->tDS_min &&
0633             spec_timings->tDSC_min <= onfi_timings->tDSC_min &&
0634             spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
0635             spec_timings->tRR_min <= onfi_timings->tRR_min &&
0636             spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
0637             spec_timings->tWRCK_min <= onfi_timings->tWRCK_min &&
0638             spec_timings->tWW_min <= onfi_timings->tWW_min)
0639             return mode;
0640     }
0641 
0642     return 0;
0643 }
0644 
0645 /*
0646  * onfi_fill_sdr_interface_config - Initialize a SDR interface config from a
0647  *                                  given ONFI mode
0648  * @chip: The NAND chip
0649  * @iface: The interface configuration to fill
0650  * @timing_mode: The ONFI timing mode
0651  */
0652 static void onfi_fill_sdr_interface_config(struct nand_chip *chip,
0653                        struct nand_interface_config *iface,
0654                        unsigned int timing_mode)
0655 {
0656     struct onfi_params *onfi = chip->parameters.onfi;
0657 
0658     if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
0659         return;
0660 
0661     *iface = onfi_sdr_timings[timing_mode];
0662 
0663     /*
0664      * Initialize timings that cannot be deduced from timing mode:
0665      * tPROG, tBERS, tR and tCCS.
0666      * These information are part of the ONFI parameter page.
0667      */
0668     if (onfi) {
0669         struct nand_sdr_timings *timings = &iface->timings.sdr;
0670 
0671         /* microseconds -> picoseconds */
0672         timings->tPROG_max = 1000000ULL * onfi->tPROG;
0673         timings->tBERS_max = 1000000ULL * onfi->tBERS;
0674         timings->tR_max = 1000000ULL * onfi->tR;
0675 
0676         /* nanoseconds -> picoseconds */
0677         timings->tCCS_min = 1000UL * onfi->tCCS;
0678     }
0679 }
0680 
0681 /**
0682  * onfi_fill_nvddr_interface_config - Initialize a NVDDR interface config from a
0683  *                                    given ONFI mode
0684  * @chip: The NAND chip
0685  * @iface: The interface configuration to fill
0686  * @timing_mode: The ONFI timing mode
0687  */
0688 static void onfi_fill_nvddr_interface_config(struct nand_chip *chip,
0689                          struct nand_interface_config *iface,
0690                          unsigned int timing_mode)
0691 {
0692     struct onfi_params *onfi = chip->parameters.onfi;
0693 
0694     if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_nvddr_timings)))
0695         return;
0696 
0697     *iface = onfi_nvddr_timings[timing_mode];
0698 
0699     /*
0700      * Initialize timings that cannot be deduced from timing mode:
0701      * tPROG, tBERS, tR, tCCS and tCAD.
0702      * These information are part of the ONFI parameter page.
0703      */
0704     if (onfi) {
0705         struct nand_nvddr_timings *timings = &iface->timings.nvddr;
0706 
0707         /* microseconds -> picoseconds */
0708         timings->tPROG_max = 1000000ULL * onfi->tPROG;
0709         timings->tBERS_max = 1000000ULL * onfi->tBERS;
0710         timings->tR_max = 1000000ULL * onfi->tR;
0711 
0712         /* nanoseconds -> picoseconds */
0713         timings->tCCS_min = 1000UL * onfi->tCCS;
0714 
0715         if (onfi->fast_tCAD)
0716             timings->tCAD_min = 25000;
0717     }
0718 }
0719 
0720 /**
0721  * onfi_fill_interface_config - Initialize an interface config from a given
0722  *                              ONFI mode
0723  * @chip: The NAND chip
0724  * @iface: The interface configuration to fill
0725  * @type: The interface type
0726  * @timing_mode: The ONFI timing mode
0727  */
0728 void onfi_fill_interface_config(struct nand_chip *chip,
0729                 struct nand_interface_config *iface,
0730                 enum nand_interface_type type,
0731                 unsigned int timing_mode)
0732 {
0733     if (type == NAND_SDR_IFACE)
0734         return onfi_fill_sdr_interface_config(chip, iface, timing_mode);
0735     else
0736         return onfi_fill_nvddr_interface_config(chip, iface, timing_mode);
0737 }