int check_ddr_training(void)
{
#ifdef CONFIG_DDR_TRAINING_STARTUP
	int ix;
	char *s = getenv("unddrtr");

	if (s && (*s == 'y' || *s == 'Y'))
		return 0;


	if (get_ddrtr_result_by_env(&ddrtr_result)) {
		/* ddr training function will set value to ddr register. */

		if (ddr_training())
			return 0;

		setenv(DDR_TRAINING_ENV,
			dump_ddrtr_result(&ddrtr_result, ' '));
		return do_saveenv(NULL, 0, 0, NULL);
	}

	printf("Set training value to DDR controller\n");
	for (ix = 0; ix < ddrtr_result.count; ix++) {
		writel(ddrtr_result.reg[ix].val,
			ddrtr_result.reg[ix].reg);
	}
#endif /* CONFIG_DDR_TRAINING_STARTUP */

	return 0;
}
static int ddr_addrtrain(void)
{
	ddrtr_t entry;
	struct ddrtr_result_t *result;
	struct ddrtr_param_t param;

	param.cmd = DDRTR_PARAM_ADDRTRAIN;
	entry = (ddrtr_t)get_ddrtr_entry();
	if (!entry)
		return -1;
	printf("## DDR address training entry: 0x%08X, ", (unsigned int)entry);

	asm("mcr p15, 0, r0, c7, c5, 0");
	asm("mcr p15, 0, r0, c7, c10, 4");

	result = entry(&param);
	if (!result) {
		printf("## DDR address training fail, reset system.\n");
		reset_cpu(0);
		return 0;
	}

	memcpy((void *)&ddrtr_result, result, sizeof(ddrtr_result));
	printf("## DDR address training terminated.\n");
	ddr_training_result((unsigned int)(&(ddrtr_result.data)));
	printf("\nDDR address training Registers and Value:\n");
	printf(dump_ddrtr_result(result, '\n'));
	return 0;
}
int do_ddr_training(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	if (argc < 2 || strcmp(argv[1], "training")) {
		cmd_usage(cmdtp);
		return 1;
	}

	if (ddr_training())
		return 0;

#ifdef CONFIG_DDR_TRAINING_STARTUP
	setenv(DDR_TRAINING_ENV, dump_ddrtr_result(&ddrtr_result, ' '));
#endif /* CONFIG_DDR_TRAINING_STARTUP */

	return 0;
}
int ddr_training(void)
{
	ddrtr_t entry;
	unsigned int start, length;
	struct ddrtr_result_t *result;
	struct ddrtr_param_t param;

	start = get_ddr_free(&length, 0x100000);
	param.cmd = DDRTR_PARAM_TRAINING;
	param.train.start = start;
	param.train.length = length;

	entry = (ddrtr_t)get_ddrtr_entry();
	if (!entry)
		return -1;

	printf("## DDR training entry: 0x%08X  area: 0x%08X - 0x%08X\n",
		(unsigned int)entry, start, start + length);

	asm("mcr p15, 0, r0, c7, c5, 0");
	asm("mcr p15, 0, r0, c7, c10, 4");

	result = entry(&param);
	if (!result) {
		printf("## DDR training fail, reset system.\n");
		reset_cpu(0);
		return 0;
	}
	memcpy((void *)&ddrtr_result, result, sizeof(ddrtr_result));

	printf("## DDR training terminated.\n");

	ddr_training_result((unsigned int)(&(ddrtr_result.data)));

	printf("\nDDR Training Registers and Value:\n");
	printf(dump_ddrtr_result(result, '\n'));

	return 0;
}
int ddr_training(void)
{
	ddrtr_t entry;
	unsigned int start, end;
	struct ddrtr_result_t *result;

	start = get_ddr_free(&end, 0x100000);
	end += start;

	entry = (ddrtr_t)get_ddrtr_entry();
	if (!entry)
		return -1;

	printf ("## DDR training entry: 0x%08X, "
		"training area: 0x%08X - 0x%08X\n",
		(unsigned int)entry, start, end);

	asm("mcr p15, 0, r0, c7, c5, 0");
	asm("mcr p15, 0, r0, c7, c10, 4");

	result = entry(start, (end - start));
	if (!result) {
		printf("## DDR training fail, reset system.\n");
		reset_cpu(0);
		return 0;
	}
	memcpy((void*)&ddrtr_result, result, sizeof(ddrtr_result));

	printf ("## DDR training terminated.\n");

	ddr_training_result((unsigned int)(&(ddrtr_result.data)));

	printf("\nDDR Training Registers and Value:\n");
	printf(dump_ddrtr_result(result, '\n'));

	return 0;
}
int do_ddr_training(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	const char *cmd;

	if (argc < 2) {
		cmd_usage(cmdtp);
		return 1;
	}

	cmd = argv[1];

	if (!strcmp(cmd, "training"))
		return ddr_training();
	if (!strcmp(cmd, "addrtrain"))
		return ddr_addrtrain();
	if (!strcmp(cmd, "pressure"))
		return ddrt_pressure(argc - 1, argv + 1);

#ifdef CONFIG_DDR_TRAINING_STARTUP
	setenv(DDR_TRAINING_ENV, dump_ddrtr_result(&ddrtr_result, ' '));
#endif /* CONFIG_DDR_TRAINING_STARTUP */

	return 0;
}