738 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2014 Free Electrons4 *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_MAX14 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 specification18 * 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 a558 * set of timings559 * @spec_timings: the timings to challenge560 */561unsigned int562onfi_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 mode605 * given a set of timings606 * @spec_timings: the timings to challenge607 */608unsigned int609onfi_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 a647 * given ONFI mode648 * @chip: The NAND chip649 * @iface: The interface configuration to fill650 * @timing_mode: The ONFI timing mode651 */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 a683 * given ONFI mode684 * @chip: The NAND chip685 * @iface: The interface configuration to fill686 * @timing_mode: The ONFI timing mode687 */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 given722 * ONFI mode723 * @chip: The NAND chip724 * @iface: The interface configuration to fill725 * @type: The interface type726 * @timing_mode: The ONFI timing mode727 */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 else736 return onfi_fill_nvddr_interface_config(chip, iface, timing_mode);737}738