diff --git a/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c index 4a1e1fc87c..ae94def765 100644 --- a/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c +++ b/ArmPkg/Drivers/PL34xDmc/PL341Dmc.c @@ -16,358 +16,206 @@ #include #include -// -// DMC Configuration Register Map -// -#define DMC_STATUS_REG 0x00 -#define DMC_COMMAND_REG 0x04 -#define DMC_DIRECT_CMD_REG 0x08 -#define DMC_MEMORY_CONFIG_REG 0x0C -#define DMC_REFRESH_PRD_REG 0x10 -#define DMC_CAS_LATENCY_REG 0x14 -#define DMC_WRITE_LATENCY_REG 0x18 -#define DMC_T_MRD_REG 0x1C -#define DMC_T_RAS_REG 0x20 -#define DMC_T_RC_REG 0x24 -#define DMC_T_RCD_REG 0x28 -#define DMC_T_RFC_REG 0x2C -#define DMC_T_RP_REG 0x30 -#define DMC_T_RRD_REG 0x34 -#define DMC_T_WR_REG 0x38 -#define DMC_T_WTR_REG 0x3C -#define DMC_T_XP_REG 0x40 -#define DMC_T_XSR_REG 0x44 -#define DMC_T_ESR_REG 0x48 -#define DMC_MEMORY_CFG2_REG 0x4C -#define DMC_MEMORY_CFG3_REG 0x50 -#define DMC_T_FAW_REG 0x54 - -// Returns the state of the memory controller: -#define DMC_STATUS_CONFIG 0x0 -#define DMC_STATUS_READY 0x1 -#define DMC_STATUS_PAUSED 0x2 -#define DMC_STATUS_LOWPOWER 0x3 - -// Changes the state of the memory controller: -#define DMC_COMMAND_GO 0x0 -#define DMC_COMMAND_SLEEP 0x1 -#define DMC_COMMAND_WAKEUP 0x2 -#define DMC_COMMAND_PAUSE 0x3 -#define DMC_COMMAND_CONFIGURE 0x4 -#define DMC_COMMAND_ACTIVEPAUSE 0x7 - -// Determines the command required -#define DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL 0x0 -#define DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH (0x1 << 18) -#define DMC_DIRECT_CMD_MEMCMD_MODEREG (0x2 << 18) -#define DMC_DIRECT_CMD_MEMCMD_EXTMODEREG (0x2 << 18) -#define DMC_DIRECT_CMD_MEMCMD_NOP (0x3 << 18) -#define DMC_DIRECT_CMD_MEMCMD_DPD (0x1 << 22) -#define DMC_DIRECT_CMD_BANKADDR(n) ((n & 0x3) << 16) -#define DMC_DIRECT_CMD_CHIP_ADDR(n) ((n & 0x3) << 20) - - -// -// AXI ID configuration register map -// -#define DMC_ID_0_CFG_REG 0x100 -#define DMC_ID_1_CFG_REG 0x104 -#define DMC_ID_2_CFG_REG 0x108 -#define DMC_ID_3_CFG_REG 0x10C -#define DMC_ID_4_CFG_REG 0x110 -#define DMC_ID_5_CFG_REG 0x114 -#define DMC_ID_6_CFG_REG 0x118 -#define DMC_ID_7_CFG_REG 0x11C -#define DMC_ID_8_CFG_REG 0x120 -#define DMC_ID_9_CFG_REG 0x124 -#define DMC_ID_10_CFG_REG 0x128 -#define DMC_ID_11_CFG_REG 0x12C -#define DMC_ID_12_CFG_REG 0x130 -#define DMC_ID_13_CFG_REG 0x134 -#define DMC_ID_14_CFG_REG 0x138 -#define DMC_ID_15_CFG_REG 0x13C - -// Set the QoS -#define DMC_ID_CFG_QOS_DISABLE 0 -#define DMC_ID_CFG_QOS_ENABLE 1 -#define DMC_ID_CFG_QOS_MIN 2 - - -// -// Chip configuration register map -// -#define DMC_CHIP_0_CFG_REG 0x200 -#define DMC_CHIP_1_CFG_REG 0x204 -#define DMC_CHIP_2_CFG_REG 0x208 -#define DMC_CHIP_3_CFG_REG 0x20C - -// -// User Defined Pins -// -#define DMC_USER_STATUS_REG 0x300 -#define DMC_USER_0_CFG_REG 0x304 -#define DMC_USER_1_CFG_REG 0x308 -#define DMC_FEATURE_CRTL_REG 0x30C -#define DMC_USER_2_CFG_REG 0x310 - - -// -// PHY Register Settings -// -#define TC_UIOLHNC_MASK 0x000003C0 -#define TC_UIOLHNC_SHIFT 0x6 -#define TC_UIOLHPC_MASK 0x0000003F -#define TC_UIOLHPC_SHIFT 0x2 -#define TC_UIOHOCT_MASK 0x2 -#define TC_UIOHOCT_SHIFT 0x1 -#define TC_UIOHSTOP_SHIFT 0x0 -#define TC_UIOLHXC_VALUE 0x4 - -// -// Extended Mode Register settings -// -#define DDR_EMR_OCD_MASK 0x0000380 -#define DDR_EMR_OCD_SHIFT 0x7 -#define DDR_EMR_RTT_MASK 0x00000044 // DDR2 Device RTT (ODT) settings -#define DDR_EMR_RTT_SHIFT 0x2 -#define DDR_EMR_ODS_MASK 0x00000002 // DDR2 Output Drive Strength -#define DDR_EMR_ODS_SHIFT 0x0001 -// Termination Values: -#define DDR_EMR_RTT_50 0x00000044 // DDR2 50 Ohm termination -#define DDR_EMR_RTT_75R 0x00000004 // DDR2 75 Ohm termination -#define DDR_EMR_RTT_150 0x00000040 // DDR2 150 Ohm termination -// Output Drive Strength Values: -#define DDR_EMR_ODS_FULL 0x0 // DDR2 Full Drive Strength -#define DDR_EMR_ODS_HALF 0x1 // DDR2 Half Drive Strength -// OCD values -#define DDR_EMR_OCD_DEFAULT 0x7 -#define DDR_EMR_OCD_NS 0x0 - -#define DDR_EMR_ODS_VAL DDR_EMR_ODS_FULL - - - +// Macros for writing to DDR2 controller. #define DmcWriteReg(reg,val) MmioWrite32(DmcBase + reg, val) #define DmcReadReg(reg) MmioRead32(DmcBase + reg) -// Initialize PL341 Dynamic Memory Controller -VOID PL341DmcInit(struct pl341_dmc_config *config) { - UINTN DmcBase = config->base; - UINT32 i, chip, val32; +// Macros for writing/reading to DDR2 PHY controller +#define DmcPhyWriteReg(reg,val) MmioWrite32(DmcPhyBase + reg, val) +#define DmcPhyReadReg(reg) MmioRead32(DmcPhyBase + reg) - // Set config mode - DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_CONFIGURE); +// Initialise PL341 Dynamic Memory Controller +VOID +PL341DmcInit ( + IN PL341_DMC_CONFIG *DmcConfig + ) +{ + UINTN DmcBase; + UINTN Index; + UINT32 Chip; + + DmcBase = DmcConfig->base; + + // Set config mode + DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_CONFIGURE); + + // + // Setup the QoS AXI ID bits + // + if (DmcConfig->HasQos) { + // CLCD AXIID = 000 + DmcWriteReg(DMC_ID_0_CFG_REG, DMC_ID_CFG_QOS_ENABLE | DMC_ID_CFG_QOS_MIN); + + // Default disable QoS + DmcWriteReg(DMC_ID_1_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_2_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_3_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_4_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_5_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_6_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_7_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_8_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_9_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_10_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_11_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_12_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_13_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_14_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + DmcWriteReg(DMC_ID_15_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + } + + // + // Initialise memory controlller + // + DmcWriteReg(DMC_REFRESH_PRD_REG, DmcConfig->refresh_prd); + DmcWriteReg(DMC_CAS_LATENCY_REG, DmcConfig->cas_latency); + DmcWriteReg(DMC_WRITE_LATENCY_REG, DmcConfig->write_latency); + DmcWriteReg(DMC_T_MRD_REG, DmcConfig->t_mrd); + DmcWriteReg(DMC_T_RAS_REG, DmcConfig->t_ras); + DmcWriteReg(DMC_T_RC_REG, DmcConfig->t_rc); + DmcWriteReg(DMC_T_RCD_REG, DmcConfig->t_rcd); + DmcWriteReg(DMC_T_RFC_REG, DmcConfig->t_rfc); + DmcWriteReg(DMC_T_RP_REG, DmcConfig->t_rp); + DmcWriteReg(DMC_T_RRD_REG, DmcConfig->t_rrd); + DmcWriteReg(DMC_T_WR_REG, DmcConfig->t_wr); + DmcWriteReg(DMC_T_WTR_REG, DmcConfig->t_wtr); + DmcWriteReg(DMC_T_XP_REG, DmcConfig->t_xp); + DmcWriteReg(DMC_T_XSR_REG, DmcConfig->t_xsr); + DmcWriteReg(DMC_T_ESR_REG, DmcConfig->t_esr); + DmcWriteReg(DMC_T_FAW_REG, DmcConfig->t_faw); + DmcWriteReg(DMC_T_WRLAT_DIFF, DmcConfig->t_wdata_en); + DmcWriteReg(DMC_T_RDATA_EN, DmcConfig->t_data_en); + + // + // Initialise PL341 Mem Config Registers + // + + // Set PL341 Memory Config + DmcWriteReg(DMC_MEMORY_CONFIG_REG, DmcConfig->MemoryCfg); + + // Set PL341 Memory Config 2 + DmcWriteReg(DMC_MEMORY_CFG2_REG, DmcConfig->MemoryCfg2); + + // Set PL341 Chip Select + DmcWriteReg(DMC_CHIP_0_CFG_REG, DmcConfig->ChipCfg0); + DmcWriteReg(DMC_CHIP_1_CFG_REG, DmcConfig->ChipCfg1); + DmcWriteReg(DMC_CHIP_2_CFG_REG, DmcConfig->ChipCfg2); + DmcWriteReg(DMC_CHIP_3_CFG_REG, DmcConfig->ChipCfg3); + + // Delay + for (Index = 0; Index < 10; Index++) { + DmcReadReg(DMC_STATUS_REG); + } + + // Set PL341 Memory Config 3 + DmcWriteReg(DMC_MEMORY_CFG3_REG, DmcConfig->MemoryCfg3); + + if (DmcConfig->IsUserCfg) { + // + // Set Test Chip PHY Registers via PL341 User Config Reg + // Note that user_cfgX registers are Write Only + // + // DLL Freq set = 250MHz - 266MHz + // + DmcWriteReg(DMC_USER_0_CFG_REG, DmcConfig->User0Cfg); + + // user_config2 + // ------------ + // Set defaults before calibrating the DDR2 buffer impendence + // - Disable ODT + // - Default drive strengths + DmcWriteReg(DMC_USER_2_CFG_REG, 0x40000198); // - // Setup the QoS AXI ID bits + // Auto calibrate the DDR2 buffers impendence // + while (!(DmcReadReg(DMC_USER_STATUS_REG) & 0x100)); - if (config->has_qos) { - // CLCD AXIID = 000 - DmcWriteReg(DMC_ID_0_CFG_REG, DMC_ID_CFG_QOS_ENABLE | DMC_ID_CFG_QOS_MIN); + // Set the output driven strength + DmcWriteReg(DMC_USER_2_CFG_REG, 0x40800000 | DmcConfig->User2Cfg); - // Default disable QoS - DmcWriteReg(DMC_ID_1_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_2_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_3_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_4_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_5_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_6_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_7_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_8_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_9_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_10_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_11_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_12_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_13_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_14_CFG_REG, DMC_ID_CFG_QOS_DISABLE); - DmcWriteReg(DMC_ID_15_CFG_REG, DMC_ID_CFG_QOS_DISABLE); + // + // Set PL341 Feature Control Register + // + // Disable early BRESP - use to optimise CLCD performance + DmcWriteReg(DMC_FEATURE_CRTL_REG, 0x00000001); + } + + // + // Config memories + // + for (Chip = 0; Chip < DmcConfig->MaxChip; Chip++) { + // Send nop + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_NOP); + + // Pre-charge all + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL); + + // Delay + for (Index = 0; Index < 10; Index++) { + DmcReadReg(DMC_STATUS_REG); + } + + // Set (EMR2) extended mode register 2 + DmcWriteReg(DMC_DIRECT_CMD_REG, + DMC_DIRECT_CMD_CHIP_ADDR(Chip) | + DMC_DIRECT_CMD_BANKADDR(2) | + DMC_DIRECT_CMD_MEMCMD_EXTMODEREG); + + // Set (EMR3) extended mode register 3 + DmcWriteReg(DMC_DIRECT_CMD_REG, + DMC_DIRECT_CMD_CHIP_ADDR(Chip) | + DMC_DIRECT_CMD_BANKADDR(3) | + DMC_DIRECT_CMD_MEMCMD_EXTMODEREG); + + // + // Set (EMR) Extended Mode Register + // + // Put into OCD default state + DmcWriteReg(DMC_DIRECT_CMD_REG,DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_BANKADDR(1) | DMC_DIRECT_CMD_MEMCMD_EXTMODEREG); + + // + // Set (MR) mode register - With DLL reset + // + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_EXTMODEREG | DmcConfig->ModeReg | DDR2_MR_DLL_RESET); + + // Pre-charge all + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL); + // Auto-refresh + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH); + // Auto-refresh + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH); + + // + // Set (MR) mode register - Without DLL reset + // + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | DMC_DIRECT_CMD_MEMCMD_EXTMODEREG | DmcConfig->ModeReg); + + // Delay + for (Index = 0; Index < 10; Index++) { + DmcReadReg(DMC_STATUS_REG); } // - // Initialise memory controlller + // Set (EMR) extended mode register - Enable OCD defaults // - DmcWriteReg(DMC_REFRESH_PRD_REG, config->refresh_prd); - DmcWriteReg(DMC_CAS_LATENCY_REG, config->cas_latency); - DmcWriteReg(DMC_WRITE_LATENCY_REG, config->write_latency); - DmcWriteReg(DMC_T_MRD_REG, config->t_mrd); - DmcWriteReg(DMC_T_RAS_REG, config->t_ras); - DmcWriteReg(DMC_T_RC_REG, config->t_rc); - DmcWriteReg(DMC_T_RCD_REG, config->t_rcd); - DmcWriteReg(DMC_T_RFC_REG, config->t_rfc); - DmcWriteReg(DMC_T_RP_REG, config->t_rp); - DmcWriteReg(DMC_T_RRD_REG, config->t_rrd); - DmcWriteReg(DMC_T_WR_REG, config->t_wr); - DmcWriteReg(DMC_T_WTR_REG, config->t_wtr); - DmcWriteReg(DMC_T_XP_REG, config->t_xp); - DmcWriteReg(DMC_T_XSR_REG, config->t_xsr); - DmcWriteReg(DMC_T_ESR_REG, config->t_esr); - DmcWriteReg(DMC_T_FAW_REG, config->t_faw); - - // ======================================================================= - // Initialise PL341 Mem Config Registers - // ======================================================================= - - // |====================================== - // | Set PL341 Memory Config - // |====================================== - DmcWriteReg(DMC_MEMORY_CONFIG_REG, config->memory_cfg); - - // |====================================== - // | Set PL341 Memory Config 2 - // |====================================== - DmcWriteReg(DMC_MEMORY_CFG2_REG, config->memory_cfg2); - - // |====================================== - // | Set PL341 Chip Select - // |====================================== - DmcWriteReg(DMC_CHIP_0_CFG_REG, config->chip_cfg0); - DmcWriteReg(DMC_CHIP_1_CFG_REG, config->chip_cfg1); - DmcWriteReg(DMC_CHIP_2_CFG_REG, config->chip_cfg2); - DmcWriteReg(DMC_CHIP_3_CFG_REG, config->chip_cfg3); - - // |====================================== - // | Set PL341 Memory Config 3 - // |====================================== - DmcWriteReg(DMC_MEMORY_CFG3_REG, config->memory_cfg3); - - // |======================================================== - // |Set Test Chip PHY Registers via PL341 User Config Reg - // |Note that user_cfgX registers are Write Only - // | - // |DLL Freq set = 250MHz - 266MHz - // |======================================================== - DmcWriteReg(DMC_USER_0_CFG_REG, 0x7C924924); - - // user_config2 - // ------------ - // Set defaults before calibrating the DDR2 buffer impendence - // -Disable ODT - // -Default drive strengths - DmcWriteReg(DMC_USER_2_CFG_REG, 0x40000198); - - // |======================================================= - // |Auto calibrate the DDR2 buffers impendence - // |======================================================= - val32 = DmcReadReg(DMC_USER_STATUS_REG); - while (!(val32 & 0x100)) { - val32 = DmcReadReg(DMC_USER_STATUS_REG); - } - - // Set the output driven strength - DmcWriteReg(DMC_USER_2_CFG_REG, 0x40800000 | - (TC_UIOLHXC_VALUE << TC_UIOLHNC_SHIFT) | - (TC_UIOLHXC_VALUE << TC_UIOLHPC_SHIFT) | - (0x1 << TC_UIOHOCT_SHIFT) | - (0x1 << TC_UIOHSTOP_SHIFT)); - - // |====================================== - // | Set PL341 Feature Control Register - // |====================================== - // | Disable early BRESP - use to optimise CLCD performance - DmcWriteReg(DMC_FEATURE_CRTL_REG, 0x00000001); - - //================= - // Config memories - //================= - - for (chip = 0; chip <= config-> max_chip; chip++) { - // send nop - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_NOP); - // pre-charge all - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL); - - // delay - for (i = 0; i < 10; i++) { - val32 = DmcReadReg(DMC_STATUS_REG); - } - - // set (EMR2) extended mode register 2 - DmcWriteReg(DMC_DIRECT_CMD_REG, - DMC_DIRECT_CMD_CHIP_ADDR(chip) | - DMC_DIRECT_CMD_BANKADDR(2) | - DMC_DIRECT_CMD_MEMCMD_EXTMODEREG); - // set (EMR3) extended mode register 3 - DmcWriteReg(DMC_DIRECT_CMD_REG, - DMC_DIRECT_CMD_CHIP_ADDR(chip) | - DMC_DIRECT_CMD_BANKADDR(3) | - DMC_DIRECT_CMD_MEMCMD_EXTMODEREG); - - // ================================= - // set (EMR) Extended Mode Register - // ================================== - // Put into OCD default state - DmcWriteReg(DMC_DIRECT_CMD_REG, - DMC_DIRECT_CMD_CHIP_ADDR(chip) | - DMC_DIRECT_CMD_BANKADDR(1) | - DMC_DIRECT_CMD_MEMCMD_EXTMODEREG); - - // =========================================================== - // set (MR) mode register - With DLL reset - // =========================================================== - // Burst Length = 4 (010) - // Burst Type = Seq (0) - // Latency = 4 (100) - // Test mode = Off (0) - // DLL reset = Yes (1) - // Wr Recovery = 4 (011) - // PD = Normal (0) - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00080742); - - // pre-charge all - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL); - // auto-refresh - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH); - // auto-refresh - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH); - - // delay - for (i = 0; i < 10; i++) { - val32 = DmcReadReg(DMC_STATUS_REG); - } - - // =========================================================== - // set (MR) mode register - Without DLL reset - // =========================================================== - // auto-refresh - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH); - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00080642); - - // delay - for (i = 0; i < 10; i++) { - val32 = DmcReadReg(DMC_STATUS_REG); - } - - // ====================================================== - // set (EMR) extended mode register - Enable OCD defaults - // ====================================================== - val32 = 0; //NOP - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00090000 | - (DDR_EMR_OCD_DEFAULT << DDR_EMR_OCD_SHIFT) | - DDR_EMR_RTT_75R | - (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK)); - - // delay - for (i = 0; i < 10; i++) { - val32 = DmcReadReg(DMC_STATUS_REG); - } - - // Set (EMR) extended mode register - OCD Exit - val32 = 0; //NOP - DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(chip) | 0x00090000 | - (DDR_EMR_OCD_NS << DDR_EMR_OCD_SHIFT) | - DDR_EMR_RTT_75R | - (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK)); + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | (0x00090000) | + (1 << DDR_MODESET_SHFT) | (DDR_EMR_OCD_DEFAULT << DDR_EMR_OCD_SHIFT) | DmcConfig->ExtModeReg); + // Delay + for (Index = 0; Index < 10; Index++) { + DmcReadReg(DMC_STATUS_REG); } - //---------------------------------------- - // go command - DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_GO); + // Set (EMR) extended mode register - OCD Exit + DmcWriteReg(DMC_DIRECT_CMD_REG, DMC_DIRECT_CMD_CHIP_ADDR(Chip) | (0x00090000) | + (1 << DDR_MODESET_SHFT) | (DDR_EMR_OCD_NS << DDR_EMR_OCD_SHIFT) | DmcConfig->ExtModeReg); + } + + // Move DDR2 Controller to Ready state by issueing GO command + DmcWriteReg(DMC_COMMAND_REG, DMC_COMMAND_GO); + + // wait for ready + while (!(DmcReadReg(DMC_STATUS_REG) & DMC_STATUS_READY)); - // wait for ready - val32 = DmcReadReg(DMC_STATUS_REG); - while (!(val32 & DMC_STATUS_READY)) { - val32 = DmcReadReg(DMC_STATUS_REG); - } } diff --git a/ArmPkg/Include/Drivers/PL341Dmc.h b/ArmPkg/Include/Drivers/PL341Dmc.h index 6ccc8482b5..461ec16cc2 100644 --- a/ArmPkg/Include/Drivers/PL341Dmc.h +++ b/ArmPkg/Include/Drivers/PL341Dmc.h @@ -12,38 +12,46 @@ * **/ -#ifndef PL341DMC_H_ -#define PL341DMC_H_ +#ifndef _PL341DMC_H_ +#define _PL341DMC_H_ -struct pl341_dmc_config { - UINTN base; // base address for the controller - UINTN has_qos; // has QoS registers - UINTN max_chip; // number of memory chips accessible - UINT32 refresh_prd; - UINT32 cas_latency; - UINT32 write_latency; - UINT32 t_mrd; - UINT32 t_ras; - UINT32 t_rc; - UINT32 t_rcd; - UINT32 t_rfc; - UINT32 t_rp; - UINT32 t_rrd; - UINT32 t_wr; - UINT32 t_wtr; - UINT32 t_xp; - UINT32 t_xsr; - UINT32 t_esr; - UINT32 memory_cfg; - UINT32 memory_cfg2; - UINT32 memory_cfg3; - UINT32 chip_cfg0; - UINT32 chip_cfg1; - UINT32 chip_cfg2; - UINT32 chip_cfg3; - UINT32 t_faw; -}; +typedef struct { + UINTN base; // base address for the controller + UINTN phy_ctrl_base; // DDR2 Phy control base + UINTN HasQos; // has QoS registers + UINTN MaxChip; // number of memory chips accessible + BOOLEAN IsUserCfg; + UINT32 User0Cfg; + UINT32 User2Cfg; + UINT32 refresh_prd; + UINT32 cas_latency; + UINT32 write_latency; + UINT32 t_mrd; + UINT32 t_ras; + UINT32 t_rc; + UINT32 t_rcd; + UINT32 t_rfc; + UINT32 t_rp; + UINT32 t_rrd; + UINT32 t_wr; + UINT32 t_wtr; + UINT32 t_xp; + UINT32 t_xsr; + UINT32 t_esr; + UINT32 MemoryCfg; + UINT32 MemoryCfg2; + UINT32 MemoryCfg3; + UINT32 ChipCfg0; + UINT32 ChipCfg1; + UINT32 ChipCfg2; + UINT32 ChipCfg3; + UINT32 t_faw; + UINT32 t_data_en; + UINT32 t_wdata_en; + UINT32 ModeReg; + UINT32 ExtModeReg; +} PL341_DMC_CONFIG; /* Memory config bit fields */ #define DMC_MEMORY_CONFIG_COLUMN_ADDRESS_9 0x1 @@ -76,9 +84,263 @@ struct pl341_dmc_config { #define DMC_MEMORY_CFG2_MEM_WIDTH_64 (0x2 << 6) #define DMC_MEMORY_CFG2_MEM_WIDTH_RESERVED (0x3 << 6) +// +// DMC Configuration Register Map +// +#define DMC_STATUS_REG 0x00 +#define DMC_COMMAND_REG 0x04 +#define DMC_DIRECT_CMD_REG 0x08 +#define DMC_MEMORY_CONFIG_REG 0x0C +#define DMC_REFRESH_PRD_REG 0x10 +#define DMC_CAS_LATENCY_REG 0x14 +#define DMC_WRITE_LATENCY_REG 0x18 +#define DMC_T_MRD_REG 0x1C +#define DMC_T_RAS_REG 0x20 +#define DMC_T_RC_REG 0x24 +#define DMC_T_RCD_REG 0x28 +#define DMC_T_RFC_REG 0x2C +#define DMC_T_RP_REG 0x30 +#define DMC_T_RRD_REG 0x34 +#define DMC_T_WR_REG 0x38 +#define DMC_T_WTR_REG 0x3C +#define DMC_T_XP_REG 0x40 +#define DMC_T_XSR_REG 0x44 +#define DMC_T_ESR_REG 0x48 +#define DMC_MEMORY_CFG2_REG 0x4C +#define DMC_MEMORY_CFG3_REG 0x50 +#define DMC_T_FAW_REG 0x54 +#define DMC_T_RDATA_EN 0x5C /* DFI read data enable register */ +#define DMC_T_WRLAT_DIFF 0x60 /* DFI write data enable register */ + +// Returns the state of the memory controller: +#define DMC_STATUS_CONFIG 0x0 +#define DMC_STATUS_READY 0x1 +#define DMC_STATUS_PAUSED 0x2 +#define DMC_STATUS_LOWPOWER 0x3 + +// Changes the state of the memory controller: +#define DMC_COMMAND_GO 0x0 +#define DMC_COMMAND_SLEEP 0x1 +#define DMC_COMMAND_WAKEUP 0x2 +#define DMC_COMMAND_PAUSE 0x3 +#define DMC_COMMAND_CONFIGURE 0x4 +#define DMC_COMMAND_ACTIVEPAUSE 0x7 + +// Determines the command required +#define DMC_DIRECT_CMD_MEMCMD_PRECHARGEALL 0x0 +#define DMC_DIRECT_CMD_MEMCMD_AUTOREFRESH (0x1 << 18) +#define DMC_DIRECT_CMD_MEMCMD_MODEREG (0x2 << 18) +#define DMC_DIRECT_CMD_MEMCMD_EXTMODEREG (0x2 << 18) +#define DMC_DIRECT_CMD_MEMCMD_NOP (0x3 << 18) +#define DMC_DIRECT_CMD_MEMCMD_DPD (0x1 << 22) +#define DMC_DIRECT_CMD_BANKADDR(n) ((n & 0x3) << 16) +#define DMC_DIRECT_CMD_CHIP_ADDR(n) ((n & 0x3) << 20) -VOID PL341DmcInit(struct pl341_dmc_config *config); +// +// AXI ID configuration register map +// +#define DMC_ID_0_CFG_REG 0x100 +#define DMC_ID_1_CFG_REG 0x104 +#define DMC_ID_2_CFG_REG 0x108 +#define DMC_ID_3_CFG_REG 0x10C +#define DMC_ID_4_CFG_REG 0x110 +#define DMC_ID_5_CFG_REG 0x114 +#define DMC_ID_6_CFG_REG 0x118 +#define DMC_ID_7_CFG_REG 0x11C +#define DMC_ID_8_CFG_REG 0x120 +#define DMC_ID_9_CFG_REG 0x124 +#define DMC_ID_10_CFG_REG 0x128 +#define DMC_ID_11_CFG_REG 0x12C +#define DMC_ID_12_CFG_REG 0x130 +#define DMC_ID_13_CFG_REG 0x134 +#define DMC_ID_14_CFG_REG 0x138 +#define DMC_ID_15_CFG_REG 0x13C + +// Set the QoS +#define DMC_ID_CFG_QOS_DISABLE 0 +#define DMC_ID_CFG_QOS_ENABLE 1 +#define DMC_ID_CFG_QOS_MIN 2 -#endif /* PL341DMC_H_ */ +// +// Chip configuration register map +// +#define DMC_CHIP_0_CFG_REG 0x200 +#define DMC_CHIP_1_CFG_REG 0x204 +#define DMC_CHIP_2_CFG_REG 0x208 +#define DMC_CHIP_3_CFG_REG 0x20C + +// +// User Defined Pins +// +#define DMC_USER_STATUS_REG 0x300 +#define DMC_USER_0_CFG_REG 0x304 +#define DMC_USER_1_CFG_REG 0x308 +#define DMC_FEATURE_CRTL_REG 0x30C +#define DMC_USER_2_CFG_REG 0x310 + + +// +// PHY Register Settings +// +#define PHY_PTM_DFI_CLK_RANGE 0xE00 // DDR2 PHY PTM register offset +#define PHY_PTM_IOTERM 0xE04 +#define PHY_PTM_PLL_EN 0xe0c +#define PHY_PTM_PLL_RANGE 0xe18 +#define PHY_PTM_FEEBACK_DIV 0xe1c +#define PHY_PTM_RCLK_DIV 0xe20 +#define PHY_PTM_LOCK_STATUS 0xe28 +#define PHY_PTM_INIT_DONE 0xe34 +#define PHY_PTM_ADDCOM_IOSTR_OFF 0xec8 +#define PHY_PTM_SQU_TRAINING 0xee8 +#define PHY_PTM_SQU_STAT 0xeec + +// ============================================================================== +// PIPD 40G DDR2/DDR3 PHY Register definitions +// +// Offsets from APB Base Address +// ============================================================================== +#define PHY_BYTE0_OFFSET 0x000 +#define PHY_BYTE1_OFFSET 0x200 +#define PHY_BYTE2_OFFSET 0x400 +#define PHY_BYTE3_OFFSET 0x600 + +#define PHY_BYTE0_COARSE_SQADJ_INIT 0x064 ;// Coarse squelch adjust +#define PHY_BYTE1_COARSE_SQADJ_INIT 0x264 ;// Coarse squelch adjust +#define PHY_BYTE2_COARSE_SQADJ_INIT 0x464 ;// Coarse squelch adjust +#define PHY_BYTE3_COARSE_SQADJ_INIT 0x664 ;// Coarse squelch adjust + +#define PHY_BYTE0_IOSTR_OFFSET 0x004 +#define PHY_BYTE1_IOSTR_OFFSET 0x204 +#define PHY_BYTE2_IOSTR_OFFSET 0x404 +#define PHY_BYTE3_IOSTR_OFFSET 0x604 + + +;//-------------------------------------------------------------------------- + +// DFI Clock ranges: + +#define PHY_PTM_DFI_CLK_RANGE_200MHz 0x0 +#define PHY_PTM_DFI_CLK_RANGE_201_267MHz 0x1 +#define PHY_PTM_DFI_CLK_RANGE_268_333MHz 0x2 +#define PHY_PTM_DFI_CLK_RANGE_334_400MHz 0x3 +#define PHY_PTM_DFI_CLK_RANGE_401_533MHz 0x4 +#define PHY_PTM_DFI_CLK_RANGE_534_667MHz 0x5 +#define PHY_PTM_DFI_CLK_RANGE_668_800MHz 0x6 + + + +#define PHY_PTM_DFI_CLK_RANGE_VAL PHY_PTM_DFI_CLK_RANGE_334_400MHz + +//-------------------------------------------------------------------------- + + +// PLL Range + +#define PHY_PTM_PLL_RANGE_200_400MHz 0x0 // b0 = frequency >= 200 MHz and < 400 MHz +#define PHY_PTM_PLL_RANGE_400_800MHz 0x1 // b1 = frequency >= 400 MHz. +#define PHY_PTM_FEEBACK_DIV_200_400MHz 0x0 // b0 = frequency >= 200 MHz and < 400 MHz +#define PHY_PTM_FEEBACK_DIV_400_800MHz 0x1 // b1 = frequency >= 400 MHz. +#define PHY_PTM_REFCLK_DIV_200_400MHz 0x0 +#define PHY_PTM_REFCLK_DIV_400_800MHz 0x1 + + +// PHY Reset in SCC + +#define SCC_PHY_RST_REG_OFF 0xA0 +#define SCC_REMAP_REG_OFF 0x00 +#define SCC_PHY_RST0_MASK 1 // Active LOW PHY0 reset +#define SCC_PHY_RST0_SHFT 0 // Active LOW PHY0 reset +#define SCC_PHY_RST1_MASK 0x100 // Active LOW PHY1 reset +#define SCC_PHY_RST1_SHFT 8 // Active LOW PHY1 reset + +#define TC_UIOLHNC_MASK 0x000003C0 +#define TC_UIOLHNC_SHIFT 0x6 +#define TC_UIOLHPC_MASK 0x0000003F +#define TC_UIOLHPC_SHIFT 0x2 +#define TC_UIOHOCT_MASK 0x2 +#define TC_UIOHOCT_SHIFT 0x1 +#define TC_UIOHSTOP_SHIFT 0x0 +#define TC_UIOLHXC_VALUE 0x4 + +#define PHY_PTM_SQU_TRAINING_ENABLE 0x1 +#define PHY_PTM_SQU_TRAINING_DISABLE 0x0 + + +//-------------------------------------- +// JEDEC DDR2 Device Register definitions and settings +//-------------------------------------- +#define DDR_MODESET_SHFT 14 +#define DDR_MODESET_MR 0x0 ;// Mode register +#define DDR_MODESET_EMR 0x1 ;// Extended Mode register +#define DDR_MODESET_EMR2 0x2 +#define DDR_MODESET_EMR3 0x3 + +// +// Extended Mode Register settings +// +#define DDR_EMR_OCD_MASK 0x0000380 +#define DDR_EMR_OCD_SHIFT 0x7 +#define DDR_EMR_RTT_MASK 0x00000044 // DDR2 Device RTT (ODT) settings +#define DDR_EMR_RTT_SHIFT 0x2 +#define DDR_EMR_ODS_MASK 0x00000002 // DDR2 Output Drive Strength +#define DDR_EMR_ODS_SHIFT 0x0001 + +// Termination Values: +#define DDR_EMR_RTT_50R 0x00000044 // DDR2 50 Ohm termination +#define DDR_EMR_RTT_75R 0x00000004 // DDR2 75 Ohm termination +#define DDR_EMR_RTT_150 0x00000040 // DDR2 150 Ohm termination + +// Output Drive Strength Values: +#define DDR_EMR_ODS_FULL 0x0 // DDR2 Full Drive Strength +#define DDR_EMR_ODS_HALF 0x1 // DDR2 Half Drive Strength + +// OCD values +#define DDR_EMR_OCD_DEFAULT 0x7 +#define DDR_EMR_OCD_NS 0x0 + +#define DDR_EMR_ODS_VAL DDR_EMR_ODS_FULL + +#define DDR_SDRAM_START_ADDR 0x10000000 + + +// ---------------------------------------- +// PHY IOTERM values +// ---------------------------------------- +#define PHY_PTM_IOTERM_OFF 0x0 +#define PHY_PTM_IOTERM_150R 0x1 +#define PHY_PTM_IOTERM_75R 0x2 +#define PHY_PTM_IOTERM_50R 0x3 + +#define PHY_BYTE_IOSTR_60OHM 0x0 +#define PHY_BYTE_IOSTR_40OHM 0x1 +#define PHY_BYTE_IOSTR_30OHM 0x2 +#define PHY_BYTE_IOSTR_30AOHM 0x3 + +#define DDR2_MR_BURST_LENGTH_4 (2) +#define DDR2_MR_BURST_LENGTH_8 (3) +#define DDR2_MR_DLL_RESET (1 << 8) +#define DDR2_MR_CAS_LATENCY_4 (4 << 4) +#define DDR2_MR_CAS_LATENCY_5 (5 << 4) +#define DDR2_MR_CAS_LATENCY_6 (6 << 4) +#define DDR2_MR_WR_CYCLES_2 (1 << 9) +#define DDR2_MR_WR_CYCLES_3 (2 << 9) +#define DDR2_MR_WR_CYCLES_4 (3 << 9) +#define DDR2_MR_WR_CYCLES_5 (4 << 9) +#define DDR2_MR_WR_CYCLES_6 (5 << 9) + + +VOID PL341DmcInit ( + IN PL341_DMC_CONFIG *config + ); + +VOID PL341DmcPhyInit ( + IN UINTN DmcPhyBase + ); + +VOID PL341DmcTrainPHY ( + IN UINTN DmcPhyBase + ); + +#endif /* _PL341DMC_H_ */ diff --git a/ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibCTA9x4/CTA9x4.c b/ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibCTA9x4/CTA9x4.c index b8d1ff0f72..c2783bbca2 100644 --- a/ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibCTA9x4/CTA9x4.c +++ b/ArmPlatformPkg/ArmVExpressPkg/Library/ArmVExpressLibCTA9x4/CTA9x4.c @@ -25,31 +25,38 @@ #define SerialPrint(txt) SerialPortWrite (txt, AsciiStrLen(txt)+1); // DDR2 timings -struct pl341_dmc_config ddr_timings = { - .base = ARM_VE_DMC_BASE, - .has_qos = 1, - .refresh_prd = 0x3D0, - .cas_latency = 0x8, - .write_latency = 0x3, - .t_mrd = 0x2, - .t_ras = 0xA, - .t_rc = 0xE, - .t_rcd = 0x104, - .t_rfc = 0x2f32, - .t_rp = 0x14, - .t_rrd = 0x2, - .t_wr = 0x4, - .t_wtr = 0x2, - .t_xp = 0x2, - .t_xsr = 0xC8, - .t_esr = 0x14, - .memory_cfg = DMC_MEMORY_CONFIG_ACTIVE_CHIP_1 | DMC_MEMORY_CONFIG_BURST_4 | - DMC_MEMORY_CONFIG_ROW_ADDRESS_15 | DMC_MEMORY_CONFIG_COLUMN_ADDRESS_10, - .memory_cfg2 = DMC_MEMORY_CFG2_DQM_INIT | DMC_MEMORY_CFG2_CKE_INIT | - DMC_MEMORY_CFG2_BANK_BITS_3 | DMC_MEMORY_CFG2_MEM_WIDTH_32, - .memory_cfg3 = 0x00000001, - .chip_cfg0 = 0x00010000, - .t_faw = 0x00000A0D, +PL341_DMC_CONFIG DDRTimings = { + .base = ARM_VE_DMC_BASE, + .phy_ctrl_base = 0x0, //There is no DDR2 PHY controller on CTA9 test chip + .MaxChip = 1, + .IsUserCfg = TRUE, + .User0Cfg = 0x7C924924, + .User2Cfg = (TC_UIOLHXC_VALUE << TC_UIOLHNC_SHIFT) | (TC_UIOLHXC_VALUE << TC_UIOLHPC_SHIFT) | (0x1 << TC_UIOHOCT_SHIFT) | (0x1 << TC_UIOHSTOP_SHIFT), + .HasQos = TRUE, + .refresh_prd = 0x3D0, + .cas_latency = 0x8, + .write_latency = 0x3, + .t_mrd = 0x2, + .t_ras = 0xA, + .t_rc = 0xE, + .t_rcd = 0x104, + .t_rfc = 0x2f32, + .t_rp = 0x14, + .t_rrd = 0x2, + .t_wr = 0x4, + .t_wtr = 0x2, + .t_xp = 0x2, + .t_xsr = 0xC8, + .t_esr = 0x14, + .MemoryCfg = DMC_MEMORY_CONFIG_ACTIVE_CHIP_1 | DMC_MEMORY_CONFIG_BURST_4 | + DMC_MEMORY_CONFIG_ROW_ADDRESS_15 | DMC_MEMORY_CONFIG_COLUMN_ADDRESS_10, + .MemoryCfg2 = DMC_MEMORY_CFG2_DQM_INIT | DMC_MEMORY_CFG2_CKE_INIT | + DMC_MEMORY_CFG2_BANK_BITS_3 | DMC_MEMORY_CFG2_MEM_WIDTH_32, + .MemoryCfg3 = 0x00000001, + .ChipCfg0 = 0x00010000, + .t_faw = 0x00000A0D, + .ModeReg = DDR2_MR_BURST_LENGTH_4 | DDR2_MR_CAS_LATENCY_4 | DDR2_MR_WR_CYCLES_4, + .ExtModeReg = DDR_EMR_RTT_50R | (DDR_EMR_ODS_VAL << DDR_EMR_ODS_MASK), }; /** @@ -219,6 +226,6 @@ ArmPlatformInitializeSystemMemory ( VOID ) { - PL341DmcInit(&ddr_timings); + PL341DmcInit(&DDRTimings); PL301AxiInit(ARM_VE_FAXI_BASE); }