Skip to content
Snippets Groups Projects
sequencer.c 119 KiB
Newer Older
/*
 * Copyright Altera Corporation (C) 2012-2015
 *
 * SPDX-License-Identifier:    BSD-3-Clause
 */

#include <common.h>
#include <asm/io.h>
#include <asm/arch/sdram.h>
#include "sequencer.h"
#include "sequencer_auto.h"
#include "sequencer_auto_ac_init.h"
#include "sequencer_auto_inst_init.h"
#include "sequencer_defines.h"

static void scc_mgr_load_dqs_for_write_group(uint32_t write_group);

static struct socfpga_sdr_rw_load_manager *sdr_rw_load_mgr_regs =
	(struct socfpga_sdr_rw_load_manager *)(BASE_RW_MGR + 0x800);

static struct socfpga_sdr_rw_load_jump_manager *sdr_rw_load_jump_mgr_regs =
	(struct socfpga_sdr_rw_load_jump_manager *)(BASE_RW_MGR + 0xC00);

static struct socfpga_sdr_reg_file *sdr_reg_file =
	(struct socfpga_sdr_reg_file *)SDR_PHYGRP_REGFILEGRP_ADDRESS;

static struct socfpga_sdr_scc_mgr *sdr_scc_mgr =
	(struct socfpga_sdr_scc_mgr *)(BASE_SCC_MGR + 0x0E00);

static struct socfpga_phy_mgr_cmd *phy_mgr_cmd =
	(struct socfpga_phy_mgr_cmd *)(BASE_PHY_MGR);

static struct socfpga_phy_mgr_cfg *phy_mgr_cfg =
	(struct socfpga_phy_mgr_cfg *)(BASE_PHY_MGR + 0x4000);

static struct socfpga_data_mgr *data_mgr =
	(struct socfpga_data_mgr *)(BASE_DATA_MGR);

#define DELTA_D		1
#define MGR_SELECT_MASK		0xf8000

/*
 * In order to reduce ROM size, most of the selectable calibration steps are
 * decided at compile time based on the user's calibration mode selection,
 * as captured by the STATIC_CALIB_STEPS selection below.
 *
 * However, to support simulation-time selection of fast simulation mode, where
 * we skip everything except the bare minimum, we need a few of the steps to
 * be dynamic.  In those cases, we either use the DYNAMIC_CALIB_STEPS for the
 * check, which is based on the rtl-supplied value, or we dynamically compute
 * the value to use based on the dynamically-chosen calibration mode
 */

#define DLEVEL 0
#define STATIC_IN_RTL_SIM 0
#define STATIC_SKIP_DELAY_LOOPS 0

#define STATIC_CALIB_STEPS (STATIC_IN_RTL_SIM | CALIB_SKIP_FULL_TEST | \
	STATIC_SKIP_DELAY_LOOPS)

/* calibration steps requested by the rtl */
uint16_t dyn_calib_steps;

/*
 * To make CALIB_SKIP_DELAY_LOOPS a dynamic conditional option
 * instead of static, we use boolean logic to select between
 * non-skip and skip values
 *
 * The mask is set to include all bits when not-skipping, but is
 * zero when skipping
 */

uint16_t skip_delay_mask;	/* mask off bits when skipping/not-skipping */

#define SKIP_DELAY_LOOP_VALUE_OR_ZERO(non_skip_value) \
	((non_skip_value) & skip_delay_mask)

struct gbl_type *gbl;
struct param_type *param;
uint32_t curr_shadow_reg;

static uint32_t rw_mgr_mem_calibrate_write_test(uint32_t rank_bgn,
	uint32_t write_group, uint32_t use_dm,
	uint32_t all_correct, uint32_t *bit_chk, uint32_t all_ranks);

