18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2014 Free Electrons 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include <linux/kernel.h> 88c2ecf20Sopenharmony_ci#include <linux/err.h> 98c2ecf20Sopenharmony_ci#include <linux/export.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "internals.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define ONFI_DYN_TIMING_MAX U16_MAX 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci/* 168c2ecf20Sopenharmony_ci * For non-ONFI chips we use the highest possible value for tPROG and tBERS. 178c2ecf20Sopenharmony_ci * tR and tCCS will take the default values precised in the ONFI specification 188c2ecf20Sopenharmony_ci * for timing mode 0, respectively 200us and 500ns. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * These four values are tweaked to be more accurate in the case of ONFI chips. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_cistatic const struct nand_interface_config onfi_sdr_timings[] = { 238c2ecf20Sopenharmony_ci /* Mode 0 */ 248c2ecf20Sopenharmony_ci { 258c2ecf20Sopenharmony_ci .type = NAND_SDR_IFACE, 268c2ecf20Sopenharmony_ci .timings.mode = 0, 278c2ecf20Sopenharmony_ci .timings.sdr = { 288c2ecf20Sopenharmony_ci .tCCS_min = 500000, 298c2ecf20Sopenharmony_ci .tR_max = 200000000, 308c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 318c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 328c2ecf20Sopenharmony_ci .tADL_min = 400000, 338c2ecf20Sopenharmony_ci .tALH_min = 20000, 348c2ecf20Sopenharmony_ci .tALS_min = 50000, 358c2ecf20Sopenharmony_ci .tAR_min = 25000, 368c2ecf20Sopenharmony_ci .tCEA_max = 100000, 378c2ecf20Sopenharmony_ci .tCEH_min = 20000, 388c2ecf20Sopenharmony_ci .tCH_min = 20000, 398c2ecf20Sopenharmony_ci .tCHZ_max = 100000, 408c2ecf20Sopenharmony_ci .tCLH_min = 20000, 418c2ecf20Sopenharmony_ci .tCLR_min = 20000, 428c2ecf20Sopenharmony_ci .tCLS_min = 50000, 438c2ecf20Sopenharmony_ci .tCOH_min = 0, 448c2ecf20Sopenharmony_ci .tCS_min = 70000, 458c2ecf20Sopenharmony_ci .tDH_min = 20000, 468c2ecf20Sopenharmony_ci .tDS_min = 40000, 478c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 488c2ecf20Sopenharmony_ci .tIR_min = 10000, 498c2ecf20Sopenharmony_ci .tITC_max = 1000000, 508c2ecf20Sopenharmony_ci .tRC_min = 100000, 518c2ecf20Sopenharmony_ci .tREA_max = 40000, 528c2ecf20Sopenharmony_ci .tREH_min = 30000, 538c2ecf20Sopenharmony_ci .tRHOH_min = 0, 548c2ecf20Sopenharmony_ci .tRHW_min = 200000, 558c2ecf20Sopenharmony_ci .tRHZ_max = 200000, 568c2ecf20Sopenharmony_ci .tRLOH_min = 0, 578c2ecf20Sopenharmony_ci .tRP_min = 50000, 588c2ecf20Sopenharmony_ci .tRR_min = 40000, 598c2ecf20Sopenharmony_ci .tRST_max = 250000000000ULL, 608c2ecf20Sopenharmony_ci .tWB_max = 200000, 618c2ecf20Sopenharmony_ci .tWC_min = 100000, 628c2ecf20Sopenharmony_ci .tWH_min = 30000, 638c2ecf20Sopenharmony_ci .tWHR_min = 120000, 648c2ecf20Sopenharmony_ci .tWP_min = 50000, 658c2ecf20Sopenharmony_ci .tWW_min = 100000, 668c2ecf20Sopenharmony_ci }, 678c2ecf20Sopenharmony_ci }, 688c2ecf20Sopenharmony_ci /* Mode 1 */ 698c2ecf20Sopenharmony_ci { 708c2ecf20Sopenharmony_ci .type = NAND_SDR_IFACE, 718c2ecf20Sopenharmony_ci .timings.mode = 1, 728c2ecf20Sopenharmony_ci .timings.sdr = { 738c2ecf20Sopenharmony_ci .tCCS_min = 500000, 748c2ecf20Sopenharmony_ci .tR_max = 200000000, 758c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 768c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 778c2ecf20Sopenharmony_ci .tADL_min = 400000, 788c2ecf20Sopenharmony_ci .tALH_min = 10000, 798c2ecf20Sopenharmony_ci .tALS_min = 25000, 808c2ecf20Sopenharmony_ci .tAR_min = 10000, 818c2ecf20Sopenharmony_ci .tCEA_max = 45000, 828c2ecf20Sopenharmony_ci .tCEH_min = 20000, 838c2ecf20Sopenharmony_ci .tCH_min = 10000, 848c2ecf20Sopenharmony_ci .tCHZ_max = 50000, 858c2ecf20Sopenharmony_ci .tCLH_min = 10000, 868c2ecf20Sopenharmony_ci .tCLR_min = 10000, 878c2ecf20Sopenharmony_ci .tCLS_min = 25000, 888c2ecf20Sopenharmony_ci .tCOH_min = 15000, 898c2ecf20Sopenharmony_ci .tCS_min = 35000, 908c2ecf20Sopenharmony_ci .tDH_min = 10000, 918c2ecf20Sopenharmony_ci .tDS_min = 20000, 928c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 938c2ecf20Sopenharmony_ci .tIR_min = 0, 948c2ecf20Sopenharmony_ci .tITC_max = 1000000, 958c2ecf20Sopenharmony_ci .tRC_min = 50000, 968c2ecf20Sopenharmony_ci .tREA_max = 30000, 978c2ecf20Sopenharmony_ci .tREH_min = 15000, 988c2ecf20Sopenharmony_ci .tRHOH_min = 15000, 998c2ecf20Sopenharmony_ci .tRHW_min = 100000, 1008c2ecf20Sopenharmony_ci .tRHZ_max = 100000, 1018c2ecf20Sopenharmony_ci .tRLOH_min = 0, 1028c2ecf20Sopenharmony_ci .tRP_min = 25000, 1038c2ecf20Sopenharmony_ci .tRR_min = 20000, 1048c2ecf20Sopenharmony_ci .tRST_max = 500000000, 1058c2ecf20Sopenharmony_ci .tWB_max = 100000, 1068c2ecf20Sopenharmony_ci .tWC_min = 45000, 1078c2ecf20Sopenharmony_ci .tWH_min = 15000, 1088c2ecf20Sopenharmony_ci .tWHR_min = 80000, 1098c2ecf20Sopenharmony_ci .tWP_min = 25000, 1108c2ecf20Sopenharmony_ci .tWW_min = 100000, 1118c2ecf20Sopenharmony_ci }, 1128c2ecf20Sopenharmony_ci }, 1138c2ecf20Sopenharmony_ci /* Mode 2 */ 1148c2ecf20Sopenharmony_ci { 1158c2ecf20Sopenharmony_ci .type = NAND_SDR_IFACE, 1168c2ecf20Sopenharmony_ci .timings.mode = 2, 1178c2ecf20Sopenharmony_ci .timings.sdr = { 1188c2ecf20Sopenharmony_ci .tCCS_min = 500000, 1198c2ecf20Sopenharmony_ci .tR_max = 200000000, 1208c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 1218c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 1228c2ecf20Sopenharmony_ci .tADL_min = 400000, 1238c2ecf20Sopenharmony_ci .tALH_min = 10000, 1248c2ecf20Sopenharmony_ci .tALS_min = 15000, 1258c2ecf20Sopenharmony_ci .tAR_min = 10000, 1268c2ecf20Sopenharmony_ci .tCEA_max = 30000, 1278c2ecf20Sopenharmony_ci .tCEH_min = 20000, 1288c2ecf20Sopenharmony_ci .tCH_min = 10000, 1298c2ecf20Sopenharmony_ci .tCHZ_max = 50000, 1308c2ecf20Sopenharmony_ci .tCLH_min = 10000, 1318c2ecf20Sopenharmony_ci .tCLR_min = 10000, 1328c2ecf20Sopenharmony_ci .tCLS_min = 15000, 1338c2ecf20Sopenharmony_ci .tCOH_min = 15000, 1348c2ecf20Sopenharmony_ci .tCS_min = 25000, 1358c2ecf20Sopenharmony_ci .tDH_min = 5000, 1368c2ecf20Sopenharmony_ci .tDS_min = 15000, 1378c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 1388c2ecf20Sopenharmony_ci .tIR_min = 0, 1398c2ecf20Sopenharmony_ci .tITC_max = 1000000, 1408c2ecf20Sopenharmony_ci .tRC_min = 35000, 1418c2ecf20Sopenharmony_ci .tREA_max = 25000, 1428c2ecf20Sopenharmony_ci .tREH_min = 15000, 1438c2ecf20Sopenharmony_ci .tRHOH_min = 15000, 1448c2ecf20Sopenharmony_ci .tRHW_min = 100000, 1458c2ecf20Sopenharmony_ci .tRHZ_max = 100000, 1468c2ecf20Sopenharmony_ci .tRLOH_min = 0, 1478c2ecf20Sopenharmony_ci .tRR_min = 20000, 1488c2ecf20Sopenharmony_ci .tRST_max = 500000000, 1498c2ecf20Sopenharmony_ci .tWB_max = 100000, 1508c2ecf20Sopenharmony_ci .tRP_min = 17000, 1518c2ecf20Sopenharmony_ci .tWC_min = 35000, 1528c2ecf20Sopenharmony_ci .tWH_min = 15000, 1538c2ecf20Sopenharmony_ci .tWHR_min = 80000, 1548c2ecf20Sopenharmony_ci .tWP_min = 17000, 1558c2ecf20Sopenharmony_ci .tWW_min = 100000, 1568c2ecf20Sopenharmony_ci }, 1578c2ecf20Sopenharmony_ci }, 1588c2ecf20Sopenharmony_ci /* Mode 3 */ 1598c2ecf20Sopenharmony_ci { 1608c2ecf20Sopenharmony_ci .type = NAND_SDR_IFACE, 1618c2ecf20Sopenharmony_ci .timings.mode = 3, 1628c2ecf20Sopenharmony_ci .timings.sdr = { 1638c2ecf20Sopenharmony_ci .tCCS_min = 500000, 1648c2ecf20Sopenharmony_ci .tR_max = 200000000, 1658c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 1668c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 1678c2ecf20Sopenharmony_ci .tADL_min = 400000, 1688c2ecf20Sopenharmony_ci .tALH_min = 5000, 1698c2ecf20Sopenharmony_ci .tALS_min = 10000, 1708c2ecf20Sopenharmony_ci .tAR_min = 10000, 1718c2ecf20Sopenharmony_ci .tCEA_max = 25000, 1728c2ecf20Sopenharmony_ci .tCEH_min = 20000, 1738c2ecf20Sopenharmony_ci .tCH_min = 5000, 1748c2ecf20Sopenharmony_ci .tCHZ_max = 50000, 1758c2ecf20Sopenharmony_ci .tCLH_min = 5000, 1768c2ecf20Sopenharmony_ci .tCLR_min = 10000, 1778c2ecf20Sopenharmony_ci .tCLS_min = 10000, 1788c2ecf20Sopenharmony_ci .tCOH_min = 15000, 1798c2ecf20Sopenharmony_ci .tCS_min = 25000, 1808c2ecf20Sopenharmony_ci .tDH_min = 5000, 1818c2ecf20Sopenharmony_ci .tDS_min = 10000, 1828c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 1838c2ecf20Sopenharmony_ci .tIR_min = 0, 1848c2ecf20Sopenharmony_ci .tITC_max = 1000000, 1858c2ecf20Sopenharmony_ci .tRC_min = 30000, 1868c2ecf20Sopenharmony_ci .tREA_max = 20000, 1878c2ecf20Sopenharmony_ci .tREH_min = 10000, 1888c2ecf20Sopenharmony_ci .tRHOH_min = 15000, 1898c2ecf20Sopenharmony_ci .tRHW_min = 100000, 1908c2ecf20Sopenharmony_ci .tRHZ_max = 100000, 1918c2ecf20Sopenharmony_ci .tRLOH_min = 0, 1928c2ecf20Sopenharmony_ci .tRP_min = 15000, 1938c2ecf20Sopenharmony_ci .tRR_min = 20000, 1948c2ecf20Sopenharmony_ci .tRST_max = 500000000, 1958c2ecf20Sopenharmony_ci .tWB_max = 100000, 1968c2ecf20Sopenharmony_ci .tWC_min = 30000, 1978c2ecf20Sopenharmony_ci .tWH_min = 10000, 1988c2ecf20Sopenharmony_ci .tWHR_min = 80000, 1998c2ecf20Sopenharmony_ci .tWP_min = 15000, 2008c2ecf20Sopenharmony_ci .tWW_min = 100000, 2018c2ecf20Sopenharmony_ci }, 2028c2ecf20Sopenharmony_ci }, 2038c2ecf20Sopenharmony_ci /* Mode 4 */ 2048c2ecf20Sopenharmony_ci { 2058c2ecf20Sopenharmony_ci .type = NAND_SDR_IFACE, 2068c2ecf20Sopenharmony_ci .timings.mode = 4, 2078c2ecf20Sopenharmony_ci .timings.sdr = { 2088c2ecf20Sopenharmony_ci .tCCS_min = 500000, 2098c2ecf20Sopenharmony_ci .tR_max = 200000000, 2108c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 2118c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 2128c2ecf20Sopenharmony_ci .tADL_min = 400000, 2138c2ecf20Sopenharmony_ci .tALH_min = 5000, 2148c2ecf20Sopenharmony_ci .tALS_min = 10000, 2158c2ecf20Sopenharmony_ci .tAR_min = 10000, 2168c2ecf20Sopenharmony_ci .tCEA_max = 25000, 2178c2ecf20Sopenharmony_ci .tCEH_min = 20000, 2188c2ecf20Sopenharmony_ci .tCH_min = 5000, 2198c2ecf20Sopenharmony_ci .tCHZ_max = 30000, 2208c2ecf20Sopenharmony_ci .tCLH_min = 5000, 2218c2ecf20Sopenharmony_ci .tCLR_min = 10000, 2228c2ecf20Sopenharmony_ci .tCLS_min = 10000, 2238c2ecf20Sopenharmony_ci .tCOH_min = 15000, 2248c2ecf20Sopenharmony_ci .tCS_min = 20000, 2258c2ecf20Sopenharmony_ci .tDH_min = 5000, 2268c2ecf20Sopenharmony_ci .tDS_min = 10000, 2278c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 2288c2ecf20Sopenharmony_ci .tIR_min = 0, 2298c2ecf20Sopenharmony_ci .tITC_max = 1000000, 2308c2ecf20Sopenharmony_ci .tRC_min = 25000, 2318c2ecf20Sopenharmony_ci .tREA_max = 20000, 2328c2ecf20Sopenharmony_ci .tREH_min = 10000, 2338c2ecf20Sopenharmony_ci .tRHOH_min = 15000, 2348c2ecf20Sopenharmony_ci .tRHW_min = 100000, 2358c2ecf20Sopenharmony_ci .tRHZ_max = 100000, 2368c2ecf20Sopenharmony_ci .tRLOH_min = 5000, 2378c2ecf20Sopenharmony_ci .tRP_min = 12000, 2388c2ecf20Sopenharmony_ci .tRR_min = 20000, 2398c2ecf20Sopenharmony_ci .tRST_max = 500000000, 2408c2ecf20Sopenharmony_ci .tWB_max = 100000, 2418c2ecf20Sopenharmony_ci .tWC_min = 25000, 2428c2ecf20Sopenharmony_ci .tWH_min = 10000, 2438c2ecf20Sopenharmony_ci .tWHR_min = 80000, 2448c2ecf20Sopenharmony_ci .tWP_min = 12000, 2458c2ecf20Sopenharmony_ci .tWW_min = 100000, 2468c2ecf20Sopenharmony_ci }, 2478c2ecf20Sopenharmony_ci }, 2488c2ecf20Sopenharmony_ci /* Mode 5 */ 2498c2ecf20Sopenharmony_ci { 2508c2ecf20Sopenharmony_ci .type = NAND_SDR_IFACE, 2518c2ecf20Sopenharmony_ci .timings.mode = 5, 2528c2ecf20Sopenharmony_ci .timings.sdr = { 2538c2ecf20Sopenharmony_ci .tCCS_min = 500000, 2548c2ecf20Sopenharmony_ci .tR_max = 200000000, 2558c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 2568c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 2578c2ecf20Sopenharmony_ci .tADL_min = 400000, 2588c2ecf20Sopenharmony_ci .tALH_min = 5000, 2598c2ecf20Sopenharmony_ci .tALS_min = 10000, 2608c2ecf20Sopenharmony_ci .tAR_min = 10000, 2618c2ecf20Sopenharmony_ci .tCEA_max = 25000, 2628c2ecf20Sopenharmony_ci .tCEH_min = 20000, 2638c2ecf20Sopenharmony_ci .tCH_min = 5000, 2648c2ecf20Sopenharmony_ci .tCHZ_max = 30000, 2658c2ecf20Sopenharmony_ci .tCLH_min = 5000, 2668c2ecf20Sopenharmony_ci .tCLR_min = 10000, 2678c2ecf20Sopenharmony_ci .tCLS_min = 10000, 2688c2ecf20Sopenharmony_ci .tCOH_min = 15000, 2698c2ecf20Sopenharmony_ci .tCS_min = 15000, 2708c2ecf20Sopenharmony_ci .tDH_min = 5000, 2718c2ecf20Sopenharmony_ci .tDS_min = 7000, 2728c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 2738c2ecf20Sopenharmony_ci .tIR_min = 0, 2748c2ecf20Sopenharmony_ci .tITC_max = 1000000, 2758c2ecf20Sopenharmony_ci .tRC_min = 20000, 2768c2ecf20Sopenharmony_ci .tREA_max = 16000, 2778c2ecf20Sopenharmony_ci .tREH_min = 7000, 2788c2ecf20Sopenharmony_ci .tRHOH_min = 15000, 2798c2ecf20Sopenharmony_ci .tRHW_min = 100000, 2808c2ecf20Sopenharmony_ci .tRHZ_max = 100000, 2818c2ecf20Sopenharmony_ci .tRLOH_min = 5000, 2828c2ecf20Sopenharmony_ci .tRP_min = 10000, 2838c2ecf20Sopenharmony_ci .tRR_min = 20000, 2848c2ecf20Sopenharmony_ci .tRST_max = 500000000, 2858c2ecf20Sopenharmony_ci .tWB_max = 100000, 2868c2ecf20Sopenharmony_ci .tWC_min = 20000, 2878c2ecf20Sopenharmony_ci .tWH_min = 7000, 2888c2ecf20Sopenharmony_ci .tWHR_min = 80000, 2898c2ecf20Sopenharmony_ci .tWP_min = 10000, 2908c2ecf20Sopenharmony_ci .tWW_min = 100000, 2918c2ecf20Sopenharmony_ci }, 2928c2ecf20Sopenharmony_ci }, 2938c2ecf20Sopenharmony_ci}; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_cistatic const struct nand_interface_config onfi_nvddr_timings[] = { 2968c2ecf20Sopenharmony_ci /* Mode 0 */ 2978c2ecf20Sopenharmony_ci { 2988c2ecf20Sopenharmony_ci .type = NAND_NVDDR_IFACE, 2998c2ecf20Sopenharmony_ci .timings.mode = 0, 3008c2ecf20Sopenharmony_ci .timings.nvddr = { 3018c2ecf20Sopenharmony_ci .tCCS_min = 500000, 3028c2ecf20Sopenharmony_ci .tR_max = 200000000, 3038c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 3048c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 3058c2ecf20Sopenharmony_ci .tAC_min = 3000, 3068c2ecf20Sopenharmony_ci .tAC_max = 25000, 3078c2ecf20Sopenharmony_ci .tADL_min = 400000, 3088c2ecf20Sopenharmony_ci .tCAD_min = 45000, 3098c2ecf20Sopenharmony_ci .tCAH_min = 10000, 3108c2ecf20Sopenharmony_ci .tCALH_min = 10000, 3118c2ecf20Sopenharmony_ci .tCALS_min = 10000, 3128c2ecf20Sopenharmony_ci .tCAS_min = 10000, 3138c2ecf20Sopenharmony_ci .tCEH_min = 20000, 3148c2ecf20Sopenharmony_ci .tCH_min = 10000, 3158c2ecf20Sopenharmony_ci .tCK_min = 50000, 3168c2ecf20Sopenharmony_ci .tCS_min = 35000, 3178c2ecf20Sopenharmony_ci .tDH_min = 5000, 3188c2ecf20Sopenharmony_ci .tDQSCK_min = 3000, 3198c2ecf20Sopenharmony_ci .tDQSCK_max = 25000, 3208c2ecf20Sopenharmony_ci .tDQSD_min = 0, 3218c2ecf20Sopenharmony_ci .tDQSD_max = 18000, 3228c2ecf20Sopenharmony_ci .tDQSHZ_max = 20000, 3238c2ecf20Sopenharmony_ci .tDQSQ_max = 5000, 3248c2ecf20Sopenharmony_ci .tDS_min = 5000, 3258c2ecf20Sopenharmony_ci .tDSC_min = 50000, 3268c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 3278c2ecf20Sopenharmony_ci .tITC_max = 1000000, 3288c2ecf20Sopenharmony_ci .tQHS_max = 6000, 3298c2ecf20Sopenharmony_ci .tRHW_min = 100000, 3308c2ecf20Sopenharmony_ci .tRR_min = 20000, 3318c2ecf20Sopenharmony_ci .tRST_max = 500000000, 3328c2ecf20Sopenharmony_ci .tWB_max = 100000, 3338c2ecf20Sopenharmony_ci .tWHR_min = 80000, 3348c2ecf20Sopenharmony_ci .tWRCK_min = 20000, 3358c2ecf20Sopenharmony_ci .tWW_min = 100000, 3368c2ecf20Sopenharmony_ci }, 3378c2ecf20Sopenharmony_ci }, 3388c2ecf20Sopenharmony_ci /* Mode 1 */ 3398c2ecf20Sopenharmony_ci { 3408c2ecf20Sopenharmony_ci .type = NAND_NVDDR_IFACE, 3418c2ecf20Sopenharmony_ci .timings.mode = 1, 3428c2ecf20Sopenharmony_ci .timings.nvddr = { 3438c2ecf20Sopenharmony_ci .tCCS_min = 500000, 3448c2ecf20Sopenharmony_ci .tR_max = 200000000, 3458c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 3468c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 3478c2ecf20Sopenharmony_ci .tAC_min = 3000, 3488c2ecf20Sopenharmony_ci .tAC_max = 25000, 3498c2ecf20Sopenharmony_ci .tADL_min = 400000, 3508c2ecf20Sopenharmony_ci .tCAD_min = 45000, 3518c2ecf20Sopenharmony_ci .tCAH_min = 5000, 3528c2ecf20Sopenharmony_ci .tCALH_min = 5000, 3538c2ecf20Sopenharmony_ci .tCALS_min = 5000, 3548c2ecf20Sopenharmony_ci .tCAS_min = 5000, 3558c2ecf20Sopenharmony_ci .tCEH_min = 20000, 3568c2ecf20Sopenharmony_ci .tCH_min = 5000, 3578c2ecf20Sopenharmony_ci .tCK_min = 30000, 3588c2ecf20Sopenharmony_ci .tCS_min = 25000, 3598c2ecf20Sopenharmony_ci .tDH_min = 2500, 3608c2ecf20Sopenharmony_ci .tDQSCK_min = 3000, 3618c2ecf20Sopenharmony_ci .tDQSCK_max = 25000, 3628c2ecf20Sopenharmony_ci .tDQSD_min = 0, 3638c2ecf20Sopenharmony_ci .tDQSD_max = 18000, 3648c2ecf20Sopenharmony_ci .tDQSHZ_max = 20000, 3658c2ecf20Sopenharmony_ci .tDQSQ_max = 2500, 3668c2ecf20Sopenharmony_ci .tDS_min = 3000, 3678c2ecf20Sopenharmony_ci .tDSC_min = 30000, 3688c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 3698c2ecf20Sopenharmony_ci .tITC_max = 1000000, 3708c2ecf20Sopenharmony_ci .tQHS_max = 3000, 3718c2ecf20Sopenharmony_ci .tRHW_min = 100000, 3728c2ecf20Sopenharmony_ci .tRR_min = 20000, 3738c2ecf20Sopenharmony_ci .tRST_max = 500000000, 3748c2ecf20Sopenharmony_ci .tWB_max = 100000, 3758c2ecf20Sopenharmony_ci .tWHR_min = 80000, 3768c2ecf20Sopenharmony_ci .tWRCK_min = 20000, 3778c2ecf20Sopenharmony_ci .tWW_min = 100000, 3788c2ecf20Sopenharmony_ci }, 3798c2ecf20Sopenharmony_ci }, 3808c2ecf20Sopenharmony_ci /* Mode 2 */ 3818c2ecf20Sopenharmony_ci { 3828c2ecf20Sopenharmony_ci .type = NAND_NVDDR_IFACE, 3838c2ecf20Sopenharmony_ci .timings.mode = 2, 3848c2ecf20Sopenharmony_ci .timings.nvddr = { 3858c2ecf20Sopenharmony_ci .tCCS_min = 500000, 3868c2ecf20Sopenharmony_ci .tR_max = 200000000, 3878c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 3888c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 3898c2ecf20Sopenharmony_ci .tAC_min = 3000, 3908c2ecf20Sopenharmony_ci .tAC_max = 25000, 3918c2ecf20Sopenharmony_ci .tADL_min = 400000, 3928c2ecf20Sopenharmony_ci .tCAD_min = 45000, 3938c2ecf20Sopenharmony_ci .tCAH_min = 4000, 3948c2ecf20Sopenharmony_ci .tCALH_min = 4000, 3958c2ecf20Sopenharmony_ci .tCALS_min = 4000, 3968c2ecf20Sopenharmony_ci .tCAS_min = 4000, 3978c2ecf20Sopenharmony_ci .tCEH_min = 20000, 3988c2ecf20Sopenharmony_ci .tCH_min = 4000, 3998c2ecf20Sopenharmony_ci .tCK_min = 20000, 4008c2ecf20Sopenharmony_ci .tCS_min = 15000, 4018c2ecf20Sopenharmony_ci .tDH_min = 1700, 4028c2ecf20Sopenharmony_ci .tDQSCK_min = 3000, 4038c2ecf20Sopenharmony_ci .tDQSCK_max = 25000, 4048c2ecf20Sopenharmony_ci .tDQSD_min = 0, 4058c2ecf20Sopenharmony_ci .tDQSD_max = 18000, 4068c2ecf20Sopenharmony_ci .tDQSHZ_max = 20000, 4078c2ecf20Sopenharmony_ci .tDQSQ_max = 1700, 4088c2ecf20Sopenharmony_ci .tDS_min = 2000, 4098c2ecf20Sopenharmony_ci .tDSC_min = 20000, 4108c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 4118c2ecf20Sopenharmony_ci .tITC_max = 1000000, 4128c2ecf20Sopenharmony_ci .tQHS_max = 2000, 4138c2ecf20Sopenharmony_ci .tRHW_min = 100000, 4148c2ecf20Sopenharmony_ci .tRR_min = 20000, 4158c2ecf20Sopenharmony_ci .tRST_max = 500000000, 4168c2ecf20Sopenharmony_ci .tWB_max = 100000, 4178c2ecf20Sopenharmony_ci .tWHR_min = 80000, 4188c2ecf20Sopenharmony_ci .tWRCK_min = 20000, 4198c2ecf20Sopenharmony_ci .tWW_min = 100000, 4208c2ecf20Sopenharmony_ci }, 4218c2ecf20Sopenharmony_ci }, 4228c2ecf20Sopenharmony_ci /* Mode 3 */ 4238c2ecf20Sopenharmony_ci { 4248c2ecf20Sopenharmony_ci .type = NAND_NVDDR_IFACE, 4258c2ecf20Sopenharmony_ci .timings.mode = 3, 4268c2ecf20Sopenharmony_ci .timings.nvddr = { 4278c2ecf20Sopenharmony_ci .tCCS_min = 500000, 4288c2ecf20Sopenharmony_ci .tR_max = 200000000, 4298c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 4308c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 4318c2ecf20Sopenharmony_ci .tAC_min = 3000, 4328c2ecf20Sopenharmony_ci .tAC_max = 25000, 4338c2ecf20Sopenharmony_ci .tADL_min = 400000, 4348c2ecf20Sopenharmony_ci .tCAD_min = 45000, 4358c2ecf20Sopenharmony_ci .tCAH_min = 3000, 4368c2ecf20Sopenharmony_ci .tCALH_min = 3000, 4378c2ecf20Sopenharmony_ci .tCALS_min = 3000, 4388c2ecf20Sopenharmony_ci .tCAS_min = 3000, 4398c2ecf20Sopenharmony_ci .tCEH_min = 20000, 4408c2ecf20Sopenharmony_ci .tCH_min = 3000, 4418c2ecf20Sopenharmony_ci .tCK_min = 15000, 4428c2ecf20Sopenharmony_ci .tCS_min = 15000, 4438c2ecf20Sopenharmony_ci .tDH_min = 1300, 4448c2ecf20Sopenharmony_ci .tDQSCK_min = 3000, 4458c2ecf20Sopenharmony_ci .tDQSCK_max = 25000, 4468c2ecf20Sopenharmony_ci .tDQSD_min = 0, 4478c2ecf20Sopenharmony_ci .tDQSD_max = 18000, 4488c2ecf20Sopenharmony_ci .tDQSHZ_max = 20000, 4498c2ecf20Sopenharmony_ci .tDQSQ_max = 1300, 4508c2ecf20Sopenharmony_ci .tDS_min = 1500, 4518c2ecf20Sopenharmony_ci .tDSC_min = 15000, 4528c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 4538c2ecf20Sopenharmony_ci .tITC_max = 1000000, 4548c2ecf20Sopenharmony_ci .tQHS_max = 1500, 4558c2ecf20Sopenharmony_ci .tRHW_min = 100000, 4568c2ecf20Sopenharmony_ci .tRR_min = 20000, 4578c2ecf20Sopenharmony_ci .tRST_max = 500000000, 4588c2ecf20Sopenharmony_ci .tWB_max = 100000, 4598c2ecf20Sopenharmony_ci .tWHR_min = 80000, 4608c2ecf20Sopenharmony_ci .tWRCK_min = 20000, 4618c2ecf20Sopenharmony_ci .tWW_min = 100000, 4628c2ecf20Sopenharmony_ci }, 4638c2ecf20Sopenharmony_ci }, 4648c2ecf20Sopenharmony_ci /* Mode 4 */ 4658c2ecf20Sopenharmony_ci { 4668c2ecf20Sopenharmony_ci .type = NAND_NVDDR_IFACE, 4678c2ecf20Sopenharmony_ci .timings.mode = 4, 4688c2ecf20Sopenharmony_ci .timings.nvddr = { 4698c2ecf20Sopenharmony_ci .tCCS_min = 500000, 4708c2ecf20Sopenharmony_ci .tR_max = 200000000, 4718c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 4728c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 4738c2ecf20Sopenharmony_ci .tAC_min = 3000, 4748c2ecf20Sopenharmony_ci .tAC_max = 25000, 4758c2ecf20Sopenharmony_ci .tADL_min = 400000, 4768c2ecf20Sopenharmony_ci .tCAD_min = 45000, 4778c2ecf20Sopenharmony_ci .tCAH_min = 2500, 4788c2ecf20Sopenharmony_ci .tCALH_min = 2500, 4798c2ecf20Sopenharmony_ci .tCALS_min = 2500, 4808c2ecf20Sopenharmony_ci .tCAS_min = 2500, 4818c2ecf20Sopenharmony_ci .tCEH_min = 20000, 4828c2ecf20Sopenharmony_ci .tCH_min = 2500, 4838c2ecf20Sopenharmony_ci .tCK_min = 12000, 4848c2ecf20Sopenharmony_ci .tCS_min = 15000, 4858c2ecf20Sopenharmony_ci .tDH_min = 1100, 4868c2ecf20Sopenharmony_ci .tDQSCK_min = 3000, 4878c2ecf20Sopenharmony_ci .tDQSCK_max = 25000, 4888c2ecf20Sopenharmony_ci .tDQSD_min = 0, 4898c2ecf20Sopenharmony_ci .tDQSD_max = 18000, 4908c2ecf20Sopenharmony_ci .tDQSHZ_max = 20000, 4918c2ecf20Sopenharmony_ci .tDQSQ_max = 1000, 4928c2ecf20Sopenharmony_ci .tDS_min = 1100, 4938c2ecf20Sopenharmony_ci .tDSC_min = 12000, 4948c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 4958c2ecf20Sopenharmony_ci .tITC_max = 1000000, 4968c2ecf20Sopenharmony_ci .tQHS_max = 1200, 4978c2ecf20Sopenharmony_ci .tRHW_min = 100000, 4988c2ecf20Sopenharmony_ci .tRR_min = 20000, 4998c2ecf20Sopenharmony_ci .tRST_max = 500000000, 5008c2ecf20Sopenharmony_ci .tWB_max = 100000, 5018c2ecf20Sopenharmony_ci .tWHR_min = 80000, 5028c2ecf20Sopenharmony_ci .tWRCK_min = 20000, 5038c2ecf20Sopenharmony_ci .tWW_min = 100000, 5048c2ecf20Sopenharmony_ci }, 5058c2ecf20Sopenharmony_ci }, 5068c2ecf20Sopenharmony_ci /* Mode 5 */ 5078c2ecf20Sopenharmony_ci { 5088c2ecf20Sopenharmony_ci .type = NAND_NVDDR_IFACE, 5098c2ecf20Sopenharmony_ci .timings.mode = 5, 5108c2ecf20Sopenharmony_ci .timings.nvddr = { 5118c2ecf20Sopenharmony_ci .tCCS_min = 500000, 5128c2ecf20Sopenharmony_ci .tR_max = 200000000, 5138c2ecf20Sopenharmony_ci .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 5148c2ecf20Sopenharmony_ci .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, 5158c2ecf20Sopenharmony_ci .tAC_min = 3000, 5168c2ecf20Sopenharmony_ci .tAC_max = 25000, 5178c2ecf20Sopenharmony_ci .tADL_min = 400000, 5188c2ecf20Sopenharmony_ci .tCAD_min = 45000, 5198c2ecf20Sopenharmony_ci .tCAH_min = 2000, 5208c2ecf20Sopenharmony_ci .tCALH_min = 2000, 5218c2ecf20Sopenharmony_ci .tCALS_min = 2000, 5228c2ecf20Sopenharmony_ci .tCAS_min = 2000, 5238c2ecf20Sopenharmony_ci .tCEH_min = 20000, 5248c2ecf20Sopenharmony_ci .tCH_min = 2000, 5258c2ecf20Sopenharmony_ci .tCK_min = 10000, 5268c2ecf20Sopenharmony_ci .tCS_min = 15000, 5278c2ecf20Sopenharmony_ci .tDH_min = 900, 5288c2ecf20Sopenharmony_ci .tDQSCK_min = 3000, 5298c2ecf20Sopenharmony_ci .tDQSCK_max = 25000, 5308c2ecf20Sopenharmony_ci .tDQSD_min = 0, 5318c2ecf20Sopenharmony_ci .tDQSD_max = 18000, 5328c2ecf20Sopenharmony_ci .tDQSHZ_max = 20000, 5338c2ecf20Sopenharmony_ci .tDQSQ_max = 850, 5348c2ecf20Sopenharmony_ci .tDS_min = 900, 5358c2ecf20Sopenharmony_ci .tDSC_min = 10000, 5368c2ecf20Sopenharmony_ci .tFEAT_max = 1000000, 5378c2ecf20Sopenharmony_ci .tITC_max = 1000000, 5388c2ecf20Sopenharmony_ci .tQHS_max = 1000, 5398c2ecf20Sopenharmony_ci .tRHW_min = 100000, 5408c2ecf20Sopenharmony_ci .tRR_min = 20000, 5418c2ecf20Sopenharmony_ci .tRST_max = 500000000, 5428c2ecf20Sopenharmony_ci .tWB_max = 100000, 5438c2ecf20Sopenharmony_ci .tWHR_min = 80000, 5448c2ecf20Sopenharmony_ci .tWRCK_min = 20000, 5458c2ecf20Sopenharmony_ci .tWW_min = 100000, 5468c2ecf20Sopenharmony_ci }, 5478c2ecf20Sopenharmony_ci }, 5488c2ecf20Sopenharmony_ci}; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci/* All NAND chips share the same reset data interface: SDR mode 0 */ 5518c2ecf20Sopenharmony_ciconst struct nand_interface_config *nand_get_reset_interface_config(void) 5528c2ecf20Sopenharmony_ci{ 5538c2ecf20Sopenharmony_ci return &onfi_sdr_timings[0]; 5548c2ecf20Sopenharmony_ci} 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci/** 5578c2ecf20Sopenharmony_ci * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a 5588c2ecf20Sopenharmony_ci * set of timings 5598c2ecf20Sopenharmony_ci * @spec_timings: the timings to challenge 5608c2ecf20Sopenharmony_ci */ 5618c2ecf20Sopenharmony_ciunsigned int 5628c2ecf20Sopenharmony_cionfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings) 5638c2ecf20Sopenharmony_ci{ 5648c2ecf20Sopenharmony_ci const struct nand_sdr_timings *onfi_timings; 5658c2ecf20Sopenharmony_ci int mode; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) { 5688c2ecf20Sopenharmony_ci onfi_timings = &onfi_sdr_timings[mode].timings.sdr; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (spec_timings->tCCS_min <= onfi_timings->tCCS_min && 5718c2ecf20Sopenharmony_ci spec_timings->tADL_min <= onfi_timings->tADL_min && 5728c2ecf20Sopenharmony_ci spec_timings->tALH_min <= onfi_timings->tALH_min && 5738c2ecf20Sopenharmony_ci spec_timings->tALS_min <= onfi_timings->tALS_min && 5748c2ecf20Sopenharmony_ci spec_timings->tAR_min <= onfi_timings->tAR_min && 5758c2ecf20Sopenharmony_ci spec_timings->tCEH_min <= onfi_timings->tCEH_min && 5768c2ecf20Sopenharmony_ci spec_timings->tCH_min <= onfi_timings->tCH_min && 5778c2ecf20Sopenharmony_ci spec_timings->tCLH_min <= onfi_timings->tCLH_min && 5788c2ecf20Sopenharmony_ci spec_timings->tCLR_min <= onfi_timings->tCLR_min && 5798c2ecf20Sopenharmony_ci spec_timings->tCLS_min <= onfi_timings->tCLS_min && 5808c2ecf20Sopenharmony_ci spec_timings->tCOH_min <= onfi_timings->tCOH_min && 5818c2ecf20Sopenharmony_ci spec_timings->tCS_min <= onfi_timings->tCS_min && 5828c2ecf20Sopenharmony_ci spec_timings->tDH_min <= onfi_timings->tDH_min && 5838c2ecf20Sopenharmony_ci spec_timings->tDS_min <= onfi_timings->tDS_min && 5848c2ecf20Sopenharmony_ci spec_timings->tIR_min <= onfi_timings->tIR_min && 5858c2ecf20Sopenharmony_ci spec_timings->tRC_min <= onfi_timings->tRC_min && 5868c2ecf20Sopenharmony_ci spec_timings->tREH_min <= onfi_timings->tREH_min && 5878c2ecf20Sopenharmony_ci spec_timings->tRHOH_min <= onfi_timings->tRHOH_min && 5888c2ecf20Sopenharmony_ci spec_timings->tRHW_min <= onfi_timings->tRHW_min && 5898c2ecf20Sopenharmony_ci spec_timings->tRLOH_min <= onfi_timings->tRLOH_min && 5908c2ecf20Sopenharmony_ci spec_timings->tRP_min <= onfi_timings->tRP_min && 5918c2ecf20Sopenharmony_ci spec_timings->tRR_min <= onfi_timings->tRR_min && 5928c2ecf20Sopenharmony_ci spec_timings->tWC_min <= onfi_timings->tWC_min && 5938c2ecf20Sopenharmony_ci spec_timings->tWH_min <= onfi_timings->tWH_min && 5948c2ecf20Sopenharmony_ci spec_timings->tWHR_min <= onfi_timings->tWHR_min && 5958c2ecf20Sopenharmony_ci spec_timings->tWP_min <= onfi_timings->tWP_min && 5968c2ecf20Sopenharmony_ci spec_timings->tWW_min <= onfi_timings->tWW_min) 5978c2ecf20Sopenharmony_ci return mode; 5988c2ecf20Sopenharmony_ci } 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci return 0; 6018c2ecf20Sopenharmony_ci} 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_ci/** 6048c2ecf20Sopenharmony_ci * onfi_fill_interface_config - Initialize an interface config from a given 6058c2ecf20Sopenharmony_ci * ONFI mode 6068c2ecf20Sopenharmony_ci * @chip: The NAND chip 6078c2ecf20Sopenharmony_ci * @iface: The interface configuration to fill 6088c2ecf20Sopenharmony_ci * @type: The interface type 6098c2ecf20Sopenharmony_ci * @timing_mode: The ONFI timing mode 6108c2ecf20Sopenharmony_ci */ 6118c2ecf20Sopenharmony_civoid onfi_fill_interface_config(struct nand_chip *chip, 6128c2ecf20Sopenharmony_ci struct nand_interface_config *iface, 6138c2ecf20Sopenharmony_ci enum nand_interface_type type, 6148c2ecf20Sopenharmony_ci unsigned int timing_mode) 6158c2ecf20Sopenharmony_ci{ 6168c2ecf20Sopenharmony_ci struct onfi_params *onfi = chip->parameters.onfi; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci if (WARN_ON(type != NAND_SDR_IFACE)) 6198c2ecf20Sopenharmony_ci return; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings))) 6228c2ecf20Sopenharmony_ci return; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci *iface = onfi_sdr_timings[timing_mode]; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* 6278c2ecf20Sopenharmony_ci * Initialize timings that cannot be deduced from timing mode: 6288c2ecf20Sopenharmony_ci * tPROG, tBERS, tR and tCCS. 6298c2ecf20Sopenharmony_ci * These information are part of the ONFI parameter page. 6308c2ecf20Sopenharmony_ci */ 6318c2ecf20Sopenharmony_ci if (onfi) { 6328c2ecf20Sopenharmony_ci struct nand_sdr_timings *timings = &iface->timings.sdr; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci /* microseconds -> picoseconds */ 6358c2ecf20Sopenharmony_ci timings->tPROG_max = 1000000ULL * onfi->tPROG; 6368c2ecf20Sopenharmony_ci timings->tBERS_max = 1000000ULL * onfi->tBERS; 6378c2ecf20Sopenharmony_ci timings->tR_max = 1000000ULL * onfi->tR; 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci /* nanoseconds -> picoseconds */ 6408c2ecf20Sopenharmony_ci timings->tCCS_min = 1000UL * onfi->tCCS; 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci} 643