1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2014 Free Electrons 4 * 5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> 6 */ 7 #include <linux/kernel.h> 8 #include <linux/err.h> 9 #include <linux/export.h> 10 11 #include "internals.h" 12 13 #define ONFI_DYN_TIMING_MAX U16_MAX 14 15 static const struct nand_data_interface onfi_sdr_timings[] = { 16 /* Mode 0 */ 17 { 18 .type = NAND_SDR_IFACE, 19 .timings.mode = 0, 20 .timings.sdr = { 21 .tCCS_min = 500000, 22 .tR_max = 200000000, 23 .tADL_min = 400000, 24 .tALH_min = 20000, 25 .tALS_min = 50000, 26 .tAR_min = 25000, 27 .tCEA_max = 100000, 28 .tCEH_min = 20000, 29 .tCH_min = 20000, 30 .tCHZ_max = 100000, 31 .tCLH_min = 20000, 32 .tCLR_min = 20000, 33 .tCLS_min = 50000, 34 .tCOH_min = 0, 35 .tCS_min = 70000, 36 .tDH_min = 20000, 37 .tDS_min = 40000, 38 .tFEAT_max = 1000000, 39 .tIR_min = 10000, 40 .tITC_max = 1000000, 41 .tRC_min = 100000, 42 .tREA_max = 40000, 43 .tREH_min = 30000, 44 .tRHOH_min = 0, 45 .tRHW_min = 200000, 46 .tRHZ_max = 200000, 47 .tRLOH_min = 0, 48 .tRP_min = 50000, 49 .tRR_min = 40000, 50 .tRST_max = 250000000000ULL, 51 .tWB_max = 200000, 52 .tWC_min = 100000, 53 .tWH_min = 30000, 54 .tWHR_min = 120000, 55 .tWP_min = 50000, 56 .tWW_min = 100000, 57 }, 58 }, 59 /* Mode 1 */ 60 { 61 .type = NAND_SDR_IFACE, 62 .timings.mode = 1, 63 .timings.sdr = { 64 .tCCS_min = 500000, 65 .tR_max = 200000000, 66 .tADL_min = 400000, 67 .tALH_min = 10000, 68 .tALS_min = 25000, 69 .tAR_min = 10000, 70 .tCEA_max = 45000, 71 .tCEH_min = 20000, 72 .tCH_min = 10000, 73 .tCHZ_max = 50000, 74 .tCLH_min = 10000, 75 .tCLR_min = 10000, 76 .tCLS_min = 25000, 77 .tCOH_min = 15000, 78 .tCS_min = 35000, 79 .tDH_min = 10000, 80 .tDS_min = 20000, 81 .tFEAT_max = 1000000, 82 .tIR_min = 0, 83 .tITC_max = 1000000, 84 .tRC_min = 50000, 85 .tREA_max = 30000, 86 .tREH_min = 15000, 87 .tRHOH_min = 15000, 88 .tRHW_min = 100000, 89 .tRHZ_max = 100000, 90 .tRLOH_min = 0, 91 .tRP_min = 25000, 92 .tRR_min = 20000, 93 .tRST_max = 500000000, 94 .tWB_max = 100000, 95 .tWC_min = 45000, 96 .tWH_min = 15000, 97 .tWHR_min = 80000, 98 .tWP_min = 25000, 99 .tWW_min = 100000, 100 }, 101 }, 102 /* Mode 2 */ 103 { 104 .type = NAND_SDR_IFACE, 105 .timings.mode = 2, 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.mode = 3, 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.mode = 4, 192 .timings.sdr = { 193 .tCCS_min = 500000, 194 .tR_max = 200000000, 195 .tADL_min = 400000, 196 .tALH_min = 5000, 197 .tALS_min = 10000, 198 .tAR_min = 10000, 199 .tCEA_max = 25000, 200 .tCEH_min = 20000, 201 .tCH_min = 5000, 202 .tCHZ_max = 30000, 203 .tCLH_min = 5000, 204 .tCLR_min = 10000, 205 .tCLS_min = 10000, 206 .tCOH_min = 15000, 207 .tCS_min = 20000, 208 .tDH_min = 5000, 209 .tDS_min = 10000, 210 .tFEAT_max = 1000000, 211 .tIR_min = 0, 212 .tITC_max = 1000000, 213 .tRC_min = 25000, 214 .tREA_max = 20000, 215 .tREH_min = 10000, 216 .tRHOH_min = 15000, 217 .tRHW_min = 100000, 218 .tRHZ_max = 100000, 219 .tRLOH_min = 5000, 220 .tRP_min = 12000, 221 .tRR_min = 20000, 222 .tRST_max = 500000000, 223 .tWB_max = 100000, 224 .tWC_min = 25000, 225 .tWH_min = 10000, 226 .tWHR_min = 80000, 227 .tWP_min = 12000, 228 .tWW_min = 100000, 229 }, 230 }, 231 /* Mode 5 */ 232 { 233 .type = NAND_SDR_IFACE, 234 .timings.mode = 5, 235 .timings.sdr = { 236 .tCCS_min = 500000, 237 .tR_max = 200000000, 238 .tADL_min = 400000, 239 .tALH_min = 5000, 240 .tALS_min = 10000, 241 .tAR_min = 10000, 242 .tCEA_max = 25000, 243 .tCEH_min = 20000, 244 .tCH_min = 5000, 245 .tCHZ_max = 30000, 246 .tCLH_min = 5000, 247 .tCLR_min = 10000, 248 .tCLS_min = 10000, 249 .tCOH_min = 15000, 250 .tCS_min = 15000, 251 .tDH_min = 5000, 252 .tDS_min = 7000, 253 .tFEAT_max = 1000000, 254 .tIR_min = 0, 255 .tITC_max = 1000000, 256 .tRC_min = 20000, 257 .tREA_max = 16000, 258 .tREH_min = 7000, 259 .tRHOH_min = 15000, 260 .tRHW_min = 100000, 261 .tRHZ_max = 100000, 262 .tRLOH_min = 5000, 263 .tRP_min = 10000, 264 .tRR_min = 20000, 265 .tRST_max = 500000000, 266 .tWB_max = 100000, 267 .tWC_min = 20000, 268 .tWH_min = 7000, 269 .tWHR_min = 80000, 270 .tWP_min = 10000, 271 .tWW_min = 100000, 272 }, 273 }, 274 }; 275 276 /** 277 * onfi_fill_data_interface - [NAND Interface] Initialize a data interface from 278 * given ONFI mode 279 * @mode: The ONFI timing mode 280 */ 281 int onfi_fill_data_interface(struct nand_chip *chip, 282 enum nand_data_interface_type type, 283 int timing_mode) 284 { 285 struct nand_data_interface *iface = &chip->data_interface; 286 struct onfi_params *onfi = chip->parameters.onfi; 287 288 if (type != NAND_SDR_IFACE) 289 return -EINVAL; 290 291 if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings)) 292 return -EINVAL; 293 294 *iface = onfi_sdr_timings[timing_mode]; 295 296 /* 297 * Initialize timings that cannot be deduced from timing mode: 298 * tPROG, tBERS, tR and tCCS. 299 * These information are part of the ONFI parameter page. 300 */ 301 if (onfi) { 302 struct nand_sdr_timings *timings = &iface->timings.sdr; 303 304 /* microseconds -> picoseconds */ 305 timings->tPROG_max = 1000000ULL * onfi->tPROG; 306 timings->tBERS_max = 1000000ULL * onfi->tBERS; 307 timings->tR_max = 1000000ULL * onfi->tR; 308 309 /* nanoseconds -> picoseconds */ 310 timings->tCCS_min = 1000UL * onfi->tCCS; 311 } else { 312 struct nand_sdr_timings *timings = &iface->timings.sdr; 313 /* 314 * For non-ONFI chips we use the highest possible value for 315 * tPROG and tBERS. tR and tCCS will take the default values 316 * precised in the ONFI specification for timing mode 0, 317 * respectively 200us and 500ns. 318 */ 319 320 /* microseconds -> picoseconds */ 321 timings->tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX; 322 timings->tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX; 323 324 timings->tR_max = 200000000; 325 timings->tCCS_min = 500000; 326 } 327 328 return 0; 329 } 330