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