nand_timings.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2014 Free Electrons
  4. *
  5. * Author: Boris BREZILLON <[email protected]>
  6. */
  7. #include <linux/kernel.h>
  8. #include <linux/err.h>
  9. #include <linux/export.h>
  10. #include "internals.h"
  11. #define ONFI_DYN_TIMING_MAX U16_MAX
  12. /*
  13. * For non-ONFI chips we use the highest possible value for tPROG and tBERS.
  14. * tR and tCCS will take the default values precised in the ONFI specification
  15. * for timing mode 0, respectively 200us and 500ns.
  16. *
  17. * These four values are tweaked to be more accurate in the case of ONFI chips.
  18. */
  19. static const struct nand_interface_config onfi_sdr_timings[] = {
  20. /* Mode 0 */
  21. {
  22. .type = NAND_SDR_IFACE,
  23. .timings.mode = 0,
  24. .timings.sdr = {
  25. .tCCS_min = 500000,
  26. .tR_max = 200000000,
  27. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  28. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  29. .tADL_min = 400000,
  30. .tALH_min = 20000,
  31. .tALS_min = 50000,
  32. .tAR_min = 25000,
  33. .tCEA_max = 100000,
  34. .tCEH_min = 20000,
  35. .tCH_min = 20000,
  36. .tCHZ_max = 100000,
  37. .tCLH_min = 20000,
  38. .tCLR_min = 20000,
  39. .tCLS_min = 50000,
  40. .tCOH_min = 0,
  41. .tCS_min = 70000,
  42. .tDH_min = 20000,
  43. .tDS_min = 40000,
  44. .tFEAT_max = 1000000,
  45. .tIR_min = 10000,
  46. .tITC_max = 1000000,
  47. .tRC_min = 100000,
  48. .tREA_max = 40000,
  49. .tREH_min = 30000,
  50. .tRHOH_min = 0,
  51. .tRHW_min = 200000,
  52. .tRHZ_max = 200000,
  53. .tRLOH_min = 0,
  54. .tRP_min = 50000,
  55. .tRR_min = 40000,
  56. .tRST_max = 250000000000ULL,
  57. .tWB_max = 200000,
  58. .tWC_min = 100000,
  59. .tWH_min = 30000,
  60. .tWHR_min = 120000,
  61. .tWP_min = 50000,
  62. .tWW_min = 100000,
  63. },
  64. },
  65. /* Mode 1 */
  66. {
  67. .type = NAND_SDR_IFACE,
  68. .timings.mode = 1,
  69. .timings.sdr = {
  70. .tCCS_min = 500000,
  71. .tR_max = 200000000,
  72. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  73. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  74. .tADL_min = 400000,
  75. .tALH_min = 10000,
  76. .tALS_min = 25000,
  77. .tAR_min = 10000,
  78. .tCEA_max = 45000,
  79. .tCEH_min = 20000,
  80. .tCH_min = 10000,
  81. .tCHZ_max = 50000,
  82. .tCLH_min = 10000,
  83. .tCLR_min = 10000,
  84. .tCLS_min = 25000,
  85. .tCOH_min = 15000,
  86. .tCS_min = 35000,
  87. .tDH_min = 10000,
  88. .tDS_min = 20000,
  89. .tFEAT_max = 1000000,
  90. .tIR_min = 0,
  91. .tITC_max = 1000000,
  92. .tRC_min = 50000,
  93. .tREA_max = 30000,
  94. .tREH_min = 15000,
  95. .tRHOH_min = 15000,
  96. .tRHW_min = 100000,
  97. .tRHZ_max = 100000,
  98. .tRLOH_min = 0,
  99. .tRP_min = 25000,
  100. .tRR_min = 20000,
  101. .tRST_max = 500000000,
  102. .tWB_max = 100000,
  103. .tWC_min = 45000,
  104. .tWH_min = 15000,
  105. .tWHR_min = 80000,
  106. .tWP_min = 25000,
  107. .tWW_min = 100000,
  108. },
  109. },
  110. /* Mode 2 */
  111. {
  112. .type = NAND_SDR_IFACE,
  113. .timings.mode = 2,
  114. .timings.sdr = {
  115. .tCCS_min = 500000,
  116. .tR_max = 200000000,
  117. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  118. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  119. .tADL_min = 400000,
  120. .tALH_min = 10000,
  121. .tALS_min = 15000,
  122. .tAR_min = 10000,
  123. .tCEA_max = 30000,
  124. .tCEH_min = 20000,
  125. .tCH_min = 10000,
  126. .tCHZ_max = 50000,
  127. .tCLH_min = 10000,
  128. .tCLR_min = 10000,
  129. .tCLS_min = 15000,
  130. .tCOH_min = 15000,
  131. .tCS_min = 25000,
  132. .tDH_min = 5000,
  133. .tDS_min = 15000,
  134. .tFEAT_max = 1000000,
  135. .tIR_min = 0,
  136. .tITC_max = 1000000,
  137. .tRC_min = 35000,
  138. .tREA_max = 25000,
  139. .tREH_min = 15000,
  140. .tRHOH_min = 15000,
  141. .tRHW_min = 100000,
  142. .tRHZ_max = 100000,
  143. .tRLOH_min = 0,
  144. .tRR_min = 20000,
  145. .tRST_max = 500000000,
  146. .tWB_max = 100000,
  147. .tRP_min = 17000,
  148. .tWC_min = 35000,
  149. .tWH_min = 15000,
  150. .tWHR_min = 80000,
  151. .tWP_min = 17000,
  152. .tWW_min = 100000,
  153. },
  154. },
  155. /* Mode 3 */
  156. {
  157. .type = NAND_SDR_IFACE,
  158. .timings.mode = 3,
  159. .timings.sdr = {
  160. .tCCS_min = 500000,
  161. .tR_max = 200000000,
  162. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  163. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  164. .tADL_min = 400000,
  165. .tALH_min = 5000,
  166. .tALS_min = 10000,
  167. .tAR_min = 10000,
  168. .tCEA_max = 25000,
  169. .tCEH_min = 20000,
  170. .tCH_min = 5000,
  171. .tCHZ_max = 50000,
  172. .tCLH_min = 5000,
  173. .tCLR_min = 10000,
  174. .tCLS_min = 10000,
  175. .tCOH_min = 15000,
  176. .tCS_min = 25000,
  177. .tDH_min = 5000,
  178. .tDS_min = 10000,
  179. .tFEAT_max = 1000000,
  180. .tIR_min = 0,
  181. .tITC_max = 1000000,
  182. .tRC_min = 30000,
  183. .tREA_max = 20000,
  184. .tREH_min = 10000,
  185. .tRHOH_min = 15000,
  186. .tRHW_min = 100000,
  187. .tRHZ_max = 100000,
  188. .tRLOH_min = 0,
  189. .tRP_min = 15000,
  190. .tRR_min = 20000,
  191. .tRST_max = 500000000,
  192. .tWB_max = 100000,
  193. .tWC_min = 30000,
  194. .tWH_min = 10000,
  195. .tWHR_min = 80000,
  196. .tWP_min = 15000,
  197. .tWW_min = 100000,
  198. },
  199. },
  200. /* Mode 4 */
  201. {
  202. .type = NAND_SDR_IFACE,
  203. .timings.mode = 4,
  204. .timings.sdr = {
  205. .tCCS_min = 500000,
  206. .tR_max = 200000000,
  207. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  208. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  209. .tADL_min = 400000,
  210. .tALH_min = 5000,
  211. .tALS_min = 10000,
  212. .tAR_min = 10000,
  213. .tCEA_max = 25000,
  214. .tCEH_min = 20000,
  215. .tCH_min = 5000,
  216. .tCHZ_max = 30000,
  217. .tCLH_min = 5000,
  218. .tCLR_min = 10000,
  219. .tCLS_min = 10000,
  220. .tCOH_min = 15000,
  221. .tCS_min = 20000,
  222. .tDH_min = 5000,
  223. .tDS_min = 10000,
  224. .tFEAT_max = 1000000,
  225. .tIR_min = 0,
  226. .tITC_max = 1000000,
  227. .tRC_min = 25000,
  228. .tREA_max = 20000,
  229. .tREH_min = 10000,
  230. .tRHOH_min = 15000,
  231. .tRHW_min = 100000,
  232. .tRHZ_max = 100000,
  233. .tRLOH_min = 5000,
  234. .tRP_min = 12000,
  235. .tRR_min = 20000,
  236. .tRST_max = 500000000,
  237. .tWB_max = 100000,
  238. .tWC_min = 25000,
  239. .tWH_min = 10000,
  240. .tWHR_min = 80000,
  241. .tWP_min = 12000,
  242. .tWW_min = 100000,
  243. },
  244. },
  245. /* Mode 5 */
  246. {
  247. .type = NAND_SDR_IFACE,
  248. .timings.mode = 5,
  249. .timings.sdr = {
  250. .tCCS_min = 500000,
  251. .tR_max = 200000000,
  252. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  253. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  254. .tADL_min = 400000,
  255. .tALH_min = 5000,
  256. .tALS_min = 10000,
  257. .tAR_min = 10000,
  258. .tCEA_max = 25000,
  259. .tCEH_min = 20000,
  260. .tCH_min = 5000,
  261. .tCHZ_max = 30000,
  262. .tCLH_min = 5000,
  263. .tCLR_min = 10000,
  264. .tCLS_min = 10000,
  265. .tCOH_min = 15000,
  266. .tCS_min = 15000,
  267. .tDH_min = 5000,
  268. .tDS_min = 7000,
  269. .tFEAT_max = 1000000,
  270. .tIR_min = 0,
  271. .tITC_max = 1000000,
  272. .tRC_min = 20000,
  273. .tREA_max = 16000,
  274. .tREH_min = 7000,
  275. .tRHOH_min = 15000,
  276. .tRHW_min = 100000,
  277. .tRHZ_max = 100000,
  278. .tRLOH_min = 5000,
  279. .tRP_min = 10000,
  280. .tRR_min = 20000,
  281. .tRST_max = 500000000,
  282. .tWB_max = 100000,
  283. .tWC_min = 20000,
  284. .tWH_min = 7000,
  285. .tWHR_min = 80000,
  286. .tWP_min = 10000,
  287. .tWW_min = 100000,
  288. },
  289. },
  290. };
  291. static const struct nand_interface_config onfi_nvddr_timings[] = {
  292. /* Mode 0 */
  293. {
  294. .type = NAND_NVDDR_IFACE,
  295. .timings.mode = 0,
  296. .timings.nvddr = {
  297. .tCCS_min = 500000,
  298. .tR_max = 200000000,
  299. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  300. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  301. .tAC_min = 3000,
  302. .tAC_max = 25000,
  303. .tADL_min = 400000,
  304. .tCAD_min = 45000,
  305. .tCAH_min = 10000,
  306. .tCALH_min = 10000,
  307. .tCALS_min = 10000,
  308. .tCAS_min = 10000,
  309. .tCEH_min = 20000,
  310. .tCH_min = 10000,
  311. .tCK_min = 50000,
  312. .tCS_min = 35000,
  313. .tDH_min = 5000,
  314. .tDQSCK_min = 3000,
  315. .tDQSCK_max = 25000,
  316. .tDQSD_min = 0,
  317. .tDQSD_max = 18000,
  318. .tDQSHZ_max = 20000,
  319. .tDQSQ_max = 5000,
  320. .tDS_min = 5000,
  321. .tDSC_min = 50000,
  322. .tFEAT_max = 1000000,
  323. .tITC_max = 1000000,
  324. .tQHS_max = 6000,
  325. .tRHW_min = 100000,
  326. .tRR_min = 20000,
  327. .tRST_max = 500000000,
  328. .tWB_max = 100000,
  329. .tWHR_min = 80000,
  330. .tWRCK_min = 20000,
  331. .tWW_min = 100000,
  332. },
  333. },
  334. /* Mode 1 */
  335. {
  336. .type = NAND_NVDDR_IFACE,
  337. .timings.mode = 1,
  338. .timings.nvddr = {
  339. .tCCS_min = 500000,
  340. .tR_max = 200000000,
  341. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  342. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  343. .tAC_min = 3000,
  344. .tAC_max = 25000,
  345. .tADL_min = 400000,
  346. .tCAD_min = 45000,
  347. .tCAH_min = 5000,
  348. .tCALH_min = 5000,
  349. .tCALS_min = 5000,
  350. .tCAS_min = 5000,
  351. .tCEH_min = 20000,
  352. .tCH_min = 5000,
  353. .tCK_min = 30000,
  354. .tCS_min = 25000,
  355. .tDH_min = 2500,
  356. .tDQSCK_min = 3000,
  357. .tDQSCK_max = 25000,
  358. .tDQSD_min = 0,
  359. .tDQSD_max = 18000,
  360. .tDQSHZ_max = 20000,
  361. .tDQSQ_max = 2500,
  362. .tDS_min = 3000,
  363. .tDSC_min = 30000,
  364. .tFEAT_max = 1000000,
  365. .tITC_max = 1000000,
  366. .tQHS_max = 3000,
  367. .tRHW_min = 100000,
  368. .tRR_min = 20000,
  369. .tRST_max = 500000000,
  370. .tWB_max = 100000,
  371. .tWHR_min = 80000,
  372. .tWRCK_min = 20000,
  373. .tWW_min = 100000,
  374. },
  375. },
  376. /* Mode 2 */
  377. {
  378. .type = NAND_NVDDR_IFACE,
  379. .timings.mode = 2,
  380. .timings.nvddr = {
  381. .tCCS_min = 500000,
  382. .tR_max = 200000000,
  383. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  384. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  385. .tAC_min = 3000,
  386. .tAC_max = 25000,
  387. .tADL_min = 400000,
  388. .tCAD_min = 45000,
  389. .tCAH_min = 4000,
  390. .tCALH_min = 4000,
  391. .tCALS_min = 4000,
  392. .tCAS_min = 4000,
  393. .tCEH_min = 20000,
  394. .tCH_min = 4000,
  395. .tCK_min = 20000,
  396. .tCS_min = 15000,
  397. .tDH_min = 1700,
  398. .tDQSCK_min = 3000,
  399. .tDQSCK_max = 25000,
  400. .tDQSD_min = 0,
  401. .tDQSD_max = 18000,
  402. .tDQSHZ_max = 20000,
  403. .tDQSQ_max = 1700,
  404. .tDS_min = 2000,
  405. .tDSC_min = 20000,
  406. .tFEAT_max = 1000000,
  407. .tITC_max = 1000000,
  408. .tQHS_max = 2000,
  409. .tRHW_min = 100000,
  410. .tRR_min = 20000,
  411. .tRST_max = 500000000,
  412. .tWB_max = 100000,
  413. .tWHR_min = 80000,
  414. .tWRCK_min = 20000,
  415. .tWW_min = 100000,
  416. },
  417. },
  418. /* Mode 3 */
  419. {
  420. .type = NAND_NVDDR_IFACE,
  421. .timings.mode = 3,
  422. .timings.nvddr = {
  423. .tCCS_min = 500000,
  424. .tR_max = 200000000,
  425. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  426. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  427. .tAC_min = 3000,
  428. .tAC_max = 25000,
  429. .tADL_min = 400000,
  430. .tCAD_min = 45000,
  431. .tCAH_min = 3000,
  432. .tCALH_min = 3000,
  433. .tCALS_min = 3000,
  434. .tCAS_min = 3000,
  435. .tCEH_min = 20000,
  436. .tCH_min = 3000,
  437. .tCK_min = 15000,
  438. .tCS_min = 15000,
  439. .tDH_min = 1300,
  440. .tDQSCK_min = 3000,
  441. .tDQSCK_max = 25000,
  442. .tDQSD_min = 0,
  443. .tDQSD_max = 18000,
  444. .tDQSHZ_max = 20000,
  445. .tDQSQ_max = 1300,
  446. .tDS_min = 1500,
  447. .tDSC_min = 15000,
  448. .tFEAT_max = 1000000,
  449. .tITC_max = 1000000,
  450. .tQHS_max = 1500,
  451. .tRHW_min = 100000,
  452. .tRR_min = 20000,
  453. .tRST_max = 500000000,
  454. .tWB_max = 100000,
  455. .tWHR_min = 80000,
  456. .tWRCK_min = 20000,
  457. .tWW_min = 100000,
  458. },
  459. },
  460. /* Mode 4 */
  461. {
  462. .type = NAND_NVDDR_IFACE,
  463. .timings.mode = 4,
  464. .timings.nvddr = {
  465. .tCCS_min = 500000,
  466. .tR_max = 200000000,
  467. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  468. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  469. .tAC_min = 3000,
  470. .tAC_max = 25000,
  471. .tADL_min = 400000,
  472. .tCAD_min = 45000,
  473. .tCAH_min = 2500,
  474. .tCALH_min = 2500,
  475. .tCALS_min = 2500,
  476. .tCAS_min = 2500,
  477. .tCEH_min = 20000,
  478. .tCH_min = 2500,
  479. .tCK_min = 12000,
  480. .tCS_min = 15000,
  481. .tDH_min = 1100,
  482. .tDQSCK_min = 3000,
  483. .tDQSCK_max = 25000,
  484. .tDQSD_min = 0,
  485. .tDQSD_max = 18000,
  486. .tDQSHZ_max = 20000,
  487. .tDQSQ_max = 1000,
  488. .tDS_min = 1100,
  489. .tDSC_min = 12000,
  490. .tFEAT_max = 1000000,
  491. .tITC_max = 1000000,
  492. .tQHS_max = 1200,
  493. .tRHW_min = 100000,
  494. .tRR_min = 20000,
  495. .tRST_max = 500000000,
  496. .tWB_max = 100000,
  497. .tWHR_min = 80000,
  498. .tWRCK_min = 20000,
  499. .tWW_min = 100000,
  500. },
  501. },
  502. /* Mode 5 */
  503. {
  504. .type = NAND_NVDDR_IFACE,
  505. .timings.mode = 5,
  506. .timings.nvddr = {
  507. .tCCS_min = 500000,
  508. .tR_max = 200000000,
  509. .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  510. .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
  511. .tAC_min = 3000,
  512. .tAC_max = 25000,
  513. .tADL_min = 400000,
  514. .tCAD_min = 45000,
  515. .tCAH_min = 2000,
  516. .tCALH_min = 2000,
  517. .tCALS_min = 2000,
  518. .tCAS_min = 2000,
  519. .tCEH_min = 20000,
  520. .tCH_min = 2000,
  521. .tCK_min = 10000,
  522. .tCS_min = 15000,
  523. .tDH_min = 900,
  524. .tDQSCK_min = 3000,
  525. .tDQSCK_max = 25000,
  526. .tDQSD_min = 0,
  527. .tDQSD_max = 18000,
  528. .tDQSHZ_max = 20000,
  529. .tDQSQ_max = 850,
  530. .tDS_min = 900,
  531. .tDSC_min = 10000,
  532. .tFEAT_max = 1000000,
  533. .tITC_max = 1000000,
  534. .tQHS_max = 1000,
  535. .tRHW_min = 100000,
  536. .tRR_min = 20000,
  537. .tRST_max = 500000000,
  538. .tWB_max = 100000,
  539. .tWHR_min = 80000,
  540. .tWRCK_min = 20000,
  541. .tWW_min = 100000,
  542. },
  543. },
  544. };
  545. /* All NAND chips share the same reset data interface: SDR mode 0 */
  546. const struct nand_interface_config *nand_get_reset_interface_config(void)
  547. {
  548. return &onfi_sdr_timings[0];
  549. }
  550. /**
  551. * onfi_find_closest_sdr_mode - Derive the closest ONFI SDR timing mode given a
  552. * set of timings
  553. * @spec_timings: the timings to challenge
  554. */
  555. unsigned int
  556. onfi_find_closest_sdr_mode(const struct nand_sdr_timings *spec_timings)
  557. {
  558. const struct nand_sdr_timings *onfi_timings;
  559. int mode;
  560. for (mode = ARRAY_SIZE(onfi_sdr_timings) - 1; mode > 0; mode--) {
  561. onfi_timings = &onfi_sdr_timings[mode].timings.sdr;
  562. if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
  563. spec_timings->tADL_min <= onfi_timings->tADL_min &&
  564. spec_timings->tALH_min <= onfi_timings->tALH_min &&
  565. spec_timings->tALS_min <= onfi_timings->tALS_min &&
  566. spec_timings->tAR_min <= onfi_timings->tAR_min &&
  567. spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
  568. spec_timings->tCH_min <= onfi_timings->tCH_min &&
  569. spec_timings->tCLH_min <= onfi_timings->tCLH_min &&
  570. spec_timings->tCLR_min <= onfi_timings->tCLR_min &&
  571. spec_timings->tCLS_min <= onfi_timings->tCLS_min &&
  572. spec_timings->tCOH_min <= onfi_timings->tCOH_min &&
  573. spec_timings->tCS_min <= onfi_timings->tCS_min &&
  574. spec_timings->tDH_min <= onfi_timings->tDH_min &&
  575. spec_timings->tDS_min <= onfi_timings->tDS_min &&
  576. spec_timings->tIR_min <= onfi_timings->tIR_min &&
  577. spec_timings->tRC_min <= onfi_timings->tRC_min &&
  578. spec_timings->tREH_min <= onfi_timings->tREH_min &&
  579. spec_timings->tRHOH_min <= onfi_timings->tRHOH_min &&
  580. spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
  581. spec_timings->tRLOH_min <= onfi_timings->tRLOH_min &&
  582. spec_timings->tRP_min <= onfi_timings->tRP_min &&
  583. spec_timings->tRR_min <= onfi_timings->tRR_min &&
  584. spec_timings->tWC_min <= onfi_timings->tWC_min &&
  585. spec_timings->tWH_min <= onfi_timings->tWH_min &&
  586. spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
  587. spec_timings->tWP_min <= onfi_timings->tWP_min &&
  588. spec_timings->tWW_min <= onfi_timings->tWW_min)
  589. return mode;
  590. }
  591. return 0;
  592. }
  593. /**
  594. * onfi_find_closest_nvddr_mode - Derive the closest ONFI NVDDR timing mode
  595. * given a set of timings
  596. * @spec_timings: the timings to challenge
  597. */
  598. unsigned int
  599. onfi_find_closest_nvddr_mode(const struct nand_nvddr_timings *spec_timings)
  600. {
  601. const struct nand_nvddr_timings *onfi_timings;
  602. int mode;
  603. for (mode = ARRAY_SIZE(onfi_nvddr_timings) - 1; mode > 0; mode--) {
  604. onfi_timings = &onfi_nvddr_timings[mode].timings.nvddr;
  605. if (spec_timings->tCCS_min <= onfi_timings->tCCS_min &&
  606. spec_timings->tAC_min <= onfi_timings->tAC_min &&
  607. spec_timings->tADL_min <= onfi_timings->tADL_min &&
  608. spec_timings->tCAD_min <= onfi_timings->tCAD_min &&
  609. spec_timings->tCAH_min <= onfi_timings->tCAH_min &&
  610. spec_timings->tCALH_min <= onfi_timings->tCALH_min &&
  611. spec_timings->tCALS_min <= onfi_timings->tCALS_min &&
  612. spec_timings->tCAS_min <= onfi_timings->tCAS_min &&
  613. spec_timings->tCEH_min <= onfi_timings->tCEH_min &&
  614. spec_timings->tCH_min <= onfi_timings->tCH_min &&
  615. spec_timings->tCK_min <= onfi_timings->tCK_min &&
  616. spec_timings->tCS_min <= onfi_timings->tCS_min &&
  617. spec_timings->tDH_min <= onfi_timings->tDH_min &&
  618. spec_timings->tDQSCK_min <= onfi_timings->tDQSCK_min &&
  619. spec_timings->tDQSD_min <= onfi_timings->tDQSD_min &&
  620. spec_timings->tDS_min <= onfi_timings->tDS_min &&
  621. spec_timings->tDSC_min <= onfi_timings->tDSC_min &&
  622. spec_timings->tRHW_min <= onfi_timings->tRHW_min &&
  623. spec_timings->tRR_min <= onfi_timings->tRR_min &&
  624. spec_timings->tWHR_min <= onfi_timings->tWHR_min &&
  625. spec_timings->tWRCK_min <= onfi_timings->tWRCK_min &&
  626. spec_timings->tWW_min <= onfi_timings->tWW_min)
  627. return mode;
  628. }
  629. return 0;
  630. }
  631. /*
  632. * onfi_fill_sdr_interface_config - Initialize a SDR interface config from a
  633. * given ONFI mode
  634. * @chip: The NAND chip
  635. * @iface: The interface configuration to fill
  636. * @timing_mode: The ONFI timing mode
  637. */
  638. static void onfi_fill_sdr_interface_config(struct nand_chip *chip,
  639. struct nand_interface_config *iface,
  640. unsigned int timing_mode)
  641. {
  642. struct onfi_params *onfi = chip->parameters.onfi;
  643. if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_sdr_timings)))
  644. return;
  645. *iface = onfi_sdr_timings[timing_mode];
  646. /*
  647. * Initialize timings that cannot be deduced from timing mode:
  648. * tPROG, tBERS, tR and tCCS.
  649. * These information are part of the ONFI parameter page.
  650. */
  651. if (onfi) {
  652. struct nand_sdr_timings *timings = &iface->timings.sdr;
  653. /* microseconds -> picoseconds */
  654. timings->tPROG_max = 1000000ULL * onfi->tPROG;
  655. timings->tBERS_max = 1000000ULL * onfi->tBERS;
  656. timings->tR_max = 1000000ULL * onfi->tR;
  657. /* nanoseconds -> picoseconds */
  658. timings->tCCS_min = 1000UL * onfi->tCCS;
  659. }
  660. }
  661. /**
  662. * onfi_fill_nvddr_interface_config - Initialize a NVDDR interface config from a
  663. * given ONFI mode
  664. * @chip: The NAND chip
  665. * @iface: The interface configuration to fill
  666. * @timing_mode: The ONFI timing mode
  667. */
  668. static void onfi_fill_nvddr_interface_config(struct nand_chip *chip,
  669. struct nand_interface_config *iface,
  670. unsigned int timing_mode)
  671. {
  672. struct onfi_params *onfi = chip->parameters.onfi;
  673. if (WARN_ON(timing_mode >= ARRAY_SIZE(onfi_nvddr_timings)))
  674. return;
  675. *iface = onfi_nvddr_timings[timing_mode];
  676. /*
  677. * Initialize timings that cannot be deduced from timing mode:
  678. * tPROG, tBERS, tR, tCCS and tCAD.
  679. * These information are part of the ONFI parameter page.
  680. */
  681. if (onfi) {
  682. struct nand_nvddr_timings *timings = &iface->timings.nvddr;
  683. /* microseconds -> picoseconds */
  684. timings->tPROG_max = 1000000ULL * onfi->tPROG;
  685. timings->tBERS_max = 1000000ULL * onfi->tBERS;
  686. timings->tR_max = 1000000ULL * onfi->tR;
  687. /* nanoseconds -> picoseconds */
  688. timings->tCCS_min = 1000UL * onfi->tCCS;
  689. if (onfi->fast_tCAD)
  690. timings->tCAD_min = 25000;
  691. }
  692. }
  693. /**
  694. * onfi_fill_interface_config - Initialize an interface config from a given
  695. * ONFI mode
  696. * @chip: The NAND chip
  697. * @iface: The interface configuration to fill
  698. * @type: The interface type
  699. * @timing_mode: The ONFI timing mode
  700. */
  701. void onfi_fill_interface_config(struct nand_chip *chip,
  702. struct nand_interface_config *iface,
  703. enum nand_interface_type type,
  704. unsigned int timing_mode)
  705. {
  706. if (type == NAND_SDR_IFACE)
  707. return onfi_fill_sdr_interface_config(chip, iface, timing_mode);
  708. else
  709. return onfi_fill_nvddr_interface_config(chip, iface, timing_mode);
  710. }