static u32 sdr_get_addr(u32 *base)
{
	u32 addr = (u32)base & MGR_SELECT_MASK;

	switch (addr) {
	case BASE_PHY_MGR:
		addr = (((u32)base >> 8) & (1 << 6)) | ((u32)base & 0x3f) |
			SDR_PHYGRP_PHYMGRGRP_ADDRESS;
		break;
	case BASE_RW_MGR:
		addr = ((u32)base & 0x1fff) | SDR_PHYGRP_RWMGRGRP_ADDRESS;
		break;
	case BASE_DATA_MGR:
		addr = ((u32)base & 0x7ff) | SDR_PHYGRP_DATAMGRGRP_ADDRESS;
		break;
	case BASE_SCC_MGR:
		addr = ((u32)base & 0xfff) | SDR_PHYGRP_SCCGRP_ADDRESS;
		break;
	case BASE_REG_FILE:
		addr = ((u32)base & 0x7ff) | SDR_PHYGRP_REGFILEGRP_ADDRESS;
		break;
	case BASE_MMR:
		addr = ((u32)base & 0xfff) | SDR_CTRLGRP_ADDRESS;
		break;
	default:
		return -1;
	}

	return addr;
}

static void set_failing_group_stage(uint32_t group, uint32_t stage,
	uint32_t substage)
{
	/*
	 * Only set the global stage if there was not been any other
	 * failing group
	 */
	if (gbl->error_stage == CAL_STAGE_NIL)	{
		gbl->error_substage = substage;
		gbl->error_stage = stage;
		gbl->error_group = group;
	}
}

static void reg_file_set_group(uint32_t set_group)
{
	u32 addr = (u32)&sdr_reg_file->cur_stage;

	/* Read the current group and stage */
	uint32_t cur_stage_group = readl(SOCFPGA_SDR_ADDRESS + addr);

	/* Clear the group */
	cur_stage_group &= 0x0000FFFF;

	/* Set the group */
	cur_stage_group |= (set_group << 16);

	/* Write the data back */
	writel(cur_stage_group, SOCFPGA_SDR_ADDRESS + addr);
}

static void reg_file_set_stage(uint32_t set_stage)
{
	u32 addr = (u32)&sdr_reg_file->cur_stage;

	/* Read the current group and stage */
	uint32_t cur_stage_group = readl(SOCFPGA_SDR_ADDRESS + addr);

	/* Clear the stage and substage */
	cur_stage_group &= 0xFFFF0000;

	/* Set the stage */
	cur_stage_group |= (set_stage & 0x000000FF);

	/* Write the data back */
	writel(cur_stage_group, SOCFPGA_SDR_ADDRESS + addr);
}

static void reg_file_set_sub_stage(uint32_t set_sub_stage)
{
	u32 addr = (u32)&sdr_reg_file->cur_stage;

	/* Read the current group and stage */
	uint32_t cur_stage_group = readl(SOCFPGA_SDR_ADDRESS + addr);

	/* Clear the substage */
	cur_stage_group &= 0xFFFF00FF;

	/* Set the sub stage */
	cur_stage_group |= ((set_sub_stage << 8) & 0x0000FF00);

	/* Write the data back */
	writel(cur_stage_group, SOCFPGA_SDR_ADDRESS + addr);
}

static void initialize(void)
{
	u32 addr = sdr_get_addr(&phy_mgr_cfg->mux_sel);

	debug("%s:%d\n", __func__, __LINE__);
	/* USER calibration has control over path to memory */
	/*
	 * In Hard PHY this is a 2-bit control:
	 * 0: AFI Mux Select
	 * 1: DDIO Mux Select
	 */
	writel(0x3, SOCFPGA_SDR_ADDRESS + addr);

	/* USER memory clock is not stable we begin initialization  */
	addr = sdr_get_addr(&phy_mgr_cfg->reset_mem_stbl);
	writel(0, SOCFPGA_SDR_ADDRESS + addr);

	/* USER calibration status all set to zero */
	addr = sdr_get_addr(&phy_mgr_cfg->cal_status);
Loading
Loading full blame...