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}