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