mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	As part of bringing the master branch back in to next, we need to allow for all of these changes to exist here. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
		
			
				
	
	
		
			335 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			335 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 *  Copyright (C) 2014 Free Electrons
 | 
						|
 *
 | 
						|
 *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
 | 
						|
 *
 | 
						|
 * This program is free software; you can redistribute it and/or modify
 | 
						|
 * it under the terms of the GNU General Public License version 2 as
 | 
						|
 * published by the Free Software Foundation.
 | 
						|
 *
 | 
						|
 */
 | 
						|
#include <linux/err.h>
 | 
						|
#include <linux/kernel.h>
 | 
						|
#include <linux/mtd/rawnand.h>
 | 
						|
 | 
						|
static const struct nand_data_interface onfi_sdr_timings[] = {
 | 
						|
	/* Mode 0 */
 | 
						|
	{
 | 
						|
		.type = NAND_SDR_IFACE,
 | 
						|
		.timings.sdr = {
 | 
						|
			.tCCS_min = 500000,
 | 
						|
			.tR_max = 200000000,
 | 
						|
			.tADL_min = 400000,
 | 
						|
			.tALH_min = 20000,
 | 
						|
			.tALS_min = 50000,
 | 
						|
			.tAR_min = 25000,
 | 
						|
			.tCEA_max = 100000,
 | 
						|
			.tCEH_min = 20000,
 | 
						|
			.tCH_min = 20000,
 | 
						|
			.tCHZ_max = 100000,
 | 
						|
			.tCLH_min = 20000,
 | 
						|
			.tCLR_min = 20000,
 | 
						|
			.tCLS_min = 50000,
 | 
						|
			.tCOH_min = 0,
 | 
						|
			.tCS_min = 70000,
 | 
						|
			.tDH_min = 20000,
 | 
						|
			.tDS_min = 40000,
 | 
						|
			.tFEAT_max = 1000000,
 | 
						|
			.tIR_min = 10000,
 | 
						|
			.tITC_max = 1000000,
 | 
						|
			.tRC_min = 100000,
 | 
						|
			.tREA_max = 40000,
 | 
						|
			.tREH_min = 30000,
 | 
						|
			.tRHOH_min = 0,
 | 
						|
			.tRHW_min = 200000,
 | 
						|
			.tRHZ_max = 200000,
 | 
						|
			.tRLOH_min = 0,
 | 
						|
			.tRP_min = 50000,
 | 
						|
			.tRR_min = 40000,
 | 
						|
			.tRST_max = 250000000000ULL,
 | 
						|
			.tWB_max = 200000,
 | 
						|
			.tWC_min = 100000,
 | 
						|
			.tWH_min = 30000,
 | 
						|
			.tWHR_min = 120000,
 | 
						|
			.tWP_min = 50000,
 | 
						|
			.tWW_min = 100000,
 | 
						|
		},
 | 
						|
	},
 | 
						|
	/* Mode 1 */
 | 
						|
	{
 | 
						|
		.type = NAND_SDR_IFACE,
 | 
						|
		.timings.sdr = {
 | 
						|
			.tCCS_min = 500000,
 | 
						|
			.tR_max = 200000000,
 | 
						|
			.tADL_min = 400000,
 | 
						|
			.tALH_min = 10000,
 | 
						|
			.tALS_min = 25000,
 | 
						|
			.tAR_min = 10000,
 | 
						|
			.tCEA_max = 45000,
 | 
						|
			.tCEH_min = 20000,
 | 
						|
			.tCH_min = 10000,
 | 
						|
			.tCHZ_max = 50000,
 | 
						|
			.tCLH_min = 10000,
 | 
						|
			.tCLR_min = 10000,
 | 
						|
			.tCLS_min = 25000,
 | 
						|
			.tCOH_min = 15000,
 | 
						|
			.tCS_min = 35000,
 | 
						|
			.tDH_min = 10000,
 | 
						|
			.tDS_min = 20000,
 | 
						|
			.tFEAT_max = 1000000,
 | 
						|
			.tIR_min = 0,
 | 
						|
			.tITC_max = 1000000,
 | 
						|
			.tRC_min = 50000,
 | 
						|
			.tREA_max = 30000,
 | 
						|
			.tREH_min = 15000,
 | 
						|
			.tRHOH_min = 15000,
 | 
						|
			.tRHW_min = 100000,
 | 
						|
			.tRHZ_max = 100000,
 | 
						|
			.tRLOH_min = 0,
 | 
						|
			.tRP_min = 25000,
 | 
						|
			.tRR_min = 20000,
 | 
						|
			.tRST_max = 500000000,
 | 
						|
			.tWB_max = 100000,
 | 
						|
			.tWC_min = 45000,
 | 
						|
			.tWH_min = 15000,
 | 
						|
			.tWHR_min = 80000,
 | 
						|
			.tWP_min = 25000,
 | 
						|
			.tWW_min = 100000,
 | 
						|
		},
 | 
						|
	},
 | 
						|
	/* Mode 2 */
 | 
						|
	{
 | 
						|
		.type = NAND_SDR_IFACE,
 | 
						|
		.timings.sdr = {
 | 
						|
			.tCCS_min = 500000,
 | 
						|
			.tR_max = 200000000,
 | 
						|
			.tADL_min = 400000,
 | 
						|
			.tALH_min = 10000,
 | 
						|
			.tALS_min = 15000,
 | 
						|
			.tAR_min = 10000,
 | 
						|
			.tCEA_max = 30000,
 | 
						|
			.tCEH_min = 20000,
 | 
						|
			.tCH_min = 10000,
 | 
						|
			.tCHZ_max = 50000,
 | 
						|
			.tCLH_min = 10000,
 | 
						|
			.tCLR_min = 10000,
 | 
						|
			.tCLS_min = 15000,
 | 
						|
			.tCOH_min = 15000,
 | 
						|
			.tCS_min = 25000,
 | 
						|
			.tDH_min = 5000,
 | 
						|
			.tDS_min = 15000,
 | 
						|
			.tFEAT_max = 1000000,
 | 
						|
			.tIR_min = 0,
 | 
						|
			.tITC_max = 1000000,
 | 
						|
			.tRC_min = 35000,
 | 
						|
			.tREA_max = 25000,
 | 
						|
			.tREH_min = 15000,
 | 
						|
			.tRHOH_min = 15000,
 | 
						|
			.tRHW_min = 100000,
 | 
						|
			.tRHZ_max = 100000,
 | 
						|
			.tRLOH_min = 0,
 | 
						|
			.tRR_min = 20000,
 | 
						|
			.tRST_max = 500000000,
 | 
						|
			.tWB_max = 100000,
 | 
						|
			.tRP_min = 17000,
 | 
						|
			.tWC_min = 35000,
 | 
						|
			.tWH_min = 15000,
 | 
						|
			.tWHR_min = 80000,
 | 
						|
			.tWP_min = 17000,
 | 
						|
			.tWW_min = 100000,
 | 
						|
		},
 | 
						|
	},
 | 
						|
	/* Mode 3 */
 | 
						|
	{
 | 
						|
		.type = NAND_SDR_IFACE,
 | 
						|
		.timings.sdr = {
 | 
						|
			.tCCS_min = 500000,
 | 
						|
			.tR_max = 200000000,
 | 
						|
			.tADL_min = 400000,
 | 
						|
			.tALH_min = 5000,
 | 
						|
			.tALS_min = 10000,
 | 
						|
			.tAR_min = 10000,
 | 
						|
			.tCEA_max = 25000,
 | 
						|
			.tCEH_min = 20000,
 | 
						|
			.tCH_min = 5000,
 | 
						|
			.tCHZ_max = 50000,
 | 
						|
			.tCLH_min = 5000,
 | 
						|
			.tCLR_min = 10000,
 | 
						|
			.tCLS_min = 10000,
 | 
						|
			.tCOH_min = 15000,
 | 
						|
			.tCS_min = 25000,
 | 
						|
			.tDH_min = 5000,
 | 
						|
			.tDS_min = 10000,
 | 
						|
			.tFEAT_max = 1000000,
 | 
						|
			.tIR_min = 0,
 | 
						|
			.tITC_max = 1000000,
 | 
						|
			.tRC_min = 30000,
 | 
						|
			.tREA_max = 20000,
 | 
						|
			.tREH_min = 10000,
 | 
						|
			.tRHOH_min = 15000,
 | 
						|
			.tRHW_min = 100000,
 | 
						|
			.tRHZ_max = 100000,
 | 
						|
			.tRLOH_min = 0,
 | 
						|
			.tRP_min = 15000,
 | 
						|
			.tRR_min = 20000,
 | 
						|
			.tRST_max = 500000000,
 | 
						|
			.tWB_max = 100000,
 | 
						|
			.tWC_min = 30000,
 | 
						|
			.tWH_min = 10000,
 | 
						|
			.tWHR_min = 80000,
 | 
						|
			.tWP_min = 15000,
 | 
						|
			.tWW_min = 100000,
 | 
						|
		},
 | 
						|
	},
 | 
						|
	/* Mode 4 */
 | 
						|
	{
 | 
						|
		.type = NAND_SDR_IFACE,
 | 
						|
		.timings.sdr = {
 | 
						|
			.tCCS_min = 500000,
 | 
						|
			.tR_max = 200000000,
 | 
						|
			.tADL_min = 400000,
 | 
						|
			.tALH_min = 5000,
 | 
						|
			.tALS_min = 10000,
 | 
						|
			.tAR_min = 10000,
 | 
						|
			.tCEA_max = 25000,
 | 
						|
			.tCEH_min = 20000,
 | 
						|
			.tCH_min = 5000,
 | 
						|
			.tCHZ_max = 30000,
 | 
						|
			.tCLH_min = 5000,
 | 
						|
			.tCLR_min = 10000,
 | 
						|
			.tCLS_min = 10000,
 | 
						|
			.tCOH_min = 15000,
 | 
						|
			.tCS_min = 20000,
 | 
						|
			.tDH_min = 5000,
 | 
						|
			.tDS_min = 10000,
 | 
						|
			.tFEAT_max = 1000000,
 | 
						|
			.tIR_min = 0,
 | 
						|
			.tITC_max = 1000000,
 | 
						|
			.tRC_min = 25000,
 | 
						|
			.tREA_max = 20000,
 | 
						|
			.tREH_min = 10000,
 | 
						|
			.tRHOH_min = 15000,
 | 
						|
			.tRHW_min = 100000,
 | 
						|
			.tRHZ_max = 100000,
 | 
						|
			.tRLOH_min = 5000,
 | 
						|
			.tRP_min = 12000,
 | 
						|
			.tRR_min = 20000,
 | 
						|
			.tRST_max = 500000000,
 | 
						|
			.tWB_max = 100000,
 | 
						|
			.tWC_min = 25000,
 | 
						|
			.tWH_min = 10000,
 | 
						|
			.tWHR_min = 80000,
 | 
						|
			.tWP_min = 12000,
 | 
						|
			.tWW_min = 100000,
 | 
						|
		},
 | 
						|
	},
 | 
						|
	/* Mode 5 */
 | 
						|
	{
 | 
						|
		.type = NAND_SDR_IFACE,
 | 
						|
		.timings.sdr = {
 | 
						|
			.tCCS_min = 500000,
 | 
						|
			.tR_max = 200000000,
 | 
						|
			.tADL_min = 400000,
 | 
						|
			.tALH_min = 5000,
 | 
						|
			.tALS_min = 10000,
 | 
						|
			.tAR_min = 10000,
 | 
						|
			.tCEA_max = 25000,
 | 
						|
			.tCEH_min = 20000,
 | 
						|
			.tCH_min = 5000,
 | 
						|
			.tCHZ_max = 30000,
 | 
						|
			.tCLH_min = 5000,
 | 
						|
			.tCLR_min = 10000,
 | 
						|
			.tCLS_min = 10000,
 | 
						|
			.tCOH_min = 15000,
 | 
						|
			.tCS_min = 15000,
 | 
						|
			.tDH_min = 5000,
 | 
						|
			.tDS_min = 7000,
 | 
						|
			.tFEAT_max = 1000000,
 | 
						|
			.tIR_min = 0,
 | 
						|
			.tITC_max = 1000000,
 | 
						|
			.tRC_min = 20000,
 | 
						|
			.tREA_max = 16000,
 | 
						|
			.tREH_min = 7000,
 | 
						|
			.tRHOH_min = 15000,
 | 
						|
			.tRHW_min = 100000,
 | 
						|
			.tRHZ_max = 100000,
 | 
						|
			.tRLOH_min = 5000,
 | 
						|
			.tRP_min = 10000,
 | 
						|
			.tRR_min = 20000,
 | 
						|
			.tRST_max = 500000000,
 | 
						|
			.tWB_max = 100000,
 | 
						|
			.tWC_min = 20000,
 | 
						|
			.tWH_min = 7000,
 | 
						|
			.tWHR_min = 80000,
 | 
						|
			.tWP_min = 10000,
 | 
						|
			.tWW_min = 100000,
 | 
						|
		},
 | 
						|
	},
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
 | 
						|
 * timings according to the given ONFI timing mode
 | 
						|
 * @mode: ONFI timing mode
 | 
						|
 */
 | 
						|
const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
 | 
						|
{
 | 
						|
	if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
 | 
						|
		return ERR_PTR(-EINVAL);
 | 
						|
 | 
						|
	return &onfi_sdr_timings[mode].timings.sdr;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(onfi_async_timing_mode_to_sdr_timings);
 | 
						|
 | 
						|
/**
 | 
						|
 * onfi_init_data_interface - [NAND Interface] Initialize a data interface from
 | 
						|
 * given ONFI mode
 | 
						|
 * @iface: The data interface to be initialized
 | 
						|
 * @mode: The ONFI timing mode
 | 
						|
 */
 | 
						|
int onfi_init_data_interface(struct nand_chip *chip,
 | 
						|
			     struct nand_data_interface *iface,
 | 
						|
			     enum nand_data_interface_type type,
 | 
						|
			     int timing_mode)
 | 
						|
{
 | 
						|
	if (type != NAND_SDR_IFACE)
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	if (timing_mode < 0 || timing_mode >= ARRAY_SIZE(onfi_sdr_timings))
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	*iface = onfi_sdr_timings[timing_mode];
 | 
						|
 | 
						|
	/*
 | 
						|
	 * Initialize timings that cannot be deduced from timing mode:
 | 
						|
	 * tR, tPROG, tCCS, ...
 | 
						|
	 * These information are part of the ONFI parameter page.
 | 
						|
	 */
 | 
						|
	if (chip->onfi_version) {
 | 
						|
		struct nand_onfi_params *params = &chip->onfi_params;
 | 
						|
		struct nand_sdr_timings *timings = &iface->timings.sdr;
 | 
						|
 | 
						|
		/* microseconds -> picoseconds */
 | 
						|
		timings->tPROG_max = 1000000ULL * le16_to_cpu(params->t_prog);
 | 
						|
		timings->tBERS_max = 1000000ULL * le16_to_cpu(params->t_bers);
 | 
						|
		timings->tR_max = 1000000ULL * le16_to_cpu(params->t_r);
 | 
						|
 | 
						|
		/* nanoseconds -> picoseconds */
 | 
						|
		timings->tCCS_min = 1000UL * le16_to_cpu(params->t_ccs);
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(onfi_init_data_interface);
 | 
						|
 | 
						|
/**
 | 
						|
 * nand_get_default_data_interface - [NAND Interface] Retrieve NAND
 | 
						|
 * data interface for mode 0. This is used as default timing after
 | 
						|
 * reset.
 | 
						|
 */
 | 
						|
const struct nand_data_interface *nand_get_default_data_interface(void)
 | 
						|
{
 | 
						|
	return &onfi_sdr_timings[0];
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(nand_get_default_data_interface);
 |