Home | History | Annotate | Download | only in nand
      1 /*
      2  *  Copyright (C) 2014 Free Electrons
      3  *
      4  *  Author: Boris BREZILLON <boris.brezillon (at) 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 <common.h>
     12 #include <linux/kernel.h>
     13 #include <linux/mtd/rawnand.h>
     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_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
    272  * timings according to the given ONFI timing mode
    273  * @mode: ONFI timing mode
    274  */
    275 const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
    276 {
    277 	if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
    278 		return ERR_PTR(-EINVAL);
    279 
    280 	return &onfi_sdr_timings[mode].timings.sdr;
    281 }
    282 EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
    283 
    284 /**
    285  * onfi_init_data_interface - [NAND Interface] Initialize a data interface from
    286  * given ONFI mode
    287  * @iface: The data interface to be initialized
    288  * @mode: The ONFI timing mode
    289  */
    290 int onfi_init_data_interface(struct nand_chip *chip,
    291 			     struct nand_data_interface *iface,
    292 			     enum nand_data_interface_type type,
    293 			     int timing_mode)
    294 {
    295 	if (type != NAND_SDR_IFACE)
    296 		return -EINVAL;
    297 
    298 	if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
    299 		return -EINVAL;
    300 
    301 	*iface = onfi_sdr_timings[timing_mode];
    302 
    303 	/*
    304 	 * Initialize timings that cannot be deduced from timing mode:
    305 	 * tR, tPROG, tCCS, ...
    306 	 * These information are part of the ONFI parameter page.
    307 	 */
    308 	if (chip->onfi_version) {
    309 		struct nand_onfi_params *params = &chip->onfi_params;
    310 		struct nand_sdr_timings *timings = &iface->timings.sdr;
    311 
    312 		/* microseconds -> picoseconds */
    313 		timings->tPROG_max = 1000000ULL * le16_to_cpu(params->t_prog);
    314 		timings->tBERS_max = 1000000ULL * le16_to_cpu(params->t_bers);
    315 		timings->tR_max = 1000000ULL * le16_to_cpu(params->t_r);
    316 
    317 		/* nanoseconds -> picoseconds */
    318 		timings->tCCS_min = 1000UL * le16_to_cpu(params->t_ccs);
    319 	}
    320 
    321 	return 0;
    322 }
    323 EXPORT_SYMBOL(onfi_init_data_interface);
    324 
    325 /**
    326  * nand_get_default_data_interface - [NAND Interface] Retrieve NAND
    327  * data interface for mode 0. This is used as default timing after
    328  * reset.
    329  */
    330 const struct nand_data_interface *nand_get_default_data_interface(void)
    331 {
    332 	return &onfi_sdr_timings[0];
    333 }
    334 EXPORT_SYMBOL(nand_get_default_data_interface);
    335