blob: d4b2f43252ca24e04ede0d481f78587872514af9 [file] [log] [blame]
/****************************************************************************
* arch/risc-v/src/mpfs/mpfs_ddr.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <errno.h>
#include <nuttx/arch.h>
#include <nuttx/wdog.h>
#include <nuttx/clock.h>
#include <nuttx/sdio.h>
#include <nuttx/signal.h>
#include <nuttx/irq.h>
#include <nuttx/cache.h>
#include <arch/board/board.h>
#include <arch/board/board_liberodefs.h>
#include "riscv_internal.h"
#include "mpfs_dma.h"
#include "hardware/mpfs_sysreg.h"
#include "hardware/mpfs_ddr.h"
#include "hardware/mpfs_sgmii.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* DDR write latency range */
#define WR_LATENCY_MIN 0
#define WR_LATENCY_MAX 3
/* Training types status offsets */
#define BCLK_SCLK_BIT (1 << 0)
#define ADDCMD_BIT (1 << 1)
#define WRLVL_BIT (1 << 2)
#define RDGATE_BIT (1 << 3)
#define DQ_DQS_BIT (1 << 4)
#define ONE_MB_MTC 20
/* RPC values and ranges */
#define DEFAULT_RPC_166_VALUE 2
#define MIN_RPC_166_VALUE 2
#define MAX_RPC_166_VALUE 4
#define NUM_RPC_166_VALUES (MAX_RPC_166_VALUE - \
MIN_RPC_166_VALUE)
/* Write - read memory test patterns */
#define PATTERN_INCREMENTAL (0x01 << 0)
#define PATTERN_WALKING_ONE (0x01 << 1)
#define PATTERN_WALKING_ZERO (0x01 << 2)
#define PATTERN_RANDOM (0x01 << 3)
#define PATTERN_CCCCCCCC (0x01 << 4)
#define PATTERN_55555555 (0x01 << 5)
#define PATTERN_ZEROS (0x01 << 6)
#define MAX_NO_PATTERNS 7
/* Write - read memory test properties */
#define SW_CFG_NUM_READS_WRITES 0x20000
#define SW_CONFIG_PATTERN (PATTERN_INCREMENTAL | \
PATTERN_WALKING_ONE | \
PATTERN_WALKING_ZERO | \
PATTERN_RANDOM | \
PATTERN_CCCCCCCC | \
PATTERN_55555555)
/* Retraining limits */
#define ABNORMAL_RETRAIN_CA_DECREASE_COUNT 2
#define ABNORMAL_RETRAIN_CA_DLY_DECREASE_COUNT 2
#define DQ_DQS_NUM_TAPS 5
/* PLL convenience bits */
#define PLL_CTRL_LOCK_BIT (1 << 25)
#define PLL_INIT_AND_OUT_OF_RESET 0x00000003
#define PLL_CTRL_REG_POWERDOWN_B_MASK 0x00000001
/* DDRPHY bit masks and defines */
#define DDRPHY_MODE_BUS_WIDTH_MASK (0x7 << 5)
#define DDRPHY_MODE_BUS_WIDTH_4_LANE (0x1 << 5)
#define DDRPHY_MODE_MASK 0x7
#define DDRPHY_MODE_ECC_MASK (0x1 << 3)
#define DDRPHY_MODE_ECC_ON (0x1 << 3)
#define DDRPHY_MODE_RANK_MASK (0x1 << 26)
#define DDRPHY_MODE_ONE_RANK (0x0 << 26)
#define DDRPHY_MODE_TWO_RANKS (0x1 << 26)
#define DMI_DBI_MASK (~(0x1 << 8))
/* DDR frequency properties */
#define DDR_FREQ_MARGIN 10
#define DDR_1333_MHZ 1333333333
#define DDR_1600_MHZ 1600000000
/* MPFS clock configuration register */
#define MPFS_SYSREG_SOFT_RESET_CR (MPFS_SYSREG_BASE + \
MPFS_SYSREG_SOFT_RESET_CR_OFFSET)
#define MPFS_SYSREG_SUBBLK_CLOCK_CR (MPFS_SYSREG_BASE + \
MPFS_SYSREG_SUBBLK_CLOCK_CR_OFFSET)
/* Max supported lanes */
#define MAX_LANES 5
/* BCLK / SCLK offset */
#define SW_TRAINING_BCLK_SCLK_OFFSET 0x00000000
/* Register poll retry counts until fail */
#define MPFS_DEFAULT_RETRIES 0xffff
#define MPFS_LONG_RETRIES 0xffffff
/****************************************************************************
* Private Types
****************************************************************************/
enum ddr_type_e
{
DDR3 = 0x00,
DDR3L = 0x01,
DDR4 = 0x02,
LPDDR3 = 0x03,
LPDDR4 = 0x04,
DDR_OFF_MODE = 0x07
};
enum seg_setup_e
{
DEFAULT_SEG_SETUP = 0x00,
LIBERO_SEG_SETUP
};
enum mtc_pattern_e
{
MTC_COUNTING_PATTERN = 0x00,
MTC_WALKING_ONE = 0x01,
MTC_PSEUDO_RANDOM = 0x02,
MTC_NO_REPEATING_PSEUDO_RANDOM = 0x03,
MTC_ALT_ONES_ZEROS = 0x04,
MTC_ALT_5_A = 0x05,
MTC_USER = 0x06,
MTC_PSEUDO_RANDOM_16BIT = 0x07,
MTC_PSEUDO_RANDOM_8BIT = 0x08,
};
enum mtc_add_pattern_e
{
MTC_ADD_SEQUENTIAL = 0x00,
MTC_ADD_RANDOM = 0x01,
};
enum ddr_access_size_e
{
DDR_32_BIT,
DDR_64_BIT
};
struct mpfs_ddr_priv_s
{
uint32_t tip_cfg_params;
uint32_t dpc_bits;
uint32_t rpc_166_fifo_offset;
uint32_t bclk_answer;
uint8_t number_of_lanes_to_calibrate;
uint8_t refclk_sweep_index;
bool en_addcmd0_ovrt9;
};
/****************************************************************************
* Private Data
****************************************************************************/
static struct mpfs_ddr_priv_s g_mpfs_ddr_priv =
{
.en_addcmd0_ovrt9 = true,
.refclk_sweep_index = 0xf,
.bclk_answer = 0,
};
#ifdef CONFIG_MPFS_DDR_MANUAL_ADDCMD_TRAINING
static const uint8_t refclk_offsets[][5] =
{
{LIBERO_SETTING_REFCLK_DDR3_1333_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_0,
LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_1,
LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_2,
LIBERO_SETTING_REFCLK_DDR3_1333_OFFSET_3},
{LIBERO_SETTING_REFCLK_DDR3L_1333_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_DDR3L_1333_OFFSET_0,
LIBERO_SETTING_REFCLK_DDR3L_1333_OFFSET_1,
LIBERO_SETTING_REFCLK_DDR3L_1333_OFFSET_2,
LIBERO_SETTING_REFCLK_DDR3L_1333_OFFSET_3},
{LIBERO_SETTING_REFCLK_DDR4_1600_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_DDR4_1600_OFFSET_0,
LIBERO_SETTING_REFCLK_DDR4_1600_OFFSET_1,
LIBERO_SETTING_REFCLK_DDR4_1600_OFFSET_2,
LIBERO_SETTING_REFCLK_DDR4_1600_OFFSET_3},
{LIBERO_SETTING_REFCLK_LPDDR3_1600_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_LPDDR3_1600_OFFSET_0,
LIBERO_SETTING_REFCLK_LPDDR3_1600_OFFSET_1,
LIBERO_SETTING_REFCLK_LPDDR3_1600_OFFSET_2,
LIBERO_SETTING_REFCLK_LPDDR3_1600_OFFSET_3},
{LIBERO_SETTING_REFCLK_LPDDR4_1600_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_LPDDR4_1600_OFFSET_0,
LIBERO_SETTING_REFCLK_LPDDR4_1600_OFFSET_1,
LIBERO_SETTING_REFCLK_LPDDR4_1600_OFFSET_2,
LIBERO_SETTING_REFCLK_LPDDR4_1600_OFFSET_3},
{LIBERO_SETTING_REFCLK_DDR3_1067_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_DDR3_1067_OFFSET_0,
LIBERO_SETTING_REFCLK_DDR3_1067_OFFSET_1,
LIBERO_SETTING_REFCLK_DDR3_1067_OFFSET_2,
LIBERO_SETTING_REFCLK_DDR3_1067_OFFSET_3},
{LIBERO_SETTING_REFCLK_DDR3L_1067_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_DDR3L_1067_OFFSET_0,
LIBERO_SETTING_REFCLK_DDR3L_1067_OFFSET_1,
LIBERO_SETTING_REFCLK_DDR3L_1067_OFFSET_2,
LIBERO_SETTING_REFCLK_DDR3L_1067_OFFSET_3},
{LIBERO_SETTING_REFCLK_DDR4_1333_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_DDR4_1333_OFFSET_0,
LIBERO_SETTING_REFCLK_DDR4_1333_OFFSET_1,
LIBERO_SETTING_REFCLK_DDR4_1333_OFFSET_2,
LIBERO_SETTING_REFCLK_DDR4_1333_OFFSET_3},
{LIBERO_SETTING_REFCLK_LPDDR3_1333_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_LPDDR3_1333_OFFSET_0,
LIBERO_SETTING_REFCLK_LPDDR3_1333_OFFSET_1,
LIBERO_SETTING_REFCLK_LPDDR3_1333_OFFSET_2,
LIBERO_SETTING_REFCLK_LPDDR3_1333_OFFSET_3},
{LIBERO_SETTING_REFCLK_LPDDR4_1333_NUM_OFFSETS,
LIBERO_SETTING_REFCLK_LPDDR4_1333_OFFSET_0,
LIBERO_SETTING_REFCLK_LPDDR4_1333_OFFSET_1,
LIBERO_SETTING_REFCLK_LPDDR4_1333_OFFSET_2,
LIBERO_SETTING_REFCLK_LPDDR4_1333_OFFSET_3},
};
#endif
/* State of the seiran128 PRNG, with initial seed */
static uint64_t prng_state[2] =
{
0x6c64f673ed93b6cc,
0x97c703d5f6c9d72b
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: mpfs_wait_cycles
*
* Description:
* Wait n number of cycles. This mimics the vendor provided wait loops.
*
* Input Parameters:
* n - number of cycles to loop
*
****************************************************************************/
static void mpfs_wait_cycles(uint32_t n)
{
volatile uint32_t count = n;
while (count != 0)
{
count--;
}
}
/****************************************************************************
* Name: mpfs_ddr_off_mode
*
* Description:
* Sets the DDR in off mode
*
****************************************************************************/
#ifdef CONFIG_MPFS_DDR_OFF_MODE
static void mpfs_ddr_off_mode(void)
{
/* Sets the mode register to off mode */
putreg32(LIBERO_SETTING_DDRPHY_MODE_OFF,
MPFS_CFG_DDR_SGMII_PHY_DDRPHY_MODE);
/* VS for off mode */
putreg32(LIBERO_SETTING_DPC_BITS_OFF_MODE,
MPFS_CFG_DDR_SGMII_PHY_DPC_BITS);
/* Toggle decoder here */
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_DRIVER);
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_ODT);
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_IO);
/* Set ibuff to off mode */
putreg32(0x07, MPFS_CFG_DDR_SGMII_PHY_RPC95); /* addcmd I/O */
putreg32(0x07, MPFS_CFG_DDR_SGMII_PHY_RPC96); /* clk */
putreg32(0x07, MPFS_CFG_DDR_SGMII_PHY_RPC97); /* dq */
putreg32(0x07, MPFS_CFG_DDR_SGMII_PHY_RPC98); /* dqs */
/* UNUSED_SPACE0:
* bits 15:14 connect to ibufmx DQ/DQS/DM
* bits 13:12 connect to ibufmx CA/CK
*/
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0);
/* REG_POWERDOWN_B on PLL turn-off, in case was turned on */
modifyreg32(MPFS_IOSCB_MSS_PLL_CTRL, 0x01, 0);
}
#endif
/****************************************************************************
* Name: mpfs_set_ddr_mode_reg_and_vs_bits
*
* Description:
* Sets the DDR PHY mode.
*
* Input Parameters:
* priv - Instance of the ddr private state structure.
*
****************************************************************************/
static void mpfs_set_ddr_mode_reg_and_vs_bits(struct mpfs_ddr_priv_s *priv)
{
uint32_t ddrphy_mode = LIBERO_SETTING_DDRPHY_MODE;
#ifdef MPFS_DDR_TYPE_DDR4
if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_ECC_MASK) ==
DDRPHY_MODE_ECC_ON)
{
/* For ECC on when DDR4, and data mask on during training, training
* will not pass. This will eventually be handled by the configurator.
* DM will not be allowed for DDR4 with ECC.
*/
ddrphy_mode &= DMI_DBI_MASK;
}
#endif
putreg32(ddrphy_mode, MPFS_CFG_DDR_SGMII_PHY_DDRPHY_MODE);
mpfs_wait_cycles(100);
putreg32(priv->dpc_bits, MPFS_CFG_DDR_SGMII_PHY_DPC_BITS);
}
/****************************************************************************
* Name: mpfs_config_ddr_io_pull_up_downs
*
* Description:
* Configure DDR pull-ups and pull-downs.
*
* Input Parameters:
* priv - Instance of the ddr private state structure.
*
****************************************************************************/
static void mpfs_config_ddr_io_pull_up_downs(struct mpfs_ddr_priv_s *priv)
{
#ifdef CONFIG_MPFS_DDR_TYPE_LPDDR4
if (priv->en_addcmd0_ovrt9)
{
/* set overrides (associated bit set to 1 if I/O not being used */
putreg32(LIBERO_SETTING_RPC_EN_ADDCMD0_OVRT9,
MPFS_CFG_DDR_SGMII_PHY_OVRT9);
putreg32(LIBERO_SETTING_RPC_EN_ADDCMD1_OVRT10,
MPFS_CFG_DDR_SGMII_PHY_OVRT10);
putreg32(LIBERO_SETTING_RPC_EN_ADDCMD2_OVRT11,
MPFS_CFG_DDR_SGMII_PHY_OVRT11);
putreg32(LIBERO_SETTING_RPC_EN_DATA0_OVRT12,
MPFS_CFG_DDR_SGMII_PHY_OVRT12);
putreg32(LIBERO_SETTING_RPC_EN_DATA1_OVRT13,
MPFS_CFG_DDR_SGMII_PHY_OVRT13);
putreg32(LIBERO_SETTING_RPC_EN_DATA2_OVRT14,
MPFS_CFG_DDR_SGMII_PHY_OVRT14);
putreg32(LIBERO_SETTING_RPC_EN_DATA3_OVRT15,
MPFS_CFG_DDR_SGMII_PHY_OVRT15);
putreg32(LIBERO_SETTING_RPC_EN_ECC_OVRT16,
MPFS_CFG_DDR_SGMII_PHY_OVRT16);
/* Set the required wpu state.
* Note: associated I/O bit 1=> off, 0=> on
*/
putreg32(LIBERO_SETTING_RPC235_WPD_ADD_CMD0,
MPFS_CFG_DDR_SGMII_PHY_RPC235);
putreg32(LIBERO_SETTING_RPC236_WPD_ADD_CMD1,
MPFS_CFG_DDR_SGMII_PHY_RPC236);
putreg32(LIBERO_SETTING_RPC237_WPD_ADD_CMD2,
MPFS_CFG_DDR_SGMII_PHY_RPC237);
putreg32(LIBERO_SETTING_RPC238_WPD_DATA0,
MPFS_CFG_DDR_SGMII_PHY_RPC238);
putreg32(LIBERO_SETTING_RPC239_WPD_DATA1,
MPFS_CFG_DDR_SGMII_PHY_RPC239);
putreg32(LIBERO_SETTING_RPC240_WPD_DATA2,
MPFS_CFG_DDR_SGMII_PHY_RPC240);
putreg32(LIBERO_SETTING_RPC241_WPD_DATA3,
MPFS_CFG_DDR_SGMII_PHY_RPC241);
putreg32(LIBERO_SETTING_RPC242_WPD_ECC,
MPFS_CFG_DDR_SGMII_PHY_RPC242);
/* Set the required wpd state.
* Note: associated I/O bit 1=> off, 0=> on
*/
putreg32(LIBERO_SETTING_RPC243_WPU_ADD_CMD0,
MPFS_CFG_DDR_SGMII_PHY_RPC243);
putreg32(LIBERO_SETTING_RPC244_WPU_ADD_CMD1,
MPFS_CFG_DDR_SGMII_PHY_RPC244);
putreg32(LIBERO_SETTING_RPC245_WPU_ADD_CMD2,
MPFS_CFG_DDR_SGMII_PHY_RPC245);
putreg32(LIBERO_SETTING_RPC246_WPU_DATA0,
MPFS_CFG_DDR_SGMII_PHY_RPC246);
putreg32(LIBERO_SETTING_RPC247_WPU_DATA1,
MPFS_CFG_DDR_SGMII_PHY_RPC247);
putreg32(LIBERO_SETTING_RPC248_WPU_DATA2,
MPFS_CFG_DDR_SGMII_PHY_RPC248);
putreg32(LIBERO_SETTING_RPC249_WPU_DATA3,
MPFS_CFG_DDR_SGMII_PHY_RPC249);
putreg32(LIBERO_SETTING_RPC250_WPU_ECC,
MPFS_CFG_DDR_SGMII_PHY_RPC250);
}
#endif
}
/****************************************************************************
* Name: mpfs_set_ddr_rpc_regs
*
* Description:
* Write DDR phy mode reg (eg. DDR3).
* When we write to the mode register, an ip state machine copies default
* values for the particular mode chosen to RPC registers associated with
* DDR in the MSS custom block.
*
* The RPC register values are transferred to the SCB registers in a
* subsequent step.
*
* Input Parameters:
* priv - Instance of the ddr private state structure.
*
****************************************************************************/
static void mpfs_set_ddr_rpc_regs(struct mpfs_ddr_priv_s *priv)
{
#if defined(CONFIG_MPFS_DDR_TYPE_DDR3) || defined(CONFIG_MPFS_DDR_TYPE_DDR3L)
/* Required when rank x 2 */
if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_RANK_MASK) ==
DDRPHY_MODE_TWO_RANKS)
{
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SPIO253);
}
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98);
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0);
#elif defined(CONFIG_MPFS_DDR_TYPE_DDR4)
putreg32(2, MPFS_CFG_DDR_SGMII_PHY_RPC10_ODT);
putreg32(2, MPFS_CFG_DDR_SGMII_PHY_RPC11_ODT);
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98);
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0);
#elif defined(CONFIG_MPFS_DDR_TYPE_LPDDR3)
putreg32(2, MPFS_CFG_DDR_SGMII_PHY_RPC10_ODT);
putreg32(2, MPFS_CFG_DDR_SGMII_PHY_RPC11_ODT);
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98);
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0);
#elif defined(CONFIG_MPFS_DDR_TYPE_LPDDR4)
/* OVRT_EN_ADDCMD1 (default 0xf00), register named ovrt11 */
if (!priv->en_addcmd0_ovrt9)
{
/* If this define is not present, indicates older
* Libero core (pre 2.0.109), so we run this code.
*/
putreg32(LIBERO_SETTING_RPC_EN_ADDCMD1_OVRT10,
MPFS_CFG_DDR_SGMII_PHY_OVRT10);
/* Use pull-ups to set the CMD/ADD ODT */
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_RPC245);
putreg32(0xffffffff, MPFS_CFG_DDR_SGMII_PHY_RPC237);
/* OVRT_EN_ADDCMD2 (default 0xE06U), register named ovrt12 */
putreg32(LIBERO_SETTING_RPC_EN_ADDCMD2_OVRT11,
MPFS_CFG_DDR_SGMII_PHY_OVRT11);
}
/* Required when rank x 2 */
if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_RANK_MASK) ==
DDRPHY_MODE_TWO_RANKS)
{
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SPIO253);
}
/* Write ibufmd_dqs. Value is a constant coped from HSS refenrece code */
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_RPC98);
/* Write TXDLY offset data. 0x14 is a constant copied from HSS reference
* code, it is unknown whether this needs to be adjustable at the moment
*/
putreg32(0x14, MPFS_CFG_DDR_SGMII_PHY_RPC226);
putreg32(0xa000, MPFS_CFG_DDR_SGMII_PHY_UNUSED_SPACE0);
putreg32(0xa000, MPFS_CFG_DDR_SGMII_PHY_SPARE0);
#endif
putreg32(LIBERO_SETTING_RPC_156_VALUE, MPFS_CFG_DDR_SGMII_PHY_RPC156);
putreg32(0x2, MPFS_CFG_DDR_SGMII_PHY_RPC27);
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_RPC203);
putreg32(LIBERO_SETTING_RPC_ODT_ADDCMD, MPFS_CFG_DDR_SGMII_PHY_RPC1_ODT);
putreg32(LIBERO_SETTING_RPC_ODT_CLK, MPFS_CFG_DDR_SGMII_PHY_RPC2_ODT);
putreg32(LIBERO_SETTING_RPC_ODT_DQ, MPFS_CFG_DDR_SGMII_PHY_RPC3_ODT);
putreg32(LIBERO_SETTING_RPC_ODT_DQS, MPFS_CFG_DDR_SGMII_PHY_RPC4_ODT);
/* bclk_sel_clkn - selects bclk sclk training clock */
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_RPC19);
/* Add cmd - selects bclk sclk training clock */
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_RPC20);
/* Each lane has its own FIFO. This paramater adjusts offset for
* all lanes.
*/
putreg32(priv->rpc_166_fifo_offset, MPFS_CFG_DDR_SGMII_PHY_RPC166);
mpfs_config_ddr_io_pull_up_downs(priv);
}
/****************************************************************************
* Name: mpfs_ddr_pvt_calibration
*
* Description:
* PVT calibration:
* Wait for IOEN from power detectors DDR and SGMII - IO enable signal
* from System Control power on.
*
* Returned Value:
* 0 on success, -ETIMEDOUT in case of error.
*
****************************************************************************/
static int mpfs_ddr_pvt_calibration(void)
{
uint32_t retries = MPFS_DEFAULT_RETRIES;
while ((!(getreg32(MPFS_CFG_DDR_SGMII_PHY_IOC_REG1) & (1 << 4))) &&
--retries);
if (retries == 0)
{
merr("timeout!\n");
return -ETIMEDOUT;
}
/* Voltage ramp time */
mpfs_wait_cycles(0xf);
/* DDRIO: calib_reset: 1 -> 0, clk divider changed - from 2 - to 3 */
putreg32(0x06, MPFS_CFG_DDR_SGMII_PHY_IOC_REG6);
/* PVT soft nv reset - SCB, should load from RPC */
putreg32(1, MPFS_IOSCB_CALIB_DDR_SOFT_RESET);
putreg32(0, MPFS_IOSCB_CALIB_DDR_SOFT_RESET);
/* R3.4 Wait for PVT calibration to complete;
* Check bit 2 sro_calib_status.
*
* The G5 Memory controller needs to see that the IO calibration has
* completed before kicking off DDR training.
* It uses the calib_status signal as a flag for this.
*/
while (!(getreg32(MPFS_IOSCB_CALIB_DDR_IOC_REG1) & 0x04));
while (!(getreg32(MPFS_CFG_DDR_SGMII_PHY_IOC_REG1) & 0x04));
/* Assert calib lock */
modifyreg32(MPFS_CFG_DDR_SGMII_PHY_IOC_REG0, (1 << 14), 0);
modifyreg32(MPFS_IOSCB_CALIB_DDR_IOC_REG0, (1 << 14), 0);
modifyreg32(MPFS_CFG_DDR_SGMII_PHY_IOC_REG0, 0, (1 << 14));
modifyreg32(MPFS_IOSCB_CALIB_DDR_IOC_REG0, 0, (1 << 14));
return 0;
}
/****************************************************************************
* Name: mpfs_ddr_pll_config
*
* Description:
* Configure DDR PLL according to a set of predefined values.
*
****************************************************************************/
static void mpfs_ddr_pll_config(void)
{
putreg32(PLL_INIT_AND_OUT_OF_RESET, MPFS_IOSCB_DDR_PLL_SOFT_RESET);
putreg32(LIBERO_SETTING_DDR_PLL_CTRL &
~(PLL_CTRL_REG_POWERDOWN_B_MASK), MPFS_IOSCB_DDR_PLL_CTRL);
putreg32(LIBERO_SETTING_DDR_PLL_REF_FB, MPFS_IOSCB_DDR_PLL_REF_FB);
putreg32(LIBERO_SETTING_DDR_PLL_DIV_0_1, MPFS_IOSCB_DDR_PLL_DIV_0_1);
putreg32(LIBERO_SETTING_DDR_PLL_DIV_2_3, MPFS_IOSCB_DDR_PLL_DIV_2_3);
putreg32(LIBERO_SETTING_DDR_PLL_CTRL2, MPFS_IOSCB_DDR_PLL_CTRL2);
putreg32(LIBERO_SETTING_DDR_PLL_FRACN, MPFS_IOSCB_DDR_PLL_FRACN);
putreg32(LIBERO_SETTING_DDR_SSCG_REG_0, MPFS_IOSCB_DDR_PLL_SSCG_REG_0);
putreg32(LIBERO_SETTING_DDR_SSCG_REG_1, MPFS_IOSCB_DDR_PLL_SSCG_REG_1);
putreg32(LIBERO_SETTING_DDR_SSCG_REG_2, MPFS_IOSCB_DDR_PLL_SSCG_REG_2);
putreg32(LIBERO_SETTING_DDR_SSCG_REG_3, MPFS_IOSCB_DDR_PLL_SSCG_REG_3);
putreg32(LIBERO_SETTING_DDR_PLL_PHADJ, MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32(LIBERO_SETTING_DDR_PLL_CTRL | 1, MPFS_IOSCB_DDR_PLL_CTRL);
}
/****************************************************************************
* Name: mpfs_ddr_pll_lock_scb
*
* Description:
* Check whether the DDR PLL has locked.
*
* Returned Value:
* 0 if PLL has locked, 1 otherwise.
*
****************************************************************************/
static int mpfs_ddr_pll_lock_scb(void)
{
if (getreg32(MPFS_IOSCB_DDR_PLL_CTRL) & PLL_CTRL_LOCK_BIT)
{
/* PLL has locked */
return 0;
}
return 1;
}
#define INIT_SETTING_SEG0_0 0x00007F80
#define INIT_SETTING_SEG0_1 0x00007000
#define INIT_SETTING_SEG0_2 0x00000000
#define INIT_SETTING_SEG0_3 0x00000000
#define INIT_SETTING_SEG0_4 0x00000000
#define INIT_SETTING_SEG0_5 0x00000000
#define INIT_SETTING_SEG0_6 0x00000000
#define INIT_SETTING_SEG0_7 0x00000000
#define INIT_SETTING_SEG1_0 0x00000000
#define INIT_SETTING_SEG1_1 0x00000000
#define INIT_SETTING_SEG1_2 0x00007F40
#define INIT_SETTING_SEG1_3 0x00006C00
#define INIT_SETTING_SEG1_4 0x00007F30
#define INIT_SETTING_SEG1_5 0x00006800
#define INIT_SETTING_SEG1_6 0x00000000
#define INIT_SETTING_SEG1_7 0x00000000
/****************************************************************************
* Name: mpfs_setup_ddr_segments
*
* Description:
* Sets up the MPU configurations properly.
*
* Input Parameters:
* option - Default setup, or values from the Libero tool.
*
****************************************************************************/
void mpfs_setup_ddr_segments(enum seg_setup_e option)
{
uint32_t val_l;
uint32_t val_h;
if (option == DEFAULT_SEG_SETUP)
{
/* Segment 0 */
val_l = INIT_SETTING_SEG0_0 & 0x7fff;
val_h = INIT_SETTING_SEG0_1 & 0x7fff;
putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG0_REG0);
/* Segment 1 */
val_l = INIT_SETTING_SEG1_2 & 0x7fff;
val_h = INIT_SETTING_SEG1_3 & 0x7fff;
putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG1_REG1);
val_l = INIT_SETTING_SEG1_4 & 0x7fff;
val_h = INIT_SETTING_SEG1_5 & 0x7fff;
putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG1_REG2);
}
else
{
/* Segment 0 */
val_l = LIBERO_SETTING_SEG0_0 & 0x7fff;
val_h = LIBERO_SETTING_SEG0_1 & 0x7fff;
putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG0_REG0);
/* Segment 1 */
val_l = LIBERO_SETTING_SEG1_2 & 0x7fff;
val_h = LIBERO_SETTING_SEG1_3 & 0x7fff;
putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG1_REG1);
val_l = LIBERO_SETTING_SEG1_4 & 0x7fff;
val_h = LIBERO_SETTING_SEG1_5 & 0x7fff;
putreg64((((uint64_t)val_h) << 32) | val_l, MPFS_MPUCFG_SEG1_REG2);
}
/* Disable ddr blocker: cleared at reset. When written to '1' disables
* the blocker function allowing the L2 cache controller to access the
* DDRC. Once written to '1' the register cannot be written to 0, only
* an devie reset will clear the register.
*/
putreg64((((uint64_t)0x01) << 32) , MPFS_MPUCFG_SEG0_REG3);
}
/****************************************************************************
* Name: mpfs_init_ddrc
*
* Description:
* Assigns value constants provided by the Libero tool and the
* manufacturer. This writes good known values into all DDR RW registers.
*
****************************************************************************/
static void mpfs_init_ddrc(void)
{
/* Turn on DDRC clock */
modifyreg32(MPFS_SYSREG_SUBBLK_CLOCK_CR, 0,
SYSREG_SUBBLK_CLOCK_CR_DDRC);
/* Remove soft reset */
modifyreg32(MPFS_SYSREG_SOFT_RESET_CR, 0,
SYSREG_SUBBLK_CLOCK_CR_DDRC);
modifyreg32(MPFS_SYSREG_SOFT_RESET_CR,
SYSREG_SUBBLK_CLOCK_CR_DDRC, 0);
putreg32(LIBERO_SETTING_CFG_MANUAL_ADDRESS_MAP,
MPFS_DDR_CSR_APB_CFG_MANUAL_ADDRESS_MAP);
putreg32(LIBERO_SETTING_CFG_CHIPADDR_MAP,
MPFS_DDR_CSR_APB_CFG_CHIPADDR_MAP);
putreg32(LIBERO_SETTING_CFG_CIDADDR_MAP,
MPFS_DDR_CSR_APB_CFG_CIDADDR_MAP);
putreg32(LIBERO_SETTING_CFG_MB_AUTOPCH_COL_BIT_POS_LOW,
MPFS_DDR_CSR_APB_CFG_MB_AUTOPCH_COL_BIT_POS_LOW);
putreg32(LIBERO_SETTING_CFG_MB_AUTOPCH_COL_BIT_POS_HIGH,
MPFS_DDR_CSR_APB_CFG_MB_AUTOPCH_COL_BIT_POS_HIGH);
putreg32(LIBERO_SETTING_CFG_BANKADDR_MAP_0,
MPFS_DDR_CSR_APB_CFG_BANKADDR_MAP_0);
putreg32(LIBERO_SETTING_CFG_BANKADDR_MAP_1,
MPFS_DDR_CSR_APB_CFG_BANKADDR_MAP_1);
putreg32(LIBERO_SETTING_CFG_ROWADDR_MAP_0,
MPFS_DDR_CSR_APB_CFG_ROWADDR_MAP_0);
putreg32(LIBERO_SETTING_CFG_ROWADDR_MAP_1,
MPFS_DDR_CSR_APB_CFG_ROWADDR_MAP_1);
putreg32(LIBERO_SETTING_CFG_ROWADDR_MAP_2,
MPFS_DDR_CSR_APB_CFG_ROWADDR_MAP_2);
putreg32(LIBERO_SETTING_CFG_ROWADDR_MAP_3,
MPFS_DDR_CSR_APB_CFG_ROWADDR_MAP_3);
putreg32(LIBERO_SETTING_CFG_COLADDR_MAP_0,
MPFS_DDR_CSR_APB_CFG_COLADDR_MAP_0);
putreg32(LIBERO_SETTING_CFG_COLADDR_MAP_1,
MPFS_DDR_CSR_APB_CFG_COLADDR_MAP_1);
putreg32(LIBERO_SETTING_CFG_COLADDR_MAP_2,
MPFS_DDR_CSR_APB_CFG_COLADDR_MAP_2);
putreg32(LIBERO_SETTING_CFG_VRCG_ENABLE,
MPFS_DDR_CSR_APB_CFG_VRCG_ENABLE);
putreg32(LIBERO_SETTING_CFG_VRCG_DISABLE,
MPFS_DDR_CSR_APB_CFG_VRCG_DISABLE);
putreg32(LIBERO_SETTING_CFG_WRITE_LATENCY_SET,
MPFS_DDR_CSR_APB_CFG_WRITE_LATENCY_SET);
putreg32(LIBERO_SETTING_CFG_THERMAL_OFFSET,
MPFS_DDR_CSR_APB_CFG_THERMAL_OFFSET);
putreg32(LIBERO_SETTING_CFG_SOC_ODT,
MPFS_DDR_CSR_APB_CFG_SOC_ODT);
putreg32(LIBERO_SETTING_CFG_ODTE_CK,
MPFS_DDR_CSR_APB_CFG_ODTE_CK);
putreg32(LIBERO_SETTING_CFG_ODTE_CS,
MPFS_DDR_CSR_APB_CFG_ODTE_CS);
putreg32(LIBERO_SETTING_CFG_ODTD_CA,
MPFS_DDR_CSR_APB_CFG_ODTD_CA);
putreg32(LIBERO_SETTING_CFG_LPDDR4_FSP_OP,
MPFS_DDR_CSR_APB_CFG_LPDDR4_FSP_OP);
putreg32(LIBERO_SETTING_CFG_GENERATE_REFRESH_ON_SRX,
MPFS_DDR_CSR_APB_CFG_GENERATE_REFRESH_ON_SRX);
putreg32(LIBERO_SETTING_CFG_DBI_CL,
MPFS_DDR_CSR_APB_CFG_DBI_CL);
putreg32(LIBERO_SETTING_CFG_NON_DBI_CL,
MPFS_DDR_CSR_APB_CFG_NON_DBI_CL);
putreg32(LIBERO_SETTING_INIT_FORCE_WRITE_DATA_0,
MPFS_DDR_CSR_APB_INIT_FORCE_WRITE_DATA_0);
putreg32(LIBERO_SETTING_CFG_WRITE_CRC,
MPFS_DDR_CSR_APB_CFG_WRITE_CRC);
putreg32(LIBERO_SETTING_CFG_MPR_READ_FORMAT,
MPFS_DDR_CSR_APB_CFG_MPR_READ_FORMAT);
putreg32(LIBERO_SETTING_CFG_WR_CMD_LAT_CRC_DM,
MPFS_DDR_CSR_APB_CFG_WR_CMD_LAT_CRC_DM);
putreg32(LIBERO_SETTING_CFG_FINE_GRAN_REF_MODE,
MPFS_DDR_CSR_APB_CFG_FINE_GRAN_REF_MODE);
putreg32(LIBERO_SETTING_CFG_TEMP_SENSOR_READOUT,
MPFS_DDR_CSR_APB_CFG_TEMP_SENSOR_READOUT);
putreg32(LIBERO_SETTING_CFG_PER_DRAM_ADDR_EN,
MPFS_DDR_CSR_APB_CFG_PER_DRAM_ADDR_EN);
putreg32(LIBERO_SETTING_CFG_GEARDOWN_MODE,
MPFS_DDR_CSR_APB_CFG_GEARDOWN_MODE);
putreg32(LIBERO_SETTING_CFG_WR_PREAMBLE,
MPFS_DDR_CSR_APB_CFG_WR_PREAMBLE);
putreg32(LIBERO_SETTING_CFG_RD_PREAMBLE,
MPFS_DDR_CSR_APB_CFG_RD_PREAMBLE);
putreg32(LIBERO_SETTING_CFG_RD_PREAMB_TRN_MODE,
MPFS_DDR_CSR_APB_CFG_RD_PREAMB_TRN_MODE);
putreg32(LIBERO_SETTING_CFG_SR_ABORT,
MPFS_DDR_CSR_APB_CFG_SR_ABORT);
putreg32(LIBERO_SETTING_CFG_CS_TO_CMDADDR_LATENCY,
MPFS_DDR_CSR_APB_CFG_CS_TO_CMDADDR_LATENCY);
putreg32(LIBERO_SETTING_CFG_INT_VREF_MON,
MPFS_DDR_CSR_APB_CFG_INT_VREF_MON);
putreg32(LIBERO_SETTING_CFG_TEMP_CTRL_REF_MODE,
MPFS_DDR_CSR_APB_CFG_TEMP_CTRL_REF_MODE);
putreg32(LIBERO_SETTING_CFG_TEMP_CTRL_REF_RANGE,
MPFS_DDR_CSR_APB_CFG_TEMP_CTRL_REF_RANGE);
putreg32(LIBERO_SETTING_CFG_MAX_PWR_DOWN_MODE,
MPFS_DDR_CSR_APB_CFG_MAX_PWR_DOWN_MODE);
putreg32(LIBERO_SETTING_CFG_READ_DBI,
MPFS_DDR_CSR_APB_CFG_READ_DBI);
putreg32(LIBERO_SETTING_CFG_WRITE_DBI,
MPFS_DDR_CSR_APB_CFG_WRITE_DBI);
putreg32(LIBERO_SETTING_CFG_DATA_MASK,
MPFS_DDR_CSR_APB_CFG_DATA_MASK);
putreg32(LIBERO_SETTING_CFG_CA_PARITY_PERSIST_ERR,
MPFS_DDR_CSR_APB_CFG_CA_PARITY_PERSIST_ERR);
putreg32(LIBERO_SETTING_CFG_RTT_PARK,
MPFS_DDR_CSR_APB_CFG_RTT_PARK);
putreg32(LIBERO_SETTING_CFG_ODT_INBUF_4_PD,
MPFS_DDR_CSR_APB_CFG_ODT_INBUF_4_PD);
putreg32(LIBERO_SETTING_CFG_CA_PARITY_ERR_STATUS,
MPFS_DDR_CSR_APB_CFG_CA_PARITY_ERR_STATUS);
putreg32(LIBERO_SETTING_CFG_CRC_ERROR_CLEAR,
MPFS_DDR_CSR_APB_CFG_CRC_ERROR_CLEAR);
putreg32(LIBERO_SETTING_CFG_CA_PARITY_LATENCY,
MPFS_DDR_CSR_APB_CFG_CA_PARITY_LATENCY);
putreg32(LIBERO_SETTING_CFG_CCD_S,
MPFS_DDR_CSR_APB_CFG_CCD_S);
putreg32(LIBERO_SETTING_CFG_CCD_L,
MPFS_DDR_CSR_APB_CFG_CCD_L);
putreg32(LIBERO_SETTING_CFG_VREFDQ_TRN_ENABLE,
MPFS_DDR_CSR_APB_CFG_VREFDQ_TRN_ENABLE);
putreg32(LIBERO_SETTING_CFG_VREFDQ_TRN_RANGE,
MPFS_DDR_CSR_APB_CFG_VREFDQ_TRN_RANGE);
putreg32(LIBERO_SETTING_CFG_VREFDQ_TRN_VALUE,
MPFS_DDR_CSR_APB_CFG_VREFDQ_TRN_VALUE);
putreg32(LIBERO_SETTING_CFG_RRD_S, MPFS_DDR_CSR_APB_CFG_RRD_S);
putreg32(LIBERO_SETTING_CFG_RRD_L, MPFS_DDR_CSR_APB_CFG_RRD_L);
putreg32(LIBERO_SETTING_CFG_WTR_S, MPFS_DDR_CSR_APB_CFG_WTR_S);
putreg32(LIBERO_SETTING_CFG_WTR_L, MPFS_DDR_CSR_APB_CFG_WTR_L);
putreg32(LIBERO_SETTING_CFG_WTR_S_CRC_DM,
MPFS_DDR_CSR_APB_CFG_WTR_S_CRC_DM);
putreg32(LIBERO_SETTING_CFG_WTR_L_CRC_DM,
MPFS_DDR_CSR_APB_CFG_WTR_L_CRC_DM);
putreg32(LIBERO_SETTING_CFG_WR_CRC_DM, MPFS_DDR_CSR_APB_CFG_WR_CRC_DM);
putreg32(LIBERO_SETTING_CFG_RFC1, MPFS_DDR_CSR_APB_CFG_RFC1);
putreg32(LIBERO_SETTING_CFG_RFC2, MPFS_DDR_CSR_APB_CFG_RFC2);
putreg32(LIBERO_SETTING_CFG_RFC4, MPFS_DDR_CSR_APB_CFG_RFC4);
putreg32(LIBERO_SETTING_CFG_NIBBLE_DEVICES,
MPFS_DDR_CSR_APB_CFG_NIBBLE_DEVICES);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS0_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS0_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS0_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS0_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS1_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS1_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS1_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS1_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS2_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS2_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS2_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS2_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS3_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS3_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS3_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS3_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS4_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS4_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS4_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS4_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS5_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS5_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS5_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS5_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS6_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS6_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS6_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS6_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS7_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS7_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS7_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS7_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS8_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS8_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS8_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS8_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS9_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS9_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS9_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS9_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS10_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS10_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS10_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS10_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS11_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS11_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS11_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS11_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS12_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS12_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS12_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS12_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS13_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS13_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS13_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS13_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS14_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS14_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS14_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS14_1);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS15_0,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS15_0);
putreg32(LIBERO_SETTING_CFG_BIT_MAP_INDEX_CS15_1,
MPFS_DDR_CSR_APB_CFG_BIT_MAP_INDEX_CS15_1);
putreg32(LIBERO_SETTING_CFG_NUM_LOGICAL_RANKS_PER_3DS,
MPFS_DDR_CSR_APB_CFG_NUM_LOGICAL_RANKS_PER_3DS);
putreg32(LIBERO_SETTING_CFG_RFC_DLR1, MPFS_DDR_CSR_APB_CFG_RFC_DLR1);
putreg32(LIBERO_SETTING_CFG_RFC_DLR2, MPFS_DDR_CSR_APB_CFG_RFC_DLR2);
putreg32(LIBERO_SETTING_CFG_RFC_DLR4, MPFS_DDR_CSR_APB_CFG_RFC_DLR4);
putreg32(LIBERO_SETTING_CFG_RRD_DLR, MPFS_DDR_CSR_APB_CFG_RRD_DLR);
putreg32(LIBERO_SETTING_CFG_FAW_DLR, MPFS_DDR_CSR_APB_CFG_FAW_DLR);
putreg32(LIBERO_SETTING_CFG_ADVANCE_ACTIVATE_READY,
MPFS_DDR_CSR_APB_CFG_ADVANCE_ACTIVATE_READY);
putreg32(LIBERO_SETTING_CTRLR_SOFT_RESET_N,
MPFS_DDR_CSR_APB_CTRLR_SOFT_RESET_N);
putreg32(LIBERO_SETTING_CFG_LOOKAHEAD_PCH,
MPFS_DDR_CSR_APB_CFG_LOOKAHEAD_PCH);
putreg32(LIBERO_SETTING_CFG_LOOKAHEAD_ACT,
MPFS_DDR_CSR_APB_CFG_LOOKAHEAD_ACT);
putreg32(LIBERO_SETTING_INIT_AUTOINIT_DISABLE,
MPFS_DDR_CSR_APB_INIT_AUTOINIT_DISABLE);
putreg32(LIBERO_SETTING_INIT_FORCE_RESET,
MPFS_DDR_CSR_APB_INIT_FORCE_RESET);
putreg32(LIBERO_SETTING_INIT_GEARDOWN_EN,
MPFS_DDR_CSR_APB_INIT_GEARDOWN_EN);
putreg32(LIBERO_SETTING_INIT_DISABLE_CKE,
MPFS_DDR_CSR_APB_INIT_DISABLE_CKE);
putreg32(LIBERO_SETTING_INIT_CS,
MPFS_DDR_CSR_APB_INIT_CS);
putreg32(LIBERO_SETTING_INIT_PRECHARGE_ALL,
MPFS_DDR_CSR_APB_INIT_PRECHARGE_ALL);
putreg32(LIBERO_SETTING_INIT_REFRESH, MPFS_DDR_CSR_APB_INIT_REFRESH);
putreg32(LIBERO_SETTING_INIT_ZQ_CAL_REQ, MPFS_DDR_CSR_APB_INIT_ZQ_CAL_REQ);
putreg32(LIBERO_SETTING_CFG_BL, MPFS_DDR_CSR_APB_CFG_BL);
putreg32(LIBERO_SETTING_CTRLR_INIT, MPFS_DDR_CSR_APB_CTRLR_INIT);
putreg32(LIBERO_SETTING_CFG_AUTO_REF_EN, MPFS_DDR_CSR_APB_CFG_AUTO_REF_EN);
putreg32(LIBERO_SETTING_CFG_RAS, MPFS_DDR_CSR_APB_CFG_RAS);
putreg32(LIBERO_SETTING_CFG_RCD, MPFS_DDR_CSR_APB_CFG_RCD);
putreg32(LIBERO_SETTING_CFG_RRD, MPFS_DDR_CSR_APB_CFG_RRD);
putreg32(LIBERO_SETTING_CFG_RP, MPFS_DDR_CSR_APB_CFG_RP);
putreg32(LIBERO_SETTING_CFG_RC, MPFS_DDR_CSR_APB_CFG_RC);
putreg32(LIBERO_SETTING_CFG_FAW, MPFS_DDR_CSR_APB_CFG_FAW);
putreg32(LIBERO_SETTING_CFG_RFC, MPFS_DDR_CSR_APB_CFG_RFC);
putreg32(LIBERO_SETTING_CFG_RTP, MPFS_DDR_CSR_APB_CFG_RTP);
putreg32(LIBERO_SETTING_CFG_WR, MPFS_DDR_CSR_APB_CFG_WR);
putreg32(LIBERO_SETTING_CFG_WTR, MPFS_DDR_CSR_APB_CFG_WTR);
putreg32(LIBERO_SETTING_CFG_PASR, MPFS_DDR_CSR_APB_CFG_PASR);
putreg32(LIBERO_SETTING_CFG_XP, MPFS_DDR_CSR_APB_CFG_XP);
putreg32(LIBERO_SETTING_CFG_XSR, MPFS_DDR_CSR_APB_CFG_XSR);
putreg32(LIBERO_SETTING_CFG_CL, MPFS_DDR_CSR_APB_CFG_CL);
putreg32(LIBERO_SETTING_CFG_READ_TO_WRITE,
MPFS_DDR_CSR_APB_CFG_READ_TO_WRITE);
putreg32(LIBERO_SETTING_CFG_WRITE_TO_WRITE,
MPFS_DDR_CSR_APB_CFG_WRITE_TO_WRITE);
putreg32(LIBERO_SETTING_CFG_WRITE_TO_WRITE,
MPFS_DDR_CSR_APB_CFG_READ_TO_READ);
putreg32(LIBERO_SETTING_CFG_WRITE_TO_WRITE,
MPFS_DDR_CSR_APB_CFG_WRITE_TO_READ);
putreg32(LIBERO_SETTING_CFG_READ_TO_WRITE_ODT,
MPFS_DDR_CSR_APB_CFG_READ_TO_WRITE_ODT);
putreg32(LIBERO_SETTING_CFG_WRITE_TO_WRITE_ODT,
MPFS_DDR_CSR_APB_CFG_WRITE_TO_WRITE_ODT);
putreg32(LIBERO_SETTING_CFG_READ_TO_READ_ODT,
MPFS_DDR_CSR_APB_CFG_READ_TO_READ_ODT);
putreg32(LIBERO_SETTING_CFG_WRITE_TO_READ_ODT,
MPFS_DDR_CSR_APB_CFG_WRITE_TO_READ_ODT);
putreg32(LIBERO_SETTING_CFG_MIN_READ_IDLE,
MPFS_DDR_CSR_APB_CFG_MIN_READ_IDLE);
putreg32(LIBERO_SETTING_CFG_MRD, MPFS_DDR_CSR_APB_CFG_MRD);
putreg32(LIBERO_SETTING_CFG_BT, MPFS_DDR_CSR_APB_CFG_BT);
putreg32(LIBERO_SETTING_CFG_DS, MPFS_DDR_CSR_APB_CFG_DS);
putreg32(LIBERO_SETTING_CFG_QOFF, MPFS_DDR_CSR_APB_CFG_QOFF);
putreg32(LIBERO_SETTING_CFG_RTT, MPFS_DDR_CSR_APB_CFG_RTT);
putreg32(LIBERO_SETTING_CFG_DLL_DISABLE, MPFS_DDR_CSR_APB_CFG_DLL_DISABLE);
putreg32(LIBERO_SETTING_CFG_REF_PER, MPFS_DDR_CSR_APB_CFG_REF_PER);
putreg32(LIBERO_SETTING_CFG_STARTUP_DELAY,
MPFS_DDR_CSR_APB_CFG_STARTUP_DELAY);
putreg32(LIBERO_SETTING_CFG_MEM_COLBITS,
MPFS_DDR_CSR_APB_CFG_MEM_COLBITS);
putreg32(LIBERO_SETTING_CFG_MEM_ROWBITS,
MPFS_DDR_CSR_APB_CFG_MEM_ROWBITS);
putreg32(LIBERO_SETTING_CFG_MEM_BANKBITS,
MPFS_DDR_CSR_APB_CFG_MEM_BANKBITS);
putreg32(LIBERO_SETTING_CFG_ODT_RD_MAP_CS0,
MPFS_DDR_CSR_APB_CFG_ODT_RD_MAP_CS0);
putreg32(LIBERO_SETTING_CFG_ODT_RD_MAP_CS1,
MPFS_DDR_CSR_APB_CFG_ODT_RD_MAP_CS1);
putreg32(LIBERO_SETTING_CFG_ODT_RD_MAP_CS2,
MPFS_DDR_CSR_APB_CFG_ODT_RD_MAP_CS2);
putreg32(LIBERO_SETTING_CFG_ODT_RD_MAP_CS3,
MPFS_DDR_CSR_APB_CFG_ODT_RD_MAP_CS3);
putreg32(LIBERO_SETTING_CFG_ODT_RD_MAP_CS4,
MPFS_DDR_CSR_APB_CFG_ODT_RD_MAP_CS4);
putreg32(LIBERO_SETTING_CFG_ODT_RD_MAP_CS5,
MPFS_DDR_CSR_APB_CFG_ODT_RD_MAP_CS5);
putreg32(LIBERO_SETTING_CFG_ODT_RD_MAP_CS6,
MPFS_DDR_CSR_APB_CFG_ODT_RD_MAP_CS6);
putreg32(LIBERO_SETTING_CFG_ODT_RD_MAP_CS7,
MPFS_DDR_CSR_APB_CFG_ODT_RD_MAP_CS7);
putreg32(LIBERO_SETTING_CFG_ODT_WR_MAP_CS0,
MPFS_DDR_CSR_APB_CFG_ODT_WR_MAP_CS0);
putreg32(LIBERO_SETTING_CFG_ODT_WR_MAP_CS1,
MPFS_DDR_CSR_APB_CFG_ODT_WR_MAP_CS1);
putreg32(LIBERO_SETTING_CFG_ODT_WR_MAP_CS2,
MPFS_DDR_CSR_APB_CFG_ODT_WR_MAP_CS2);
putreg32(LIBERO_SETTING_CFG_ODT_WR_MAP_CS3,
MPFS_DDR_CSR_APB_CFG_ODT_WR_MAP_CS3);
putreg32(LIBERO_SETTING_CFG_ODT_WR_MAP_CS4,
MPFS_DDR_CSR_APB_CFG_ODT_WR_MAP_CS4);
putreg32(LIBERO_SETTING_CFG_ODT_WR_MAP_CS5,
MPFS_DDR_CSR_APB_CFG_ODT_WR_MAP_CS5);
putreg32(LIBERO_SETTING_CFG_ODT_WR_MAP_CS6,
MPFS_DDR_CSR_APB_CFG_ODT_WR_MAP_CS6);
putreg32(LIBERO_SETTING_CFG_ODT_WR_MAP_CS7,
MPFS_DDR_CSR_APB_CFG_ODT_WR_MAP_CS7);
putreg32(LIBERO_SETTING_CFG_ODT_RD_TURN_ON,
MPFS_DDR_CSR_APB_CFG_ODT_RD_TURN_ON);
putreg32(LIBERO_SETTING_CFG_ODT_WR_TURN_ON,
MPFS_DDR_CSR_APB_CFG_ODT_WR_TURN_ON);
putreg32(LIBERO_SETTING_CFG_ODT_RD_TURN_OFF,
MPFS_DDR_CSR_APB_CFG_ODT_RD_TURN_OFF);
putreg32(LIBERO_SETTING_CFG_ODT_WR_TURN_OFF,
MPFS_DDR_CSR_APB_CFG_ODT_WR_TURN_OFF);
putreg32(LIBERO_SETTING_CFG_EMR3, MPFS_DDR_CSR_APB_CFG_EMR3);
putreg32(LIBERO_SETTING_CFG_TWO_T, MPFS_DDR_CSR_APB_CFG_TWO_T);
putreg32(LIBERO_SETTING_CFG_TWO_T_SEL_CYCLE,
MPFS_DDR_CSR_APB_CFG_TWO_T_SEL_CYCLE);
putreg32(LIBERO_SETTING_CFG_REGDIMM, MPFS_DDR_CSR_APB_CFG_REGDIMM);
putreg32(LIBERO_SETTING_CFG_MOD, MPFS_DDR_CSR_APB_CFG_MOD);
putreg32(LIBERO_SETTING_CFG_XS, MPFS_DDR_CSR_APB_CFG_XS);
putreg32(LIBERO_SETTING_CFG_XSDLL, MPFS_DDR_CSR_APB_CFG_XSDLL);
putreg32(LIBERO_SETTING_CFG_XPR, MPFS_DDR_CSR_APB_CFG_XPR);
putreg32(LIBERO_SETTING_CFG_AL_MODE, MPFS_DDR_CSR_APB_CFG_AL_MODE);
putreg32(LIBERO_SETTING_CFG_CWL, MPFS_DDR_CSR_APB_CFG_CWL);
putreg32(LIBERO_SETTING_CFG_BL_MODE, MPFS_DDR_CSR_APB_CFG_BL_MODE);
putreg32(LIBERO_SETTING_CFG_TDQS, MPFS_DDR_CSR_APB_CFG_TDQS);
putreg32(LIBERO_SETTING_CFG_RTT_WR, MPFS_DDR_CSR_APB_CFG_RTT_WR);
putreg32(LIBERO_SETTING_CFG_LP_ASR, MPFS_DDR_CSR_APB_CFG_LP_ASR);
putreg32(LIBERO_SETTING_CFG_AUTO_SR, MPFS_DDR_CSR_APB_CFG_AUTO_SR);
putreg32(LIBERO_SETTING_CFG_SRT, MPFS_DDR_CSR_APB_CFG_SRT);
putreg32(LIBERO_SETTING_CFG_ADDR_MIRROR, MPFS_DDR_CSR_APB_CFG_ADDR_MIRROR);
putreg32(LIBERO_SETTING_CFG_ZQ_CAL_TYPE, MPFS_DDR_CSR_APB_CFG_ZQ_CAL_TYPE);
putreg32(LIBERO_SETTING_CFG_ZQ_CAL_PER, MPFS_DDR_CSR_APB_CFG_ZQ_CAL_PER);
putreg32(LIBERO_SETTING_CFG_AUTO_ZQ_CAL_EN,
MPFS_DDR_CSR_APB_CFG_AUTO_ZQ_CAL_EN);
putreg32(LIBERO_SETTING_CFG_MEMORY_TYPE, MPFS_DDR_CSR_APB_CFG_MEMORY_TYPE);
putreg32(LIBERO_SETTING_CFG_ONLY_SRANK_CMDS,
MPFS_DDR_CSR_APB_CFG_ONLY_SRANK_CMDS);
putreg32(LIBERO_SETTING_CFG_NUM_RANKS, MPFS_DDR_CSR_APB_CFG_NUM_RANKS);
putreg32(LIBERO_SETTING_CFG_QUAD_RANK, MPFS_DDR_CSR_APB_CFG_QUAD_RANK);
putreg32(LIBERO_SETTING_CFG_EARLY_RANK_TO_WR_START,
MPFS_DDR_CSR_APB_CFG_EARLY_RANK_TO_WR_START);
putreg32(LIBERO_SETTING_CFG_EARLY_RANK_TO_RD_START,
MPFS_DDR_CSR_APB_CFG_EARLY_RANK_TO_RD_START);
putreg32(LIBERO_SETTING_CFG_PASR_BANK, MPFS_DDR_CSR_APB_CFG_PASR_BANK);
putreg32(LIBERO_SETTING_CFG_PASR_SEG, MPFS_DDR_CSR_APB_CFG_PASR_SEG);
putreg32(LIBERO_SETTING_INIT_MRR_MODE, MPFS_DDR_CSR_APB_INIT_MRR_MODE);
putreg32(LIBERO_SETTING_INIT_MR_W_REQ, MPFS_DDR_CSR_APB_INIT_MR_W_REQ);
putreg32(LIBERO_SETTING_INIT_MR_ADDR, MPFS_DDR_CSR_APB_INIT_MR_ADDR);
putreg32(LIBERO_SETTING_INIT_MR_WR_DATA, MPFS_DDR_CSR_APB_INIT_MR_WR_DATA);
putreg32(LIBERO_SETTING_INIT_MR_WR_MASK, MPFS_DDR_CSR_APB_INIT_MR_WR_MASK);
putreg32(LIBERO_SETTING_INIT_NOP, MPFS_DDR_CSR_APB_INIT_NOP);
putreg32(LIBERO_SETTING_CFG_INIT_DURATION,
MPFS_DDR_CSR_APB_CFG_INIT_DURATION);
putreg32(LIBERO_SETTING_CFG_ZQINIT_CAL_DURATION,
MPFS_DDR_CSR_APB_CFG_ZQINIT_CAL_DURATION);
putreg32(LIBERO_SETTING_CFG_ZQ_CAL_L_DURATION,
MPFS_DDR_CSR_APB_CFG_ZQ_CAL_L_DURATION);
putreg32(LIBERO_SETTING_CFG_ZQ_CAL_S_DURATION,
MPFS_DDR_CSR_APB_CFG_ZQ_CAL_S_DURATION);
putreg32(LIBERO_SETTING_CFG_ZQ_CAL_R_DURATION,
MPFS_DDR_CSR_APB_CFG_ZQ_CAL_R_DURATION);
putreg32(LIBERO_SETTING_CFG_MRR, MPFS_DDR_CSR_APB_CFG_MRR);
putreg32(LIBERO_SETTING_CFG_MRW, MPFS_DDR_CSR_APB_CFG_MRW);
putreg32(LIBERO_SETTING_CFG_ODT_POWERDOWN,
MPFS_DDR_CSR_APB_CFG_ODT_POWERDOWN);
putreg32(LIBERO_SETTING_CFG_WL, MPFS_DDR_CSR_APB_CFG_WL);
putreg32(LIBERO_SETTING_CFG_RL, MPFS_DDR_CSR_APB_CFG_RL);
putreg32(LIBERO_SETTING_CFG_CAL_READ_PERIOD,
MPFS_DDR_CSR_APB_CFG_CAL_READ_PERIOD);
putreg32(LIBERO_SETTING_CFG_NUM_CAL_READS,
MPFS_DDR_CSR_APB_CFG_NUM_CAL_READS);
putreg32(LIBERO_SETTING_INIT_SELF_REFRESH,
MPFS_DDR_CSR_APB_INIT_SELF_REFRESH);
putreg32(LIBERO_SETTING_INIT_POWER_DOWN,
MPFS_DDR_CSR_APB_INIT_POWER_DOWN);
putreg32(LIBERO_SETTING_INIT_FORCE_WRITE,
MPFS_DDR_CSR_APB_INIT_FORCE_WRITE);
putreg32(LIBERO_SETTING_INIT_FORCE_WRITE_CS,
MPFS_DDR_CSR_APB_INIT_FORCE_WRITE_CS);
putreg32(LIBERO_SETTING_CFG_CTRLR_INIT_DISABLE,
MPFS_DDR_CSR_APB_CFG_CTRLR_INIT_DISABLE);
putreg32(LIBERO_SETTING_INIT_RDIMM_COMPLETE,
MPFS_DDR_CSR_APB_INIT_RDIMM_COMPLETE);
putreg32(LIBERO_SETTING_CFG_RDIMM_LAT,
MPFS_DDR_CSR_APB_CFG_RDIMM_LAT);
putreg32(LIBERO_SETTING_CFG_RDIMM_BSIDE_INVERT,
MPFS_DDR_CSR_APB_CFG_RDIMM_BSIDE_INVERT);
putreg32(LIBERO_SETTING_CFG_LRDIMM,
MPFS_DDR_CSR_APB_CFG_LRDIMM);
putreg32(LIBERO_SETTING_INIT_MEMORY_RESET_MASK,
MPFS_DDR_CSR_APB_INIT_MEMORY_RESET_MASK);
putreg32(LIBERO_SETTING_CFG_RD_PREAMB_TOGGLE,
MPFS_DDR_CSR_APB_CFG_RD_PREAMB_TOGGLE);
putreg32(LIBERO_SETTING_CFG_RD_POSTAMBLE,
MPFS_DDR_CSR_APB_CFG_RD_POSTAMBLE);
putreg32(LIBERO_SETTING_CFG_PU_CAL, MPFS_DDR_CSR_APB_CFG_PU_CAL);
putreg32(LIBERO_SETTING_CFG_DQ_ODT, MPFS_DDR_CSR_APB_CFG_DQ_ODT);
putreg32(LIBERO_SETTING_CFG_CA_ODT, MPFS_DDR_CSR_APB_CFG_CA_ODT);
putreg32(LIBERO_SETTING_CFG_ZQLATCH_DURATION,
MPFS_DDR_CSR_APB_CFG_ZQLATCH_DURATION);
putreg32(LIBERO_SETTING_INIT_CAL_SELECT,
MPFS_DDR_CSR_APB_INIT_CAL_SELECT);
putreg32(LIBERO_SETTING_INIT_CAL_L_R_REQ,
MPFS_DDR_CSR_APB_INIT_CAL_L_R_REQ);
putreg32(LIBERO_SETTING_INIT_CAL_L_B_SIZE,
MPFS_DDR_CSR_APB_INIT_CAL_L_B_SIZE);
putreg32(LIBERO_SETTING_INIT_RWFIFO, MPFS_DDR_CSR_APB_INIT_RWFIFO);
putreg32(LIBERO_SETTING_INIT_RD_DQCAL, MPFS_DDR_CSR_APB_INIT_RD_DQCAL);
putreg32(LIBERO_SETTING_INIT_START_DQSOSC,
MPFS_DDR_CSR_APB_INIT_START_DQSOSC);
putreg32(LIBERO_SETTING_INIT_STOP_DQSOSC,
MPFS_DDR_CSR_APB_INIT_STOP_DQSOSC);
putreg32(LIBERO_SETTING_INIT_ZQ_CAL_START,
MPFS_DDR_CSR_APB_INIT_ZQ_CAL_START);
putreg32(LIBERO_SETTING_CFG_WR_POSTAMBLE,
MPFS_DDR_CSR_APB_CFG_WR_POSTAMBLE);
putreg32(LIBERO_SETTING_INIT_CAL_L_ADDR_0,
MPFS_DDR_CSR_APB_INIT_CAL_L_ADDR_0);
putreg32(LIBERO_SETTING_INIT_CAL_L_ADDR_1,
MPFS_DDR_CSR_APB_INIT_CAL_L_ADDR_1);
putreg32(LIBERO_SETTING_CFG_CTRLUPD_TRIG,
MPFS_DDR_CSR_APB_CFG_CTRLUPD_TRIG);
putreg32(LIBERO_SETTING_CFG_CTRLUPD_START_DELAY,
MPFS_DDR_CSR_APB_CFG_CTRLUPD_START_DELAY);
putreg32(LIBERO_SETTING_CFG_DFI_T_CTRLUPD_MAX,
MPFS_DDR_CSR_APB_CFG_DFI_T_CTRLUPD_MAX);
putreg32(LIBERO_SETTING_CFG_CTRLR_BUSY_SEL,
MPFS_DDR_CSR_APB_CFG_CTRLR_BUSY_SEL);
putreg32(LIBERO_SETTING_CFG_CTRLR_BUSY_VALUE,
MPFS_DDR_CSR_APB_CFG_CTRLR_BUSY_VALUE);
putreg32(LIBERO_SETTING_CFG_CTRLR_BUSY_TURN_OFF_DELAY,
MPFS_DDR_CSR_APB_CFG_CTRLR_BUSY_TURN_OFF_DELAY);
putreg32(LIBERO_SETTING_CFG_CTRLR_BUSY_SLOW_RESTART_WIN,
MPFS_DDR_CSR_APB_CFG_CTRLR_BUSY_SLOW_RESTART_WINDOW);
putreg32(LIBERO_SETTING_CFG_CTRLR_BUSY_RESTART_HOLDOFF,
MPFS_DDR_CSR_APB_CFG_CTRLR_BUSY_RESTART_HOLDOFF);
putreg32(LIBERO_SETTING_CFG_PARITY_RDIMM_DELAY,
MPFS_DDR_CSR_APB_CFG_PARITY_RDIMM_DELAY);
putreg32(LIBERO_SETTING_CFG_CTRLR_BUSY_ENABLE,
MPFS_DDR_CSR_APB_CFG_CTRLR_BUSY_ENABLE);
putreg32(LIBERO_SETTING_CFG_ASYNC_ODT,
MPFS_DDR_CSR_APB_CFG_ASYNC_ODT);
putreg32(LIBERO_SETTING_CFG_ZQ_CAL_DURATION,
MPFS_DDR_CSR_APB_CFG_ZQ_CAL_DURATION);
putreg32(LIBERO_SETTING_CFG_MRRI, MPFS_DDR_CSR_APB_CFG_MRRI);
putreg32(LIBERO_SETTING_INIT_ODT_FORCE_EN,
MPFS_DDR_CSR_APB_INIT_ODT_FORCE_EN);
putreg32(LIBERO_SETTING_INIT_ODT_FORCE_RANK,
MPFS_DDR_CSR_APB_INIT_ODT_FORCE_RANK);
putreg32(LIBERO_SETTING_CFG_PHYUPD_ACK_DELAY,
MPFS_DDR_CSR_APB_CFG_PHYUPD_ACK_DELAY);
putreg32(LIBERO_SETTING_CFG_MIRROR_X16_BG0_BG1,
MPFS_DDR_CSR_APB_CFG_MIRROR_X16_BG0_BG1);
putreg32(LIBERO_SETTING_INIT_PDA_MR_W_REQ,
MPFS_DDR_CSR_APB_INIT_PDA_MR_W_REQ);
putreg32(LIBERO_SETTING_INIT_PDA_NIBBLE_SELECT,
MPFS_DDR_CSR_APB_INIT_PDA_NIBBLE_SELECT);
putreg32(LIBERO_SETTING_CFG_DRAM_CLK_DISABLE_IN_SELF_RFH,
MPFS_DDR_CSR_APB_CFG_DRAM_CLK_DISABLE_IN_SELF_REFRESH);
putreg32(LIBERO_SETTING_CFG_CKSRE, MPFS_DDR_CSR_APB_CFG_CKSRE);
putreg32(LIBERO_SETTING_CFG_CKSRX, MPFS_DDR_CSR_APB_CFG_CKSRX);
putreg32(LIBERO_SETTING_CFG_RCD_STAB, MPFS_DDR_CSR_APB_CFG_RCD_STAB);
putreg32(LIBERO_SETTING_CFG_DFI_T_CTRL_DELAY,
MPFS_DDR_CSR_APB_CFG_DFI_T_CTRL_DELAY);
putreg32(LIBERO_SETTING_CFG_DFI_T_DRAM_CLK_ENABLE,
MPFS_DDR_CSR_APB_CFG_DFI_T_DRAM_CLK_ENABLE);
putreg32(LIBERO_SETTING_CFG_IDLE_TIME_TO_SELF_REFRESH,
MPFS_DDR_CSR_APB_CFG_IDLE_TIME_TO_SELF_REFRESH);
putreg32(LIBERO_SETTING_CFG_IDLE_TIME_TO_POWER_DOWN,
MPFS_DDR_CSR_APB_CFG_IDLE_TIME_TO_POWER_DOWN);
putreg32(LIBERO_SETTING_CFG_BURST_RW_REFRESH_HOLDOFF,
MPFS_DDR_CSR_APB_CFG_BURST_RW_REFRESH_HOLDOFF);
putreg32(LIBERO_SETTING_CFG_BG_INTERLEAVE,
MPFS_DDR_CSR_APB_CFG_BG_INTERLEAVE);
putreg32(LIBERO_SETTING_CFG_REFRESH_DURING_PHY_TRAINING,
MPFS_DDR_CSR_APB_CFG_REFRESH_DURING_PHY_TRAINING);
putreg32(LIBERO_SETTING_CFG_STARVE_TIMEOUT_P0,
MPFS_DDR_CSR_APB_CFG_STARVE_TIMEOUT_P0);
putreg32(LIBERO_SETTING_CFG_STARVE_TIMEOUT_P1,
MPFS_DDR_CSR_APB_CFG_STARVE_TIMEOUT_P1);
putreg32(LIBERO_SETTING_CFG_STARVE_TIMEOUT_P2,
MPFS_DDR_CSR_APB_CFG_STARVE_TIMEOUT_P2);
putreg32(LIBERO_SETTING_CFG_STARVE_TIMEOUT_P3,
MPFS_DDR_CSR_APB_CFG_STARVE_TIMEOUT_P3);
putreg32(LIBERO_SETTING_CFG_STARVE_TIMEOUT_P4,
MPFS_DDR_CSR_APB_CFG_STARVE_TIMEOUT_P4);
putreg32(LIBERO_SETTING_CFG_STARVE_TIMEOUT_P5,
MPFS_DDR_CSR_APB_CFG_STARVE_TIMEOUT_P5);
putreg32(LIBERO_SETTING_CFG_STARVE_TIMEOUT_P6,
MPFS_DDR_CSR_APB_CFG_STARVE_TIMEOUT_P6);
putreg32(LIBERO_SETTING_CFG_STARVE_TIMEOUT_P7,
MPFS_DDR_CSR_APB_CFG_STARVE_TIMEOUT_P7);
putreg32(LIBERO_SETTING_CFG_REORDER_EN,
MPFS_DDR_CSR_APB_CFG_REORDER_EN);
putreg32(LIBERO_SETTING_CFG_REORDER_QUEUE_EN,
MPFS_DDR_CSR_APB_CFG_REORDER_QUEUE_EN);
putreg32(LIBERO_SETTING_CFG_INTRAPORT_REORDER_EN,
MPFS_DDR_CSR_APB_CFG_INTRAPORT_REORDER_EN);
putreg32(LIBERO_SETTING_CFG_INTRAPORT_REORDER_EN,
MPFS_DDR_CSR_APB_CFG_MAINTAIN_COHERENCY);
putreg32(LIBERO_SETTING_CFG_Q_AGE_LIMIT,
MPFS_DDR_CSR_APB_CFG_Q_AGE_LIMIT);
putreg32(LIBERO_SETTING_CFG_RO_CLOSED_PAGE_POLICY,
MPFS_DDR_CSR_APB_CFG_RO_CLOSED_PAGE_POLICY);
putreg32(LIBERO_SETTING_CFG_REORDER_RW_ONLY,
MPFS_DDR_CSR_APB_CFG_REORDER_RW_ONLY);
putreg32(LIBERO_SETTING_CFG_RO_PRIORITY_EN,
MPFS_DDR_CSR_APB_CFG_RO_PRIORITY_EN);
putreg32(LIBERO_SETTING_CFG_DM_EN, MPFS_DDR_CSR_APB_CFG_DM_EN);
putreg32(LIBERO_SETTING_CFG_RMW_EN, MPFS_DDR_CSR_APB_CFG_RMW_EN);
putreg32(LIBERO_SETTING_CFG_ECC_CORRECTION_EN,
MPFS_DDR_CSR_APB_CFG_ECC_CORRECTION_EN);
putreg32(LIBERO_SETTING_CFG_ECC_BYPASS,
MPFS_DDR_CSR_APB_CFG_ECC_BYPASS);
putreg32(LIBERO_SETTING_INIT_WRITE_DATA_1B_ECC_ERROR_GEN,
MPFS_DDR_CSR_APB_INIT_WRITE_DATA_1B_ECC_ERROR_GEN);
putreg32(LIBERO_SETTING_INIT_WRITE_DATA_2B_ECC_ERROR_GEN,
MPFS_DDR_CSR_APB_INIT_WRITE_DATA_2B_ECC_ERROR_GEN);
putreg32(LIBERO_SETTING_CFG_ECC_1BIT_INT_THRESH,
MPFS_DDR_CSR_APB_CFG_ECC_1BIT_INT_THRESH);
putreg32(LIBERO_SETTING_INIT_READ_CAPTURE_ADDR,
MPFS_DDR_CSR_APB_INIT_READ_CAPTURE_ADDR);
putreg32(LIBERO_SETTING_CFG_ERROR_GROUP_SEL,
MPFS_DDR_CSR_APB_CFG_ERROR_GROUP_SEL);
putreg32(LIBERO_SETTING_CFG_DATA_SEL,
MPFS_DDR_CSR_APB_CFG_DATA_SEL);
putreg32(LIBERO_SETTING_CFG_TRIG_MODE,
MPFS_DDR_CSR_APB_CFG_TRIG_MODE);
putreg32(LIBERO_SETTING_CFG_POST_TRIG_CYCS,
MPFS_DDR_CSR_APB_CFG_POST_TRIG_CYCS);
putreg32(LIBERO_SETTING_CFG_TRIG_MASK,
MPFS_DDR_CSR_APB_CFG_TRIG_MASK);
putreg32(LIBERO_SETTING_CFG_EN_MASK,
MPFS_DDR_CSR_APB_CFG_EN_MASK);
putreg32(LIBERO_SETTING_MTC_ACQ_ADDR, MPFS_DDR_CSR_APB_MTC_ACQ_ADDR);
putreg32(LIBERO_SETTING_CFG_TRIG_MT_ADDR_0,
MPFS_DDR_CSR_APB_CFG_TRIG_MT_ADDR_0);
putreg32(LIBERO_SETTING_CFG_TRIG_MT_ADDR_1,
MPFS_DDR_CSR_APB_CFG_TRIG_MT_ADDR_1);
putreg32(LIBERO_SETTING_CFG_TRIG_ERR_MASK_0,
MPFS_DDR_CSR_APB_MT_ERROR_MASK_0);
putreg32(LIBERO_SETTING_CFG_TRIG_ERR_MASK_1,
MPFS_DDR_CSR_APB_MT_ERROR_MASK_1);
putreg32(LIBERO_SETTING_CFG_TRIG_ERR_MASK_2,
MPFS_DDR_CSR_APB_MT_ERROR_MASK_2);
putreg32(LIBERO_SETTING_CFG_TRIG_ERR_MASK_3,
MPFS_DDR_CSR_APB_MT_ERROR_MASK_3);
putreg32(LIBERO_SETTING_CFG_TRIG_ERR_MASK_4,
MPFS_DDR_CSR_APB_MT_ERROR_MASK_4);
putreg32(LIBERO_SETTING_MTC_ACQ_WR_DATA_0,
MPFS_DDR_CSR_APB_MTC_ACQ_WR_DATA_0);
putreg32(LIBERO_SETTING_MTC_ACQ_WR_DATA_1,
MPFS_DDR_CSR_APB_MTC_ACQ_WR_DATA_1);
putreg32(LIBERO_SETTING_MTC_ACQ_WR_DATA_2,
MPFS_DDR_CSR_APB_MTC_ACQ_WR_DATA_2);
putreg32(LIBERO_SETTING_CFG_PRE_TRIG_CYCS,
MPFS_DDR_CSR_APB_CFG_PRE_TRIG_CYCS);
putreg32(LIBERO_SETTING_CFG_DATA_SEL_FIRST_ERROR,
MPFS_DDR_CSR_APB_CFG_DATA_SEL_FIRST_ERROR);
putreg32(LIBERO_SETTING_CFG_DQ_WIDTH, MPFS_DDR_CSR_APB_CFG_DQ_WIDTH);
putreg32(LIBERO_SETTING_CFG_ACTIVE_DQ_SEL,
MPFS_DDR_CSR_APB_CFG_ACTIVE_DQ_SEL);
putreg32(LIBERO_SETTING_INIT_CA_PARITY_ERROR_GEN_REQ,
MPFS_DDR_CSR_APB_INIT_CA_PARITY_ERROR_GEN_REQ);
putreg32(LIBERO_SETTING_INIT_CA_PARITY_ERROR_GEN_CMD,
MPFS_DDR_CSR_APB_INIT_CA_PARITY_ERROR_GEN_CMD);
putreg32(LIBERO_SETTING_CFG_DFI_T_RDDATA_EN,
MPFS_DDR_CSR_APB_CFG_DFI_T_RDDATA_EN);
putreg32(LIBERO_SETTING_CFG_DFI_T_PHY_RDLAT,
MPFS_DDR_CSR_APB_CFG_DFI_T_PHY_RDLAT);
putreg32(LIBERO_SETTING_CFG_DFI_T_PHY_WRLAT,
MPFS_DDR_CSR_APB_CFG_DFI_T_PHY_WRLAT);
putreg32(LIBERO_SETTING_CFG_DFI_PHYUPD_EN,
MPFS_DDR_CSR_APB_CFG_DFI_PHYUPD_EN);
putreg32(LIBERO_SETTING_INIT_DFI_LP_DATA_REQ,
MPFS_DDR_CSR_APB_INIT_DFI_LP_DATA_REQ);
putreg32(LIBERO_SETTING_INIT_DFI_LP_CTRL_REQ,
MPFS_DDR_CSR_APB_INIT_DFI_LP_CTRL_REQ);
putreg32(LIBERO_SETTING_INIT_DFI_LP_WAKEUP,
MPFS_DDR_CSR_APB_INIT_DFI_LP_WAKEUP);
putreg32(LIBERO_SETTING_INIT_DFI_DRAM_CLK_DISABLE,
MPFS_DDR_CSR_APB_INIT_DFI_DRAM_CLK_DISABLE);
putreg32(LIBERO_SETTING_CFG_DFI_DATA_BYTE_DISABLE,
MPFS_DDR_CSR_APB_CFG_DFI_DATA_BYTE_DISABLE);
putreg32(LIBERO_SETTING_CFG_DFI_LVL_SEL,
MPFS_DDR_CSR_APB_CFG_DFI_LVL_SEL);
putreg32(LIBERO_SETTING_CFG_DFI_LVL_PERIODIC,
MPFS_DDR_CSR_APB_CFG_DFI_LVL_PERIODIC);
putreg32(LIBERO_SETTING_CFG_DFI_LVL_PATTERN,
MPFS_DDR_CSR_APB_CFG_DFI_LVL_PATTERN);
putreg32(LIBERO_SETTING_PHY_DFI_INIT_START,
MPFS_DDR_CSR_APB_PHY_DFI_INIT_START);
putreg32(LIBERO_SETTING_CFG_AXI_START_ADDRESS_AXI1_0,
MPFS_DDR_CSR_APB_CFG_AXI_START_ADDRESS_AXI1_0);
putreg32(LIBERO_SETTING_CFG_AXI_START_ADDRESS_AXI1_1,
MPFS_DDR_CSR_APB_CFG_AXI_START_ADDRESS_AXI1_1);
putreg32(LIBERO_SETTING_CFG_AXI_START_ADDRESS_AXI2_0,
MPFS_DDR_CSR_APB_CFG_AXI_START_ADDRESS_AXI2_0);
putreg32(LIBERO_SETTING_CFG_AXI_START_ADDRESS_AXI2_1,
MPFS_DDR_CSR_APB_CFG_AXI_START_ADDRESS_AXI2_1);
putreg32(LIBERO_SETTING_CFG_AXI_END_ADDRESS_AXI1_0,
MPFS_DDR_CSR_APB_CFG_AXI_END_ADDRESS_AXI1_0);
putreg32(LIBERO_SETTING_CFG_AXI_END_ADDRESS_AXI1_1,
MPFS_DDR_CSR_APB_CFG_AXI_END_ADDRESS_AXI1_1);
putreg32(LIBERO_SETTING_CFG_AXI_END_ADDRESS_AXI2_0,
MPFS_DDR_CSR_APB_CFG_AXI_END_ADDRESS_AXI2_0);
putreg32(LIBERO_SETTING_CFG_AXI_END_ADDRESS_AXI2_1,
MPFS_DDR_CSR_APB_CFG_AXI_END_ADDRESS_AXI2_1);
putreg32(LIBERO_SETTING_CFG_MEM_START_ADDRESS_AXI1_0,
MPFS_DDR_CSR_APB_CFG_MEM_START_ADDRESS_AXI1_0);
putreg32(LIBERO_SETTING_CFG_MEM_START_ADDRESS_AXI1_1,
MPFS_DDR_CSR_APB_CFG_MEM_START_ADDRESS_AXI1_1);
putreg32(LIBERO_SETTING_CFG_MEM_START_ADDRESS_AXI2_0,
MPFS_DDR_CSR_APB_CFG_MEM_START_ADDRESS_AXI2_0);
putreg32(LIBERO_SETTING_CFG_MEM_START_ADDRESS_AXI2_1,
MPFS_DDR_CSR_APB_CFG_MEM_START_ADDRESS_AXI2_1);
putreg32(LIBERO_SETTING_CFG_ENABLE_BUS_HOLD_AXI1,
MPFS_DDR_CSR_APB_CFG_ENABLE_BUS_HOLD_AXI1);
putreg32(LIBERO_SETTING_CFG_ENABLE_BUS_HOLD_AXI2,
MPFS_DDR_CSR_APB_CFG_ENABLE_BUS_HOLD_AXI2);
putreg32(LIBERO_SETTING_CFG_AXI_AUTO_PCH,
MPFS_DDR_CSR_APB_CFG_AXI_AUTO_PCH);
putreg32(LIBERO_SETTING_PHY_RESET_CONTROL,
MPFS_DDR_CSR_APB_PHY_RESET_CONTROL);
modifyreg32(MPFS_DDR_CSR_APB_PHY_RESET_CONTROL, 0x8000, 0);
putreg32(LIBERO_SETTING_PHY_PC_RANK, MPFS_DDR_CSR_APB_PHY_PC_RANK);
putreg32(LIBERO_SETTING_PHY_RANKS_TO_TRAIN,
MPFS_DDR_CSR_APB_PHY_RANKS_TO_TRAIN);
putreg32(LIBERO_SETTING_PHY_WRITE_REQUEST,
MPFS_DDR_CSR_APB_PHY_WRITE_REQUEST);
putreg32(LIBERO_SETTING_PHY_READ_REQUEST,
MPFS_DDR_CSR_APB_PHY_READ_REQUEST);
putreg32(LIBERO_SETTING_PHY_WRITE_LEVEL_DELAY,
MPFS_DDR_CSR_APB_PHY_WRITE_LEVEL_DELAY);
putreg32(LIBERO_SETTING_PHY_GATE_TRAIN_DELAY,
MPFS_DDR_CSR_APB_PHY_GATE_TRAIN_DELAY);
putreg32(LIBERO_SETTING_PHY_EYE_TRAIN_DELAY,
MPFS_DDR_CSR_APB_PHY_EYE_TRAIN_DELAY);
putreg32(LIBERO_SETTING_PHY_EYE_PAT,
MPFS_DDR_CSR_APB_PHY_EYE_PAT);
putreg32(LIBERO_SETTING_PHY_START_RECAL,
MPFS_DDR_CSR_APB_PHY_START_RECAL);
putreg32(LIBERO_SETTING_PHY_CLR_DFI_LVL_PERIODIC,
MPFS_DDR_CSR_APB_PHY_CLR_DFI_LVL_PERIODIC);
putreg32(LIBERO_SETTING_PHY_TRAIN_STEP_ENABLE,
MPFS_DDR_CSR_APB_PHY_TRAIN_STEP_ENABLE);
putreg32(LIBERO_SETTING_PHY_LPDDR_DQ_CAL_PAT,
MPFS_DDR_CSR_APB_PHY_LPDDR_DQ_CAL_PAT);
putreg32(LIBERO_SETTING_PHY_INDPNDT_TRAINING,
MPFS_DDR_CSR_APB_PHY_INDPNDT_TRAINING);
putreg32(LIBERO_SETTING_PHY_ENCODED_QUAD_CS,
MPFS_DDR_CSR_APB_PHY_ENCODED_QUAD_CS);
putreg32(LIBERO_SETTING_PHY_HALF_CLK_DLY_ENABLE,
MPFS_DDR_CSR_APB_PHY_HALF_CLK_DLY_ENABLE);
}
#ifdef CONFIG_MPFS_DDR_MANUAL_ADDCMD_TRAINING
/****************************************************************************
* Name: mpfs_ddr_manual_addcmd_refclk_offset
*
* Description:
* This function determines current sweep offset based on DDR type.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Sweep offset
*
****************************************************************************/
static uint8_t mpfs_ddr_manual_addcmd_refclk_offset(
struct mpfs_ddr_priv_s *priv)
{
uint8_t refclk_offset;
uint8_t type_array_index;
type_array_index = (uint8_t)CONFIG_MPFS_DDR_TYPE;
#if defined(CONFIG_MPFS_DDR_TYPE_DDR3) || defined(CONFIG_MPFS_DDR_TYPE_DDR3L)
if (LIBERO_SETTING_DDR_CLK + DDR_FREQ_MARGIN < DDR_1333_MHZ)
{
type_array_index = type_array_index + (uint8_t)LPDDR4 + 1;
}
#else
if (LIBERO_SETTING_DDR_CLK + DDR_FREQ_MARGIN < DDR_1600_MHZ)
{
type_array_index = type_array_index + (uint8_t)LPDDR4 + 1;
}
#endif
DEBUGASSERT(type_array_index < sizeof(refclk_offsets) /
sizeof(refclk_offsets[0]));
if (priv->refclk_sweep_index >= refclk_offsets[type_array_index][0])
{
priv->refclk_sweep_index = 0;
}
refclk_offset = refclk_offsets[type_array_index] \
[priv->refclk_sweep_index + 1];
priv->refclk_sweep_index = (priv->refclk_sweep_index + 1);
return refclk_offset;
}
#endif
/****************************************************************************
* Name: mpfs_get_num_lanes
*
* Description:
* This function returns the number of lanes present.
*
* Returned Value:
* Number of lanes
*
****************************************************************************/
static uint8_t mpfs_get_num_lanes(void)
{
uint8_t lanes;
/* Check width, 16-bit or 32-bit supported, 1 => 32-bit */
if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_BUS_WIDTH_MASK) ==
DDRPHY_MODE_BUS_WIDTH_4_LANE)
{
lanes = 4;
}
else
{
lanes = 2;
}
/* Check if using ECC, add a lane */
if ((LIBERO_SETTING_DDRPHY_MODE & DDRPHY_MODE_ECC_MASK) ==
DDRPHY_MODE_ECC_ON)
{
lanes++;
}
return lanes;
}
/****************************************************************************
* Name: mpfs_load_dq
*
* Description:
* This function loads the DQ for the corresponding lane.
*
* Input Parameters:
* lane - the lane number
*
****************************************************************************/
#ifdef CONFIG_MPFS_DDR_TYPE_LPDDR4
static void mpfs_load_dq(uint8_t lane)
{
if (lane < 4)
{
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG0);
}
else
{
modifyreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1, 0x0f, 0);
}
/* Set expert_dfi_status_override_to_shim = 0x7 */
putreg32(0x07, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DFI_STATUS_OVERRIDE);
putreg32(0x21, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
if (lane < 4)
{
putreg32(0xffu << (lane * 8),
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG0);
}
else
{
modifyreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1, 0, 0x0f);
}
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG0);
if (lane < 4)
{
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG0);
}
else
{
modifyreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1, 0x0f, 0);
}
}
#endif
/****************************************************************************
* Name: mpfs_mtc_test
*
* Description:
* This performs a memory test with the NWL memory test core.
*
* Input Parameters:
* mask - Test bitmask
* start_address - Test start address
* data_pattern - Data pattern for testing
* add_pattern - Data modifier pattern
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a fail.
*
****************************************************************************/
static int mpfs_mtc_test(uint8_t mask, uint64_t start_address,
uint32_t size,
enum mtc_pattern_e data_pattern,
enum mtc_add_pattern_e add_pattern)
{
/* Write calibration:
* Configure common memory test interface by writing registers:
* MT_STOP_ON_ERROR, MT_DATA_PATTERN, MT_ADDR_PATTERN, MT_ADDR_BITS
*/
putreg32(0, MPFS_DDR_CSR_APB_MT_STOP_ON_ERROR);
/* make sure off, will turn on later. */
putreg32(0, MPFS_DDR_CSR_APB_MT_EN_SINGLE);
/* MT_DATA_PATTERN:
*
* 0x00 => Counting pattern
* 0x01 => walking 1's
* 0x02 => pseudo mpfs_ddr_random
* 0x03 => no repeating pseudo mpfs_ddr_random
* 0x04 => alt 1's and 0's
* 0x05 => alt 5's and A's
* 0x06 => User specified
* 0x07 => pseudo mpfs_ddr_random 16-bit
* 0x08 => pseudo mpfs_ddr_random 8-bit
* 0x09- 0x0f reserved
*
*/
/* Added changing pattern so write pattern is different, read back
* cannot pass on previously written data.
*/
putreg32(data_pattern, MPFS_DDR_CSR_APB_MT_DATA_PATTERN);
if (add_pattern == MTC_ADD_RANDOM)
{
/* MT_ADDR_PATTERN
* 0x00 => Count in pattern
* 0x01 => Pseudo Random Pattern
* 0x02 => Arbiatry Pattern Gen (user defined ) - Using RAMS
*/
putreg32(1, MPFS_DDR_CSR_APB_MT_ADDR_PATTERN);
}
else
{
putreg32(0, MPFS_DDR_CSR_APB_MT_ADDR_PATTERN);
}
if (add_pattern != MTC_ADD_RANDOM)
{
/* Set the starting address and number to test
*
* MT_START_ADDR
* Starting address
* MT_ADRESS_BITS
* Length to test = 2 ** MT_ADRESS_BITS
*/
putreg32((uint32_t)(start_address & 0xffffffff),
MPFS_DDR_CSR_APB_MT_START_ADDR_0);
/* The address here is as see from DDR controller => start at 0x0 */
putreg32((uint32_t)(start_address >> 32),
MPFS_DDR_CSR_APB_MT_START_ADDR_1);
}
else
{
putreg32(0, MPFS_DDR_CSR_APB_MT_START_ADDR_0);
putreg32(0, MPFS_DDR_CSR_APB_MT_START_ADDR_1);
}
putreg32(size, MPFS_DDR_CSR_APB_MT_ADDR_BITS);
/* MT_ERROR_MASK:
* All bits set in this field mask corresponding bits in data fields
* i.e. mt_error and mt_error_hold will not be set for errors in
* those fields
*
* Structure of 144 bits same as DFI bus 36 bits per lane
* ( 8 physical * 4) + (1ECC * 4) = 36
*
* If we wrote out the following pattern from software:
* 0x12345678
* 0x87654321
* 0x56789876
* 0x43211234
* We should see:
* NNNN_YXXX_XXX3_4YXX_XXXX_76YX_XXXX_X21Y_XXXX_XX78
* N: not used
*/
putreg32(0xffffffff, MPFS_DDR_CSR_APB_MT_ERROR_MASK_0);
putreg32(0xffffffff, MPFS_DDR_CSR_APB_MT_ERROR_MASK_1);
putreg32(0xffffffff, MPFS_DDR_CSR_APB_MT_ERROR_MASK_2);
putreg32(0xffffffff, MPFS_DDR_CSR_APB_MT_ERROR_MASK_3);
putreg32(0xffffffff, MPFS_DDR_CSR_APB_MT_ERROR_MASK_4);
if (mask & 0x1)
{
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_0, 0x000000ff, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_1, 0x00000ff0, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_2, 0x0000ff00, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_3, 0x000ff000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_4, 0x00000000, 0);
}
if (mask & 0x2)
{
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_0, 0x0000ff00, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_1, 0x000ff000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_2, 0x00ff0000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_3, 0x0ff00000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_4, 0x00000000, 0);
}
if (mask & 0x4)
{
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_0, 0x00ff0000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_1, 0x0ff00000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_2, 0xff000000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_3, 0xf0000000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_4, 0x0000000f, 0);
}
if (mask & 0x8)
{
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_0, 0xff000000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_1, 0xf0000000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_2, 0x0000000f, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_3, 0x000000ff, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_4, 0x00000ff0, 0);
}
if (mask & 0x10)
{
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_0, 0x00000000, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_1, 0x0000000f, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_2, 0x000000f0, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_3, 0x00000f00, 0);
modifyreg32(MPFS_DDR_CSR_APB_MT_ERROR_MASK_4, 0x0000f000, 0);
}
/* MT_EN_SINGLE - Will not repeat if this is set */
putreg32(0, MPFS_DDR_CSR_APB_MT_EN_SINGLE);
putreg32(1, MPFS_DDR_CSR_APB_MT_EN_SINGLE);
/* MT_DONE_ACK - Set when test completes */
uint32_t retries = MPFS_LONG_RETRIES;
while (!(getreg32(MPFS_DDR_CSR_APB_MT_DONE_ACK) & 0x01) &&
--retries);
if (retries == 0)
{
merr("Timeout!\n");
return -ETIMEDOUT;
}
/* Return the error status */
return getreg32(MPFS_DDR_CSR_APB_MT_ERROR_STS) & 0x01;
}
/****************************************************************************
* Name: mpfs_mtc_test_all
*
* Description:
* This performs a memory test with the NWL memory test core
* using all available test patterns.
*
* Input Parameters:
* mask - Test bitmask
* start_address - Test start address
* size - Size of the area to test
* add_pattern - Data modifier pattern
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a fail.
*
****************************************************************************/
static int mpfs_mtc_test_all(uint8_t mask, uint64_t start_address,
uint32_t size,
enum mtc_add_pattern_e add_pattern)
{
int result;
enum mtc_pattern_e test_pattern;
/* Read once to flush MTC. During write calibration the first MTC
* read must be discarded as it is unreliable after a series of
* bad writes. Only check -ETIMEDOUT; if that occurs, we'll bail out
*/
result = mpfs_mtc_test(mask, start_address, size,
MTC_COUNTING_PATTERN,
add_pattern);
if (result == -ETIMEDOUT)
{
return result;
}
/* Test all patterns except MTC_USER */
result = 0;
for (test_pattern = MTC_COUNTING_PATTERN;
test_pattern <= MTC_PSEUDO_RANDOM_8BIT && result == 0;
test_pattern++)
{
if (test_pattern == MTC_USER)
{
continue;
}
/* Read using different patterns */
result = mpfs_mtc_test(mask, start_address, size,
test_pattern,
add_pattern);
}
return result;
}
/****************************************************************************
* Name: mpfs_write_calibration_using_mtc
*
* Description:
* Use Memory Test Core plugged in to the front end of the DDR controller
* to perform lane-based writes and read backs and increment write
* calibration offset for each lane until data match occurs. The Memory
* Test Core is the basis for all training.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a failure.
*
****************************************************************************/
static int mpfs_write_calibration_using_mtc(struct mpfs_ddr_priv_s *priv)
{
uint64_t start_address = 0x00;
uint32_t size = ONE_MB_MTC;
int result = 0;
uint8_t done = 0x0;
uint8_t lane;
uint32_t cal_data;
int lanes;
uint8_t offset[MAX_LANES];
uint8_t done_mask;
/* Initialize number of lanes */
lanes = priv->number_of_lanes_to_calibrate;
/* Bit 3 must be set if we want to use the expert_wrcalib register. */
putreg32(0x08, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
/* mask of as many 1 bits as there are lanes */
done_mask = 0xff >> (8 - lanes);
/* Training carried out here: sweeping write calibration offset from 0 to F
* Explanation: A register, expert_wrcalib, is described in MSS DDR TIP
* Register Map [1], and its purpose is to delay by X number of memory
* clock cycles the write data, write data mask, and write output enable
* with the respect to the address and command for each lane.
*/
for (cal_data = 0x00000;
cal_data < 0xfffff && done != done_mask && result != -ETIMEDOUT;
cal_data += 0x11111)
{
putreg32(cal_data, MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB);
for (lane = 0; lane < lanes && result != -ETIMEDOUT; lane++)
{
uint8_t cal_value = cal_data & 0xf;
uint8_t mask = (uint8_t)(0x1 << lane);
/* Check if this lane is not yet done and the test passes */
if (!(done & (0x1 << lane)))
{
/* First passing value is the offset point, record it */
result = mpfs_mtc_test_all(mask, start_address, size,
MTC_ADD_SEQUENTIAL);
if (result == 0)
{
offset[lane] = cal_value;
done |= 1 << lane;
}
}
}
}
/* If calibration was successful, calculate and set the value */
if (done == done_mask)
{
/* Calibration succeeded, set the result */
result = 0;
/* Create cal_data mask from individua lane offsets */
cal_data = 0x0;
for (lane = 0; lane < lanes; lane++)
{
cal_data |= offset[lane] << (lane * 4);
}
/* Set the write calibration which has been calculated */
putreg32(cal_data,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_WRCALIB);
}
else if (result == 0)
{
/* Just in case calibration is not done but last result from lane test
* was OK
*/
result = 1;
}
return result;
}
/****************************************************************************
* Name: mpfs_ddr_rand
*
* Description:
* This is adapted from seiran128
* (https://github.com/andanteyk/prng-seiran)
*
* Returned Value:
* Non-cryptographically secure pseudo random number
*
****************************************************************************/
static inline uint64_t rotl(uint64_t x, int k)
{
return (x << k) | (x >> (-k & 0x3f));
}
static int mpfs_ddr_rand(void)
{
uint64_t s0 = prng_state[0];
uint64_t s1 = prng_state[1];
uint64_t result = rotl((s0 + s1) * 9, 29) + s0;
prng_state[0] = s0 ^ rotl(s1, 29);
prng_state[1] = s0 ^ (s1 << 9);
return (int)result;
}
/****************************************************************************
* Name: mpfs_ddr_write
*
* Description:
* This writes values into DDR with various patterns. These values are
* meant to be read back and validated later.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
* ddr_word_ptr - DDR address to start from
* no_of_access - Number of accesses
* data_ptrn - Data pattern
* data_width - 64 or 32 bit data width
*
****************************************************************************/
static void mpfs_ddr_write(struct mpfs_ddr_priv_s *priv,
volatile uint64_t *ddr_word_ptr,
uint32_t no_of_access,
int8_t data_ptrn,
enum ddr_access_size_e data_width)
{
uint64_t data;
uint32_t i;
volatile uint32_t *ddr_32_ptr = (uint32_t *)ddr_word_ptr;
switch (data_ptrn)
{
case PATTERN_INCREMENTAL:
data = 0x00000000;
break;
case PATTERN_WALKING_ONE:
data = 0x00000001;
break;
case PATTERN_WALKING_ZERO:
data = 0x01;
data = ~data;
break;
case PATTERN_RANDOM:
data = (uint64_t)mpfs_ddr_rand();
break;
case PATTERN_CCCCCCCC:
data = 0xcccccccccccccccc;
break;
case PATTERN_55555555:
data = 0x5555555555555555;
break;
case PATTERN_ZEROS:
data = 0x00000000;
break;
default:
data = 0x00000000;
break;
}
for (i = 0; i < no_of_access; i++)
{
switch (data_width)
{
case DDR_32_BIT:
data &= 0xffffffff;
*ddr_32_ptr = (uint32_t)data;
ddr_32_ptr = ddr_32_ptr + 1;
break;
default:
case DDR_64_BIT:
*ddr_word_ptr = data;
ddr_word_ptr = ddr_word_ptr + 1;
break;
}
switch (data_ptrn)
{
case PATTERN_INCREMENTAL:
data = data + 0x00000001;
break;
case PATTERN_WALKING_ONE:
if (data == 0x80000000)
{
data = 0x00000001;
}
else
{
data = (data << 1);
}
break;
case PATTERN_WALKING_ZERO:
data = ~data;
if (data == 0x80000000)
data = 0x00000001;
else
{
data = (data << 1);
}
data = ~data;
break;
case PATTERN_RANDOM:
data = (uint64_t)mpfs_ddr_rand();
break;
case PATTERN_CCCCCCCC:
data = 0xcccccccccccccccc;
break;
case PATTERN_55555555:
data = 0x5555555555555555;
break;
case PATTERN_ZEROS:
data = 0x00000000;
break;
default:
break;
}
}
}
/****************************************************************************
* Name: mpfs_ddr_read
*
* Description:
* This reads back values from DDR written earlier by mpfs_ddr_write() and
* validates them.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
* ddr_word_ptr - DDR address to start from
* no_of_access - Number of accesses
* data_ptrn - Data pattern
* data_width - 64 or 32 bit data width
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a failure.
*
****************************************************************************/
uint32_t mpfs_ddr_read(struct mpfs_ddr_priv_s *priv,
volatile uint64_t *ddr_word_ptr,
uint32_t no_of_access,
uint8_t data_ptrn,
enum ddr_access_size_e data_width)
{
uint32_t i;
uint64_t data;
uint32_t err_cnt;
volatile uint64_t ddr_data;
volatile uint64_t *ddr_word_pt_t;
volatile uint64_t *first_ddr_word_pt_t;
uint32_t mpfs_ddr_rand_addr_offset;
volatile uint32_t *ddr_32_pt_t;
err_cnt = 0U;
first_ddr_word_pt_t = ddr_word_ptr;
ddr_32_pt_t = (uint32_t *)ddr_word_ptr;
switch (data_ptrn)
{
case PATTERN_INCREMENTAL:
data = 0x00000000;
break;
case PATTERN_WALKING_ONE:
data = 0x00000001;
break;
case PATTERN_WALKING_ZERO:
data = 0x01;
data = ~data;
break;
case PATTERN_RANDOM:
data = (uint64_t)mpfs_ddr_rand();
*ddr_word_ptr = data;
*ddr_32_pt_t = (uint32_t)data;
break;
case PATTERN_CCCCCCCC:
data = 0xcccccccccccccccc;
break;
case PATTERN_55555555:
data = 0x5555555555555555;
break;
case PATTERN_ZEROS:
data = 0x00000000;
break;
default:
data = 0x00000000;
break;
}
if (data_ptrn == '4')
{
mpfs_wait_cycles(10);
}
for (i = 0; i < (no_of_access); i++)
{
switch (data_width)
{
case DDR_32_BIT:
data &= 0xffffffff;
ddr_data = *ddr_32_pt_t;
break;
default:
case DDR_64_BIT:
ddr_word_pt_t = ddr_word_ptr;
ddr_data = *ddr_word_pt_t;
break;
}
if (ddr_data != data)
{
err_cnt++;
}
ddr_word_ptr = ddr_word_ptr + 1U;
ddr_32_pt_t = ddr_32_pt_t +1U;
switch (data_ptrn)
{
case PATTERN_INCREMENTAL:
data = data + 0x01;
break;
case PATTERN_WALKING_ONE:
if (data == 0x80000000)
data = 0x00000001;
else
data = (data << 1);
break;
case PATTERN_WALKING_ZERO:
data = ~data;
if (data == 0x80000000)
{
data = 0x00000001;
}
else
{
data = (data << 1);
}
data = ~data;
break;
case PATTERN_RANDOM:
data = (uint64_t)mpfs_ddr_rand();
mpfs_ddr_rand_addr_offset = (uint32_t)(mpfs_ddr_rand() &
0xffffc);
ddr_word_ptr = first_ddr_word_pt_t +
mpfs_ddr_rand_addr_offset;
ddr_32_pt_t = (uint32_t *)(first_ddr_word_pt_t +
mpfs_ddr_rand_addr_offset);
*ddr_word_ptr = data;
*ddr_32_pt_t = (uint32_t)data;
break;
case PATTERN_CCCCCCCC:
data = 0xcccccccccccccccc;
break;
case PATTERN_55555555:
data = 0x5555555555555555;
break;
case PATTERN_ZEROS:
data = 0x00000000;
break;
default:
break;
}
}
return (err_cnt);
}
/****************************************************************************
* Name: mpfs_ddr_read_write_fn
*
* Description:
* This writes and reads back values from the determined location in DDR
* memory.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
* ddr_word_ptr - DDR address to start from
* no_access - Number of accesses
* pattern - Data pattern
*
* Returned Value:
* 0 on success, number of errors otherwise.
*
****************************************************************************/
static uint32_t mpfs_ddr_read_write_fn(struct mpfs_ddr_priv_s *priv,
uint64_t *ddr_word_ptr,
uint32_t no_access,
uint32_t pattern)
{
uint32_t error_cnt = 0;
uint8_t pattern_mask;
uint32_t pattern_shift;
for (pattern_shift = 0; pattern_shift < MAX_NO_PATTERNS;
pattern_shift++)
{
pattern_mask = (uint8_t)(0x01 << pattern_shift);
if (pattern & pattern_mask)
{
/* Write the pattern */
mpfs_ddr_write(priv, (uint64_t *)ddr_word_ptr, no_access,
pattern_mask, DDR_64_BIT);
error_cnt += mpfs_ddr_read(priv, (uint64_t *)ddr_word_ptr,
no_access, pattern_mask,
DDR_64_BIT);
/* Write the pattern */
mpfs_ddr_write(priv, (uint64_t *)ddr_word_ptr, no_access,
pattern_mask, DDR_32_BIT);
/* Read back and verifies */
error_cnt += mpfs_ddr_read(priv, (uint64_t *)ddr_word_ptr,
no_access, pattern_mask,
DDR_32_BIT);
}
}
return error_cnt;
}
#ifdef CONFIG_MPFS_DDR_MANUAL_ADDCMD_TRAINING
/****************************************************************************
* Name: mpfs_ddr_manual_addcmd_training
*
* Description:
* Performs manual addcmd training.
*
* Input Parameters:
* priv - Instance of the ddr private state structure.
*
****************************************************************************/
static void mpfs_ddr_manual_addcmd_training(struct mpfs_ddr_priv_s *priv)
{
uint32_t bclk_phase;
uint32_t bclk90_phase;
uint32_t refclk_phase;
uint32_t ca_indly;
uint32_t dpc_vals;
uint32_t j;
uint32_t i;
/* If automatic training is enabled, skip this */
if ((LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) == 0)
{
return;
}
/* Apply offset & load the phase */
bclk_phase = ((priv->bclk_answer + SW_TRAINING_BCLK_SCLK_OFFSET) &
0x07) << 8;
bclk90_phase = ((priv->bclk_answer + SW_TRAINING_BCLK_SCLK_OFFSET + 2) &
0x07) << 11;
/* Store DRV & VREF initial values (to be re-applied after
* CA training)
*/
uint32_t ca_drv = getreg32(MPFS_CFG_DDR_SGMII_PHY_RPC1_DRV);
uint32_t ca_vref = (getreg32(MPFS_CFG_DDR_SGMII_PHY_DPC_BITS) >> 12) &
0x3f;
uint32_t dpc_bits_new;
uint32_t vref_answer;
uint32_t transition_a5_min_last = 129;
putreg32(0x01, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
for (ca_indly = 0; ca_indly < 30; ca_indly = ca_indly + 5)
{
putreg32(ca_indly, MPFS_CFG_DDR_SGMII_PHY_RPC145);
putreg32(ca_indly, MPFS_CFG_DDR_SGMII_PHY_RPC147);
uint32_t break_loop = 1;
uint32_t in_window = 0;
vref_answer = 128;
/* Begin VREF training */
for (uint32_t vref = 5; vref < 30; vref++)
{
uint32_t transition_a5_max = 0;
uint32_t transition_a5_min = 128;
uint32_t rx_a5_last;
uint32_t rx_a5;
uint32_t transition_a5;
uint32_t range_a5 = 0;
if (transition_a5_min_last > 128)
{
transition_a5_min_last = 128;
}
putreg32(0, MPFS_IOSCB_BANK_CNTL_DDR_SOFT_RESET);
/* Set VREF */
mpfs_wait_cycles(10);
dpc_bits_new = (getreg32(MPFS_CFG_DDR_SGMII_PHY_DPC_BITS) &
0xfffc0fff) | (vref << 12) | (0x1 << 18);
putreg32(dpc_bits_new, MPFS_CFG_DDR_SGMII_PHY_DPC_BITS);
mpfs_wait_cycles(10);
putreg32(1, MPFS_IOSCB_BANK_CNTL_DDR_SOFT_RESET);
mpfs_wait_cycles(10);
uint32_t deltat = 128;
for (j = 0; j < 20; j++)
{
putreg32(0x00,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_DIRECTION_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x180000,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x180000,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_DIRECTION_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x180000,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
rx_a5_last = 0xf;
transition_a5 = 0;
deltat = 128;
mpfs_wait_cycles(10);
for (i = 0; i < (128 - ca_indly); i++)
{
putreg32(0x00,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
putreg32(0x180000,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
putreg32(0x00,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
mpfs_wait_cycles(10);
rx_a5 = (getreg32(
MPFS_CFG_DDR_SGMII_PHY_EXPERT_ADDCMD_LN_READBACK) \
& 0x0300) >> 8;
if (transition_a5 != 0)
{
if (((i - transition_a5) > 8))
{
break;
}
}
if (transition_a5 == 0)
{
if (((rx_a5 ^ rx_a5_last) & rx_a5))
{
transition_a5 = i;
}
else
{
rx_a5_last = rx_a5;
}
}
else
{
if ((i - transition_a5) == 4)
{
if (!((rx_a5 ^ rx_a5_last) & rx_a5))
{
/* Continue looking for transition */
transition_a5 = 0;
rx_a5_last = rx_a5;
}
}
}
}
if (transition_a5 != 0)
{
if (transition_a5 > transition_a5_max)
{
transition_a5_max = transition_a5;
}
if (transition_a5 < transition_a5_min)
{
transition_a5_min = transition_a5;
}
}
}
range_a5 = transition_a5_max - transition_a5_min;
if (transition_a5_min < 10)
{
break_loop = 0;
}
if (range_a5 <= 5)
{
if (transition_a5_min > transition_a5_min_last)
{
deltat = transition_a5_min - transition_a5_min_last;
}
else
{
deltat = transition_a5_min_last - transition_a5_min;
}
if (deltat <= 5)
{
in_window = (in_window << 1) | 1;
}
}
else
{
in_window = (in_window << 1) | 0;
}
if (vref_answer == 128)
{
if ((in_window & 0x3) == 0x3)
{
vref_answer = vref;
break;
}
}
transition_a5_min_last = transition_a5_min;
}
if (break_loop)
{
break;
}
}
putreg32(0, MPFS_IOSCB_BANK_CNTL_DDR_SOFT_RESET);
/* Set VREF */
mpfs_wait_cycles(10);
if (vref_answer == 128)
{
vref_answer = 0x10;
dpc_bits_new = (getreg32(MPFS_CFG_DDR_SGMII_PHY_DPC_BITS) & 0xfffc0fff)
| (vref_answer << 12) | (0x1 << 18);
}
else
{
vref_answer = vref_answer;
dpc_bits_new = (getreg32(MPFS_CFG_DDR_SGMII_PHY_DPC_BITS) & 0xfffc0fff)
| (vref_answer << 12) | (0x1 << 18);
}
putreg32(dpc_bits_new, MPFS_CFG_DDR_SGMII_PHY_DPC_BITS);
mpfs_wait_cycles(10);
putreg32(1, MPFS_IOSCB_BANK_CNTL_DDR_SOFT_RESET);
mpfs_wait_cycles(10000);
/* Begin manual addcmd training */
uint32_t init_del_offset = 0x8;
uint32_t a5_offset_fail;
uint32_t rpc147_offset = 0x2;
uint32_t rpc145_offset = 0x0;
uint8_t refclk_offset = mpfs_ddr_manual_addcmd_refclk_offset(priv);
a5_offset_fail = 1;
while (a5_offset_fail)
{
a5_offset_fail = 0; /* 1 indicates a fail */
putreg32(init_del_offset + rpc147_offset,
MPFS_CFG_DDR_SGMII_PHY_RPC147);
putreg32(init_del_offset + rpc145_offset,
MPFS_CFG_DDR_SGMII_PHY_RPC145);
putreg32(0x03, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
uint32_t rx_a5;
uint32_t rx_a5_last;
uint32_t rx_ck;
uint32_t rx_ck_last;
uint32_t transition_a5;
uint32_t transition_ck;
uint32_t difference[8] = {
0
};
uint32_t transition_ck_array[8] = {
0
};
uint32_t transitions_found;
uint32_t transition_a5_max = 0;
for (j = 0; j < 16; j++)
{
/* Increase j loop to increase number of samples on transition_a5
* (for noisy CA in LPDDR4)
*/
/* Load INDLY */
putreg32(0x00,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_DIRECTION_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x180000, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
/* Load OUTDLY */
putreg32(0x180000,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_DIRECTION_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x180000, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
refclk_phase = (j % 8U) << 2U;
putreg32((0x00004003 | bclk_phase | bclk90_phase | refclk_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32((0x00000003 | bclk_phase | bclk90_phase | refclk_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32((0x00004003 | bclk_phase | bclk90_phase | refclk_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
rx_a5_last = 0xf;
rx_ck_last = 0x5;
transition_a5 = 0;
transition_ck = 0;
mpfs_wait_cycles(100);
transitions_found = 0;
i = 0;
while ((!transitions_found) & (i < 128))
{
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
putreg32(0x180000,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
mpfs_wait_cycles(10);
rx_a5 =
(getreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_ADDCMD_LN_READBACK) &
0x0300) >> 8;
rx_ck =
getreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_ADDCMD_LN_READBACK) &
0x000f;
if ((transition_a5 != 0) && (transition_ck != 0))
{
if (((i - transition_a5) > 8) && ((i - transition_ck) > 8))
{
transitions_found = 1;
}
}
if (transition_ck == 0)
{
if (rx_ck_last != 0x5) /* If edge detected */
{
if (rx_ck == 0x5)
transition_ck = i; /* Transition detected at i */
}
rx_ck_last = rx_ck;
}
else
{
if ((i - transition_ck) == 4)
{
/* If rx_ck not stable after 4 increments, mark it
* a false transition
*/
if (rx_ck != rx_ck_last)
{
/* Keep looking for transition */
transition_ck = 0;
rx_ck_last = rx_ck;
}
}
}
if (transition_a5 == 0)
{
if (((rx_a5 ^ rx_a5_last) & rx_a5))
{
transition_a5 = i;
}
else
{
rx_a5_last = rx_a5;
}
}
else
{
if ((i - transition_a5) == 4)
{
if (!((rx_a5 ^ rx_a5_last) & rx_a5))
{
/* Keep looking for transition */
transition_a5 = 0;
rx_a5_last = rx_a5;
}
}
}
if ((transition_a5 != 0) && (transition_ck != 0))
{
if ((i == transition_a5) || (i == transition_ck))
{
}
}
i++;
}
if (transition_a5 > transition_a5_max)
{
transition_a5_max = transition_a5;
}
if ((transition_a5 != 0) && (transition_ck != 0) && (j < 8))
{
transition_ck_array[j] = transition_ck;
}
}
uint32_t min_diff = 0xff;
uint32_t min_refclk = 0x8;
if (transition_a5_max < 5)
{
a5_offset_fail = a5_offset_fail | 1;
}
for (uint32_t k = 0; k < 8; k++)
{
if (transition_a5_max >= transition_ck_array[k])
difference[k] = transition_a5_max - transition_ck_array[k];
else
difference[k] = 0xff;
if (difference[k] < min_diff)
{
min_diff = difference[k];
min_refclk = k;
}
}
if (min_diff == 0xff)
{
a5_offset_fail = a5_offset_fail | 1;
}
if (min_refclk == 0x8)
{
/* If ADDCMD training fails due to extremely low frequency,
* use PLL to provide offset.
*/
a5_offset_fail = a5_offset_fail | 4;
}
if (a5_offset_fail == 0)
{
refclk_phase = ((refclk_offset + min_refclk) & 0x7) << 2;
putreg32((0x00004003 | bclk_phase | bclk90_phase | refclk_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32((0x00000003 | bclk_phase | bclk90_phase | refclk_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32((0x00004003 | bclk_phase | bclk90_phase | refclk_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
/* Load INDLY */
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_DIRECTION_REG1);
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x180000, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
/* Load OUTDLY */
putreg32(0x180000,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_DIRECTION_REG1);
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x180000, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
for (uint32_t m = 0; m < min_diff; m++)
{
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
putreg32(0x180000,
MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MOVE_REG1);
}
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_DIRECTION_REG1);
putreg32(0x0, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
}
else
{
if (a5_offset_fail & 0x1)
{
if (init_del_offset < 0xff)
{
/* If transition_a5 too low, increase indly offset on CK
* and CA and retrain
*/
init_del_offset += (transition_a5_max) + 5;
}
else
{
break;
}
}
}
}
/* Set VREF back to configured value */
putreg32(0, MPFS_IOSCB_BANK_CNTL_DDR_SOFT_RESET);
mpfs_wait_cycles(10);
dpc_vals = (getreg32(MPFS_CFG_DDR_SGMII_PHY_DPC_BITS) & 0xfffc0fff) |
(ca_vref << 12) | (0x1 << 18);
putreg32(dpc_vals, MPFS_CFG_DDR_SGMII_PHY_DPC_BITS);
mpfs_wait_cycles(10);
putreg32(0x01, MPFS_IOSCB_BANK_CNTL_DDR_SOFT_RESET);
mpfs_wait_cycles(10);
/* Set CA DRV back to configured value */
putreg32(ca_drv, MPFS_CFG_DDR_SGMII_PHY_RPC1_DRV);
}
#endif
/****************************************************************************
* Name: mpfs_ddr_sm_init
*
* Description:
* Initializes the state machine. In the event on -EAGAIN later, this will
* be called again before restarting the entire process.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
****************************************************************************/
static void mpfs_ddr_sm_init(struct mpfs_ddr_priv_s *priv)
{
priv->tip_cfg_params = LIBERO_SETTING_TIP_CFG_PARAMS;
priv->dpc_bits = LIBERO_SETTING_DPC_BITS;
priv->rpc_166_fifo_offset = DEFAULT_RPC_166_VALUE;
priv->refclk_sweep_index = 0xf;
priv->number_of_lanes_to_calibrate = mpfs_get_num_lanes();
}
/****************************************************************************
* Name: mpfs_ddr_fail
*
* Description:
* This performs the mandatory steps to close-up the ddr controller if
* the training failed on a permanent manner.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
****************************************************************************/
static void mpfs_ddr_fail(struct mpfs_ddr_priv_s *priv)
{
putreg32(0, MPFS_DDR_CSR_APB_PHY_DFI_INIT_START);
/* Reset controller */
putreg32(0, MPFS_DDR_CSR_APB_CTRLR_INIT);
putreg32(0, MPFS_CFG_DDR_SGMII_PHY_TRAINING_START);
}
/****************************************************************************
* Name: mpfs_set_mode_vs_bits
*
* Description:
* Select VS bits for DDR mode selected - set dynamic pc bit settings to
* allow editing of RPC registers pvt calibration etc.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a failure.
*
****************************************************************************/
static int mpfs_set_mode_vs_bits(struct mpfs_ddr_priv_s *priv)
{
uint32_t retries = MPFS_DEFAULT_RETRIES;
uint32_t d;
/* Set the training mode */
mpfs_set_ddr_mode_reg_and_vs_bits(priv);
/* Flash registers with RPC values */
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_DRIVER);
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_ODT);
putreg32(1, MPFS_CFG_DDR_SGMII_PHY_SOFT_RESET_DECODER_IO);
/* Correct some rpc registers, which were incorrectly set in mode
* setting
*/
mpfs_set_ddr_rpc_regs(priv);
/* Set soft reset on IP to load RPC to SCB regs (dynamic mode),
* bring the DDR bank controller out of reset
*/
putreg32(1, MPFS_IOSCB_BANK_CNTL_DDR_SOFT_RESET);
/* Calibrate DDR I/O here, once all RPC settings correct */
if (mpfs_ddr_pvt_calibration())
{
return 1;
}
/* Configure the DDR PLL */
mpfs_ddr_pll_config();
/* Verify DDR PLL lock */
while (mpfs_ddr_pll_lock_scb() && --retries);
if (retries == 0)
{
merr("Timeout\n");
return 1;
}
/* Configure Segments- address mapping, CFG0/CFG1 */
mpfs_setup_ddr_segments(DEFAULT_SEG_SETUP);
/* Set-up DDRC */
mpfs_init_ddrc();
/* Assert training reset, reset pin is bit 1 */
putreg32(0x02, MPFS_CFG_DDR_SGMII_PHY_TRAINING_RESET);
putreg32(0x00, MPFS_DDR_CSR_APB_CTRLR_SOFT_RESET_N);
putreg32(0x01, MPFS_DDR_CSR_APB_CTRLR_SOFT_RESET_N);
/* Rotate bclk90 by 90 deg */
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
/* Expert mode enable */
putreg32(0x02, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
putreg32(0x7c, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
putreg32(0x78, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
putreg32(0x78, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
putreg32(0x7c, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
putreg32(0x64, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
putreg32(0x66, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
for (d = 0; d < LIBERO_SETTING_TIP_CONFIG_PARAMS_BCLK_VCOPHS_OFFSET; d++)
{
putreg32(0x67, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
putreg32(0x66, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
}
putreg32(0x64, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_EXPERT_PLLCNT);
/* setting load delay lines */
putreg32(0x1f, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MV_RD_DLY_REG);
putreg32(0xffffffff, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_MV_RD_DLY_REG);
putreg32(0xffffffff, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x3f, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_PAUSE);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_PAUSE);
putreg32(0x06, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DFI_STATUS_OVERRIDE);
putreg32(0xffffffff, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG0);
putreg32(0x0f, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG0);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x04, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DFI_STATUS_OVERRIDE);
putreg32(0xffffffff, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG0);
putreg32(0x0f, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG0);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_LOAD_REG1);
/* Clear */
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DFI_STATUS_OVERRIDE);
putreg32(0x3f, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_PAUSE);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_DLYCNT_PAUSE);
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_EXPERT_MODE_EN);
/* Set training parameters
*
* Tip static parameters 0:
*
* 30:22 Number of VCO Phase offsets between BCLK and SCLK
* 21:13 Number of VCO Phase offsets between BCLK and SCLK
* 12:6 Number of VCO Phase offsets between BCLK and SCLK
* 5:3 Number of VCO Phase offsets between BCLK and SCLK
* 2:0 Number of VCO Phase offsets between REFCLK and ADDCMD bits
*/
putreg32(priv->tip_cfg_params, MPFS_CFG_DDR_SGMII_PHY_TIP_CFG_PARAMS);
return 0;
}
#ifdef CONFIG_MPFS_DDR_MANUAL_BCLSCLK_TRAINING
/****************************************************************************
* Name: mpfs_bclksclk_sw
*
* Description:
* This performs a manual BCLKSCLK training.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
****************************************************************************/
static void mpfs_bclksclk_sw(struct mpfs_ddr_priv_s *priv)
{
uint32_t rx_previous = 0x3;
uint32_t rx_current = 0;
uint32_t answer_count[8] = {
0
};
uint32_t answer_index = 0;
uint32_t bclk90_phase;
uint32_t bclk_phase;
uint32_t max;
uint32_t j;
uint32_t i;
/* We have chosen to use software bclk sclk sweep instead of IP */
priv->bclk_answer = 0;
for (i = 0; i < (8 * 100); i++)
{
bclk_phase = (i & 0x07) << 8;
bclk90_phase = ((i + 2) & 0x07) << 11;
/* Load BCLK90 phase */
putreg32((0x00004003 | bclk_phase | bclk90_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32((0x00000003 | bclk_phase | bclk90_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32((0x00004003 | bclk_phase | bclk90_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
/* Sample RX_BCLK */
rx_current = (
getreg32(MPFS_CFG_DDR_SGMII_PHY_EXPERT_ADDCMD_LN_READBACK)
>> 12) & 0x03;
/* If transition found, break the loop */
if ((rx_current & (~rx_previous)) != 0x00)
{
answer_index = i & 0x07;
/* Increment the answer count for this index */
answer_count[answer_index]++;
}
rx_previous = rx_current;
max = 0;
for (j = 0; j < 8; j++)
{
/* Sweep through found answers and select the most common */
if (answer_count[j] > max)
{
priv->bclk_answer = j;
max = answer_count[j];
}
}
}
/* Apply offset & load the phase */
bclk_phase = ((priv->bclk_answer + SW_TRAINING_BCLK_SCLK_OFFSET) &
0x07) << 8;
bclk90_phase = ((priv->bclk_answer + SW_TRAINING_BCLK_SCLK_OFFSET + 2) &
0x07) << 11;
putreg32((0x00004003 | bclk_phase | bclk90_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32((0x00000003 | bclk_phase | bclk90_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
putreg32((0x00004003 | bclk_phase | bclk90_phase),
MPFS_IOSCB_DDR_PLL_PHADJ);
}
#endif
/****************************************************************************
* Name: mpfs_training_start
*
* Description:
* This starts the DDR training process.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
****************************************************************************/
static void mpfs_training_start(struct mpfs_ddr_priv_s *priv)
{
putreg32(LIBERO_SETTING_TRAINING_SKIP_SETTING,
MPFS_CFG_DDR_SGMII_PHY_TRAINING_SKIP);
#if defined(CONFIG_MPFS_DDR_TYPE_LPDDR4) || defined(CONFIG_MPFS_DDR_TYPE_DDR3) || \
defined(CONFIG_MPFS_DDR_TYPE_DDR4)
/* RX_MD_CLKN */
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_RPC168);
#endif
/* Release reset to training */
putreg32(0x00, MPFS_CFG_DDR_SGMII_PHY_TRAINING_RESET);
putreg32(0, MPFS_DDR_CSR_APB_PHY_DFI_INIT_START);
putreg32(1, MPFS_DDR_CSR_APB_PHY_DFI_INIT_START);
putreg32(0, MPFS_DDR_CSR_APB_CTRLR_INIT);
putreg32(1, MPFS_DDR_CSR_APB_CTRLR_INIT);
}
/****************************************************************************
* Name: mpfs_training_start_check
*
* Description:
* Checks the training has completed.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a failure.
*
****************************************************************************/
static int mpfs_training_start_check(struct mpfs_ddr_priv_s *priv)
{
unsigned int retries = MPFS_DEFAULT_RETRIES;
while (!(getreg32(MPFS_DDR_CSR_APB_STAT_DFI_INIT_COMPLETE) & 0x01) &&
--retries);
if (retries == 0)
{
merr("Timeout!\n");
return 1;
}
return 0;
}
/****************************************************************************
* Name: mpfs_training_bclksclk
*
* Description:
* Checks the BCLK/SCLK training status for completion.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a failure.
*
****************************************************************************/
static int mpfs_training_bclksclk(struct mpfs_ddr_priv_s *priv)
{
uint32_t retries = MPFS_DEFAULT_RETRIES;
if (LIBERO_SETTING_TRAINING_SKIP_SETTING & BCLK_SCLK_BIT)
{
return 0;
}
while (!(getreg32(MPFS_CFG_DDR_SGMII_PHY_TRAINING_STATUS) & BCLK_SCLK_BIT)
&& --retries);
if (retries == 0)
{
merr("Timeout!\n");
return -ETIMEDOUT;
}
return 0;
}
/****************************************************************************
* Name: mpfs_training_addcmd
*
* Description:
* Checks the training addcmd status for completion.
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a failure
*
****************************************************************************/
static int mpfs_training_addcmd(void)
{
uint32_t retries = MPFS_DEFAULT_RETRIES;
if (LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT)
{
return 0;
}
while (!(getreg32(MPFS_CFG_DDR_SGMII_PHY_TRAINING_STATUS) & ADDCMD_BIT)
&& --retries);
if (retries == 0)
{
merr("Timeout!\n");
return -ETIMEDOUT;
}
return 0;
}
/****************************************************************************
* Name: mpfs_training_verify
*
* Description:
* Checks the training addcmd status for completion and read the training
* results.
*
* Returned Value:
* Zero (OK) is returned on success. A nonzero value indicates a failure.
*
****************************************************************************/
static int mpfs_training_verify(void)
{
uint32_t low_ca_dly_count;
uint32_t decrease_count;
uint32_t addcmd_status0;
uint32_t addcmd_status1;
uint32_t retries = MPFS_DEFAULT_RETRIES;
uint32_t t_status = 0;
uint32_t lane_sel;
uint32_t last;
uint32_t i;
while (!(getreg32(MPFS_DDR_CSR_APB_STAT_DFI_TRAINING_COMPLETE) & 0x01) &&
--retries);
if (retries == 0)
{
merr("Timeout\n");
return -ETIMEDOUT;
}
for (lane_sel = 0; lane_sel < LIBERO_SETTING_DATA_LANES_USED; lane_sel++)
{
mpfs_wait_cycles(10);
putreg32(lane_sel, MPFS_CFG_DDR_SGMII_PHY_LANE_SELECT);
mpfs_wait_cycles(10);
/* Verify cmd address results, rejects if not acceptable */
addcmd_status0 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS0);
addcmd_status1 = getreg32(MPFS_CFG_DDR_SGMII_PHY_ADDCMD_STATUS1);
uint32_t ca_status[8] =
{
((addcmd_status0) & 0xff),
((addcmd_status0 >> 8) & 0xff),
((addcmd_status0 >> 16) & 0xff),
((addcmd_status0 >> 24) & 0xff),
((addcmd_status1) & 0xff),
((addcmd_status1 >> 8) & 0xff),
((addcmd_status1 >> 16) & 0xff),
((addcmd_status1 >> 24) & 0xff)
};
low_ca_dly_count = 0;
last = 0;
decrease_count = 0;
for (i = 0; i < 8; i++)
{
if (ca_status[i] < 5)
{
low_ca_dly_count++;
}
if (ca_status[i] <= last)
{
decrease_count++;
}
last = ca_status[i];
}
if (ca_status[0] <= ca_status[7])
{
decrease_count++;
}
if ((LIBERO_SETTING_TRAINING_SKIP_SETTING & ADDCMD_BIT) != ADDCMD_BIT)
{
/* Retrain if abnormal CA training result detected */
if (low_ca_dly_count > ABNORMAL_RETRAIN_CA_DLY_DECREASE_COUNT)
{
t_status |= 0x01;
}
/* Retrain if abnormal CA training result detected */
if (decrease_count > ABNORMAL_RETRAIN_CA_DECREASE_COUNT)
{
t_status |= 0x01;
}
}
/* Check that gate training passed without error */
t_status |= getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_ERR_COMB);
mpfs_wait_cycles(10);
/* Check that DQ/DQS training passed without error */
if (getreg32(MPFS_CFG_DDR_SGMII_PHY_DQ_DQS_ERR_DONE) != 8)
{
t_status |= 0x01;
}
/* Check that DQ/DQS calculated window is above 5 taps. */
if (getreg32(MPFS_CFG_DDR_SGMII_PHY_DQDQS_STATUS2) < DQ_DQS_NUM_TAPS)
{
t_status |= 0x01;
}
/* Extra checks */
uint32_t temp = 0;
uint32_t gt_clk_sel = getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_CLK_SEL) &
0x03;
if ((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) & 0xff) == 0)
{
temp++;
if (gt_clk_sel == 0)
{
t_status |= 0x01;
}
}
if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 8) & 0xff) == 0)
{
temp++;
if (gt_clk_sel == 1)
{
t_status |= 0x01;
}
}
if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 16) & 0xff) == 0)
{
temp++;
if (gt_clk_sel == 2)
{
t_status |= 0x01;
}
}
if (((getreg32(MPFS_CFG_DDR_SGMII_PHY_GT_TXDLY) >> 24) & 0xff) == 0)
{
temp++;
if (gt_clk_sel == 3)
{
t_status |= 0x01;
}
}
if (temp > 1)
{
t_status |= 0x01;
}
}
if (t_status != 0)
{
merr("Training failed. Restarting!\n");
return -EAGAIN;
}
return 0;
}
/****************************************************************************
* Name: mpfs_training_wrlvl_wait
*
* Description:
* Waits for the WRLVL bit being set.
*
* Returned Value:
* Zero is returned on success. -ETIMEDOUT otherwise.
*
****************************************************************************/
static int mpfs_training_wrlvl_wait(void)
{
uint32_t retries = MPFS_LONG_RETRIES;
if (LIBERO_SETTING_TRAINING_SKIP_SETTING & WRLVL_BIT)
{
return 0;
}
while (!(getreg32(MPFS_CFG_DDR_SGMII_PHY_TRAINING_STATUS) & WRLVL_BIT) &&
--retries);
if (retries == 0)
{
merr("Timeout!\n");
return -ETIMEDOUT;
}
return 0;
}
/****************************************************************************
* Name: mpfs_training_rdgate
*
* Description:
* Checks for the read gate training completion.
*
* Returned Value:
* Zero is returned on success. -ETIMEDOUT otherwise.
*
****************************************************************************/
static int mpfs_training_rdgate(void)
{
uint32_t retries = MPFS_DEFAULT_RETRIES;
if (LIBERO_SETTING_TRAINING_SKIP_SETTING & RDGATE_BIT)
{
return 0;
}
while (!(getreg32(MPFS_CFG_DDR_SGMII_PHY_TRAINING_STATUS) & RDGATE_BIT) &&
--retries);
if (retries == 0)
{
merr("Timeout!\n");
return -ETIMEDOUT;
}
return 0;
}
/****************************************************************************
* Name: mpfs_dq_dqs
*
* Description:
* Checks for the DQ/DQS training completion.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero is returned on success. -ETIMEDOUT otherwise.
*
****************************************************************************/
static int mpfs_dq_dqs(void)
{
uint32_t retries = MPFS_DEFAULT_RETRIES;
while (!(getreg32(MPFS_CFG_DDR_SGMII_PHY_TRAINING_STATUS) & DQ_DQS_BIT) &&
--retries);
if (retries == 0)
{
merr("Timeout!\n");
return 1;
}
return 0;
}
/****************************************************************************
* Name: mpfs_training_write_calibration
*
* Description:
* Checks for the DQ/DQS training completion
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero is returned on success. Nonzero indicates a failure
*
****************************************************************************/
static int mpfs_training_write_calibration(struct mpfs_ddr_priv_s *priv)
{
int error;
uint32_t write_latency = LIBERO_SETTING_CFG_WRITE_LATENCY_SET;
/* Now start the write calibration as training has been successful */
#ifdef CONFIG_MPFS_DDR_TYPE_LPDDR4
uint8_t lane;
/* Changed default value to centre dq/dqs on window */
putreg32(0x0c, MPFS_CFG_DDR_SGMII_PHY_RPC220);
for (lane = 0; lane < priv->number_of_lanes_to_calibrate; lane++)
{
mpfs_load_dq(lane);
}
#endif
if (LIBERO_SETTING_CFG_WRITE_LATENCY_SET == 0)
{
/* Find the proper write latency by using mtc test */
do
{
putreg32(write_latency, MPFS_DDR_CSR_APB_CFG_DFI_T_PHY_WRLAT);
error = mpfs_write_calibration_using_mtc(priv);
}
while (error && ++write_latency <= WR_LATENCY_MAX);
}
else
{
putreg32(write_latency, MPFS_DDR_CSR_APB_CFG_DFI_T_PHY_WRLAT);
error = mpfs_write_calibration_using_mtc(priv);
}
/* Return error if mtc test failed on all allowed latency values */
if (error)
{
merr("Write calib fail!\n");
return -EIO;
}
return 0;
}
/****************************************************************************
* Name: mpfs_training_full_mtc_test
*
* Description:
* Performs a comprehensive memory test.
*
* Returned Value:
* Zero is returned on success. -EIO on error.
*
****************************************************************************/
static int mpfs_training_full_mtc_test(void)
{
int error = 0;
uint8_t mask;
if (mpfs_get_num_lanes() <= 3)
{
mask = 0x3;
}
else
{
mask = 0xf;
}
/* Test sequential additions */
error = mpfs_mtc_test_all(mask, 0x00, ONE_MB_MTC, MTC_ADD_SEQUENTIAL);
if (error == 0)
{
/* Test random additions */
error = mpfs_mtc_test_all(mask, 0x00, ONE_MB_MTC, MTC_ADD_RANDOM);
}
if (error)
{
merr("Full MTC fail\n");
return -EIO;
}
return 0;
}
/****************************************************************************
* Name: mpfs_ddr_test_32bit_nc
*
* Description:
* High level function for calling mpfs_ddr_read_write_fn(). Using
* non-cached memory alias from 0xc0000000.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero is returned on success. Nonzero indicates a failure.
*
****************************************************************************/
static int mpfs_ddr_test_32bit_nc(struct mpfs_ddr_priv_s *priv)
{
uint32_t error;
/* Write and read back test from drr, non-cached access */
error = mpfs_ddr_read_write_fn(priv,
(uint64_t *)LIBERO_SETTING_DDR_32_NON_CACHE,
SW_CFG_NUM_READS_WRITES,
SW_CONFIG_PATTERN);
if (error)
{
merr("Found errors, memory is corrupt!\n");
return -EIO;
}
return 0;
}
/****************************************************************************
* Name: mpfs_ddr_setup
*
* Description:
* This is the high-level state machine that goes through the training
* sequence step-by-step. DDR_TRAINING_IP_* defines are here to provide
* references for the manufacturer's reference HSS bootloader code. This
* helps when applying future patches.
*
* Input Parameters:
* priv - Instance of the ddr private state structure
*
* Returned Value:
* Zero is returned on success. Nonzero indicates a failure.
*
****************************************************************************/
static int mpfs_ddr_setup(struct mpfs_ddr_priv_s *priv)
{
int retval;
mpfs_ddr_sm_init(priv);
/* DDR_TRAINING_SET_MODE_VS_BITS */
retval = mpfs_set_mode_vs_bits(priv);
if (retval)
{
return retval;
}
/* DDR_MANUAL_BCLSCLK_TRAINING_SW */
#ifdef CONFIG_MPFS_DDR_MANUAL_BCLSCLK_TRAINING
mpfs_bclksclk_sw(priv);
#endif
/* DDR_MANUAL_ADDCMD_TRAINING_SW */
#ifdef CONFIG_MPFS_DDR_MANUAL_ADDCMD_TRAINING
mpfs_ddr_manual_addcmd_training(priv);
#endif
mpfs_training_start(priv);
/* DDR_TRAINING_IP_SM_START_CHECK */
retval = mpfs_training_start_check(priv);
if (retval)
{
return retval;
}
/* DDR_TRAINING_IP_SM_BCLKSCLK */
retval = mpfs_training_bclksclk(priv);
if (retval)
{
return retval;
}
/* DDR_TRAINING_IP_SM_ADDCMD */
retval = mpfs_training_addcmd();
if (retval)
{
return retval;
}
/* DDR_TRAINING_IP_SM_WRLVL */
retval = mpfs_training_wrlvl_wait();
if (retval)
{
return retval;
}
/* DDR_TRAINING_IP_SM_RDGATE */
retval = mpfs_training_rdgate();
if (retval)
{
return retval;
}
/* DDR_TRAINING_IP_SM_DQ_DQS */
retval = mpfs_dq_dqs();
if (retval)
{
return retval;
}
retval = mpfs_training_verify();
if (retval)
{
return retval;
}
putreg32(LIBERO_SETTING_DDRPHY_MODE, MPFS_CFG_DDR_SGMII_PHY_DDRPHY_MODE);
/* DDR_TRAINING_WRITE_CALIBRATION */
retval = mpfs_training_write_calibration(priv);
if (retval)
{
return retval;
}
/* DDR_FULL_MTC_CHECK */
retval = mpfs_training_full_mtc_test();
if (retval)
{
return retval;
}
/* DDR_FULL_32BIT_NC_CHECK */
retval = mpfs_ddr_test_32bit_nc(priv);
if (retval)
{
return retval;
}
/* DDR_TRAINING_FINISHED */
/* Configure Segments, address mapping, CFG0/CFG1 */
mpfs_setup_ddr_segments(LIBERO_SEG_SETUP);
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: mpfs_ddr_init
*
* Description:
* This is the high-level call for initializing the DDR memory.
*
* Returned Value:
* Zero is returned on success, or a negated errno on failure.
*
****************************************************************************/
int mpfs_ddr_init(void)
{
struct mpfs_ddr_priv_s *priv = &g_mpfs_ddr_priv;
int ddr_status;
/* On -EAGAIN, the whole training is restarted from the very beginning */
do
{
ddr_status = mpfs_ddr_setup(priv);
if (ddr_status == -EAGAIN)
{
mpfs_ddr_fail(priv);
}
}
while (ddr_status == -EAGAIN);
if (ddr_status == 0)
{
minfo("DDR setup successfully\n");
}
else
{
minfo("DDR setup returned error: %d\n", ddr_status);
mpfs_ddr_fail(priv);
}
minfo("Done ddr setup\n");
return ddr_status;
}