.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2014 Free Electrons |
---|
3 | 4 | * |
---|
4 | 5 | * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License version 2 as |
---|
8 | | - * published by the Free Software Foundation. |
---|
9 | | - * |
---|
10 | 6 | */ |
---|
11 | 7 | #include <linux/kernel.h> |
---|
12 | 8 | #include <linux/err.h> |
---|
13 | 9 | #include <linux/export.h> |
---|
14 | | -#include <linux/mtd/rawnand.h> |
---|
| 10 | + |
---|
| 11 | +#include "internals.h" |
---|
15 | 12 | |
---|
16 | 13 | #define ONFI_DYN_TIMING_MAX U16_MAX |
---|
17 | 14 | |
---|
18 | | -static const struct nand_data_interface onfi_sdr_timings[] = { |
---|
| 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 | + */ |
---|
| 22 | +static const struct nand_interface_config onfi_sdr_timings[] = { |
---|
19 | 23 | /* Mode 0 */ |
---|
20 | 24 | { |
---|
21 | 25 | .type = NAND_SDR_IFACE, |
---|
| 26 | + .timings.mode = 0, |
---|
22 | 27 | .timings.sdr = { |
---|
23 | 28 | .tCCS_min = 500000, |
---|
24 | 29 | .tR_max = 200000000, |
---|
| 30 | + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
| 31 | + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
25 | 32 | .tADL_min = 400000, |
---|
26 | 33 | .tALH_min = 20000, |
---|
27 | 34 | .tALS_min = 50000, |
---|
.. | .. |
---|
61 | 68 | /* Mode 1 */ |
---|
62 | 69 | { |
---|
63 | 70 | .type = NAND_SDR_IFACE, |
---|
| 71 | + .timings.mode = 1, |
---|
64 | 72 | .timings.sdr = { |
---|
65 | 73 | .tCCS_min = 500000, |
---|
66 | 74 | .tR_max = 200000000, |
---|
| 75 | + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
| 76 | + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
67 | 77 | .tADL_min = 400000, |
---|
68 | 78 | .tALH_min = 10000, |
---|
69 | 79 | .tALS_min = 25000, |
---|
.. | .. |
---|
103 | 113 | /* Mode 2 */ |
---|
104 | 114 | { |
---|
105 | 115 | .type = NAND_SDR_IFACE, |
---|
| 116 | + .timings.mode = 2, |
---|
106 | 117 | .timings.sdr = { |
---|
107 | 118 | .tCCS_min = 500000, |
---|
108 | 119 | .tR_max = 200000000, |
---|
| 120 | + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
| 121 | + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
109 | 122 | .tADL_min = 400000, |
---|
110 | 123 | .tALH_min = 10000, |
---|
111 | 124 | .tALS_min = 15000, |
---|
.. | .. |
---|
145 | 158 | /* Mode 3 */ |
---|
146 | 159 | { |
---|
147 | 160 | .type = NAND_SDR_IFACE, |
---|
| 161 | + .timings.mode = 3, |
---|
148 | 162 | .timings.sdr = { |
---|
149 | 163 | .tCCS_min = 500000, |
---|
150 | 164 | .tR_max = 200000000, |
---|
| 165 | + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
| 166 | + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
151 | 167 | .tADL_min = 400000, |
---|
152 | 168 | .tALH_min = 5000, |
---|
153 | 169 | .tALS_min = 10000, |
---|
.. | .. |
---|
187 | 203 | /* Mode 4 */ |
---|
188 | 204 | { |
---|
189 | 205 | .type = NAND_SDR_IFACE, |
---|
| 206 | + .timings.mode = 4, |
---|
190 | 207 | .timings.sdr = { |
---|
191 | 208 | .tCCS_min = 500000, |
---|
192 | 209 | .tR_max = 200000000, |
---|
| 210 | + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
| 211 | + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
193 | 212 | .tADL_min = 400000, |
---|
194 | 213 | .tALH_min = 5000, |
---|
195 | 214 | .tALS_min = 10000, |
---|
.. | .. |
---|
229 | 248 | /* Mode 5 */ |
---|
230 | 249 | { |
---|
231 | 250 | .type = NAND_SDR_IFACE, |
---|
| 251 | + .timings.mode = 5, |
---|
232 | 252 | .timings.sdr = { |
---|
233 | 253 | .tCCS_min = 500000, |
---|
234 | 254 | .tR_max = 200000000, |
---|
| 255 | + .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
| 256 | + .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX, |
---|
235 | 257 | .tADL_min = 400000, |
---|
236 | 258 | .tALH_min = 5000, |
---|
237 | 259 | .tALS_min = 10000, |
---|
.. | .. |
---|
270 | 292 | }, |
---|
271 | 293 | }; |
---|
272 | 294 | |
---|
273 | | -/** |
---|
274 | | - * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND |
---|
275 | | - * timings according to the given ONFI timing mode |
---|
276 | | - * @mode: ONFI timing mode |
---|
277 | | - */ |
---|
278 | | -const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode) |
---|
279 | | -{ |
---|
280 | | - if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings)) |
---|
281 | | - return ERR_PTR(-EINVAL); |
---|
| 295 | +static 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 | +}; |
---|
282 | 549 | |
---|
283 | | - return &onfi_sdr_timings[mode].timings.sdr; |
---|
| 550 | +/* All NAND chips share the same reset data interface: SDR mode 0 */ |
---|
| 551 | +const struct nand_interface_config *nand_get_reset_interface_config(void) |
---|
| 552 | +{ |
---|
| 553 | + return &onfi_sdr_timings[0]; |
---|
284 | 554 | } |
---|
285 | | -EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings); |
---|
286 | 555 | |
---|
287 | 556 | /** |
---|
288 | | - * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from |
---|
289 | | - * given ONFI mode |
---|
290 | | - * @mode: The ONFI timing mode |
---|
| 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 |
---|
291 | 560 | */ |
---|
292 | | -int onfi_fill_data_interface(struct nand_chip *chip, |
---|
293 | | - enum nand_data_interface_type type, |
---|
294 | | - int timing_mode) |
---|
| 561 | +unsigned int |
---|
| 562 | +onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings) |
---|
295 | 563 | { |
---|
296 | | - struct nand_data_interface *iface = &chip->data_interface; |
---|
| 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_fill_interface_config - Initialize an interface config from a given |
---|
| 605 | + * ONFI mode |
---|
| 606 | + * @chip: The NAND chip |
---|
| 607 | + * @iface: The interface configuration to fill |
---|
| 608 | + * @type: The interface type |
---|
| 609 | + * @timing_mode: The ONFI timing mode |
---|
| 610 | + */ |
---|
| 611 | +void onfi_fill_interface_config(struct nand_chip *chip, |
---|
| 612 | + struct nand_interface_config *iface, |
---|
| 613 | + enum nand_interface_type type, |
---|
| 614 | + unsigned int timing_mode) |
---|
| 615 | +{ |
---|
297 | 616 | struct onfi_params *onfi = chip->parameters.onfi; |
---|
298 | 617 | |
---|
299 | | - if (type != NAND_SDR_IFACE) |
---|
300 | | - return -EINVAL; |
---|
| 618 | + if (WARN_ON(type != NAND_SDR_IFACE)) |
---|
| 619 | + return; |
---|
301 | 620 | |
---|
302 | | - if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings)) |
---|
303 | | - return -EINVAL; |
---|
| 621 | + if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings))) |
---|
| 622 | + return; |
---|
304 | 623 | |
---|
305 | 624 | *iface = onfi_sdr_timings[timing_mode]; |
---|
306 | 625 | |
---|
.. | .. |
---|
319 | 638 | |
---|
320 | 639 | /* nanoseconds -> picoseconds */ |
---|
321 | 640 | timings->tCCS_min = 1000UL * onfi->tCCS; |
---|
322 | | - } else { |
---|
323 | | - struct nand_sdr_timings *timings = &iface->timings.sdr; |
---|
324 | | - /* |
---|
325 | | - * For non-ONFI chips we use the highest possible value for |
---|
326 | | - * tPROG and tBERS. tR and tCCS will take the default values |
---|
327 | | - * precised in the ONFI specification for timing mode 0, |
---|
328 | | - * respectively 200us and 500ns. |
---|
329 | | - */ |
---|
330 | | - |
---|
331 | | - /* microseconds -> picoseconds */ |
---|
332 | | - timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX; |
---|
333 | | - timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX; |
---|
334 | | - |
---|
335 | | - timings->tR_max = 200000000; |
---|
336 | | - timings->tCCS_min = 500000; |
---|
337 | 641 | } |
---|
338 | | - |
---|
339 | | - return 0; |
---|
340 | 642 | } |
---|
341 | | -EXPORT_SYMBOL(onfi_fill_data_interface); |
---|