mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2025-08-14 19:26:58 +02:00
As part of bringing the master branch back in to next, we need to allow for all of these changes to exist here. Reported-by: Jonas Karlman <jonas@kwiboo.se> Signed-off-by: Tom Rini <trini@konsulko.com>
955 lines
32 KiB
C
955 lines
32 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* (C) Copyright 2022 - Analog Devices, Inc.
|
|
*
|
|
* Written and/or maintained by Timesys Corporation
|
|
*
|
|
* Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com>
|
|
* Contact: Greg Malysa <greg.malysa@timesys.com>
|
|
*/
|
|
|
|
#include <asm/io.h>
|
|
#include <asm/arch-adi/sc5xx/sc5xx.h>
|
|
#include <linux/types.h>
|
|
#include "clkinit.h"
|
|
#include "dmcinit.h"
|
|
|
|
#define REG_DMC0_BASE 0x31070000
|
|
#define REG_DMC1_BASE 0x31073000
|
|
|
|
#define REG_DMC_CTL 0x0004 // Control Register
|
|
#define REG_DMC_STAT 0x0008 // Status Register
|
|
#define REG_DMC_CFG 0x0040 // Configuration Register
|
|
#define REG_DMC_TR0 0x0044 // Timing 0 Register
|
|
#define REG_DMC_TR1 0x0048 // Timing 1 Register
|
|
#define REG_DMC_TR2 0x004C // Timing 2 Register
|
|
#define REG_DMC_MR 0x0060 // Shadow MR Register (DDR3)
|
|
#define REG_DMC_EMR1 0x0064 // Shadow EMR1 Register
|
|
#define REG_DMC_EMR2 0x0068 // Shadow EMR2 Register
|
|
#define REG_DMC_EMR3 0x006C
|
|
#define REG_DMC_DLLCTL 0x0080 // DLL Control Register
|
|
#define REG_DMC_DT_CALIB_ADDR 0x0090 // Data Calibration Address Register
|
|
#define REG_DMC_CPHY_CTL 0x01C0 // Controller to PHY Interface Register
|
|
|
|
/* SC57x && SC58x DMC REGs */
|
|
#define REG_DMC_PHY_CTL0 0x1000 // PHY Control 0 Register
|
|
#define REG_DMC_PHY_CTL1 0x1004 // PHY Control 1 Register
|
|
#define REG_DMC_PHY_CTL2 0x1008 // PHY Control 2 Register
|
|
#define REG_DMC_PHY_CTL3 0x100c // PHY Control 3 Register
|
|
#define REG_DMC_PHY_CTL4 0x1010 // PHY Control 4 Register
|
|
#define REG_DMC_CAL_PADCTL0 0x1034 // CALIBRATION PAD CTL 0 Register
|
|
#define REG_DMC_CAL_PADCTL2 0x103C // CALIBRATION PAD CTL2 Register
|
|
/* END */
|
|
|
|
/* SC59x DMC REGs */
|
|
#define REG_DMC_DDR_LANE0_CTL0 0x1000 // Data Lane 0 Control Register 0
|
|
#define REG_DMC_DDR_LANE0_CTL1 0x1004 // Data Lane 0 Control Register 1
|
|
#define REG_DMC_DDR_LANE1_CTL0 0x100C // Data Lane 1 Control Register 0
|
|
#define REG_DMC_DDR_LANE1_CTL1 0x1010 // Data Lane 1 Control Register 1
|
|
#define REG_DMC_DDR_ROOT_CTL 0x1018 // DDR ROOT Module Control Register
|
|
#define REG_DMC_DDR_ZQ_CTL0 0x1034 // DDR Calibration Control Register 0
|
|
#define REG_DMC_DDR_ZQ_CTL1 0x1038 // DDR Calibration Control Register 1
|
|
#define REG_DMC_DDR_ZQ_CTL2 0x103C // DDR Calibration Control Register 2
|
|
#define REG_DMC_DDR_CA_CTL 0x1068 // DDR CA Lane Control Register
|
|
/* END */
|
|
|
|
#define REG_DMC_DDR_SCRATCH_2 0x1074
|
|
#define REG_DMC_DDR_SCRATCH_3 0x1078
|
|
#define REG_DMC_DDR_SCRATCH_6 0x1084
|
|
#define REG_DMC_DDR_SCRATCH_7 0x1088
|
|
|
|
#define REG_DMC_DDR_SCRATCH_STAT0 0x107C
|
|
#define REG_DMC_DDR_SCRATCH_STAT1 0x1080
|
|
|
|
#define DMC0_DATA_CALIB_ADD 0x80000000
|
|
#define DMC1_DATA_CALIB_ADD 0xC0000000
|
|
|
|
#define BITM_DMC_CFG_EXTBANK 0x0000F000 /* External Banks */
|
|
#define ENUM_DMC_CFG_EXTBANK1 0x00000000 /* EXTBANK: 1 External Bank */
|
|
#define BITM_DMC_CFG_SDRSIZE 0x00000F00 /* SDRAM Size */
|
|
#define ENUM_DMC_CFG_SDRSIZE64 0x00000000 /* SDRSIZE: 64M Bit SDRAM (LPDDR Only) */
|
|
#define ENUM_DMC_CFG_SDRSIZE128 0x00000100 /* SDRSIZE: 128M Bit SDRAM (LPDDR Only) */
|
|
#define ENUM_DMC_CFG_SDRSIZE256 0x00000200 /* SDRSIZE: 256M Bit SDRAM */
|
|
#define ENUM_DMC_CFG_SDRSIZE512 0x00000300 /* SDRSIZE: 512M Bit SDRAM */
|
|
#define ENUM_DMC_CFG_SDRSIZE1G 0x00000400 /* SDRSIZE: 1G Bit SDRAM */
|
|
#define ENUM_DMC_CFG_SDRSIZE2G 0x00000500 /* SDRSIZE: 2G Bit SDRAM */
|
|
#define ENUM_DMC_CFG_SDRSIZE4G 0x00000600 /* SDRSIZE: 4G Bit SDRAM */
|
|
#define ENUM_DMC_CFG_SDRSIZE8G 0x00000700 /* SDRSIZE: 8G Bit SDRAM */
|
|
#define BITM_DMC_CFG_SDRWID 0x000000F0 /* SDRAM Width */
|
|
#define ENUM_DMC_CFG_SDRWID16 0x00000020 /* SDRWID: 16-Bit Wide SDRAM */
|
|
#define BITM_DMC_CFG_IFWID 0x0000000F /* Interface Width */
|
|
#define ENUM_DMC_CFG_IFWID16 0x00000002 /* IFWID: 16-Bit Wide Interface */
|
|
|
|
#define BITM_DMC_CTL_DDR3EN 0x00000001
|
|
#define BITM_DMC_CTL_INIT 0x00000004
|
|
#define BITP_DMC_STAT_INITDONE 2 /* Initialization Done */
|
|
#define BITM_DMC_STAT_INITDONE 0x00000004
|
|
|
|
#define BITP_DMC_CTL_AL_EN 27
|
|
#define BITP_DMC_CTL_ZQCL 25 /* ZQ Calibration Long */
|
|
#define BITP_DMC_CTL_ZQCS 24 /* ZQ Calibration Short */
|
|
#define BITP_DMC_CTL_DLLCAL 13 /* DLL Calibration Start */
|
|
#define BITP_DMC_CTL_PPREF 12 /* Postpone Refresh */
|
|
#define BITP_DMC_CTL_RDTOWR 9 /* Read-to-Write Cycle */
|
|
#define BITP_DMC_CTL_ADDRMODE 8 /* Addressing (Page/Bank) Mode */
|
|
#define BITP_DMC_CTL_RESET 7 /* Reset SDRAM */
|
|
#define BITP_DMC_CTL_PREC 6 /* Precharge */
|
|
#define BITP_DMC_CTL_DPDREQ 5 /* Deep Power Down Request */
|
|
#define BITP_DMC_CTL_PDREQ 4 /* Power Down Request */
|
|
#define BITP_DMC_CTL_SRREQ 3 /* Self Refresh Request */
|
|
#define BITP_DMC_CTL_INIT 2 /* Initialize DRAM Start */
|
|
#define BITP_DMC_CTL_LPDDR 1 /* Low Power DDR Mode */
|
|
#define BITP_DMC_CTL_DDR3EN 0 /* DDR3 Mode */
|
|
|
|
#ifdef CONFIG_TARGET_SC584_EZKIT
|
|
#define DMC_PADCTL2_VALUE 0x0078283C
|
|
#elif CONFIG_TARGET_SC573_EZKIT
|
|
#define DMC_PADCTL2_VALUE 0x00782828
|
|
#elif CONFIG_TARGET_SC589_MINI || CONFIG_TARGET_SC589_EZKIT
|
|
#define DMC_PADCTL2_VALUE 0x00783C3C
|
|
#elif defined(CONFIG_SC57X) || defined(CONFIG_SC58X)
|
|
#error "PADCTL2 not specified for custom board!"
|
|
#else
|
|
//Newer DMC. Legacy calibration obsolete
|
|
#define DMC_PADCTL2_VALUE 0x0
|
|
#endif
|
|
|
|
#define DMC_CPHYCTL_VALUE 0x0000001A
|
|
|
|
#define BITP_DMC_MR1_QOFF 12 /* Output Buffer Enable */
|
|
#define BITP_DMC_MR1_TDQS 11 /* Termination Data Strobe */
|
|
#define BITP_DMC_MR1_RTT2 9 /* Rtt_nom */
|
|
#define BITP_DMC_MR1_WL 7 /* Write Leveling Enable. */
|
|
#define BITP_DMC_MR1_RTT1 6 /* Rtt_nom */
|
|
#define BITP_DMC_MR1_DIC1 5 /* Output Driver Impedance Control */
|
|
#define BITP_DMC_MR1_AL 3 /* Additive Latency */
|
|
#define BITP_DMC_MR1_RTT0 2 /* Rtt_nom */
|
|
#define BITP_DMC_MR1_DIC0 1 /* Output Driver Impedance control */
|
|
#define BITP_DMC_MR1_DLLEN 0 /* DLL Enable */
|
|
|
|
#define BITP_DMC_MR2_CWL 3 /* CAS write Latency */
|
|
|
|
#define BITP_DMC_TR0_TMRD 28 /* Timing Mode Register Delay */
|
|
#define BITP_DMC_TR0_TRC 20 /* Timing Row Cycle */
|
|
#define BITP_DMC_TR0_TRAS 12 /* Timing Row Active Time */
|
|
#define BITP_DMC_TR0_TRP 8 /* Timing RAS Precharge. */
|
|
#define BITP_DMC_TR0_TWTR 4 /* Timing Write to Read */
|
|
#define BITP_DMC_TR0_TRCD 0 /* Timing RAS to CAS Delay */
|
|
|
|
#define BITP_DMC_TR1_TRRD 28 /* Timing Read-Read Delay */
|
|
#define BITP_DMC_TR1_TRFC 16 /* Timing Refresh-to-Command */
|
|
#define BITP_DMC_TR1_TREF 0 /* Timing Refresh Interval */
|
|
|
|
#define BITP_DMC_TR2_TCKE 20 /* Timing Clock Enable */
|
|
#define BITP_DMC_TR2_TXP 16 /* Timing Exit Powerdown */
|
|
#define BITP_DMC_TR2_TWR 12 /* Timing Write Recovery */
|
|
#define BITP_DMC_TR2_TRTP 8 /* Timing Read-to-Precharge */
|
|
#define BITP_DMC_TR2_TFAW 0 /* Timing Four-Activated-Window */
|
|
|
|
#define BITP_DMC_MR_PD 12 /* Active Powerdown Mode */
|
|
#define BITP_DMC_MR_WRRECOV 9 /* Write Recovery */
|
|
#define BITP_DMC_MR_DLLRST 8 /* DLL Reset */
|
|
#define BITP_DMC_MR_CL 4 /* CAS Latency */
|
|
#define BITP_DMC_MR_CL0 2 /* CAS Latency */
|
|
#define BITP_DMC_MR_BLEN 0 /* Burst Length */
|
|
|
|
#define BITP_DMC_DLLCTL_DATACYC 8 /* Data Cycles */
|
|
#define BITP_DMC_DLLCTL_DLLCALRDCNT 0 /* DLL Calibration RD Count */
|
|
|
|
#define BITM_DMC_DLLCTL_DATACYC 0x00000F00 /* Data Cycles */
|
|
#define BITM_DMC_DLLCTL_DLLCALRDCNT 0x000000FF /* DLL Calib RD Count */
|
|
|
|
#define BITP_DMC_STAT_PHYRDPHASE 20 /* PHY Read Phase */
|
|
|
|
#define BITM_DMC_DDR_LANE0_CTL0_CB_RSTDAT 0x08000000 /* Rst Data Pads */
|
|
#define BITM_DMC_DDR_LANE1_CTL0_CB_RSTDAT 0x08000000 /* Rst Data Pads */
|
|
#define BITM_DMC_DDR_LANE0_CTL1_COMP_DCYCLE 0x00000002 /* Compute Dcycle */
|
|
#define BITM_DMC_DDR_LANE1_CTL1_COMP_DCYCLE 0x00000002 /* Compute Dcycle */
|
|
#define BITM_DMC_DDR_LANE1_CTL0_CB_RSTDLL 0x00000100 /* Rst Lane DLL */
|
|
#define BITM_DMC_DDR_LANE0_CTL0_CB_RSTDLL 0x00000100 /* Rst Lane DLL */
|
|
#define BITP_DMC_DDR_ROOT_CTL_PIPE_OFSTDCYCLE 10 /* Pipeline offset for PHYC_DATACYCLE */
|
|
#define BITM_DMC_DDR_ROOT_CTL_SW_REFRESH 0x00002000 /* Refresh Lane DLL Code */
|
|
#define BITM_DMC_DDR_CA_CTL_SW_REFRESH 0x00004000 /* Refresh Lane DLL Code */
|
|
|
|
#define BITP_DMC_CTL_RL_DQS 26 /* RL_DQS */
|
|
#define BITM_DMC_CTL_RL_DQS 0x04000000 /* RL_DQS */
|
|
#define BITP_DMC_EMR3_MPR 2 /* Multi Purpose Read Enable (Read Leveling)*/
|
|
#define BITM_DMC_EMR3_MPR 0x00000004 /* Multi Purpose Read Enable (Read Leveling)*/
|
|
#define BITM_DMC_MR1_WL 0x00000080 /* Write Leveling Enable.*/
|
|
#define BITM_DMC_STAT_PHYRDPHASE 0x00F00000 /* PHY Read Phase */
|
|
|
|
#define BITP_DMC_DDR_LANE0_CTL1_BYPCODE 10
|
|
#define BITM_DMC_DDR_LANE0_CTL1_BYPCODE 0x00007C00
|
|
#define BITP_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN 15
|
|
#define BITM_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN 0x00008000
|
|
|
|
#define DMC_ZQCTL0_VALUE 0x00785A64
|
|
#define DMC_ZQCTL1_VALUE 0
|
|
#define DMC_ZQCTL2_VALUE 0x70000000
|
|
|
|
#define DMC_TRIG_CALIB 0
|
|
#define DMC_OFSTDCYCLE 2
|
|
|
|
#define BITP_DMC_CAL_PADCTL0_RTTCALEN 31 /* RTT Calibration Enable */
|
|
#define BITP_DMC_CAL_PADCTL0_PDCALEN 30 /* PULLDOWN Calib Enable */
|
|
#define BITP_DMC_CAL_PADCTL0_PUCALEN 29 /* PULLUP Calib Enable */
|
|
#define BITP_DMC_CAL_PADCTL0_CALSTRT 28 /* Start New Calib ( Hardware Cleared) */
|
|
#define BITM_DMC_CAL_PADCTL0_RTTCALEN 0x80000000 /* RTT Calibration Enable */
|
|
#define BITM_DMC_CAL_PADCTL0_PDCALEN 0x40000000 /* PULLDOWN Calib Enable */
|
|
#define BITM_DMC_CAL_PADCTL0_PUCALEN 0x20000000 /* PULLUP Calib Enable */
|
|
#define BITM_DMC_CAL_PADCTL0_CALSTRT 0x10000000 /* Start New Calib ( Hardware Cleared) */
|
|
#define ENUM_DMC_PHY_CTL4_DDR3 0x00000000 /* DDRMODE: DDR3 Mode */
|
|
#define ENUM_DMC_PHY_CTL4_DDR2 0x00000001 /* DDRMODE: DDR2 Mode */
|
|
#define ENUM_DMC_PHY_CTL4_LPDDR 0x00000003 /* DDRMODE: LPDDR Mode */
|
|
|
|
#define BITP_DMC_DDR_ZQ_CTL0_IMPRTT 16 /* Data/DQS ODT */
|
|
#define BITP_DMC_DDR_ZQ_CTL0_IMPWRDQ 8 /* Data/DQS/DM/CLK Drive Strength */
|
|
#define BITP_DMC_DDR_ZQ_CTL0_IMPWRADD 0 /* Address/Command Drive Strength */
|
|
#define BITM_DMC_DDR_ZQ_CTL0_IMPRTT 0x00FF0000 /* Data/DQS ODT */
|
|
#define BITM_DMC_DDR_ZQ_CTL0_IMPWRDQ 0x0000FF00 /* Data/DQS/DM/CLK Drive Strength */
|
|
#define BITM_DMC_DDR_ZQ_CTL0_IMPWRADD 0x000000FF /* Address/Command Drive Strength */
|
|
|
|
#define BITM_DMC_DDR_ROOT_CTL_TRIG_RD_XFER_ALL 0x00200000 /* All Lane Read Status */
|
|
|
|
#if defined(CONFIG_ADI_USE_DDR2)
|
|
#define DMC_MR0_VALUE \
|
|
((DMC_BL / 4 + 1) << BITP_DMC_MR_BLEN) | \
|
|
(DMC_CL << BITP_DMC_MR_CL) | \
|
|
(DMC_WRRECOV << BITP_DMC_MR_WRRECOV)
|
|
|
|
#define DMC_MR1_VALUE \
|
|
(DMC_MR1_AL << BITP_DMC_MR1_AL | 0x04) \
|
|
|
|
#define DMC_MR2_VALUE 0
|
|
#define DMC_MR3_VALUE 0
|
|
|
|
#define DMC_CTL_VALUE \
|
|
(DMC_RDTOWR << BITP_DMC_CTL_RDTOWR) | \
|
|
(1 << BITP_DMC_CTL_DLLCAL) | \
|
|
(BITM_DMC_CTL_INIT)
|
|
#else
|
|
#define DMC_MR0_VALUE \
|
|
(0 << BITP_DMC_MR_BLEN) | \
|
|
(DMC_CL0 << BITP_DMC_MR_CL0) | \
|
|
(DMC_CL123 << BITP_DMC_MR_CL) | \
|
|
(DMC_WRRECOV << BITP_DMC_MR_WRRECOV) | \
|
|
(1 << BITP_DMC_MR_DLLRST)
|
|
|
|
#define DMC_MR1_VALUE \
|
|
(DMC_MR1_DLLEN << BITP_DMC_MR1_DLLEN) | \
|
|
(DMC_MR1_DIC0 << BITP_DMC_MR1_DIC0) | \
|
|
(DMC_MR1_RTT0 << BITP_DMC_MR1_RTT0) | \
|
|
(DMC_MR1_AL << BITP_DMC_MR1_AL) | \
|
|
(DMC_MR1_DIC1 << BITP_DMC_MR1_DIC1) | \
|
|
(DMC_MR1_RTT1 << BITP_DMC_MR1_RTT1) | \
|
|
(DMC_MR1_RTT2 << BITP_DMC_MR1_RTT2) | \
|
|
(DMC_MR1_WL << BITP_DMC_MR1_WL) | \
|
|
(DMC_MR1_TDQS << BITP_DMC_MR1_TDQS) | \
|
|
(DMC_MR1_QOFF << BITP_DMC_MR1_QOFF)
|
|
|
|
#define DMC_MR2_VALUE \
|
|
((DMC_WL) << BITP_DMC_MR2_CWL)
|
|
|
|
#define DMC_MR3_VALUE \
|
|
((DMC_WL) << BITP_DMC_MR2_CWL)
|
|
|
|
#define DMC_CTL_VALUE \
|
|
(DMC_RDTOWR << BITP_DMC_CTL_RDTOWR) | \
|
|
(BITM_DMC_CTL_INIT) | \
|
|
(BITM_DMC_CTL_DDR3EN) | \
|
|
(DMC_CTL_AL_EN << BITP_DMC_CTL_AL_EN)
|
|
#endif
|
|
|
|
#define DMC_DLLCTL_VALUE \
|
|
(DMC_DATACYC << BITP_DMC_DLLCTL_DATACYC) | \
|
|
(DMC_DLLCALRDCNT << BITP_DMC_DLLCTL_DLLCALRDCNT)
|
|
|
|
#define DMC_CFG_VALUE \
|
|
ENUM_DMC_CFG_IFWID16 | \
|
|
ENUM_DMC_CFG_SDRWID16 | \
|
|
SDR_CHIP_SIZE | \
|
|
ENUM_DMC_CFG_EXTBANK1
|
|
|
|
#define DMC_TR0_VALUE \
|
|
(DMC_TRCD << BITP_DMC_TR0_TRCD) | \
|
|
(DMC_TWTR << BITP_DMC_TR0_TWTR) | \
|
|
(DMC_TRP << BITP_DMC_TR0_TRP) | \
|
|
(DMC_TRAS << BITP_DMC_TR0_TRAS) | \
|
|
(DMC_TRC << BITP_DMC_TR0_TRC) | \
|
|
(DMC_TMRD << BITP_DMC_TR0_TMRD)
|
|
|
|
#define DMC_TR1_VALUE \
|
|
(DMC_TREF << BITP_DMC_TR1_TREF) | \
|
|
(DMC_TRFC << BITP_DMC_TR1_TRFC) | \
|
|
(DMC_TRRD << BITP_DMC_TR1_TRRD)
|
|
|
|
#define DMC_TR2_VALUE \
|
|
(DMC_TFAW << BITP_DMC_TR2_TFAW) | \
|
|
(DMC_TRTP << BITP_DMC_TR2_TRTP) | \
|
|
(DMC_TWR << BITP_DMC_TR2_TWR) | \
|
|
(DMC_TXP << BITP_DMC_TR2_TXP) | \
|
|
(DMC_TCKE << BITP_DMC_TR2_TCKE)
|
|
|
|
enum DDR_MODE {
|
|
DDR3_MODE,
|
|
DDR2_MODE,
|
|
LPDDR_MODE,
|
|
};
|
|
|
|
enum CALIBRATION_MODE {
|
|
CALIBRATION_LEGACY,
|
|
CALIBRATION_METHOD1,
|
|
CALIBRATION_METHOD2,
|
|
};
|
|
|
|
static struct dmc_param {
|
|
phys_addr_t reg;
|
|
u32 ddr_mode;
|
|
u32 padctl2_value;
|
|
u32 dmc_cphyctl_value;
|
|
u32 dmc_cfg_value;
|
|
u32 dmc_dllctl_value;
|
|
u32 dmc_ctl_value;
|
|
u32 dmc_tr0_value;
|
|
u32 dmc_tr1_value;
|
|
u32 dmc_tr2_value;
|
|
u32 dmc_mr0_value;
|
|
u32 dmc_mr1_value;
|
|
u32 dmc_mr2_value;
|
|
u32 dmc_mr3_value;
|
|
u32 dmc_zqctl0_value;
|
|
u32 dmc_zqctl1_value;
|
|
u32 dmc_zqctl2_value;
|
|
u32 dmc_data_calib_add_value;
|
|
bool phy_init_required;
|
|
bool anomaly_20000037_applicable;
|
|
enum CALIBRATION_MODE calib_mode;
|
|
} dmc;
|
|
|
|
#ifdef CONFIG_SC59X_64
|
|
#define DQS_DEFAULT_DELAY 3ul
|
|
|
|
#define DELAYTRIM 1
|
|
#define LANE0_DQS_DELAY 1
|
|
#define LANE1_DQS_DELAY 1
|
|
|
|
#define CLKDIR 0ul
|
|
|
|
#define DQSTRIM 0
|
|
#define DQSCODE 0ul
|
|
|
|
#define CLKTRIM 0
|
|
#define CLKCODE 0ul
|
|
#endif
|
|
|
|
static inline void calibration_legacy(void)
|
|
{
|
|
u32 temp;
|
|
|
|
/* 1. Set DDR mode to DDR3/DDR2/LPDDR in DMCx_PHY_CTL4 register */
|
|
if (dmc.ddr_mode == DDR3_MODE)
|
|
writel(ENUM_DMC_PHY_CTL4_DDR3, dmc.reg + REG_DMC_PHY_CTL4);
|
|
else if (dmc.ddr_mode == DDR2_MODE)
|
|
writel(ENUM_DMC_PHY_CTL4_DDR2, dmc.reg + REG_DMC_PHY_CTL4);
|
|
else if (dmc.ddr_mode == LPDDR_MODE)
|
|
writel(ENUM_DMC_PHY_CTL4_LPDDR, dmc.reg + REG_DMC_PHY_CTL4);
|
|
|
|
/*
|
|
* 2. Make sure that the bits 6, 7, 25, and 27 of the DMC_PHY_
|
|
* CTL3 register are set
|
|
*/
|
|
writel(0x0A0000C0, dmc.reg + REG_DMC_PHY_CTL3);
|
|
|
|
/*
|
|
* 3. For DDR2/DDR3 mode, make sure that the bits 0, 1, 2, 3 of
|
|
* the DMC_PHY_CTL0 register and the bits 26, 27, 28, 29, 30, 31
|
|
* of the DMC_PHY_CTL2 are set.
|
|
*/
|
|
if (dmc.ddr_mode == DDR3_MODE ||
|
|
dmc.ddr_mode == DDR2_MODE) {
|
|
writel(0XFC000000, dmc.reg + REG_DMC_PHY_CTL2);
|
|
writel(0x0000000f, dmc.reg + REG_DMC_PHY_CTL0);
|
|
}
|
|
|
|
writel(0x00000000, dmc.reg + REG_DMC_PHY_CTL1);
|
|
|
|
/* 4. For DDR3 mode, set bit 1 and configure bits [5:2] of the
|
|
* DMC_CPHY_CTL register with WL=CWL+AL in DCLK cycles.
|
|
*/
|
|
if (dmc.ddr_mode == DDR3_MODE)
|
|
writel(dmc.dmc_cphyctl_value, dmc.reg + REG_DMC_CPHY_CTL);
|
|
/* 5. Perform On Die Termination(ODT) & Driver Impedance Calibration */
|
|
if (dmc.ddr_mode == LPDDR_MODE) {
|
|
/* Bypass processor ODT */
|
|
writel(0x80000, dmc.reg + REG_DMC_PHY_CTL1);
|
|
} else {
|
|
/* Set bits RTTCALEN, PDCALEN, PUCALEN of register */
|
|
temp = BITM_DMC_CAL_PADCTL0_RTTCALEN |
|
|
BITM_DMC_CAL_PADCTL0_PDCALEN |
|
|
BITM_DMC_CAL_PADCTL0_PUCALEN;
|
|
writel(temp, dmc.reg + REG_DMC_CAL_PADCTL0);
|
|
/* Configure ODT and drive impedance values in the
|
|
* DMCx_CAL_PADCTL2 register
|
|
*/
|
|
writel(dmc.padctl2_value, dmc.reg + REG_DMC_CAL_PADCTL2);
|
|
/* start calibration */
|
|
temp |= BITM_DMC_CAL_PADCTL0_CALSTRT;
|
|
writel(temp, dmc.reg + REG_DMC_CAL_PADCTL0);
|
|
/* Wait for PAD calibration to complete - 300 DCLK cycle.
|
|
* Worst case: CCLK=450 MHz, DCLK=125 MHz
|
|
*/
|
|
dmcdelay(300);
|
|
}
|
|
}
|
|
|
|
static inline void calibration_method1(void)
|
|
{
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
writel(dmc.dmc_zqctl0_value, dmc.reg + REG_DMC_DDR_ZQ_CTL0);
|
|
writel(dmc.dmc_zqctl1_value, dmc.reg + REG_DMC_DDR_ZQ_CTL1);
|
|
writel(dmc.dmc_zqctl2_value, dmc.reg + REG_DMC_DDR_ZQ_CTL2);
|
|
|
|
/* Generate the trigger */
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
writel(0x00010000ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(8000u);
|
|
|
|
/* The [31:26] bits may change if pad ring changes */
|
|
writel(0x0C000001ul | DMC_TRIG_CALIB, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(8000u);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
#endif
|
|
}
|
|
|
|
static inline void calibration_method2(void)
|
|
{
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
u32 stat_value = 0x0u;
|
|
u32 drv_pu, drv_pd, odt_pu, odt_pd;
|
|
u32 ro_dt, clk_dqs_drv_impedance;
|
|
u32 temp;
|
|
|
|
/* Reset trigger */
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_3);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
|
|
/* Writing internal registers in calib pad to zero. Calib mode set
|
|
* to 1 [26], trig M1 S1 write [16], this enables usage of scratch
|
|
* registers instead of ZQCTL registers
|
|
*/
|
|
writel(0x04010000ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
|
|
/* TRIGGER FOR M2-S2 WRITE -> slave id 31:26 trig m2,s2 write
|
|
* bit 1->1 slave1 address is 4
|
|
*/
|
|
writel(0x10000002ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
|
|
/* reset Trigger */
|
|
writel(0x0u, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0x0u, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
|
|
/* write to slave 1, make the power down bit high */
|
|
writel(0x1ul << 12, dmc.reg + REG_DMC_DDR_SCRATCH_3);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
dmcdelay(2500u);
|
|
|
|
/* Calib mode set to 1 [26], trig M1 S1 write [16] */
|
|
writel(0x04010000ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
|
|
writel(0x10000002ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
writel(0x0, dmc.reg + REG_DMC_DDR_SCRATCH_3);
|
|
|
|
/* for slave 0 */
|
|
writel(dmc.dmc_zqctl0_value, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
|
|
/* Calib mode set to 1 [26], trig M1 S1 write [16] */
|
|
writel(0x04010000ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
|
|
writel(0x0C000002ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
|
|
/* writing to slave 1
|
|
* calstrt is 0, but other programming is done
|
|
*
|
|
* make power down LOW again, to kickstart BIAS circuit
|
|
*/
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_3);
|
|
writel(0x30000000ul, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
|
|
/* write to ca_ctl lane, calib mode set to 1 [26],
|
|
* trig M1 S1 write [16]
|
|
*/
|
|
writel(0x04010000ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
|
|
/* copies data to lane controller slave
|
|
* TRIGGER FOR M2-S2 WRITE -> slave id 31:26
|
|
* trig m2,s2 write bit 1->1
|
|
* slave1 address is 4
|
|
*/
|
|
writel(0x10000002ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
|
|
/* reset Trigger */
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_3);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_3);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
writel(0x04010000ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0x10000002ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_3);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
writel(0x0ul, dmc.reg + REG_DMC_DDR_SCRATCH_3);
|
|
writel(0x50000000ul, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
writel(0x04010000ul, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0x10000002ul, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0u, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0u, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
writel(0x0C000004u, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
writel(BITM_DMC_DDR_ROOT_CTL_TRIG_RD_XFER_ALL,
|
|
dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0u, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0u, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
// calculate ODT PU and PD values
|
|
stat_value = ((readl(dmc.reg + REG_DMC_DDR_SCRATCH_7) & 0x0000FFFFu) <<
|
|
16);
|
|
stat_value |= ((readl(dmc.reg + REG_DMC_DDR_SCRATCH_6) & 0xFFFF0000u) >>
|
|
16);
|
|
clk_dqs_drv_impedance = ((dmc.dmc_zqctl0_value) &
|
|
BITM_DMC_DDR_ZQ_CTL0_IMPWRDQ) >> BITP_DMC_DDR_ZQ_CTL0_IMPWRDQ;
|
|
ro_dt = ((dmc.dmc_zqctl0_value) & BITM_DMC_DDR_ZQ_CTL0_IMPRTT) >>
|
|
BITP_DMC_DDR_ZQ_CTL0_IMPRTT;
|
|
drv_pu = stat_value & 0x0000003Fu;
|
|
drv_pd = (stat_value >> 12) & 0x0000003Fu;
|
|
odt_pu = (drv_pu * clk_dqs_drv_impedance) / ro_dt;
|
|
odt_pd = (drv_pd * clk_dqs_drv_impedance) / ro_dt;
|
|
temp = ((1uL << 24) |
|
|
((drv_pd & 0x0000003Fu)) |
|
|
((odt_pd & 0x0000003Fu) << 6) |
|
|
((drv_pu & 0x0000003Fu) << 12) |
|
|
((odt_pu & 0x0000003Fu) << 18));
|
|
temp |= readl(dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_SCRATCH_2);
|
|
writel(0x0C010000u, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0x08000002u, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0u, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0u, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
writel(0x04010000u, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0x80000002u, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0u, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
writel(0u, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
#endif
|
|
}
|
|
|
|
static inline void adi_dmc_lane_reset(bool reset, uint32_t dmc_no)
|
|
{
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
u32 temp;
|
|
phys_addr_t base = (dmc_no == 0) ? REG_DMC0_BASE : REG_DMC1_BASE;
|
|
phys_addr_t ln0 = base + REG_DMC_DDR_LANE0_CTL0;
|
|
phys_addr_t ln1 = base + REG_DMC_DDR_LANE1_CTL0;
|
|
|
|
if (reset) {
|
|
temp = readl(ln0);
|
|
temp |= BITM_DMC_DDR_LANE0_CTL0_CB_RSTDLL;
|
|
writel(temp, ln0);
|
|
|
|
temp = readl(ln1);
|
|
temp |= BITM_DMC_DDR_LANE1_CTL0_CB_RSTDLL;
|
|
writel(temp, ln1);
|
|
} else {
|
|
temp = readl(ln0);
|
|
temp &= ~BITM_DMC_DDR_LANE0_CTL0_CB_RSTDLL;
|
|
writel(temp, ln0);
|
|
|
|
temp = readl(ln1);
|
|
temp &= ~BITM_DMC_DDR_LANE1_CTL0_CB_RSTDLL;
|
|
writel(temp, ln1);
|
|
}
|
|
dmcdelay(9000u);
|
|
#endif
|
|
}
|
|
|
|
void adi_dmc_reset_lanes(bool reset)
|
|
{
|
|
if (!IS_ENABLED(CONFIG_ADI_USE_DDR2)) {
|
|
if (IS_ENABLED(CONFIG_SC59X) || IS_ENABLED(CONFIG_SC59X_64)) {
|
|
if (IS_ENABLED(CONFIG_ADI_USE_DMC0))
|
|
adi_dmc_lane_reset(reset, 0);
|
|
if (IS_ENABLED(CONFIG_ADI_USE_DMC1))
|
|
adi_dmc_lane_reset(reset, 1);
|
|
}
|
|
else {
|
|
u32 temp = reset ? 0x800 : 0x0;
|
|
|
|
if (IS_ENABLED(CONFIG_ADI_USE_DMC0))
|
|
writel(temp, REG_DMC0_BASE + REG_DMC_PHY_CTL0);
|
|
if (IS_ENABLED(CONFIG_ADI_USE_DMC1))
|
|
writel(temp, REG_DMC1_BASE + REG_DMC_PHY_CTL0);
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void dmc_controller_init(void)
|
|
{
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
u32 phyphase, rd_cnt, t_EMR1, t_EMR3, t_CTL, data_cyc, temp;
|
|
#endif
|
|
|
|
/* 1. Program the DMC controller registers: DMCx_CFG, DMCx_TR0,
|
|
* DMCx_TR1, DMCx_TR2, DMCx_MR(DDR2/LPDDR)/DMCx_MR0(DDR3),
|
|
* DMCx_EMR1(DDR2)/DMCx_MR1(DDR3),
|
|
* DMCx_EMR2(DDR2)/DMCx_EMR(LPDDR)/DMCx_MR2(DDR3)
|
|
*/
|
|
writel(dmc.dmc_cfg_value, dmc.reg + REG_DMC_CFG);
|
|
writel(dmc.dmc_tr0_value, dmc.reg + REG_DMC_TR0);
|
|
writel(dmc.dmc_tr1_value, dmc.reg + REG_DMC_TR1);
|
|
writel(dmc.dmc_tr2_value, dmc.reg + REG_DMC_TR2);
|
|
writel(dmc.dmc_mr0_value, dmc.reg + REG_DMC_MR);
|
|
writel(dmc.dmc_mr1_value, dmc.reg + REG_DMC_EMR1);
|
|
writel(dmc.dmc_mr2_value, dmc.reg + REG_DMC_EMR2);
|
|
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
writel(dmc.dmc_mr3_value, dmc.reg + REG_DMC_EMR3);
|
|
writel(dmc.dmc_dllctl_value, dmc.reg + REG_DMC_DLLCTL);
|
|
dmcdelay(2000u);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
temp |= BITM_DMC_DDR_CA_CTL_SW_REFRESH;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
dmcdelay(5u);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
temp |= BITM_DMC_DDR_ROOT_CTL_SW_REFRESH |
|
|
(DMC_OFSTDCYCLE << BITP_DMC_DDR_ROOT_CTL_PIPE_OFSTDCYCLE);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
#endif
|
|
|
|
/* 2. Make sure that the REG_DMC_DT_CALIB_ADDR register is programmed
|
|
* to an unused DMC location corresponding to a burst of 16 bytes
|
|
* (by default it is the starting address of the DMC address range).
|
|
*/
|
|
#ifndef CONFIG_SC59X
|
|
writel(dmc.dmc_data_calib_add_value, dmc.reg + REG_DMC_DT_CALIB_ADDR);
|
|
#endif
|
|
/* 3. Program the DMCx_CTL register with INIT bit set to start
|
|
* the DMC initialization sequence
|
|
*/
|
|
writel(dmc.dmc_ctl_value, dmc.reg + REG_DMC_CTL);
|
|
/* 4. Wait for the DMC initialization to complete by polling
|
|
* DMCx_STAT.INITDONE bit.
|
|
*/
|
|
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
dmcdelay(722000u);
|
|
|
|
/* Add necessary delay depending on the configuration */
|
|
t_EMR1 = (dmc.dmc_mr1_value & BITM_DMC_MR1_WL) >> BITP_DMC_MR1_WL;
|
|
|
|
dmcdelay(600u);
|
|
if (t_EMR1 != 0u)
|
|
while ((readl(dmc.reg + REG_DMC_EMR1) & BITM_DMC_MR1_WL) != 0)
|
|
;
|
|
|
|
t_EMR3 = (dmc.dmc_mr3_value & BITM_DMC_EMR3_MPR) >>
|
|
BITP_DMC_EMR3_MPR;
|
|
dmcdelay(2000u);
|
|
if (t_EMR3 != 0u)
|
|
while ((readl(dmc.reg + REG_DMC_EMR3) & BITM_DMC_EMR3_MPR) != 0)
|
|
;
|
|
|
|
t_CTL = (dmc.dmc_ctl_value & BITM_DMC_CTL_RL_DQS) >> BITP_DMC_CTL_RL_DQS;
|
|
dmcdelay(600u);
|
|
if (t_CTL != 0u)
|
|
while ((readl(dmc.reg + REG_DMC_CTL) & BITM_DMC_CTL_RL_DQS) != 0)
|
|
;
|
|
#endif
|
|
|
|
/* check if DMC initialization finished*/
|
|
while ((readl(dmc.reg + REG_DMC_STAT) & BITM_DMC_STAT_INITDONE) == 0)
|
|
;
|
|
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
/* toggle DCYCLE */
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
temp |= BITM_DMC_DDR_LANE0_CTL1_COMP_DCYCLE;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
temp |= BITM_DMC_DDR_LANE1_CTL1_COMP_DCYCLE;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
|
|
dmcdelay(10u);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
temp &= (~BITM_DMC_DDR_LANE0_CTL1_COMP_DCYCLE);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
temp &= (~BITM_DMC_DDR_LANE1_CTL1_COMP_DCYCLE);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
|
|
/* toggle RSTDAT */
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL0);
|
|
temp |= BITM_DMC_DDR_LANE0_CTL0_CB_RSTDAT;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL0);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL0);
|
|
temp &= (~BITM_DMC_DDR_LANE0_CTL0_CB_RSTDAT);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL0);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL0);
|
|
temp |= BITM_DMC_DDR_LANE1_CTL0_CB_RSTDAT;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL0);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL0);
|
|
temp &= (~BITM_DMC_DDR_LANE1_CTL0_CB_RSTDAT);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL0);
|
|
|
|
dmcdelay(2500u);
|
|
|
|
/* Program phyphase*/
|
|
phyphase = (readl(dmc.reg + REG_DMC_STAT) &
|
|
BITM_DMC_STAT_PHYRDPHASE) >> BITP_DMC_STAT_PHYRDPHASE;
|
|
data_cyc = (phyphase << BITP_DMC_DLLCTL_DATACYC) &
|
|
BITM_DMC_DLLCTL_DATACYC;
|
|
rd_cnt = dmc.dmc_dllctl_value;
|
|
rd_cnt <<= BITP_DMC_DLLCTL_DLLCALRDCNT;
|
|
rd_cnt &= BITM_DMC_DLLCTL_DLLCALRDCNT;
|
|
writel(rd_cnt | data_cyc, dmc.reg + REG_DMC_DLLCTL);
|
|
writel((dmc.dmc_ctl_value & (~BITM_DMC_CTL_INIT) &
|
|
(~BITM_DMC_CTL_RL_DQS)), dmc.reg + REG_DMC_CTL);
|
|
|
|
#if DELAYTRIM
|
|
/* DQS delay trim*/
|
|
u32 stat_value, WL_code_LDQS, WL_code_UDQS;
|
|
|
|
/* For LDQS */
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL1) | (0x000000D0);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
dmcdelay(2500u);
|
|
writel(0x00400000, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0x0, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
stat_value = (readl(dmc.reg + REG_DMC_DDR_SCRATCH_STAT0) &
|
|
(0xFFFF0000)) >> 16;
|
|
WL_code_LDQS = (stat_value) & (0x0000001F);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
temp &= ~(BITM_DMC_DDR_LANE0_CTL1_BYPCODE |
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
|
|
/* If write leveling is enabled */
|
|
if ((dmc.dmc_mr1_value & BITM_DMC_MR1_WL) >> BITP_DMC_MR1_WL) {
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
temp |= (((WL_code_LDQS + LANE0_DQS_DELAY) <<
|
|
BITP_DMC_DDR_LANE0_CTL1_BYPCODE) &
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPCODE) |
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
} else {
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
temp |= (((DQS_DEFAULT_DELAY + LANE0_DQS_DELAY) <<
|
|
BITP_DMC_DDR_LANE0_CTL1_BYPCODE) &
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPCODE) |
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL1);
|
|
}
|
|
dmcdelay(2500u);
|
|
|
|
/* For UDQS */
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL1) | (0x000000D0);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
dmcdelay(2500u);
|
|
writel(0x00800000, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
dmcdelay(2500u);
|
|
writel(0x0, dmc.reg + REG_DMC_DDR_ROOT_CTL);
|
|
stat_value = (readl(dmc.reg + REG_DMC_DDR_SCRATCH_STAT1) &
|
|
(0xFFFF0000)) >> 16;
|
|
WL_code_UDQS = (stat_value) & (0x0000001F);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
temp &= ~(BITM_DMC_DDR_LANE0_CTL1_BYPCODE |
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
|
|
/* If write leveling is enabled */
|
|
if ((dmc.dmc_mr1_value & BITM_DMC_MR1_WL) >> BITP_DMC_MR1_WL) {
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
temp |= (((WL_code_UDQS + LANE1_DQS_DELAY) <<
|
|
BITP_DMC_DDR_LANE0_CTL1_BYPCODE) &
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPCODE) |
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
} else {
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
temp |= (((DQS_DEFAULT_DELAY + LANE1_DQS_DELAY) <<
|
|
BITP_DMC_DDR_LANE0_CTL1_BYPCODE) &
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPCODE) |
|
|
BITM_DMC_DDR_LANE0_CTL1_BYPDELCHAINEN;
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL1);
|
|
}
|
|
dmcdelay(2500u);
|
|
#endif
|
|
|
|
#else
|
|
/* 5. Program the DMCx_CTL.DLLCTL register with 0x948 value
|
|
* (DATACYC=9, DLLCALRDCNT=72).
|
|
*/
|
|
writel(0x00000948, dmc.reg + REG_DMC_DLLCTL);
|
|
#endif
|
|
|
|
/* 6. Workaround for anomaly#20000037 */
|
|
if (dmc.anomaly_20000037_applicable) {
|
|
/* Perform dummy read to any DMC location */
|
|
readl(0x80000000);
|
|
|
|
writel(readl(dmc.reg + REG_DMC_PHY_CTL0) | 0x1000,
|
|
dmc.reg + REG_DMC_PHY_CTL0);
|
|
/* Clear DMCx_PHY_CTL0.RESETDAT bit */
|
|
writel(readl(dmc.reg + REG_DMC_PHY_CTL0) & (~0x1000),
|
|
dmc.reg + REG_DMC_PHY_CTL0);
|
|
}
|
|
}
|
|
|
|
static inline void dmc_init(void)
|
|
{
|
|
/* PHY Calibration+Initialization */
|
|
if (!dmc.phy_init_required)
|
|
goto out;
|
|
|
|
switch (dmc.calib_mode) {
|
|
case CALIBRATION_LEGACY:
|
|
calibration_legacy();
|
|
break;
|
|
case CALIBRATION_METHOD1:
|
|
calibration_method1();
|
|
break;
|
|
case CALIBRATION_METHOD2:
|
|
calibration_method2();
|
|
break;
|
|
}
|
|
|
|
#if DQSTRIM
|
|
/* DQS duty trim */
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE0_CTL0);
|
|
temp |= ((DQSCODE) << BITP_DMC_DDR_LANE0_CTL0_BYPENB) &
|
|
(BITM_DMC_DDR_LANE1_CTL0_BYPENB |
|
|
BITM_DMC_DDR_LANE0_CTL0_BYPSELP |
|
|
BITM_DMC_DDR_LANE0_CTL0_BYPCODE);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE0_CTL0);
|
|
|
|
temp = readl(dmc.reg + REG_DMC_DDR_LANE1_CTL0);
|
|
temp |= ((DQSCODE) << BITP_DMC_DDR_LANE1_CTL0_BYPENB) &
|
|
(BITM_DMC_DDR_LANE1_CTL1_BYPCODE |
|
|
BITM_DMC_DDR_LANE1_CTL0_BYPSELP |
|
|
BITM_DMC_DDR_LANE1_CTL0_BYPCODE);
|
|
writel(temp, dmc.reg + REG_DMC_DDR_LANE1_CTL0);
|
|
#endif
|
|
|
|
#if CLKTRIM
|
|
/* Clock duty trim */
|
|
temp = readl(dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
temp |= (((CLKCODE << BITP_DMC_DDR_CA_CTL_BYPCODE1) &
|
|
BITM_DMC_DDR_CA_CTL_BYPCODE1) |
|
|
BITM_DMC_DDR_CA_CTL_BYPENB |
|
|
((CLKDIR << BITP_DMC_DDR_CA_CTL_BYPSELP) &
|
|
BITM_DMC_DDR_CA_CTL_BYPSELP));
|
|
writel(temp, dmc.reg + REG_DMC_DDR_CA_CTL);
|
|
#endif
|
|
|
|
out:
|
|
/* Controller Initialization */
|
|
dmc_controller_init();
|
|
}
|
|
|
|
static inline void __dmc_config(uint32_t dmc_no)
|
|
{
|
|
if (dmc_no == 0) {
|
|
dmc.reg = REG_DMC0_BASE;
|
|
dmc.dmc_data_calib_add_value = DMC0_DATA_CALIB_ADD;
|
|
} else if (dmc_no == 1) {
|
|
dmc.reg = REG_DMC1_BASE;
|
|
dmc.dmc_data_calib_add_value = DMC1_DATA_CALIB_ADD;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
if (IS_ENABLED(CONFIG_ADI_USE_DDR2))
|
|
dmc.ddr_mode = DDR2_MODE;
|
|
else
|
|
dmc.ddr_mode = DDR3_MODE;
|
|
|
|
dmc.phy_init_required = true;
|
|
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
dmc.anomaly_20000037_applicable = false;
|
|
dmc.dmc_dllctl_value = DMC_DLLCTL_VALUE;
|
|
dmc.calib_mode = CALIBRATION_METHOD2;
|
|
#else
|
|
dmc.anomaly_20000037_applicable = true;
|
|
dmc.calib_mode = CALIBRATION_LEGACY;
|
|
#endif
|
|
|
|
dmc.dmc_ctl_value = DMC_CTL_VALUE;
|
|
dmc.dmc_cfg_value = DMC_CFG_VALUE;
|
|
dmc.dmc_tr0_value = DMC_TR0_VALUE;
|
|
dmc.dmc_tr1_value = DMC_TR1_VALUE;
|
|
dmc.dmc_tr2_value = DMC_TR2_VALUE;
|
|
dmc.dmc_mr0_value = DMC_MR0_VALUE;
|
|
dmc.dmc_mr1_value = DMC_MR1_VALUE;
|
|
dmc.dmc_mr2_value = DMC_MR2_VALUE;
|
|
|
|
#if defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64)
|
|
dmc.dmc_mr3_value = DMC_MR3_VALUE;
|
|
dmc.dmc_zqctl0_value = DMC_ZQCTL0_VALUE;
|
|
dmc.dmc_zqctl1_value = DMC_ZQCTL1_VALUE;
|
|
dmc.dmc_zqctl2_value = DMC_ZQCTL2_VALUE;
|
|
#endif
|
|
|
|
dmc.padctl2_value = DMC_PADCTL2_VALUE;
|
|
dmc.dmc_cphyctl_value = DMC_CPHYCTL_VALUE;
|
|
|
|
/* Initialize DMC now */
|
|
dmc_init();
|
|
}
|
|
|
|
void DMC_Config(void)
|
|
{
|
|
if (IS_ENABLED(CONFIG_ADI_USE_DMC0))
|
|
__dmc_config(0);
|
|
|
|
if (IS_ENABLED(CONFIG_ADI_USE_DMC1))
|
|
__dmc_config(1);
|
|
}
|