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