Skip to content
Snippets Groups Projects
interactive.c 71.1 KiB
Newer Older
 * Copyright 2010-2014 Freescale Semiconductor, Inc.
 * SPDX-License-Identifier:	GPL-2.0+
 */

/*
 * Generic driver for Freescale DDR/DDR2/DDR3 memory controller.
 * Based on code from spd_sdram.c
 * Author: James Yang [at freescale.com]
 *         York Sun [at freescale.com]
 */

#include <common.h>
#include <cli.h>
#include <linux/ctype.h>
#include <asm/types.h>
#include <fsl_ddr_sdram.h>
#include <fsl_ddr.h>

/* Option parameter Structures */
struct options_string {
	const char *option_name;
	size_t offset;
	unsigned int size;
	const char printhex;
};

static unsigned int picos_to_mhz(unsigned int picos)
{
	return 1000000 / picos;
}

static void print_option_table(const struct options_string *table,
			 int table_size,
			 const void *base)
{
	unsigned int i;
	unsigned int *ptr;
	unsigned long long *ptr_l;

	for (i = 0; i < table_size; i++) {
		switch (table[i].size) {
		case 4:
			ptr = (unsigned int *) (base + table[i].offset);
			if (table[i].printhex) {
				printf("%s = 0x%08X\n",
					table[i].option_name, *ptr);
			} else {
				printf("%s = %u\n",
					table[i].option_name, *ptr);
			}
			break;
		case 8:
			ptr_l = (unsigned long long *) (base + table[i].offset);
			printf("%s = %llu\n",
				table[i].option_name, *ptr_l);
			break;
		default:
			printf("Unrecognized size!\n");
			break;
		}
	}
}

static int handle_option_table(const struct options_string *table,
			 int table_size,
			 void *base,
			 const char *opt,
			 const char *val)
{
	unsigned int i;
	unsigned int value, *ptr;
	unsigned long long value_l, *ptr_l;

	for (i = 0; i < table_size; i++) {
		if (strcmp(table[i].option_name, opt) != 0)
			continue;
		switch (table[i].size) {
		case 4:
			value = simple_strtoul(val, NULL, 0);
			ptr = base + table[i].offset;
			*ptr = value;
			break;
		case 8:
			value_l = simple_strtoull(val, NULL, 0);
			ptr_l = base + table[i].offset;
			*ptr_l = value_l;
			break;
		default:
			printf("Unrecognized size!\n");
			break;
		}
		return 1;
	}

	return 0;
}

static void fsl_ddr_generic_edit(void *pdata,
			   void *pend,
			   unsigned int element_size,
			   unsigned int element_num,
			   unsigned int value)
{
	char *pcdata = (char *)pdata;		/* BIG ENDIAN ONLY */

	pcdata += element_num * element_size;
	if ((pcdata + element_size) > (char *) pend) {
		printf("trying to write past end of data\n");
		return;
	}

	switch (element_size) {
	case 1:
		__raw_writeb(value, pcdata);
		break;
	case 2:
		__raw_writew(value, pcdata);
		break;
	case 4:
		__raw_writel(value, pcdata);
		break;
	default:
		printf("unexpected element size %u\n", element_size);
		break;
	}
}

static void fsl_ddr_spd_edit(fsl_ddr_info_t *pinfo,
		       unsigned int ctrl_num,
		       unsigned int dimm_num,
		       unsigned int element_num,
		       unsigned int value)
{
	generic_spd_eeprom_t *pspd;

	pspd = &(pinfo->spd_installed_dimms[ctrl_num][dimm_num]);
	fsl_ddr_generic_edit(pspd, pspd + 1, 1, element_num, value);
}

#define COMMON_TIMING(x) {#x, offsetof(common_timing_params_t, x), \
	sizeof((common_timing_params_t *)0)->x, 0}

static void lowest_common_dimm_parameters_edit(fsl_ddr_info_t *pinfo,
					unsigned int ctrl_num,
					const char *optname_str,
					const char *value_str)
{
	common_timing_params_t *p = &pinfo->common_timing_params[ctrl_num];

	static const struct options_string options[] = {
		COMMON_TIMING(tckmin_x_ps),
		COMMON_TIMING(tckmax_ps),
#if defined(CONFIG_SYS_FSL_DDR3) || defined(CONFIG_SYS_FSL_DDR4)
		COMMON_TIMING(taamin_ps),
		COMMON_TIMING(trcd_ps),
		COMMON_TIMING(trp_ps),
		COMMON_TIMING(tras_ps),

#ifdef CONFIG_SYS_FSL_DDR4
		COMMON_TIMING(trfc1_ps),
		COMMON_TIMING(trfc2_ps),
		COMMON_TIMING(trfc4_ps),
		COMMON_TIMING(trrds_ps),
		COMMON_TIMING(trrdl_ps),
		COMMON_TIMING(tccdl_ps),
#else
		COMMON_TIMING(twtr_ps),
		COMMON_TIMING(trfc_ps),
		COMMON_TIMING(trrd_ps),
		COMMON_TIMING(trtp_ps),
#endif
		COMMON_TIMING(twr_ps),
		COMMON_TIMING(trc_ps),
		COMMON_TIMING(refresh_rate_ps),
		COMMON_TIMING(extended_op_srt),
#if defined(CONFIG_SYS_FSL_DDR1) || defined(CONFIG_SYS_FSL_DDR2)
		COMMON_TIMING(tis_ps),
		COMMON_TIMING(tih_ps),
		COMMON_TIMING(tds_ps),
		COMMON_TIMING(tdh_ps),
		COMMON_TIMING(tdqsq_max_ps),
		COMMON_TIMING(tqhs_ps),
		COMMON_TIMING(ndimms_present),
		COMMON_TIMING(lowest_common_spd_caslat),
		COMMON_TIMING(highest_common_derated_caslat),
		COMMON_TIMING(additive_latency),
		COMMON_TIMING(all_dimms_burst_lengths_bitmask),
		COMMON_TIMING(all_dimms_registered),
		COMMON_TIMING(all_dimms_unbuffered),
		COMMON_TIMING(all_dimms_ecc_capable),
		COMMON_TIMING(total_mem),
		COMMON_TIMING(base_address),
	};
	static const unsigned int n_opts = ARRAY_SIZE(options);
Loading
Loading full blame...