nand_timings.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. * Copyright (C) 2014 Free Electrons
  3. *
  4. * 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. */
  11. #include <linux/kernel.h>
  12. #include <linux/err.h>
  13. #include <linux/export.h>
  14. #include <linux/mtd/nand.h>
  15. static const struct nand_data_interface onfi_sdr_timings[] = {
  16. /* Mode 0 */
  17. {
  18. .type = NAND_SDR_IFACE,
  19. .timings.sdr = {
  20. .tADL_min = 400000,
  21. .tALH_min = 20000,
  22. .tALS_min = 50000,
  23. .tAR_min = 25000,
  24. .tCEA_max = 100000,
  25. .tCEH_min = 20000,
  26. .tCH_min = 20000,
  27. .tCHZ_max = 100000,
  28. .tCLH_min = 20000,
  29. .tCLR_min = 20000,
  30. .tCLS_min = 50000,
  31. .tCOH_min = 0,
  32. .tCS_min = 70000,
  33. .tDH_min = 20000,
  34. .tDS_min = 40000,
  35. .tFEAT_max = 1000000,
  36. .tIR_min = 10000,
  37. .tITC_max = 1000000,
  38. .tRC_min = 100000,
  39. .tREA_max = 40000,
  40. .tREH_min = 30000,
  41. .tRHOH_min = 0,
  42. .tRHW_min = 200000,
  43. .tRHZ_max = 200000,
  44. .tRLOH_min = 0,
  45. .tRP_min = 50000,
  46. .tRR_min = 40000,
  47. .tRST_max = 250000000000ULL,
  48. .tWB_max = 200000,
  49. .tWC_min = 100000,
  50. .tWH_min = 30000,
  51. .tWHR_min = 120000,
  52. .tWP_min = 50000,
  53. .tWW_min = 100000,
  54. },
  55. },
  56. /* Mode 1 */
  57. {
  58. .type = NAND_SDR_IFACE,
  59. .timings.sdr = {
  60. .tADL_min = 400000,
  61. .tALH_min = 10000,
  62. .tALS_min = 25000,
  63. .tAR_min = 10000,
  64. .tCEA_max = 45000,
  65. .tCEH_min = 20000,
  66. .tCH_min = 10000,
  67. .tCHZ_max = 50000,
  68. .tCLH_min = 10000,
  69. .tCLR_min = 10000,
  70. .tCLS_min = 25000,
  71. .tCOH_min = 15000,
  72. .tCS_min = 35000,
  73. .tDH_min = 10000,
  74. .tDS_min = 20000,
  75. .tFEAT_max = 1000000,
  76. .tIR_min = 0,
  77. .tITC_max = 1000000,
  78. .tRC_min = 50000,
  79. .tREA_max = 30000,
  80. .tREH_min = 15000,
  81. .tRHOH_min = 15000,
  82. .tRHW_min = 100000,
  83. .tRHZ_max = 100000,
  84. .tRLOH_min = 0,
  85. .tRP_min = 25000,
  86. .tRR_min = 20000,
  87. .tRST_max = 500000000,
  88. .tWB_max = 100000,
  89. .tWC_min = 45000,
  90. .tWH_min = 15000,
  91. .tWHR_min = 80000,
  92. .tWP_min = 25000,
  93. .tWW_min = 100000,
  94. },
  95. },
  96. /* Mode 2 */
  97. {
  98. .type = NAND_SDR_IFACE,
  99. .timings.sdr = {
  100. .tADL_min = 400000,
  101. .tALH_min = 10000,
  102. .tALS_min = 15000,
  103. .tAR_min = 10000,
  104. .tCEA_max = 30000,
  105. .tCEH_min = 20000,
  106. .tCH_min = 10000,
  107. .tCHZ_max = 50000,
  108. .tCLH_min = 10000,
  109. .tCLR_min = 10000,
  110. .tCLS_min = 15000,
  111. .tCOH_min = 15000,
  112. .tCS_min = 25000,
  113. .tDH_min = 5000,
  114. .tDS_min = 15000,
  115. .tFEAT_max = 1000000,
  116. .tIR_min = 0,
  117. .tITC_max = 1000000,
  118. .tRC_min = 35000,
  119. .tREA_max = 25000,
  120. .tREH_min = 15000,
  121. .tRHOH_min = 15000,
  122. .tRHW_min = 100000,
  123. .tRHZ_max = 100000,
  124. .tRLOH_min = 0,
  125. .tRR_min = 20000,
  126. .tRST_max = 500000000,
  127. .tWB_max = 100000,
  128. .tRP_min = 17000,
  129. .tWC_min = 35000,
  130. .tWH_min = 15000,
  131. .tWHR_min = 80000,
  132. .tWP_min = 17000,
  133. .tWW_min = 100000,
  134. },
  135. },
  136. /* Mode 3 */
  137. {
  138. .type = NAND_SDR_IFACE,
  139. .timings.sdr = {
  140. .tADL_min = 400000,
  141. .tALH_min = 5000,
  142. .tALS_min = 10000,
  143. .tAR_min = 10000,
  144. .tCEA_max = 25000,
  145. .tCEH_min = 20000,
  146. .tCH_min = 5000,
  147. .tCHZ_max = 50000,
  148. .tCLH_min = 5000,
  149. .tCLR_min = 10000,
  150. .tCLS_min = 10000,
  151. .tCOH_min = 15000,
  152. .tCS_min = 25000,
  153. .tDH_min = 5000,
  154. .tDS_min = 10000,
  155. .tFEAT_max = 1000000,
  156. .tIR_min = 0,
  157. .tITC_max = 1000000,
  158. .tRC_min = 30000,
  159. .tREA_max = 20000,
  160. .tREH_min = 10000,
  161. .tRHOH_min = 15000,
  162. .tRHW_min = 100000,
  163. .tRHZ_max = 100000,
  164. .tRLOH_min = 0,
  165. .tRP_min = 15000,
  166. .tRR_min = 20000,
  167. .tRST_max = 500000000,
  168. .tWB_max = 100000,
  169. .tWC_min = 30000,
  170. .tWH_min = 10000,
  171. .tWHR_min = 80000,
  172. .tWP_min = 15000,
  173. .tWW_min = 100000,
  174. },
  175. },
  176. /* Mode 4 */
  177. {
  178. .type = NAND_SDR_IFACE,
  179. .timings.sdr = {
  180. .tADL_min = 400000,
  181. .tALH_min = 5000,
  182. .tALS_min = 10000,
  183. .tAR_min = 10000,
  184. .tCEA_max = 25000,
  185. .tCEH_min = 20000,
  186. .tCH_min = 5000,
  187. .tCHZ_max = 30000,
  188. .tCLH_min = 5000,
  189. .tCLR_min = 10000,
  190. .tCLS_min = 10000,
  191. .tCOH_min = 15000,
  192. .tCS_min = 20000,
  193. .tDH_min = 5000,
  194. .tDS_min = 10000,
  195. .tFEAT_max = 1000000,
  196. .tIR_min = 0,
  197. .tITC_max = 1000000,
  198. .tRC_min = 25000,
  199. .tREA_max = 20000,
  200. .tREH_min = 10000,
  201. .tRHOH_min = 15000,
  202. .tRHW_min = 100000,
  203. .tRHZ_max = 100000,
  204. .tRLOH_min = 5000,
  205. .tRP_min = 12000,
  206. .tRR_min = 20000,
  207. .tRST_max = 500000000,
  208. .tWB_max = 100000,
  209. .tWC_min = 25000,
  210. .tWH_min = 10000,
  211. .tWHR_min = 80000,
  212. .tWP_min = 12000,
  213. .tWW_min = 100000,
  214. },
  215. },
  216. /* Mode 5 */
  217. {
  218. .type = NAND_SDR_IFACE,
  219. .timings.sdr = {
  220. .tADL_min = 400000,
  221. .tALH_min = 5000,
  222. .tALS_min = 10000,
  223. .tAR_min = 10000,
  224. .tCEA_max = 25000,
  225. .tCEH_min = 20000,
  226. .tCH_min = 5000,
  227. .tCHZ_max = 30000,
  228. .tCLH_min = 5000,
  229. .tCLR_min = 10000,
  230. .tCLS_min = 10000,
  231. .tCOH_min = 15000,
  232. .tCS_min = 15000,
  233. .tDH_min = 5000,
  234. .tDS_min = 7000,
  235. .tFEAT_max = 1000000,
  236. .tIR_min = 0,
  237. .tITC_max = 1000000,
  238. .tRC_min = 20000,
  239. .tREA_max = 16000,
  240. .tREH_min = 7000,
  241. .tRHOH_min = 15000,
  242. .tRHW_min = 100000,
  243. .tRHZ_max = 100000,
  244. .tRLOH_min = 5000,
  245. .tRP_min = 10000,
  246. .tRR_min = 20000,
  247. .tRST_max = 500000000,
  248. .tWB_max = 100000,
  249. .tWC_min = 20000,
  250. .tWH_min = 7000,
  251. .tWHR_min = 80000,
  252. .tWP_min = 10000,
  253. .tWW_min = 100000,
  254. },
  255. },
  256. };
  257. /**
  258. * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
  259. * timings according to the given ONFI timing mode
  260. * @mode: ONFI timing mode
  261. */
  262. const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
  263. {
  264. if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
  265. return ERR_PTR(-EINVAL);
  266. return &onfi_sdr_timings[mode].timings.sdr;
  267. }
  268. EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
  269. /**
  270. * onfi_init_data_interface - [NAND Interface] Initialize a data interface from
  271. * given ONFI mode
  272. * @iface: The data interface to be initialized
  273. * @mode: The ONFI timing mode
  274. */
  275. int onfi_init_data_interface(struct nand_chip *chip,
  276. struct nand_data_interface *iface,
  277. enum nand_data_interface_type type,
  278. int timing_mode)
  279. {
  280. if (type != NAND_SDR_IFACE)
  281. return -EINVAL;
  282. if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
  283. return -EINVAL;
  284. *iface = onfi_sdr_timings[timing_mode];
  285. /*
  286. * TODO: initialize timings that cannot be deduced from timing mode:
  287. * tR, tPROG, tCCS, ...
  288. * These information are part of the ONFI parameter page.
  289. */
  290. return 0;
  291. }
  292. EXPORT_SYMBOL(onfi_init_data_interface);
  293. /**
  294. * nand_get_default_data_interface - [NAND Interface] Retrieve NAND
  295. * data interface for mode 0. This is used as default timing after
  296. * reset.
  297. */
  298. const struct nand_data_interface *nand_get_default_data_interface(void)
  299. {
  300. return &onfi_sdr_timings[0];
  301. }
  302. EXPORT_SYMBOL(nand_get_default_data_interface);