From fae82c8f83b278c81ad707a133bb2c11bcd12276 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:12 +0200 Subject: phy: marvell: a3700: Change return type of macro MVEBU_REG All the calls to reg_set and friends have to cast the first argument to void __iomem *. Lets change the return type of the MVEBU_REG macro instead. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 206 ++++++++++++++++--------------------- drivers/phy/marvell/comphy_a3700.h | 8 +- 2 files changed, 96 insertions(+), 118 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index bb8d3b2e34..71fd8dcbdf 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -140,78 +140,72 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) /* * 1. Enable max PLL. */ - reg_set16((void __iomem *)LANE_CFG1_ADDR(PCIE), - bf_use_max_pll_rate, 0); + reg_set16(LANE_CFG1_ADDR(PCIE), bf_use_max_pll_rate, 0); /* * 2. Select 20 bit SERDES interface. */ - reg_set16((void __iomem *)GLOB_CLK_SRC_LO_ADDR(PCIE), - bf_cfg_sel_20b, 0); + reg_set16(GLOB_CLK_SRC_LO_ADDR(PCIE), bf_cfg_sel_20b, 0); /* * 3. Force to use reg setting for PCIe mode */ - reg_set16((void __iomem *)MISC_REG1_ADDR(PCIE), - bf_sel_bits_pcie_force, 0); + reg_set16(MISC_REG1_ADDR(PCIE), bf_sel_bits_pcie_force, 0); /* * 4. Change RX wait */ - reg_set16((void __iomem *)PWR_MGM_TIM1_ADDR(PCIE), 0x10C, 0xFFFF); + reg_set16(PWR_MGM_TIM1_ADDR(PCIE), 0x10C, 0xFFFF); /* * 5. Enable idle sync */ - reg_set16((void __iomem *)UNIT_CTRL_ADDR(PCIE), - 0x60 | rb_idle_sync_en, 0xFFFF); + reg_set16(UNIT_CTRL_ADDR(PCIE), 0x60 | rb_idle_sync_en, 0xFFFF); /* * 6. Enable the output of 100M/125M/500M clock */ - reg_set16((void __iomem *)MISC_REG0_ADDR(PCIE), + reg_set16(MISC_REG0_ADDR(PCIE), 0xA00D | rb_clk500m_en | rb_clk100m_125m_en, 0xFFFF); /* * 7. Enable TX */ - reg_set((void __iomem *)PHY_REF_CLK_ADDR, 0x1342, 0xFFFFFFFF); + reg_set(PHY_REF_CLK_ADDR, 0x1342, 0xFFFFFFFF); /* * 8. Check crystal jumper setting and program the Power and PLL * Control accordingly */ if (get_ref_clk() == 40) { - reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(PCIE), + reg_set16(PWR_PLL_CTRL_ADDR(PCIE), 0xFC63, 0xFFFF); /* 40 MHz */ } else { - reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(PCIE), + reg_set16(PWR_PLL_CTRL_ADDR(PCIE), 0xFC62, 0xFFFF); /* 25 MHz */ } /* * 9. Override Speed_PLL value and use MAC PLL */ - reg_set16((void __iomem *)KVCO_CAL_CTRL_ADDR(PCIE), - 0x0040 | rb_use_max_pll_rate, 0xFFFF); + reg_set16(KVCO_CAL_CTRL_ADDR(PCIE), 0x0040 | rb_use_max_pll_rate, + 0xFFFF); /* * 10. Check the Polarity invert bit */ if (invert & PHY_POLARITY_TXD_INVERT) { - reg_set16((void __iomem *)SYNC_PATTERN_ADDR(PCIE), - phy_txd_inv, 0); + reg_set16(SYNC_PATTERN_ADDR(PCIE), phy_txd_inv, 0); } if (invert & PHY_POLARITY_RXD_INVERT) { - reg_set16((void __iomem *)SYNC_PATTERN_ADDR(PCIE), - phy_rxd_inv, 0); + reg_set16(SYNC_PATTERN_ADDR(PCIE), phy_rxd_inv, 0); } /* * 11. Release SW reset */ - reg_set16((void __iomem *)GLOB_PHY_CTRL0_ADDR(PCIE), + reg_set16(GLOB_PHY_CTRL0_ADDR(PCIE), rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32, bf_soft_rst | bf_mode_refdiv); @@ -219,11 +213,11 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) udelay(PLL_SET_DELAY_US); /* Assert PCLK enabled */ - ret = comphy_poll_reg((void *)LANE_STAT1_ADDR(PCIE), /* address */ - rb_txdclk_pclk_en, /* value */ - rb_txdclk_pclk_en, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ - POLL_16B_REG); /* 16bit */ + ret = comphy_poll_reg(LANE_STAT1_ADDR(PCIE), /* address */ + rb_txdclk_pclk_en, /* value */ + rb_txdclk_pclk_en, /* mask */ + PLL_LOCK_TIMEOUT, /* timeout */ + POLL_16B_REG); /* 16bit */ if (ret == 0) printf("Failed to lock PCIe PLL\n"); @@ -247,57 +241,53 @@ static int comphy_sata_power_up(void) /* * 0. Swap SATA TX lines */ - reg_set((void __iomem *)rh_vsreg_addr, - vphy_sync_pattern_reg, 0xFFFFFFFF); - reg_set((void __iomem *)rh_vsreg_data, bs_txd_inv, bs_txd_inv); + reg_set(rh_vsreg_addr, vphy_sync_pattern_reg, 0xFFFFFFFF); + reg_set(rh_vsreg_data, bs_txd_inv, bs_txd_inv); /* * 1. Select 40-bit data width width */ - reg_set((void __iomem *)rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF); - reg_set((void __iomem *)rh_vsreg_data, 0x800, bs_phyintf_40bit); + reg_set(rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF); + reg_set(rh_vsreg_data, 0x800, bs_phyintf_40bit); /* * 2. Select reference clock and PHY mode (SATA) */ - reg_set((void __iomem *)rh_vsreg_addr, vphy_power_reg0, 0xFFFFFFFF); + reg_set(rh_vsreg_addr, vphy_power_reg0, 0xFFFFFFFF); if (get_ref_clk() == 40) { - reg_set((void __iomem *)rh_vsreg_data, - 0x3, 0x00FF); /* 40 MHz */ + reg_set(rh_vsreg_data, 0x3, 0x00FF); /* 40 MHz */ } else { - reg_set((void __iomem *)rh_vsreg_data, - 0x1, 0x00FF); /* 25 MHz */ + reg_set(rh_vsreg_data, 0x1, 0x00FF); /* 25 MHz */ } /* * 3. Use maximum PLL rate (no power save) */ - reg_set((void __iomem *)rh_vsreg_addr, vphy_calctl_reg, 0xFFFFFFFF); - reg_set((void __iomem *)rh_vsreg_data, - bs_max_pll_rate, bs_max_pll_rate); + reg_set(rh_vsreg_addr, vphy_calctl_reg, 0xFFFFFFFF); + reg_set(rh_vsreg_data, bs_max_pll_rate, bs_max_pll_rate); /* * 4. Reset reserved bit (??) */ - reg_set((void __iomem *)rh_vsreg_addr, vphy_reserve_reg, 0xFFFFFFFF); - reg_set((void __iomem *)rh_vsreg_data, 0, bs_phyctrl_frm_pin); + reg_set(rh_vsreg_addr, vphy_reserve_reg, 0xFFFFFFFF); + reg_set(rh_vsreg_data, 0, bs_phyctrl_frm_pin); /* * 5. Set vendor-specific configuration (??) */ - reg_set((void __iomem *)rh_vs0_a, vsata_ctrl_reg, 0xFFFFFFFF); - reg_set((void __iomem *)rh_vs0_d, bs_phy_pu_pll, bs_phy_pu_pll); + reg_set(rh_vs0_a, vsata_ctrl_reg, 0xFFFFFFFF); + reg_set(rh_vs0_d, bs_phy_pu_pll, bs_phy_pu_pll); /* Wait for > 55 us to allow PLL be enabled */ udelay(PLL_SET_DELAY_US); /* Assert SATA PLL enabled */ - reg_set((void __iomem *)rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF); - ret = comphy_poll_reg((void *)rh_vsreg_data, /* address */ - bs_pll_ready_tx, /* value */ - bs_pll_ready_tx, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ - POLL_32B_REG); /* 32bit */ + reg_set(rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF); + ret = comphy_poll_reg(rh_vsreg_data, /* address */ + bs_pll_ready_tx, /* value */ + bs_pll_ready_tx, /* mask */ + PLL_LOCK_TIMEOUT, /* timeout */ + POLL_32B_REG); /* 32bit */ if (ret == 0) printf("Failed to lock SATA PLL\n"); @@ -320,19 +310,18 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) /* * 1. Power up OTG module */ - reg_set((void __iomem *)USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0); + reg_set(USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0); /* * 2. Set counter for 100us pulse in USB3 Host and Device * restore default burst size limit (Reference Clock 31:24) */ - reg_set((void __iomem *)USB3_CTRPUL_VAL_REG, - 0x8 << 24, rb_usb3_ctr_100ns); + reg_set(USB3_CTRPUL_VAL_REG, 0x8 << 24, rb_usb3_ctr_100ns); /* 0xd005c300 = 0x1001 */ /* set PRD_TXDEEMPH (3.5db de-emph) */ - reg_set16((void __iomem *)LANE_CFG0_ADDR(USB3), 0x1, 0xFF); + reg_set16(LANE_CFG0_ADDR(USB3), 0x1, 0xFF); /* * unset BIT0: set Tx Electrical Idle Mode: Transmitter is in @@ -340,91 +329,82 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) */ /* unset BIT4: set G2 Tx Datapath with no Delayed Latency */ /* unset BIT6: set Tx Detect Rx Mode at LoZ mode */ - reg_set16((void __iomem *)LANE_CFG1_ADDR(USB3), 0x0, 0xFFFF); + reg_set16(LANE_CFG1_ADDR(USB3), 0x0, 0xFFFF); /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */ - reg_set16((void __iomem *)LANE_CFG4_ADDR(USB3), - bf_spread_spectrum_clock_en, 0x80); + reg_set16(LANE_CFG4_ADDR(USB3), bf_spread_spectrum_clock_en, 0x80); /* * set Override Margining Controls From the MAC: Use margining signals * from lane configuration */ - reg_set16((void __iomem *)TEST_MODE_CTRL_ADDR(USB3), - rb_mode_margin_override, 0xFFFF); + reg_set16(TEST_MODE_CTRL_ADDR(USB3), rb_mode_margin_override, 0xFFFF); /* set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles */ /* set Mode Clock Source = PCLK is generated from REFCLK */ - reg_set16((void __iomem *)GLOB_CLK_SRC_LO_ADDR(USB3), 0x0, 0xFF); + reg_set16(GLOB_CLK_SRC_LO_ADDR(USB3), 0x0, 0xFF); /* set G2 Spread Spectrum Clock Amplitude at 4K */ - reg_set16((void __iomem *)GEN2_SETTING_2_ADDR(USB3), g2_tx_ssc_amp, - 0xF000); + reg_set16(GEN2_SETTING_2_ADDR(USB3), g2_tx_ssc_amp, 0xF000); /* * unset G3 Spread Spectrum Clock Amplitude & set G3 TX and RX Register * Master Current Select */ - reg_set16((void __iomem *)GEN2_SETTING_3_ADDR(USB3), 0x0, 0xFFFF); + reg_set16(GEN2_SETTING_3_ADDR(USB3), 0x0, 0xFFFF); /* * 3. Check crystal jumper setting and program the Power and PLL * Control accordingly */ if (get_ref_clk() == 40) { - reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(USB3), 0xFCA3, - 0xFFFF); /* 40 MHz */ + reg_set16(PWR_PLL_CTRL_ADDR(USB3), 0xFCA3, 0xFFFF); /* 40 MHz */ } else { - reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(USB3), 0xFCA2, - 0xFFFF); /* 25 MHz */ + reg_set16(PWR_PLL_CTRL_ADDR(USB3), 0xFCA2, 0xFFFF); /* 25 MHz */ } /* * 4. Change RX wait */ - reg_set16((void __iomem *)PWR_MGM_TIM1_ADDR(USB3), 0x10C, 0xFFFF); + reg_set16(PWR_MGM_TIM1_ADDR(USB3), 0x10C, 0xFFFF); /* * 5. Enable idle sync */ - reg_set16((void __iomem *)UNIT_CTRL_ADDR(USB3), 0x60 | rb_idle_sync_en, - 0xFFFF); + reg_set16(UNIT_CTRL_ADDR(USB3), 0x60 | rb_idle_sync_en, 0xFFFF); /* * 6. Enable the output of 500M clock */ - reg_set16((void __iomem *)MISC_REG0_ADDR(USB3), 0xA00D | rb_clk500m_en, - 0xFFFF); + reg_set16(MISC_REG0_ADDR(USB3), 0xA00D | rb_clk500m_en, 0xFFFF); /* * 7. Set 20-bit data width */ - reg_set16((void __iomem *)DIG_LB_EN_ADDR(USB3), 0x0400, 0xFFFF); + reg_set16(DIG_LB_EN_ADDR(USB3), 0x0400, 0xFFFF); /* * 8. Override Speed_PLL value and use MAC PLL */ - reg_set16((void __iomem *)KVCO_CAL_CTRL_ADDR(USB3), - 0x0040 | rb_use_max_pll_rate, 0xFFFF); + reg_set16(KVCO_CAL_CTRL_ADDR(USB3), 0x0040 | rb_use_max_pll_rate, + 0xFFFF); /* * 9. Check the Polarity invert bit */ if (invert & PHY_POLARITY_TXD_INVERT) { - reg_set16((void __iomem *)SYNC_PATTERN_ADDR(USB3), - phy_txd_inv, 0); + reg_set16(SYNC_PATTERN_ADDR(USB3), phy_txd_inv, 0); } if (invert & PHY_POLARITY_RXD_INVERT) { - reg_set16((void __iomem *)SYNC_PATTERN_ADDR(USB3), - phy_rxd_inv, 0); + reg_set16(SYNC_PATTERN_ADDR(USB3), phy_rxd_inv, 0); } /* * 10. Release SW reset */ - reg_set16((void __iomem *)GLOB_PHY_CTRL0_ADDR(USB3), + reg_set16(GLOB_PHY_CTRL0_ADDR(USB3), rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 | 0x20, 0xFFFF); @@ -432,11 +412,11 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) udelay(PLL_SET_DELAY_US); /* Assert PCLK enabled */ - ret = comphy_poll_reg((void *)LANE_STAT1_ADDR(USB3), /* address */ - rb_txdclk_pclk_en, /* value */ - rb_txdclk_pclk_en, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ - POLL_16B_REG); /* 16bit */ + ret = comphy_poll_reg(LANE_STAT1_ADDR(USB3), /* address */ + rb_txdclk_pclk_en, /* value */ + rb_txdclk_pclk_en, /* mask */ + PLL_LOCK_TIMEOUT, /* timeout */ + POLL_16B_REG); /* 16bit */ if (ret == 0) printf("Failed to lock USB3 PLL\n"); @@ -454,7 +434,7 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) * INT_MODE=ID in order to avoid unexpected * behaviour or both interrupts together */ - reg_set((void __iomem *)USB32_CTRL_BASE, + reg_set(USB32_CTRL_BASE, usb32_ctrl_id_mode | usb32_ctrl_int_mode, usb32_ctrl_id_mode | usb32_ctrl_soft_id | usb32_ctrl_int_mode); @@ -488,32 +468,32 @@ static int comphy_usb2_power_up(u8 usb32) * See "PLL Settings for Typical REFCLK" table */ if (get_ref_clk() == 25) { - reg_set((void __iomem *)USB2_PHY_BASE(usb32), - 5 | (96 << 16), 0x3F | (0xFF << 16) | (0x3 << 28)); + reg_set(USB2_PHY_BASE(usb32), 5 | (96 << 16), + 0x3F | (0xFF << 16) | (0x3 << 28)); } /* * 1. PHY pull up and disable USB2 suspend */ - reg_set((void __iomem *)USB2_PHY_CTRL_ADDR(usb32), + reg_set(USB2_PHY_CTRL_ADDR(usb32), RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU(usb32), 0); if (usb32 != 0) { /* * 2. Power up OTG module */ - reg_set((void __iomem *)USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0); + reg_set(USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0); /* * 3. Configure PHY charger detection */ - reg_set((void __iomem *)USB2_PHY_CHRGR_DET_ADDR, 0, + reg_set(USB2_PHY_CHRGR_DET_ADDR, 0, rb_cdp_en | rb_dcp_en | rb_pd_en | rb_cdp_dm_auto | rb_enswitch_dp | rb_enswitch_dm | rb_pu_chrg_dtc); } /* Assert PLL calibration done */ - ret = comphy_poll_reg((void *)USB2_PHY_CAL_CTRL_ADDR(usb32), + ret = comphy_poll_reg(USB2_PHY_CAL_CTRL_ADDR(usb32), rb_usb2phy_pllcal_done, /* value */ rb_usb2phy_pllcal_done, /* mask */ PLL_LOCK_TIMEOUT, /* timeout */ @@ -522,7 +502,7 @@ static int comphy_usb2_power_up(u8 usb32) printf("Failed to end USB2 PLL calibration\n"); /* Assert impedance calibration done */ - ret = comphy_poll_reg((void *)USB2_PHY_CAL_CTRL_ADDR(usb32), + ret = comphy_poll_reg(USB2_PHY_CAL_CTRL_ADDR(usb32), rb_usb2phy_impcal_done, /* value */ rb_usb2phy_impcal_done, /* mask */ PLL_LOCK_TIMEOUT, /* timeout */ @@ -531,7 +511,7 @@ static int comphy_usb2_power_up(u8 usb32) printf("Failed to end USB2 impedance calibration\n"); /* Assert squetch calibration done */ - ret = comphy_poll_reg((void *)USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32), + ret = comphy_poll_reg(USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32), rb_usb2phy_sqcal_done, /* value */ rb_usb2phy_sqcal_done, /* mask */ PLL_LOCK_TIMEOUT, /* timeout */ @@ -540,7 +520,7 @@ static int comphy_usb2_power_up(u8 usb32) printf("Failed to end USB2 unknown calibration\n"); /* Assert PLL is ready */ - ret = comphy_poll_reg((void *)USB2_PHY_PLL_CTRL0_ADDR(usb32), + ret = comphy_poll_reg(USB2_PHY_PLL_CTRL0_ADDR(usb32), rb_usb2phy_pll_ready, /* value */ rb_usb2phy_pll_ready, /* mask */ PLL_LOCK_TIMEOUT, /* timeout */ @@ -566,35 +546,34 @@ static int comphy_emmc_power_up(void) /* * 1. Bus power ON, Bus voltage 1.8V */ - reg_set((void __iomem *)SDIO_HOST_CTRL1_ADDR, 0xB00, 0xF00); + reg_set(SDIO_HOST_CTRL1_ADDR, 0xB00, 0xF00); /* * 2. Set FIFO parameters */ - reg_set((void __iomem *)SDIO_SDHC_FIFO_ADDR, 0x315, 0xFFFFFFFF); + reg_set(SDIO_SDHC_FIFO_ADDR, 0x315, 0xFFFFFFFF); /* * 3. Set Capabilities 1_2 */ - reg_set((void __iomem *)SDIO_CAP_12_ADDR, 0x25FAC8B2, 0xFFFFFFFF); + reg_set(SDIO_CAP_12_ADDR, 0x25FAC8B2, 0xFFFFFFFF); /* * 4. Set Endian */ - reg_set((void __iomem *)SDIO_ENDIAN_ADDR, 0x00c00000, 0); + reg_set(SDIO_ENDIAN_ADDR, 0x00c00000, 0); /* * 4. Init PHY */ - reg_set((void __iomem *)SDIO_PHY_TIMING_ADDR, 0x80000000, 0x80000000); - reg_set((void __iomem *)SDIO_PHY_PAD_CTRL0_ADDR, 0x50000000, - 0xF0000000); + reg_set(SDIO_PHY_TIMING_ADDR, 0x80000000, 0x80000000); + reg_set(SDIO_PHY_PAD_CTRL0_ADDR, 0x50000000, 0xF0000000); /* * 5. DLL reset */ - reg_set((void __iomem *)SDIO_DLL_RST_ADDR, 0xFFFEFFFF, 0); - reg_set((void __iomem *)SDIO_DLL_RST_ADDR, 0x00010000, 0); + reg_set(SDIO_DLL_RST_ADDR, 0xFFFEFFFF, 0); + reg_set(SDIO_DLL_RST_ADDR, 0x00010000, 0); debug_exit(); @@ -649,7 +628,7 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) /* * 1. Configure PHY to SATA/SAS mode by setting pin PIN_PIPE_SEL=0 */ - reg_set((void __iomem *)COMPHY_SEL_ADDR, 0, rf_compy_select(lane)); + reg_set(COMPHY_SEL_ADDR, 0, rf_compy_select(lane)); /* * 2. Reset PHY by setting PHY input port PIN_RESET=1. @@ -657,7 +636,7 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) * PHY TXP/TXN output to idle state during PHY initialization * 4. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0. */ - reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), + reg_set(COMPHY_PHY_CFG1_ADDR(lane), rb_pin_reset_comphy | rb_pin_tx_idle | rb_pin_pu_iveref, rb_pin_reset_core | rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx); @@ -665,21 +644,20 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) /* * 5. Release reset to the PHY by setting PIN_RESET=0. */ - reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), - 0, rb_pin_reset_comphy); + reg_set(COMPHY_PHY_CFG1_ADDR(lane), 0, rb_pin_reset_comphy); /* * 7. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide * COMPHY bit rate */ if (speed == PHY_SPEED_3_125G) { /* 3.125 GHz */ - reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), + reg_set(COMPHY_PHY_CFG1_ADDR(lane), (0x8 << rf_gen_rx_sel_shift) | (0x8 << rf_gen_tx_sel_shift), rf_gen_rx_select | rf_gen_tx_select); } else if (speed == PHY_SPEED_1_25G) { /* 1.25 GHz */ - reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), + reg_set(COMPHY_PHY_CFG1_ADDR(lane), (0x6 << rf_gen_rx_sel_shift) | (0x6 << rf_gen_tx_sel_shift), rf_gen_rx_select | rf_gen_tx_select); @@ -784,7 +762,7 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) * programming should be done before PIN_PU_PLL=1. There should be * no register programming for normal PHY operation from this point. */ - reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), + reg_set(COMPHY_PHY_CFG1_ADDR(lane), rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx, rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx); @@ -792,7 +770,7 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) * 20. Wait for PHY power up sequence to finish by checking output ports * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1. */ - ret = comphy_poll_reg((void *)COMPHY_PHY_STAT1_ADDR(lane), /* address */ + ret = comphy_poll_reg(COMPHY_PHY_STAT1_ADDR(lane), /* address */ rb_pll_ready_tx | rb_pll_ready_rx, /* value */ rb_pll_ready_tx | rb_pll_ready_rx, /* mask */ PLL_LOCK_TIMEOUT, /* timeout */ @@ -803,8 +781,7 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) /* * 21. Set COMPHY input port PIN_TX_IDLE=0 */ - reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), - 0x0, rb_pin_tx_idle); + reg_set(COMPHY_PHY_CFG1_ADDR(lane), 0x0, rb_pin_tx_idle); /* * 22. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1. @@ -814,10 +791,9 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) * PIN_RX_INIT_DONE= 1. * Please refer to RX initialization part for details. */ - reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), rb_phy_rx_init, - 0x0); + reg_set(COMPHY_PHY_CFG1_ADDR(lane), rb_phy_rx_init, 0x0); - ret = comphy_poll_reg((void *)COMPHY_PHY_STAT1_ADDR(lane), /* address */ + ret = comphy_poll_reg(COMPHY_PHY_STAT1_ADDR(lane), /* address */ rb_rx_init_done, /* value */ rb_rx_init_done, /* mask */ PLL_LOCK_TIMEOUT, /* timeout */ diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index 322fc371f1..d41a1aa516 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -9,7 +9,8 @@ #include "comphy.h" #include "comphy_hpipe.h" -#define MVEBU_REG(offs) ((uintptr_t)MVEBU_REGISTER(offs)) +#define MVEBU_REG(offs) \ + ((void __iomem *)(ulong)MVEBU_REGISTER(offs)) #define DEFAULT_REFCLK_MHZ 25 #define PLL_SET_DELAY_US 600 @@ -60,11 +61,12 @@ #define USB3PHY_SHFT 2 #define SGMIIPHY_BASE(l) (l == 1 ? USB3PHY_BASE : PCIEPHY_BASE) -#define SGMIIPHY_ADDR(l, a) (((a & 0x00007FF) * 2) | SGMIIPHY_BASE(l)) +#define SGMIIPHY_ADDR(l, a) \ + ((void __iomem *)(((a & 0x00007FF) * 2) + SGMIIPHY_BASE(l))) #define phy_read16(l, a) read16((void __iomem *)SGMIIPHY_ADDR(l, a)) #define phy_write16(l, a, data, mask) \ - reg_set16((void __iomem *)SGMIIPHY_ADDR(l, a), data, mask) + reg_set16(SGMIIPHY_ADDR(l, a), data, mask) /* units */ #define PCIE 1 -- cgit From 63cfff9fdeced543eb41093b0a143b4ba03cb0e1 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:13 +0200 Subject: phy: marvell: a3700: Use reg_set16 instead of phy_write16 The macro phy_write16 is not used by the rest of the code, phy_read16 is not used at all. We also change the macro SGMIIPHY_ADDR to a static inline function. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 25 ++++++++++++++----------- drivers/phy/marvell/comphy_a3700.h | 15 ++++++++------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 71fd8dcbdf..3d913f4342 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -610,7 +610,7 @@ static void comphy_sgmii_phy_init(u32 lane, u32 speed) val = sgmii_phy_init[addr]; } - phy_write16(lane, addr, val, 0xFFFF); + reg_set16(sgmiiphy_addr(lane, addr), val, 0xFFFF); } } @@ -673,26 +673,26 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) mdelay(10); /* 9. Program COMPHY register PHY_MODE */ - phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR, - PHY_MODE_SGMII << rf_phy_mode_shift, rf_phy_mode_mask); + reg_set16(sgmiiphy_addr(lane, PHY_PWR_PLL_CTRL_ADDR), + PHY_MODE_SGMII << rf_phy_mode_shift, rf_phy_mode_mask); /* * 10. Set COMPHY register REFCLK_SEL to select the correct REFCLK * source */ - phy_write16(lane, PHY_MISC_REG0_ADDR, 0, rb_ref_clk_sel); + reg_set16(sgmiiphy_addr(lane, PHY_MISC_REG0_ADDR), 0, rb_ref_clk_sel); /* * 11. Set correct reference clock frequency in COMPHY register * REF_FREF_SEL. */ if (get_ref_clk() == 40) { - phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR, - 0x4 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask); + reg_set16(sgmiiphy_addr(lane, PHY_PWR_PLL_CTRL_ADDR), + 0x4 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask); } else { /* 25MHz */ - phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR, - 0x1 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask); + reg_set16(sgmiiphy_addr(lane, PHY_PWR_PLL_CTRL_ADDR), + 0x1 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask); } /* 12. Program COMPHY register PHY_GEN_MAX[1:0] */ @@ -708,7 +708,8 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) * bus width */ /* 10bit */ - phy_write16(lane, PHY_DIG_LB_EN_ADDR, 0, rf_data_width_mask); + reg_set16(sgmiiphy_addr(lane, PHY_DIG_LB_EN_ADDR), 0, + rf_data_width_mask); /* * 14. As long as DFE function needs to be enabled in any mode, @@ -751,10 +752,12 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) * 18. Check the PHY Polarity invert bit */ if (invert & PHY_POLARITY_TXD_INVERT) - phy_write16(lane, PHY_SYNC_PATTERN_ADDR, phy_txd_inv, 0); + reg_set16(sgmiiphy_addr(lane, PHY_SYNC_PATTERN_ADDR), + phy_txd_inv, 0); if (invert & PHY_POLARITY_RXD_INVERT) - phy_write16(lane, PHY_SYNC_PATTERN_ADDR, phy_rxd_inv, 0); + reg_set16(sgmiiphy_addr(lane, PHY_SYNC_PATTERN_ADDR), + phy_rxd_inv, 0); /* * 19. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index d41a1aa516..ca8c648c35 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -60,13 +60,14 @@ #define USB32_CTRL_BASE MVEBU_REG(0x05D800) #define USB3PHY_SHFT 2 -#define SGMIIPHY_BASE(l) (l == 1 ? USB3PHY_BASE : PCIEPHY_BASE) -#define SGMIIPHY_ADDR(l, a) \ - ((void __iomem *)(((a & 0x00007FF) * 2) + SGMIIPHY_BASE(l))) - -#define phy_read16(l, a) read16((void __iomem *)SGMIIPHY_ADDR(l, a)) -#define phy_write16(l, a, data, mask) \ - reg_set16(SGMIIPHY_ADDR(l, a), data, mask) +static inline void __iomem *sgmiiphy_addr(u32 lane, u32 addr) +{ + addr = (addr & 0x00007FF) * 2; + if (lane == 1) + return PCIEPHY_BASE + addr; + else + return USB3PHY_BASE + addr; +} /* units */ #define PCIE 1 -- cgit From 210f4aae81430a59743562ac3c5d8b4d68bd809f Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:14 +0200 Subject: phy: marvell: a3700: Don't create functional macro for each register Currently there is for each register special functional macro, ie: LANE_CFG1_ADDR(u) GLOB_CLK_SRC_LO_ADDR(u) ... where can be either PCIE or USB3. Change this to one function PHY_ADDR(unit, addr). The code becomes: phy_addr(PCIE, LANE_CFG1) phy_addr(PCIE, GLOB_CLK_SRC_LO) ... Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 108 ++++++++++++++++++------------------- drivers/phy/marvell/comphy_a3700.h | 92 +++++++++++++------------------ 2 files changed, 89 insertions(+), 111 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 3d913f4342..4adf0822fc 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -140,72 +140,70 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) /* * 1. Enable max PLL. */ - reg_set16(LANE_CFG1_ADDR(PCIE), bf_use_max_pll_rate, 0); + reg_set16(phy_addr(PCIE, LANE_CFG1), bf_use_max_pll_rate, 0); /* * 2. Select 20 bit SERDES interface. */ - reg_set16(GLOB_CLK_SRC_LO_ADDR(PCIE), bf_cfg_sel_20b, 0); + reg_set16(phy_addr(PCIE, GLOB_CLK_SRC_LO), bf_cfg_sel_20b, 0); /* * 3. Force to use reg setting for PCIe mode */ - reg_set16(MISC_REG1_ADDR(PCIE), bf_sel_bits_pcie_force, 0); + reg_set16(phy_addr(PCIE, MISC_REG1), bf_sel_bits_pcie_force, 0); /* * 4. Change RX wait */ - reg_set16(PWR_MGM_TIM1_ADDR(PCIE), 0x10C, 0xFFFF); + reg_set16(phy_addr(PCIE, PWR_MGM_TIM1), 0x10C, 0xFFFF); /* * 5. Enable idle sync */ - reg_set16(UNIT_CTRL_ADDR(PCIE), 0x60 | rb_idle_sync_en, 0xFFFF); + reg_set16(phy_addr(PCIE, UNIT_CTRL), 0x60 | rb_idle_sync_en, 0xFFFF); /* * 6. Enable the output of 100M/125M/500M clock */ - reg_set16(MISC_REG0_ADDR(PCIE), + reg_set16(phy_addr(PCIE, MISC_REG0), 0xA00D | rb_clk500m_en | rb_clk100m_125m_en, 0xFFFF); /* * 7. Enable TX */ - reg_set(PHY_REF_CLK_ADDR, 0x1342, 0xFFFFFFFF); + reg_set(PCIE_REF_CLK_ADDR, 0x1342, 0xFFFFFFFF); /* * 8. Check crystal jumper setting and program the Power and PLL * Control accordingly */ if (get_ref_clk() == 40) { - reg_set16(PWR_PLL_CTRL_ADDR(PCIE), - 0xFC63, 0xFFFF); /* 40 MHz */ + /* 40 MHz */ + reg_set16(phy_addr(PCIE, PWR_PLL_CTRL), 0xFC63, 0xFFFF); } else { - reg_set16(PWR_PLL_CTRL_ADDR(PCIE), - 0xFC62, 0xFFFF); /* 25 MHz */ + /* 25 MHz */ + reg_set16(phy_addr(PCIE, PWR_PLL_CTRL), 0xFC62, 0xFFFF); } /* * 9. Override Speed_PLL value and use MAC PLL */ - reg_set16(KVCO_CAL_CTRL_ADDR(PCIE), 0x0040 | rb_use_max_pll_rate, + reg_set16(phy_addr(PCIE, KVCO_CAL_CTRL), 0x0040 | rb_use_max_pll_rate, 0xFFFF); /* * 10. Check the Polarity invert bit */ - if (invert & PHY_POLARITY_TXD_INVERT) { - reg_set16(SYNC_PATTERN_ADDR(PCIE), phy_txd_inv, 0); - } + if (invert & PHY_POLARITY_TXD_INVERT) + reg_set16(phy_addr(PCIE, SYNC_PATTERN), phy_txd_inv, 0); - if (invert & PHY_POLARITY_RXD_INVERT) { - reg_set16(SYNC_PATTERN_ADDR(PCIE), phy_rxd_inv, 0); - } + if (invert & PHY_POLARITY_RXD_INVERT) + reg_set16(phy_addr(PCIE, SYNC_PATTERN), phy_rxd_inv, 0); /* * 11. Release SW reset */ - reg_set16(GLOB_PHY_CTRL0_ADDR(PCIE), + reg_set16(phy_addr(PCIE, GLOB_PHY_CTRL0), rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32, bf_soft_rst | bf_mode_refdiv); @@ -213,11 +211,11 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) udelay(PLL_SET_DELAY_US); /* Assert PCLK enabled */ - ret = comphy_poll_reg(LANE_STAT1_ADDR(PCIE), /* address */ - rb_txdclk_pclk_en, /* value */ - rb_txdclk_pclk_en, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ - POLL_16B_REG); /* 16bit */ + ret = comphy_poll_reg(phy_addr(PCIE, LANE_STAT1), /* address */ + rb_txdclk_pclk_en, /* value */ + rb_txdclk_pclk_en, /* mask */ + PLL_LOCK_TIMEOUT, /* timeout */ + POLL_16B_REG); /* 16bit */ if (ret == 0) printf("Failed to lock PCIe PLL\n"); @@ -321,7 +319,7 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) /* 0xd005c300 = 0x1001 */ /* set PRD_TXDEEMPH (3.5db de-emph) */ - reg_set16(LANE_CFG0_ADDR(USB3), 0x1, 0xFF); + reg_set16(phy_addr(USB3, LANE_CFG0), 0x1, 0xFF); /* * unset BIT0: set Tx Electrical Idle Mode: Transmitter is in @@ -329,82 +327,83 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) */ /* unset BIT4: set G2 Tx Datapath with no Delayed Latency */ /* unset BIT6: set Tx Detect Rx Mode at LoZ mode */ - reg_set16(LANE_CFG1_ADDR(USB3), 0x0, 0xFFFF); + reg_set16(phy_addr(USB3, LANE_CFG1), 0x0, 0xFFFF); /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */ - reg_set16(LANE_CFG4_ADDR(USB3), bf_spread_spectrum_clock_en, 0x80); + reg_set16(phy_addr(USB3, LANE_CFG4), bf_spread_spectrum_clock_en, 0x80); /* * set Override Margining Controls From the MAC: Use margining signals * from lane configuration */ - reg_set16(TEST_MODE_CTRL_ADDR(USB3), rb_mode_margin_override, 0xFFFF); + reg_set16(phy_addr(USB3, TEST_MODE_CTRL), rb_mode_margin_override, + 0xFFFF); /* set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles */ /* set Mode Clock Source = PCLK is generated from REFCLK */ - reg_set16(GLOB_CLK_SRC_LO_ADDR(USB3), 0x0, 0xFF); + reg_set16(phy_addr(USB3, GLOB_CLK_SRC_LO), 0x0, 0xFF); /* set G2 Spread Spectrum Clock Amplitude at 4K */ - reg_set16(GEN2_SETTING_2_ADDR(USB3), g2_tx_ssc_amp, 0xF000); + reg_set16(phy_addr(USB3, GEN2_SETTINGS_2), g2_tx_ssc_amp, 0xF000); /* * unset G3 Spread Spectrum Clock Amplitude & set G3 TX and RX Register * Master Current Select */ - reg_set16(GEN2_SETTING_3_ADDR(USB3), 0x0, 0xFFFF); + reg_set16(phy_addr(USB3, GEN2_SETTINGS_3), 0x0, 0xFFFF); /* * 3. Check crystal jumper setting and program the Power and PLL * Control accordingly */ if (get_ref_clk() == 40) { - reg_set16(PWR_PLL_CTRL_ADDR(USB3), 0xFCA3, 0xFFFF); /* 40 MHz */ + /* 40 MHz */ + reg_set16(phy_addr(USB3, PWR_PLL_CTRL), 0xFCA3, 0xFFFF); } else { - reg_set16(PWR_PLL_CTRL_ADDR(USB3), 0xFCA2, 0xFFFF); /* 25 MHz */ + /* 25 MHz */ + reg_set16(phy_addr(USB3, PWR_PLL_CTRL), 0xFCA2, 0xFFFF); } /* * 4. Change RX wait */ - reg_set16(PWR_MGM_TIM1_ADDR(USB3), 0x10C, 0xFFFF); + reg_set16(phy_addr(USB3, PWR_MGM_TIM1), 0x10C, 0xFFFF); /* * 5. Enable idle sync */ - reg_set16(UNIT_CTRL_ADDR(USB3), 0x60 | rb_idle_sync_en, 0xFFFF); + reg_set16(phy_addr(USB3, UNIT_CTRL), 0x60 | rb_idle_sync_en, 0xFFFF); /* * 6. Enable the output of 500M clock */ - reg_set16(MISC_REG0_ADDR(USB3), 0xA00D | rb_clk500m_en, 0xFFFF); + reg_set16(phy_addr(USB3, MISC_REG0), 0xA00D | rb_clk500m_en, 0xFFFF); /* * 7. Set 20-bit data width */ - reg_set16(DIG_LB_EN_ADDR(USB3), 0x0400, 0xFFFF); + reg_set16(phy_addr(USB3, DIG_LB_EN), 0x0400, 0xFFFF); /* * 8. Override Speed_PLL value and use MAC PLL */ - reg_set16(KVCO_CAL_CTRL_ADDR(USB3), 0x0040 | rb_use_max_pll_rate, + reg_set16(phy_addr(USB3, KVCO_CAL_CTRL), 0x0040 | rb_use_max_pll_rate, 0xFFFF); /* * 9. Check the Polarity invert bit */ - if (invert & PHY_POLARITY_TXD_INVERT) { - reg_set16(SYNC_PATTERN_ADDR(USB3), phy_txd_inv, 0); - } + if (invert & PHY_POLARITY_TXD_INVERT) + reg_set16(phy_addr(USB3, SYNC_PATTERN), phy_txd_inv, 0); - if (invert & PHY_POLARITY_RXD_INVERT) { - reg_set16(SYNC_PATTERN_ADDR(USB3), phy_rxd_inv, 0); - } + if (invert & PHY_POLARITY_RXD_INVERT) + reg_set16(phy_addr(USB3, SYNC_PATTERN), phy_rxd_inv, 0); /* * 10. Release SW reset */ - reg_set16(GLOB_PHY_CTRL0_ADDR(USB3), + reg_set16(phy_addr(USB3, GLOB_PHY_CTRL0), rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 | 0x20, 0xFFFF); @@ -412,7 +411,7 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) udelay(PLL_SET_DELAY_US); /* Assert PCLK enabled */ - ret = comphy_poll_reg(LANE_STAT1_ADDR(USB3), /* address */ + ret = comphy_poll_reg(phy_addr(USB3, LANE_STAT1), /* address */ rb_txdclk_pclk_en, /* value */ rb_txdclk_pclk_en, /* mask */ PLL_LOCK_TIMEOUT, /* timeout */ @@ -673,25 +672,25 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) mdelay(10); /* 9. Program COMPHY register PHY_MODE */ - reg_set16(sgmiiphy_addr(lane, PHY_PWR_PLL_CTRL_ADDR), + reg_set16(sgmiiphy_addr(lane, PWR_PLL_CTRL), PHY_MODE_SGMII << rf_phy_mode_shift, rf_phy_mode_mask); /* * 10. Set COMPHY register REFCLK_SEL to select the correct REFCLK * source */ - reg_set16(sgmiiphy_addr(lane, PHY_MISC_REG0_ADDR), 0, rb_ref_clk_sel); + reg_set16(sgmiiphy_addr(lane, MISC_REG0), 0, rb_ref_clk_sel); /* * 11. Set correct reference clock frequency in COMPHY register * REF_FREF_SEL. */ if (get_ref_clk() == 40) { - reg_set16(sgmiiphy_addr(lane, PHY_PWR_PLL_CTRL_ADDR), + reg_set16(sgmiiphy_addr(lane, PWR_PLL_CTRL), 0x4 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask); } else { /* 25MHz */ - reg_set16(sgmiiphy_addr(lane, PHY_PWR_PLL_CTRL_ADDR), + reg_set16(sgmiiphy_addr(lane, PWR_PLL_CTRL), 0x1 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask); } @@ -708,8 +707,7 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) * bus width */ /* 10bit */ - reg_set16(sgmiiphy_addr(lane, PHY_DIG_LB_EN_ADDR), 0, - rf_data_width_mask); + reg_set16(sgmiiphy_addr(lane, DIG_LB_EN), 0, rf_data_width_mask); /* * 14. As long as DFE function needs to be enabled in any mode, @@ -752,12 +750,10 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) * 18. Check the PHY Polarity invert bit */ if (invert & PHY_POLARITY_TXD_INVERT) - reg_set16(sgmiiphy_addr(lane, PHY_SYNC_PATTERN_ADDR), - phy_txd_inv, 0); + reg_set16(sgmiiphy_addr(lane, SYNC_PATTERN), phy_txd_inv, 0); if (invert & PHY_POLARITY_RXD_INVERT) - reg_set16(sgmiiphy_addr(lane, PHY_SYNC_PATTERN_ADDR), - phy_rxd_inv, 0); + reg_set16(sgmiiphy_addr(lane, SYNC_PATTERN), phy_rxd_inv, 0); /* * 19. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index ca8c648c35..0d7b4255fe 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -70,116 +70,98 @@ static inline void __iomem *sgmiiphy_addr(u32 lane, u32 addr) } /* units */ -#define PCIE 1 -#define USB3 2 +enum phy_unit { + PCIE = 1, + USB3 = 2, +}; -#define PHY_BASE(unit) ((unit == PCIE) ? PCIEPHY_BASE : USB3PHY_BASE) -#define PHY_SHFT(unit) ((unit == PCIE) ? PCIEPHY_SHFT : USB3PHY_SHFT) +static inline void __iomem *phy_addr(enum phy_unit unit, u32 addr) +{ + if (unit == PCIE) + return PCIEPHY_BASE + addr * PCIEPHY_SHFT; + else + return USB3PHY_BASE + addr * USB3PHY_SHFT; +} /* bit definition for USB32_CTRL_BASE (USB32 Control Mode) */ #define usb32_ctrl_id_mode BIT(0) #define usb32_ctrl_soft_id BIT(1) #define usb32_ctrl_int_mode BIT(4) - -#define PHY_PWR_PLL_CTRL_ADDR 0x01 /* for phy_read16 and phy_write16 */ -#define PWR_PLL_CTRL_ADDR(unit) \ - (PHY_PWR_PLL_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit)) +#define PWR_PLL_CTRL 0x01 #define rf_phy_mode_shift 5 #define rf_phy_mode_mask (0x7 << rf_phy_mode_shift) #define rf_ref_freq_sel_shift 0 #define rf_ref_freq_sel_mask (0x1F << rf_ref_freq_sel_shift) #define PHY_MODE_SGMII 0x4 -/* for phy_read16 and phy_write16 */ -#define PHY_REG_KVCO_CAL_CTRL_ADDR 0x02 -#define KVCO_CAL_CTRL_ADDR(unit) \ - (PHY_REG_KVCO_CAL_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit)) +#define KVCO_CAL_CTRL 0x02 #define rb_use_max_pll_rate BIT(12) #define rb_force_calibration_done BIT(9) -/* for phy_read16 and phy_write16 */ -#define PHY_DIG_LB_EN_ADDR 0x23 -#define DIG_LB_EN_ADDR(unit) \ - (PHY_DIG_LB_EN_ADDR * PHY_SHFT(unit) + PHY_BASE(unit)) +#define DIG_LB_EN 0x23 #define rf_data_width_shift 10 #define rf_data_width_mask (0x3 << rf_data_width_shift) -/* for phy_read16 and phy_write16 */ -#define PHY_SYNC_PATTERN_ADDR 0x24 -#define SYNC_PATTERN_ADDR(unit) \ - (PHY_SYNC_PATTERN_ADDR * PHY_SHFT(unit) + PHY_BASE(unit)) +#define SYNC_PATTERN 0x24 #define phy_txd_inv BIT(10) #define phy_rxd_inv BIT(11) -/* for phy_read16 and phy_write16 */ -#define PHY_REG_UNIT_CTRL_ADDR 0x48 -#define UNIT_CTRL_ADDR(unit) \ - (PHY_REG_UNIT_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit)) +#define SYNC_MASK_GEN 0x25 #define rb_idle_sync_en BIT(12) -/* for phy_read16 and phy_write16 */ -#define PHY_REG_GEN2_SETTINGS_2 0x3e -#define GEN2_SETTING_2_ADDR(unit) \ - (PHY_REG_GEN2_SETTINGS_2 * PHY_SHFT(unit) + PHY_BASE(unit)) +#define UNIT_CTRL 0x48 + +#define GEN2_SETTINGS_2 0x3e #define g2_tx_ssc_amp BIT(14) -/* for phy_read16 and phy_write16 */ -#define PHY_REG_GEN2_SETTINGS_3 0x3f -#define GEN2_SETTING_3_ADDR(unit) \ - (PHY_REG_GEN2_SETTINGS_3 * PHY_SHFT(unit) + PHY_BASE(unit)) +#define GEN2_SETTINGS_3 0x3f + +#define GEN3_SETTINGS_3 0x112 -/* for phy_read16 and phy_write16 */ -#define PHY_MISC_REG0_ADDR 0x4f -#define MISC_REG0_ADDR(unit) \ - (PHY_MISC_REG0_ADDR * PHY_SHFT(unit) + PHY_BASE(unit)) +#define MISC_REG0 0x4f #define rb_clk100m_125m_en BIT(4) #define rb_clk500m_en BIT(7) #define rb_ref_clk_sel BIT(10) -/* for phy_read16 and phy_write16 */ -#define PHY_REG_IFACE_REF_CLK_CTRL_ADDR 0x51 -#define UNIT_IFACE_REF_CLK_CTRL_ADDR(unit) \ - (PHY_REG_IFACE_REF_CLK_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit)) +#define UNIT_IFACE_REF_CLK_CTRL 0x51 #define rb_ref1m_gen_div_force BIT(8) #define rf_ref1m_gen_div_value_shift 0 #define rf_ref1m_gen_div_value_mask (0xFF << rf_ref1m_gen_div_value_shift) -/* for phy_read16 and phy_write16 */ -#define PHY_REG_ERR_CNT_CONST_CTRL_ADDR 0x6A -#define UNIT_ERR_CNT_CONST_CTRL_ADDR(unit) \ - (PHY_REG_ERR_CNT_CONST_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit)) +#define UNIT_ERR_CNT_CONST_CTRL 0x6a #define rb_fast_dfe_enable BIT(13) -#define MISC_REG1_ADDR(u) (0x73 * PHY_SHFT(u) + PHY_BASE(u)) +#define MISC_REG1 0x73 #define bf_sel_bits_pcie_force BIT(15) -#define LANE_CFG0_ADDR(u) (0x180 * PHY_SHFT(u) + PHY_BASE(u)) +#define LANE_CFG0 0x180 #define bf_use_max_pll_rate BIT(9) -#define LANE_CFG1_ADDR(u) (0x181 * PHY_SHFT(u) + PHY_BASE(u)) + +#define LANE_CFG1 0x181 #define bf_use_max_pll_rate BIT(9) -/* 0x5c310 = 0x93 (set BIT7) */ -#define LANE_CFG4_ADDR(u) (0x188 * PHY_SHFT(u) + PHY_BASE(u)) + +#define LANE_CFG4 0x188 #define bf_spread_spectrum_clock_en BIT(7) -#define LANE_STAT1_ADDR(u) (0x183 * PHY_SHFT(u) + PHY_BASE(u)) +#define LANE_STAT1 0x183 #define rb_txdclk_pclk_en BIT(0) -#define GLOB_PHY_CTRL0_ADDR(u) (0x1c1 * PHY_SHFT(u) + PHY_BASE(u)) +#define GLOB_PHY_CTRL0 0x1c1 #define bf_soft_rst BIT(0) #define bf_mode_refdiv 0x30 #define rb_mode_core_clk_freq_sel BIT(9) #define rb_mode_pipe_width_32 BIT(3) -#define TEST_MODE_CTRL_ADDR(u) (0x1c2 * PHY_SHFT(u) + PHY_BASE(u)) +#define TEST_MODE_CTRL 0x1c2 #define rb_mode_margin_override BIT(2) -#define GLOB_CLK_SRC_LO_ADDR(u) (0x1c3 * PHY_SHFT(u) + PHY_BASE(u)) +#define GLOB_CLK_SRC_LO 0x1c3 #define bf_cfg_sel_20b BIT(15) -#define PWR_MGM_TIM1_ADDR(u) (0x1d0 * PHY_SHFT(u) + PHY_BASE(u)) +#define PWR_MGM_TIM1 0x1d0 -#define PHY_REF_CLK_ADDR (0x4814 + PCIE_BASE) +#define PCIE_REF_CLK_ADDR (PCIE_BASE + 0x4814) #define USB3_CTRPUL_VAL_REG (0x20 + USB32_BASE) #define USB3H_CTRPUL_VAL_REG (0x3454 + USB32H_BASE) -- cgit From 52f026e224b42a27f0d2a05167898b031a8ea70e Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:15 +0200 Subject: phy: marvell: a3700: Use same timeout for all register polling The timeout is set to PLL_LOCK_TIMEOUT in every call to comphy_poll_reg. Remove this parameter from the function. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 4adf0822fc..d1ccb4a62a 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -105,12 +105,11 @@ static u16 sgmii_phy_init[512] = { * * return: 1 on success, 0 on timeout */ -static u32 comphy_poll_reg(void *addr, u32 val, u32 mask, u32 timeout, - u8 op_type) +static u32 comphy_poll_reg(void *addr, u32 val, u32 mask, u8 op_type) { - u32 rval = 0xDEAD; + u32 rval = 0xDEAD, timeout; - for (; timeout > 0; timeout--) { + for (timeout = PLL_LOCK_TIMEOUT; timeout > 0; timeout--) { if (op_type == POLL_16B_REG) rval = readw(addr); /* 16 bit */ else @@ -214,7 +213,6 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) ret = comphy_poll_reg(phy_addr(PCIE, LANE_STAT1), /* address */ rb_txdclk_pclk_en, /* value */ rb_txdclk_pclk_en, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_16B_REG); /* 16bit */ if (ret == 0) printf("Failed to lock PCIe PLL\n"); @@ -284,7 +282,6 @@ static int comphy_sata_power_up(void) ret = comphy_poll_reg(rh_vsreg_data, /* address */ bs_pll_ready_tx, /* value */ bs_pll_ready_tx, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_32B_REG); /* 32bit */ if (ret == 0) printf("Failed to lock SATA PLL\n"); @@ -414,7 +411,6 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) ret = comphy_poll_reg(phy_addr(USB3, LANE_STAT1), /* address */ rb_txdclk_pclk_en, /* value */ rb_txdclk_pclk_en, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_16B_REG); /* 16bit */ if (ret == 0) printf("Failed to lock USB3 PLL\n"); @@ -495,7 +491,6 @@ static int comphy_usb2_power_up(u8 usb32) ret = comphy_poll_reg(USB2_PHY_CAL_CTRL_ADDR(usb32), rb_usb2phy_pllcal_done, /* value */ rb_usb2phy_pllcal_done, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_32B_REG); /* 32bit */ if (ret == 0) printf("Failed to end USB2 PLL calibration\n"); @@ -504,7 +499,6 @@ static int comphy_usb2_power_up(u8 usb32) ret = comphy_poll_reg(USB2_PHY_CAL_CTRL_ADDR(usb32), rb_usb2phy_impcal_done, /* value */ rb_usb2phy_impcal_done, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_32B_REG); /* 32bit */ if (ret == 0) printf("Failed to end USB2 impedance calibration\n"); @@ -513,7 +507,6 @@ static int comphy_usb2_power_up(u8 usb32) ret = comphy_poll_reg(USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32), rb_usb2phy_sqcal_done, /* value */ rb_usb2phy_sqcal_done, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_32B_REG); /* 32bit */ if (ret == 0) printf("Failed to end USB2 unknown calibration\n"); @@ -522,7 +515,6 @@ static int comphy_usb2_power_up(u8 usb32) ret = comphy_poll_reg(USB2_PHY_PLL_CTRL0_ADDR(usb32), rb_usb2phy_pll_ready, /* value */ rb_usb2phy_pll_ready, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_32B_REG); /* 32bit */ if (ret == 0) @@ -772,7 +764,6 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) ret = comphy_poll_reg(COMPHY_PHY_STAT1_ADDR(lane), /* address */ rb_pll_ready_tx | rb_pll_ready_rx, /* value */ rb_pll_ready_tx | rb_pll_ready_rx, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_32B_REG); /* 32bit */ if (ret == 0) printf("Failed to lock PLL for SGMII PHY %d\n", lane); @@ -795,7 +786,6 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) ret = comphy_poll_reg(COMPHY_PHY_STAT1_ADDR(lane), /* address */ rb_rx_init_done, /* value */ rb_rx_init_done, /* mask */ - PLL_LOCK_TIMEOUT, /* timeout */ POLL_32B_REG); /* 32bit */ if (ret == 0) printf("Failed to init RX of SGMII PHY %d\n", lane); -- cgit From 1a9283ace571384b60b931567b0a6055acec27cc Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:16 +0200 Subject: phy: marvell: a3700: Use (!ret) instead of (ret == 0) In U-Boot it is usually written this way. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index d1ccb4a62a..a62d672e86 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -214,7 +214,7 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) rb_txdclk_pclk_en, /* value */ rb_txdclk_pclk_en, /* mask */ POLL_16B_REG); /* 16bit */ - if (ret == 0) + if (!ret) printf("Failed to lock PCIe PLL\n"); debug_exit(); @@ -283,7 +283,7 @@ static int comphy_sata_power_up(void) bs_pll_ready_tx, /* value */ bs_pll_ready_tx, /* mask */ POLL_32B_REG); /* 32bit */ - if (ret == 0) + if (!ret) printf("Failed to lock SATA PLL\n"); debug_exit(); @@ -412,7 +412,7 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) rb_txdclk_pclk_en, /* value */ rb_txdclk_pclk_en, /* mask */ POLL_16B_REG); /* 16bit */ - if (ret == 0) + if (!ret) printf("Failed to lock USB3 PLL\n"); /* @@ -492,7 +492,7 @@ static int comphy_usb2_power_up(u8 usb32) rb_usb2phy_pllcal_done, /* value */ rb_usb2phy_pllcal_done, /* mask */ POLL_32B_REG); /* 32bit */ - if (ret == 0) + if (!ret) printf("Failed to end USB2 PLL calibration\n"); /* Assert impedance calibration done */ @@ -500,7 +500,7 @@ static int comphy_usb2_power_up(u8 usb32) rb_usb2phy_impcal_done, /* value */ rb_usb2phy_impcal_done, /* mask */ POLL_32B_REG); /* 32bit */ - if (ret == 0) + if (!ret) printf("Failed to end USB2 impedance calibration\n"); /* Assert squetch calibration done */ @@ -508,7 +508,7 @@ static int comphy_usb2_power_up(u8 usb32) rb_usb2phy_sqcal_done, /* value */ rb_usb2phy_sqcal_done, /* mask */ POLL_32B_REG); /* 32bit */ - if (ret == 0) + if (!ret) printf("Failed to end USB2 unknown calibration\n"); /* Assert PLL is ready */ @@ -517,7 +517,7 @@ static int comphy_usb2_power_up(u8 usb32) rb_usb2phy_pll_ready, /* mask */ POLL_32B_REG); /* 32bit */ - if (ret == 0) + if (!ret) printf("Failed to lock USB2 PLL\n"); debug_exit(); @@ -765,7 +765,7 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) rb_pll_ready_tx | rb_pll_ready_rx, /* value */ rb_pll_ready_tx | rb_pll_ready_rx, /* mask */ POLL_32B_REG); /* 32bit */ - if (ret == 0) + if (!ret) printf("Failed to lock PLL for SGMII PHY %d\n", lane); /* @@ -787,7 +787,7 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) rb_rx_init_done, /* value */ rb_rx_init_done, /* mask */ POLL_32B_REG); /* 32bit */ - if (ret == 0) + if (!ret) printf("Failed to init RX of SGMII PHY %d\n", lane); debug_exit(); @@ -818,7 +818,7 @@ void comphy_dedicated_phys_init(void) if (node > 0) { if (fdtdec_get_is_enabled(blob, node)) { ret = comphy_usb2_power_up(usb32); - if (ret == 0) + if (!ret) printf("Failed to initialize UTMI PHY\n"); else debug("UTMI PHY init succeed\n"); @@ -836,7 +836,7 @@ void comphy_dedicated_phys_init(void) if (node > 0) { if (fdtdec_get_is_enabled(blob, node)) { ret = comphy_sata_power_up(); - if (ret == 0) + if (!ret) printf("Failed to initialize SATA PHY\n"); else debug("SATA PHY init succeed\n"); @@ -857,7 +857,7 @@ void comphy_dedicated_phys_init(void) if (node > 0) { if (fdtdec_get_is_enabled(blob, node)) { ret = comphy_emmc_power_up(); - if (ret == 0) + if (!ret) printf("Failed to initialize SDIO/eMMC PHY\n"); else debug("SDIO/eMMC PHY init succeed\n"); @@ -915,7 +915,7 @@ int comphy_a3700_init(struct chip_serdes_phy_config *chip_cfg, ret = 1; break; } - if (ret == 0) + if (!ret) printf("PLL is not locked - Failed to initialize lane %d\n", lane); } -- cgit From a2745c88032e27b16d0f78748175365601dd5107 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:17 +0200 Subject: phy: marvell: a3700: Use reg_set_indirect istead of 2 reg_sets Create a special function for indirect register setting, reg_set_indirect, and use it instead of the two calls to reg_set. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index a62d672e86..81f2b636e6 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -223,6 +223,17 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) return ret; } +/* + * reg_set_indirect + * + * return: void + */ +static void reg_set_indirect(u32 reg, u16 data, u16 mask) +{ + reg_set(rh_vsreg_addr, reg, 0xFFFFFFFF); + reg_set(rh_vsreg_data, data, mask); +} + /* * comphy_sata_power_up * @@ -230,43 +241,40 @@ static int comphy_pcie_power_up(u32 speed, u32 invert) */ static int comphy_sata_power_up(void) { - int ret; + int ret; debug_enter(); /* * 0. Swap SATA TX lines */ - reg_set(rh_vsreg_addr, vphy_sync_pattern_reg, 0xFFFFFFFF); - reg_set(rh_vsreg_data, bs_txd_inv, bs_txd_inv); + reg_set_indirect(vphy_sync_pattern_reg, bs_txd_inv, bs_txd_inv); /* * 1. Select 40-bit data width width */ - reg_set(rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF); - reg_set(rh_vsreg_data, 0x800, bs_phyintf_40bit); + reg_set_indirect(vphy_loopback_reg0, 0x800, bs_phyintf_40bit); /* * 2. Select reference clock and PHY mode (SATA) */ - reg_set(rh_vsreg_addr, vphy_power_reg0, 0xFFFFFFFF); if (get_ref_clk() == 40) { - reg_set(rh_vsreg_data, 0x3, 0x00FF); /* 40 MHz */ + /* 40 MHz */ + reg_set_indirect(vphy_power_reg0, 0x3, 0x00FF); } else { - reg_set(rh_vsreg_data, 0x1, 0x00FF); /* 25 MHz */ + /* 20 MHz */ + reg_set_indirect(vphy_power_reg0, 0x1, 0x00FF); } /* * 3. Use maximum PLL rate (no power save) */ - reg_set(rh_vsreg_addr, vphy_calctl_reg, 0xFFFFFFFF); - reg_set(rh_vsreg_data, bs_max_pll_rate, bs_max_pll_rate); + reg_set_indirect(vphy_calctl_reg, bs_max_pll_rate, bs_max_pll_rate); /* * 4. Reset reserved bit (??) */ - reg_set(rh_vsreg_addr, vphy_reserve_reg, 0xFFFFFFFF); - reg_set(rh_vsreg_data, 0, bs_phyctrl_frm_pin); + reg_set_indirect(vphy_reserve_reg, 0, bs_phyctrl_frm_pin); /* * 5. Set vendor-specific configuration (??) -- cgit From 86093582618baee4611a53764d25858ada322102 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:18 +0200 Subject: phy: marvell: a3700: Access USB3 register indirectly on lane 2 When USB3 is on comphy lane 2 on the Armada 37xx, the registers have to be accessed indirectly via SATA indirect access. This is the case of the Turris Mox board from CZ.NIC. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 102 ++++++++++++++++++++++++------------- drivers/phy/marvell/comphy_a3700.h | 1 + 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 81f2b636e6..4fb23bb547 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -132,7 +132,7 @@ static u32 comphy_poll_reg(void *addr, u32 val, u32 mask, u8 op_type) */ static int comphy_pcie_power_up(u32 speed, u32 invert) { - int ret; + int ret; debug_enter(); @@ -299,14 +299,36 @@ static int comphy_sata_power_up(void) return ret; } +/* + * usb3_reg_set16 + * + * return: void + */ +static void usb3_reg_set16(u32 reg, u16 data, u16 mask, u32 lane) +{ + /* + * When Lane 2 PHY is for USB3, access the PHY registers + * through indirect Address and Data registers INDIR_ACC_PHY_ADDR + * (RD00E0178h [31:0]) and INDIR_ACC_PHY_DATA (RD00E017Ch [31:0]) + * within the SATA Host Controller registers, Lane 2 base register + * offset is 0x200 + */ + + if (lane == 2) + reg_set_indirect(USB3PHY_LANE2_REG_BASE_OFFSET + reg, data, + mask); + else + reg_set16(phy_addr(USB3, reg), data, mask); +} + /* * comphy_usb3_power_up * * return: 1 if PLL locked (OK), 0 otherwise (FAIL) */ -static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) +static int comphy_usb3_power_up(u32 lane, u32 type, u32 speed, u32 invert) { - int ret; + int ret; debug_enter(); @@ -324,39 +346,38 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) /* 0xd005c300 = 0x1001 */ /* set PRD_TXDEEMPH (3.5db de-emph) */ - reg_set16(phy_addr(USB3, LANE_CFG0), 0x1, 0xFF); + usb3_reg_set16(LANE_CFG0, 0x1, 0xFF, lane); /* * unset BIT0: set Tx Electrical Idle Mode: Transmitter is in - * low impedance mode during electrical idle + * low impedance mode during electrical idle + * unset BIT4: set G2 Tx Datapath with no Delayed Latency + * unset BIT6: set Tx Detect Rx Mode at LoZ mode */ - /* unset BIT4: set G2 Tx Datapath with no Delayed Latency */ - /* unset BIT6: set Tx Detect Rx Mode at LoZ mode */ - reg_set16(phy_addr(USB3, LANE_CFG1), 0x0, 0xFFFF); + usb3_reg_set16(LANE_CFG1, 0x0, 0xFFFF, lane); - /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */ - reg_set16(phy_addr(USB3, LANE_CFG4), bf_spread_spectrum_clock_en, 0x80); + /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */ + usb3_reg_set16(LANE_CFG4, bf_spread_spectrum_clock_en, 0x80, lane); /* * set Override Margining Controls From the MAC: Use margining signals * from lane configuration */ - reg_set16(phy_addr(USB3, TEST_MODE_CTRL), rb_mode_margin_override, - 0xFFFF); + usb3_reg_set16(TEST_MODE_CTRL, rb_mode_margin_override, 0xFFFF, lane); /* set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles */ /* set Mode Clock Source = PCLK is generated from REFCLK */ - reg_set16(phy_addr(USB3, GLOB_CLK_SRC_LO), 0x0, 0xFF); + usb3_reg_set16(GLOB_CLK_SRC_LO, 0x0, 0xFF, lane); /* set G2 Spread Spectrum Clock Amplitude at 4K */ - reg_set16(phy_addr(USB3, GEN2_SETTINGS_2), g2_tx_ssc_amp, 0xF000); + usb3_reg_set16(GEN2_SETTINGS_2, g2_tx_ssc_amp, 0xF000, lane); /* * unset G3 Spread Spectrum Clock Amplitude & set G3 TX and RX Register * Master Current Select */ - reg_set16(phy_addr(USB3, GEN2_SETTINGS_3), 0x0, 0xFFFF); + usb3_reg_set16(GEN2_SETTINGS_3, 0x0, 0xFFFF, lane); /* * 3. Check crystal jumper setting and program the Power and PLL @@ -364,62 +385,72 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) */ if (get_ref_clk() == 40) { /* 40 MHz */ - reg_set16(phy_addr(USB3, PWR_PLL_CTRL), 0xFCA3, 0xFFFF); + usb3_reg_set16(PWR_PLL_CTRL, 0xFCA3, 0xFFFF, lane); } else { /* 25 MHz */ - reg_set16(phy_addr(USB3, PWR_PLL_CTRL), 0xFCA2, 0xFFFF); + usb3_reg_set16(PWR_PLL_CTRL, 0xFCA2, 0xFFFF, lane); } /* * 4. Change RX wait */ - reg_set16(phy_addr(USB3, PWR_MGM_TIM1), 0x10C, 0xFFFF); + usb3_reg_set16(PWR_MGM_TIM1, 0x10C, 0xFFFF, lane); /* * 5. Enable idle sync */ - reg_set16(phy_addr(USB3, UNIT_CTRL), 0x60 | rb_idle_sync_en, 0xFFFF); + usb3_reg_set16(UNIT_CTRL, 0x60 | rb_idle_sync_en, 0xFFFF, lane); /* * 6. Enable the output of 500M clock */ - reg_set16(phy_addr(USB3, MISC_REG0), 0xA00D | rb_clk500m_en, 0xFFFF); + usb3_reg_set16(MISC_REG0, 0xA00D | rb_clk500m_en, 0xFFFF, lane); /* * 7. Set 20-bit data width */ - reg_set16(phy_addr(USB3, DIG_LB_EN), 0x0400, 0xFFFF); + usb3_reg_set16(DIG_LB_EN, 0x0400, 0xFFFF, lane); /* * 8. Override Speed_PLL value and use MAC PLL */ - reg_set16(phy_addr(USB3, KVCO_CAL_CTRL), 0x0040 | rb_use_max_pll_rate, - 0xFFFF); + usb3_reg_set16(KVCO_CAL_CTRL, 0x0040 | rb_use_max_pll_rate, 0xFFFF, + lane); /* * 9. Check the Polarity invert bit */ if (invert & PHY_POLARITY_TXD_INVERT) - reg_set16(phy_addr(USB3, SYNC_PATTERN), phy_txd_inv, 0); + usb3_reg_set16(SYNC_PATTERN, phy_txd_inv, 0, lane); if (invert & PHY_POLARITY_RXD_INVERT) - reg_set16(phy_addr(USB3, SYNC_PATTERN), phy_rxd_inv, 0); + usb3_reg_set16(SYNC_PATTERN, phy_rxd_inv, 0, lane); /* * 10. Release SW reset */ - reg_set16(phy_addr(USB3, GLOB_PHY_CTRL0), - rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 | 0x20, - 0xFFFF); + usb3_reg_set16(GLOB_PHY_CTRL0, + rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 + | 0x20, 0xFFFF, lane); /* Wait for > 55 us to allow PCLK be enabled */ udelay(PLL_SET_DELAY_US); /* Assert PCLK enabled */ - ret = comphy_poll_reg(phy_addr(USB3, LANE_STAT1), /* address */ - rb_txdclk_pclk_en, /* value */ - rb_txdclk_pclk_en, /* mask */ - POLL_16B_REG); /* 16bit */ + if (lane == 2) { + reg_set(rh_vsreg_addr, + LANE_STAT1 + USB3PHY_LANE2_REG_BASE_OFFSET, + 0xFFFFFFFF); + ret = comphy_poll_reg(rh_vsreg_data, /* address */ + rb_txdclk_pclk_en, /* value */ + rb_txdclk_pclk_en, /* mask */ + POLL_32B_REG); /* 32bit */ + } else { + ret = comphy_poll_reg(phy_addr(USB3, LANE_STAT1), /* address */ + rb_txdclk_pclk_en, /* value */ + rb_txdclk_pclk_en, /* mask */ + POLL_16B_REG); /* 16bit */ + } if (!ret) printf("Failed to lock USB3 PLL\n"); @@ -455,7 +486,7 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) */ static int comphy_usb2_power_up(u8 usb32) { - int ret; + int ret; debug_enter(); @@ -620,7 +651,7 @@ static void comphy_sgmii_phy_init(u32 lane, u32 speed) */ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) { - int ret; + int ret; debug_enter(); @@ -906,7 +937,8 @@ int comphy_a3700_init(struct chip_serdes_phy_config *chip_cfg, case PHY_TYPE_USB3_HOST0: case PHY_TYPE_USB3_DEVICE: - ret = comphy_usb3_power_up(comphy_map->type, + ret = comphy_usb3_power_up(lane, + comphy_map->type, comphy_map->speed, comphy_map->invert); break; diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index 0d7b4255fe..07f4792aef 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -59,6 +59,7 @@ #define USB2PHY2_BASE MVEBU_REG(0x05F000) #define USB32_CTRL_BASE MVEBU_REG(0x05D800) #define USB3PHY_SHFT 2 +#define USB3PHY_LANE2_REG_BASE_OFFSET 0x200 static inline void __iomem *sgmiiphy_addr(u32 lane, u32 addr) { -- cgit From de49bd0e73f7d4e764f3c6b67a536de5d4e8841b Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:19 +0200 Subject: phy: marvell: a3700: Set USB3 RX wait depending on ref clock According to specification, CFG_PM_RXDLOZ_WAIT should be set to 0x7 when reference clock is at 25 MHz. The specification (at least the version I have) does not mentoin the setting for 40 MHz reference clock, but Marvell's U-Boot sets 0xC in that case. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 4fb23bb547..3da9eedc23 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -382,20 +382,18 @@ static int comphy_usb3_power_up(u32 lane, u32 type, u32 speed, u32 invert) /* * 3. Check crystal jumper setting and program the Power and PLL * Control accordingly + * 4. Change RX wait */ if (get_ref_clk() == 40) { /* 40 MHz */ usb3_reg_set16(PWR_PLL_CTRL, 0xFCA3, 0xFFFF, lane); + usb3_reg_set16(PWR_MGM_TIM1, 0x10C, 0xFFFF, lane); } else { /* 25 MHz */ usb3_reg_set16(PWR_PLL_CTRL, 0xFCA2, 0xFFFF, lane); + usb3_reg_set16(PWR_MGM_TIM1, 0x107, 0xFFFF, lane); } - /* - * 4. Change RX wait - */ - usb3_reg_set16(PWR_MGM_TIM1, 0x10C, 0xFFFF, lane); - /* * 5. Enable idle sync */ -- cgit From 7d7f22fbd30ec925b278275bd8b950837d6d3c7e Mon Sep 17 00:00:00 2001 From: zachary Date: Tue, 24 Apr 2018 17:21:20 +0200 Subject: phy: marvell: a3700: revise the USB3 comphy setting during power on This commit is based on commit d9899826 by zachary from u-boot-marvell, see github.com/MarvellEmbeddedProcessors/u-boot-marvell/commit/d9899826 - According to design specification, the transmitter should be set to high impedence mode during electrical idle. Thus transmitter should detect RX at high impedence mode also, and delay is needed to accommodate high impedence off latency. Otherwise the USB3 will have detection issue that most of the time the USB3 device can not be detected at all, or be detected as USB2 device sometimes. Modified registers: RD005C302h (R181h) (0051h) Lane Configuration 1 Bit 6: set to 1 to let Tx detect Rx at HiZ mode Bit [3:4]: set to 2 to be delayed by 2 clock cycles Bit 0: set to 1 to set transmitter to high impedance mode during idle. - USB3 De-emphasize level of -3.5dB is mandatory, but USB3 MAC selects 0x2 (emphasize disabled) in the MAC_PHY_TXDEEMPH [1:0], while it is supposed to select 0x1(3.5dB emphasize). Thus need to override what comes from the MAC(by setting register 0x1c2 bit2 to 0x1) and to configure the overridded values of MAC_PHY_TXDEEMPH [1:0] to 0x1(bit15 of register 0x181 and bit0 of register 0x180). - According to USB3 application note, need to update below comphy registers: Set max speed generation to USB3.0 5Gbps(set RD005C04Ah bit[11:10] to 1) Set capacitor value to 0xF(set RF005C224 bit[3:0] to 0xF) Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 31 +++++++++++++++++++++++-------- drivers/phy/marvell/comphy_a3700.h | 5 +++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 3da9eedc23..90e594fddc 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -349,13 +349,18 @@ static int comphy_usb3_power_up(u32 lane, u32 type, u32 speed, u32 invert) usb3_reg_set16(LANE_CFG0, 0x1, 0xFF, lane); /* - * unset BIT0: set Tx Electrical Idle Mode: Transmitter is in - * low impedance mode during electrical idle - * unset BIT4: set G2 Tx Datapath with no Delayed Latency - * unset BIT6: set Tx Detect Rx Mode at LoZ mode - */ - usb3_reg_set16(LANE_CFG1, 0x0, 0xFFFF, lane); - + * Set BIT0: enable transmitter in high impedance mode + * Set BIT[3:4]: delay 2 clock cycles for HiZ off latency + * Set BIT6: Tx detect Rx at HiZ mode + * Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db + * together with bit 0 of COMPHY_REG_LANE_CFG0_ADDR + * register + */ + usb3_reg_set16(LANE_CFG1, + tx_det_rx_mode | gen2_tx_data_dly_deft + | tx_elec_idle_mode_en, + prd_txdeemph1_mask | tx_det_rx_mode + | gen2_tx_data_dly_mask | tx_elec_idle_mode_en, lane); /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */ usb3_reg_set16(LANE_CFG4, bf_spread_spectrum_clock_en, 0x80, lane); @@ -425,7 +430,17 @@ static int comphy_usb3_power_up(u32 lane, u32 type, u32 speed, u32 invert) usb3_reg_set16(SYNC_PATTERN, phy_rxd_inv, 0, lane); /* - * 10. Release SW reset + * 10. Set max speed generation to USB3.0 5Gbps + */ + usb3_reg_set16(SYNC_MASK_GEN, 0x0400, 0x0C00, lane); + + /* + * 11. Set capacitor value for FFE gain peaking to 0xF + */ + usb3_reg_set16(GEN3_SETTINGS_3, 0xF, 0xF, lane); + + /* + * 12. Release SW reset */ usb3_reg_set16(GLOB_PHY_CTRL0, rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index 07f4792aef..7990aab1c6 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -141,6 +141,11 @@ static inline void __iomem *phy_addr(enum phy_unit unit, u32 addr) #define LANE_CFG1 0x181 #define bf_use_max_pll_rate BIT(9) +#define prd_txdeemph1_mask BIT(15) +#define tx_det_rx_mode BIT(6) +#define gen2_tx_data_dly_deft (2 << 3) +#define gen2_tx_data_dly_mask (BIT(3) | BIT(4)) +#define tx_elec_idle_mode_en BIT(0) #define LANE_CFG4 0x188 #define bf_spread_spectrum_clock_en BIT(7) -- cgit From 7586ac2b49dd3046868354201ab6a208c3a5b82c Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:21 +0200 Subject: phy: marvell: mux: Support nontrivial node order in selector register Currently comphy_mux supports only trivial order of nodes in pin selector register, that is lane N on position N*bitcount. Add support for nontrivial order, with map stored in device tree property mux-lane-order. This is needed for Armada 37xx. As far as I know, there is no driver for Armada 37xx comphy in the kernel. When such a driver comes, this will need to be rewritten to support the device tree bindings from the kernel. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy.h | 1 + drivers/phy/marvell/comphy_core.c | 4 ++++ drivers/phy/marvell/comphy_mux.c | 17 ++++++++++++++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/drivers/phy/marvell/comphy.h b/drivers/phy/marvell/comphy.h index 30ab52877b..b4027778be 100644 --- a/drivers/phy/marvell/comphy.h +++ b/drivers/phy/marvell/comphy.h @@ -96,6 +96,7 @@ struct chip_serdes_phy_config { void __iomem *hpipe3_base_addr; u32 comphy_lanes_count; u32 comphy_mux_bitcount; + const fdt32_t *comphy_mux_lane_order; u32 cp_index; }; diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index 17ab39c5d0..2622751f49 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -134,6 +134,10 @@ static int comphy_probe(struct udevice *dev) return -EINVAL; } + chip_cfg->comphy_mux_lane_order = + fdtdec_locate_array(blob, node, "mux-lane-order", + chip_cfg->comphy_lanes_count); + if (device_is_compatible(dev, "marvell,comphy-armada-3700")) chip_cfg->ptr_comphy_chip_init = comphy_a3700_init; diff --git a/drivers/phy/marvell/comphy_mux.c b/drivers/phy/marvell/comphy_mux.c index 0538702317..1f757d8e04 100644 --- a/drivers/phy/marvell/comphy_mux.c +++ b/drivers/phy/marvell/comphy_mux.c @@ -78,7 +78,8 @@ static u32 comphy_mux_get_mux_value(struct comphy_mux_data *mux_data, static void comphy_mux_reg_write(struct comphy_mux_data *mux_data, struct comphy_map *comphy_map_data, int comphy_max_lanes, - void __iomem *selector_base, u32 bitcount) + void __iomem *selector_base, + const fdt32_t *mux_lane_order, u32 bitcount) { u32 lane, value, offset, mask; @@ -89,7 +90,15 @@ static void comphy_mux_reg_write(struct comphy_mux_data *mux_data, if (comphy_map_data->type == PHY_TYPE_IGNORE) continue; - offset = lane * bitcount; + /* + * if the order of nodes in selector base register is + * nontrivial, use mapping from mux_lane_order + */ + if (mux_lane_order) + offset = fdt32_to_cpu(mux_lane_order[lane]) * bitcount; + else + offset = lane * bitcount; + mask = (((1 << bitcount) - 1) << offset); value = (comphy_mux_get_mux_value(mux_data, comphy_map_data->type, @@ -105,6 +114,7 @@ void comphy_mux_init(struct chip_serdes_phy_config *chip_cfg, void __iomem *selector_base) { struct comphy_mux_data *mux_data; + const fdt32_t *mux_lane_order; u32 mux_bitcount; u32 comphy_max_lanes; @@ -112,13 +122,14 @@ void comphy_mux_init(struct chip_serdes_phy_config *chip_cfg, comphy_max_lanes = chip_cfg->comphy_lanes_count; mux_data = chip_cfg->mux_data; + mux_lane_order = chip_cfg->comphy_mux_lane_order; mux_bitcount = chip_cfg->comphy_mux_bitcount; /* check if the configuration is valid */ comphy_mux_check_config(mux_data, comphy_map_data, comphy_max_lanes); /* Init COMPHY selectors */ comphy_mux_reg_write(mux_data, comphy_map_data, comphy_max_lanes, - selector_base, mux_bitcount); + selector_base, mux_lane_order, mux_bitcount); debug_exit(); } -- cgit From 3282a3e75fbea752f96df63baaad4c7f7d14d3b6 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:22 +0200 Subject: phy: marvell: a3700: Fix SGMII cfg and stat register addresses The register addresses on lanes 0 and 1 are switched, first comes 1 and then 0. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index 7990aab1c6..0f0138dc97 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -24,7 +24,7 @@ #define COMPHY_SEL_ADDR MVEBU_REG(0x0183FC) #define rf_compy_select(lane) (0x1 << (((lane) == 1) ? 4 : 0)) -#define COMPHY_PHY_CFG1_ADDR(lane) MVEBU_REG(0x018300 + (lane) * 0x28) +#define COMPHY_PHY_CFG1_ADDR(lane) MVEBU_REG(0x018300 + (1 - lane) * 0x28) #define rb_pin_pu_iveref BIT(1) #define rb_pin_reset_core BIT(11) #define rb_pin_reset_comphy BIT(12) @@ -38,7 +38,7 @@ #define rf_gen_tx_select (0x0F << rf_gen_tx_sel_shift) #define rb_phy_rx_init BIT(30) -#define COMPHY_PHY_STAT1_ADDR(lane) MVEBU_REG(0x018318 + (lane) * 0x28) +#define COMPHY_PHY_STAT1_ADDR(lane) MVEBU_REG(0x018318 + (1 - lane) * 0x28) #define rb_rx_init_done BIT(0) #define rb_pll_ready_rx BIT(2) #define rb_pll_ready_tx BIT(3) -- cgit From 22f418935be4f5c6de26d2563a61d68136d80586 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:23 +0200 Subject: phy: marvell: a3700: Use comphy_mux on Armada 37xx. Lane 0 supports SGMII1 and USB3. Lane 1 supports SGMII0 and PEX0. Lane 2 supports SATA0 and USB3. This is needed for Armada 37xx. This introduces new device tree bindings. AFAIK there is currently no driver for Armada 37xx comphy in Linux. When such a driver will be pushed into Linux, this will need to be rewritten accordingly. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- arch/arm/dts/armada-37xx.dtsi | 5 +++-- drivers/phy/marvell/comphy_a3700.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi index 54007428ed..040e8568e6 100644 --- a/arch/arm/dts/armada-37xx.dtsi +++ b/arch/arm/dts/armada-37xx.dtsi @@ -290,8 +290,9 @@ compatible = "marvell,mvebu-comphy", "marvell,comphy-armada-3700"; reg = <0x18300 0x28>, <0x1f300 0x3d000>; - mux-bitcount = <1>; - max-lanes = <2>; + mux-bitcount = <4>; + mux-lane-order = <1 0 2>; + max-lanes = <3>; }; }; diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 90e594fddc..bf68f5d6be 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -13,6 +13,38 @@ DECLARE_GLOBAL_DATA_PTR; +struct comphy_mux_data a3700_comphy_mux_data[] = { +/* Lane 0 */ + { + 4, + { + { PHY_TYPE_UNCONNECTED, 0x0 }, + { PHY_TYPE_SGMII1, 0x0 }, + { PHY_TYPE_USB3_HOST0, 0x1 }, + { PHY_TYPE_USB3_DEVICE, 0x1 } + } + }, +/* Lane 1 */ + { + 3, + { + { PHY_TYPE_UNCONNECTED, 0x0}, + { PHY_TYPE_SGMII0, 0x0}, + { PHY_TYPE_PEX0, 0x1} + } + }, +/* Lane 2 */ + { + 4, + { + { PHY_TYPE_UNCONNECTED, 0x0}, + { PHY_TYPE_SATA0, 0x0}, + { PHY_TYPE_USB3_HOST0, 0x1}, + { PHY_TYPE_USB3_DEVICE, 0x1} + } + }, +}; + struct sgmii_phy_init_data_fix { u16 addr; u16 value; @@ -932,6 +964,10 @@ int comphy_a3700_init(struct chip_serdes_phy_config *chip_cfg, debug_enter(); + /* Initialize PHY mux */ + chip_cfg->mux_data = a3700_comphy_mux_data; + comphy_mux_init(chip_cfg, serdes_map, COMPHY_SEL_ADDR); + for (lane = 0, comphy_map = serdes_map; lane < comphy_max_count; lane++, comphy_map++) { debug("Initialize serdes number %d\n", lane); -- cgit From 7288182aa6c11e4b0b2783cd4c7762f93f12cb64 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:24 +0200 Subject: phy: marvell: a3700: Save/restore selector reg in SGMII init In SGMII initialization PIN_PIPE_SEL has to be zero when resetting the PHY. Since comphy_mux already set the selector register to correct values, we have to store it's value before setting it to 0 and restore it after SGMII init. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 9 ++++++++- drivers/phy/marvell/comphy_a3700.h | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index bf68f5d6be..50167a69af 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -697,13 +697,15 @@ static void comphy_sgmii_phy_init(u32 lane, u32 speed) static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) { int ret; + u32 saved_selector; debug_enter(); /* * 1. Configure PHY to SATA/SAS mode by setting pin PIN_PIPE_SEL=0 */ - reg_set(COMPHY_SEL_ADDR, 0, rf_compy_select(lane)); + saved_selector = readl(COMPHY_SEL_ADDR); + reg_set(COMPHY_SEL_ADDR, 0, 0xFFFFFFFF); /* * 2. Reset PHY by setting PHY input port PIN_RESET=1. @@ -874,6 +876,11 @@ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) if (!ret) printf("Failed to init RX of SGMII PHY %d\n", lane); + /* + * Restore saved selector. + */ + reg_set(COMPHY_SEL_ADDR, saved_selector, 0xFFFFFFFF); + debug_exit(); return ret; diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index 0f0138dc97..a14767d809 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -22,7 +22,6 @@ * COMPHY SB definitions */ #define COMPHY_SEL_ADDR MVEBU_REG(0x0183FC) -#define rf_compy_select(lane) (0x1 << (((lane) == 1) ? 4 : 0)) #define COMPHY_PHY_CFG1_ADDR(lane) MVEBU_REG(0x018300 + (1 - lane) * 0x28) #define rb_pin_pu_iveref BIT(1) -- cgit From 82a248df9af7057152a1359e7405585419accc1e Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:25 +0200 Subject: driver: clk: Add support for clocks on Armada 37xx The drivers are based on Linux driver by Gregory Clement. The TBG clocks support only the .get_rate method. - since setting rate is not supported, the driver computes the rates when probing and so subsequent calls to the .get_rate method do not read the corresponding registers again The peripheral clocks support methods .get_rate, .enable and .disable. - the .set_parent method theoretically could be supported on some clocks (the parent would have to be one of the TBG clocks) - the .set_rate method would have to try all the divider values to find the best approximation of a given rate, and it doesn't seem like this should be needed in U-Boot, therefore not implemented Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- arch/arm/dts/armada-37xx.dtsi | 20 ++ drivers/clk/Kconfig | 1 + drivers/clk/Makefile | 1 + drivers/clk/mvebu/Kconfig | 11 + drivers/clk/mvebu/Makefile | 1 + drivers/clk/mvebu/armada-37xx-periph.c | 465 +++++++++++++++++++++++++++++++++ drivers/clk/mvebu/armada-37xx-tbg.c | 152 +++++++++++ 7 files changed, 651 insertions(+) create mode 100644 drivers/clk/mvebu/Kconfig create mode 100644 drivers/clk/mvebu/Makefile create mode 100644 drivers/clk/mvebu/armada-37xx-periph.c create mode 100644 drivers/clk/mvebu/armada-37xx-tbg.c diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi index 040e8568e6..c72fd25abc 100644 --- a/arch/arm/dts/armada-37xx.dtsi +++ b/arch/arm/dts/armada-37xx.dtsi @@ -107,6 +107,26 @@ status = "disabled"; }; + nb_periph_clk: nb-periph-clk@13000 { + compatible = "marvell,armada-3700-periph-clock-nb"; + reg = <0x13000 0x100>; + clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, <&tbg 3>; + #clock-cells = <1>; + }; + + sb_periph_clk: sb-periph-clk@18000 { + compatible = "marvell,armada-3700-periph-clock-sb"; + reg = <0x18000 0x100>; + clocks = <&tbg 0>, <&tbg 1>, <&tbg 2>, <&tbg 3>; + #clock-cells = <1>; + }; + + tbg: tbg@13200 { + compatible = "marvell,armada-3700-tbg-clock"; + reg = <0x13200 0x100>; + #clock-cells = <1>; + }; + pinctrl_nb: pinctrl-nb@13800 { compatible = "marvell,armada3710-nb-pinctrl", "syscon", "simple-mfd"; diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 60a6859c24..edb4ca58ea 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -88,6 +88,7 @@ source "drivers/clk/uniphier/Kconfig" source "drivers/clk/exynos/Kconfig" source "drivers/clk/at91/Kconfig" source "drivers/clk/renesas/Kconfig" +source "drivers/clk/mvebu/Kconfig" config ICS8N3QV01 bool "Enable ICS8N3QV01 VCXO driver" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 0b4f38527a..58139b13a8 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -11,6 +11,7 @@ obj-y += tegra/ obj-$(CONFIG_ARCH_ASPEED) += aspeed/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_CLK_AT91) += at91/ +obj-$(CONFIG_CLK_MVEBU) += mvebu/ obj-$(CONFIG_CLK_BCM6345) += clk_bcm6345.o obj-$(CONFIG_CLK_BOSTON) += clk_boston.o obj-$(CONFIG_CLK_EXYNOS) += exynos/ diff --git a/drivers/clk/mvebu/Kconfig b/drivers/clk/mvebu/Kconfig new file mode 100644 index 0000000000..e776a15e7b --- /dev/null +++ b/drivers/clk/mvebu/Kconfig @@ -0,0 +1,11 @@ +config CLK_MVEBU + bool "MVEBU clock drivers" + depends on CLK && ARCH_MVEBU + help + Enable support for clock present on Marvell MVEBU SoCs. + +config CLK_ARMADA_3720 + bool "Marvell Armada 3720 clock driver" + depends on CLK_MVEBU && ARM64 + help + Enable this to support the clocks on Marvell Armada 3720 SoC. diff --git a/drivers/clk/mvebu/Makefile b/drivers/clk/mvebu/Makefile new file mode 100644 index 0000000000..7f80313203 --- /dev/null +++ b/drivers/clk/mvebu/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_CLK_ARMADA_3720) += armada-37xx-periph.o armada-37xx-tbg.o diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c new file mode 100644 index 0000000000..af08e3df08 --- /dev/null +++ b/drivers/clk/mvebu/armada-37xx-periph.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell Armada 37xx SoC Peripheral clocks + * + * Marek Behun + * + * Based on Linux driver by: + * Gregory CLEMENT + */ + +#include +#include +#include +#include +#include +#include +#include + +#define TBG_SEL 0x0 +#define DIV_SEL0 0x4 +#define DIV_SEL1 0x8 +#define DIV_SEL2 0xC +#define CLK_SEL 0x10 +#define CLK_DIS 0x14 + +enum a37xx_periph_parent { + TBG_A_P = 0, + TBG_B_P = 1, + TBG_A_S = 2, + TBG_B_S = 3, + MAX_TBG_PARENTS = 4, + XTAL = 4, + MAX_PARENTS = 5, +}; + +static const struct { + const char *name; + enum a37xx_periph_parent parent; +} a37xx_periph_parent_names[] = { + { "TBG-A-P", TBG_A_P }, + { "TBG-B-P", TBG_B_P }, + { "TBG-A-S", TBG_A_S }, + { "TBG-B-S", TBG_B_S }, + { "xtal", XTAL }, +}; + +struct clk_periph; + +struct a37xx_periphclk { + void __iomem *reg; + + ulong parents[MAX_PARENTS]; + + const struct clk_periph *clks; + bool clk_has_periph_parent[16]; + int clk_parent[16]; + + int count; +}; + +struct clk_div_table { + u32 div; + u32 val; +}; + +struct clk_periph { + const char *name; + + const char *parent_name; + + u32 disable_bit; + int mux_shift; + + const struct clk_div_table *div_table[2]; + s32 div_reg_off[2]; + u32 div_mask[2]; + int div_shift[2]; + + unsigned can_gate : 1; + unsigned can_mux : 1; + unsigned dividers : 2; +}; + +static const struct clk_div_table div_table1[] = { + { 1, 1 }, + { 2, 2 }, + { 0, 0 }, +}; + +static const struct clk_div_table div_table2[] = { + { 2, 1 }, + { 4, 2 }, + { 0, 0 }, +}; + +static const struct clk_div_table div_table6[] = { + { 1, 1 }, + { 2, 2 }, + { 3, 3 }, + { 4, 4 }, + { 5, 5 }, + { 6, 6 }, + { 0, 0 }, +}; + +#define CLK_FULL_DD(_n, _d, _mux, _r0, _r1, _s0, _s1) \ + { \ + .name = #_n, \ + .disable_bit = BIT(_d), \ + .mux_shift = _mux, \ + .div_table[0] = div_table6, \ + .div_table[1] = div_table6, \ + .div_reg_off[0] = _r0, \ + .div_reg_off[1] = _r1, \ + .div_shift[0] = _s0, \ + .div_shift[1] = _s1, \ + .div_mask[0] = 7, \ + .div_mask[1] = 7, \ + .can_gate = 1, \ + .can_mux = 1, \ + .dividers = 2, \ + } + +#define CLK_FULL(_n, _d, _mux, _r, _s, _m, _t) \ + { \ + .name = #_n, \ + .disable_bit = BIT(_d), \ + .mux_shift = _mux, \ + .div_table[0] = _t, \ + .div_reg_off[0] = _r, \ + .div_shift[0] = _s, \ + .div_mask[0] = _m, \ + .can_gate = 1, \ + .can_mux = 1, \ + .dividers = 1, \ + } + +#define CLK_GATE_DIV(_n, _d, _r, _s, _m, _t, _p) \ + { \ + .name = #_n, \ + .parent_name = _p, \ + .disable_bit = BIT(_d), \ + .div_table[0] = _t, \ + .div_reg_off[0] = _r, \ + .div_shift[0] = _s, \ + .div_mask[0] = _m, \ + .can_gate = 1, \ + .dividers = 1, \ + } + +#define CLK_GATE(_n, _d, _p) \ + { \ + .name = #_n, \ + .parent_name = _p, \ + .disable_bit = BIT(_d), \ + .can_gate = 1, \ + } + +#define CLK_MUX_DIV(_n, _mux, _r, _s, _m, _t) \ + { \ + .name = #_n, \ + .mux_shift = _mux, \ + .div_table[0] = _t, \ + .div_reg_off[0] = _r, \ + .div_shift[0] = _s, \ + .div_mask[0] = _m, \ + .can_mux = 1, \ + .dividers = 1, \ + } + +#define CLK_MUX_DD(_n, _mux, _r0, _r1, _s0, _s1) \ + { \ + .name = #_n, \ + .mux_shift = _mux, \ + .div_table[0] = div_table6, \ + .div_table[1] = div_table6, \ + .div_reg_off[0] = _r0, \ + .div_reg_off[1] = _r1, \ + .div_shift[0] = _s0, \ + .div_shift[1] = _s1, \ + .div_mask[0] = 7, \ + .div_mask[1] = 7, \ + .can_mux = 1, \ + .dividers = 2, \ + } + +/* NB periph clocks */ +static const struct clk_periph clks_nb[] = { + CLK_FULL_DD(mmc, 2, 0, DIV_SEL2, DIV_SEL2, 16, 13), + CLK_FULL_DD(sata_host, 3, 2, DIV_SEL2, DIV_SEL2, 10, 7), + CLK_FULL_DD(sec_at, 6, 4, DIV_SEL1, DIV_SEL1, 3, 0), + CLK_FULL_DD(sec_dap, 7, 6, DIV_SEL1, DIV_SEL1, 9, 6), + CLK_FULL_DD(tscem, 8, 8, DIV_SEL1, DIV_SEL1, 15, 12), + CLK_FULL(tscem_tmx, 10, 10, DIV_SEL1, 18, 7, div_table6), + CLK_GATE(avs, 11, "xtal"), + CLK_FULL_DD(sqf, 12, 12, DIV_SEL1, DIV_SEL1, 27, 24), + CLK_FULL_DD(pwm, 13, 14, DIV_SEL0, DIV_SEL0, 3, 0), + CLK_GATE(i2c_2, 16, "xtal"), + CLK_GATE(i2c_1, 17, "xtal"), + CLK_GATE_DIV(ddr_phy, 19, DIV_SEL0, 18, 1, div_table2, "TBG-A-S"), + CLK_FULL_DD(ddr_fclk, 21, 16, DIV_SEL0, DIV_SEL0, 15, 12), + CLK_FULL(trace, 22, 18, DIV_SEL0, 20, 7, div_table6), + CLK_FULL(counter, 23, 20, DIV_SEL0, 23, 7, div_table6), + CLK_FULL_DD(eip97, 24, 24, DIV_SEL2, DIV_SEL2, 22, 19), + CLK_MUX_DIV(cpu, 22, DIV_SEL0, 28, 7, div_table6), + { }, +}; + +/* SB periph clocks */ +static const struct clk_periph clks_sb[] = { + CLK_MUX_DD(gbe_50, 6, DIV_SEL2, DIV_SEL2, 6, 9), + CLK_MUX_DD(gbe_core, 8, DIV_SEL1, DIV_SEL1, 18, 21), + CLK_MUX_DD(gbe_125, 10, DIV_SEL1, DIV_SEL1, 6, 9), + CLK_GATE(gbe1_50, 0, "gbe_50"), + CLK_GATE(gbe0_50, 1, "gbe_50"), + CLK_GATE(gbe1_125, 2, "gbe_125"), + CLK_GATE(gbe0_125, 3, "gbe_125"), + CLK_GATE_DIV(gbe1_core, 4, DIV_SEL1, 13, 1, div_table1, "gbe_core"), + CLK_GATE_DIV(gbe0_core, 5, DIV_SEL1, 14, 1, div_table1, "gbe_core"), + CLK_GATE_DIV(gbe_bm, 12, DIV_SEL1, 0, 1, div_table1, "gbe_core"), + CLK_FULL_DD(sdio, 11, 14, DIV_SEL0, DIV_SEL0, 3, 6), + CLK_FULL_DD(usb32_usb2_sys, 16, 16, DIV_SEL0, DIV_SEL0, 9, 12), + CLK_FULL_DD(usb32_ss_sys, 17, 18, DIV_SEL0, DIV_SEL0, 15, 18), + { }, +}; + +static inline int get_mux(struct a37xx_periphclk *priv, int shift) +{ + return (readl(priv->reg + TBG_SEL) >> shift) & 3; +} + +static ulong periph_clk_get_rate(struct a37xx_periphclk *priv, int id); + +static ulong get_parent_rate(struct a37xx_periphclk *priv, int id) +{ + const struct clk_periph *clk = &priv->clks[id]; + ulong res; + + if (clk->can_mux) { + /* parent is one of TBG clocks */ + int tbg = get_mux(priv, clk->mux_shift); + + res = priv->parents[tbg]; + } else if (priv->clk_has_periph_parent[id]) { + /* parent is one of other periph clocks */ + + if (priv->clk_parent[id] >= priv->count) + return -EINVAL; + + res = periph_clk_get_rate(priv, priv->clk_parent[id]); + } else { + /* otherwise parent is one of TBGs or XTAL */ + + if (priv->clk_parent[id] >= MAX_PARENTS) + return -EINVAL; + + res = priv->parents[priv->clk_parent[id]]; + } + + return res; +} + +static ulong get_div(struct a37xx_periphclk *priv, + const struct clk_periph *clk, int idx) +{ + const struct clk_div_table *i; + u32 reg; + + reg = readl(priv->reg + clk->div_reg_off[idx]); + reg = (reg >> clk->div_shift[idx]) & clk->div_mask[idx]; + + /* find divisor for register value val */ + for (i = clk->div_table[idx]; i && i->div != 0; ++i) + if (i->val == reg) + return i->div; + + return 0; +} + +static ulong periph_clk_get_rate(struct a37xx_periphclk *priv, int id) +{ + const struct clk_periph *clk = &priv->clks[id]; + ulong rate, div; + int i; + + rate = get_parent_rate(priv, id); + if (rate == -EINVAL) + return -EINVAL; + + /* divide the parent rate by dividers */ + div = 1; + for (i = 0; i < clk->dividers; ++i) + div *= get_div(priv, clk, i); + + if (!div) + return 0; + + return DIV_ROUND_UP(rate, div); +} + +static ulong armada_37xx_periph_clk_get_rate(struct clk *clk) +{ + struct a37xx_periphclk *priv = dev_get_priv(clk->dev); + + if (clk->id >= priv->count) + return -EINVAL; + + return periph_clk_get_rate(priv, clk->id); +} + +static int periph_clk_enable(struct clk *clk, int enable) +{ + struct a37xx_periphclk *priv = dev_get_priv(clk->dev); + const struct clk_periph *periph_clk = &priv->clks[clk->id]; + + if (clk->id >= priv->count) + return -EINVAL; + + if (!periph_clk->can_gate) + return -ENOTSUPP; + + if (enable) + clrbits_le32(priv->reg + CLK_DIS, periph_clk->disable_bit); + else + setbits_le32(priv->reg + CLK_DIS, periph_clk->disable_bit); + + return 0; +} + +static int armada_37xx_periph_clk_enable(struct clk *clk) +{ + return periph_clk_enable(clk, 1); +} + +static int armada_37xx_periph_clk_disable(struct clk *clk) +{ + return periph_clk_enable(clk, 0); +} + +int armada_37xx_periph_clk_dump(struct udevice *dev) +{ + struct a37xx_periphclk *priv = dev_get_priv(dev); + const struct clk_periph *clks; + int i; + + if (!priv) + return -ENODEV; + + clks = priv->clks; + + for (i = 0; i < priv->count; ++i) + printf(" %s at %lu Hz\n", clks[i].name, + periph_clk_get_rate(priv, i)); + printf("\n"); + + return 0; +} + +static int armada_37xx_periph_clk_probe(struct udevice *dev) +{ + struct a37xx_periphclk *priv = dev_get_priv(dev); + const struct clk_periph *clks; + int ret, i; + + clks = (const struct clk_periph *)dev_get_driver_data(dev); + if (!clks) + return -ENODEV; + + priv->reg = dev_read_addr_ptr(dev); + if (!priv->reg) { + dev_err(dev, "no io address\n"); + return -ENODEV; + } + + /* count clk_periph nodes */ + priv->count = 0; + while (clks[priv->count].name) + priv->count++; + + priv->clks = clks; + + /* assign parent IDs to nodes which have non-NULL parent_name */ + for (i = 0; i < priv->count; ++i) { + int j; + + if (!clks[i].parent_name) + continue; + + /* first try if parent_name is one of TBGs or XTAL */ + for (j = 0; j < MAX_PARENTS; ++j) + if (!strcmp(clks[i].parent_name, + a37xx_periph_parent_names[j].name)) + break; + + if (j < MAX_PARENTS) { + priv->clk_has_periph_parent[i] = false; + priv->clk_parent[i] = + a37xx_periph_parent_names[j].parent; + continue; + } + + /* else parent_name should be one of other periph clocks */ + for (j = 0; j < priv->count; ++j) { + if (!strcmp(clks[i].parent_name, clks[j].name)) + break; + } + + if (j < priv->count) { + priv->clk_has_periph_parent[i] = true; + priv->clk_parent[i] = j; + continue; + } + + dev_err(dev, "undefined parent %s\n", clks[i].parent_name); + return -EINVAL; + } + + for (i = 0; i < MAX_PARENTS; ++i) { + struct clk clk; + + if (i == XTAL) { + priv->parents[i] = get_ref_clk() * 1000000; + continue; + } + + ret = clk_get_by_index(dev, i, &clk); + if (ret) { + dev_err(dev, "one of parent clocks (%i) missing: %i\n", + i, ret); + return -ENODEV; + } + + priv->parents[i] = clk_get_rate(&clk); + clk_free(&clk); + } + + return 0; +} + +static const struct clk_ops armada_37xx_periph_clk_ops = { + .get_rate = armada_37xx_periph_clk_get_rate, + .enable = armada_37xx_periph_clk_enable, + .disable = armada_37xx_periph_clk_disable, +}; + +static const struct udevice_id armada_37xx_periph_clk_ids[] = { + { + .compatible = "marvell,armada-3700-periph-clock-nb", + .data = (ulong)clks_nb, + }, + { + .compatible = "marvell,armada-3700-periph-clock-sb", + .data = (ulong)clks_sb, + }, + {} +}; + +U_BOOT_DRIVER(armada_37xx_periph_clk) = { + .name = "armada_37xx_periph_clk", + .id = UCLASS_CLK, + .of_match = armada_37xx_periph_clk_ids, + .ops = &armada_37xx_periph_clk_ops, + .priv_auto_alloc_size = sizeof(struct a37xx_periphclk), + .probe = armada_37xx_periph_clk_probe, +}; diff --git a/drivers/clk/mvebu/armada-37xx-tbg.c b/drivers/clk/mvebu/armada-37xx-tbg.c new file mode 100644 index 0000000000..c035b8f1fa --- /dev/null +++ b/drivers/clk/mvebu/armada-37xx-tbg.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell Armada 37xx SoC Time Base Generator clocks + * + * Marek Behun + * + * Based on Linux driver by: + * Gregory CLEMENT + */ + +#include +#include +#include +#include +#include +#include + +#define NUM_TBG 4 + +#define TBG_CTRL0 0x4 +#define TBG_CTRL1 0x8 +#define TBG_CTRL7 0x20 +#define TBG_CTRL8 0x30 + +#define TBG_DIV_MASK 0x1FF + +#define TBG_A_REFDIV 0 +#define TBG_B_REFDIV 16 + +#define TBG_A_FBDIV 2 +#define TBG_B_FBDIV 18 + +#define TBG_A_VCODIV_SE 0 +#define TBG_B_VCODIV_SE 16 + +#define TBG_A_VCODIV_DIFF 1 +#define TBG_B_VCODIV_DIFF 17 + +struct tbg_def { + const char *name; + u32 refdiv_offset; + u32 fbdiv_offset; + u32 vcodiv_reg; + u32 vcodiv_offset; +}; + +static const struct tbg_def tbg[NUM_TBG] = { + {"TBG-A-P", TBG_A_REFDIV, TBG_A_FBDIV, TBG_CTRL8, TBG_A_VCODIV_DIFF}, + {"TBG-B-P", TBG_B_REFDIV, TBG_B_FBDIV, TBG_CTRL8, TBG_B_VCODIV_DIFF}, + {"TBG-A-S", TBG_A_REFDIV, TBG_A_FBDIV, TBG_CTRL1, TBG_A_VCODIV_SE}, + {"TBG-B-S", TBG_B_REFDIV, TBG_B_FBDIV, TBG_CTRL1, TBG_B_VCODIV_SE}, +}; + +struct a37xx_tbgclk { + ulong rates[NUM_TBG]; + unsigned int mult[NUM_TBG]; + unsigned int div[NUM_TBG]; +}; + +static unsigned int tbg_get_mult(void __iomem *reg, const struct tbg_def *ptbg) +{ + u32 val; + + val = readl(reg + TBG_CTRL0); + + return ((val >> ptbg->fbdiv_offset) & TBG_DIV_MASK) << 2; +} + +static unsigned int tbg_get_div(void __iomem *reg, const struct tbg_def *ptbg) +{ + u32 val; + unsigned int div; + + val = readl(reg + TBG_CTRL7); + + div = (val >> ptbg->refdiv_offset) & TBG_DIV_MASK; + if (div == 0) + div = 1; + val = readl(reg + ptbg->vcodiv_reg); + + div *= 1 << ((val >> ptbg->vcodiv_offset) & TBG_DIV_MASK); + + return div; +} + +static ulong armada_37xx_tbg_clk_get_rate(struct clk *clk) +{ + struct a37xx_tbgclk *priv = dev_get_priv(clk->dev); + + if (clk->id >= NUM_TBG) + return -ENODEV; + + return priv->rates[clk->id]; +} + +int armada_37xx_tbg_clk_dump(struct udevice *dev) +{ + struct a37xx_tbgclk *priv = dev_get_priv(dev); + int i; + + for (i = 0; i < NUM_TBG; ++i) + printf(" %s at %lu Hz\n", tbg[i].name, + priv->rates[i]); + printf("\n"); + + return 0; +} + +static int armada_37xx_tbg_clk_probe(struct udevice *dev) +{ + struct a37xx_tbgclk *priv = dev_get_priv(dev); + void __iomem *reg; + ulong xtal; + int i; + + reg = dev_read_addr_ptr(dev); + if (!reg) { + dev_err(dev, "no io address\n"); + return -ENODEV; + } + + xtal = (ulong)get_ref_clk() * 1000000; + + for (i = 0; i < NUM_TBG; ++i) { + unsigned int mult, div; + + mult = tbg_get_mult(reg, &tbg[i]); + div = tbg_get_div(reg, &tbg[i]); + + priv->rates[i] = (xtal * mult) / div; + } + + return 0; +} + +static const struct clk_ops armada_37xx_tbg_clk_ops = { + .get_rate = armada_37xx_tbg_clk_get_rate, +}; + +static const struct udevice_id armada_37xx_tbg_clk_ids[] = { + { .compatible = "marvell,armada-3700-tbg-clock" }, + {} +}; + +U_BOOT_DRIVER(armada_37xx_tbg_clk) = { + .name = "armada_37xx_tbg_clk", + .id = UCLASS_CLK, + .of_match = armada_37xx_tbg_clk_ids, + .ops = &armada_37xx_tbg_clk_ops, + .priv_auto_alloc_size = sizeof(struct a37xx_tbgclk), + .probe = armada_37xx_tbg_clk_probe, +}; -- cgit From dbbd5bdd27437909dac5c664303cd6e0fe420f39 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:26 +0200 Subject: spi: mvebu_a3700_spi: Use Armada 37xx clk driver for SPI clock frequency Since now we have driver for clocks on Armada 37xx, use it to determine SQF clock frequency for the SPI driver. Also change the default config files for Armada 37xx devices so that the clock driver is enabled by default, otherwise the SPI driver cannot be enabled. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- arch/arm/dts/armada-37xx.dtsi | 4 +-- configs/mvebu_db-88f3720_defconfig | 3 ++ configs/mvebu_espressobin-88f3720_defconfig | 3 ++ drivers/spi/Kconfig | 1 + drivers/spi/mvebu_a3700_spi.c | 52 ++++++++++++++++------------- 5 files changed, 37 insertions(+), 26 deletions(-) diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi index c72fd25abc..5b4a1a49bb 100644 --- a/arch/arm/dts/armada-37xx.dtsi +++ b/arch/arm/dts/armada-37xx.dtsi @@ -301,8 +301,8 @@ #address-cells = <1>; #size-cells = <0>; #clock-cells = <0>; - clock-frequency = <160000>; - spi-max-frequency = <40000>; + spi-max-frequency = <50000000>; + clocks = <&nb_periph_clk 7>; status = "disabled"; }; diff --git a/configs/mvebu_db-88f3720_defconfig b/configs/mvebu_db-88f3720_defconfig index 67a8077a58..691d7211dc 100644 --- a/configs/mvebu_db-88f3720_defconfig +++ b/configs/mvebu_db-88f3720_defconfig @@ -36,6 +36,9 @@ CONFIG_DM_GPIO=y # CONFIG_MVEBU_GPIO is not set CONFIG_DM_I2C=y CONFIG_MISC=y +CONFIG_CLK=y +CONFIG_CLK_MVEBU=y +CONFIG_CLK_ARMADA_3720=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y diff --git a/configs/mvebu_espressobin-88f3720_defconfig b/configs/mvebu_espressobin-88f3720_defconfig index 48dae2d791..60259bcf2c 100644 --- a/configs/mvebu_espressobin-88f3720_defconfig +++ b/configs/mvebu_espressobin-88f3720_defconfig @@ -35,6 +35,9 @@ CONFIG_BLOCK_CACHE=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_MISC=y +CONFIG_CLK=y +CONFIG_CLK_MVEBU=y +CONFIG_CLK_ARMADA_3720=y CONFIG_DM_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6667f7321f..3532c2ad46 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -104,6 +104,7 @@ config ICH_SPI config MVEBU_A3700_SPI bool "Marvell Armada 3700 SPI driver" + select CLK_ARMADA_3720 help Enable the Marvell Armada 3700 SPI driver. This driver can be used to access the SPI NOR flash on platforms embedding this diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c index e99252e153..feeafdceaa 100644 --- a/drivers/spi/mvebu_a3700_spi.c +++ b/drivers/spi/mvebu_a3700_spi.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -21,9 +22,8 @@ DECLARE_GLOBAL_DATA_PTR; #define MVEBU_SPI_A3700_CLK_POL BIT(7) #define MVEBU_SPI_A3700_FIFO_EN BIT(17) #define MVEBU_SPI_A3700_SPI_EN_0 BIT(16) -#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT 0 -#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK \ - (0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT) +#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK 0x1f + /* SPI registers */ struct spi_reg { @@ -35,8 +35,7 @@ struct spi_reg { struct mvebu_spi_platdata { struct spi_reg *spireg; - unsigned int frequency; - unsigned int clock; + struct clk clk; }; static void spi_cs_activate(struct spi_reg *reg, int cs) @@ -177,17 +176,18 @@ static int mvebu_spi_set_speed(struct udevice *bus, uint hz) { struct mvebu_spi_platdata *plat = dev_get_platdata(bus); struct spi_reg *reg = plat->spireg; - u32 data; + u32 data, prescale; data = readl(®->cfg); - /* Set Prescaler */ - data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK; + prescale = DIV_ROUND_UP(clk_get_rate(&plat->clk), hz); + if (prescale > 0x1f) + prescale = 0x1f; + else if (prescale > 0xf) + prescale = 0x10 + (prescale + 1) / 2; - /* Calculate Prescaler = (spi_input_freq / spi_max_freq) */ - if (hz > plat->frequency) - hz = plat->frequency; - data |= plat->clock / hz; + data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK; + data |= prescale & MVEBU_SPI_A3700_CLK_PRESCALE_MASK; writel(data, ®->cfg); @@ -251,21 +251,24 @@ static int mvebu_spi_probe(struct udevice *bus) static int mvebu_spi_ofdata_to_platdata(struct udevice *bus) { struct mvebu_spi_platdata *plat = dev_get_platdata(bus); + int ret; plat->spireg = (struct spi_reg *)devfdt_get_addr(bus); - /* - * FIXME - * Right now, mvebu does not have a clock infrastructure in U-Boot - * which should be used to query the input clock to the SPI - * controller. Once this clock driver is integrated into U-Boot - * it should be used to read the input clock and the DT property - * can be removed. - */ - plat->clock = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus), - "clock-frequency", 160000); - plat->frequency = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus), - "spi-max-frequency", 40000); + ret = clk_get_by_index(bus, 0, &plat->clk); + if (ret) { + dev_err(bus, "cannot get clock\n"); + return ret; + } + + return 0; +} + +static int mvebu_spi_remove(struct udevice *bus) +{ + struct mvebu_spi_platdata *plat = dev_get_platdata(bus); + + clk_free(&plat->clk); return 0; } @@ -293,4 +296,5 @@ U_BOOT_DRIVER(mvebu_spi) = { .ofdata_to_platdata = mvebu_spi_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata), .probe = mvebu_spi_probe, + .remove = mvebu_spi_remove, }; -- cgit From dd77690c434f02b985c9c30be66943ffc1fea48c Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:27 +0200 Subject: clk: armada-37xx: Support soc_clk_dump Add support for the clk dump command on Armada 37xx. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- drivers/clk/mvebu/armada-37xx-periph.c | 36 +++++++++++++++++++++++++++++++++- drivers/clk/mvebu/armada-37xx-tbg.c | 2 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c index af08e3df08..902a6cc9ef 100644 --- a/drivers/clk/mvebu/armada-37xx-periph.c +++ b/drivers/clk/mvebu/armada-37xx-periph.c @@ -337,7 +337,8 @@ static int armada_37xx_periph_clk_disable(struct clk *clk) return periph_clk_enable(clk, 0); } -int armada_37xx_periph_clk_dump(struct udevice *dev) +#if defined(CONFIG_CMD_CLK) && defined(CONFIG_CLK_ARMADA_3720) +static int armada_37xx_periph_clk_dump(struct udevice *dev) { struct a37xx_periphclk *priv = dev_get_priv(dev); const struct clk_periph *clks; @@ -356,6 +357,39 @@ int armada_37xx_periph_clk_dump(struct udevice *dev) return 0; } +static int clk_dump(const char *name, int (*func)(struct udevice *)) +{ + struct udevice *dev; + + if (uclass_get_device_by_name(UCLASS_CLK, name, &dev)) { + printf("Cannot find device %s\n", name); + return -ENODEV; + } + + return func(dev); +} + +int armada_37xx_tbg_clk_dump(struct udevice *); + +int soc_clk_dump(void) +{ + printf(" xtal at %u000000 Hz\n\n", get_ref_clk()); + + if (clk_dump("tbg@13200", armada_37xx_tbg_clk_dump)) + return 1; + + if (clk_dump("nb-periph-clk@13000", + armada_37xx_periph_clk_dump)) + return 1; + + if (clk_dump("sb-periph-clk@18000", + armada_37xx_periph_clk_dump)) + return 1; + + return 0; +} +#endif + static int armada_37xx_periph_clk_probe(struct udevice *dev) { struct a37xx_periphclk *priv = dev_get_priv(dev); diff --git a/drivers/clk/mvebu/armada-37xx-tbg.c b/drivers/clk/mvebu/armada-37xx-tbg.c index c035b8f1fa..aa7ccd690f 100644 --- a/drivers/clk/mvebu/armada-37xx-tbg.c +++ b/drivers/clk/mvebu/armada-37xx-tbg.c @@ -93,6 +93,7 @@ static ulong armada_37xx_tbg_clk_get_rate(struct clk *clk) return priv->rates[clk->id]; } +#if defined(CONFIG_CMD_CLK) && defined(CONFIG_CLK_ARMADA_3720) int armada_37xx_tbg_clk_dump(struct udevice *dev) { struct a37xx_tbgclk *priv = dev_get_priv(dev); @@ -105,6 +106,7 @@ int armada_37xx_tbg_clk_dump(struct udevice *dev) return 0; } +#endif static int armada_37xx_tbg_clk_probe(struct udevice *dev) { -- cgit From 2d7a0f4399f924422e959613b4c2634dcd0ad87e Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:28 +0200 Subject: phy: marvell: core: Cosmetic fixes Move the reg_set* functions into comphy.h as static inline functions. Change return type of get_*_string to const char *. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy.h | 41 ++++++++++++++++++++++--- drivers/phy/marvell/comphy_core.c | 64 +++++++++------------------------------ 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/drivers/phy/marvell/comphy.h b/drivers/phy/marvell/comphy.h index b4027778be..b588ae41f0 100644 --- a/drivers/phy/marvell/comphy.h +++ b/drivers/phy/marvell/comphy.h @@ -101,10 +101,43 @@ struct chip_serdes_phy_config { }; /* Register helper functions */ -void reg_set(void __iomem *addr, u32 data, u32 mask); -void reg_set_silent(void __iomem *addr, u32 data, u32 mask); -void reg_set16(void __iomem *addr, u16 data, u16 mask); -void reg_set_silent16(void __iomem *addr, u16 data, u16 mask); +static inline void reg_set_silent(void __iomem *addr, u32 data, u32 mask) +{ + u32 reg_data; + + reg_data = readl(addr); + reg_data &= ~mask; + reg_data |= data; + writel(reg_data, addr); +} + +static inline void reg_set(void __iomem *addr, u32 data, u32 mask) +{ + debug("Write to address = %#010lx, data = %#010x (mask = %#010x) - ", + (unsigned long)addr, data, mask); + debug("old value = %#010x ==> ", readl(addr)); + reg_set_silent(addr, data, mask); + debug("new value %#010x\n", readl(addr)); +} + +static inline void reg_set_silent16(void __iomem *addr, u16 data, u16 mask) +{ + u16 reg_data; + + reg_data = readw(addr); + reg_data &= ~mask; + reg_data |= data; + writew(reg_data, addr); +} + +static inline void reg_set16(void __iomem *addr, u16 data, u16 mask) +{ + debug("Write to address = %#010lx, data = %#06x (mask = %#06x) - ", + (unsigned long)addr, data, mask); + debug("old value = %#06x ==> ", readw(addr)); + reg_set_silent16(addr, data, mask); + debug("new value %#06x\n", readw(addr)); +} /* SoC specific init functions */ #ifdef CONFIG_ARMADA_3700 diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index 2622751f49..c6e2cc8897 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -17,11 +17,13 @@ DECLARE_GLOBAL_DATA_PTR; -static char *get_speed_string(u32 speed) +static const char *get_speed_string(u32 speed) { - char *speed_strings[] = {"1.25 Gbps", "1.5 Gbps", "2.5 Gbps", - "3.0 Gbps", "3.125 Gbps", "5 Gbps", "6 Gbps", - "6.25 Gbps", "10.31 Gbps" }; + static const char * const speed_strings[] = { + "1.25 Gbps", "1.5 Gbps", "2.5 Gbps", + "3.0 Gbps", "3.125 Gbps", "5 Gbps", "6 Gbps", + "6.25 Gbps", "10.31 Gbps" + }; if (speed < 0 || speed > PHY_SPEED_MAX) return "invalid"; @@ -29,14 +31,16 @@ static char *get_speed_string(u32 speed) return speed_strings[speed]; } -static char *get_type_string(u32 type) +static const char *get_type_string(u32 type) { - char *type_strings[] = {"UNCONNECTED", "PEX0", "PEX1", "PEX2", "PEX3", - "SATA0", "SATA1", "SATA2", "SATA3", "SGMII0", - "SGMII1", "SGMII2", "SGMII3", "QSGMII", - "USB3_HOST0", "USB3_HOST1", "USB3_DEVICE", - "XAUI0", "XAUI1", "XAUI2", "XAUI3", - "RXAUI0", "RXAUI1", "SFI", "IGNORE"}; + static const char * const type_strings[] = { + "UNCONNECTED", "PEX0", "PEX1", "PEX2", "PEX3", + "SATA0", "SATA1", "SATA2", "SATA3", "SGMII0", + "SGMII1", "SGMII2", "SGMII3", "QSGMII", + "USB3_HOST0", "USB3_HOST1", "USB3_DEVICE", + "XAUI0", "XAUI1", "XAUI2", "XAUI3", + "RXAUI0", "RXAUI1", "SFI", "IGNORE" + }; if (type < 0 || type > PHY_TYPE_MAX) return "invalid"; @@ -44,44 +48,6 @@ static char *get_type_string(u32 type) return type_strings[type]; } -void reg_set(void __iomem *addr, u32 data, u32 mask) -{ - debug("Write to address = %#010lx, data = %#010x (mask = %#010x) - ", - (unsigned long)addr, data, mask); - debug("old value = %#010x ==> ", readl(addr)); - reg_set_silent(addr, data, mask); - debug("new value %#010x\n", readl(addr)); -} - -void reg_set_silent(void __iomem *addr, u32 data, u32 mask) -{ - u32 reg_data; - - reg_data = readl(addr); - reg_data &= ~mask; - reg_data |= data; - writel(reg_data, addr); -} - -void reg_set16(void __iomem *addr, u16 data, u16 mask) -{ - debug("Write to address = %#010lx, data = %#06x (mask = %#06x) - ", - (unsigned long)addr, data, mask); - debug("old value = %#06x ==> ", readw(addr)); - reg_set_silent16(addr, data, mask); - debug("new value %#06x\n", readw(addr)); -} - -void reg_set_silent16(void __iomem *addr, u16 data, u16 mask) -{ - u16 reg_data; - - reg_data = readw(addr); - reg_data &= ~mask; - reg_data |= data; - writew(reg_data, addr); -} - void comphy_print(struct chip_serdes_phy_config *chip_cfg, struct comphy_map *comphy_map_data) { -- cgit From cf2cf8510a10d954ea46b4a49a7bf9d95cccf4bd Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:29 +0200 Subject: net: mvneta: Fix fault when wrong device tree The driver does not check id phy_connect failed (for example on wrong property name in device tree). In such a case a fault occurs and the CPU is restarted. Signed-off-by: Marek Behun Reviewed-by: Stefan Roese Signed-off-by: Stefan Roese --- drivers/net/mvneta.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index 6eacd6116a..7036b517b4 100644 --- a/drivers/net/mvneta.c +++ b/drivers/net/mvneta.c @@ -1562,6 +1562,10 @@ static int mvneta_start(struct udevice *dev) phydev = phy_connect(pp->bus, pp->phyaddr, dev, pp->phy_interface); + if (!phydev) { + printf("phy_connect failed\n"); + return -ENODEV; + } pp->phydev = phydev; phy_config(phydev); -- cgit From 2b69a67389fc43d7e16ef8c31d2a8845572acff6 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:30 +0200 Subject: watchdog: Add support for Armada 37xx CPU watchdog This adds support for the CPU watchdog found on Marvell Armada 37xx SoCs. There are 4 counters which can be set as CPU watchdog counters. This driver uses the second counter (ID 1, counting from 0) (Marvell's Linux also uses second counter by default). In the future it could be adapted to use other counters, with definition in the device tree. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- arch/arm/dts/armada-37xx.dtsi | 6 ++ drivers/watchdog/Kconfig | 9 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/armada-37xx-wdt.c | 175 +++++++++++++++++++++++++++++++++++++ 4 files changed, 191 insertions(+) create mode 100644 drivers/watchdog/armada-37xx-wdt.c diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi index 5b4a1a49bb..a1052add0c 100644 --- a/arch/arm/dts/armada-37xx.dtsi +++ b/arch/arm/dts/armada-37xx.dtsi @@ -107,6 +107,12 @@ status = "disabled"; }; + wdt: watchdog-timer@8300 { + compatible = "marvell,armada-3700-wdt"; + reg = <0xd064 0x4>, + <0x8300 0x40>; + }; + nb_periph_clk: nb-periph-clk@13000 { compatible = "marvell,armada-3700-periph-clock-nb"; reg = <0x13000 0x100>; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index dca2c901ac..148c6a0d68 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -60,6 +60,15 @@ config WDT_SANDBOX can be probed and supports all of the methods of WDT, but does not really do anything. +config WDT_ARMADA_37XX + bool "Marvell Armada 37xx watchdog timer support" + depends on WDT && ARMADA_3700 + help + Enable this to support Watchdog Timer on Marvell Armada 37xx SoC. + There are 4 possible clocks which can be used on these SoCs. This + driver uses the second clock (ID 1), assuming that so will also + Linux's driver. + config WDT_ASPEED bool "Aspeed ast2400/ast2500 watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index c6f8aa3b13..f405f51b93 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_TANGIER_WATCHDOG) += tangier_wdt.o obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o obj-$(CONFIG_WDT) += wdt-uclass.o obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o +obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o diff --git a/drivers/watchdog/armada-37xx-wdt.c b/drivers/watchdog/armada-37xx-wdt.c new file mode 100644 index 0000000000..0fa4fda4fc --- /dev/null +++ b/drivers/watchdog/armada-37xx-wdt.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Marvell Armada 37xx SoC Watchdog Driver + * + * Marek Behun + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct a37xx_wdt { + void __iomem *sel_reg; + void __iomem *reg; + ulong clk_rate; + u64 timeout; +}; + +/* + * We use Counter 1 for watchdog timer, because so does Marvell's Linux by + * default. + */ + +#define CNTR_CTRL 0x10 +#define CNTR_CTRL_ENABLE 0x0001 +#define CNTR_CTRL_ACTIVE 0x0002 +#define CNTR_CTRL_MODE_MASK 0x000c +#define CNTR_CTRL_MODE_ONESHOT 0x0000 +#define CNTR_CTRL_PRESCALE_MASK 0xff00 +#define CNTR_CTRL_PRESCALE_MIN 2 +#define CNTR_CTRL_PRESCALE_SHIFT 8 + +#define CNTR_COUNT_LOW 0x14 +#define CNTR_COUNT_HIGH 0x18 + +static void set_counter_value(struct a37xx_wdt *priv) +{ + writel(priv->timeout & 0xffffffff, priv->reg + CNTR_COUNT_LOW); + writel(priv->timeout >> 32, priv->reg + CNTR_COUNT_HIGH); +} + +static void a37xx_wdt_enable(struct a37xx_wdt *priv) +{ + u32 reg = readl(priv->reg + CNTR_CTRL); + + reg |= CNTR_CTRL_ENABLE; + writel(reg, priv->reg + CNTR_CTRL); +} + +static void a37xx_wdt_disable(struct a37xx_wdt *priv) +{ + u32 reg = readl(priv->reg + CNTR_CTRL); + + reg &= ~CNTR_CTRL_ENABLE; + writel(reg, priv->reg + CNTR_CTRL); +} + +static int a37xx_wdt_reset(struct udevice *dev) +{ + struct a37xx_wdt *priv = dev_get_priv(dev); + + if (!priv->timeout) + return -EINVAL; + + a37xx_wdt_disable(priv); + set_counter_value(priv); + a37xx_wdt_enable(priv); + + return 0; +} + +static int a37xx_wdt_expire_now(struct udevice *dev, ulong flags) +{ + struct a37xx_wdt *priv = dev_get_priv(dev); + + a37xx_wdt_disable(priv); + priv->timeout = 0; + set_counter_value(priv); + a37xx_wdt_enable(priv); + + return 0; +} + +static int a37xx_wdt_start(struct udevice *dev, u64 ms, ulong flags) +{ + struct a37xx_wdt *priv = dev_get_priv(dev); + u32 reg; + + reg = readl(priv->reg + CNTR_CTRL); + + if (reg & CNTR_CTRL_ACTIVE) + return -EBUSY; + + /* set mode */ + reg = (reg & ~CNTR_CTRL_MODE_MASK) | CNTR_CTRL_MODE_ONESHOT; + + /* set prescaler to the min value */ + reg &= ~CNTR_CTRL_PRESCALE_MASK; + reg |= CNTR_CTRL_PRESCALE_MIN << CNTR_CTRL_PRESCALE_SHIFT; + + priv->timeout = ms * priv->clk_rate / 1000 / CNTR_CTRL_PRESCALE_MIN; + + writel(reg, priv->reg + CNTR_CTRL); + + set_counter_value(priv); + a37xx_wdt_enable(priv); + + return 0; +} + +static int a37xx_wdt_stop(struct udevice *dev) +{ + struct a37xx_wdt *priv = dev_get_priv(dev); + + a37xx_wdt_disable(priv); + + return 0; +} + +static int a37xx_wdt_probe(struct udevice *dev) +{ + struct a37xx_wdt *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_read_addr_index(dev, 0); + if (addr == FDT_ADDR_T_NONE) + goto err; + priv->sel_reg = (void __iomem *)addr; + + addr = dev_read_addr_index(dev, 1); + if (addr == FDT_ADDR_T_NONE) + goto err; + priv->reg = (void __iomem *)addr; + + priv->clk_rate = (ulong)get_ref_clk() * 1000000; + + a37xx_wdt_disable(priv); + + /* + * We use timer 1 as watchdog timer (because Marvell's Linux uses that + * timer as default), therefore we only set bit TIMER1_IS_WCHDOG_TIMER. + */ + writel(1 << 1, priv->sel_reg); + + return 0; +err: + dev_err(dev, "no io address\n"); + return -ENODEV; +} + +static const struct wdt_ops a37xx_wdt_ops = { + .start = a37xx_wdt_start, + .reset = a37xx_wdt_reset, + .stop = a37xx_wdt_stop, + .expire_now = a37xx_wdt_expire_now, +}; + +static const struct udevice_id a37xx_wdt_ids[] = { + { .compatible = "marvell,armada-3700-wdt" }, + {} +}; + +U_BOOT_DRIVER(a37xx_wdt) = { + .name = "armada_37xx_wdt", + .id = UCLASS_WDT, + .of_match = a37xx_wdt_ids, + .probe = a37xx_wdt_probe, + .priv_auto_alloc_size = sizeof(struct a37xx_wdt), + .ops = &a37xx_wdt_ops, +}; -- cgit From 80af1a9ef6c81db3d8b1bd8a73ab6a94ed20a1ea Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Tue, 24 Apr 2018 17:21:31 +0200 Subject: arm64: mvebu: Add basic support for the Turris Mox board This adds basic support for the Turris Mox board from CZ.NIC, which is currently being crowdfunded on Indiegogo. Turris Mox is as modular router based on the Armada 3720 SOC (same as EspressoBin). The basic module can be extended by different modules. The device tree binary for the kernel can be dependent on which modules are connected, and in what order. Because of this, the board specific code creates in U-Boot a variable called module_topology, which carries this information. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- arch/arm/dts/Makefile | 1 + arch/arm/dts/armada-3720-turris-mox.dts | 132 ++++++++++++++++++++++++++++++++ arch/arm/mach-mvebu/Kconfig | 7 ++ arch/arm/mach-mvebu/Makefile | 2 +- board/CZ.NIC/turris_mox/MAINTAINERS | 6 ++ board/CZ.NIC/turris_mox/Makefile | 5 ++ board/CZ.NIC/turris_mox/turris_mox.c | 127 ++++++++++++++++++++++++++++++ configs/turris_mox_defconfig | 76 ++++++++++++++++++ include/configs/turris_mox.h | 108 ++++++++++++++++++++++++++ 9 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 arch/arm/dts/armada-3720-turris-mox.dts create mode 100644 board/CZ.NIC/turris_mox/MAINTAINERS create mode 100644 board/CZ.NIC/turris_mox/Makefile create mode 100644 board/CZ.NIC/turris_mox/turris_mox.c create mode 100644 configs/turris_mox_defconfig create mode 100644 include/configs/turris_mox.h diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index f94940a7dd..7bec3d6cfe 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -87,6 +87,7 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \ dtb-$(CONFIG_ARCH_MVEBU) += \ armada-3720-db.dtb \ armada-3720-espressobin.dtb \ + armada-3720-turris-mox.dtb \ armada-375-db.dtb \ armada-388-clearfog.dtb \ armada-388-gp.dtb \ diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts new file mode 100644 index 0000000000..bef100afce --- /dev/null +++ b/arch/arm/dts/armada-3720-turris-mox.dts @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0+ or X11 +/* + * Device Tree file for CZ.NIC Turris Mox Board + * 2018 by Marek Behun + * + * Based on armada-3720-espressobin.dts by: + * Gregory CLEMENT + * Konstantin Porotchkin + */ + +/dts-v1/; + +#include +#include "armada-372x.dtsi" + +/ { + model = "CZ.NIC Turris Mox Board"; + compatible = "cznic,turris-mox", "marvell,armada3720", + "marvell,armada3710"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + ethernet0 = ð0; + i2c0 = &i2c0; + spi0 = &spi0; + }; + + memory { + device_type = "memory"; + reg = <0x00000000 0x00000000 0x00000000 0x20000000>; + }; + + reg_usb3_vbus: usb3_vbus@0 { + compatible = "regulator-fixed"; + regulator-name = "usb3-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + shutdown-delay-us = <1000000>; + gpio = <&gpiosb 0 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + }; + + mdio { + eth_phy1: ethernet-phy@1 { + reg = <1>; + }; + }; +}; + +&comphy { + max-lanes = <3>; + phy0 { + phy-type = ; + phy-speed = ; + }; + + phy1 { + phy-type = ; + phy-speed = ; + }; + + phy2 { + phy-type = ; + phy-speed = ; + }; +}; + +ð0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&rgmii_pins>, <&smi_pins>; + phy-mode = "rgmii"; + phy = <ð_phy1>; +}; + +&i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + status = "okay"; +}; + +&sdhci1 { + bus-width = <4>; + status = "okay"; +}; + +&pinctrl_nb { + spi_cs1_pins: spi-cs1-pins { + groups = "spi_cs1"; + function = "spi"; + }; +}; + +&pinctrl_sb { + smi_pins: smi-pins { + groups = "smi"; + function = "smi"; + }; +}; + +&spi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi_cs1_pins>; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,s25fl064l", "spi-flash"; + reg = <0>; + spi-max-frequency = <20000000>; + m25p,fast-read; + }; +}; + +&uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; + status = "okay"; +}; + +&usb2 { + status = "okay"; +}; + +&usb3 { + vbus-supply = <®_usb3_vbus>; + status = "okay"; +}; diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index ec42cf9044..f431cff950 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -96,6 +96,10 @@ config TARGET_TURRIS_OMNIA bool "Support Turris Omnia" select 88F6820 +config TARGET_TURRIS_MOX + bool "Support Turris Mox" + select ARMADA_3700 + config TARGET_MVEBU_ARMADA_8K bool "Support Armada 7k/8k platforms" select ARMADA_8K @@ -133,6 +137,7 @@ config SYS_BOARD default "db-88f6820-gp" if TARGET_DB_88F6820_GP default "db-88f6820-amc" if TARGET_DB_88F6820_AMC default "turris_omnia" if TARGET_TURRIS_OMNIA + default "turris_mox" if TARGET_TURRIS_MOX default "mvebu_armada-8k" if TARGET_MVEBU_ARMADA_8K default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP default "ds414" if TARGET_DS414 @@ -151,6 +156,7 @@ config SYS_CONFIG_NAME default "maxbcm" if TARGET_MAXBCM default "theadorable" if TARGET_THEADORABLE default "turris_omnia" if TARGET_TURRIS_OMNIA + default "turris_mox" if TARGET_TURRIS_MOX config SYS_VENDOR default "Marvell" if TARGET_DB_MV784MP_GP @@ -162,6 +168,7 @@ config SYS_VENDOR default "solidrun" if TARGET_CLEARFOG default "Synology" if TARGET_DS414 default "CZ.NIC" if TARGET_TURRIS_OMNIA + default "CZ.NIC" if TARGET_TURRIS_MOX config SYS_SOC default "mvebu" diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index af4ca03688..3b9a8116d8 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -7,7 +7,7 @@ ifdef CONFIG_ARM64 obj-$(CONFIG_ARMADA_3700) += armada3700/ obj-$(CONFIG_ARMADA_8K) += armada8k/ obj-y += arm64-common.o -obj-y += sata.o +obj-$(CONFIG_AHCI) += sata.o else # CONFIG_ARM64 diff --git a/board/CZ.NIC/turris_mox/MAINTAINERS b/board/CZ.NIC/turris_mox/MAINTAINERS new file mode 100644 index 0000000000..2b9c1132f5 --- /dev/null +++ b/board/CZ.NIC/turris_mox/MAINTAINERS @@ -0,0 +1,6 @@ +TURRIS OMNIA BOARD +M: Marek Behún +S: Maintained +F: board/CZ.NIC/turris_mox/ +F: include/configs/turris_mox.h +F: configs/turris_mox_defconfig diff --git a/board/CZ.NIC/turris_mox/Makefile b/board/CZ.NIC/turris_mox/Makefile new file mode 100644 index 0000000000..619704288b --- /dev/null +++ b/board/CZ.NIC/turris_mox/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018 Marek Behun + +obj-y := turris_mox.o diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c new file mode 100644 index 0000000000..130d4c606d --- /dev/null +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -0,0 +1,127 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Marek Behun + */ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_WDT_ARMADA_3720 +#include +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_WDT_ARMADA_3720 +static struct udevice *watchdog_dev; + +void watchdog_reset(void) +{ + static ulong next_reset; + ulong now; + + if (!watchdog_dev) + return; + + now = timer_get_us(); + + /* Do not reset the watchdog too often */ + if (now > next_reset) { + wdt_reset(watchdog_dev); + next_reset = now + 100000; + } +} +#endif + +int board_init(void) +{ + /* address of boot parameters */ + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + +#ifdef CONFIG_WDT_ARMADA_3720 + if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { + printf("Cannot find Armada 3720 watchdog!\n"); + } else { + printf("Enabling Armada 3720 watchdog (3 minutes timeout).\n"); + wdt_start(watchdog_dev, 180000, 0); + } +#endif + + return 0; +} + +int last_stage_init(void) +{ + struct spi_slave *slave; + struct udevice *dev; + u8 din[10], dout[10]; + int ret, i; + size_t len = 0; + char module_topology[128]; + + ret = spi_get_bus_and_cs(0, 1, 20000000, SPI_CPHA, "spi_generic_drv", + "mox-modules@1", &dev, &slave); + if (ret) + goto fail; + + ret = spi_claim_bus(slave); + if (ret) + goto fail_free; + + memset(din, 0, 10); + memset(dout, 0, 10); + + ret = spi_xfer(slave, 80, dout, din, SPI_XFER_ONCE); + if (ret) + goto fail_release; + + if (din[0] != 0x00 && din[0] != 0xff) + goto fail_release; + + printf("Module Topology:\n"); + for (i = 1; i < 10 && din[i] != 0xff; ++i) { + u8 mid = din[i] & 0xf; + size_t mlen; + const char *mname = ""; + + switch (mid) { + case 0x1: + mname = "sfp-"; + printf("% 4i: SFP Module\n", i); + break; + case 0x2: + mname = "pci-"; + printf("% 4i: Mini-PCIe Module\n", i); + break; + case 0x3: + mname = "topaz-"; + printf("% 4i: Topaz Switch Module\n", i); + break; + default: + printf("% 4i: unknown (ID %i)\n", i, mid); + } + + mlen = strlen(mname); + if (len + mlen < sizeof(module_topology)) { + strcpy(module_topology + len, mname); + len += mlen; + } + } + printf("\n"); + + module_topology[len > 0 ? len - 1 : 0] = '\0'; + + env_set("module_topology", module_topology); + +fail_release: + spi_release_bus(slave); +fail_free: + spi_free_slave(slave); +fail: + if (ret) + printf("Cannot read module topology!\n"); + return ret; +} diff --git a/configs/turris_mox_defconfig b/configs/turris_mox_defconfig new file mode 100644 index 0000000000..7dea7157dc --- /dev/null +++ b/configs/turris_mox_defconfig @@ -0,0 +1,76 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_TEXT_BASE=0x00000000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_TURRIS_MOX=y +CONFIG_DEFAULT_DEVICE_TREE="armada-3720-turris-mox" +CONFIG_DEBUG_UART=y +CONFIG_DISTRO_DEFAULTS=y +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_ARCH_EARLY_INIT_R=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_CLK=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_MVEBU_BUBT=y +CONFIG_CMD_BTRFS=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_MAC_PARTITION=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_BLOCK_CACHE=y +CONFIG_DM_I2C=y +CONFIG_MISC=y +CONFIG_CLK=y +CONFIG_CLK_MVEBU=y +CONFIG_CLK_ARMADA_3720=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_SDMA=y +CONFIG_MMC_SDHCI_XENON=y +CONFIG_WDT=y +CONFIG_WDT_ARMADA_37XX=y +CONFIG_DM_GPIO=y +# CONFIG_MVEBU_GPIO is not set +CONFIG_PINCTRL=y +CONFIG_PINCTRL_GENERIC=y +CONFIG_PINMUX=y +CONFIG_PINCTRL_ARMADA_37XX=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_PHYLIB=y +CONFIG_PHY_GIGE=y +CONFIG_MVNETA=y +CONFIG_MVEBU_COMPHY_SUPPORT=y +# CONFIG_SPL_SERIAL_PRESENT is not set +CONFIG_DEBUG_MVEBU_A3700_UART=y +CONFIG_DEBUG_UART_BASE=0xd0012000 +CONFIG_DEBUG_UART_CLOCK=25804800 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_MVEBU_A3700_UART=y +CONFIG_MVEBU_A3700_SPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_MCS7830=y +CONFIG_USB_ETHER_RTL8152=y +CONFIG_USB_ETHER_SMSC95XX=y +CONFIG_SHA1=y +CONFIG_SHA256=y diff --git a/include/configs/turris_mox.h b/include/configs/turris_mox.h new file mode 100644 index 0000000000..5784851271 --- /dev/null +++ b/include/configs/turris_mox.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018 Marek Behun + * + * Based on mvebu_armada-37xx.h by Stefan Roese + */ + +#ifndef _CONFIG_TURRIS_MOX_H +#define _CONFIG_TURRIS_MOX_H + +#define CONFIG_LAST_STAGE_INIT + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_DISPLAY_BOARDINFO_LATE + +/* additions for new ARM relocation support */ +#define CONFIG_SYS_SDRAM_BASE 0x00000000 + +#define CONFIG_NR_DRAM_BANKS 1 + +/* auto boot */ +#define CONFIG_PREBOOT + +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, \ + 115200, 230400, 460800, 921600 } + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CONFIG_CMDLINE_TAG /* enable passing of ATAGs */ +#define CONFIG_INITRD_TAG /* enable INITRD tag */ +#define CONFIG_SETUP_MEMORY_TAGS /* enable memory tag */ + +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buff Size */ + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN (4 << 20) /* 4MiB for malloc() */ + +/* + * Other required minimal configurations + */ +#define CONFIG_ARCH_CPU_INIT /* call arch_cpu_init() */ +#define CONFIG_SYS_LOAD_ADDR 0x00800000 /* default load adr- 8M */ +#define CONFIG_SYS_MEMTEST_START 0x00800000 /* 8M */ +#define CONFIG_SYS_MEMTEST_END 0x00ffffff /*(_16M -1) */ +#define CONFIG_SYS_RESET_ADDRESS 0xffff0000 /* Rst Vector Adr */ +#define CONFIG_SYS_MAXARGS 32 /* max number of command args */ + +#define CONFIG_SYS_ALT_MEMTEST + +/* End of 16M scrubbed by training in bootrom */ +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + 0xFF0000) + +/* + * I2C + */ +#define CONFIG_I2C_MV +#define CONFIG_SYS_I2C_SLAVE 0x0 + +/* + * SPI Flash configuration + */ +#define CONFIG_ENV_SPI_BUS 0 +#define CONFIG_ENV_SPI_CS 0 + +/* SPI NOR flash default params, used by sf commands */ +#define CONFIG_SF_DEFAULT_SPEED 20000000 +#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0 +#define CONFIG_ENV_SPI_MODE CONFIG_SF_DEFAULT_MODE + +/* Environment in SPI NOR flash */ +#define CONFIG_ENV_OFFSET 0x180000 /* as Marvell U-Boot version */ +#define CONFIG_ENV_SIZE (64 << 10) /* 64KiB */ +#define CONFIG_ENV_SECT_SIZE (64 << 10) /* 64KiB sectors */ + +/* + * Ethernet Driver configuration + */ +#define CONFIG_ENV_OVERWRITE /* ethaddr can be reprogrammed */ +#define CONFIG_ARP_TIMEOUT 200 +#define CONFIG_NET_RETRY_COUNT 50 +#define CONFIG_PHY_MARVELL + +#define CONFIG_USB_MAX_CONTROLLER_COUNT (3 + 3) + +#define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 0) \ + func(USB, usb, 0) \ + func(PXE, pxe, na) \ + func(DHCP, dhcp, na) + +#include + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "scriptaddr=0x4d00000\0" \ + "pxefile_addr_r=0x4e00000\0" \ + "fdt_addr_r=0x4f00000\0" \ + "kernel_addr_r=0x5000000\0" \ + "ramdisk_addr_r=0x8000000\0" \ + BOOTENV + +#endif /* _CONFIG_TURRIS_MOX_H */ -- cgit From e6fce12d1476eda5b595274451443c3468f844d0 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 May 2018 13:28:26 +1200 Subject: ARM: mvebu: a38x: move definition of PEX_CFG_DIRECT_ACCESS PEX_CFG_DIRECT_ACCESS was defined in ddr3_hws_hw_training_def.h despite only being used in the serdes code. Move this definition to ctrl_pex.h where all the other PEX defines are. Also remove the duplicate definition of PEX_DEVICE_AND_VENDOR_ID which is already defined in ctrl_pex.h. Signed-off-by: Chris Packham Signed-off-by: Stefan Roese --- arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h | 1 + drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h index 53ed4eab32..3f30b6bf97 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h +++ b/arch/arm/mach-mvebu/serdes/a38x/ctrl_pex.h @@ -46,6 +46,7 @@ /* Controller revision info */ #define PEX_DEVICE_AND_VENDOR_ID 0x000 +#define PEX_CFG_DIRECT_ACCESS(if, reg) (PEX_IF_REGS_BASE(if) + (reg)) /* PCI Express Configuration Address Register */ #define PXCAR_REG_NUM_OFFS 2 diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h b/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h index c99437be22..a87fc404cb 100644 --- a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h +++ b/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h @@ -421,8 +421,6 @@ /* Power Management Clock Gating Control Register */ #define POWER_MNG_CTRL_REG 0x18220 -#define PEX_DEVICE_AND_VENDOR_ID 0x000 -#define PEX_CFG_DIRECT_ACCESS(if, reg) (PEX_IF_REGS_BASE(if) + (reg)) #define PMC_PEXSTOPCLOCK_OFFS(p) ((p) < 8 ? (5 + (p)) : (18 + (p))) #define PMC_PEXSTOPCLOCK_MASK(p) (1 << PMC_PEXSTOPCLOCK_OFFS(p)) #define PMC_PEXSTOPCLOCK_EN(p) (1 << PMC_PEXSTOPCLOCK_OFFS(p)) -- cgit From c4195d5553595f12a6f5e943c9ee5e68097d7c72 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 May 2018 13:28:27 +1200 Subject: ARM: mvebu: a38x: move sys_env_device_rev_get Move sys_env_device_rev_get() from the ddr training code to sys_env_lib.c (which currently resides with the serdes code). This brings sys_env_device_rev_get() into line with sys_env_device_id_get() and sys_env_model_get(). Signed-off-by: Chris Packham Signed-off-by: Stefan Roese --- arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c | 26 ++++++++++++++++++++++++-- arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h | 1 - drivers/ddr/marvell/a38x/ddr3_init.c | 24 ------------------------ 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c index d26068e1d7..d387893af3 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c +++ b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.c @@ -12,8 +12,6 @@ #include "seq_exec.h" #include "sys_env_lib.h" -#include "../../../drivers/ddr/marvell/a38x/ddr3_a38x.h" - #ifdef CONFIG_ARMADA_38X enum unit_id sys_env_soc_unit_nums[MAX_UNITS_ID][MAX_DEV_ID_NUM] = { /* 6820 6810 6811 6828 */ @@ -234,3 +232,27 @@ u32 sys_env_device_id_get(void) return g_dev_id; } + +/* + * sys_env_device_rev_get - Get Marvell controller device revision number + * + * DESCRIPTION: + * This function returns 8bit describing the device revision as defined + * Revision ID Register. + * + * INPUT: + * None. + * + * OUTPUT: + * None. + * + * RETURN: + * 8bit desscribing Marvell controller revision number + */ +u8 sys_env_device_rev_get(void) +{ + u32 value; + + value = reg_read(DEV_VERSION_ID_REG); + return (value & (REVISON_ID_MASK)) >> REVISON_ID_OFFS; +} diff --git a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h index c5461067fd..953445b7d7 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h +++ b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h @@ -7,7 +7,6 @@ #define _SYS_ENV_LIB_H #include "../../../drivers/ddr/marvell/a38x/ddr3_init.h" -#include "../../../drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h" /* Serdes definitions */ #define COMMON_PHY_BASE_ADDR 0x18300 diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c index 6ee13c10e4..1c5b1f75ca 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.c +++ b/drivers/ddr/marvell/a38x/ddr3_init.c @@ -107,30 +107,6 @@ static int ddr3_hws_tune_training_params(u8 dev_num); /* A39x revisions */ #define MV_88F69XX_Z1_ID 0x2 -/* - * sys_env_device_rev_get - Get Marvell controller device revision number - * - * DESCRIPTION: - * This function returns 8bit describing the device revision as defined - * Revision ID Register. - * - * INPUT: - * None. - * - * OUTPUT: - * None. - * - * RETURN: - * 8bit desscribing Marvell controller revision number - */ -u8 sys_env_device_rev_get(void) -{ - u32 value; - - value = reg_read(DEV_VERSION_ID_REG); - return (value & (REVISON_ID_MASK)) >> REVISON_ID_OFFS; -} - /* * sys_env_dlb_config_ptr_get * -- cgit From 00a7767766ace1f3ca3de7f9d44e145b9092bbad Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 May 2018 13:28:28 +1200 Subject: ARM: mvebu: a38x: remove some unused code No in-tree code defines SUPPORT_STATIC_DUNIT_CONFIG or STATIC_ALGO_SUPPORT. Remove ddr3_a38x_mc_static.h and use unifdef to remove unused sections in the rest of the ddr/marvell/a38x code. Signed-off-by: Chris Packham Signed-off-by: Stefan Roese --- drivers/ddr/marvell/a38x/ddr3_a38x.c | 51 --- drivers/ddr/marvell/a38x/ddr3_a38x_mc_static.h | 225 ------------ drivers/ddr/marvell/a38x/ddr3_debug.c | 9 - drivers/ddr/marvell/a38x/ddr3_init.c | 29 -- drivers/ddr/marvell/a38x/ddr3_init.h | 1 - drivers/ddr/marvell/a38x/ddr3_training.c | 41 --- drivers/ddr/marvell/a38x/ddr3_training_static.c | 438 ------------------------ 7 files changed, 794 deletions(-) delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x_mc_static.h diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x.c b/drivers/ddr/marvell/a38x/ddr3_a38x.c index e152e842ae..c356d09008 100644 --- a/drivers/ddr/marvell/a38x/ddr3_a38x.c +++ b/drivers/ddr/marvell/a38x/ddr3_a38x.c @@ -76,41 +76,6 @@ struct trip_delay_element a38x_board_round_trip_delay_array[] = { { 4282, 6160 } /* ECC PUP */ }; -#ifdef STATIC_ALGO_SUPPORT -/* package trace */ -static struct trip_delay_element a38x_package_round_trip_delay_array[] = { - /* IF BUS DQ_DELAY CK_DELAY */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 } -}; - -static int a38x_silicon_delay_offset[] = { - /* board 0 */ - 0, - /* board 1 */ - 0, - /* board 2 */ - 0 -}; -#endif static u8 a38x_bw_per_freq[DDR_FREQ_LIMIT] = { 0x3, /* DDR_FREQ_100 */ @@ -367,22 +332,6 @@ static int ddr3_tip_init_a38x_silicon(u32 dev_num, u32 board_id) ddr3_tip_register_dq_table(dev_num, dq_bit_map_2_phy_pin); -#ifdef STATIC_ALGO_SUPPORT - { - struct hws_tip_static_config_info static_config; - u32 board_offset = - board_id * A38X_NUMBER_OF_INTERFACES * - tm->num_of_bus_per_interface; - - static_config.silicon_delay = - a38x_silicon_delay_offset[board_id]; - static_config.package_trace_arr = - a38x_package_round_trip_delay_array; - static_config.board_trace_arr = - &a38x_board_round_trip_delay_array[board_offset]; - ddr3_tip_init_static_config_db(dev_num, &static_config); - } -#endif status = ddr3_tip_a38x_get_init_freq(dev_num, &ddr_freq); if (MV_OK != status) { DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x_mc_static.h b/drivers/ddr/marvell/a38x/ddr3_a38x_mc_static.h deleted file mode 100644 index a5b4f70458..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x_mc_static.h +++ /dev/null @@ -1,225 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#ifndef _DDR3_A38X_MC_STATIC_H -#define _DDR3_A38X_MC_STATIC_H - -#include "ddr3_a38x.h" - -#ifdef SUPPORT_STATIC_DUNIT_CONFIG - -#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT -static struct reg_data ddr3_customer_800[] = { - /* parameters for customer board (based on 800MHZ) */ - {0x1400, 0x7b00cc30, 0xffffffff}, - {0x1404, 0x36301820, 0xffffffff}, - {0x1408, 0x5415baab, 0xffffffff}, - {0x140c, 0x38411def, 0xffffffff}, - {0x1410, 0x18300000, 0xffffffff}, - {0x1414, 0x00000700, 0xffffffff}, - {0x1424, 0x0060f3ff, 0xffffffff}, - {0x1428, 0x0011a940, 0xffffffff}, - {0x142c, 0x28c5134, 0xffffffff}, - {0x1474, 0x00000000, 0xffffffff}, - {0x147c, 0x0000d771, 0xffffffff}, - {0x1494, 0x00030000, 0xffffffff}, - {0x149c, 0x00000300, 0xffffffff}, - {0x14a8, 0x00000000, 0xffffffff}, - {0x14cc, 0xbd09000d, 0xffffffff}, - {0x1504, 0xfffffff1, 0xffffffff}, - {0x150c, 0xffffffe5, 0xffffffff}, - {0x1514, 0x00000000, 0xffffffff}, - {0x151c, 0x00000000, 0xffffffff}, - {0x1538, 0x00000b0b, 0xffffffff}, - {0x153c, 0x00000c0c, 0xffffffff}, - {0x15d0, 0x00000670, 0xffffffff}, - {0x15d4, 0x00000046, 0xffffffff}, - {0x15d8, 0x00000010, 0xffffffff}, - {0x15dc, 0x00000000, 0xffffffff}, - {0x15e0, 0x00000023, 0xffffffff}, - {0x15e4, 0x00203c18, 0xffffffff}, - {0x15ec, 0xf8000019, 0xffffffff}, - {0x16a0, 0xcc000006, 0xffffffff}, /* Clock Delay */ - {0xe4124, 0x08008073, 0xffffffff}, /* AVS BG default */ - {0, 0, 0} -}; - -#else /* CONFIG_CUSTOMER_BOARD_SUPPORT */ - -struct reg_data ddr3_a38x_933[MV_MAX_DDR3_STATIC_SIZE] = { - /* parameters for 933MHZ */ - {0x1400, 0x7b00ce3a, 0xffffffff}, - {0x1404, 0x36301820, 0xffffffff}, - {0x1408, 0x7417eccf, 0xffffffff}, - {0x140c, 0x3e421f98, 0xffffffff}, - {0x1410, 0x1a300000, 0xffffffff}, - {0x1414, 0x00000700, 0xffffffff}, - {0x1424, 0x0060f3ff, 0xffffffff}, - {0x1428, 0x0013ca50, 0xffffffff}, - {0x142c, 0x028c5165, 0xffffffff}, - {0x1474, 0x00000000, 0xffffffff}, - {0x147c, 0x0000e871, 0xffffffff}, - {0x1494, 0x00010000, 0xffffffff}, - {0x149c, 0x00000001, 0xffffffff}, - {0x14a8, 0x00000000, 0xffffffff}, - {0x14cc, 0xbd09000d, 0xffffffff}, - {0x1504, 0xffffffe1, 0xffffffff}, - {0x150c, 0xffffffe5, 0xffffffff}, - {0x1514, 0x00000000, 0xffffffff}, - {0x151c, 0x00000000, 0xffffffff}, - {0x1538, 0x00000d0d, 0xffffffff}, - {0x153c, 0x00000d0d, 0xffffffff}, - {0x15d0, 0x00000608, 0xffffffff}, - {0x15d4, 0x00000044, 0xffffffff}, - {0x15d8, 0x00000020, 0xffffffff}, - {0x15dc, 0x00000000, 0xffffffff}, - {0x15e0, 0x00000021, 0xffffffff}, - {0x15e4, 0x00203c18, 0xffffffff}, - {0x15ec, 0xf8000019, 0xffffffff}, - {0x16a0, 0xcc000006, 0xffffffff}, /* Clock Delay */ - {0xe4124, 0x08008073, 0xffffffff}, /* AVS BG default */ - {0, 0, 0} -}; - -static struct reg_data ddr3_a38x_800[] = { - /* parameters for 800MHZ */ - {0x1400, 0x7b00cc30, 0xffffffff}, - {0x1404, 0x36301820, 0xffffffff}, - {0x1408, 0x5415baab, 0xffffffff}, - {0x140c, 0x38411def, 0xffffffff}, - {0x1410, 0x18300000, 0xffffffff}, - {0x1414, 0x00000700, 0xffffffff}, - {0x1424, 0x0060f3ff, 0xffffffff}, - {0x1428, 0x0011a940, 0xffffffff}, - {0x142c, 0x28c5134, 0xffffffff}, - {0x1474, 0x00000000, 0xffffffff}, - {0x147c, 0x0000d771, 0xffffffff}, - {0x1494, 0x00030000, 0xffffffff}, - {0x149c, 0x00000300, 0xffffffff}, - {0x14a8, 0x00000000, 0xffffffff}, - {0x14cc, 0xbd09000d, 0xffffffff}, - {0x1504, 0xfffffff1, 0xffffffff}, - {0x150c, 0xffffffe5, 0xffffffff}, - {0x1514, 0x00000000, 0xffffffff}, - {0x151c, 0x00000000, 0xffffffff}, - {0x1538, 0x00000b0b, 0xffffffff}, - {0x153c, 0x00000c0c, 0xffffffff}, - {0x15d0, 0x00000670, 0xffffffff}, - {0x15d4, 0x00000046, 0xffffffff}, - {0x15d8, 0x00000010, 0xffffffff}, - {0x15dc, 0x00000000, 0xffffffff}, - {0x15e0, 0x00000023, 0xffffffff}, - {0x15e4, 0x00203c18, 0xffffffff}, - {0x15ec, 0xf8000019, 0xffffffff}, - {0x16a0, 0xcc000006, 0xffffffff}, /* Clock Delay */ - {0xe4124, 0x08008073, 0xffffffff}, /* AVS BG default */ - {0, 0, 0} -}; - -static struct reg_data ddr3_a38x_667[] = { - /* parameters for 667MHZ */ - /* DDR SDRAM Configuration Register */ - {0x1400, 0x7b00ca28, 0xffffffff}, - /* Dunit Control Low Register - kw28 bit12 low (disable CLK1) */ - {0x1404, 0x36301820, 0xffffffff}, - /* DDR SDRAM Timing (Low) Register */ - {0x1408, 0x43149997, 0xffffffff}, - /* DDR SDRAM Timing (High) Register */ - {0x140c, 0x38411bc7, 0xffffffff}, - /* DDR SDRAM Address Control Register */ - {0x1410, 0x14330000, 0xffffffff}, - /* DDR SDRAM Open Pages Control Register */ - {0x1414, 0x00000700, 0xffffffff}, - /* Dunit Control High Register (2 :1 - bits 15:12 = 0xd) */ - {0x1424, 0x0060f3ff, 0xffffffff}, - /* Dunit Control High Register */ - {0x1428, 0x000f8830, 0xffffffff}, - /* Dunit Control High Register (2:1 - bit 29 = '1') */ - {0x142c, 0x28c50f8, 0xffffffff}, - {0x147c, 0x0000c671, 0xffffffff}, - /* DDR SDRAM ODT Control (Low) Register */ - {0x1494, 0x00030000, 0xffffffff}, - /* DDR SDRAM ODT Control (High) Register, will be configured at WL */ - {0x1498, 0x00000000, 0xffffffff}, - /* DDR Dunit ODT Control Register */ - {0x149c, 0x00000300, 0xffffffff}, - {0x14a8, 0x00000000, 0xffffffff}, /* */ - {0x14cc, 0xbd09000d, 0xffffffff}, /* */ - {0x1474, 0x00000000, 0xffffffff}, - /* Read Data Sample Delays Register */ - {0x1538, 0x00000009, 0xffffffff}, - /* Read Data Ready Delay Register */ - {0x153c, 0x0000000c, 0xffffffff}, - {0x1504, 0xfffffff1, 0xffffffff}, /* */ - {0x150c, 0xffffffe5, 0xffffffff}, /* */ - {0x1514, 0x00000000, 0xffffffff}, /* */ - {0x151c, 0x0, 0xffffffff}, /* */ - {0x15d0, 0x00000650, 0xffffffff}, /* MR0 */ - {0x15d4, 0x00000046, 0xffffffff}, /* MR1 */ - {0x15d8, 0x00000010, 0xffffffff}, /* MR2 */ - {0x15dc, 0x00000000, 0xffffffff}, /* MR3 */ - {0x15e0, 0x23, 0xffffffff}, /* */ - {0x15e4, 0x00203c18, 0xffffffff}, /* ZQC Configuration Register */ - {0x15ec, 0xf8000019, 0xffffffff}, /* DDR PHY */ - {0x16a0, 0xcc000006, 0xffffffff}, /* Clock Delay */ - {0xe4124, 0x08008073, 0xffffffff}, /* AVS BG default */ - {0, 0, 0} -}; - -static struct reg_data ddr3_a38x_533[] = { - /* parameters for 533MHZ */ - /* DDR SDRAM Configuration Register */ - {0x1400, 0x7b00d040, 0xffffffff}, - /* Dunit Control Low Register - kw28 bit12 low (disable CLK1) */ - {0x1404, 0x36301820, 0xffffffff}, - /* DDR SDRAM Timing (Low) Register */ - {0x1408, 0x33137772, 0xffffffff}, - /* DDR SDRAM Timing (High) Register */ - {0x140c, 0x3841199f, 0xffffffff}, - /* DDR SDRAM Address Control Register */ - {0x1410, 0x10330000, 0xffffffff}, - /* DDR SDRAM Open Pages Control Register */ - {0x1414, 0x00000700, 0xffffffff}, - /* Dunit Control High Register (2 :1 - bits 15:12 = 0xd) */ - {0x1424, 0x0060f3ff, 0xffffffff}, - /* Dunit Control High Register */ - {0x1428, 0x000d6720, 0xffffffff}, - /* Dunit Control High Register (2:1 - bit 29 = '1') */ - {0x142c, 0x028c50c3, 0xffffffff}, - {0x147c, 0x0000b571, 0xffffffff}, - /* DDR SDRAM ODT Control (Low) Register */ - {0x1494, 0x00030000, 0xffffffff}, - /* DDR SDRAM ODT Control (High) Register, will be configured at WL */ - {0x1498, 0x00000000, 0xffffffff}, - /* DDR Dunit ODT Control Register */ - {0x149c, 0x00000003, 0xffffffff}, - {0x14a8, 0x00000000, 0xffffffff}, /* */ - {0x14cc, 0xbd09000d, 0xffffffff}, /* */ - {0x1474, 0x00000000, 0xffffffff}, - /* Read Data Sample Delays Register */ - {0x1538, 0x00000707, 0xffffffff}, - /* Read Data Ready Delay Register */ - {0x153c, 0x00000707, 0xffffffff}, - {0x1504, 0xffffffe1, 0xffffffff}, /* */ - {0x150c, 0xffffffe5, 0xffffffff}, /* */ - {0x1514, 0x00000000, 0xffffffff}, /* */ - {0x151c, 0x00000000, 0xffffffff}, /* */ - {0x15d0, 0x00000630, 0xffffffff}, /* MR0 */ - {0x15d4, 0x00000046, 0xffffffff}, /* MR1 */ - {0x15d8, 0x00000008, 0xffffffff}, /* MR2 */ - {0x15dc, 0x00000000, 0xffffffff}, /* MR3 */ - {0x15e0, 0x00000023, 0xffffffff}, /* */ - {0x15e4, 0x00203c18, 0xffffffff}, /* ZQC Configuration Register */ - {0x15ec, 0xf8000019, 0xffffffff}, /* DDR PHY */ - {0x16a0, 0xcc000006, 0xffffffff}, /* Clock Delay */ - {0xe4124, 0x08008073, 0xffffffff}, /* AVS BG default */ - {0, 0, 0} -}; - -#endif /* CONFIG_CUSTOMER_BOARD_SUPPORT */ - -#endif /* SUPPORT_STATIC_DUNIT_CONFIG */ - -#endif /* _DDR3_A38X_MC_STATIC_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c b/drivers/ddr/marvell/a38x/ddr3_debug.c index 68ab9476cc..c14400840e 100644 --- a/drivers/ddr/marvell/a38x/ddr3_debug.c +++ b/drivers/ddr/marvell/a38x/ddr3_debug.c @@ -867,15 +867,6 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) case 0x25: *ptr = (u32 *)&is_adll_calib_before_init; break; -#ifdef STATIC_ALGO_SUPPORT - case 0x26: - *ptr = (u32 *)&(silicon_delay[0]); - break; - - case 0x27: - *ptr = (u32 *)&wl_debug_delay; - break; -#endif case 0x28: *ptr = (u32 *)&is_tune_result; break; diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c index 1c5b1f75ca..73d984ba66 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.c +++ b/drivers/ddr/marvell/a38x/ddr3_init.c @@ -59,20 +59,6 @@ struct dram_modes { }; struct dram_modes ddr_modes[] = { -#ifdef SUPPORT_STATIC_DUNIT_CONFIG - /* Conf name, CPUFreq, Fab_freq, Chip ID, Chip/Board, MC regs*/ -#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT - {"a38x_customer_0_800", DDR_FREQ_800, 0, 0x0, A38X_CUSTOMER_BOARD_ID0, - ddr3_customer_800}, - {"a38x_customer_1_800", DDR_FREQ_800, 0, 0x0, A38X_CUSTOMER_BOARD_ID1, - ddr3_customer_800}, -#else - {"a38x_533", DDR_FREQ_533, 0, 0x0, MARVELL_BOARD, ddr3_a38x_533}, - {"a38x_667", DDR_FREQ_667, 0, 0x0, MARVELL_BOARD, ddr3_a38x_667}, - {"a38x_800", DDR_FREQ_800, 0, 0x0, MARVELL_BOARD, ddr3_a38x_800}, - {"a38x_933", DDR_FREQ_933, 0, 0x0, MARVELL_BOARD, ddr3_a38x_933}, -#endif -#endif }; #endif /* defined(CONFIG_ARMADA_38X) */ @@ -91,9 +77,6 @@ static char *ddr_type = "DDR3"; */ u8 generic_init_controller = 1; -#ifdef SUPPORT_STATIC_DUNIT_CONFIG -static u32 ddr3_get_static_ddr_mode(void); -#endif static int ddr3_hws_tune_training_params(u8 dev_num); /* device revision */ @@ -342,18 +325,6 @@ int ddr3_init(void) /* Set X-BAR windows for the training sequence */ ddr3_save_and_set_training_windows(win); -#ifdef SUPPORT_STATIC_DUNIT_CONFIG - /* - * Load static controller configuration (in case dynamic/generic init - * is not enabled - */ - if (generic_init_controller == 0) { - ddr3_tip_init_specific_reg_config(0, - ddr_modes - [ddr3_get_static_ddr_mode - ()].regs); - } -#endif /* Tune training algo paramteres */ status = ddr3_hws_tune_training_params(0); diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h b/drivers/ddr/marvell/a38x/ddr3_init.h index 05ff62b041..8cb645ffb5 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.h +++ b/drivers/ddr/marvell/a38x/ddr3_init.h @@ -8,7 +8,6 @@ #if defined(CONFIG_ARMADA_38X) #include "ddr3_a38x.h" -#include "ddr3_a38x_mc_static.h" #include "ddr3_a38x_topology.h" #endif #include "ddr3_hws_hw_training.h" diff --git a/drivers/ddr/marvell/a38x/ddr3_training.c b/drivers/ddr/marvell/a38x/ddr3_training.c index c4a150ea74..fee589b746 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training.c +++ b/drivers/ddr/marvell/a38x/ddr3_training.c @@ -635,12 +635,6 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ MASK_ALL_BITS)); } } else { -#ifdef STATIC_ALGO_SUPPORT - CHECK_STATUS(ddr3_tip_static_init_controller(dev_num)); -#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) - CHECK_STATUS(ddr3_tip_static_phy_init_controller(dev_num)); -#endif -#endif /* STATIC_ALGO_SUPPORT */ } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { @@ -814,25 +808,6 @@ int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type) if (algo_type == ALGO_TYPE_DYNAMIC) { ret = ddr3_tip_ddr3_auto_tune(dev_num); } else { -#ifdef STATIC_ALGO_SUPPORT - { - enum hws_ddr_freq freq; - freq = init_freq; - - /* add to mask */ - if (is_adll_calib_before_init != 0) { - printf("with adll calib before init\n"); - adll_calibration(dev_num, ACCESS_TYPE_MULTICAST, - 0, freq); - } - /* - * Frequency per interface is not relevant, - * only interface 0 - */ - ret = ddr3_tip_run_static_alg(dev_num, - freq); - } -#endif } if (ret != MV_OK) { @@ -2027,22 +2002,6 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) } } -#ifdef STATIC_ALGO_SUPPORT - if (mask_tune_func & STATIC_LEVELING_MASK_BIT) { - training_stage = STATIC_LEVELING; - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, - ("STATIC_LEVELING_MASK_BIT\n")); - ret = ddr3_tip_run_static_alg(dev_num, freq); - if (is_reg_dump != 0) - ddr3_tip_reg_dump(dev_num); - if (ret != MV_OK) { - DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, - ("ddr3_tip_run_static_alg failure\n")); - if (debug_mode == 0) - return MV_FAIL; - } - } -#endif if (mask_tune_func & SET_LOW_FREQ_MASK_BIT) { training_stage = SET_LOW_FREQ; diff --git a/drivers/ddr/marvell/a38x/ddr3_training_static.c b/drivers/ddr/marvell/a38x/ddr3_training_static.c index dddbfe17b0..1b4bfb2e02 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_static.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_static.c @@ -25,444 +25,6 @@ u32 g_odt_config_1cs = 0x10000; u32 g_rtt_nom = 0x44; u32 g_dic = 0x2; -#ifdef STATIC_ALGO_SUPPORT - -#define PARAM_NOT_CARE 0 -#define MAX_STATIC_SEQ 48 - -u32 silicon_delay[HWS_MAX_DEVICE_NUM]; -struct hws_tip_static_config_info static_config[HWS_MAX_DEVICE_NUM]; -static reg_data *static_init_controller_config[HWS_MAX_DEVICE_NUM]; - -/* debug delay in write leveling */ -int wl_debug_delay = 0; -/* pup register #3 for functional board */ -int function_reg_value = 8; -u32 silicon; - -u32 read_ready_delay_phase_offset[] = { 4, 4, 4, 4, 6, 6, 6, 6 }; - -static struct cs_element chip_select_map[] = { - /* CS Value (single only) Num_CS */ - {0, 0}, - {0, 1}, - {1, 1}, - {0, 2}, - {2, 1}, - {0, 2}, - {0, 2}, - {0, 3}, - {3, 1}, - {0, 2}, - {0, 2}, - {0, 3}, - {0, 2}, - {0, 3}, - {0, 3}, - {0, 4} -}; - -/* - * Register static init controller DB - */ -int ddr3_tip_init_specific_reg_config(u32 dev_num, reg_data *reg_config_arr) -{ - static_init_controller_config[dev_num] = reg_config_arr; - return MV_OK; -} - -/* - * Register static info DB - */ -int ddr3_tip_init_static_config_db( - u32 dev_num, struct hws_tip_static_config_info *static_config_info) -{ - static_config[dev_num].board_trace_arr = - static_config_info->board_trace_arr; - static_config[dev_num].package_trace_arr = - static_config_info->package_trace_arr; - silicon_delay[dev_num] = static_config_info->silicon_delay; - - return MV_OK; -} - -/* - * Static round trip flow - Calculates the total round trip delay. - */ -int ddr3_tip_static_round_trip_arr_build(u32 dev_num, - struct trip_delay_element *table_ptr, - int is_wl, u32 *round_trip_delay_arr) -{ - u32 bus_index, global_bus; - u32 if_id; - u32 bus_per_interface; - int sign; - u32 temp; - u32 board_trace; - struct trip_delay_element *pkg_delay_ptr; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* - * In WL we calc the diff between Clock to DQs in RL we sum the round - * trip of Clock and DQs - */ - sign = (is_wl) ? -1 : 1; - - bus_per_interface = GET_TOPOLOGY_NUM_OF_BUSES(); - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_index = 0; bus_index < bus_per_interface; - bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); - global_bus = (if_id * bus_per_interface) + bus_index; - - /* calculate total trip delay (package and board) */ - board_trace = (table_ptr[global_bus].dqs_delay * sign) + - table_ptr[global_bus].ck_delay; - temp = (board_trace * 163) / 1000; - - /* Convert the length to delay in psec units */ - pkg_delay_ptr = - static_config[dev_num].package_trace_arr; - round_trip_delay_arr[global_bus] = temp + - (int)(pkg_delay_ptr[global_bus].dqs_delay * - sign) + - (int)pkg_delay_ptr[global_bus].ck_delay + - (int)((is_wl == 1) ? wl_debug_delay : - (int)silicon_delay[dev_num]); - DEBUG_TRAINING_STATIC_IP( - DEBUG_LEVEL_TRACE, - ("Round Trip Build round_trip_delay_arr[0x%x]: 0x%x temp 0x%x\n", - global_bus, round_trip_delay_arr[global_bus], - temp)); - } - } - - return MV_OK; -} - -/* - * Write leveling for static flow - calculating the round trip delay of the - * DQS signal. - */ -int ddr3_tip_write_leveling_static_config(u32 dev_num, u32 if_id, - enum hws_ddr_freq frequency, - u32 *round_trip_delay_arr) -{ - u32 bus_index; /* index to the bus loop */ - u32 bus_start_index; - u32 bus_per_interface; - u32 phase = 0; - u32 adll = 0, adll_cen, adll_inv, adll_final; - u32 adll_period = MEGA / freq_val[frequency] / 64; - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("ddr3_tip_write_leveling_static_config\n")); - DEBUG_TRAINING_STATIC_IP( - DEBUG_LEVEL_TRACE, - ("dev_num 0x%x IF 0x%x freq %d (adll_period 0x%x)\n", - dev_num, if_id, frequency, adll_period)); - - bus_per_interface = GET_TOPOLOGY_NUM_OF_BUSES(); - bus_start_index = if_id * bus_per_interface; - for (bus_index = bus_start_index; - bus_index < (bus_start_index + bus_per_interface); bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); - phase = round_trip_delay_arr[bus_index] / (32 * adll_period); - adll = (round_trip_delay_arr[bus_index] - - (phase * 32 * adll_period)) / adll_period; - adll = (adll > 31) ? 31 : adll; - adll_cen = 16 + adll; - adll_inv = adll_cen / 32; - adll_final = adll_cen - (adll_inv * 32); - adll_final = (adll_final > 31) ? 31 : adll_final; - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("\t%d - phase 0x%x adll 0x%x\n", - bus_index, phase, adll)); - /* - * Writing to all 4 phy of Interface number, - * bit 0 \96 4 \96 ADLL, bit 6-8 phase - */ - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - (bus_index % 4), DDR_PHY_DATA, - PHY_WRITE_DELAY(cs), - ((phase << 6) + (adll & 0x1f)), 0x1df)); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - ACCESS_TYPE_UNICAST, (bus_index % 4), - DDR_PHY_DATA, WRITE_CENTRALIZATION_PHY_REG, - ((adll_inv & 0x1) << 5) + adll_final)); - } - - return MV_OK; -} - -/* - * Read leveling for static flow - */ -int ddr3_tip_read_leveling_static_config(u32 dev_num, - u32 if_id, - enum hws_ddr_freq frequency, - u32 *total_round_trip_delay_arr) -{ - u32 cs, data0, data1, data3 = 0; - u32 bus_index; /* index to the bus loop */ - u32 bus_start_index; - u32 phase0, phase1, max_phase; - u32 adll0, adll1; - u32 cl_value; - u32 min_delay; - u32 sdr_period = MEGA / freq_val[frequency]; - u32 ddr_period = MEGA / freq_val[frequency] / 2; - u32 adll_period = MEGA / freq_val[frequency] / 64; - enum hws_speed_bin speed_bin_index; - u32 rd_sample_dly[MAX_CS_NUM] = { 0 }; - u32 rd_ready_del[MAX_CS_NUM] = { 0 }; - u32 bus_per_interface = GET_TOPOLOGY_NUM_OF_BUSES(); - struct hws_topology_map *tm = ddr3_get_topology_map(); - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("ddr3_tip_read_leveling_static_config\n")); - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("dev_num 0x%x ifc 0x%x freq %d\n", dev_num, - if_id, frequency)); - DEBUG_TRAINING_STATIC_IP( - DEBUG_LEVEL_TRACE, - ("Sdr_period 0x%x Ddr_period 0x%x adll_period 0x%x\n", - sdr_period, ddr_period, adll_period)); - - if (tm->interface_params[first_active_if].memory_freq == - frequency) { - cl_value = tm->interface_params[first_active_if].cas_l; - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("cl_value 0x%x\n", cl_value)); - } else { - speed_bin_index = tm->interface_params[if_id].speed_bin_index; - cl_value = cas_latency_table[speed_bin_index].cl_val[frequency]; - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("cl_value 0x%x speed_bin_index %d\n", - cl_value, speed_bin_index)); - } - - bus_start_index = if_id * bus_per_interface; - - for (bus_index = bus_start_index; - bus_index < (bus_start_index + bus_per_interface); - bus_index += 2) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); - cs = chip_select_map[ - tm->interface_params[if_id].as_bus_params[ - (bus_index % 4)].cs_bitmask].cs_num; - - /* read sample delay calculation */ - min_delay = (total_round_trip_delay_arr[bus_index] < - total_round_trip_delay_arr[bus_index + 1]) ? - total_round_trip_delay_arr[bus_index] : - total_round_trip_delay_arr[bus_index + 1]; - /* round down */ - rd_sample_dly[cs] = 2 * (min_delay / (sdr_period * 2)); - DEBUG_TRAINING_STATIC_IP( - DEBUG_LEVEL_TRACE, - ("\t%d - min_delay 0x%x cs 0x%x rd_sample_dly[cs] 0x%x\n", - bus_index, min_delay, cs, rd_sample_dly[cs])); - - /* phase calculation */ - phase0 = (total_round_trip_delay_arr[bus_index] - - (sdr_period * rd_sample_dly[cs])) / (ddr_period); - phase1 = (total_round_trip_delay_arr[bus_index + 1] - - (sdr_period * rd_sample_dly[cs])) / (ddr_period); - max_phase = (phase0 > phase1) ? phase0 : phase1; - DEBUG_TRAINING_STATIC_IP( - DEBUG_LEVEL_TRACE, - ("\tphase0 0x%x phase1 0x%x max_phase 0x%x\n", - phase0, phase1, max_phase)); - - /* ADLL calculation */ - adll0 = (u32)((total_round_trip_delay_arr[bus_index] - - (sdr_period * rd_sample_dly[cs]) - - (ddr_period * phase0)) / adll_period); - adll0 = (adll0 > 31) ? 31 : adll0; - adll1 = (u32)((total_round_trip_delay_arr[bus_index + 1] - - (sdr_period * rd_sample_dly[cs]) - - (ddr_period * phase1)) / adll_period); - adll1 = (adll1 > 31) ? 31 : adll1; - - /* The Read delay close the Read FIFO */ - rd_ready_del[cs] = rd_sample_dly[cs] + - read_ready_delay_phase_offset[max_phase]; - DEBUG_TRAINING_STATIC_IP( - DEBUG_LEVEL_TRACE, - ("\tadll0 0x%x adll1 0x%x rd_ready_del[cs] 0x%x\n", - adll0, adll1, rd_ready_del[cs])); - - /* - * Write to the phy of Interface (bit 0 \96 4 \96 ADLL, - * bit 6-8 phase) - */ - data0 = ((phase0 << 6) + (adll0 & 0x1f)); - data1 = ((phase1 << 6) + (adll1 & 0x1f)); - - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - (bus_index % 4), DDR_PHY_DATA, PHY_READ_DELAY(cs), - data0, 0x1df)); - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - ((bus_index + 1) % 4), DDR_PHY_DATA, - PHY_READ_DELAY(cs), data1, 0x1df)); - } - - for (bus_index = 0; bus_index < bus_per_interface; bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - bus_index, DDR_PHY_DATA, 0x3, data3, 0x1f)); - } - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_SAMPLE_DELAY, - (rd_sample_dly[0] + cl_value) + (rd_sample_dly[1] << 8), - MASK_ALL_BITS)); - - /* Read_ready_del0 bit 0-4 , CS bits 8-12 */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_READY_DELAY, - rd_ready_del[0] + (rd_ready_del[1] << 8) + cl_value, - MASK_ALL_BITS)); - - return MV_OK; -} - -/* - * DDR3 Static flow - */ -int ddr3_tip_run_static_alg(u32 dev_num, enum hws_ddr_freq freq) -{ - u32 if_id = 0; - struct trip_delay_element *table_ptr; - u32 wl_total_round_trip_delay_arr[MAX_TOTAL_BUS_NUM]; - u32 rl_total_round_trip_delay_arr[MAX_TOTAL_BUS_NUM]; - struct init_cntr_param init_cntr_prm; - int ret; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("ddr3_tip_run_static_alg")); - - init_cntr_prm.do_mrs_phy = 1; - init_cntr_prm.is_ctrl64_bit = 0; - init_cntr_prm.init_phy = 1; - ret = hws_ddr3_tip_init_controller(dev_num, &init_cntr_prm); - if (ret != MV_OK) { - DEBUG_TRAINING_STATIC_IP( - DEBUG_LEVEL_ERROR, - ("hws_ddr3_tip_init_controller failure\n")); - } - - /* calculate the round trip delay for Write Leveling */ - table_ptr = static_config[dev_num].board_trace_arr; - CHECK_STATUS(ddr3_tip_static_round_trip_arr_build - (dev_num, table_ptr, 1, - wl_total_round_trip_delay_arr)); - /* calculate the round trip delay for Read Leveling */ - CHECK_STATUS(ddr3_tip_static_round_trip_arr_build - (dev_num, table_ptr, 0, - rl_total_round_trip_delay_arr)); - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - /* check if the interface is enabled */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - /* - * Static frequency is defined according to init-frequency - * (not target) - */ - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("Static IF %d freq %d\n", - if_id, freq)); - CHECK_STATUS(ddr3_tip_write_leveling_static_config - (dev_num, if_id, freq, - wl_total_round_trip_delay_arr)); - CHECK_STATUS(ddr3_tip_read_leveling_static_config - (dev_num, if_id, freq, - rl_total_round_trip_delay_arr)); - } - - return MV_OK; -} - -/* - * Init controller for static flow - */ -int ddr3_tip_static_init_controller(u32 dev_num) -{ - u32 index_cnt = 0; - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("ddr3_tip_static_init_controller\n")); - while (static_init_controller_config[dev_num][index_cnt].reg_addr != - 0) { - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - static_init_controller_config[dev_num][index_cnt]. - reg_addr, - static_init_controller_config[dev_num][index_cnt]. - reg_data, - static_init_controller_config[dev_num][index_cnt]. - reg_mask)); - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("Init_controller index_cnt %d\n", - index_cnt)); - index_cnt++; - } - - return MV_OK; -} - -int ddr3_tip_static_phy_init_controller(u32 dev_num) -{ - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("Phy Init Controller 2\n")); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xa4, - 0x3dfe)); - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("Phy Init Controller 3\n")); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xa6, - 0xcb2)); - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("Phy Init Controller 4\n")); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xa9, - 0)); - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("Static Receiver Calibration\n")); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xd0, - 0x1f)); - - DEBUG_TRAINING_STATIC_IP(DEBUG_LEVEL_TRACE, - ("Static V-REF Calibration\n")); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0xa8, - 0x434)); - - return MV_OK; -} -#endif /* * Configure phy (called by static init controller) for static flow -- cgit From 2b4ffbf6b4944a0b3125fd2c9c0ba3568264367a Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 May 2018 13:28:29 +1200 Subject: ARM: mvebu: a38x: sync ddr training code with upstream This syncs drivers/ddr/marvell/a38x/ with the mv_ddr-armada-17.10 branch of https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git. The upstream code is incorporated omitting the ddr4 and apn806 and folding the nested a38x directory up one level. After that a semi-automated step is used to drop unused features with unifdef find drivers/ddr/marvell/a38x/ -name '*.[ch]' | \ xargs unifdef -m -UMV_DDR -UMV_DDR_ATF -UCONFIG_DDR4 \ -UCONFIG_APN806 -UCONFIG_MC_STATIC \ -UCONFIG_MC_STATIC_PRINT -UCONFIG_PHY_STATIC \ -UCONFIG_64BIT INTER_REGS_BASE is updated to be defined as SOC_REGS_PHY_BASE. Some now empty files are removed and the ternary license is replaced with a SPDX GPL-2.0+ identifier. Signed-off-by: Chris Packham Signed-off-by: Stefan Roese --- board/CZ.NIC/turris_omnia/turris_omnia.c | 36 +- board/Marvell/db-88f6820-amc/db-88f6820-amc.c | 20 +- board/Marvell/db-88f6820-gp/db-88f6820-gp.c | 20 +- board/gdsys/a38x/controlcenterdc.c | 21 +- board/solidrun/clearfog/clearfog.c | 20 +- drivers/ddr/marvell/a38x/Makefile | 10 +- drivers/ddr/marvell/a38x/ddr3_a38x.c | 685 --------- drivers/ddr/marvell/a38x/ddr3_a38x.h | 92 -- drivers/ddr/marvell/a38x/ddr3_a38x_topology.h | 21 - drivers/ddr/marvell/a38x/ddr3_a38x_training.c | 39 - drivers/ddr/marvell/a38x/ddr3_debug.c | 733 ++++++---- drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c | 147 -- drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h | 48 - .../ddr/marvell/a38x/ddr3_hws_hw_training_def.h | 461 ------- drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h | 16 - drivers/ddr/marvell/a38x/ddr3_init.c | 745 ++-------- drivers/ddr/marvell/a38x/ddr3_init.h | 299 +--- drivers/ddr/marvell/a38x/ddr3_logging_def.h | 10 +- drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h | 1 + drivers/ddr/marvell/a38x/ddr3_topology_def.h | 6 +- drivers/ddr/marvell/a38x/ddr3_training.c | 1450 +++++++++++-------- drivers/ddr/marvell/a38x/ddr3_training_bist.c | 548 ++++++-- .../marvell/a38x/ddr3_training_centralization.c | 108 +- drivers/ddr/marvell/a38x/ddr3_training_db.c | 267 +++- drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c | 98 +- drivers/ddr/marvell/a38x/ddr3_training_ip.h | 19 +- drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h | 6 +- drivers/ddr/marvell/a38x/ddr3_training_ip_db.h | 71 +- drivers/ddr/marvell/a38x/ddr3_training_ip_def.h | 34 +- drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c | 1134 +++++++++------ drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h | 9 +- drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h | 305 +--- drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h | 17 +- drivers/ddr/marvell/a38x/ddr3_training_ip_static.h | 30 - drivers/ddr/marvell/a38x/ddr3_training_leveling.c | 1347 ++++++++++-------- drivers/ddr/marvell/a38x/ddr3_training_leveling.h | 2 +- drivers/ddr/marvell/a38x/ddr3_training_pbs.c | 201 +-- drivers/ddr/marvell/a38x/ddr3_training_static.c | 100 -- drivers/ddr/marvell/a38x/ddr_ml_wrapper.h | 148 ++ drivers/ddr/marvell/a38x/ddr_topology_def.h | 83 +- drivers/ddr/marvell/a38x/mv_ddr_build_message.c | 1 + drivers/ddr/marvell/a38x/mv_ddr_common.c | 47 + drivers/ddr/marvell/a38x/mv_ddr_common.h | 20 + drivers/ddr/marvell/a38x/mv_ddr_plat.c | 1455 ++++++++++++++++++++ drivers/ddr/marvell/a38x/mv_ddr_plat.h | 235 ++++ drivers/ddr/marvell/a38x/mv_ddr_regs.h | 446 ++++++ drivers/ddr/marvell/a38x/mv_ddr_spd.c | 377 +++++ drivers/ddr/marvell/a38x/mv_ddr_spd.h | 289 ++++ drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c | 102 ++ drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h | 117 ++ drivers/ddr/marvell/a38x/mv_ddr_topology.c | 197 +++ drivers/ddr/marvell/a38x/mv_ddr_topology.h | 123 ++ drivers/ddr/marvell/a38x/seq_exec.h | 64 + drivers/ddr/marvell/a38x/silicon_if.h | 16 - drivers/ddr/marvell/a38x/xor.c | 184 ++- drivers/ddr/marvell/a38x/xor.h | 3 +- 56 files changed, 7944 insertions(+), 5139 deletions(-) delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x.c delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x_topology.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_a38x_training.c delete mode 100644 drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c delete mode 100644 drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_training_ip_static.h delete mode 100644 drivers/ddr/marvell/a38x/ddr3_training_static.c create mode 100644 drivers/ddr/marvell/a38x/ddr_ml_wrapper.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_build_message.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_common.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_common.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_plat.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_plat.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_regs.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_spd.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_spd.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_topology.c create mode 100644 drivers/ddr/marvell/a38x/mv_ddr_topology.h create mode 100644 drivers/ddr/marvell/a38x/seq_exec.h delete mode 100644 drivers/ddr/marvell/a38x/silicon_if.h diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 58d1f5fe35..29f81cdccf 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -27,7 +27,7 @@ # include #endif -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> DECLARE_GLOBAL_DATA_PTR; @@ -200,7 +200,8 @@ static bool omnia_read_eeprom(struct omnia_eeprom *oep) * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map board_topology_map_1g = { +static struct mv_ddr_topology_map board_topology_map_1g = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -209,17 +210,19 @@ static struct hws_topology_map board_topology_map_1g = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1600K, /* speed_bin */ - BUS_WIDTH_16, /* memory_width */ - MEM_4G, /* mem_size */ + MV_DDR_DEV_WIDTH_16BIT, /* memory_width */ + MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_NORMAL, /* temperature */ - HWS_TIM_2T} }, /* timing (force 2t) */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_NORMAL} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -static struct hws_topology_map board_topology_map_2g = { +static struct mv_ddr_topology_map board_topology_map_2g = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -228,17 +231,18 @@ static struct hws_topology_map board_topology_map_2g = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1600K, /* speed_bin */ - BUS_WIDTH_16, /* memory_width */ - MEM_8G, /* mem_size */ + MV_DDR_DEV_WIDTH_16BIT, /* memory_width */ + MV_DDR_DIE_CAP_8GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_NORMAL, /* temperature */ - HWS_TIM_2T} }, /* timing (force 2t) */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_NORMAL} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { static int mem = 0; struct omnia_eeprom oep; diff --git a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c index ba9738c0f7..e39dc75f92 100644 --- a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c +++ b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c @@ -11,7 +11,7 @@ #include #include -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> DECLARE_GLOBAL_DATA_PTR; @@ -55,7 +55,8 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map board_topology_map = { +static struct mv_ddr_topology_map board_topology_map = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -64,17 +65,18 @@ static struct hws_topology_map board_topology_map = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1866L, /* speed_bin */ - BUS_WIDTH_8, /* memory_width */ - MEM_2G, /* mem_size */ + MV_DDR_DEV_WIDTH_8BIT, /* memory_width */ + MV_DDR_DIE_CAP_2GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_LOW, /* temperature */ - HWS_TIM_DEFAULT} }, /* timing */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { /* Return the board topology as defined in the board code */ return &board_topology_map; diff --git a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c index fc405b939b..ee12ca68ec 100644 --- a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c +++ b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c @@ -11,7 +11,7 @@ #include #include -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> DECLARE_GLOBAL_DATA_PTR; @@ -76,7 +76,8 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map board_topology_map = { +static struct mv_ddr_topology_map board_topology_map = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -85,17 +86,18 @@ static struct hws_topology_map board_topology_map = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1866L, /* speed_bin */ - BUS_WIDTH_8, /* memory_width */ - MEM_4G, /* mem_size */ + MV_DDR_DEV_WIDTH_8BIT, /* memory_width */ + MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_LOW, /* temperature */ - HWS_TIM_DEFAULT} }, /* timing */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { /* Return the board topology as defined in the board code */ return &board_topology_map; diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c index 5599767dff..f750e47b72 100644 --- a/board/gdsys/a38x/controlcenterdc.c +++ b/board/gdsys/a38x/controlcenterdc.c @@ -12,7 +12,7 @@ #include #include -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include "../arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.h" #include "keyprogram.h" @@ -39,7 +39,8 @@ DECLARE_GLOBAL_DATA_PTR; * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map ddr_topology_map = { +static struct mv_ddr_topology_map ddr_topology_map = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -48,14 +49,16 @@ static struct hws_topology_map ddr_topology_map = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1600K, /* speed_bin */ - BUS_WIDTH_16, /* memory_width */ - MEM_4G, /* mem_size */ + MV_DDR_DEV_WIDTH_16BIT, /* memory_width */ + MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_533, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_LOW, /* temperature */ - HWS_TIM_DEFAULT} }, /* timing */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ + }; static struct serdes_map serdes_topology_map[] = { @@ -121,7 +124,7 @@ void board_pex_config(void) #endif } -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { return &ddr_topology_map; } diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c index 61de16d19e..cc11feb85e 100644 --- a/board/solidrun/clearfog/clearfog.c +++ b/board/solidrun/clearfog/clearfog.c @@ -11,7 +11,7 @@ #include #include -#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h" +#include "../drivers/ddr/marvell/a38x/ddr3_init.h" #include <../serdes/a38x/high_speed_env_spec.h> DECLARE_GLOBAL_DATA_PTR; @@ -69,7 +69,8 @@ int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count) * be used by the DDR3 init code in the SPL U-Boot version to configure * the DDR3 controller. */ -static struct hws_topology_map board_topology_map = { +static struct mv_ddr_topology_map board_topology_map = { + DEBUG_LEVEL_ERROR, 0x1, /* active interfaces */ /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */ { { { {0x1, 0, 0, 0}, @@ -78,17 +79,18 @@ static struct hws_topology_map board_topology_map = { {0x1, 0, 0, 0}, {0x1, 0, 0, 0} }, SPEED_BIN_DDR_1600K, /* speed_bin */ - BUS_WIDTH_16, /* memory_width */ - MEM_4G, /* mem_size */ + MV_DDR_DEV_WIDTH_16BIT, /* memory_width */ + MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - HWS_TEMP_LOW, /* temperature */ - HWS_TIM_DEFAULT} }, /* timing */ - 5, /* Num Of Bus Per Interface*/ - BUS_MASK_32BIT /* Busses mask */ + MV_DDR_TEMP_LOW} }, /* temperature */ + BUS_MASK_32BIT, /* Busses mask */ + MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ + { {0} }, /* raw spd data */ + {0} /* timing parameters */ }; -struct hws_topology_map *ddr3_get_topology_map(void) +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void) { /* Return the board topology as defined in the board code */ return &board_topology_map; diff --git a/drivers/ddr/marvell/a38x/Makefile b/drivers/ddr/marvell/a38x/Makefile index 5e258bfe6a..8251d6db66 100644 --- a/drivers/ddr/marvell/a38x/Makefile +++ b/drivers/ddr/marvell/a38x/Makefile @@ -1,9 +1,8 @@ # SPDX-License-Identifier: GPL-2.0+ -obj-$(CONFIG_SPL_BUILD) += ddr3_a38x.o -obj-$(CONFIG_SPL_BUILD) += ddr3_a38x_training.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_plat.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_sys_env_lib.o obj-$(CONFIG_SPL_BUILD) += ddr3_debug.o -obj-$(CONFIG_SPL_BUILD) += ddr3_hws_hw_training.o obj-$(CONFIG_SPL_BUILD) += ddr3_init.o obj-$(CONFIG_SPL_BUILD) += ddr3_training.o obj-$(CONFIG_SPL_BUILD) += ddr3_training_bist.o @@ -13,5 +12,8 @@ obj-$(CONFIG_SPL_BUILD) += ddr3_training_hw_algo.o obj-$(CONFIG_SPL_BUILD) += ddr3_training_ip_engine.o obj-$(CONFIG_SPL_BUILD) += ddr3_training_leveling.o obj-$(CONFIG_SPL_BUILD) += ddr3_training_pbs.o -obj-$(CONFIG_SPL_BUILD) += ddr3_training_static.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_build_message.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_common.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_spd.o +obj-$(CONFIG_SPL_BUILD) += mv_ddr_topology.o obj-$(CONFIG_SPL_BUILD) += xor.o diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x.c b/drivers/ddr/marvell/a38x/ddr3_a38x.c deleted file mode 100644 index c356d09008..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x.c +++ /dev/null @@ -1,685 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#include -#include -#include -#include -#include -#include - -#include "ddr3_init.h" - -#define A38X_NUMBER_OF_INTERFACES 5 - -#define SAR_DEV_ID_OFFS 27 -#define SAR_DEV_ID_MASK 0x7 - -/* Termal Sensor Registers */ -#define TSEN_STATE_REG 0xe4070 -#define TSEN_STATE_OFFSET 31 -#define TSEN_STATE_MASK (0x1 << TSEN_STATE_OFFSET) -#define TSEN_CONF_REG 0xe4074 -#define TSEN_CONF_RST_OFFSET 8 -#define TSEN_CONF_RST_MASK (0x1 << TSEN_CONF_RST_OFFSET) -#define TSEN_STATUS_REG 0xe4078 -#define TSEN_STATUS_READOUT_VALID_OFFSET 10 -#define TSEN_STATUS_READOUT_VALID_MASK (0x1 << \ - TSEN_STATUS_READOUT_VALID_OFFSET) -#define TSEN_STATUS_TEMP_OUT_OFFSET 0 -#define TSEN_STATUS_TEMP_OUT_MASK (0x3ff << TSEN_STATUS_TEMP_OUT_OFFSET) - -static struct dfx_access interface_map[] = { - /* Pipe Client */ - { 0, 17 }, - { 1, 7 }, - { 1, 11 }, - { 0, 3 }, - { 1, 25 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 } -}; - -/* This array hold the board round trip delay (DQ and CK) per */ -struct trip_delay_element a38x_board_round_trip_delay_array[] = { - /* 1st board */ - /* Interface bus DQS-delay CK-delay */ - { 3952, 5060 }, - { 3192, 4493 }, - { 4785, 6677 }, - { 3413, 7267 }, - { 4282, 6086 }, /* ECC PUP */ - { 3952, 5134 }, - { 3192, 4567 }, - { 4785, 6751 }, - { 3413, 7341 }, - { 4282, 6160 }, /* ECC PUP */ - - /* 2nd board */ - /* Interface bus DQS-delay CK-delay */ - { 3952, 5060 }, - { 3192, 4493 }, - { 4785, 6677 }, - { 3413, 7267 }, - { 4282, 6086 }, /* ECC PUP */ - { 3952, 5134 }, - { 3192, 4567 }, - { 4785, 6751 }, - { 3413, 7341 }, - { 4282, 6160 } /* ECC PUP */ -}; - - -static u8 a38x_bw_per_freq[DDR_FREQ_LIMIT] = { - 0x3, /* DDR_FREQ_100 */ - 0x4, /* DDR_FREQ_400 */ - 0x4, /* DDR_FREQ_533 */ - 0x5, /* DDR_FREQ_667 */ - 0x5, /* DDR_FREQ_800 */ - 0x5, /* DDR_FREQ_933 */ - 0x5, /* DDR_FREQ_1066 */ - 0x3, /* DDR_FREQ_311 */ - 0x3, /* DDR_FREQ_333 */ - 0x4, /* DDR_FREQ_467 */ - 0x5, /* DDR_FREQ_850 */ - 0x5, /* DDR_FREQ_600 */ - 0x3, /* DDR_FREQ_300 */ - 0x5, /* DDR_FREQ_900 */ - 0x3, /* DDR_FREQ_360 */ - 0x5 /* DDR_FREQ_1000 */ -}; - -static u8 a38x_rate_per_freq[DDR_FREQ_LIMIT] = { - /*TBD*/ 0x1, /* DDR_FREQ_100 */ - 0x2, /* DDR_FREQ_400 */ - 0x2, /* DDR_FREQ_533 */ - 0x2, /* DDR_FREQ_667 */ - 0x2, /* DDR_FREQ_800 */ - 0x3, /* DDR_FREQ_933 */ - 0x3, /* DDR_FREQ_1066 */ - 0x1, /* DDR_FREQ_311 */ - 0x1, /* DDR_FREQ_333 */ - 0x2, /* DDR_FREQ_467 */ - 0x2, /* DDR_FREQ_850 */ - 0x2, /* DDR_FREQ_600 */ - 0x1, /* DDR_FREQ_300 */ - 0x2, /* DDR_FREQ_900 */ - 0x1, /* DDR_FREQ_360 */ - 0x2 /* DDR_FREQ_1000 */ -}; - -static u16 a38x_vco_freq_per_sar[] = { - 666, /* 0 */ - 1332, - 800, - 1600, - 1066, - 2132, - 1200, - 2400, - 1332, - 1332, - 1500, - 1500, - 1600, /* 12 */ - 1600, - 1700, - 1700, - 1866, - 1866, - 1800, /* 18 */ - 2000, - 2000, - 4000, - 2132, - 2132, - 2300, - 2300, - 2400, - 2400, - 2500, - 2500, - 800 -}; - -u32 pipe_multicast_mask; - -u32 dq_bit_map_2_phy_pin[] = { - 1, 0, 2, 6, 9, 8, 3, 7, /* 0 */ - 8, 9, 1, 7, 2, 6, 3, 0, /* 1 */ - 3, 9, 7, 8, 1, 0, 2, 6, /* 2 */ - 1, 0, 6, 2, 8, 3, 7, 9, /* 3 */ - 0, 1, 2, 9, 7, 8, 3, 6, /* 4 */ -}; - -static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id, - enum hws_ddr_freq freq); - -/* - * Read temperature TJ value - */ -u32 ddr3_ctrl_get_junc_temp(u8 dev_num) -{ - int reg = 0; - - /* Initiates TSEN hardware reset once */ - if ((reg_read(TSEN_CONF_REG) & TSEN_CONF_RST_MASK) == 0) - reg_bit_set(TSEN_CONF_REG, TSEN_CONF_RST_MASK); - mdelay(10); - - /* Check if the readout field is valid */ - if ((reg_read(TSEN_STATUS_REG) & TSEN_STATUS_READOUT_VALID_MASK) == 0) { - printf("%s: TSEN not ready\n", __func__); - return 0; - } - - reg = reg_read(TSEN_STATUS_REG); - reg = (reg & TSEN_STATUS_TEMP_OUT_MASK) >> TSEN_STATUS_TEMP_OUT_OFFSET; - - return ((((10000 * reg) / 21445) * 1000) - 272674) / 1000; -} - -/* - * Name: ddr3_tip_a38x_get_freq_config. - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_get_freq_config(u8 dev_num, enum hws_ddr_freq freq, - struct hws_tip_freq_config_info - *freq_config_info) -{ - if (a38x_bw_per_freq[freq] == 0xff) - return MV_NOT_SUPPORTED; - - if (freq_config_info == NULL) - return MV_BAD_PARAM; - - freq_config_info->bw_per_freq = a38x_bw_per_freq[freq]; - freq_config_info->rate_per_freq = a38x_rate_per_freq[freq]; - freq_config_info->is_supported = 1; - - return MV_OK; -} - -/* - * Name: ddr3_tip_a38x_pipe_enable. - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_pipe_enable(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, int enable) -{ - u32 data_value, pipe_enable_mask = 0; - - if (enable == 0) { - pipe_enable_mask = 0; - } else { - if (interface_access == ACCESS_TYPE_MULTICAST) - pipe_enable_mask = pipe_multicast_mask; - else - pipe_enable_mask = (1 << interface_map[if_id].pipe); - } - - CHECK_STATUS(ddr3_tip_reg_read - (dev_num, PIPE_ENABLE_ADDR, &data_value, MASK_ALL_BITS)); - data_value = (data_value & (~0xff)) | pipe_enable_mask; - CHECK_STATUS(ddr3_tip_reg_write(dev_num, PIPE_ENABLE_ADDR, data_value)); - - return MV_OK; -} - -/* - * Name: ddr3_tip_a38x_if_write. - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_if_write(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, u32 reg_addr, u32 data_value, - u32 mask) -{ - u32 ui_data_read; - - if (mask != MASK_ALL_BITS) { - CHECK_STATUS(ddr3_tip_a38x_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, reg_addr, - &ui_data_read, MASK_ALL_BITS)); - data_value = (ui_data_read & (~mask)) | (data_value & mask); - } - - reg_write(reg_addr, data_value); - - return MV_OK; -} - -/* - * Name: ddr3_tip_a38x_if_read. - * Desc: - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_if_read(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, u32 reg_addr, u32 *data, u32 mask) -{ - *data = reg_read(reg_addr) & mask; - - return MV_OK; -} - -/* - * Name: ddr3_tip_a38x_select_ddr_controller. - * Desc: Enable/Disable access to Marvell's server. - * Args: dev_num - device number - * enable - whether to enable or disable the server - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -int ddr3_tip_a38x_select_ddr_controller(u8 dev_num, int enable) -{ - u32 reg; - - reg = reg_read(CS_ENABLE_REG); - - if (enable) - reg |= (1 << 6); - else - reg &= ~(1 << 6); - - reg_write(CS_ENABLE_REG, reg); - - return MV_OK; -} - -/* - * Name: ddr3_tip_init_a38x_silicon. - * Desc: init Training SW DB. - * Args: - * Notes: - * Returns: MV_OK if success, other error code if fail. - */ -static int ddr3_tip_init_a38x_silicon(u32 dev_num, u32 board_id) -{ - struct hws_tip_config_func_db config_func; - enum hws_ddr_freq ddr_freq; - int status; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* new read leveling version */ - config_func.tip_dunit_read_func = ddr3_tip_a38x_if_read; - config_func.tip_dunit_write_func = ddr3_tip_a38x_if_write; - config_func.tip_dunit_mux_select_func = - ddr3_tip_a38x_select_ddr_controller; - config_func.tip_get_freq_config_info_func = - ddr3_tip_a38x_get_freq_config; - config_func.tip_set_freq_divider_func = ddr3_tip_a38x_set_divider; - config_func.tip_get_device_info_func = ddr3_tip_a38x_get_device_info; - config_func.tip_get_temperature = ddr3_ctrl_get_junc_temp; - - ddr3_tip_init_config_func(dev_num, &config_func); - - ddr3_tip_register_dq_table(dev_num, dq_bit_map_2_phy_pin); - - status = ddr3_tip_a38x_get_init_freq(dev_num, &ddr_freq); - if (MV_OK != status) { - DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, - ("DDR3 silicon get target frequency - FAILED 0x%x\n", - status)); - return status; - } - - rl_version = 1; - mask_tune_func = (SET_LOW_FREQ_MASK_BIT | - LOAD_PATTERN_MASK_BIT | - SET_MEDIUM_FREQ_MASK_BIT | WRITE_LEVELING_MASK_BIT | - /* LOAD_PATTERN_2_MASK_BIT | */ - WRITE_LEVELING_SUPP_MASK_BIT | - READ_LEVELING_MASK_BIT | - PBS_RX_MASK_BIT | - PBS_TX_MASK_BIT | - SET_TARGET_FREQ_MASK_BIT | - WRITE_LEVELING_TF_MASK_BIT | - WRITE_LEVELING_SUPP_TF_MASK_BIT | - READ_LEVELING_TF_MASK_BIT | - CENTRALIZATION_RX_MASK_BIT | - CENTRALIZATION_TX_MASK_BIT); - rl_mid_freq_wa = 1; - - if ((ddr_freq == DDR_FREQ_333) || (ddr_freq == DDR_FREQ_400)) { - mask_tune_func = (WRITE_LEVELING_MASK_BIT | - LOAD_PATTERN_2_MASK_BIT | - WRITE_LEVELING_SUPP_MASK_BIT | - READ_LEVELING_MASK_BIT | - PBS_RX_MASK_BIT | - PBS_TX_MASK_BIT | - CENTRALIZATION_RX_MASK_BIT | - CENTRALIZATION_TX_MASK_BIT); - rl_mid_freq_wa = 0; /* WA not needed if 333/400 is TF */ - } - - /* Supplementary not supported for ECC modes */ - if (1 == ddr3_if_ecc_enabled()) { - mask_tune_func &= ~WRITE_LEVELING_SUPP_TF_MASK_BIT; - mask_tune_func &= ~WRITE_LEVELING_SUPP_MASK_BIT; - mask_tune_func &= ~PBS_TX_MASK_BIT; - mask_tune_func &= ~PBS_RX_MASK_BIT; - } - - if (ck_delay == -1) - ck_delay = 160; - if (ck_delay_16 == -1) - ck_delay_16 = 160; - ca_delay = 0; - delay_enable = 1; - - calibration_update_control = 1; - - init_freq = tm->interface_params[first_active_if].memory_freq; - - ddr3_tip_a38x_get_medium_freq(dev_num, &medium_freq); - - return MV_OK; -} - -int ddr3_a38x_update_topology_map(u32 dev_num, struct hws_topology_map *tm) -{ - u32 if_id = 0; - enum hws_ddr_freq freq; - - ddr3_tip_a38x_get_init_freq(dev_num, &freq); - tm->interface_params[if_id].memory_freq = freq; - - /* - * re-calc topology parameters according to topology updates - * (if needed) - */ - CHECK_STATUS(hws_ddr3_tip_load_topology_map(dev_num, tm)); - - return MV_OK; -} - -int ddr3_tip_init_a38x(u32 dev_num, u32 board_id) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (NULL == tm) - return MV_FAIL; - - ddr3_a38x_update_topology_map(dev_num, tm); - ddr3_tip_init_a38x_silicon(dev_num, board_id); - - return MV_OK; -} - -int ddr3_tip_a38x_get_init_freq(int dev_num, enum hws_ddr_freq *freq) -{ - u32 reg; - - /* Read sample at reset setting */ - reg = (reg_read(REG_DEVICE_SAR1_ADDR) >> - RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & - RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; - switch (reg) { - case 0x0: - case 0x1: - *freq = DDR_FREQ_333; - break; - case 0x2: - case 0x3: - *freq = DDR_FREQ_400; - break; - case 0x4: - case 0xd: - *freq = DDR_FREQ_533; - break; - case 0x6: - *freq = DDR_FREQ_600; - break; - case 0x8: - case 0x11: - case 0x14: - *freq = DDR_FREQ_667; - break; - case 0xc: - case 0x15: - case 0x1b: - *freq = DDR_FREQ_800; - break; - case 0x10: - *freq = DDR_FREQ_933; - break; - case 0x12: - *freq = DDR_FREQ_900; - break; - case 0x13: - *freq = DDR_FREQ_900; - break; - default: - *freq = 0; - return MV_NOT_SUPPORTED; - } - - return MV_OK; -} - -int ddr3_tip_a38x_get_medium_freq(int dev_num, enum hws_ddr_freq *freq) -{ - u32 reg; - - /* Read sample at reset setting */ - reg = (reg_read(REG_DEVICE_SAR1_ADDR) >> - RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & - RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; - switch (reg) { - case 0x0: - case 0x1: - /* Medium is same as TF to run PBS in this freq */ - *freq = DDR_FREQ_333; - break; - case 0x2: - case 0x3: - /* Medium is same as TF to run PBS in this freq */ - *freq = DDR_FREQ_400; - break; - case 0x4: - case 0xd: - *freq = DDR_FREQ_533; - break; - case 0x8: - case 0x11: - case 0x14: - *freq = DDR_FREQ_333; - break; - case 0xc: - case 0x15: - case 0x1b: - *freq = DDR_FREQ_400; - break; - case 0x6: - *freq = DDR_FREQ_300; - break; - case 0x12: - *freq = DDR_FREQ_360; - break; - case 0x13: - *freq = DDR_FREQ_400; - break; - default: - *freq = 0; - return MV_NOT_SUPPORTED; - } - - return MV_OK; -} - -u32 ddr3_tip_get_init_freq(void) -{ - enum hws_ddr_freq freq; - - ddr3_tip_a38x_get_init_freq(0, &freq); - - return freq; -} - -static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id, - enum hws_ddr_freq frequency) -{ - u32 divider = 0; - u32 sar_val; - - if (if_id != 0) { - DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, - ("A38x does not support interface 0x%x\n", - if_id)); - return MV_BAD_PARAM; - } - - /* get VCO freq index */ - sar_val = (reg_read(REG_DEVICE_SAR1_ADDR) >> - RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & - RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; - divider = a38x_vco_freq_per_sar[sar_val] / freq_val[frequency]; - - /* Set Sync mode */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x20220, 0x0, - 0x1000)); - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe42f4, 0x0, - 0x200)); - - /* cpupll_clkdiv_reset_mask */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0x1f, - 0xff)); - - /* cpupll_clkdiv_reload_smooth */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, - (0x2 << 8), (0xff << 8))); - - /* cpupll_clkdiv_relax_en */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, - (0x2 << 24), (0xff << 24))); - - /* write the divider */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4268, - (divider << 8), (0x3f << 8))); - - /* set cpupll_clkdiv_reload_ratio */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, - (1 << 8), (1 << 8))); - - /* undet cpupll_clkdiv_reload_ratio */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0, - (1 << 8))); - - /* clear cpupll_clkdiv_reload_force */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, 0, - (0xff << 8))); - - /* clear cpupll_clkdiv_relax_en */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, 0, - (0xff << 24))); - - /* clear cpupll_clkdiv_reset_mask */ - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0, - 0xff)); - - /* Dunit training clock + 1:1 mode */ - if ((frequency == DDR_FREQ_LOW_FREQ) || (freq_val[frequency] <= 400)) { - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x18488, - (1 << 16), (1 << 16))); - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1524, - (0 << 15), (1 << 15))); - } else { - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x18488, - 0, (1 << 16))); - CHECK_STATUS(ddr3_tip_a38x_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1524, - (1 << 15), (1 << 15))); - } - - return MV_OK; -} - -/* - * external read from memory - */ -int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr, - u32 num_of_bursts, u32 *data) -{ - u32 burst_num; - - for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++) - data[burst_num] = readl(reg_addr + 4 * burst_num); - - return MV_OK; -} - -/* - * external write to memory - */ -int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr, - u32 num_of_bursts, u32 *data) { - u32 burst_num; - - for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++) - writel(data[burst_num], reg_addr + 4 * burst_num); - - return MV_OK; -} - -int ddr3_silicon_pre_init(void) -{ - return ddr3_silicon_init(); -} - -int ddr3_post_run_alg(void) -{ - return MV_OK; -} - -int ddr3_silicon_post_init(void) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* Set half bus width */ - if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask)) { - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - REG_SDRAM_CONFIG_ADDR, 0x0, 0x8000)); - } - - return MV_OK; -} - -int ddr3_tip_a38x_get_device_info(u8 dev_num, struct ddr3_device_info *info_ptr) -{ - info_ptr->device_id = 0x6800; - info_ptr->ck_delay = ck_delay; - - return MV_OK; -} diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x.h b/drivers/ddr/marvell/a38x/ddr3_a38x.h deleted file mode 100644 index 2543575895..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x.h +++ /dev/null @@ -1,92 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#ifndef _DDR3_A38X_H -#define _DDR3_A38X_H - -#define MAX_INTERFACE_NUM 1 -#define MAX_BUS_NUM 5 - -#include "ddr3_hws_hw_training_def.h" - -#define ECC_SUPPORT - -/* right now, we're not supporting this in mainline */ -#undef SUPPORT_STATIC_DUNIT_CONFIG - -/* Controler bus divider 1 for 32 bit, 2 for 64 bit */ -#define DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER 1 - -/* Tune internal training params values */ -#define TUNE_TRAINING_PARAMS_CK_DELAY 160 -#define TUNE_TRAINING_PARAMS_CK_DELAY_16 160 -#define TUNE_TRAINING_PARAMS_PFINGER 41 -#define TUNE_TRAINING_PARAMS_NFINGER 43 -#define TUNE_TRAINING_PARAMS_PHYREG3VAL 0xa - -#define MARVELL_BOARD MARVELL_BOARD_ID_BASE - - -#define REG_DEVICE_SAR1_ADDR 0xe4204 -#define RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET 17 -#define RST2_CPU_DDR_CLOCK_SELECT_IN_MASK 0x1f - -/* DRAM Windows */ -#define REG_XBAR_WIN_5_CTRL_ADDR 0x20050 -#define REG_XBAR_WIN_5_BASE_ADDR 0x20054 - -/* DRAM Windows */ -#define REG_XBAR_WIN_4_CTRL_ADDR 0x20040 -#define REG_XBAR_WIN_4_BASE_ADDR 0x20044 -#define REG_XBAR_WIN_4_REMAP_ADDR 0x20048 -#define REG_XBAR_WIN_7_REMAP_ADDR 0x20078 -#define REG_XBAR_WIN_16_CTRL_ADDR 0x200d0 -#define REG_XBAR_WIN_16_BASE_ADDR 0x200d4 -#define REG_XBAR_WIN_16_REMAP_ADDR 0x200dc -#define REG_XBAR_WIN_19_CTRL_ADDR 0x200e8 - -#define REG_FASTPATH_WIN_BASE_ADDR(win) (0x20180 + (0x8 * win)) -#define REG_FASTPATH_WIN_CTRL_ADDR(win) (0x20184 + (0x8 * win)) - -/* SatR defined too change topology busWidth and ECC configuration */ -#define DDR_SATR_CONFIG_MASK_WIDTH 0x8 -#define DDR_SATR_CONFIG_MASK_ECC 0x10 -#define DDR_SATR_CONFIG_MASK_ECC_PUP 0x20 - -#define REG_SAMPLE_RESET_HIGH_ADDR 0x18600 - -#define MV_BOARD_REFCLK MV_BOARD_REFCLK_25MHZ - -/* Matrix enables DRAM modes (bus width/ECC) per boardId */ -#define TOPOLOGY_UPDATE_32BIT 0 -#define TOPOLOGY_UPDATE_32BIT_ECC 1 -#define TOPOLOGY_UPDATE_16BIT 2 -#define TOPOLOGY_UPDATE_16BIT_ECC 3 -#define TOPOLOGY_UPDATE_16BIT_ECC_PUP3 4 -#define TOPOLOGY_UPDATE { \ - /* 32Bit, 32bit ECC, 16bit, 16bit ECC PUP4, 16bit ECC PUP3 */ \ - {1, 1, 1, 1, 1}, /* RD_NAS_68XX_ID */ \ - {1, 1, 1, 1, 1}, /* DB_68XX_ID */ \ - {1, 0, 1, 0, 1}, /* RD_AP_68XX_ID */ \ - {1, 0, 1, 0, 1}, /* DB_AP_68XX_ID */ \ - {1, 0, 1, 0, 1}, /* DB_GP_68XX_ID */ \ - {0, 0, 1, 1, 0}, /* DB_BP_6821_ID */ \ - {1, 1, 1, 1, 1} /* DB_AMC_6820_ID */ \ - }; - -enum { - CPU_1066MHZ_DDR_400MHZ, - CPU_RESERVED_DDR_RESERVED0, - CPU_667MHZ_DDR_667MHZ, - CPU_800MHZ_DDR_800MHZ, - CPU_RESERVED_DDR_RESERVED1, - CPU_RESERVED_DDR_RESERVED2, - CPU_RESERVED_DDR_RESERVED3, - LAST_FREQ -}; - -#define ACTIVE_INTERFACE_MASK 0x1 - -#endif /* _DDR3_A38X_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x_topology.h b/drivers/ddr/marvell/a38x/ddr3_a38x_topology.h deleted file mode 100644 index be8de88f4e..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x_topology.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#ifndef _DDR3_A38X_TOPOLOGY_H -#define _DDR3_A38X_TOPOLOGY_H - -#include "ddr_topology_def.h" - -/* Bus mask variants */ -#define BUS_MASK_32BIT 0xf -#define BUS_MASK_32BIT_ECC 0x1f -#define BUS_MASK_16BIT 0x3 -#define BUS_MASK_16BIT_ECC 0x13 -#define BUS_MASK_16BIT_ECC_PUP3 0xb - -#define DYNAMIC_CS_SIZE_CONFIG -#define DISABLE_L2_FILTERING_DURING_DDR_TRAINING - -#endif /* _DDR3_A38X_TOPOLOGY_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_a38x_training.c b/drivers/ddr/marvell/a38x/ddr3_a38x_training.c deleted file mode 100644 index 7a05e58988..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_a38x_training.c +++ /dev/null @@ -1,39 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#include -#include -#include -#include -#include -#include - -#include "ddr3_init.h" - -/* - * Name: ddr3_tip_init_silicon - * Desc: initiate silicon parameters - * Args: - * Notes: - * Returns: required value - */ -int ddr3_silicon_init(void) -{ - int status; - static int init_done; - - if (init_done == 1) - return MV_OK; - - status = ddr3_tip_init_a38x(0, 0); - if (MV_OK != status) { - printf("DDR3 A38x silicon init - FAILED 0x%x\n", status); - return status; - } - - init_done = 1; - - return MV_OK; -} diff --git a/drivers/ddr/marvell/a38x/ddr3_debug.c b/drivers/ddr/marvell/a38x/ddr3_debug.c index c14400840e..1eac0bcd2b 100644 --- a/drivers/ddr/marvell/a38x/ddr3_debug.c +++ b/drivers/ddr/marvell/a38x/ddr3_debug.c @@ -3,13 +3,6 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include -#include - #include "ddr3_init.h" u8 is_reg_dump = 0; @@ -18,7 +11,12 @@ u8 debug_pbs = DEBUG_LEVEL_ERROR; /* * API to change flags outside of the lib */ -#ifndef SILENT_LIB +#if defined(SILENT_LIB) +void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) +{ + /* do nothing */ +} +#else /* SILENT_LIB */ /* Debug flags for other Training modules */ u8 debug_training_static = DEBUG_LEVEL_ERROR; u8 debug_training = DEBUG_LEVEL_ERROR; @@ -28,7 +26,14 @@ u8 debug_training_ip = DEBUG_LEVEL_ERROR; u8 debug_training_bist = DEBUG_LEVEL_ERROR; u8 debug_training_hw_alg = DEBUG_LEVEL_ERROR; u8 debug_training_access = DEBUG_LEVEL_ERROR; -u8 debug_training_a38x = DEBUG_LEVEL_ERROR; +u8 debug_training_device = DEBUG_LEVEL_ERROR; + + +void mv_ddr_user_log_level_set(enum ddr_lib_debug_block block) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + ddr3_hws_set_log_level(block, tm->debug_level); +}; void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) { @@ -52,7 +57,7 @@ void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) debug_training_hw_alg = level; break; case DEBUG_BLOCK_DEVICE: - debug_training_a38x = level; + debug_training_device = level; break; case DEBUG_BLOCK_ACCESS: debug_training_access = level; @@ -72,24 +77,31 @@ void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) debug_pbs = level; debug_training_hw_alg = level; debug_training_access = level; - debug_training_a38x = level; + debug_training_device = level; } } -#else -void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level) -{ - return; -} -#endif +#endif /* SILENT_LIB */ -struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM]; +#if defined(DDR_VIEWER_TOOL) +static char *convert_freq(enum hws_ddr_freq freq); +#if defined(EXCLUDE_SWITCH_DEBUG) +u32 ctrl_sweepres[ADLL_LENGTH][MAX_INTERFACE_NUM][MAX_BUS_NUM]; +u32 ctrl_adll[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM]; +u32 ctrl_adll1[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM]; +u32 ctrl_level_phase[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM]; +#endif /* EXCLUDE_SWITCH_DEBUG */ +#endif /* DDR_VIEWER_TOOL */ + +struct hws_tip_config_func_db config_func_info[MAX_DEVICE_NUM]; u8 is_default_centralization = 0; u8 is_tune_result = 0; u8 is_validate_window_per_if = 0; u8 is_validate_window_per_pup = 0; u8 sweep_cnt = 1; u32 is_bist_reset_bit = 1; -static struct hws_xsb_info xsb_info[HWS_MAX_DEVICE_NUM]; +u8 is_run_leveling_sweep_tests; + +static struct hws_xsb_info xsb_info[MAX_DEVICE_NUM]; /* * Dump Dunit & Phy registers @@ -98,13 +110,14 @@ int ddr3_tip_reg_dump(u32 dev_num) { u32 if_id, reg_addr, data_value, bus_id; u32 read_data[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); printf("-- dunit registers --\n"); for (reg_addr = 0x1400; reg_addr < 0x19f0; reg_addr += 4) { printf("0x%x ", reg_addr); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, reg_addr, read_data, @@ -118,11 +131,11 @@ int ddr3_tip_reg_dump(u32 dev_num) for (reg_addr = 0; reg_addr <= 0xff; reg_addr++) { printf("0x%x ", reg_addr); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_id = 0; - bus_id < tm->num_of_bus_per_interface; + bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, @@ -131,9 +144,9 @@ int ddr3_tip_reg_dump(u32 dev_num) printf("0x%x ", data_value); } for (bus_id = 0; - bus_id < tm->num_of_bus_per_interface; + bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, @@ -163,6 +176,23 @@ int ddr3_tip_init_config_func(u32 dev_num, return MV_OK; } +/* + * Read training result table + */ +int hws_ddr3_tip_read_training_result( + u32 dev_num, enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]) +{ + if (result == NULL) + return MV_BAD_PARAM; + + memcpy(result, training_result, + sizeof(enum hws_result) * + MAX_STAGE_LIMIT * + MAX_INTERFACE_NUM); + + return MV_OK; +} + /* * Get training result info pointer */ @@ -184,7 +214,7 @@ int ddr3_tip_get_device_info(u32 dev_num, struct ddr3_device_info *info_ptr) return MV_FAIL; } -#ifndef EXCLUDE_SWITCH_DEBUG +#if defined(DDR_VIEWER_TOOL) /* * Convert freq to character string */ @@ -193,11 +223,13 @@ static char *convert_freq(enum hws_ddr_freq freq) switch (freq) { case DDR_FREQ_LOW_FREQ: return "DDR_FREQ_LOW_FREQ"; + case DDR_FREQ_400: return "400"; case DDR_FREQ_533: return "533"; + case DDR_FREQ_667: return "667"; @@ -209,6 +241,7 @@ static char *convert_freq(enum hws_ddr_freq freq) case DDR_FREQ_1066: return "1066"; + case DDR_FREQ_311: return "311"; @@ -229,6 +262,7 @@ static char *convert_freq(enum hws_ddr_freq freq) case DDR_FREQ_1000: return "DDR_FREQ_1000"; + default: return "Unknown Frequency"; } @@ -279,7 +313,7 @@ static char *convert_mem_size(u32 dev_id) int print_device_info(u8 dev_num) { struct ddr3_device_info info_ptr; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); CHECK_STATUS(ddr3_tip_get_device_info(dev_num, &info_ptr)); printf("=== DDR setup START===\n"); @@ -302,7 +336,7 @@ void hws_ddr3_tip_sweep_test(int enable) is_validate_window_per_pup = 0; } } -#endif +#endif /* DDR_VIEWER_TOOL */ char *ddr3_tip_convert_tune_result(enum hws_result tune_result) { @@ -324,9 +358,9 @@ char *ddr3_tip_convert_tune_result(enum hws_result tune_result) int ddr3_tip_print_log(u32 dev_num, u32 mem_addr) { u32 if_id = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); -#ifndef EXCLUDE_SWITCH_DEBUG +#if defined(DDR_VIEWER_TOOL) if ((is_validate_window_per_if != 0) || (is_validate_window_per_pup != 0)) { u32 is_pup_log = 0; @@ -340,16 +374,22 @@ int ddr3_tip_print_log(u32 dev_num, u32 mem_addr) /* print sweep windows */ ddr3_tip_run_sweep_test(dev_num, sweep_cnt, 1, is_pup_log); ddr3_tip_run_sweep_test(dev_num, sweep_cnt, 0, is_pup_log); +#if defined(EXCLUDE_SWITCH_DEBUG) + if (is_run_leveling_sweep_tests == 1) { + ddr3_tip_run_leveling_sweep_test(dev_num, sweep_cnt, 0, is_pup_log); + ddr3_tip_run_leveling_sweep_test(dev_num, sweep_cnt, 1, is_pup_log); + } +#endif /* EXCLUDE_SWITCH_DEBUG */ ddr3_tip_print_all_pbs_result(dev_num); ddr3_tip_print_wl_supp_result(dev_num); printf("===VALIDATE WINDOW LOG END ===\n"); CHECK_STATUS(ddr3_tip_restore_dunit_regs(dev_num)); ddr3_tip_reg_dump(dev_num); } -#endif +#endif /* DDR_VIEWER_TOOL */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("IF %d Status:\n", if_id)); @@ -479,6 +519,7 @@ int ddr3_tip_print_log(u32 dev_num, u32 mem_addr) return MV_OK; } +#if !defined(EXCLUDE_DEBUG_PRINTS) /* * Print stability log info */ @@ -487,17 +528,17 @@ int ddr3_tip_print_stability_log(u32 dev_num) u8 if_id = 0, csindex = 0, bus_id = 0, idx = 0; u32 reg_data; u32 read_data[MAX_INTERFACE_NUM]; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* Title print */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); printf("Title: I/F# , Tj, Calibration_n0, Calibration_p0, Calibration_n1, Calibration_p1, Calibration_n2, Calibration_p2,"); for (csindex = 0; csindex < max_cs; csindex++) { printf("CS%d , ", csindex); printf("\n"); - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); printf("VWTx, VWRx, WL_tot, WL_ADLL, WL_PH, RL_Tot, RL_ADLL, RL_PH, RL_Smp, Cen_tx, Cen_rx, Vref, DQVref,"); printf("\t\t"); for (idx = 0; idx < 11; idx++) @@ -511,7 +552,7 @@ int ddr3_tip_print_stability_log(u32 dev_num) /* Data print */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); printf("Data: %d,%d,", if_id, (config_func_info[dev_num].tip_get_temperature != NULL) @@ -538,11 +579,11 @@ int ddr3_tip_print_stability_log(u32 dev_num) printf("CS%d , ", csindex); for (bus_id = 0; bus_id < MAX_BUS_NUM; bus_id++) { printf("\n"); - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - RESULT_DB_PHY_REG_ADDR + + RESULT_PHY_REG + csindex, ®_data); printf("%d,%d,", (reg_data & 0x1f), ((reg_data & 0x3e0) >> 5)); @@ -550,8 +591,8 @@ int ddr3_tip_print_stability_log(u32 dev_num) ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WL_PHY_REG + - csindex * 4, ®_data); + WL_PHY_REG(csindex), + ®_data); printf("%d,%d,%d,", (reg_data & 0x1f) + ((reg_data & 0x1c0) >> 6) * 32, @@ -561,16 +602,16 @@ int ddr3_tip_print_stability_log(u32 dev_num) CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_SAMPLE_DELAY, + RD_DATA_SMPL_DLYS_REG, read_data, MASK_ALL_BITS)); read_data[if_id] = (read_data[if_id] & - (0xf << (4 * csindex))) >> - (4 * csindex); + (0x1f << (8 * csindex))) >> + (8 * csindex); ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - RL_PHY_REG + csindex * 4, + RL_PHY_REG(csindex), ®_data); printf("%d,%d,%d,%d,", (reg_data & 0x1f) + @@ -583,36 +624,26 @@ int ddr3_tip_print_stability_log(u32 dev_num) ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG - + csindex * 4, ®_data); + CTX_PHY_REG(csindex), + ®_data); printf("%d,", (reg_data & 0x3f)); ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG - + csindex * 4, ®_data); + CRX_PHY_REG(csindex), + ®_data); printf("%d,", (reg_data & 0x1f)); /* Vref */ ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - PAD_CONFIG_PHY_REG, + PAD_CFG_PHY_REG, ®_data); printf("%d,", (reg_data & 0x7)); /* DQVref */ /* Need to add the Read Function from device */ printf("%d,", 0); printf("\t\t"); - for (idx = 0; idx < 11; idx++) { - ddr3_tip_bus_read(dev_num, if_id, - ACCESS_TYPE_UNICAST, - bus_id, DDR_PHY_DATA, - 0xd0 + - 12 * csindex + - idx, ®_data); - printf("%d,", (reg_data & 0x3f)); - } - printf("\t\t"); for (idx = 0; idx < 11; idx++) { ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, @@ -639,6 +670,7 @@ int ddr3_tip_print_stability_log(u32 dev_num) return MV_OK; } +#endif /* EXCLUDE_DEBUG_PRINTS */ /* * Register XSB information @@ -652,30 +684,30 @@ int ddr3_tip_register_xsb_info(u32 dev_num, struct hws_xsb_info *xsb_info_table) /* * Read ADLL Value */ -int read_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr, u32 mask) +int ddr3_tip_read_adll_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 reg_addr, u32 mask) { u32 data_value; u32 if_id = 0, bus_id = 0; - u32 dev_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * multi CS support - reg_addr is calucalated in calling function * with CS offset */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, reg_addr, &data_value)); pup_values[if_id * - tm->num_of_bus_per_interface + bus_id] = + octets_per_if_num + bus_id] = data_value & mask; } } @@ -686,24 +718,25 @@ int read_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], /* * Write ADLL Value */ -int write_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr) +int ddr3_tip_write_adll_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 reg_addr) { u32 if_id = 0, bus_id = 0; - u32 dev_num = 0, data; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 data; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * multi CS support - reg_addr is calucalated in calling function * with CS offset */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); data = pup_values[if_id * - tm->num_of_bus_per_interface + + octets_per_if_num + bus_id]; CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, @@ -717,23 +750,78 @@ int write_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], return 0; } -#ifndef EXCLUDE_SWITCH_DEBUG -u32 rl_version = 1; /* 0 - old RL machine */ -struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM]; +/** + * Read Phase Value + */ +int read_phase_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + int reg_addr, u32 mask) +{ + u32 data_value; + u32 if_id = 0, bus_id = 0; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* multi CS support - reg_addr is calucalated in calling function with CS offset */ + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); + CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id, + ACCESS_TYPE_UNICAST, + bus_id, + DDR_PHY_DATA, reg_addr, + &data_value)); + pup_values[if_id * octets_per_if_num + bus_id] = data_value & mask; + } + } + + return 0; +} + +/** + * Write Leveling Value + */ +int write_leveling_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 pup_ph_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], int reg_addr) +{ + u32 if_id = 0, bus_id = 0; + u32 data; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* multi CS support - reg_addr is calucalated in calling function with CS offset */ + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0 ; bus_id < octets_per_if_num ; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); + data = pup_values[if_id * octets_per_if_num + bus_id] + + pup_ph_values[if_id * octets_per_if_num + bus_id]; + CHECK_STATUS(ddr3_tip_bus_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + ACCESS_TYPE_UNICAST, + bus_id, + DDR_PHY_DATA, + reg_addr, + data)); + } + } + + return 0; +} + +#if !defined(EXCLUDE_SWITCH_DEBUG) +struct hws_tip_config_func_db config_func_info[MAX_DEVICE_NUM]; u32 start_xsb_offset = 0; u8 is_rl_old = 0; u8 is_freq_old = 0; u8 is_dfs_disabled = 0; u32 default_centrlization_value = 0x12; -u32 vref = 0x4; u32 activate_select_before_run_alg = 1, activate_deselect_after_run_alg = 1, rl_test = 0, reset_read_fifo = 0; int debug_acc = 0; u32 ctrl_sweepres[ADLL_LENGTH][MAX_INTERFACE_NUM][MAX_BUS_NUM]; u32 ctrl_adll[MAX_CS_NUM * MAX_INTERFACE_NUM * MAX_BUS_NUM]; -u8 cs_mask_reg[] = { - 0, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; u32 xsb_test_table[][8] = { {0x00000000, 0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555, @@ -761,13 +849,14 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr); int ddr3_tip_print_adll(void) { u32 bus_cnt = 0, if_id, data_p1, data_p2, ui_data3, dev_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, @@ -815,7 +904,7 @@ int ddr3_tip_set_atr(u32 dev_num, u32 flag_id, u32 value) static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) { u32 tmp_val = 0, if_id = 0, pup_id = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); *ptr = NULL; @@ -829,21 +918,17 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x2: - *ptr = (u32 *)&low_freq; + low_freq = (enum hws_ddr_freq)value; break; case 0x3: - *ptr = (u32 *)&medium_freq; + medium_freq = (enum hws_ddr_freq)value; break; case 0x4: *ptr = (u32 *)&generic_init_controller; break; - case 0x5: - *ptr = (u32 *)&rl_version; - break; - case 0x8: *ptr = (u32 *)&start_xsb_offset; break; @@ -892,15 +977,14 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x33: - *ptr = (u32 *)&p_finger; + *ptr = (u32 *)&g_zpodt_data; break; case 0x34: - *ptr = (u32 *)&n_finger; + *ptr = (u32 *)&g_znodt_data; break; case 0x35: - *ptr = (u32 *)&init_freq; break; case 0x36: @@ -932,19 +1016,15 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x4e: - *ptr = (u32 *)&sweep_pattern; - break; - - case 0x50: - *ptr = (u32 *)&is_rzq6; + sweep_pattern = (enum hws_pattern)value; break; case 0x51: - *ptr = (u32 *)&znri_data_phy_val; + *ptr = (u32 *)&g_znri_data; break; case 0x52: - *ptr = (u32 *)&zpri_data_phy_val; + *ptr = (u32 *)&g_zpri_data; break; case 0x53: @@ -976,11 +1056,11 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x5a: - *ptr = (u32 *)&znri_ctrl_phy_val; + *ptr = (u32 *)&g_znri_ctrl; break; case 0x5b: - *ptr = (u32 *)&zpri_ctrl_phy_val; + *ptr = (u32 *)&g_zpri_ctrl; break; case 0x5c: @@ -988,11 +1068,11 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x5d: - *ptr = (u32 *)&vref; + *ptr = (u32 *)&vref_init_val; break; case 0x5e: - *ptr = (u32 *)&mode2_t; + *ptr = (u32 *)&mode_2t; break; case 0x5f: @@ -1020,7 +1100,7 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) break; case 0x71: - *ptr = (u32 *)&pbs_pattern; + pbs_pattern = (enum hws_pattern)value; break; case 0x72: @@ -1031,10 +1111,6 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) *ptr = (u32 *)&ck_delay; break; - case 0x74: - *ptr = (u32 *)&ck_delay_16; - break; - case 0x75: *ptr = (u32 *)&ca_delay; break; @@ -1079,6 +1155,7 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) debug_training_access = (u8)value; break; + case 0x112: *ptr = &start_pattern; break; @@ -1147,28 +1224,46 @@ static int ddr3_tip_access_atr(u32 dev_num, u32 flag_id, u32 value, u32 **ptr) return MV_OK; } -#ifndef EXCLUDE_SWITCH_DEBUG +#endif /* EXCLUDE_SWITCH_DEBUG */ + +#if defined(DDR_VIEWER_TOOL) /* * Print ADLL */ int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]) { u32 i, j; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - for (j = 0; j < tm->num_of_bus_per_interface; j++) { - VALIDATE_ACTIVE(tm->bus_act_mask, j); - for (i = 0; i < MAX_INTERFACE_NUM; i++) { - printf("%d ,", - adll[i * tm->num_of_bus_per_interface + j]); - } + for (j = 0; j < octets_per_if_num; j++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, j); + for (i = 0; i < MAX_INTERFACE_NUM; i++) + printf("%d ,", adll[i * octets_per_if_num + j]); } printf("\n"); return MV_OK; } -#endif +int print_ph(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]) +{ + u32 i, j; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + for (j = 0; j < octets_per_if_num; j++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, j); + for (i = 0; i < MAX_INTERFACE_NUM; i++) + printf("%d ,", adll[i * octets_per_if_num + j] >> 6); + } + printf("\n"); + + return MV_OK; +} +#endif /* DDR_VIEWER_TOOL */ + +#if !defined(EXCLUDE_SWITCH_DEBUG) /* byte_index - only byte 0, 1, 2, or 3, oxff - test all bytes */ static u32 ddr3_tip_compare(u32 if_id, u32 *p_src, u32 *p_dst, u32 byte_index) @@ -1181,7 +1276,7 @@ static u32 ddr3_tip_compare(u32 if_id, u32 *p_src, u32 *p_dst, 0xff) ? (u32) 0xffffffff : (u32) (0xff << (byte_index * 8)); for (burst_cnt = 0; burst_cnt < EXT_ACCESS_BURST_LENGTH; burst_cnt++) { if ((p_src[burst_cnt] & addr_offset) != - (p_dst[burst_cnt] & addr_offset)) + (p_dst[if_id] & addr_offset)) b_is_fail = 1; } @@ -1203,69 +1298,9 @@ static u32 ddr3_tip_compare(u32 if_id, u32 *p_src, u32 *p_dst, return b_is_fail; } +#endif /* EXCLUDE_SWITCH_DEBUG */ -/* test_type = 0-tx , 1-rx */ -int ddr3_tip_sweep_test(u32 dev_num, u32 test_type, - u32 mem_addr, u32 is_modify_adll, - u32 start_if, u32 end_if, u32 startpup, u32 endpup) -{ - u32 bus_cnt = 0, adll_val = 0, if_id, ui_prev_adll, ui_mask_bit, - end_adll, start_adll; - u32 reg_addr = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (test_type == 0) { - reg_addr = 1; - ui_mask_bit = 0x3f; - start_adll = 0; - end_adll = ui_mask_bit; - } else { - reg_addr = 3; - ui_mask_bit = 0x1f; - start_adll = 0; - end_adll = ui_mask_bit; - } - - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, - ("==============================\n")); - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, - ("Test type %d (0-tx, 1-rx)\n", test_type)); - - for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_cnt = startpup; bus_cnt < endpup; bus_cnt++) { - CHECK_STATUS(ddr3_tip_bus_read - (dev_num, if_id, ACCESS_TYPE_UNICAST, - bus_cnt, DDR_PHY_DATA, reg_addr, - &ui_prev_adll)); - - for (adll_val = start_adll; adll_val <= end_adll; - adll_val++) { - if (is_modify_adll == 1) { - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, - ACCESS_TYPE_UNICAST, - if_id, bus_cnt, - DDR_PHY_DATA, reg_addr, - adll_val, ui_mask_bit)); - } - } - if (is_modify_adll == 1) { - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, ACCESS_TYPE_UNICAST, - bus_cnt, DDR_PHY_DATA, reg_addr, - ui_prev_adll)); - } - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("\n")); - } - DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("\n")); - } - - return MV_OK; -} - -#ifndef EXCLUDE_SWITCH_DEBUG +#if defined(DDR_VIEWER_TOOL) /* * Sweep validation */ @@ -1273,21 +1308,23 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, u32 mode) { u32 pup = 0, start_pup = 0, end_pup = 0; - u32 adll = 0; + u32 adll = 0, rep = 0, pattern_idx = 0; u32 res[MAX_INTERFACE_NUM] = { 0 }; int if_id = 0; u32 adll_value = 0; - int reg = (direction == 0) ? WRITE_CENTRALIZATION_PHY_REG : - READ_CENTRALIZATION_PHY_REG; + u32 reg; enum hws_access_type pup_access; u32 cs; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + repeat_num = 2; if (mode == 1) { /* per pup */ start_pup = 0; - end_pup = tm->num_of_bus_per_interface - 1; + end_pup = octets_per_if_num - 1; pup_access = ACCESS_TYPE_UNICAST; } else { start_pup = 0; @@ -1296,11 +1333,12 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, } for (cs = 0; cs < max_cs; cs++) { + reg = (direction == 0) ? CTX_PHY_REG(cs) : CRX_PHY_REG(cs); for (adll = 0; adll < ADLL_LENGTH; adll++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE + VALIDATE_IF_ACTIVE (tm->if_act_mask, if_id); for (pup = start_pup; pup <= end_pup; pup++) { @@ -1312,10 +1350,9 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, for (adll = 0; adll < (MAX_INTERFACE_NUM * MAX_BUS_NUM); adll++) ctrl_adll[adll] = 0; - /* Save DQS value(after algorithm run) */ - read_adll_value(ctrl_adll, - (reg + (cs * CS_REGISTER_ADDR_OFFSET)), - MASK_ALL_BITS); + /* Save DQS value(after algorithm run) */ + ddr3_tip_read_adll_value(dev_num, ctrl_adll, + reg, MASK_ALL_BITS); /* * Sweep ADLL from 0:31 on all I/F on all Pup and perform @@ -1323,38 +1360,43 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, */ for (pup = start_pup; pup <= end_pup; pup++) { for (adll = 0; adll < ADLL_LENGTH; adll++) { - adll_value = - (direction == 0) ? (adll * 2) : adll; - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, 0, - pup_access, pup, DDR_PHY_DATA, - reg + CS_REG_VALUE(cs), - adll_value)); - hws_ddr3_run_bist(dev_num, sweep_pattern, res, - cs); - /* ddr3_tip_reset_fifo_ptr(dev_num); */ - for (if_id = 0; - if_id <= MAX_INTERFACE_NUM - 1; - if_id++) { - VALIDATE_ACTIVE - (tm->if_act_mask, - if_id); - ctrl_sweepres[adll][if_id][pup] - = res[if_id]; - if (mode == 1) { - CHECK_STATUS - (ddr3_tip_bus_write - (dev_num, - ACCESS_TYPE_UNICAST, - if_id, - ACCESS_TYPE_UNICAST, - pup, - DDR_PHY_DATA, - reg + CS_REG_VALUE(cs), - ctrl_adll[if_id * - cs * - tm->num_of_bus_per_interface - + pup])); + for (rep = 0; rep < repeat_num; rep++) { + for (pattern_idx = PATTERN_KILLER_DQ0; + pattern_idx < PATTERN_LAST; + pattern_idx++) { + adll_value = + (direction == 0) ? (adll * 2) : adll; + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, 0, + pup_access, pup, DDR_PHY_DATA, + reg, adll_value)); + hws_ddr3_run_bist(dev_num, sweep_pattern, res, + cs); + /* ddr3_tip_reset_fifo_ptr(dev_num); */ + for (if_id = 0; + if_id < MAX_INTERFACE_NUM; + if_id++) { + VALIDATE_IF_ACTIVE + (tm->if_act_mask, + if_id); + ctrl_sweepres[adll][if_id][pup] + += res[if_id]; + if (mode == 1) { + CHECK_STATUS + (ddr3_tip_bus_write + (dev_num, + ACCESS_TYPE_UNICAST, + if_id, + ACCESS_TYPE_UNICAST, + pup, + DDR_PHY_DATA, + reg, + ctrl_adll[if_id * + cs * + octets_per_if_num + + pup])); + } + } } } } @@ -1362,10 +1404,10 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, printf("Final, CS %d,%s, Sweep, Result, Adll,", cs, ((direction == 0) ? "TX" : "RX")); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (mode == 1) { for (pup = start_pup; pup <= end_pup; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); printf("I/F%d-PHY%d , ", if_id, pup); } } else { @@ -1382,9 +1424,9 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup = start_pup; pup <= end_pup; pup++) { - printf("%d , ", + printf("%8d , ", ctrl_sweepres[adll][if_id] [pup]); } @@ -1396,11 +1438,9 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, * Write back to the phy the Rx DQS value, we store in * the beginning. */ - write_adll_value(ctrl_adll, - (reg + cs * CS_REGISTER_ADDR_OFFSET)); + ddr3_tip_write_adll_value(dev_num, ctrl_adll, reg); /* print adll results */ - read_adll_value(ctrl_adll, (reg + cs * CS_REGISTER_ADDR_OFFSET), - MASK_ALL_BITS); + ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, MASK_ALL_BITS); printf("%s, DQS, ADLL,,,", (direction == 0) ? "Tx" : "Rx"); print_adll(dev_num, ctrl_adll); } @@ -1409,16 +1449,214 @@ int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, return 0; } -void print_topology(struct hws_topology_map *topology_db) +#if defined(EXCLUDE_SWITCH_DEBUG) +int ddr3_tip_run_leveling_sweep_test(int dev_num, u32 repeat_num, + u32 direction, u32 mode) +{ + u32 pup = 0, start_pup = 0, end_pup = 0, start_adll = 0; + u32 adll = 0, rep = 0, pattern_idx = 0; + u32 read_data[MAX_INTERFACE_NUM]; + u32 res[MAX_INTERFACE_NUM] = { 0 }; + int if_id = 0, gap = 0; + u32 adll_value = 0; + u32 reg; + enum hws_access_type pup_access; + u32 cs; + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + if (mode == 1) { /* per pup */ + start_pup = 0; + end_pup = octets_per_if_num - 1; + pup_access = ACCESS_TYPE_UNICAST; + } else { + start_pup = 0; + end_pup = 0; + pup_access = ACCESS_TYPE_MULTICAST; + } + + for (cs = 0; cs < max_cs; cs++) { + reg = (direction == 0) ? WL_PHY_REG(cs) : RL_PHY_REG(cs); + for (adll = 0; adll < ADLL_LENGTH; adll++) { + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = start_pup; pup <= end_pup; pup++) + ctrl_sweepres[adll][if_id][pup] = 0; + } + } + + for (adll = 0; adll < MAX_INTERFACE_NUM * MAX_BUS_NUM; adll++) { + ctrl_adll[adll] = 0; + ctrl_level_phase[adll] = 0; + ctrl_adll1[adll] = 0; + } + + /* save leveling value after running algorithm */ + ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, 0x1f); + read_phase_value(dev_num, ctrl_level_phase, reg, 0x7 << 6); + + if (direction == 0) + ddr3_tip_read_adll_value(dev_num, ctrl_adll1, + CTX_PHY_REG(cs), MASK_ALL_BITS); + + /* Sweep ADLL from 0 to 31 on all interfaces, all pups, + * and perform BIST on each stage + */ + for (pup = start_pup; pup <= end_pup; pup++) { + for (adll = 0; adll < ADLL_LENGTH; adll++) { + for (rep = 0; rep < repeat_num; rep++) { + adll_value = (direction == 0) ? (adll * 2) : (adll * 3); + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + start_adll = ctrl_adll[if_id * cs * octets_per_if_num + pup] + + (ctrl_level_phase[if_id * cs * + octets_per_if_num + + pup] >> 6) * 32; + + if (direction == 0) + start_adll = (start_adll > 32) ? (start_adll - 32) : 0; + else + start_adll = (start_adll > 48) ? (start_adll - 48) : 0; + + adll_value += start_adll; + + gap = ctrl_adll1[if_id * cs * octets_per_if_num + pup] - + ctrl_adll[if_id * cs * octets_per_if_num + pup]; + gap = (((adll_value % 32) + gap) % 64); + + adll_value = ((adll_value % 32) + + (((adll_value - (adll_value % 32)) / 32) << 6)); + + CHECK_STATUS(ddr3_tip_bus_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + pup_access, + pup, + DDR_PHY_DATA, + reg, + adll_value)); + if (direction == 0) + CHECK_STATUS(ddr3_tip_bus_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + pup_access, + pup, + DDR_PHY_DATA, + CTX_PHY_REG(cs), + gap)); + } + + for (pattern_idx = PATTERN_KILLER_DQ0; + pattern_idx < PATTERN_LAST; + pattern_idx++) { + hws_ddr3_run_bist(dev_num, sweep_pattern, res, cs); + ddr3_tip_reset_fifo_ptr(dev_num); + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + if (pup != 4) { /* TODO: remove literal */ + ctrl_sweepres[adll][if_id][pup] += res[if_id]; + } else { + CHECK_STATUS(ddr3_tip_if_read(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + 0x1458, + read_data, + MASK_ALL_BITS)); + ctrl_sweepres[adll][if_id][pup] += read_data[if_id]; + CHECK_STATUS(ddr3_tip_if_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + 0x1458, + 0x0, + 0xFFFFFFFF)); + CHECK_STATUS(ddr3_tip_if_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + 0x145C, + 0x0, + 0xFFFFFFFF)); + } + } + } + } + } + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + start_adll = ctrl_adll[if_id * cs * octets_per_if_num + pup] + + ctrl_level_phase[if_id * cs * octets_per_if_num + pup]; + CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, pup_access, pup, + DDR_PHY_DATA, reg, start_adll)); + if (direction == 0) + CHECK_STATUS(ddr3_tip_bus_write(dev_num, + ACCESS_TYPE_UNICAST, + if_id, + pup_access, + pup, + DDR_PHY_DATA, + CTX_PHY_REG(cs), + ctrl_adll1[if_id * + cs * + octets_per_if_num + + pup])); + } + } + + printf("Final,CS %d,%s,Leveling,Result,Adll,", cs, ((direction == 0) ? "TX" : "RX")); + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + if (mode == 1) { + for (pup = start_pup; pup <= end_pup; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); + printf("I/F%d-PHY%d , ", if_id, pup); + } + } else { + printf("I/F%d , ", if_id); + } + } + printf("\n"); + + for (adll = 0; adll < ADLL_LENGTH; adll++) { + adll_value = (direction == 0) ? ((adll * 2) - 32) : ((adll * 3) - 48); + printf("Final,%s,LevelingSweep,Result, %d ,", ((direction == 0) ? "TX" : "RX"), adll_value); + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = start_pup; pup <= end_pup; pup++) + printf("%8d , ", ctrl_sweepres[adll][if_id][pup]); + } + printf("\n"); + } + + /* write back to the phy the Rx DQS value, we store in the beginning */ + write_leveling_value(dev_num, ctrl_adll, ctrl_level_phase, reg); + if (direction == 0) + ddr3_tip_write_adll_value(dev_num, ctrl_adll1, CTX_PHY_REG(cs)); + + /* print adll results */ + ddr3_tip_read_adll_value(dev_num, ctrl_adll, reg, MASK_ALL_BITS); + printf("%s,DQS,Leveling,,,", (direction == 0) ? "Tx" : "Rx"); + print_adll(dev_num, ctrl_adll); + print_ph(dev_num, ctrl_level_phase); + } + ddr3_tip_reset_fifo_ptr(dev_num); + + return 0; +} +#endif /* EXCLUDE_SWITCH_DEBUG */ + +void print_topology(struct mv_ddr_topology_map *topology_db) { u32 ui, uj; + u32 dev_num = 0; printf("\tinterface_mask: 0x%x\n", topology_db->if_act_mask); - printf("\tNum Bus: %d\n", topology_db->num_of_bus_per_interface); + printf("\tNumber of buses: 0x%x\n", + ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE)); printf("\tbus_act_mask: 0x%x\n", topology_db->bus_act_mask); for (ui = 0; ui < MAX_INTERFACE_NUM; ui++) { - VALIDATE_ACTIVE(topology_db->if_act_mask, ui); + VALIDATE_IF_ACTIVE(topology_db->if_act_mask, ui); printf("\n\tInterface ID: %d\n", ui); printf("\t\tDDR Frequency: %s\n", convert_freq(topology_db-> @@ -1456,8 +1694,9 @@ void print_topology(struct hws_topology_map *topology_db) } } } -#endif +#endif /* DDR_VIEWER_TOOL */ +#if !defined(EXCLUDE_SWITCH_DEBUG) /* * Execute XSB Test transaction (rd/wr/both) */ @@ -1467,10 +1706,10 @@ int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, u32 seq = 0, if_id = 0, addr, cnt; int ret = MV_OK, ret_tmp; u32 data_read[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); addr = mem_addr; for (cnt = 0; cnt <= burst_length; cnt++) { seq = (seq + 1) % 8; @@ -1500,13 +1739,7 @@ int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, } #else /*EXCLUDE_SWITCH_DEBUG */ - -u32 rl_version = 1; /* 0 - old RL machine */ -u32 vref = 0x4; u32 start_xsb_offset = 0; -u8 cs_mask_reg[] = { - 0, 4, 8, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, u32 read_type, u32 burst_length) @@ -1514,4 +1747,4 @@ int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, return MV_OK; } -#endif +#endif /* EXCLUDE_SWITCH_DEBUG */ diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c b/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c deleted file mode 100644 index 114d91e303..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.c +++ /dev/null @@ -1,147 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#include -#include -#include -#include -#include -#include - -#include "ddr3_init.h" - -#define REG_READ_DATA_SAMPLE_DELAYS_ADDR 0x1538 -#define REG_READ_DATA_SAMPLE_DELAYS_MASK 0x1f -#define REG_READ_DATA_SAMPLE_DELAYS_OFFS 8 - -#define REG_READ_DATA_READY_DELAYS_ADDR 0x153c -#define REG_READ_DATA_READY_DELAYS_MASK 0x1f -#define REG_READ_DATA_READY_DELAYS_OFFS 8 - -int ddr3_if_ecc_enabled(void) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask) || - DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) - return 1; - else - return 0; -} - -int ddr3_pre_algo_config(void) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* Set Bus3 ECC training mode */ - if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) { - /* Set Bus3 ECC MUX */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - REG_SDRAM_PINS_MUX, 0x100, 0x100)); - } - - /* Set regular ECC training mode (bus4 and bus 3) */ - if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) || - (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))) { - /* Enable ECC Write MUX */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - TRAINING_SW_2_REG, 0x100, 0x100)); - /* General ECC enable */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - REG_SDRAM_CONFIG_ADDR, 0x40000, 0x40000)); - /* Disable Read Data ECC MUX */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - TRAINING_SW_2_REG, 0x0, 0x2)); - } - - return MV_OK; -} - -int ddr3_post_algo_config(void) -{ - struct hws_topology_map *tm = ddr3_get_topology_map(); - int status; - - status = ddr3_post_run_alg(); - if (MV_OK != status) { - printf("DDR3 Post Run Alg - FAILED 0x%x\n", status); - return status; - } - - /* Un_set ECC training mode */ - if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) || - (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))) { - /* Disable ECC Write MUX */ - CHECK_STATUS(ddr3_tip_if_write - (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, - TRAINING_SW_2_REG, 0x0, 0x100)); - /* General ECC and Bus3 ECC MUX remains enabled */ - } - - return MV_OK; -} - -int ddr3_hws_hw_training(void) -{ - enum hws_algo_type algo_mode = ALGO_TYPE_DYNAMIC; - int status; - struct init_cntr_param init_param; - - status = ddr3_silicon_pre_init(); - if (MV_OK != status) { - printf("DDR3 Pre silicon Config - FAILED 0x%x\n", status); - return status; - } - - init_param.do_mrs_phy = 1; -#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) - init_param.is_ctrl64_bit = 0; -#else - init_param.is_ctrl64_bit = 1; -#endif -#if defined(CONFIG_ALLEYCAT3) || defined(CONFIG_ARMADA_38X) || \ - defined(CONFIG_ARMADA_39X) - init_param.init_phy = 1; -#else - init_param.init_phy = 0; -#endif - init_param.msys_init = 1; - status = hws_ddr3_tip_init_controller(0, &init_param); - if (MV_OK != status) { - printf("DDR3 init controller - FAILED 0x%x\n", status); - return status; - } - - status = ddr3_silicon_post_init(); - if (MV_OK != status) { - printf("DDR3 Post Init - FAILED 0x%x\n", status); - return status; - } - - status = ddr3_pre_algo_config(); - if (MV_OK != status) { - printf("DDR3 Pre Algo Config - FAILED 0x%x\n", status); - return status; - } - - /* run algorithm in order to configure the PHY */ - status = hws_ddr3_tip_run_alg(0, algo_mode); - if (MV_OK != status) { - printf("DDR3 run algorithm - FAILED 0x%x\n", status); - return status; - } - - status = ddr3_post_algo_config(); - if (MV_OK != status) { - printf("DDR3 Post Algo Config - FAILED 0x%x\n", status); - return status; - } - - return MV_OK; -} diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h b/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h deleted file mode 100644 index 55bc0d286a..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training.h +++ /dev/null @@ -1,48 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#ifndef _DDR3_HWS_HW_TRAINING_H -#define _DDR3_HWS_HW_TRAINING_H - -/* struct used for DLB configuration array */ -struct dlb_config { - u32 reg_addr; - u32 reg_data; -}; - -/* Topology update structure */ -struct topology_update_info { - int update_ecc; - u8 ecc; - int update_width; - u8 width; - int update_ecc_pup3_mode; - u8 ecc_pup_mode_offset; -}; - -/* Topology update defines */ -#define TOPOLOGY_UPDATE_WIDTH_16BIT 1 -#define TOPOLOGY_UPDATE_WIDTH_32BIT 0 -#define TOPOLOGY_UPDATE_WIDTH_32BIT_MASK 0xf -#define TOPOLOGY_UPDATE_WIDTH_16BIT_MASK 0x3 - -#define TOPOLOGY_UPDATE_ECC_ON 1 -#define TOPOLOGY_UPDATE_ECC_OFF 0 -#define TOPOLOGY_UPDATE_ECC_OFFSET_PUP4 4 -#define TOPOLOGY_UPDATE_ECC_OFFSET_PUP3 3 - -/* - * 1. L2 filter should be set at binary header to 0xd000000, - * to avoid conflict with internal register IO. - * 2. U-Boot modifies internal registers base to 0xf100000, - * and than should update L2 filter accordingly to 0xf000000 (3.75 GB) - */ -/* temporary limit l2 filter to 3GiB (LSP issue) */ -#define L2_FILTER_FOR_MAX_MEMORY_SIZE 0xc0000000 -#define ADDRESS_FILTERING_END_REGISTER 0x8c04 - -#define SUB_VERSION 0 - -#endif /* _DDR3_HWS_HW_TRAINING_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h b/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h deleted file mode 100644 index a87fc404cb..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_hws_hw_training_def.h +++ /dev/null @@ -1,461 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#ifndef _DDR3_HWS_HW_TRAINING_DEF_H -#define _DDR3_HWS_HW_TRAINING_DEF_H - -#define SAR_DDR3_FREQ_MASK 0xfe00000 -#define SAR_CPU_FAB_GET(cpu, fab) (((cpu & 0x7) << 21) | \ - ((fab & 0xf) << 24)) - -#define MAX_CS 4 - -#define MIN_DIMM_ADDR 0x50 -#define FAR_END_DIMM_ADDR 0x50 -#define MAX_DIMM_ADDR 0x60 - -#define SDRAM_CS_SIZE 0xfffffff -#define SDRAM_CS_BASE 0x0 -#define SDRAM_DIMM_SIZE 0x80000000 - -#define CPU_CONFIGURATION_REG(id) (0x21800 + (id * 0x100)) -#define CPU_MRVL_ID_OFFSET 0x10 -#define SAR1_CPU_CORE_MASK 0x38000000 -#define SAR1_CPU_CORE_OFFSET 27 - -#define NEW_FABRIC_TWSI_ADDR 0x4e -#ifdef DB_784MP_GP -#define BUS_WIDTH_ECC_TWSI_ADDR 0x4e -#else -#define BUS_WIDTH_ECC_TWSI_ADDR 0x4f -#endif -#define MV_MAX_DDR3_STATIC_SIZE 50 -#define MV_DDR3_MODES_NUMBER 30 - -#define RESUME_RL_PATTERNS_ADDR 0xfe0000 -#define RESUME_RL_PATTERNS_SIZE 0x100 -#define RESUME_TRAINING_VALUES_ADDR (RESUME_RL_PATTERNS_ADDR + \ - RESUME_RL_PATTERNS_SIZE) -#define RESUME_TRAINING_VALUES_MAX 0xcd0 -#define BOOT_INFO_ADDR (RESUME_RL_PATTERNS_ADDR + 0x1000) -#define CHECKSUM_RESULT_ADDR (BOOT_INFO_ADDR + 0x1000) -#define NUM_OF_REGISTER_ADDR (CHECKSUM_RESULT_ADDR + 4) -#define SUSPEND_MAGIC_WORD 0xdeadb002 -#define REGISTER_LIST_END 0xffffffff - -/* MISC */ -#define INTER_REGS_BASE SOC_REGS_PHY_BASE - -/* DDR */ -#define REG_SDRAM_CONFIG_ADDR 0x1400 -#define REG_SDRAM_CONFIG_MASK 0x9fffffff -#define REG_SDRAM_CONFIG_RFRS_MASK 0x3fff -#define REG_SDRAM_CONFIG_WIDTH_OFFS 15 -#define REG_SDRAM_CONFIG_REGDIMM_OFFS 17 -#define REG_SDRAM_CONFIG_ECC_OFFS 18 -#define REG_SDRAM_CONFIG_IERR_OFFS 19 -#define REG_SDRAM_CONFIG_PUPRSTDIV_OFFS 28 -#define REG_SDRAM_CONFIG_RSTRD_OFFS 30 - -#define REG_SDRAM_PINS_MUX 0x19d4 - -#define REG_DUNIT_CTRL_LOW_ADDR 0x1404 -#define REG_DUNIT_CTRL_LOW_2T_OFFS 3 -#define REG_DUNIT_CTRL_LOW_2T_MASK 0x3 -#define REG_DUNIT_CTRL_LOW_DPDE_OFFS 14 - -#define REG_SDRAM_TIMING_LOW_ADDR 0x1408 -#define REG_SDRAM_TIMING_HIGH_ADDR 0x140c -#define REG_SDRAM_TIMING_H_R2R_OFFS 7 -#define REG_SDRAM_TIMING_H_R2R_MASK 0x3 -#define REG_SDRAM_TIMING_H_R2W_W2R_OFFS 9 -#define REG_SDRAM_TIMING_H_R2W_W2R_MASK 0x3 -#define REG_SDRAM_TIMING_H_W2W_OFFS 11 -#define REG_SDRAM_TIMING_H_W2W_MASK 0x1f -#define REG_SDRAM_TIMING_H_R2R_H_OFFS 19 -#define REG_SDRAM_TIMING_H_R2R_H_MASK 0x7 -#define REG_SDRAM_TIMING_H_R2W_W2R_H_OFFS 22 -#define REG_SDRAM_TIMING_H_R2W_W2R_H_MASK 0x7 - -#define REG_SDRAM_ADDRESS_CTRL_ADDR 0x1410 -#define REG_SDRAM_ADDRESS_SIZE_OFFS 2 -#define REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS 18 -#define REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS 4 - -#define REG_SDRAM_OPEN_PAGES_ADDR 0x1414 -#define REG_SDRAM_OPERATION_CS_OFFS 8 - -#define REG_SDRAM_OPERATION_ADDR 0x1418 -#define REG_SDRAM_OPERATION_CWA_DELAY_SEL_OFFS 24 -#define REG_SDRAM_OPERATION_CWA_DATA_OFFS 20 -#define REG_SDRAM_OPERATION_CWA_DATA_MASK 0xf -#define REG_SDRAM_OPERATION_CWA_RC_OFFS 16 -#define REG_SDRAM_OPERATION_CWA_RC_MASK 0xf -#define REG_SDRAM_OPERATION_CMD_MR0 0xf03 -#define REG_SDRAM_OPERATION_CMD_MR1 0xf04 -#define REG_SDRAM_OPERATION_CMD_MR2 0xf08 -#define REG_SDRAM_OPERATION_CMD_MR3 0xf09 -#define REG_SDRAM_OPERATION_CMD_RFRS 0xf02 -#define REG_SDRAM_OPERATION_CMD_CWA 0xf0e -#define REG_SDRAM_OPERATION_CMD_RFRS_DONE 0xf -#define REG_SDRAM_OPERATION_CMD_MASK 0xf -#define REG_SDRAM_OPERATION_CS_OFFS 8 - -#define REG_OUDDR3_TIMING_ADDR 0x142c - -#define REG_SDRAM_MODE_ADDR 0x141c - -#define REG_SDRAM_EXT_MODE_ADDR 0x1420 - -#define REG_DDR_CONT_HIGH_ADDR 0x1424 - -#define REG_ODT_TIME_LOW_ADDR 0x1428 -#define REG_ODT_ON_CTL_RD_OFFS 12 -#define REG_ODT_OFF_CTL_RD_OFFS 16 -#define REG_SDRAM_ERROR_ADDR 0x1454 -#define REG_SDRAM_AUTO_PWR_SAVE_ADDR 0x1474 -#define REG_ODT_TIME_HIGH_ADDR 0x147c - -#define REG_SDRAM_INIT_CTRL_ADDR 0x1480 -#define REG_SDRAM_INIT_CTRL_OFFS 0 -#define REG_SDRAM_INIT_CKE_ASSERT_OFFS 2 -#define REG_SDRAM_INIT_RESET_DEASSERT_OFFS 3 -#define REG_SDRAM_INIT_RESET_MASK_OFFS 1 - -#define REG_SDRAM_ODT_CTRL_LOW_ADDR 0x1494 - -#define REG_SDRAM_ODT_CTRL_HIGH_ADDR 0x1498 -#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK 0x0 -#define REG_SDRAM_ODT_CTRL_HIGH_OVRD_ENA 0x3 - -#define REG_DUNIT_ODT_CTRL_ADDR 0x149c -#define REG_DUNIT_ODT_CTRL_OVRD_OFFS 8 -#define REG_DUNIT_ODT_CTRL_OVRD_VAL_OFFS 9 - -#define REG_DRAM_FIFO_CTRL_ADDR 0x14a0 - -#define REG_DRAM_AXI_CTRL_ADDR 0x14a8 -#define REG_DRAM_AXI_CTRL_AXIDATABUSWIDTH_OFFS 0 - -#define REG_METAL_MASK_ADDR 0x14b0 -#define REG_METAL_MASK_MASK 0xdfffffff -#define REG_METAL_MASK_RETRY_OFFS 0 - -#define REG_DRAM_ADDR_CTRL_DRIVE_STRENGTH_ADDR 0x14c0 - -#define REG_DRAM_DATA_DQS_DRIVE_STRENGTH_ADDR 0x14c4 -#define REG_DRAM_VER_CAL_MACHINE_CTRL_ADDR 0x14c8 -#define REG_DRAM_MAIN_PADS_CAL_ADDR 0x14cc - -#define REG_DRAM_HOR_CAL_MACHINE_CTRL_ADDR 0x17c8 - -#define REG_CS_SIZE_SCRATCH_ADDR 0x1504 -#define REG_DYNAMIC_POWER_SAVE_ADDR 0x1520 -#define REG_DDR_IO_ADDR 0x1524 -#define REG_DDR_IO_CLK_RATIO_OFFS 15 - -#define REG_DFS_ADDR 0x1528 -#define REG_DFS_DLLNEXTSTATE_OFFS 0 -#define REG_DFS_BLOCK_OFFS 1 -#define REG_DFS_SR_OFFS 2 -#define REG_DFS_ATSR_OFFS 3 -#define REG_DFS_RECONF_OFFS 4 -#define REG_DFS_CL_NEXT_STATE_OFFS 8 -#define REG_DFS_CL_NEXT_STATE_MASK 0xf -#define REG_DFS_CWL_NEXT_STATE_OFFS 12 -#define REG_DFS_CWL_NEXT_STATE_MASK 0x7 - -#define REG_READ_DATA_SAMPLE_DELAYS_ADDR 0x1538 -#define REG_READ_DATA_SAMPLE_DELAYS_MASK 0x1f -#define REG_READ_DATA_SAMPLE_DELAYS_OFFS 8 - -#define REG_READ_DATA_READY_DELAYS_ADDR 0x153c -#define REG_READ_DATA_READY_DELAYS_MASK 0x1f -#define REG_READ_DATA_READY_DELAYS_OFFS 8 - -#define START_BURST_IN_ADDR 1 - -#define REG_DRAM_TRAINING_SHADOW_ADDR 0x18488 -#define REG_DRAM_TRAINING_ADDR 0x15b0 -#define REG_DRAM_TRAINING_LOW_FREQ_OFFS 0 -#define REG_DRAM_TRAINING_PATTERNS_OFFS 4 -#define REG_DRAM_TRAINING_MED_FREQ_OFFS 2 -#define REG_DRAM_TRAINING_WL_OFFS 3 -#define REG_DRAM_TRAINING_RL_OFFS 6 -#define REG_DRAM_TRAINING_DQS_RX_OFFS 15 -#define REG_DRAM_TRAINING_DQS_TX_OFFS 16 -#define REG_DRAM_TRAINING_CS_OFFS 20 -#define REG_DRAM_TRAINING_RETEST_OFFS 24 -#define REG_DRAM_TRAINING_DFS_FREQ_OFFS 27 -#define REG_DRAM_TRAINING_DFS_REQ_OFFS 29 -#define REG_DRAM_TRAINING_ERROR_OFFS 30 -#define REG_DRAM_TRAINING_AUTO_OFFS 31 -#define REG_DRAM_TRAINING_RETEST_PAR 0x3 -#define REG_DRAM_TRAINING_RETEST_MASK 0xf8ffffff -#define REG_DRAM_TRAINING_CS_MASK 0xff0fffff -#define REG_DRAM_TRAINING_PATTERNS_MASK 0xff0f0000 - -#define REG_DRAM_TRAINING_1_ADDR 0x15b4 -#define REG_DRAM_TRAINING_1_TRNBPOINT_OFFS 16 - -#define REG_DRAM_TRAINING_2_ADDR 0x15b8 -#define REG_DRAM_TRAINING_2_OVERRUN_OFFS 17 -#define REG_DRAM_TRAINING_2_FIFO_RST_OFFS 4 -#define REG_DRAM_TRAINING_2_RL_MODE_OFFS 3 -#define REG_DRAM_TRAINING_2_WL_MODE_OFFS 2 -#define REG_DRAM_TRAINING_2_ECC_MUX_OFFS 1 -#define REG_DRAM_TRAINING_2_SW_OVRD_OFFS 0 - -#define REG_DRAM_TRAINING_PATTERN_BASE_ADDR 0x15bc -#define REG_DRAM_TRAINING_PATTERN_BASE_OFFS 3 - -#define REG_TRAINING_DEBUG_2_ADDR 0x15c4 -#define REG_TRAINING_DEBUG_2_OFFS 16 -#define REG_TRAINING_DEBUG_2_MASK 0x3 - -#define REG_TRAINING_DEBUG_3_ADDR 0x15c8 -#define REG_TRAINING_DEBUG_3_OFFS 3 -#define REG_TRAINING_DEBUG_3_MASK 0x7 - -#define MR_CS_ADDR_OFFS 4 - -#define REG_DDR3_MR0_ADDR 0x15d0 -#define REG_DDR3_MR0_CS_ADDR 0x1870 -#define REG_DDR3_MR0_CL_MASK 0x74 -#define REG_DDR3_MR0_CL_OFFS 2 -#define REG_DDR3_MR0_CL_HIGH_OFFS 3 -#define CL_MASK 0xf - -#define REG_DDR3_MR1_ADDR 0x15d4 -#define REG_DDR3_MR1_CS_ADDR 0x1874 -#define REG_DDR3_MR1_RTT_MASK 0xfffffdbb -#define REG_DDR3_MR1_DLL_ENA_OFFS 0 -#define REG_DDR3_MR1_RTT_DISABLED 0x0 -#define REG_DDR3_MR1_RTT_RZQ2 0x40 -#define REG_DDR3_MR1_RTT_RZQ4 0x2 -#define REG_DDR3_MR1_RTT_RZQ6 0x42 -#define REG_DDR3_MR1_RTT_RZQ8 0x202 -#define REG_DDR3_MR1_RTT_RZQ12 0x4 -/* WL-disabled, OB-enabled */ -#define REG_DDR3_MR1_OUTBUF_WL_MASK 0xffffef7f -/* Output Buffer Disabled */ -#define REG_DDR3_MR1_OUTBUF_DIS_OFFS 12 -#define REG_DDR3_MR1_WL_ENA_OFFS 7 -#define REG_DDR3_MR1_WL_ENA 0x80 /* WL Enabled */ -#define REG_DDR3_MR1_ODT_MASK 0xfffffdbb - -#define REG_DDR3_MR2_ADDR 0x15d8 -#define REG_DDR3_MR2_CS_ADDR 0x1878 -#define REG_DDR3_MR2_CWL_OFFS 3 -#define REG_DDR3_MR2_CWL_MASK 0x7 -#define REG_DDR3_MR2_ODT_MASK 0xfffff9ff -#define REG_DDR3_MR3_ADDR 0x15dc -#define REG_DDR3_MR3_CS_ADDR 0x187c - -#define REG_DDR3_RANK_CTRL_ADDR 0x15e0 -#define REG_DDR3_RANK_CTRL_CS_ENA_MASK 0xf -#define REG_DDR3_RANK_CTRL_MIRROR_OFFS 4 - -#define REG_ZQC_CONF_ADDR 0x15e4 - -#define REG_DRAM_PHY_CONFIG_ADDR 0x15ec -#define REG_DRAM_PHY_CONFIG_MASK 0x3fffffff - -#define REG_ODPG_CNTRL_ADDR 0x1600 -#define REG_ODPG_CNTRL_OFFS 21 - -#define REG_PHY_LOCK_MASK_ADDR 0x1670 -#define REG_PHY_LOCK_MASK_MASK 0xfffff000 - -#define REG_PHY_LOCK_STATUS_ADDR 0x1674 -#define REG_PHY_LOCK_STATUS_LOCK_OFFS 9 -#define REG_PHY_LOCK_STATUS_LOCK_MASK 0xfff -#define REG_PHY_LOCK_APLL_ADLL_STATUS_MASK 0x7ff - -#define REG_PHY_REGISTRY_FILE_ACCESS_ADDR 0x16a0 -#define REG_PHY_REGISTRY_FILE_ACCESS_OP_WR 0xc0000000 -#define REG_PHY_REGISTRY_FILE_ACCESS_OP_RD 0x80000000 -#define REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE 0x80000000 -#define REG_PHY_BC_OFFS 27 -#define REG_PHY_CNTRL_OFFS 26 -#define REG_PHY_CS_OFFS 16 -#define REG_PHY_DQS_REF_DLY_OFFS 10 -#define REG_PHY_PHASE_OFFS 8 -#define REG_PHY_PUP_OFFS 22 - -#define REG_TRAINING_WL_ADDR 0x16ac -#define REG_TRAINING_WL_CS_MASK 0xfffffffc -#define REG_TRAINING_WL_UPD_OFFS 2 -#define REG_TRAINING_WL_CS_DONE_OFFS 3 -#define REG_TRAINING_WL_RATIO_MASK 0xffffff0f -#define REG_TRAINING_WL_1TO1 0x50 -#define REG_TRAINING_WL_2TO1 0x10 -#define REG_TRAINING_WL_DELAYEXP_MASK 0x20000000 -#define REG_TRAINING_WL_RESULTS_MASK 0x000001ff -#define REG_TRAINING_WL_RESULTS_OFFS 20 - -#define REG_REGISTERED_DRAM_CTRL_ADDR 0x16d0 -#define REG_REGISTERED_DRAM_CTRL_SR_FLOAT_OFFS 15 -#define REG_REGISTERED_DRAM_CTRL_PARITY_MASK 0x3f - -/* DLB */ -#define REG_STATIC_DRAM_DLB_CONTROL 0x1700 -#define DLB_BUS_OPTIMIZATION_WEIGHTS_REG 0x1704 -#define DLB_AGING_REGISTER 0x1708 -#define DLB_EVICTION_CONTROL_REG 0x170c -#define DLB_EVICTION_TIMERS_REGISTER_REG 0x1710 -#define DLB_USER_COMMAND_REG 0x1714 -#define DLB_BUS_WEIGHTS_DIFF_CS 0x1770 -#define DLB_BUS_WEIGHTS_DIFF_BG 0x1774 -#define DLB_BUS_WEIGHTS_SAME_BG 0x1778 -#define DLB_BUS_WEIGHTS_RD_WR 0x177c -#define DLB_BUS_WEIGHTS_ATTR_SYS_PRIO 0x1780 -#define DLB_MAIN_QUEUE_MAP 0x1784 -#define DLB_LINE_SPLIT 0x1788 - -#define DLB_ENABLE 0x1 -#define DLB_WRITE_COALESING (0x1 << 2) -#define DLB_AXI_PREFETCH_EN (0x1 << 3) -#define DLB_MBUS_PREFETCH_EN (0x1 << 4) -#define PREFETCH_N_LN_SZ_TR (0x1 << 6) -#define DLB_INTERJECTION_ENABLE (0x1 << 3) - -/* CPU */ -#define REG_BOOTROM_ROUTINE_ADDR 0x182d0 -#define REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS 12 - -#define REG_DRAM_INIT_CTRL_STATUS_ADDR 0x18488 -#define REG_DRAM_INIT_CTRL_TRN_CLK_OFFS 16 -#define REG_CPU_DIV_CLK_CTRL_0_NEW_RATIO 0x000200ff -#define REG_DRAM_INIT_CTRL_STATUS_2_ADDR 0x1488 - -#define REG_CPU_DIV_CLK_CTRL_0_ADDR 0x18700 - -#define REG_CPU_DIV_CLK_CTRL_1_ADDR 0x18704 -#define REG_CPU_DIV_CLK_CTRL_2_ADDR 0x18708 - -#define REG_CPU_DIV_CLK_CTRL_3_ADDR 0x1870c -#define REG_CPU_DIV_CLK_CTRL_3_FREQ_MASK 0xffffc0ff -#define REG_CPU_DIV_CLK_CTRL_3_FREQ_OFFS 8 - -#define REG_CPU_DIV_CLK_CTRL_4_ADDR 0x18710 - -#define REG_CPU_DIV_CLK_STATUS_0_ADDR 0x18718 -#define REG_CPU_DIV_CLK_ALL_STABLE_OFFS 8 - -#define REG_CPU_PLL_CTRL_0_ADDR 0x1871c -#define REG_CPU_PLL_STATUS_0_ADDR 0x18724 -#define REG_CORE_DIV_CLK_CTRL_ADDR 0x18740 -#define REG_CORE_DIV_CLK_STATUS_ADDR 0x18744 -#define REG_DDRPHY_APLL_CTRL_ADDR 0x18780 - -#define REG_DDRPHY_APLL_CTRL_2_ADDR 0x18784 -#define REG_SFABRIC_CLK_CTRL_ADDR 0x20858 -#define REG_SFABRIC_CLK_CTRL_SMPL_OFFS 8 - -/* DRAM Windows */ -#define REG_XBAR_WIN_19_CTRL_ADDR 0x200e8 -#define REG_XBAR_WIN_4_CTRL_ADDR 0x20040 -#define REG_XBAR_WIN_4_BASE_ADDR 0x20044 -#define REG_XBAR_WIN_4_REMAP_ADDR 0x20048 -#define REG_FASTPATH_WIN_0_CTRL_ADDR 0x20184 -#define REG_XBAR_WIN_7_REMAP_ADDR 0x20078 - -/* SRAM */ -#define REG_CDI_CONFIG_ADDR 0x20220 -#define REG_SRAM_WINDOW_0_ADDR 0x20240 -#define REG_SRAM_WINDOW_0_ENA_OFFS 0 -#define REG_SRAM_WINDOW_1_ADDR 0x20244 -#define REG_SRAM_L2_ENA_ADDR 0x8500 -#define REG_SRAM_CLEAN_BY_WAY_ADDR 0x87bc - -/* Timers */ -#define REG_TIMERS_CTRL_ADDR 0x20300 -#define REG_TIMERS_EVENTS_ADDR 0x20304 -#define REG_TIMER0_VALUE_ADDR 0x20314 -#define REG_TIMER1_VALUE_ADDR 0x2031c -#define REG_TIMER0_ENABLE_MASK 0x1 - -#define MV_BOARD_REFCLK_25MHZ 25000000 -#define CNTMR_RELOAD_REG(tmr) (REG_TIMERS_CTRL_ADDR + 0x10 + (tmr * 8)) -#define CNTMR_VAL_REG(tmr) (REG_TIMERS_CTRL_ADDR + 0x14 + (tmr * 8)) -#define CNTMR_CTRL_REG(tmr) (REG_TIMERS_CTRL_ADDR) -#define CTCR_ARM_TIMER_EN_OFFS(timer) (timer * 2) -#define CTCR_ARM_TIMER_EN_MASK(timer) (1 << CTCR_ARM_TIMER_EN_OFFS(timer)) -#define CTCR_ARM_TIMER_EN(timer) (1 << CTCR_ARM_TIMER_EN_OFFS(timer)) - -#define CTCR_ARM_TIMER_AUTO_OFFS(timer) (1 + (timer * 2)) -#define CTCR_ARM_TIMER_AUTO_MASK(timer) (1 << CTCR_ARM_TIMER_EN_OFFS(timer)) -#define CTCR_ARM_TIMER_AUTO_EN(timer) (1 << CTCR_ARM_TIMER_AUTO_OFFS(timer)) - -/* PMU */ -#define REG_PMU_I_F_CTRL_ADDR 0x1c090 -#define REG_PMU_DUNIT_BLK_OFFS 16 -#define REG_PMU_DUNIT_RFRS_OFFS 20 -#define REG_PMU_DUNIT_ACK_OFFS 24 - -/* MBUS */ -#define MBUS_UNITS_PRIORITY_CONTROL_REG (MBUS_REGS_OFFSET + 0x420) -#define FABRIC_UNITS_PRIORITY_CONTROL_REG (MBUS_REGS_OFFSET + 0x424) -#define MBUS_UNITS_PREFETCH_CONTROL_REG (MBUS_REGS_OFFSET + 0x428) -#define FABRIC_UNITS_PREFETCH_CONTROL_REG (MBUS_REGS_OFFSET + 0x42c) - -#define REG_PM_STAT_MASK_ADDR 0x2210c -#define REG_PM_STAT_MASK_CPU0_IDLE_MASK_OFFS 16 - -#define REG_PM_EVENT_STAT_MASK_ADDR 0x22120 -#define REG_PM_EVENT_STAT_MASK_DFS_DONE_OFFS 17 - -#define REG_PM_CTRL_CONFIG_ADDR 0x22104 -#define REG_PM_CTRL_CONFIG_DFS_REQ_OFFS 18 - -#define REG_FABRIC_LOCAL_IRQ_MASK_ADDR 0x218c4 -#define REG_FABRIC_LOCAL_IRQ_PMU_MASK_OFFS 18 - -/* Controller revision info */ -#define PCI_CLASS_CODE_AND_REVISION_ID 0x008 -#define PCCRIR_REVID_OFFS 0 /* Revision ID */ -#define PCCRIR_REVID_MASK (0xff << PCCRIR_REVID_OFFS) - -/* Power Management Clock Gating Control Register */ -#define POWER_MNG_CTRL_REG 0x18220 -#define PMC_PEXSTOPCLOCK_OFFS(p) ((p) < 8 ? (5 + (p)) : (18 + (p))) -#define PMC_PEXSTOPCLOCK_MASK(p) (1 << PMC_PEXSTOPCLOCK_OFFS(p)) -#define PMC_PEXSTOPCLOCK_EN(p) (1 << PMC_PEXSTOPCLOCK_OFFS(p)) -#define PMC_PEXSTOPCLOCK_STOP(p) (0 << PMC_PEXSTOPCLOCK_OFFS(p)) - -/* TWSI */ -#define TWSI_DATA_ADDR_MASK 0x7 -#define TWSI_DATA_ADDR_OFFS 1 - -/* General */ -#define MAX_CS 4 - -/* Frequencies */ -#define FAB_OPT 21 -#define CLK_CPU 12 -#define CLK_VCO (2 * CLK_CPU) -#define CLK_DDR 12 - -/* CPU Frequencies: */ -#define CLK_CPU_1000 0 -#define CLK_CPU_1066 1 -#define CLK_CPU_1200 2 -#define CLK_CPU_1333 3 -#define CLK_CPU_1500 4 -#define CLK_CPU_1666 5 -#define CLK_CPU_1800 6 -#define CLK_CPU_2000 7 -#define CLK_CPU_600 8 -#define CLK_CPU_667 9 -#define CLK_CPU_800 0xa - -/* Extra Cpu Frequencies: */ -#define CLK_CPU_1600 11 -#define CLK_CPU_2133 12 -#define CLK_CPU_2200 13 -#define CLK_CPU_2400 14 - -#endif /* _DDR3_HWS_HW_TRAINING_DEF_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h b/drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h deleted file mode 100644 index 2f8e3fdd94..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_hws_sil_training.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#ifndef _DDR3_HWS_SIL_TRAINING_H -#define _DDR3_HWS_SIL_TRAINING_H - -#include "ddr3_training_ip.h" -#include "ddr3_training_ip_prv_if.h" - -int ddr3_silicon_pre_config(void); -int ddr3_silicon_init(void); -int ddr3_silicon_get_ddr_target_freq(u32 *ddr_freq); - -#endif /* _DDR3_HWS_SIL_TRAINING_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c index 73d984ba66..27dbf4f44b 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.c +++ b/drivers/ddr/marvell/a38x/ddr3_init.c @@ -3,239 +3,30 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include -#include - #include "ddr3_init.h" +#include "mv_ddr_common.h" -#include "../../../../arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h" - -static struct dlb_config ddr3_dlb_config_table[] = { - {REG_STATIC_DRAM_DLB_CONTROL, 0x2000005c}, - {DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0x00880000}, - {DLB_AGING_REGISTER, 0x0f7f007f}, - {DLB_EVICTION_CONTROL_REG, 0x0000129f}, - {DLB_EVICTION_TIMERS_REGISTER_REG, 0x00ff0000}, - {DLB_BUS_WEIGHTS_DIFF_CS, 0x04030802}, - {DLB_BUS_WEIGHTS_DIFF_BG, 0x00000a02}, - {DLB_BUS_WEIGHTS_SAME_BG, 0x09000a01}, - {DLB_BUS_WEIGHTS_RD_WR, 0x00020005}, - {DLB_BUS_WEIGHTS_ATTR_SYS_PRIO, 0x00060f10}, - {DLB_MAIN_QUEUE_MAP, 0x00000543}, - {DLB_LINE_SPLIT, 0x00000000}, - {DLB_USER_COMMAND_REG, 0x00000000}, - {0x0, 0x0} -}; - -static struct dlb_config ddr3_dlb_config_table_a0[] = { - {REG_STATIC_DRAM_DLB_CONTROL, 0x2000005c}, - {DLB_BUS_OPTIMIZATION_WEIGHTS_REG, 0x00880000}, - {DLB_AGING_REGISTER, 0x0f7f007f}, - {DLB_EVICTION_CONTROL_REG, 0x0000129f}, - {DLB_EVICTION_TIMERS_REGISTER_REG, 0x00ff0000}, - {DLB_BUS_WEIGHTS_DIFF_CS, 0x04030802}, - {DLB_BUS_WEIGHTS_DIFF_BG, 0x00000a02}, - {DLB_BUS_WEIGHTS_SAME_BG, 0x09000a01}, - {DLB_BUS_WEIGHTS_RD_WR, 0x00020005}, - {DLB_BUS_WEIGHTS_ATTR_SYS_PRIO, 0x00060f10}, - {DLB_MAIN_QUEUE_MAP, 0x00000543}, - {DLB_LINE_SPLIT, 0x00000000}, - {DLB_USER_COMMAND_REG, 0x00000000}, - {0x0, 0x0} -}; - -#if defined(CONFIG_ARMADA_38X) -struct dram_modes { - char *mode_name; - u8 cpu_freq; - u8 fab_freq; - u8 chip_id; - u8 chip_board_rev; - struct reg_data *regs; -}; - -struct dram_modes ddr_modes[] = { -}; -#endif /* defined(CONFIG_ARMADA_38X) */ - -/* Translates topology map definitions to real memory size in bits */ +/* + * Translates topology map definitions to real memory size in bits + * (per values in ddr3_training_ip_def.h) + */ u32 mem_size[] = { - ADDR_SIZE_512MB, ADDR_SIZE_1GB, ADDR_SIZE_2GB, ADDR_SIZE_4GB, + ADDR_SIZE_512MB, + ADDR_SIZE_1GB, + ADDR_SIZE_2GB, + ADDR_SIZE_4GB, ADDR_SIZE_8GB }; static char *ddr_type = "DDR3"; /* - * Set 1 to use dynamic DUNIT configuration, - * set 0 (supported for A380 and AC3) to configure DUNIT in values set by - * ddr3_tip_init_specific_reg_config + * generic_init_controller controls D-unit configuration: + * '1' - dynamic D-unit configuration, */ u8 generic_init_controller = 1; -static int ddr3_hws_tune_training_params(u8 dev_num); - -/* device revision */ -#define DEV_VERSION_ID_REG 0x1823c -#define REVISON_ID_OFFS 8 -#define REVISON_ID_MASK 0xf00 - -/* A38x revisions */ -#define MV_88F68XX_Z1_ID 0x0 -#define MV_88F68XX_A0_ID 0x4 -/* A39x revisions */ -#define MV_88F69XX_Z1_ID 0x2 - -/* - * sys_env_dlb_config_ptr_get - * - * DESCRIPTION: defines pointer to to DLB COnfiguration table - * - * INPUT: none - * - * OUTPUT: pointer to DLB COnfiguration table - * - * RETURN: - * returns pointer to DLB COnfiguration table - */ -struct dlb_config *sys_env_dlb_config_ptr_get(void) -{ -#ifdef CONFIG_ARMADA_39X - return &ddr3_dlb_config_table_a0[0]; -#else - if (sys_env_device_rev_get() == MV_88F68XX_A0_ID) - return &ddr3_dlb_config_table_a0[0]; - else - return &ddr3_dlb_config_table[0]; -#endif -} - -/* - * sys_env_get_cs_ena_from_reg - * - * DESCRIPTION: Get bit mask of enabled CS - * - * INPUT: None - * - * OUTPUT: None - * - * RETURN: - * Bit mask of enabled CS, 1 if only CS0 enabled, - * 3 if both CS0 and CS1 enabled - */ -u32 sys_env_get_cs_ena_from_reg(void) -{ - return reg_read(REG_DDR3_RANK_CTRL_ADDR) & - REG_DDR3_RANK_CTRL_CS_ENA_MASK; -} - -static void ddr3_restore_and_set_final_windows(u32 *win) -{ - u32 win_ctrl_reg, num_of_win_regs; - u32 cs_ena = sys_env_get_cs_ena_from_reg(); - u32 ui; - - win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; - num_of_win_regs = 16; - - /* Return XBAR windows 4-7 or 16-19 init configuration */ - for (ui = 0; ui < num_of_win_regs; ui++) - reg_write((win_ctrl_reg + 0x4 * ui), win[ui]); - - printf("%s Training Sequence - Switching XBAR Window to FastPath Window\n", - ddr_type); - -#if defined DYNAMIC_CS_SIZE_CONFIG - if (ddr3_fast_path_dynamic_cs_size_config(cs_ena) != MV_OK) - printf("ddr3_fast_path_dynamic_cs_size_config FAILED\n"); -#else - u32 reg, cs; - reg = 0x1fffffe1; - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - reg |= (cs << 2); - break; - } - } - /* Open fast path Window to - 0.5G */ - reg_write(REG_FASTPATH_WIN_0_CTRL_ADDR, reg); -#endif -} - -static int ddr3_save_and_set_training_windows(u32 *win) -{ - u32 cs_ena; - u32 reg, tmp_count, cs, ui; - u32 win_ctrl_reg, win_base_reg, win_remap_reg; - u32 num_of_win_regs, win_jump_index; - win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; - win_base_reg = REG_XBAR_WIN_4_BASE_ADDR; - win_remap_reg = REG_XBAR_WIN_4_REMAP_ADDR; - win_jump_index = 0x10; - num_of_win_regs = 16; - struct hws_topology_map *tm = ddr3_get_topology_map(); - -#ifdef DISABLE_L2_FILTERING_DURING_DDR_TRAINING - /* - * Disable L2 filtering during DDR training - * (when Cross Bar window is open) - */ - reg_write(ADDRESS_FILTERING_END_REGISTER, 0); -#endif - - cs_ena = tm->interface_params[0].as_bus_params[0].cs_bitmask; - - /* Close XBAR Window 19 - Not needed */ - /* {0x000200e8} - Open Mbus Window - 2G */ - reg_write(REG_XBAR_WIN_19_CTRL_ADDR, 0); - - /* Save XBAR Windows 4-19 init configurations */ - for (ui = 0; ui < num_of_win_regs; ui++) - win[ui] = reg_read(win_ctrl_reg + 0x4 * ui); - - /* Open XBAR Windows 4-7 or 16-19 for other CS */ - reg = 0; - tmp_count = 0; - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - switch (cs) { - case 0: - reg = 0x0e00; - break; - case 1: - reg = 0x0d00; - break; - case 2: - reg = 0x0b00; - break; - case 3: - reg = 0x0700; - break; - } - reg |= (1 << 0); - reg |= (SDRAM_CS_SIZE & 0xffff0000); - - reg_write(win_ctrl_reg + win_jump_index * tmp_count, - reg); - reg = (((SDRAM_CS_SIZE + 1) * (tmp_count)) & - 0xffff0000); - reg_write(win_base_reg + win_jump_index * tmp_count, - reg); - - if (win_remap_reg <= REG_XBAR_WIN_7_REMAP_ADDR) - reg_write(win_remap_reg + - win_jump_index * tmp_count, 0); - - tmp_count++; - } - } - - return MV_OK; -} +static int mv_ddr_training_params_set(u8 dev_num); /* * Name: ddr3_init - Main DDR3 Init function @@ -246,464 +37,182 @@ static int ddr3_save_and_set_training_windows(u32 *win) */ int ddr3_init(void) { - u32 reg = 0; - u32 soc_num; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 octets_per_if_num; int status; - u32 win[16]; - - /* SoC/Board special Initializtions */ - /* Get version from internal library */ - ddr3_print_version(); - - /*Add sub_version string */ - DEBUG_INIT_C("", SUB_VERSION, 1); - - /* Switching CPU to MRVL ID */ - soc_num = (reg_read(REG_SAMPLE_RESET_HIGH_ADDR) & SAR1_CPU_CORE_MASK) >> - SAR1_CPU_CORE_OFFSET; - switch (soc_num) { - case 0x3: - case 0x1: - reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET); - case 0x0: - reg_bit_set(CPU_CONFIGURATION_REG(0), CPU_MRVL_ID_OFFSET); - default: - break; - } + int is_manual_cal_done; - /* - * Set DRAM Reset Mask in case detected GPIO indication of wakeup from - * suspend i.e the DRAM values will not be overwritten / reset when - * waking from suspend - */ - if (sys_env_suspend_wakeup_check() == - SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED) { - reg_bit_set(REG_SDRAM_INIT_CTRL_ADDR, - 1 << REG_SDRAM_INIT_RESET_MASK_OFFS); - } + /* Print mv_ddr version */ + mv_ddr_ver_print(); - /* - * Stage 0 - Set board configuration - */ + mv_ddr_pre_training_fixup(); - /* Check if DRAM is already initialized */ - if (reg_read(REG_BOOTROM_ROUTINE_ADDR) & - (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) { - printf("%s Training Sequence - 2nd boot - Skip\n", ddr_type); - return MV_OK; - } + /* SoC/Board special initializations */ + mv_ddr_pre_training_soc_config(ddr_type); - /* - * Stage 1 - Dunit Setup - */ - - /* Fix read ready phases for all SOC in reg 0x15c8 */ - reg = reg_read(REG_TRAINING_DEBUG_3_ADDR); - reg &= ~(REG_TRAINING_DEBUG_3_MASK); - reg |= 0x4; /* Phase 0 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << REG_TRAINING_DEBUG_3_OFFS); - reg |= (0x4 << (1 * REG_TRAINING_DEBUG_3_OFFS)); /* Phase 1 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (3 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (3 * REG_TRAINING_DEBUG_3_OFFS)); /* Phase 3 */ - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (4 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (4 * REG_TRAINING_DEBUG_3_OFFS)); - reg &= ~(REG_TRAINING_DEBUG_3_MASK << (5 * REG_TRAINING_DEBUG_3_OFFS)); - reg |= (0x6 << (5 * REG_TRAINING_DEBUG_3_OFFS)); - reg_write(REG_TRAINING_DEBUG_3_ADDR, reg); - - /* - * Axi_bresp_mode[8] = Compliant, - * Axi_addr_decode_cntrl[11] = Internal, - * Axi_data_bus_width[0] = 128bit - * */ - /* 0x14a8 - AXI Control Register */ - reg_write(REG_DRAM_AXI_CTRL_ADDR, 0); - - /* - * Stage 2 - Training Values Setup - */ - /* Set X-BAR windows for the training sequence */ - ddr3_save_and_set_training_windows(win); - - - /* Tune training algo paramteres */ - status = ddr3_hws_tune_training_params(0); - if (MV_OK != status) - return status; + /* Set log level for training library */ + mv_ddr_user_log_level_set(DEBUG_BLOCK_ALL); - /* Set log level for training lib */ - ddr3_hws_set_log_level(DEBUG_BLOCK_ALL, DEBUG_LEVEL_ERROR); + mv_ddr_early_init(); - /* Start New Training IP */ - status = ddr3_hws_hw_training(); - if (MV_OK != status) { - printf("%s Training Sequence - FAILED\n", ddr_type); - return status; + if (mv_ddr_topology_map_update() == NULL) { + printf("mv_ddr: failed to update topology\n"); + return MV_FAIL; } - /* - * Stage 3 - Finish - */ - /* Restore and set windows */ - ddr3_restore_and_set_final_windows(win); - - /* Update DRAM init indication in bootROM register */ - reg = reg_read(REG_BOOTROM_ROUTINE_ADDR); - reg_write(REG_BOOTROM_ROUTINE_ADDR, - reg | (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)); + if (mv_ddr_early_init2() != MV_OK) + return MV_FAIL; - /* DLB config */ - ddr3_new_tip_dlb_config(); + /* Set training algorithm's parameters */ + status = mv_ddr_training_params_set(0); + if (MV_OK != status) + return status; -#if defined(ECC_SUPPORT) - if (ddr3_if_ecc_enabled()) - ddr3_new_tip_ecc_scrub(); -#endif - printf("%s Training Sequence - Ended Successfully\n", ddr_type); + mv_ddr_mc_config(); - return MV_OK; -} + is_manual_cal_done = mv_ddr_manual_cal_do(); -/* - * Name: ddr3_get_cpu_freq - * Desc: read S@R and return CPU frequency - * Args: - * Notes: - * Returns: required value - */ -u32 ddr3_get_cpu_freq(void) -{ - return ddr3_tip_get_init_freq(); -} + mv_ddr_mc_init(); -/* - * Name: ddr3_get_fab_opt - * Desc: read S@R and return CPU frequency - * Args: - * Notes: - * Returns: required value - */ -u32 ddr3_get_fab_opt(void) -{ - return 0; /* No fabric */ -} - -/* - * Name: ddr3_get_static_m_cValue - Init Memory controller with - * static parameters - * Desc: Use this routine to init the controller without the HW training - * procedure. - * User must provide compatible header file with registers data. - * Args: None. - * Notes: - * Returns: None. - */ -u32 ddr3_get_static_mc_value(u32 reg_addr, u32 offset1, u32 mask1, - u32 offset2, u32 mask2) -{ - u32 reg, temp; - - reg = reg_read(reg_addr); - - temp = (reg >> offset1) & mask1; - if (mask2) - temp |= (reg >> offset2) & mask2; + if (!is_manual_cal_done) { + } - return temp; -} -/* - * Name: ddr3_get_static_ddr_mode - Init Memory controller with - * static parameters - * Desc: Use this routine to init the controller without the HW training - * procedure. - * User must provide compatible header file with registers data. - * Args: None. - * Notes: - * Returns: None. - */ -u32 ddr3_get_static_ddr_mode(void) -{ - u32 chip_board_rev, i; - u32 size; - - /* Valid only for A380 only, MSYS using dynamic controller config */ -#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT - /* - * Customer boards select DDR mode according to - * board ID & Sample@Reset - */ - chip_board_rev = mv_board_id_get(); -#else - /* Marvell boards select DDR mode according to Sample@Reset only */ - chip_board_rev = MARVELL_BOARD; -#endif - - size = ARRAY_SIZE(ddr_modes); - for (i = 0; i < size; i++) { - if ((ddr3_get_cpu_freq() == ddr_modes[i].cpu_freq) && - (ddr3_get_fab_opt() == ddr_modes[i].fab_freq) && - (chip_board_rev == ddr_modes[i].chip_board_rev)) - return i; + status = ddr3_silicon_post_init(); + if (MV_OK != status) { + printf("DDR3 Post Init - FAILED 0x%x\n", status); + return status; } - DEBUG_INIT_S("\n*** Error: ddr3_get_static_ddr_mode: No match for requested DDR mode. ***\n\n"); - - return 0; -} + /* PHY initialization (Training) */ + status = hws_ddr3_tip_run_alg(0, ALGO_TYPE_DYNAMIC); + if (MV_OK != status) { + printf("%s Training Sequence - FAILED\n", ddr_type); + return status; + } -/****************************************************************************** - * Name: ddr3_get_cs_num_from_reg - * Desc: - * Args: - * Notes: - * Returns: - */ -u32 ddr3_get_cs_num_from_reg(void) -{ - u32 cs_ena = sys_env_get_cs_ena_from_reg(); - u32 cs_count = 0; - u32 cs; +#if defined(CONFIG_PHY_STATIC_PRINT) + mv_ddr_phy_static_print(); +#endif - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) - cs_count++; - } + /* Post MC/PHY initializations */ + mv_ddr_post_training_soc_config(ddr_type); - return cs_count; -} + mv_ddr_post_training_fixup(); -void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps) -{ - u32 tmp, hclk = 200; - - switch (freq_mode) { - case 4: - tmp = 1; /* DDR_400; */ - hclk = 200; - break; - case 0x8: - tmp = 1; /* DDR_666; */ - hclk = 333; - break; - case 0xc: - tmp = 1; /* DDR_800; */ - hclk = 400; - break; - default: - *ddr_freq = 0; - *hclk_ps = 0; - break; + octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + if (ddr3_if_ecc_enabled()) { + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) || + MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(tm->bus_act_mask, octets_per_if_num)) + mv_ddr_mem_scrubbing(); + else + ddr3_new_tip_ecc_scrub(); } - *ddr_freq = tmp; /* DDR freq define */ - *hclk_ps = 1000000 / hclk; /* values are 1/HCLK in ps */ + printf("mv_ddr: completed successfully\n"); - return; + return MV_OK; } -void ddr3_new_tip_dlb_config(void) +uint64_t mv_ddr_get_memory_size_per_cs_in_bits(void) { - u32 reg, i = 0; - struct dlb_config *config_table_ptr = sys_env_dlb_config_ptr_get(); - - /* Write the configuration */ - while (config_table_ptr[i].reg_addr != 0) { - reg_write(config_table_ptr[i].reg_addr, - config_table_ptr[i].reg_data); - i++; - } + uint64_t memory_size_per_cs; - /* Enable DLB */ - reg = reg_read(REG_STATIC_DRAM_DLB_CONTROL); - reg |= DLB_ENABLE | DLB_WRITE_COALESING | DLB_AXI_PREFETCH_EN | - DLB_MBUS_PREFETCH_EN | PREFETCH_N_LN_SZ_TR; - reg_write(REG_STATIC_DRAM_DLB_CONTROL, reg); -} + u32 bus_cnt, num_of_active_bus = 0; + u32 num_of_sub_phys_per_ddr_unit = 0; -int ddr3_fast_path_dynamic_cs_size_config(u32 cs_ena) -{ - u32 reg, cs; - u32 mem_total_size = 0; - u32 cs_mem_size = 0; - u32 mem_total_size_c, cs_mem_size_c; - -#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE - u32 physical_mem_size; - u32 max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE; - struct hws_topology_map *tm = ddr3_get_topology_map(); -#endif + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - /* Open fast path windows */ - for (cs = 0; cs < MAX_CS; cs++) { - if (cs_ena & (1 << cs)) { - /* get CS size */ - if (ddr3_calc_mem_cs_size(cs, &cs_mem_size) != MV_OK) - return MV_FAIL; - -#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE - /* - * if number of address pins doesn't allow to use max - * mem size that is defined in topology - * mem size is defined by DEVICE_MAX_DRAM_ADDRESS_SIZE - */ - physical_mem_size = mem_size - [tm->interface_params[0].memory_size]; - - if (ddr3_get_device_width(cs) == 16) { - /* - * 16bit mem device can be twice more - no need - * in less significant pin - */ - max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE * 2; - } - - if (physical_mem_size > max_mem_size) { - cs_mem_size = max_mem_size * - (ddr3_get_bus_width() / - ddr3_get_device_width(cs)); - printf("Updated Physical Mem size is from 0x%x to %x\n", - physical_mem_size, - DEVICE_MAX_DRAM_ADDRESS_SIZE); - } -#endif + u32 octets_per_if_num = ddr3_tip_dev_attr_get(DEV_NUM_0, MV_ATTR_OCTET_PER_INTERFACE); - /* set fast path window control for the cs */ - reg = 0xffffe1; - reg |= (cs << 2); - reg |= (cs_mem_size - 1) & 0xffff0000; - /*Open fast path Window */ - reg_write(REG_FASTPATH_WIN_CTRL_ADDR(cs), reg); - - /* Set fast path window base address for the cs */ - reg = ((cs_mem_size) * cs) & 0xffff0000; - /* Set base address */ - reg_write(REG_FASTPATH_WIN_BASE_ADDR(cs), reg); - - /* - * Since memory size may be bigger than 4G the summ may - * be more than 32 bit word, - * so to estimate the result divide mem_total_size and - * cs_mem_size by 0x10000 (it is equal to >> 16) - */ - mem_total_size_c = mem_total_size >> 16; - cs_mem_size_c = cs_mem_size >> 16; - /* if the sum less than 2 G - calculate the value */ - if (mem_total_size_c + cs_mem_size_c < 0x10000) - mem_total_size += cs_mem_size; - else /* put max possible size */ - mem_total_size = L2_FILTER_FOR_MAX_MEMORY_SIZE; - } + /* count the number of active bus */ + for (bus_cnt = 0; bus_cnt < octets_per_if_num - 1/* ignore ecc octet */; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + num_of_active_bus++; } - /* Set L2 filtering to Max Memory size */ - reg_write(ADDRESS_FILTERING_END_REGISTER, mem_total_size); - - return MV_OK; -} - -u32 ddr3_get_bus_width(void) -{ - u32 bus_width; + /* calculate number of sub-phys per ddr unit */ + if (tm->interface_params[0].bus_width/* supports only single interface */ == MV_DDR_DEV_WIDTH_16BIT) + num_of_sub_phys_per_ddr_unit = TWO_SUB_PHYS; + if (tm->interface_params[0].bus_width/* supports only single interface */ == MV_DDR_DEV_WIDTH_8BIT) + num_of_sub_phys_per_ddr_unit = SINGLE_SUB_PHY; - bus_width = (reg_read(REG_SDRAM_CONFIG_ADDR) & 0x8000) >> - REG_SDRAM_CONFIG_WIDTH_OFFS; + /* calculate dram size per cs */ + memory_size_per_cs = (uint64_t)mem_size[tm->interface_params[0].memory_size] * (uint64_t)num_of_active_bus + / (uint64_t)num_of_sub_phys_per_ddr_unit * (uint64_t)MV_DDR_NUM_BITS_IN_BYTE; - return (bus_width == 0) ? 16 : 32; + return memory_size_per_cs; } -u32 ddr3_get_device_width(u32 cs) +uint64_t mv_ddr_get_total_memory_size_in_bits(void) { - u32 device_width; + uint64_t total_memory_size = 0; + uint64_t memory_size_per_cs = 0; - device_width = (reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR) & - (0x3 << (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs))) >> - (REG_SDRAM_ADDRESS_CTRL_STRUCT_OFFS * cs); + /* get the number of cs */ + u32 max_cs = ddr3_tip_max_cs_get(DEV_NUM_0); - return (device_width == 0) ? 8 : 16; -} + memory_size_per_cs = mv_ddr_get_memory_size_per_cs_in_bits(); + total_memory_size = (uint64_t)max_cs * memory_size_per_cs; -static int ddr3_get_device_size(u32 cs) -{ - u32 device_size_low, device_size_high, device_size; - u32 data, cs_low_offset, cs_high_offset; - - cs_low_offset = REG_SDRAM_ADDRESS_SIZE_OFFS + cs * 4; - cs_high_offset = REG_SDRAM_ADDRESS_SIZE_OFFS + - REG_SDRAM_ADDRESS_SIZE_HIGH_OFFS + cs; - - data = reg_read(REG_SDRAM_ADDRESS_CTRL_ADDR); - device_size_low = (data >> cs_low_offset) & 0x3; - device_size_high = (data >> cs_high_offset) & 0x1; - - device_size = device_size_low | (device_size_high << 2); - - switch (device_size) { - case 0: - return 2048; - case 2: - return 512; - case 3: - return 1024; - case 4: - return 4096; - case 5: - return 8192; - case 1: - default: - DEBUG_INIT_C("Error: Wrong device size of Cs: ", cs, 1); - /* - * Small value will give wrong emem size in - * ddr3_calc_mem_cs_size - */ - return 0; - } + return total_memory_size; } -int ddr3_calc_mem_cs_size(u32 cs, u32 *cs_size) +int ddr3_if_ecc_enabled(void) { - int cs_mem_size; - - /* Calculate in GiB */ - cs_mem_size = ((ddr3_get_bus_width() / ddr3_get_device_width(cs)) * - ddr3_get_device_size(cs)) / 8; - - /* - * Multiple controller bus width, 2x for 64 bit - * (SoC controller may be 32 or 64 bit, - * so bit 15 in 0x1400, that means if whole bus used or only half, - * have a differnt meaning - */ - cs_mem_size *= DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER; - - if (!cs_mem_size || (cs_mem_size == 64) || (cs_mem_size == 4096)) { - DEBUG_INIT_C("Error: Wrong Memory size of Cs: ", cs, 1); - return MV_BAD_VALUE; - } + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - *cs_size = cs_mem_size << 20; - return MV_OK; + if (DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask) || + DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask) || + DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask)) + return 1; + else + return 0; } /* - * Name: ddr3_hws_tune_training_params + * Name: mv_ddr_training_params_set * Desc: * Args: - * Notes: Tune internal training params + * Notes: sets internal training params * Returns: */ -static int ddr3_hws_tune_training_params(u8 dev_num) +static int mv_ddr_training_params_set(u8 dev_num) { struct tune_train_params params; int status; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 if_id; + u32 cs_num; + + CHECK_STATUS(ddr3_tip_get_first_active_if + (dev_num, tm->if_act_mask, + &if_id)); + + CHECK_STATUS(calc_cs_num(dev_num, if_id, &cs_num)); /* NOTE: do not remove any field initilization */ params.ck_delay = TUNE_TRAINING_PARAMS_CK_DELAY; - params.ck_delay_16 = TUNE_TRAINING_PARAMS_CK_DELAY_16; - params.p_finger = TUNE_TRAINING_PARAMS_PFINGER; - params.n_finger = TUNE_TRAINING_PARAMS_NFINGER; params.phy_reg3_val = TUNE_TRAINING_PARAMS_PHYREG3VAL; + params.g_zpri_data = TUNE_TRAINING_PARAMS_PRI_DATA; + params.g_znri_data = TUNE_TRAINING_PARAMS_NRI_DATA; + params.g_zpri_ctrl = TUNE_TRAINING_PARAMS_PRI_CTRL; + params.g_znri_ctrl = TUNE_TRAINING_PARAMS_NRI_CTRL; + params.g_znodt_data = TUNE_TRAINING_PARAMS_N_ODT_DATA; + params.g_zpodt_ctrl = TUNE_TRAINING_PARAMS_P_ODT_CTRL; + params.g_znodt_ctrl = TUNE_TRAINING_PARAMS_N_ODT_CTRL; + + params.g_zpodt_data = TUNE_TRAINING_PARAMS_P_ODT_DATA; + params.g_dic = TUNE_TRAINING_PARAMS_DIC; + params.g_rtt_nom = TUNE_TRAINING_PARAMS_RTT_NOM; + if (cs_num == 1) { + params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_1CS; + params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_1CS; + } else { + params.g_rtt_wr = TUNE_TRAINING_PARAMS_RTT_WR_2CS; + params.g_odt_config = TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS; + } status = ddr3_tip_tune_training_params(dev_num, ¶ms); if (MV_OK != status) { diff --git a/drivers/ddr/marvell/a38x/ddr3_init.h b/drivers/ddr/marvell/a38x/ddr3_init.h index 8cb645ffb5..382bd922f2 100644 --- a/drivers/ddr/marvell/a38x/ddr3_init.h +++ b/drivers/ddr/marvell/a38x/ddr3_init.h @@ -6,12 +6,12 @@ #ifndef _DDR3_INIT_H #define _DDR3_INIT_H -#if defined(CONFIG_ARMADA_38X) -#include "ddr3_a38x.h" -#include "ddr3_a38x_topology.h" +#include "ddr_ml_wrapper.h" +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) +#include "mv_ddr_plat.h" #endif -#include "ddr3_hws_hw_training.h" -#include "ddr3_hws_sil_training.h" + +#include "seq_exec.h" #include "ddr3_logging_def.h" #include "ddr3_training_hw_algo.h" #include "ddr3_training_ip.h" @@ -20,119 +20,9 @@ #include "ddr3_training_ip_flow.h" #include "ddr3_training_ip_pbs.h" #include "ddr3_training_ip_prv_if.h" -#include "ddr3_training_ip_static.h" #include "ddr3_training_leveling.h" #include "xor.h" -/* - * MV_DEBUG_INIT need to be defines, otherwise the output of the - * DDR2 training code is not complete and misleading - */ -#define MV_DEBUG_INIT - -#ifdef MV_DEBUG_INIT -#define DEBUG_INIT_S(s) puts(s) -#define DEBUG_INIT_D(d, l) printf("%x", d) -#define DEBUG_INIT_D_10(d, l) printf("%d", d) -#else -#define DEBUG_INIT_S(s) -#define DEBUG_INIT_D(d, l) -#define DEBUG_INIT_D_10(d, l) -#endif - -#ifdef MV_DEBUG_INIT_FULL -#define DEBUG_INIT_FULL_S(s) puts(s) -#define DEBUG_INIT_FULL_D(d, l) printf("%x", d) -#define DEBUG_INIT_FULL_D_10(d, l) printf("%d", d) -#define DEBUG_WR_REG(reg, val) \ - { DEBUG_INIT_S("Write Reg: 0x"); DEBUG_INIT_D((reg), 8); \ - DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); } -#define DEBUG_RD_REG(reg, val) \ - { DEBUG_INIT_S("Read Reg: 0x"); DEBUG_INIT_D((reg), 8); \ - DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); } -#else -#define DEBUG_INIT_FULL_S(s) -#define DEBUG_INIT_FULL_D(d, l) -#define DEBUG_INIT_FULL_D_10(d, l) -#define DEBUG_WR_REG(reg, val) -#define DEBUG_RD_REG(reg, val) -#endif - -#define DEBUG_INIT_FULL_C(s, d, l) \ - { DEBUG_INIT_FULL_S(s); \ - DEBUG_INIT_FULL_D(d, l); \ - DEBUG_INIT_FULL_S("\n"); } -#define DEBUG_INIT_C(s, d, l) \ - { DEBUG_INIT_S(s); DEBUG_INIT_D(d, l); DEBUG_INIT_S("\n"); } - -/* - * Debug (Enable/Disable modules) and Error report - */ - -#ifdef BASIC_DEBUG -#define MV_DEBUG_WL -#define MV_DEBUG_RL -#define MV_DEBUG_DQS_RESULTS -#endif - -#ifdef FULL_DEBUG -#define MV_DEBUG_WL -#define MV_DEBUG_RL -#define MV_DEBUG_DQS - -#define MV_DEBUG_PBS -#define MV_DEBUG_DFS -#define MV_DEBUG_MAIN_FULL -#define MV_DEBUG_DFS_FULL -#define MV_DEBUG_DQS_FULL -#define MV_DEBUG_RL_FULL -#define MV_DEBUG_WL_FULL -#endif - -#if defined(CONFIG_ARMADA_38X) -#include "ddr3_a38x.h" -#include "ddr3_a38x_topology.h" -#endif - -/* The following is a list of Marvell status */ -#define MV_ERROR (-1) -#define MV_OK (0x00) /* Operation succeeded */ -#define MV_FAIL (0x01) /* Operation failed */ -#define MV_BAD_VALUE (0x02) /* Illegal value (general) */ -#define MV_OUT_OF_RANGE (0x03) /* The value is out of range */ -#define MV_BAD_PARAM (0x04) /* Illegal parameter in function called */ -#define MV_BAD_PTR (0x05) /* Illegal pointer value */ -#define MV_BAD_SIZE (0x06) /* Illegal size */ -#define MV_BAD_STATE (0x07) /* Illegal state of state machine */ -#define MV_SET_ERROR (0x08) /* Set operation failed */ -#define MV_GET_ERROR (0x09) /* Get operation failed */ -#define MV_CREATE_ERROR (0x0a) /* Fail while creating an item */ -#define MV_NOT_FOUND (0x0b) /* Item not found */ -#define MV_NO_MORE (0x0c) /* No more items found */ -#define MV_NO_SUCH (0x0d) /* No such item */ -#define MV_TIMEOUT (0x0e) /* Time Out */ -#define MV_NO_CHANGE (0x0f) /* Parameter(s) is already in this value */ -#define MV_NOT_SUPPORTED (0x10) /* This request is not support */ -#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented*/ -#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized */ -#define MV_NO_RESOURCE (0x13) /* Resource not available (memory ...) */ -#define MV_FULL (0x14) /* Item is full (Queue or table etc...) */ -#define MV_EMPTY (0x15) /* Item is empty (Queue or table etc...) */ -#define MV_INIT_ERROR (0x16) /* Error occurred while INIT process */ -#define MV_HW_ERROR (0x17) /* Hardware error */ -#define MV_TX_ERROR (0x18) /* Transmit operation not succeeded */ -#define MV_RX_ERROR (0x19) /* Recieve operation not succeeded */ -#define MV_NOT_READY (0x1a) /* The other side is not ready yet */ -#define MV_ALREADY_EXIST (0x1b) /* Tried to create existing item */ -#define MV_OUT_OF_CPU_MEM (0x1c) /* Cpu memory allocation failed. */ -#define MV_NOT_STARTED (0x1d) /* Not started yet */ -#define MV_BUSY (0x1e) /* Item is busy. */ -#define MV_TERMINATE (0x1f) /* Item terminates it's work. */ -#define MV_NOT_ALIGNED (0x20) /* Wrong alignment */ -#define MV_NOT_ALLOWED (0x21) /* Operation NOT allowed */ -#define MV_WRITE_PROTECT (0x22) /* Write protected */ -#define MV_INVALID (int)(-1) - /* For checking function return values */ #define CHECK_STATUS(orig_func) \ { \ @@ -142,6 +32,14 @@ return status; \ } +#define GET_MAX_VALUE(x, y) \ + ((x) > (y)) ? (x) : (y) + +#define SUB_VERSION 0 + +/* max number of devices supported by driver */ +#define MAX_DEVICE_NUM 1 + enum log_level { MV_LOG_LEVEL_0, MV_LOG_LEVEL_1, @@ -150,28 +48,27 @@ enum log_level { }; /* Globals */ -extern u8 debug_training; +extern u8 debug_training, debug_calibration, debug_ddr4_centralization, + debug_tap_tuning, debug_dm_tuning; extern u8 is_reg_dump; extern u8 generic_init_controller; -extern u32 freq_val[]; +/* list of allowed frequency listed in order of enum hws_ddr_freq */ +extern u32 freq_val[DDR_FREQ_LAST]; extern u32 is_pll_old; extern struct cl_val_per_freq cas_latency_table[]; extern struct pattern_info pattern_table[]; extern struct cl_val_per_freq cas_write_latency_table[]; -extern u8 debug_training; extern u8 debug_centralization, debug_training_ip, debug_training_bist, debug_pbs, debug_training_static, debug_leveling; -extern u32 pipe_multicast_mask; extern struct hws_tip_config_func_db config_func_info[]; -extern u8 cs_mask_reg[]; extern u8 twr_mask_table[]; extern u8 cl_mask_table[]; extern u8 cwl_mask_table[]; extern u16 rfc_table[]; extern u32 speed_bin_table_t_rc[]; extern u32 speed_bin_table_t_rcd_t_rp[]; -extern u32 ck_delay, ck_delay_16; +extern u32 vref_init_val; extern u32 g_zpri_data; extern u32 g_znri_data; extern u32 g_zpri_ctrl; @@ -181,39 +78,28 @@ extern u32 g_znodt_data; extern u32 g_zpodt_ctrl; extern u32 g_znodt_ctrl; extern u32 g_dic; -extern u32 g_odt_config_2cs; -extern u32 g_odt_config_1cs; +extern u32 g_odt_config; extern u32 g_rtt_nom; +extern u32 g_rtt_wr; +extern u32 g_rtt_park; extern u8 debug_training_access; -extern u8 debug_training_a38x; extern u32 first_active_if; -extern enum hws_ddr_freq init_freq; -extern u32 delay_enable, ck_delay, ck_delay_16, ca_delay; +extern u32 delay_enable, ck_delay, ca_delay; extern u32 mask_tune_func; extern u32 rl_version; extern int rl_mid_freq_wa; extern u8 calibration_update_control; /* 2 external only, 1 is internal only */ extern enum hws_ddr_freq medium_freq; -extern u32 ck_delay, ck_delay_16; extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; -extern u32 first_active_if; -extern u32 mask_tune_func; -extern u32 freq_val[]; -extern enum hws_ddr_freq init_freq; extern enum hws_ddr_freq low_freq; -extern enum hws_ddr_freq medium_freq; -extern u8 generic_init_controller; extern enum auto_tune_stage training_stage; extern u32 is_pll_before_init; extern u32 is_adll_calib_before_init; extern u32 is_dfs_in_init; extern int wl_debug_delay; -extern u32 silicon_delay[HWS_MAX_DEVICE_NUM]; -extern u32 p_finger; -extern u32 n_finger; -extern u32 freq_val[DDR_FREQ_LIMIT]; +extern u32 silicon_delay[MAX_DEVICE_NUM]; extern u32 start_pattern, end_pattern; extern u32 phy_reg0_val; extern u32 phy_reg1_val; @@ -221,172 +107,93 @@ extern u32 phy_reg2_val; extern u32 phy_reg3_val; extern enum hws_pattern sweep_pattern; extern enum hws_pattern pbs_pattern; -extern u8 is_rzq6; -extern u32 znri_data_phy_val; -extern u32 zpri_data_phy_val; -extern u32 znri_ctrl_phy_val; -extern u32 zpri_ctrl_phy_val; -extern u8 debug_training_access; +extern u32 g_znri_data; +extern u32 g_zpri_data; +extern u32 g_znri_ctrl; +extern u32 g_zpri_ctrl; extern u32 finger_test, p_finger_start, p_finger_end, n_finger_start, n_finger_end, p_finger_step, n_finger_step; -extern u32 mode2_t; +extern u32 mode_2t; extern u32 xsb_validate_type; extern u32 xsb_validation_base_address; extern u32 odt_additional; extern u32 debug_mode; -extern u32 delay_enable; -extern u32 ca_delay; extern u32 debug_dunit; extern u32 clamp_tbl[]; -extern u32 freq_mask[HWS_MAX_DEVICE_NUM][DDR_FREQ_LIMIT]; -extern u32 start_pattern, end_pattern; +extern u32 freq_mask[MAX_DEVICE_NUM][DDR_FREQ_LAST]; extern u32 maxt_poll_tries; extern u32 is_bist_reset_bit; -extern u8 debug_training_bist; extern u8 vref_window_size[MAX_INTERFACE_NUM][MAX_BUS_NUM]; -extern u32 debug_mode; extern u32 effective_cs; extern int ddr3_tip_centr_skip_min_win_check; extern u32 *dq_map_table; -extern enum auto_tune_stage training_stage; -extern u8 debug_centralization; -extern u32 delay_enable; -extern u32 start_pattern, end_pattern; -extern u32 freq_val[DDR_FREQ_LIMIT]; extern u8 debug_training_hw_alg; -extern enum auto_tune_stage training_stage; -extern u8 debug_training_ip; -extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; -extern enum auto_tune_stage training_stage; -extern u32 effective_cs; - -extern u8 debug_leveling; -extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; -extern enum auto_tune_stage training_stage; -extern u32 rl_version; -extern struct cl_val_per_freq cas_latency_table[]; extern u32 start_xsb_offset; -extern u32 debug_mode; extern u32 odt_config; -extern u32 effective_cs; -extern u32 phy_reg1_val; -extern u8 debug_pbs; -extern u32 effective_cs; extern u16 mask_results_dq_reg_map[]; -extern enum hws_ddr_freq medium_freq; -extern u32 freq_val[]; -extern enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; -extern enum auto_tune_stage training_stage; -extern u32 debug_mode; -extern u32 *dq_map_table; -extern u32 vref; -extern struct cl_val_per_freq cas_latency_table[]; extern u32 target_freq; -extern struct hws_tip_config_func_db config_func_info[HWS_MAX_DEVICE_NUM]; -extern u32 clamp_tbl[]; -extern u32 init_freq; -/* list of allowed frequency listed in order of enum hws_ddr_freq */ -extern u32 freq_val[]; -extern u8 debug_training_static; -extern u32 first_active_if; +extern u32 dfs_low_freq; +extern u32 mem_size[]; + +extern u32 nominal_avs; +extern u32 extension_avs; + /* Prototypes */ +int ddr3_init(void); int ddr3_tip_enable_init_sequence(u32 dev_num); -int ddr3_tip_init_a38x(u32 dev_num, u32 board_id); - -int ddr3_hws_hw_training(void); -int ddr3_silicon_pre_init(void); +int ddr3_hws_hw_training(enum hws_algo_type algo_mode); +int mv_ddr_early_init(void); +int mv_ddr_early_init2(void); int ddr3_silicon_post_init(void); int ddr3_post_run_alg(void); int ddr3_if_ecc_enabled(void); void ddr3_new_tip_ecc_scrub(void); -void ddr3_print_version(void); -void ddr3_new_tip_dlb_config(void); -struct hws_topology_map *ddr3_get_topology_map(void); +void mv_ddr_ver_print(void); +struct mv_ddr_topology_map *mv_ddr_topology_map_get(void); int ddr3_if_ecc_enabled(void); int ddr3_tip_reg_write(u32 dev_num, u32 reg_addr, u32 data); int ddr3_tip_reg_read(u32 dev_num, u32 reg_addr, u32 *data, u32 reg_mask); int ddr3_silicon_get_ddr_target_freq(u32 *ddr_freq); -int ddr3_tip_a38x_get_freq_config(u8 dev_num, enum hws_ddr_freq freq, - struct hws_tip_freq_config_info - *freq_config_info); -int ddr3_a38x_update_topology_map(u32 dev_num, - struct hws_topology_map *topology_map); -int ddr3_tip_a38x_get_init_freq(int dev_num, enum hws_ddr_freq *freq); -int ddr3_tip_a38x_get_medium_freq(int dev_num, enum hws_ddr_freq *freq); -int ddr3_tip_a38x_if_read(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, u32 reg_addr, u32 *data, u32 mask); -int ddr3_tip_a38x_if_write(u8 dev_num, enum hws_access_type interface_access, - u32 if_id, u32 reg_addr, u32 data, u32 mask); -int ddr3_tip_a38x_get_device_info(u8 dev_num, - struct ddr3_device_info *info_ptr); - -int ddr3_tip_init_a38x(u32 dev_num, u32 board_id); int print_adll(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]); +int print_ph(u32 dev_num, u32 adll[MAX_INTERFACE_NUM * MAX_BUS_NUM]); +int read_phase_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + int reg_addr, u32 mask); +int write_leveling_value(u32 dev_num, u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 pup_ph_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], int reg_addr); int ddr3_tip_restore_dunit_regs(u32 dev_num); -void print_topology(struct hws_topology_map *topology_db); +void print_topology(struct mv_ddr_topology_map *tm); u32 mv_board_id_get(void); int ddr3_load_topology_map(void); -int ddr3_tip_init_specific_reg_config(u32 dev_num, - struct reg_data *reg_config_arr); -u32 ddr3_tip_get_init_freq(void); void ddr3_hws_set_log_level(enum ddr_lib_debug_block block, u8 level); +void mv_ddr_user_log_level_set(enum ddr_lib_debug_block block); int ddr3_tip_tune_training_params(u32 dev_num, struct tune_train_params *params); void get_target_freq(u32 freq_mode, u32 *ddr_freq, u32 *hclk_ps); -int ddr3_fast_path_dynamic_cs_size_config(u32 cs_ena); void ddr3_fast_path_static_cs_size_config(u32 cs_ena); -u32 ddr3_get_device_width(u32 cs); u32 mv_board_id_index_get(u32 board_id); -u32 mv_board_id_get(void); -u32 ddr3_get_bus_width(void); void ddr3_set_log_level(u32 n_log_level); -int ddr3_calc_mem_cs_size(u32 cs, u32 *cs_size); +int calc_cs_num(u32 dev_num, u32 if_id, u32 *cs_num); int hws_ddr3_cs_base_adr_calc(u32 if_id, u32 cs, u32 *cs_base_addr); int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode); int ddr3_tip_clean_pbs_result(u32 dev_num, enum pbs_dir pbs_mode); -int ddr3_tip_static_round_trip_arr_build(u32 dev_num, - struct trip_delay_element *table_ptr, - int is_wl, u32 *round_trip_delay_arr); - -u32 hws_ddr3_tip_max_cs_get(void); - -/* - * Accessor functions for the registers - */ -static inline void reg_write(u32 addr, u32 val) -{ - writel(val, INTER_REGS_BASE + addr); -} - -static inline u32 reg_read(u32 addr) -{ - return readl(INTER_REGS_BASE + addr); -} - -static inline void reg_bit_set(u32 addr, u32 mask) -{ - setbits_le32(INTER_REGS_BASE + addr, mask); -} - -static inline void reg_bit_clr(u32 addr, u32 mask) -{ - clrbits_le32(INTER_REGS_BASE + addr, mask); -} - +u32 mv_ddr_init_freq_get(void); +void mv_ddr_mc_config(void); +int mv_ddr_mc_init(void); +void mv_ddr_set_calib_controller(void); #endif /* _DDR3_INIT_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_logging_def.h b/drivers/ddr/marvell/a38x/ddr3_logging_def.h index fe929bb72a..ad9da1cfff 100644 --- a/drivers/ddr/marvell/a38x/ddr3_logging_def.h +++ b/drivers/ddr/marvell/a38x/ddr3_logging_def.h @@ -73,10 +73,14 @@ #endif #endif + /* Logging defines */ -#define DEBUG_LEVEL_TRACE 1 -#define DEBUG_LEVEL_INFO 2 -#define DEBUG_LEVEL_ERROR 3 +enum mv_ddr_debug_level { + DEBUG_LEVEL_TRACE = 1, + DEBUG_LEVEL_INFO = 2, + DEBUG_LEVEL_ERROR = 3, + DEBUG_LEVEL_LAST +}; enum ddr_lib_debug_block { DEBUG_BLOCK_STATIC, diff --git a/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h b/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h index ee41048c68..1e2260b871 100644 --- a/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h +++ b/drivers/ddr/marvell/a38x/ddr3_patterns_64bit.h @@ -6,6 +6,7 @@ #ifndef __DDR3_PATTERNS_64_H #define __DDR3_PATTERNS_64_H +#define FAB_OPT 21 /* * Patterns Declerations */ diff --git a/drivers/ddr/marvell/a38x/ddr3_topology_def.h b/drivers/ddr/marvell/a38x/ddr3_topology_def.h index eda2b13f90..1963bae3e6 100644 --- a/drivers/ddr/marvell/a38x/ddr3_topology_def.h +++ b/drivers/ddr/marvell/a38x/ddr3_topology_def.h @@ -6,8 +6,9 @@ #ifndef _DDR3_TOPOLOGY_DEF_H #define _DDR3_TOPOLOGY_DEF_H -/* TOPOLOGY */ +#define DEV_NUM_0 0 +/* TOPOLOGY */ enum hws_speed_bin { SPEED_BIN_DDR_800D, SPEED_BIN_DDR_800E, @@ -53,7 +54,8 @@ enum hws_ddr_freq { DDR_FREQ_900, DDR_FREQ_360, DDR_FREQ_1000, - DDR_FREQ_LIMIT + DDR_FREQ_LAST, + DDR_FREQ_SAR }; enum speed_bin_table_elements { diff --git a/drivers/ddr/marvell/a38x/ddr3_training.c b/drivers/ddr/marvell/a38x/ddr3_training.c index fee589b746..1f26d506da 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training.c +++ b/drivers/ddr/marvell/a38x/ddr3_training.c @@ -3,48 +3,35 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" - -#define GET_MAX_VALUE(x, y) \ - ((x) > (y)) ? (x) : (y) -#define CEIL_DIVIDE(x, y) \ - ((x - (x / y) * y) == 0) ? ((x / y) - 1) : (x / y) - -#define TIME_2_CLOCK_CYCLES CEIL_DIVIDE +#include "mv_ddr_common.h" #define GET_CS_FROM_MASK(mask) (cs_mask2_num[mask]) #define CS_CBE_VALUE(cs_num) (cs_cbe_reg[cs_num]) -#define TIMES_9_TREFI_CYCLES 0x8 - u32 window_mem_addr = 0; u32 phy_reg0_val = 0; u32 phy_reg1_val = 8; u32 phy_reg2_val = 0; -u32 phy_reg3_val = 0xa; -enum hws_ddr_freq init_freq = DDR_FREQ_667; +u32 phy_reg3_val = PARAM_UNDEFINED; enum hws_ddr_freq low_freq = DDR_FREQ_LOW_FREQ; enum hws_ddr_freq medium_freq; u32 debug_dunit = 0; u32 odt_additional = 1; u32 *dq_map_table = NULL; + +/* in case of ddr4 do not run ddr3_tip_write_additional_odt_setting function - mc odt always 'on' + * in ddr4 case the terminations are rttWR and rttPARK and the odt must be always 'on' 0x1498 = 0xf + */ u32 odt_config = 1; -#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ALLEYCAT3) || \ - defined(CONFIG_ARMADA_39X) -u32 is_pll_before_init = 0, is_adll_calib_before_init = 0, is_dfs_in_init = 0; -u32 dfs_low_freq = 130; -#else +u32 nominal_avs; +u32 extension_avs; + u32 is_pll_before_init = 0, is_adll_calib_before_init = 1, is_dfs_in_init = 0; -u32 dfs_low_freq = 100; -#endif -u32 g_rtt_nom_c_s0, g_rtt_nom_c_s1; +u32 dfs_low_freq; + +u32 g_rtt_nom_cs0, g_rtt_nom_cs1; u8 calibration_update_control; /* 2 external only, 1 is internal only */ enum hws_result training_result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]; @@ -55,7 +42,7 @@ u32 finger_test = 0, p_finger_start = 11, p_finger_end = 64, u32 clamp_tbl[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; /* Initiate to 0xff, this variable is define by user in debug mode */ -u32 mode2_t = 0xff; +u32 mode_2t = 0xff; u32 xsb_validate_type = 0; u32 xsb_validation_base_address = 0xf000; u32 first_active_if = 0; @@ -70,25 +57,41 @@ int rl_mid_freq_wa = 0; u32 effective_cs = 0; +u32 vref_init_val = 0x4; +u32 ck_delay = PARAM_UNDEFINED; + +/* Design guidelines parameters */ +u32 g_zpri_data = PARAM_UNDEFINED; /* controller data - P drive strength */ +u32 g_znri_data = PARAM_UNDEFINED; /* controller data - N drive strength */ +u32 g_zpri_ctrl = PARAM_UNDEFINED; /* controller C/A - P drive strength */ +u32 g_znri_ctrl = PARAM_UNDEFINED; /* controller C/A - N drive strength */ + +u32 g_zpodt_data = PARAM_UNDEFINED; /* controller data - P ODT */ +u32 g_znodt_data = PARAM_UNDEFINED; /* controller data - N ODT */ +u32 g_zpodt_ctrl = PARAM_UNDEFINED; /* controller data - P ODT */ +u32 g_znodt_ctrl = PARAM_UNDEFINED; /* controller data - N ODT */ + +u32 g_odt_config = PARAM_UNDEFINED; +u32 g_rtt_nom = PARAM_UNDEFINED; +u32 g_rtt_wr = PARAM_UNDEFINED; +u32 g_dic = PARAM_UNDEFINED; +u32 g_rtt_park = PARAM_UNDEFINED; + u32 mask_tune_func = (SET_MEDIUM_FREQ_MASK_BIT | WRITE_LEVELING_MASK_BIT | LOAD_PATTERN_2_MASK_BIT | READ_LEVELING_MASK_BIT | - SET_TARGET_FREQ_MASK_BIT | WRITE_LEVELING_TF_MASK_BIT | + SET_TARGET_FREQ_MASK_BIT | + WRITE_LEVELING_TF_MASK_BIT | READ_LEVELING_TF_MASK_BIT | - CENTRALIZATION_RX_MASK_BIT | CENTRALIZATION_TX_MASK_BIT); - -void ddr3_print_version(void) -{ - printf(DDR3_TIP_VERSION_STRING); -} + CENTRALIZATION_RX_MASK_BIT | + CENTRALIZATION_TX_MASK_BIT); static int ddr3_tip_ddr3_training_main_flow(u32 dev_num); static int ddr3_tip_write_odt(u32 dev_num, enum hws_access_type access_type, u32 if_id, u32 cl_value, u32 cwl_value); static int ddr3_tip_ddr3_auto_tune(u32 dev_num); -static int is_bus_access_done(u32 dev_num, u32 if_id, - u32 dunit_reg_adrr, u32 bit); + #ifdef ODT_TEST_SUPPORT static int odt_test(u32 dev_num, enum hws_algo_type algo_type); #endif @@ -98,7 +101,7 @@ int adll_calibration(u32 dev_num, enum hws_access_type access_type, static int ddr3_tip_set_timing(u32 dev_num, enum hws_access_type access_type, u32 if_id, enum hws_ddr_freq frequency); -static struct page_element page_param[] = { +static struct page_element page_tbl[] = { /* * 8bits 16 bits * page-size(K) page-size(K) mask @@ -111,16 +114,30 @@ static struct page_element page_param[] = { /* 2G */ { 1, 2, 4}, /* 4G */ - { 2, 2, 5} + { 2, 2, 5}, /* 8G */ + {0, 0, 0}, /* TODO: placeholder for 16-Mbit die capacity */ + {0, 0, 0}, /* TODO: placeholder for 32-Mbit die capacity */ + {0, 0, 0}, /* TODO: placeholder for 12-Mbit die capacity */ + {0, 0, 0} /* TODO: placeholder for 24-Mbit die capacity */ + }; -static u8 mem_size_config[MEM_SIZE_LAST] = { +struct page_element *mv_ddr_page_tbl_get(void) +{ + return &page_tbl[0]; +} + +static u8 mem_size_config[MV_DDR_DIE_CAP_LAST] = { 0x2, /* 512Mbit */ 0x3, /* 1Gbit */ 0x0, /* 2Gbit */ 0x4, /* 4Gbit */ - 0x5 /* 8Gbit */ + 0x5, /* 8Gbit */ + 0x0, /* TODO: placeholder for 16-Mbit die capacity */ + 0x0, /* TODO: placeholder for 32-Mbit die capacity */ + 0x0, /* TODO: placeholder for 12-Mbit die capacity */ + 0x0 /* TODO: placeholder for 24-Mbit die capacity */ }; static u8 cs_mask2_num[] = { 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 }; @@ -179,10 +196,14 @@ static struct reg_data odpg_default_value[] = { {0x16fc, 0x0, MASK_ALL_BITS} }; -static int ddr3_tip_bus_access(u32 dev_num, enum hws_access_type interface_access, - u32 if_id, enum hws_access_type phy_access, - u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, - u32 data_value, enum hws_operation oper_type); +/* MR cmd and addr definitions */ +struct mv_ddr_mr_data mr_data[] = { + {MRS0_CMD, MR0_REG}, + {MRS1_CMD, MR1_REG}, + {MRS2_CMD, MR2_REG}, + {MRS3_CMD, MR3_REG} +}; + static int ddr3_tip_pad_inv(u32 dev_num, u32 if_id); static int ddr3_tip_rank_control(u32 dev_num, u32 if_id); @@ -192,12 +213,41 @@ static int ddr3_tip_rank_control(u32 dev_num, u32 if_id); int ddr3_tip_tune_training_params(u32 dev_num, struct tune_train_params *params) { - if (params->ck_delay != -1) + if (params->ck_delay != PARAM_UNDEFINED) ck_delay = params->ck_delay; - if (params->ck_delay_16 != -1) - ck_delay_16 = params->ck_delay_16; - if (params->phy_reg3_val != -1) + if (params->phy_reg3_val != PARAM_UNDEFINED) phy_reg3_val = params->phy_reg3_val; + if (params->g_rtt_nom != PARAM_UNDEFINED) + g_rtt_nom = params->g_rtt_nom; + if (params->g_rtt_wr != PARAM_UNDEFINED) + g_rtt_wr = params->g_rtt_wr; + if (params->g_dic != PARAM_UNDEFINED) + g_dic = params->g_dic; + if (params->g_odt_config != PARAM_UNDEFINED) + g_odt_config = params->g_odt_config; + if (params->g_zpri_data != PARAM_UNDEFINED) + g_zpri_data = params->g_zpri_data; + if (params->g_znri_data != PARAM_UNDEFINED) + g_znri_data = params->g_znri_data; + if (params->g_zpri_ctrl != PARAM_UNDEFINED) + g_zpri_ctrl = params->g_zpri_ctrl; + if (params->g_znri_ctrl != PARAM_UNDEFINED) + g_znri_ctrl = params->g_znri_ctrl; + if (params->g_zpodt_data != PARAM_UNDEFINED) + g_zpodt_data = params->g_zpodt_data; + if (params->g_znodt_data != PARAM_UNDEFINED) + g_znodt_data = params->g_znodt_data; + if (params->g_zpodt_ctrl != PARAM_UNDEFINED) + g_zpodt_ctrl = params->g_zpodt_ctrl; + if (params->g_znodt_ctrl != PARAM_UNDEFINED) + g_znodt_ctrl = params->g_znodt_ctrl; + if (params->g_rtt_park != PARAM_UNDEFINED) + g_rtt_park = params->g_rtt_park; + + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, + ("DGL parameters: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n", + g_zpri_data, g_znri_data, g_zpri_ctrl, g_znri_ctrl, g_zpodt_data, g_znodt_data, + g_zpodt_ctrl, g_znodt_ctrl, g_rtt_nom, g_dic, g_odt_config, g_rtt_wr)); return MV_OK; } @@ -209,34 +259,34 @@ int ddr3_tip_configure_cs(u32 dev_num, u32 if_id, u32 cs_num, u32 enable) { u32 data, addr_hi, data_high; u32 mem_index; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (enable == 1) { data = (tm->interface_params[if_id].bus_width == - BUS_WIDTH_8) ? 0 : 1; + MV_DDR_DEV_WIDTH_8BIT) ? 0 : 1; CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_ACCESS_CONTROL_REG, (data << (cs_num * 4)), + SDRAM_ADDR_CTRL_REG, (data << (cs_num * 4)), 0x3 << (cs_num * 4))); mem_index = tm->interface_params[if_id].memory_size; addr_hi = mem_size_config[mem_index] & 0x3; CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_ACCESS_CONTROL_REG, + SDRAM_ADDR_CTRL_REG, (addr_hi << (2 + cs_num * 4)), 0x3 << (2 + cs_num * 4))); data_high = (mem_size_config[mem_index] & 0x4) >> 2; CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_ACCESS_CONTROL_REG, + SDRAM_ADDR_CTRL_REG, data_high << (20 + cs_num), 1 << (20 + cs_num))); /* Enable Address Select Mode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_ACCESS_CONTROL_REG, 1 << (16 + cs_num), + SDRAM_ADDR_CTRL_REG, 1 << (16 + cs_num), 1 << (16 + cs_num))); } switch (cs_num) { @@ -245,13 +295,13 @@ int ddr3_tip_configure_cs(u32 dev_num, u32 if_id, u32 cs_num, u32 enable) case 2: CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - DDR_CONTROL_LOW_REG, (enable << (cs_num + 11)), + DUNIT_CTRL_LOW_REG, (enable << (cs_num + 11)), 1 << (cs_num + 11))); break; case 3: CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - DDR_CONTROL_LOW_REG, (enable << 15), 1 << 15)); + DUNIT_CTRL_LOW_REG, (enable << 15), 1 << 15)); break; } @@ -261,17 +311,18 @@ int ddr3_tip_configure_cs(u32 dev_num, u32 if_id, u32 cs_num, u32 enable) /* * Calculate number of CS */ -static int calc_cs_num(u32 dev_num, u32 if_id, u32 *cs_num) +int calc_cs_num(u32 dev_num, u32 if_id, u32 *cs_num) { u32 cs; u32 bus_cnt; u32 cs_count; u32 cs_bitmask; u32 curr_cs_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); cs_count = 0; cs_bitmask = tm->interface_params[if_id]. as_bus_params[bus_cnt].cs_bitmask; @@ -302,21 +353,18 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ { u32 if_id; u32 cs_num; - u32 t_refi = 0, t_hclk = 0, t_ckclk = 0, t_faw = 0, t_pd = 0, - t_wr = 0, t2t = 0, txpdll = 0; - u32 data_value = 0, bus_width = 0, page_size = 0, cs_cnt = 0, + u32 t_ckclk = 0, t_wr = 0, t2t = 0; + u32 data_value = 0, cs_cnt = 0, mem_mask = 0, bus_index = 0; enum hws_speed_bin speed_bin_index = SPEED_BIN_DDR_2133N; - enum hws_mem_size memory_size = MEM_2G; - enum hws_ddr_freq freq = init_freq; - enum hws_timing timing; u32 cs_mask = 0; u32 cl_value = 0, cwl_val = 0; - u32 refresh_interval_cnt = 0, bus_cnt = 0, adll_tap = 0; + u32 bus_cnt = 0, adll_tap = 0; enum hws_access_type access_type = ACCESS_TYPE_UNICAST; u32 data_read[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); - u32 odt_config = g_odt_config_2cs; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + enum hws_ddr_freq freq = tm->interface_params[0].memory_freq; DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("Init_controller, do_mrs_phy=%d, is_ctrl64_bit=%d\n", @@ -329,14 +377,14 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ if (generic_init_controller == 1) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("active IF %d\n", if_id)); mem_mask = 0; for (bus_index = 0; - bus_index < GET_TOPOLOGY_NUM_OF_BUSES(); + bus_index < octets_per_if_num; bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index); mem_mask |= tm->interface_params[if_id]. as_bus_params[bus_index].mirror_enable_bitmask; @@ -345,57 +393,46 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ if (mem_mask != 0) { CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, - if_id, CS_ENABLE_REG, 0, + if_id, DUAL_DUNIT_CFG_REG, 0, 0x8)); } - memory_size = - tm->interface_params[if_id]. - memory_size; speed_bin_index = tm->interface_params[if_id]. speed_bin_index; - freq = init_freq; - t_refi = - (tm->interface_params[if_id]. - interface_temp == - HWS_TEMP_HIGH) ? TREFI_HIGH : TREFI_LOW; - t_refi *= 1000; /* psec */ - DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, - ("memy_size %d speed_bin_ind %d freq %d t_refi %d\n", - memory_size, speed_bin_index, freq, - t_refi)); - /* HCLK & CK CLK in 2:1[ps] */ + /* t_ckclk is external clock */ t_ckclk = (MEGA / freq_val[freq]); - /* t_hclk is internal clock */ - t_hclk = 2 * t_ckclk; - refresh_interval_cnt = t_refi / t_hclk; /* no units */ - bus_width = - (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) - == 1) ? (16) : (32); - - if (init_cntr_prm->is_ctrl64_bit) - bus_width = 64; - data_value = - (refresh_interval_cnt | 0x4000 | - ((bus_width == - 32) ? 0x8000 : 0) | 0x1000000) & ~(1 << 26); + if (MV_DDR_IS_HALF_BUS_DRAM_MODE(tm->bus_act_mask, octets_per_if_num)) + data_value = (0x4000 | 0 | 0x1000000) & ~(1 << 26); + else + data_value = (0x4000 | 0x8000 | 0x1000000) & ~(1 << 26); /* Interface Bus Width */ /* SRMode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, data_value, - 0x100ffff)); + SDRAM_CFG_REG, data_value, + 0x100c000)); /* Interleave first command pre-charge enable (TBD) */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_OPEN_PAGE_CONTROL_REG, (1 << 10), + SDRAM_OPEN_PAGES_CTRL_REG, (1 << 10), (1 << 10))); + /* Reset divider_b assert -> de-assert */ + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, + SDRAM_CFG_REG, + 0x0 << PUP_RST_DIVIDER_OFFS, + PUP_RST_DIVIDER_MASK << PUP_RST_DIVIDER_OFFS)); + + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, + SDRAM_CFG_REG, + 0x1 << PUP_RST_DIVIDER_OFFS, + PUP_RST_DIVIDER_MASK << PUP_RST_DIVIDER_OFFS)); + /* PHY configuration */ /* * Postamble Length = 1.5cc, Addresscntl to clk skew @@ -403,12 +440,12 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, 0x28, 0x3e)); + DRAM_PHY_CFG_REG, 0x28, 0x3e)); if (init_cntr_prm->is_ctrl64_bit) { /* positive edge */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, 0x0, + DRAM_PHY_CFG_REG, 0x0, 0xff80)); } @@ -416,17 +453,24 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ /* Xbar Read buffer select (for Internal access) */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, 0x1200c, + MAIN_PADS_CAL_MACH_CTRL_REG, 0x1200c, 0x7dffe01c)); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, + MAIN_PADS_CAL_MACH_CTRL_REG, calibration_update_control << 3, 0x3 << 3)); /* Pad calibration control - enable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, 0x1, 0x1)); + MAIN_PADS_CAL_MACH_CTRL_REG, 0x1, 0x1)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) { + /* DDR3 rank ctrl \96 part of the generic code */ + /* CS1 mirroring enable + w/a for JIRA DUNIT-14581 */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + DDR3_RANK_CTRL_REG, 0x27, MASK_ALL_BITS)); + } cs_mask = 0; data_value = 0x7; @@ -437,40 +481,19 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ * 2) Bus_width * 3) CS# * 4) Page Number - * 5) t_faw * Per Dunit get from the Map_topology the parameters: * Bus_width - * t_faw is per Dunit not per CS */ - page_size = - (tm->interface_params[if_id]. - bus_width == - BUS_WIDTH_8) ? page_param[memory_size]. - page_size_8bit : page_param[memory_size]. - page_size_16bit; - - t_faw = - (page_size == 1) ? speed_bin_table(speed_bin_index, - SPEED_BIN_TFAW1K) - : speed_bin_table(speed_bin_index, - SPEED_BIN_TFAW2K); - - data_value = TIME_2_CLOCK_CYCLES(t_faw, t_ckclk); - data_value = data_value << 24; - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - SDRAM_ACCESS_CONTROL_REG, data_value, - 0x7f000000)); data_value = (tm->interface_params[if_id]. - bus_width == BUS_WIDTH_8) ? 0 : 1; + bus_width == MV_DDR_DEV_WIDTH_8BIT) ? 0 : 1; /* create merge cs mask for all cs available in dunit */ for (bus_cnt = 0; - bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); + bus_cnt < octets_per_if_num; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); cs_mask |= tm->interface_params[if_id]. as_bus_params[bus_cnt].cs_bitmask; @@ -509,9 +532,11 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("cl_value 0x%x cwl_val 0x%x\n", cl_value, cwl_val)); - t_wr = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, - SPEED_BIN_TWR), - t_ckclk); + + t_wr = time_to_nclk(speed_bin_table + (speed_bin_index, + SPEED_BIN_TWR), t_ckclk); + data_value = ((cl_mask_table[cl_value] & 0x1) << 2) | ((cl_mask_table[cl_value] & 0xe) << 3); @@ -521,9 +546,8 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ (0x7 << 4) | (1 << 2))); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - MR0_REG, twr_mask_table[t_wr + 1] << 9, - (0x7 << 9))); - + MR0_REG, twr_mask_table[t_wr] << 9, + 0x7 << 9)); /* * MR1: Set RTT and DIC Design GL values @@ -544,7 +568,8 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ data_value |= ((tm->interface_params[if_id]. interface_temp == - HWS_TEMP_HIGH) ? (1 << 7) : 0); + MV_DDR_TEMP_HIGH) ? (1 << 7) : 0); + data_value |= g_rtt_wr; CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, MR2_REG, data_value, @@ -556,53 +581,41 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ cl_value, cwl_val); ddr3_tip_set_timing(dev_num, access_type, if_id, freq); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - DUNIT_CONTROL_HIGH_REG, 0x177, - 0x1000177)); - - if (init_cntr_prm->is_ctrl64_bit) { - /* disable 0.25 cc delay */ + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + DUNIT_CTRL_HIGH_REG, 0x1000119, + 0x100017F)); + } else { CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DUNIT_CONTROL_HIGH_REG, 0x0, - 0x800)); + DUNIT_CTRL_HIGH_REG, 0x600177 | + (init_cntr_prm->is_ctrl64_bit ? + CPU_INTERJECTION_ENA_SPLIT_ENA << CPU_INTERJECTION_ENA_OFFS : + CPU_INTERJECTION_ENA_SPLIT_DIS << CPU_INTERJECTION_ENA_OFFS), + 0x1600177 | CPU_INTERJECTION_ENA_MASK << + CPU_INTERJECTION_ENA_OFFS)); } /* reset bit 7 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DUNIT_CONTROL_HIGH_REG, + DUNIT_CTRL_HIGH_REG, (init_cntr_prm->msys_init << 7), (1 << 7))); - /* calculate number of CS (per interface) */ - CHECK_STATUS(calc_cs_num - (dev_num, if_id, &cs_num)); - timing = tm->interface_params[if_id].timing; - - if (mode2_t != 0xff) { - t2t = mode2_t; - } else if (timing != HWS_TIM_DEFAULT) { - /* Board topology map is forcing timing */ - t2t = (timing == HWS_TIM_2T) ? 1 : 0; + if (mode_2t != 0xff) { + t2t = mode_2t; } else { + /* calculate number of CS (per interface) */ + CHECK_STATUS(calc_cs_num + (dev_num, if_id, &cs_num)); t2t = (cs_num == 1) ? 0 : 1; } CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DDR_CONTROL_LOW_REG, t2t << 3, + DUNIT_CTRL_LOW_REG, t2t << 3, 0x3 << 3)); - /* move the block to ddr3_tip_set_timing - start */ - t_pd = TIMES_9_TREFI_CYCLES; - txpdll = GET_MAX_VALUE(t_ckclk * 10, - speed_bin_table(speed_bin_index, - SPEED_BIN_TXPDLL)); - txpdll = CEIL_DIVIDE((txpdll - 1), t_ckclk); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - DDR_TIMING_REG, txpdll << 4 | t_pd, - 0x1f << 4 | 0xf)); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, DDR_TIMING_REG, 0x28 << 9, 0x3f << 9)); @@ -614,31 +627,38 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ /* AUTO_ZQC_TIMING */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - TIMING_REG, (AUTO_ZQC_TIMING | (2 << 20)), + ZQC_CFG_REG, (AUTO_ZQC_TIMING | (2 << 20)), 0x3fffff)); CHECK_STATUS(ddr3_tip_if_read (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, data_read, 0x30)); + DRAM_PHY_CFG_REG, data_read, 0x30)); data_value = (data_read[if_id] == 0) ? (1 << 11) : 0; CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DUNIT_CONTROL_HIGH_REG, data_value, + DUNIT_CTRL_HIGH_REG, data_value, (1 << 11))); /* Set Active control for ODT write transactions */ - if (cs_num == 1) - odt_config = g_odt_config_1cs; CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, 0x1494, odt_config, + PARAM_NOT_CARE, 0x1494, g_odt_config, MASK_ALL_BITS)); + + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) == MV_TIP_REV_3) { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + 0x14a8, 0x900, 0x900)); + /* wa: controls control sub-phy outputs floating during self-refresh */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + 0x16d0, 0, 0x8000)); + } } - } else { } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_rank_control(dev_num, if_id)); if (init_cntr_prm->do_mrs_phy) { @@ -648,14 +668,13 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ /* Pad calibration control - disable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, 0x0, 0x1)); + MAIN_PADS_CAL_MACH_CTRL_REG, 0x0, 0x1)); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - CALIB_MACHINE_CTRL_REG, + MAIN_PADS_CAL_MACH_CTRL_REG, calibration_update_control << 3, 0x3 << 3)); } - CHECK_STATUS(ddr3_tip_enable_init_sequence(dev_num)); if (delay_enable != 0) { adll_tap = MEGA / (freq_val[freq] * 64); @@ -666,67 +685,70 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ } /* - * Load Topology map + * Rank Control Flow */ -int hws_ddr3_tip_load_topology_map(u32 dev_num, struct hws_topology_map *tm) +static int ddr3_tip_rev2_rank_control(u32 dev_num, u32 if_id) { - enum hws_speed_bin speed_bin_index; - enum hws_ddr_freq freq = DDR_FREQ_LIMIT; - u32 if_id; + u32 data_value = 0, bus_cnt = 0; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - freq_val[DDR_FREQ_LOW_FREQ] = dfs_low_freq; - tm = ddr3_get_topology_map(); - CHECK_STATUS(ddr3_tip_get_first_active_if - ((u8)dev_num, tm->if_act_mask, - &first_active_if)); - DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, - ("board IF_Mask=0x%x num_of_bus_per_interface=0x%x\n", - tm->if_act_mask, - tm->num_of_bus_per_interface)); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + data_value |= tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask; - /* - * if CL, CWL values are missing in topology map, then fill them - * according to speedbin tables - */ - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - speed_bin_index = - tm->interface_params[if_id].speed_bin_index; - /* TBD memory frequency of interface 0 only is used ! */ - freq = tm->interface_params[first_active_if].memory_freq; + if (tm->interface_params[if_id].as_bus_params[bus_cnt]. + mirror_enable_bitmask == 1) { + /* + * Check mirror_enable_bitmask + * If it is enabled, CS + 4 bit in a word to be '1' + */ + if ((tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask & 0x1) != 0) { + data_value |= tm->interface_params[if_id]. + as_bus_params[bus_cnt]. + mirror_enable_bitmask << 4; + } - DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, - ("speed_bin_index =%d freq=%d cl=%d cwl=%d\n", - speed_bin_index, freq_val[freq], - tm->interface_params[if_id]. - cas_l, - tm->interface_params[if_id]. - cas_wl)); + if ((tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask & 0x2) != 0) { + data_value |= tm->interface_params[if_id]. + as_bus_params[bus_cnt]. + mirror_enable_bitmask << 5; + } - if (tm->interface_params[if_id].cas_l == 0) { - tm->interface_params[if_id].cas_l = - cas_latency_table[speed_bin_index].cl_val[freq]; - } + if ((tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask & 0x4) != 0) { + data_value |= tm->interface_params[if_id]. + as_bus_params[bus_cnt]. + mirror_enable_bitmask << 6; + } - if (tm->interface_params[if_id].cas_wl == 0) { - tm->interface_params[if_id].cas_wl = - cas_write_latency_table[speed_bin_index].cl_val[freq]; + if ((tm->interface_params[if_id].as_bus_params[bus_cnt]. + cs_bitmask & 0x8) != 0) { + data_value |= tm->interface_params[if_id]. + as_bus_params[bus_cnt]. + mirror_enable_bitmask << 7; + } } } + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, DDR3_RANK_CTRL_REG, + data_value, 0xff)); + return MV_OK; } -/* - * RANK Control Flow - */ -static int ddr3_tip_rank_control(u32 dev_num, u32 if_id) +static int ddr3_tip_rev3_rank_control(u32 dev_num, u32 if_id) { u32 data_value = 0, bus_cnt; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - for (bus_cnt = 1; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 1; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); if ((tm->interface_params[if_id]. as_bus_params[0].cs_bitmask != tm->interface_params[if_id]. @@ -746,29 +768,38 @@ static int ddr3_tip_rank_control(u32 dev_num, u32 if_id) as_bus_params[0].mirror_enable_bitmask << 4; CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, RANK_CTRL_REG, + (dev_num, ACCESS_TYPE_UNICAST, if_id, DDR3_RANK_CTRL_REG, data_value, 0xff)); return MV_OK; } +static int ddr3_tip_rank_control(u32 dev_num, u32 if_id) +{ + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) == MV_TIP_REV_2) + return ddr3_tip_rev2_rank_control(dev_num, if_id); + else + return ddr3_tip_rev3_rank_control(dev_num, if_id); +} + /* * PAD Inverse Flow */ static int ddr3_tip_pad_inv(u32 dev_num, u32 if_id) { u32 bus_cnt, data_value, ck_swap_pup_ctrl; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); if (tm->interface_params[if_id]. as_bus_params[bus_cnt].is_dqs_swap == 1) { /* dqs swap */ ddr3_tip_bus_read_modify_write(dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt, DDR_PHY_DATA, - PHY_CONTROL_PHY_REG, 0xc0, + PHY_CTRL_PHY_REG, 0xc0, 0xc0); } @@ -785,7 +816,7 @@ static int ddr3_tip_pad_inv(u32 dev_num, u32 if_id) ddr3_tip_bus_read_modify_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ck_swap_pup_ctrl, DDR_PHY_CONTROL, - PHY_CONTROL_PHY_REG, + PHY_CTRL_PHY_REG, data_value, data_value); } } @@ -793,12 +824,147 @@ static int ddr3_tip_pad_inv(u32 dev_num, u32 if_id) return MV_OK; } +/* + * Algorithm Parameters Validation + */ +int ddr3_tip_validate_algo_var(u32 value, u32 fail_value, char *var_name) +{ + if (value == fail_value) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("Error: %s is not initialized (Algo Components Validation)\n", + var_name)); + return 0; + } + + return 1; +} + +int ddr3_tip_validate_algo_ptr(void *ptr, void *fail_value, char *ptr_name) +{ + if (ptr == fail_value) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("Error: %s is not initialized (Algo Components Validation)\n", + ptr_name)); + return 0; + } + + return 1; +} + +int ddr3_tip_validate_algo_components(u8 dev_num) +{ + int status = 1; + + /* Check DGL parameters*/ + status &= ddr3_tip_validate_algo_var(ck_delay, PARAM_UNDEFINED, "ck_delay"); + status &= ddr3_tip_validate_algo_var(phy_reg3_val, PARAM_UNDEFINED, "phy_reg3_val"); + status &= ddr3_tip_validate_algo_var(g_rtt_nom, PARAM_UNDEFINED, "g_rtt_nom"); + status &= ddr3_tip_validate_algo_var(g_dic, PARAM_UNDEFINED, "g_dic"); + status &= ddr3_tip_validate_algo_var(odt_config, PARAM_UNDEFINED, "odt_config"); + status &= ddr3_tip_validate_algo_var(g_zpri_data, PARAM_UNDEFINED, "g_zpri_data"); + status &= ddr3_tip_validate_algo_var(g_znri_data, PARAM_UNDEFINED, "g_znri_data"); + status &= ddr3_tip_validate_algo_var(g_zpri_ctrl, PARAM_UNDEFINED, "g_zpri_ctrl"); + status &= ddr3_tip_validate_algo_var(g_znri_ctrl, PARAM_UNDEFINED, "g_znri_ctrl"); + status &= ddr3_tip_validate_algo_var(g_zpodt_data, PARAM_UNDEFINED, "g_zpodt_data"); + status &= ddr3_tip_validate_algo_var(g_znodt_data, PARAM_UNDEFINED, "g_znodt_data"); + status &= ddr3_tip_validate_algo_var(g_zpodt_ctrl, PARAM_UNDEFINED, "g_zpodt_ctrl"); + status &= ddr3_tip_validate_algo_var(g_znodt_ctrl, PARAM_UNDEFINED, "g_znodt_ctrl"); + + /* Check functions pointers */ + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_dunit_mux_select_func, + NULL, "tip_dunit_mux_select_func"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_dunit_write, + NULL, "mv_ddr_dunit_write"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_dunit_read, + NULL, "mv_ddr_dunit_read"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_phy_write, + NULL, "mv_ddr_phy_write"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].mv_ddr_phy_read, + NULL, "mv_ddr_phy_read"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_get_freq_config_info_func, + NULL, "tip_get_freq_config_info_func"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_set_freq_divider_func, + NULL, "tip_set_freq_divider_func"); + status &= ddr3_tip_validate_algo_ptr(config_func_info[dev_num].tip_get_clock_ratio, + NULL, "tip_get_clock_ratio"); + + status &= ddr3_tip_validate_algo_ptr(dq_map_table, NULL, "dq_map_table"); + status &= ddr3_tip_validate_algo_var(dfs_low_freq, 0, "dfs_low_freq"); + + return (status == 1) ? MV_OK : MV_NOT_INITIALIZED; +} + + +int ddr3_pre_algo_config(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* Set Bus3 ECC training mode */ + if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) { + /* Set Bus3 ECC MUX */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + DRAM_PINS_MUX_REG, 0x100, 0x100)); + } + + /* Set regular ECC training mode (bus4 and bus 3) */ + if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) || + (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) || + (DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask))) { + /* Enable ECC Write MUX */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + TRAINING_SW_2_REG, 0x100, 0x100)); + /* General ECC enable */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + SDRAM_CFG_REG, 0x40000, 0x40000)); + /* Disable Read Data ECC MUX */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + TRAINING_SW_2_REG, 0x0, 0x2)); + } + + return MV_OK; +} + +int ddr3_post_algo_config(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + int status; + + status = ddr3_post_run_alg(); + if (MV_OK != status) { + printf("DDR3 Post Run Alg - FAILED 0x%x\n", status); + return status; + } + + /* Un_set ECC training mode */ + if ((DDR3_IS_ECC_PUP4_MODE(tm->bus_act_mask)) || + (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) || + (DDR3_IS_ECC_PUP8_MODE(tm->bus_act_mask))) { + /* Disable ECC Write MUX */ + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + TRAINING_SW_2_REG, 0x0, 0x100)); + /* General ECC and Bus3 ECC MUX remains enabled */ + } + + return MV_OK; +} + /* * Run Training Flow */ int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type) { - int ret = MV_OK, ret_tune = MV_OK; + int status = MV_OK; + + status = ddr3_pre_algo_config(); + if (MV_OK != status) { + printf("DDR3 Pre Algo Config - FAILED 0x%x\n", status); + return status; + } #ifdef ODT_TEST_SUPPORT if (finger_test == 1) @@ -806,16 +972,23 @@ int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type) #endif if (algo_type == ALGO_TYPE_DYNAMIC) { - ret = ddr3_tip_ddr3_auto_tune(dev_num); - } else { + status = ddr3_tip_ddr3_auto_tune(dev_num); } - if (ret != MV_OK) { + if (status != MV_OK) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, - ("Run_alg: tuning failed %d\n", ret_tune)); + ("******** DRAM initialization Failed (res 0x%x) ********\n", + status)); + return status; } - return ret; + status = ddr3_post_algo_config(); + if (MV_OK != status) { + printf("DDR3 Post Algo Config - FAILED 0x%x\n", status); + return status; + } + + return status; } #ifdef ODT_TEST_SUPPORT @@ -835,19 +1008,16 @@ static int odt_test(u32 dev_num, enum hws_algo_type algo_type) DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("pfinger_val %d nfinger_val %d\n", pfinger_val, nfinger_val)); - p_finger = pfinger_val; - n_finger = nfinger_val; + /* + * TODO: need to check the correctness + * of the following two lines. + */ + g_zpodt_data = pfinger_val; + g_znodt_data = nfinger_val; } if (algo_type == ALGO_TYPE_DYNAMIC) { ret = ddr3_tip_ddr3_auto_tune(dev_num); - } else { - /* - * Frequency per interface is not relevant, - * only interface 0 - */ - ret = ddr3_tip_run_static_alg(dev_num, - init_freq); } } } @@ -867,12 +1037,8 @@ static int odt_test(u32 dev_num, enum hws_algo_type algo_type) */ int hws_ddr3_tip_select_ddr_controller(u32 dev_num, int enable) { - if (config_func_info[dev_num].tip_dunit_mux_select_func != NULL) { - return config_func_info[dev_num]. - tip_dunit_mux_select_func((u8)dev_num, enable); - } - - return MV_FAIL; + return config_func_info[dev_num]. + tip_dunit_mux_select_func((u8)dev_num, enable); } /* @@ -881,14 +1047,9 @@ int hws_ddr3_tip_select_ddr_controller(u32 dev_num, int enable) int ddr3_tip_if_write(u32 dev_num, enum hws_access_type interface_access, u32 if_id, u32 reg_addr, u32 data_value, u32 mask) { - if (config_func_info[dev_num].tip_dunit_write_func != NULL) { - return config_func_info[dev_num]. - tip_dunit_write_func((u8)dev_num, interface_access, - if_id, reg_addr, - data_value, mask); - } + config_func_info[dev_num].mv_ddr_dunit_write(reg_addr, mask, data_value); - return MV_FAIL; + return MV_OK; } /* @@ -897,14 +1058,9 @@ int ddr3_tip_if_write(u32 dev_num, enum hws_access_type interface_access, int ddr3_tip_if_read(u32 dev_num, enum hws_access_type interface_access, u32 if_id, u32 reg_addr, u32 *data, u32 mask) { - if (config_func_info[dev_num].tip_dunit_read_func != NULL) { - return config_func_info[dev_num]. - tip_dunit_read_func((u8)dev_num, interface_access, - if_id, reg_addr, - data, mask); - } + config_func_info[dev_num].mv_ddr_dunit_read(reg_addr, mask, data); - return MV_FAIL; + return MV_OK; } /* @@ -918,7 +1074,7 @@ int ddr3_tip_if_polling(u32 dev_num, enum hws_access_type access_type, u32 read_data[MAX_INTERFACE_NUM]; int ret; int is_fail = 0, is_if_fail; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (access_type == ACCESS_TYPE_MULTICAST) { start_if = 0; @@ -930,7 +1086,7 @@ int ddr3_tip_if_polling(u32 dev_num, enum hws_access_type access_type, for (interface_num = start_if; interface_num <= end_if; interface_num++) { /* polling bit 3 for n times */ - VALIDATE_ACTIVE(tm->if_act_mask, interface_num); + VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num); is_if_fail = 0; for (poll_cnt = 0; poll_cnt < poll_tries; poll_cnt++) { @@ -966,42 +1122,8 @@ int ddr3_tip_bus_read(u32 dev_num, u32 if_id, enum hws_access_type phy_access, u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, u32 *data) { - u32 bus_index = 0; - u32 data_read[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (phy_access == ACCESS_TYPE_MULTICAST) { - for (bus_index = 0; bus_index < GET_TOPOLOGY_NUM_OF_BUSES(); - bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); - CHECK_STATUS(ddr3_tip_bus_access - (dev_num, ACCESS_TYPE_UNICAST, - if_id, ACCESS_TYPE_UNICAST, - bus_index, phy_type, reg_addr, 0, - OPERATION_READ)); - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - PHY_REG_FILE_ACCESS, data_read, - MASK_ALL_BITS)); - data[bus_index] = (data_read[if_id] & 0xffff); - } - } else { - CHECK_STATUS(ddr3_tip_bus_access - (dev_num, ACCESS_TYPE_UNICAST, if_id, - phy_access, phy_id, phy_type, reg_addr, 0, - OPERATION_READ)); - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - PHY_REG_FILE_ACCESS, data_read, MASK_ALL_BITS)); - - /* - * only 16 lsb bit are valid in Phy (each register is different, - * some can actually be less than 16 bits) - */ - *data = (data_read[if_id] & 0xffff); - } - - return MV_OK; + return config_func_info[dev_num]. + mv_ddr_phy_read(phy_access, phy_id, phy_type, reg_addr, data); } /* @@ -1012,88 +1134,10 @@ int ddr3_tip_bus_write(u32 dev_num, enum hws_access_type interface_access, u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, u32 data_value) { - CHECK_STATUS(ddr3_tip_bus_access - (dev_num, interface_access, if_id, phy_access, - phy_id, phy_type, reg_addr, data_value, OPERATION_WRITE)); - - return MV_OK; -} - -/* - * Bus access routine (relevant for both read & write) - */ -static int ddr3_tip_bus_access(u32 dev_num, enum hws_access_type interface_access, - u32 if_id, enum hws_access_type phy_access, - u32 phy_id, enum hws_ddr_phy phy_type, u32 reg_addr, - u32 data_value, enum hws_operation oper_type) -{ - u32 addr_low = 0x3f & reg_addr; - u32 addr_hi = ((0xc0 & reg_addr) >> 6); - u32 data_p1 = - (oper_type << 30) + (addr_hi << 28) + (phy_access << 27) + - (phy_type << 26) + (phy_id << 22) + (addr_low << 16) + - (data_value & 0xffff); - u32 data_p2 = data_p1 + (1 << 31); - u32 start_if, end_if; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, interface_access, if_id, PHY_REG_FILE_ACCESS, - data_p1, MASK_ALL_BITS)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, interface_access, if_id, PHY_REG_FILE_ACCESS, - data_p2, MASK_ALL_BITS)); - - if (interface_access == ACCESS_TYPE_UNICAST) { - start_if = if_id; - end_if = if_id; - } else { - start_if = 0; - end_if = MAX_INTERFACE_NUM - 1; - } - - /* polling for read/write execution done */ - for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(is_bus_access_done - (dev_num, if_id, PHY_REG_FILE_ACCESS, 31)); - } - - return MV_OK; + return config_func_info[dev_num]. + mv_ddr_phy_write(phy_access, phy_id, phy_type, reg_addr, data_value, OPERATION_WRITE); } -/* - * Check bus access done - */ -static int is_bus_access_done(u32 dev_num, u32 if_id, u32 dunit_reg_adrr, - u32 bit) -{ - u32 rd_data = 1; - u32 cnt = 0; - u32 data_read[MAX_INTERFACE_NUM]; - - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, dunit_reg_adrr, - data_read, MASK_ALL_BITS)); - rd_data = data_read[if_id]; - rd_data &= (1 << bit); - - while (rd_data != 0) { - if (cnt++ >= MAX_POLLING_ITERATIONS) - break; - - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - dunit_reg_adrr, data_read, MASK_ALL_BITS)); - rd_data = data_read[if_id]; - rd_data &= (1 << bit); - } - - if (cnt < MAX_POLLING_ITERATIONS) - return MV_OK; - else - return MV_FAIL; -} /* * Phy read-modify-write @@ -1104,7 +1148,7 @@ int ddr3_tip_bus_read_modify_write(u32 dev_num, enum hws_access_type access_type u32 data_value, u32 reg_mask) { u32 data_val = 0, if_id, start_if, end_if; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (access_type == ACCESS_TYPE_MULTICAST) { start_if = 0; @@ -1115,7 +1159,7 @@ int ddr3_tip_bus_read_modify_write(u32 dev_num, enum hws_access_type access_type } for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, phy_id, phy_type, reg_addr, &data_val)); @@ -1137,46 +1181,52 @@ int adll_calibration(u32 dev_num, enum hws_access_type access_type, { struct hws_tip_freq_config_info freq_config_info; u32 bus_cnt = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* Reset Diver_b assert -> de-assert */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, SDRAM_CONFIGURATION_REG, + (dev_num, access_type, if_id, SDRAM_CFG_REG, 0, 0x10000000)); mdelay(10); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, SDRAM_CONFIGURATION_REG, + (dev_num, access_type, if_id, SDRAM_CFG_REG, 0x10000000, 0x10000000)); - if (config_func_info[dev_num].tip_get_freq_config_info_func != NULL) { - CHECK_STATUS(config_func_info[dev_num]. - tip_get_freq_config_info_func((u8)dev_num, frequency, - &freq_config_info)); - } else { - DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, - ("tip_get_freq_config_info_func is NULL")); - return MV_NOT_INITIALIZED; - } + CHECK_STATUS(config_func_info[dev_num]. + tip_get_freq_config_info_func((u8)dev_num, frequency, + &freq_config_info)); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); CHECK_STATUS(ddr3_tip_bus_read_modify_write (dev_num, access_type, if_id, bus_cnt, - DDR_PHY_DATA, BW_PHY_REG, + DDR_PHY_DATA, ADLL_CFG0_PHY_REG, freq_config_info.bw_per_freq << 8, 0x700)); CHECK_STATUS(ddr3_tip_bus_read_modify_write (dev_num, access_type, if_id, bus_cnt, - DDR_PHY_DATA, RATE_PHY_REG, + DDR_PHY_DATA, ADLL_CFG2_PHY_REG, + freq_config_info.rate_per_freq, 0x7)); + } + + for (bus_cnt = 0; bus_cnt < DDR_IF_CTRL_SUBPHYS_NUM; bus_cnt++) { + CHECK_STATUS(ddr3_tip_bus_read_modify_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt, + DDR_PHY_CONTROL, ADLL_CFG0_PHY_REG, + freq_config_info.bw_per_freq << 8, 0x700)); + CHECK_STATUS(ddr3_tip_bus_read_modify_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt, + DDR_PHY_CONTROL, ADLL_CFG2_PHY_REG, freq_config_info.rate_per_freq, 0x7)); } /* DUnit to Phy drive post edge, ADLL reset assert de-assert */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, DRAM_PHY_CONFIGURATION, + (dev_num, access_type, if_id, DRAM_PHY_CFG_REG, 0, (0x80000000 | 0x40000000))); mdelay(100 / (freq_val[frequency] / freq_val[DDR_FREQ_LOW_FREQ])); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, DRAM_PHY_CONFIGURATION, + (dev_num, access_type, if_id, DRAM_PHY_CFG_REG, (0x80000000 | 0x40000000), (0x80000000 | 0x40000000))); /* polling for ADLL Done */ @@ -1189,11 +1239,11 @@ int adll_calibration(u32 dev_num, enum hws_access_type access_type, /* pup data_pup reset assert-> deassert */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, SDRAM_CONFIGURATION_REG, + (dev_num, access_type, if_id, SDRAM_CFG_REG, 0, 0x60000000)); mdelay(10); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, SDRAM_CONFIGURATION_REG, + (dev_num, access_type, if_id, SDRAM_CFG_REG, 0x60000000, 0x60000000)); return MV_OK; @@ -1203,18 +1253,21 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, u32 if_id, enum hws_ddr_freq frequency) { u32 cl_value = 0, cwl_value = 0, mem_mask = 0, val = 0, - bus_cnt = 0, t_hclk = 0, t_wr = 0, - refresh_interval_cnt = 0, cnt_id; - u32 t_ckclk; - u32 t_refi = 0, end_if, start_if; + bus_cnt = 0, t_wr = 0, t_ckclk = 0, + cnt_id; + u32 end_if, start_if; u32 bus_index = 0; int is_dll_off = 0; enum hws_speed_bin speed_bin_index = 0; struct hws_tip_freq_config_info freq_config_info; enum hws_result *flow_result = training_result[training_stage]; u32 adll_tap = 0; + u32 cs_num; + u32 t2t; u32 cs_mask[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + unsigned int tclk; DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("dev %d access %d IF %d freq %d\n", dev_num, @@ -1234,7 +1287,7 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, /* speed bin can be different for each interface */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { /* cs enable is active low */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); cs_mask[if_id] = CS_BIT_MASK; training_result[training_stage][if_id] = TEST_SUCCESS; ddr3_tip_calc_cs_mask(dev_num, if_id, effective_cs, @@ -1247,8 +1300,7 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, * and loop the unicast access functions */ for (if_id = start_if; if_id <= end_if; if_id++) { - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) - continue; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); flow_result[if_id] = TEST_SUCCESS; speed_bin_index = @@ -1259,6 +1311,18 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, tm->interface_params[if_id].cas_l; cwl_value = tm->interface_params[if_id].cas_wl; + } else if (tm->cfg_src == MV_DDR_CFG_SPD) { + tclk = 1000000 / freq_val[frequency]; + cl_value = mv_ddr_cl_calc(tm->timing_data[MV_DDR_TAA_MIN], tclk); + if (cl_value == 0) { + printf("mv_ddr: unsupported cas latency value found\n"); + return MV_FAIL; + } + cwl_value = mv_ddr_cwl_calc(tclk); + if (cwl_value == 0) { + printf("mv_ddr: unsupported cas write latency value found\n"); + return MV_FAIL; + } } else { cl_value = cas_latency_table[speed_bin_index].cl_val[frequency]; @@ -1272,7 +1336,7 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, dev_num, access_type, if_id, frequency, speed_bin_index)); - for (cnt_id = 0; cnt_id < DDR_FREQ_LIMIT; cnt_id++) { + for (cnt_id = 0; cnt_id < DDR_FREQ_LAST; cnt_id++) { DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("%d ", cas_latency_table[speed_bin_index]. @@ -1281,19 +1345,19 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("\n")); mem_mask = 0; - for (bus_index = 0; bus_index < GET_TOPOLOGY_NUM_OF_BUSES(); + for (bus_index = 0; bus_index < octets_per_if_num; bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index); mem_mask |= tm->interface_params[if_id]. as_bus_params[bus_index].mirror_enable_bitmask; } if (mem_mask != 0) { - /* motib redundant in KW28 */ + /* motib redundent in KW28 */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - CS_ENABLE_REG, 0, 0x8)); + DUAL_DUNIT_CFG_REG, 0, 0x8)); } /* dll state after exiting SR */ @@ -1343,27 +1407,37 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, ("Freq_set: DDR3 poll failed on SR entry\n")); } - /* PLL configuration */ - if (config_func_info[dev_num].tip_set_freq_divider_func != NULL) { - config_func_info[dev_num]. - tip_set_freq_divider_func(dev_num, if_id, - frequency); + /* Calculate 2T mode */ + if (mode_2t != 0xff) { + t2t = mode_2t; + } else { + /* Calculate number of CS per interface */ + CHECK_STATUS(calc_cs_num(dev_num, if_id, &cs_num)); + t2t = (cs_num == 1) ? 0 : 1; } - /* PLL configuration End */ - /* adjust t_refi to new frequency */ - t_refi = (tm->interface_params[if_id].interface_temp == - HWS_TEMP_HIGH) ? TREFI_HIGH : TREFI_LOW; - t_refi *= 1000; /*psec */ + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_INTERLEAVE_WA) == 1) { + /* Use 1T mode if 1:1 ratio configured */ + if (config_func_info[dev_num].tip_get_clock_ratio(frequency) == 1) { + /* Low freq*/ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + SDRAM_OPEN_PAGES_CTRL_REG, 0x0, 0x3C0)); + t2t = 0; + } else { + /* Middle or target freq */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + SDRAM_OPEN_PAGES_CTRL_REG, 0x3C0, 0x3C0)); + } + } + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, + DUNIT_CTRL_LOW_REG, t2t << 3, 0x3 << 3)); - /* HCLK in[ps] */ - t_hclk = MEGA / (freq_val[frequency] / 2); - refresh_interval_cnt = t_refi / t_hclk; /* no units */ - val = 0x4000 | refresh_interval_cnt; - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, val, 0x7fff)); + /* PLL configuration */ + config_func_info[dev_num].tip_set_freq_divider_func(dev_num, if_id, + frequency); /* DFS - CL/CWL/WR parameters after exiting SR */ CHECK_STATUS(ddr3_tip_if_write @@ -1373,14 +1447,14 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, (dev_num, access_type, if_id, DFS_REG, (cwl_mask_table[cwl_value] << 12), 0x7000)); - t_ckclk = MEGA / freq_val[frequency]; - t_wr = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, - SPEED_BIN_TWR), - t_ckclk); + t_ckclk = (MEGA / freq_val[frequency]); + t_wr = time_to_nclk(speed_bin_table + (speed_bin_index, + SPEED_BIN_TWR), t_ckclk); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, DFS_REG, - (twr_mask_table[t_wr + 1] << 16), 0x70000)); + (twr_mask_table[t_wr] << 16), 0x70000)); /* Restore original RTT values if returning from DLL OFF mode */ if (is_dll_off == 1) { @@ -1398,25 +1472,24 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, g_dic | g_rtt_nom, 0x266)); } - /* Reset Diver_b assert -> de-assert */ + /* Reset divider_b assert -> de-assert */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, 0, 0x10000000)); + SDRAM_CFG_REG, 0, 0x10000000)); mdelay(10); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, 0x10000000, 0x10000000)); + SDRAM_CFG_REG, 0x10000000, 0x10000000)); + + /* ADLL configuration function of process and frequency */ + CHECK_STATUS(config_func_info[dev_num]. + tip_get_freq_config_info_func(dev_num, frequency, + &freq_config_info)); - /* Adll configuration function of process and Frequency */ - if (config_func_info[dev_num].tip_get_freq_config_info_func != NULL) { - CHECK_STATUS(config_func_info[dev_num]. - tip_get_freq_config_info_func(dev_num, frequency, - &freq_config_info)); - } /* TBD check milo5 using device ID ? */ - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); CHECK_STATUS(ddr3_tip_bus_read_modify_write (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_cnt, DDR_PHY_DATA, @@ -1431,15 +1504,15 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, freq_config_info.rate_per_freq, 0x7)); } - /* DUnit to Phy drive post edge, ADLL reset assert de-assert */ + /* Dunit to PHY drive post edge, ADLL reset assert -> de-assert */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, 0, + DRAM_PHY_CFG_REG, 0, (0x80000000 | 0x40000000))); mdelay(100 / (freq_val[frequency] / freq_val[DDR_FREQ_LOW_FREQ])); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - DRAM_PHY_CONFIGURATION, (0x80000000 | 0x40000000), + DRAM_PHY_CFG_REG, (0x80000000 | 0x40000000), (0x80000000 | 0x40000000))); /* polling for ADLL Done */ @@ -1454,16 +1527,16 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, /* pup data_pup reset assert-> deassert */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, 0, 0x60000000)); + SDRAM_CFG_REG, 0, 0x60000000)); mdelay(10); CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_CONFIGURATION_REG, 0x60000000, 0x60000000)); + SDRAM_CFG_REG, 0x60000000, 0x60000000)); /* Set proper timing params before existing Self-Refresh */ ddr3_tip_set_timing(dev_num, access_type, if_id, frequency); if (delay_enable != 0) { - adll_tap = MEGA / (freq_val[frequency] * 64); + adll_tap = (is_dll_off == 1) ? 1000 : (MEGA / (freq_val[frequency] * 64)); ddr3_tip_cmd_addr_init_delay(dev_num, adll_tap); } @@ -1481,10 +1554,10 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, /* Refresh Command */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - SDRAM_OPERATION_REG, 0x2, 0xf1f)); + SDRAM_OP_REG, 0x2, 0xf1f)); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, - SDRAM_OPERATION_REG, MAX_POLLING_ITERATIONS) != MV_OK) { + SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("Freq_set: DDR3 poll failed(3)")); } @@ -1506,54 +1579,57 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, (dev_num, access_type, if_id, MR0_REG, val, (0x7 << 4) | (1 << 2))); /* MR2: CWL = 10 , Auto Self-Refresh - disable */ - val = (cwl_mask_table[cwl_value] << 3); + val = (cwl_mask_table[cwl_value] << 3) | g_rtt_wr; /* * nklein 24.10.13 - should not be here - leave value as set in * the init configuration val |= (1 << 9); * val |= ((tm->interface_params[if_id]. - * interface_temp == HWS_TEMP_HIGH) ? (1 << 7) : 0); + * interface_temp == MV_DDR_TEMP_HIGH) ? (1 << 7) : 0); */ /* nklein 24.10.13 - see above comment */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, MR2_REG, - val, (0x7 << 3))); + val, (0x7 << 3) | (0x3 << 9))); /* ODT TIMING */ val = ((cl_value - cwl_value + 1) << 4) | ((cl_value - cwl_value + 6) << 8) | ((cl_value - 1) << 12) | ((cl_value + 6) << 16); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, - if_id, ODT_TIMING_LOW, + if_id, DDR_ODT_TIMING_LOW_REG, val, 0xffff0)); val = 0x91 | ((cwl_value - 1) << 8) | ((cwl_value + 5) << 12); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, - if_id, ODT_TIMING_HI_REG, + if_id, DDR_ODT_TIMING_HIGH_REG, val, 0xffff)); - /* ODT Active */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, - if_id, - DUNIT_ODT_CONTROL_REG, - 0xf, 0xf)); + /* in case of ddr4 need to set the receiver to odt always 'on' (odt_config = '0') + * in case of ddr3 configure the odt through the timing + */ + if (odt_config != 0) { + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DUNIT_ODT_CTRL_REG, 0xf, 0xf)); + } + else { + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DUNIT_ODT_CTRL_REG, + 0x30f, 0x30f)); + } /* re-write CL */ val = ((cl_mask_table[cl_value] & 0x1) << 2) | ((cl_mask_table[cl_value] & 0xe) << 3); - CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - 0, MR0_REG, val, - (0x7 << 4) | (1 << 2))); + + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask, MR_CMD0, + val, (0x7 << 4) | (0x1 << 2))); /* re-write CWL */ - val = (cwl_mask_table[cwl_value] << 3); - CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask, MRS2_CMD, - val, (0x7 << 3))); - CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - 0, MR2_REG, val, (0x7 << 3))); + val = (cwl_mask_table[cwl_value] << 3) | g_rtt_wr; + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask, MR_CMD2, + val, (0x7 << 3) | (0x3 << 9))); if (mem_mask != 0) { CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - CS_ENABLE_REG, + DUAL_DUNIT_CFG_REG, 1 << 3, 0x8)); } } @@ -1576,20 +1652,20 @@ static int ddr3_tip_write_odt(u32 dev_num, enum hws_access_type access_type, val |= (((cl_value - 1) >> 4) << 22) | (((cl_value + 6) >> 4) << 23); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODT_TIMING_LOW, val, 0xffff0)); + DDR_ODT_TIMING_LOW_REG, val, 0xffff0)); val = 0x91 | ((cwl_value - 1) << 8) | ((cwl_value + 5) << 12); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODT_TIMING_HI_REG, val, 0xffff)); + DDR_ODT_TIMING_HIGH_REG, val, 0xffff)); if (odt_additional == 1) { CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_ODT_CONTROL_HIGH_REG, + SDRAM_ODT_CTRL_HIGH_REG, 0xf, 0xf)); } /* ODT Active */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - DUNIT_ODT_CONTROL_REG, 0xf, 0xf)); + DUNIT_ODT_CTRL_REG, 0xf, 0xf)); return MV_OK; } @@ -1602,88 +1678,146 @@ static int ddr3_tip_set_timing(u32 dev_num, enum hws_access_type access_type, { u32 t_ckclk = 0, t_ras = 0; u32 t_rcd = 0, t_rp = 0, t_wr = 0, t_wtr = 0, t_rrd = 0, t_rtp = 0, - t_rfc = 0, t_mod = 0; - u32 val = 0, page_size = 0; + t_rfc = 0, t_mod = 0, t_r2r = 0x3, t_r2r_high = 0, + t_r2w_w2r = 0x3, t_r2w_w2r_high = 0x1, t_w2w = 0x3; + u32 refresh_interval_cnt, t_hclk, t_refi, t_faw, t_pd, t_xpdll; + u32 val = 0, page_size = 0, mask = 0; enum hws_speed_bin speed_bin_index; - enum hws_mem_size memory_size = MEM_2G; - struct hws_topology_map *tm = ddr3_get_topology_map(); + enum mv_ddr_die_capacity memory_size = MV_DDR_DIE_CAP_2GBIT; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + struct page_element *page_param = mv_ddr_page_tbl_get(); speed_bin_index = tm->interface_params[if_id].speed_bin_index; memory_size = tm->interface_params[if_id].memory_size; page_size = (tm->interface_params[if_id].bus_width == - BUS_WIDTH_8) ? page_param[memory_size]. + MV_DDR_DEV_WIDTH_8BIT) ? page_param[memory_size]. page_size_8bit : page_param[memory_size].page_size_16bit; t_ckclk = (MEGA / freq_val[frequency]); + /* HCLK in[ps] */ + t_hclk = MEGA / (freq_val[frequency] / config_func_info[dev_num].tip_get_clock_ratio(frequency)); + + t_refi = (tm->interface_params[if_id].interface_temp == MV_DDR_TEMP_HIGH) ? TREFI_HIGH : TREFI_LOW; + t_refi *= 1000; /* psec */ + refresh_interval_cnt = t_refi / t_hclk; /* no units */ + + if (page_size == 1) { + t_faw = speed_bin_table(speed_bin_index, SPEED_BIN_TFAW1K); + t_faw = time_to_nclk(t_faw, t_ckclk); + t_faw = GET_MAX_VALUE(20, t_faw); + } else { /* page size =2, we do not support page size 0.5k */ + t_faw = speed_bin_table(speed_bin_index, SPEED_BIN_TFAW2K); + t_faw = time_to_nclk(t_faw, t_ckclk); + t_faw = GET_MAX_VALUE(28, t_faw); + } + + t_pd = GET_MAX_VALUE(t_ckclk * 3, speed_bin_table(speed_bin_index, SPEED_BIN_TPD)); + t_pd = time_to_nclk(t_pd, t_ckclk); + + t_xpdll = GET_MAX_VALUE(t_ckclk * 10, speed_bin_table(speed_bin_index, SPEED_BIN_TXPDLL)); + t_xpdll = time_to_nclk(t_xpdll, t_ckclk); + t_rrd = (page_size == 1) ? speed_bin_table(speed_bin_index, SPEED_BIN_TRRD1K) : speed_bin_table(speed_bin_index, SPEED_BIN_TRRD2K); t_rrd = GET_MAX_VALUE(t_ckclk * 4, t_rrd); t_rtp = GET_MAX_VALUE(t_ckclk * 4, speed_bin_table(speed_bin_index, SPEED_BIN_TRTP)); + t_mod = GET_MAX_VALUE(t_ckclk * 12, 15000); t_wtr = GET_MAX_VALUE(t_ckclk * 4, speed_bin_table(speed_bin_index, SPEED_BIN_TWTR)); - t_ras = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, + t_ras = time_to_nclk(speed_bin_table(speed_bin_index, SPEED_BIN_TRAS), t_ckclk); - t_rcd = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, + t_rcd = time_to_nclk(speed_bin_table(speed_bin_index, SPEED_BIN_TRCD), t_ckclk); - t_rp = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, + t_rp = time_to_nclk(speed_bin_table(speed_bin_index, SPEED_BIN_TRP), t_ckclk); - t_wr = TIME_2_CLOCK_CYCLES(speed_bin_table(speed_bin_index, + t_wr = time_to_nclk(speed_bin_table(speed_bin_index, SPEED_BIN_TWR), t_ckclk); - t_wtr = TIME_2_CLOCK_CYCLES(t_wtr, t_ckclk); - t_rrd = TIME_2_CLOCK_CYCLES(t_rrd, t_ckclk); - t_rtp = TIME_2_CLOCK_CYCLES(t_rtp, t_ckclk); - t_rfc = TIME_2_CLOCK_CYCLES(rfc_table[memory_size] * 1000, t_ckclk); - t_mod = GET_MAX_VALUE(t_ckclk * 24, 15000); - t_mod = TIME_2_CLOCK_CYCLES(t_mod, t_ckclk); + t_wtr = time_to_nclk(t_wtr, t_ckclk); + t_rrd = time_to_nclk(t_rrd, t_ckclk); + t_rtp = time_to_nclk(t_rtp, t_ckclk); + t_rfc = time_to_nclk(rfc_table[memory_size] * 1000, t_ckclk); + t_mod = time_to_nclk(t_mod, t_ckclk); /* SDRAM Timing Low */ - val = (t_ras & 0xf) | (t_rcd << 4) | (t_rp << 8) | (t_wr << 12) | - (t_wtr << 16) | (((t_ras & 0x30) >> 4) << 20) | (t_rrd << 24) | - (t_rtp << 28); + val = (((t_ras - 1) & SDRAM_TIMING_LOW_TRAS_MASK) << SDRAM_TIMING_LOW_TRAS_OFFS) | + (((t_rcd - 1) & SDRAM_TIMING_LOW_TRCD_MASK) << SDRAM_TIMING_LOW_TRCD_OFFS) | + (((t_rcd - 1) >> SDRAM_TIMING_LOW_TRCD_OFFS & SDRAM_TIMING_HIGH_TRCD_MASK) + << SDRAM_TIMING_HIGH_TRCD_OFFS) | + (((t_rp - 1) & SDRAM_TIMING_LOW_TRP_MASK) << SDRAM_TIMING_LOW_TRP_OFFS) | + (((t_rp - 1) >> SDRAM_TIMING_LOW_TRP_MASK & SDRAM_TIMING_HIGH_TRP_MASK) + << SDRAM_TIMING_HIGH_TRP_OFFS) | + (((t_wr - 1) & SDRAM_TIMING_LOW_TWR_MASK) << SDRAM_TIMING_LOW_TWR_OFFS) | + (((t_wtr - 1) & SDRAM_TIMING_LOW_TWTR_MASK) << SDRAM_TIMING_LOW_TWTR_OFFS) | + ((((t_ras - 1) >> 4) & SDRAM_TIMING_LOW_TRAS_HIGH_MASK) << SDRAM_TIMING_LOW_TRAS_HIGH_OFFS) | + (((t_rrd - 1) & SDRAM_TIMING_LOW_TRRD_MASK) << SDRAM_TIMING_LOW_TRRD_OFFS) | + (((t_rtp - 1) & SDRAM_TIMING_LOW_TRTP_MASK) << SDRAM_TIMING_LOW_TRTP_OFFS); + + mask = (SDRAM_TIMING_LOW_TRAS_MASK << SDRAM_TIMING_LOW_TRAS_OFFS) | + (SDRAM_TIMING_LOW_TRCD_MASK << SDRAM_TIMING_LOW_TRCD_OFFS) | + (SDRAM_TIMING_HIGH_TRCD_MASK << SDRAM_TIMING_HIGH_TRCD_OFFS) | + (SDRAM_TIMING_LOW_TRP_MASK << SDRAM_TIMING_LOW_TRP_OFFS) | + (SDRAM_TIMING_HIGH_TRP_MASK << SDRAM_TIMING_HIGH_TRP_OFFS) | + (SDRAM_TIMING_LOW_TWR_MASK << SDRAM_TIMING_LOW_TWR_OFFS) | + (SDRAM_TIMING_LOW_TWTR_MASK << SDRAM_TIMING_LOW_TWTR_OFFS) | + (SDRAM_TIMING_LOW_TRAS_HIGH_MASK << SDRAM_TIMING_LOW_TRAS_HIGH_OFFS) | + (SDRAM_TIMING_LOW_TRRD_MASK << SDRAM_TIMING_LOW_TRRD_OFFS) | + (SDRAM_TIMING_LOW_TRTP_MASK << SDRAM_TIMING_LOW_TRTP_OFFS); + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_LOW_REG, val, 0xff3fffff)); + SDRAM_TIMING_LOW_REG, val, mask)); /* SDRAM Timing High */ + val = 0; + mask = 0; + + val = (((t_rfc - 1) & SDRAM_TIMING_HIGH_TRFC_MASK) << SDRAM_TIMING_HIGH_TRFC_OFFS) | + ((t_r2r & SDRAM_TIMING_HIGH_TR2R_MASK) << SDRAM_TIMING_HIGH_TR2R_OFFS) | + ((t_r2w_w2r & SDRAM_TIMING_HIGH_TR2W_W2R_MASK) << SDRAM_TIMING_HIGH_TR2W_W2R_OFFS) | + ((t_w2w & SDRAM_TIMING_HIGH_TW2W_MASK) << SDRAM_TIMING_HIGH_TW2W_OFFS) | + ((((t_rfc - 1) >> 7) & SDRAM_TIMING_HIGH_TRFC_HIGH_MASK) << SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS) | + ((t_r2r_high & SDRAM_TIMING_HIGH_TR2R_HIGH_MASK) << SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS) | + ((t_r2w_w2r_high & SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK) << SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS) | + (((t_mod - 1) & SDRAM_TIMING_HIGH_TMOD_MASK) << SDRAM_TIMING_HIGH_TMOD_OFFS) | + ((((t_mod - 1) >> 4) & SDRAM_TIMING_HIGH_TMOD_HIGH_MASK) << SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS); + + mask = (SDRAM_TIMING_HIGH_TRFC_MASK << SDRAM_TIMING_HIGH_TRFC_OFFS) | + (SDRAM_TIMING_HIGH_TR2R_MASK << SDRAM_TIMING_HIGH_TR2R_OFFS) | + (SDRAM_TIMING_HIGH_TR2W_W2R_MASK << SDRAM_TIMING_HIGH_TR2W_W2R_OFFS) | + (SDRAM_TIMING_HIGH_TW2W_MASK << SDRAM_TIMING_HIGH_TW2W_OFFS) | + (SDRAM_TIMING_HIGH_TRFC_HIGH_MASK << SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS) | + (SDRAM_TIMING_HIGH_TR2R_HIGH_MASK << SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS) | + (SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK << SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS) | + (SDRAM_TIMING_HIGH_TMOD_MASK << SDRAM_TIMING_HIGH_TMOD_OFFS) | + (SDRAM_TIMING_HIGH_TMOD_HIGH_MASK << SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS); + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - t_rfc & 0x7f, 0x7f)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x180, 0x180)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x600, 0x600)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x1800, 0xf800)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - ((t_rfc & 0x380) >> 7) << 16, 0x70000)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, 0, - 0x380000)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - (t_mod & 0xf) << 25, 0x1e00000)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - (t_mod >> 4) << 30, 0xc0000000)); + SDRAM_TIMING_HIGH_REG, val, mask)); + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x16000000, 0x1e000000)); + SDRAM_CFG_REG, + refresh_interval_cnt << REFRESH_OFFS, + REFRESH_MASK << REFRESH_OFFS)); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - SDRAM_TIMING_HIGH_REG, - 0x40000000, 0xc0000000)); + SDRAM_ADDR_CTRL_REG, (t_faw - 1) << T_FAW_OFFS, + T_FAW_MASK << T_FAW_OFFS)); + + CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, DDR_TIMING_REG, + (t_pd - 1) << DDR_TIMING_TPD_OFFS | + (t_xpdll - 1) << DDR_TIMING_TXPDLL_OFFS, + DDR_TIMING_TPD_MASK << DDR_TIMING_TPD_OFFS | + DDR_TIMING_TXPDLL_MASK << DDR_TIMING_TXPDLL_OFFS)); + return MV_OK; } + /* * Mode Read */ @@ -1712,13 +1846,13 @@ int hws_ddr3_tip_mode_read(u32 dev_num, struct mode_info *mode_info) return ret; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - READ_DATA_SAMPLE_DELAY, mode_info->read_data_sample, + RD_DATA_SMPL_DLYS_REG, mode_info->read_data_sample, MASK_ALL_BITS); if (ret != MV_OK) return ret; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - READ_DATA_READY_DELAY, mode_info->read_data_ready, + RD_DATA_RDY_DLYS_REG, mode_info->read_data_ready, MASK_ALL_BITS); if (ret != MV_OK) return ret; @@ -1733,10 +1867,10 @@ int ddr3_tip_get_first_active_if(u8 dev_num, u32 interface_mask, u32 *interface_id) { u32 if_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (interface_mask & (1 << if_id)) { *interface_id = if_id; break; @@ -1752,13 +1886,14 @@ int ddr3_tip_get_first_active_if(u8 dev_num, u32 interface_mask, int ddr3_tip_write_cs_result(u32 dev_num, u32 offset) { u32 if_id, bus_num, cs_bitmask, data_val, cs_num; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_num = 0; bus_num < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_num = 0; bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); cs_bitmask = tm->interface_params[if_id]. as_bus_params[bus_num].cs_bitmask; @@ -1768,7 +1903,7 @@ int ddr3_tip_write_cs_result(u32 dev_num, u32 offset) ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, offset + - CS_REG_VALUE(effective_cs), + (effective_cs * 0x4), &data_val); ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, @@ -1776,7 +1911,7 @@ int ddr3_tip_write_cs_result(u32 dev_num, u32 offset) ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, offset + - CS_REG_VALUE(cs_num), + (cs_num * 0x4), data_val); } } @@ -1788,27 +1923,25 @@ int ddr3_tip_write_cs_result(u32 dev_num, u32 offset) /* * Write MRS */ -int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, u32 cmd, - u32 data, u32 mask) +int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, enum mr_number mr_num, u32 data, u32 mask) { - u32 if_id, reg; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 if_id; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - reg = (cmd == MRS1_CMD) ? MR1_REG : MR2_REG; CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, reg, data, mask)); + PARAM_NOT_CARE, mr_data[mr_num].reg_addr, data, mask)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - SDRAM_OPERATION_REG, - (cs_mask_arr[if_id] << 8) | cmd, 0xf1f)); + SDRAM_OP_REG, + (cs_mask_arr[if_id] << 8) | mr_data[mr_num].cmd, 0xf1f)); } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (ddr3_tip_if_polling(dev_num, ACCESS_TYPE_UNICAST, if_id, 0, - 0x1f, SDRAM_OPERATION_REG, + 0x1f, SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("write_mrs_cmd: Poll cmd fail")); @@ -1863,35 +1996,57 @@ int ddr3_tip_reset_fifo_ptr(u32 dev_num) int ddr3_tip_ddr3_reset_phy_regs(u32 dev_num) { u32 if_id, phy_id, cs; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (phy_id = 0; phy_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (phy_id = 0; phy_id < octets_per_if_num; phy_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, phy_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, - WL_PHY_REG + - CS_REG_VALUE(effective_cs), + WL_PHY_REG(effective_cs), phy_reg0_val)); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, - RL_PHY_REG + CS_REG_VALUE(effective_cs), + RL_PHY_REG(effective_cs), phy_reg2_val)); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG + - CS_REG_VALUE(effective_cs), phy_reg3_val)); + CRX_PHY_REG(effective_cs), phy_reg3_val)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + CTX_PHY_REG(effective_cs), phy_reg1_val)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_TX_BCAST_PHY_REG(effective_cs), 0x0)); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - CS_REG_VALUE(effective_cs), phy_reg3_val)); + PBS_RX_BCAST_PHY_REG(effective_cs), 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_TX_PHY_REG(effective_cs, DQSP_PAD), 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_RX_PHY_REG(effective_cs, DQSP_PAD), 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_TX_PHY_REG(effective_cs, DQSN_PAD), 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_RX_PHY_REG(effective_cs, DQSN_PAD), 0)); } } @@ -1901,7 +2056,7 @@ int ddr3_tip_ddr3_reset_phy_regs(u32 dev_num) CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - DDR_PHY_DATA, CSN_IOB_VREF_REG(cs), 63)); + DDR_PHY_DATA, VREF_BCAST_PHY_REG(cs), 63)); } return MV_OK; @@ -1914,16 +2069,18 @@ int ddr3_tip_restore_dunit_regs(u32 dev_num) { u32 index_cnt; + mv_ddr_set_calib_controller(); + CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, CALIB_MACHINE_CTRL_REG, + PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG, 0x1, 0x1)); CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, CALIB_MACHINE_CTRL_REG, + PARAM_NOT_CARE, MAIN_PADS_CAL_MACH_CTRL_REG, calibration_update_control << 3, 0x3 << 3)); CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_READ_MODE_ENABLE_REG, + ODPG_WR_RD_MODE_ENA_REG, 0xffff, MASK_ALL_BITS)); for (index_cnt = 0; index_cnt < ARRAY_SIZE(odpg_default_value); @@ -1938,39 +2095,72 @@ int ddr3_tip_restore_dunit_regs(u32 dev_num) return MV_OK; } +int ddr3_tip_adll_regs_bypass(u32 dev_num, u32 reg_val1, u32 reg_val2) +{ + u32 if_id, phy_id; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (phy_id = 0; phy_id < octets_per_if_num; phy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + CTX_PHY_REG(effective_cs), reg_val1)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, phy_id, DDR_PHY_DATA, + PBS_TX_BCAST_PHY_REG(effective_cs), reg_val2)); + } + } + + return MV_OK; +} + /* * Auto tune main flow */ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) { - enum hws_ddr_freq freq = init_freq; +/* TODO: enable this functionality for other platforms */ +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) struct init_cntr_param init_cntr_prm; +#endif int ret = MV_OK; + int adll_bypass_flag = 0; u32 if_id; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + enum hws_ddr_freq freq = tm->interface_params[0].memory_freq; -#ifndef EXCLUDE_SWITCH_DEBUG +#ifdef DDR_VIEWER_TOOL if (debug_training == DEBUG_LEVEL_TRACE) { CHECK_STATUS(print_device_info((u8)dev_num)); } #endif + ddr3_tip_validate_algo_components(dev_num); + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { CHECK_STATUS(ddr3_tip_ddr3_reset_phy_regs(dev_num)); } /* Set to 0 after each loop to avoid illegal value may be used */ effective_cs = 0; - freq = init_freq; + freq_val[DDR_FREQ_LOW_FREQ] = dfs_low_freq; + if (is_pll_before_init != 0) { for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); config_func_info[dev_num].tip_set_freq_divider_func( (u8)dev_num, if_id, freq); } } +/* TODO: enable this functionality for other platforms */ +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) if (is_adll_calib_before_init != 0) { DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("with adll calib before init\n")); @@ -2001,10 +2191,25 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) return MV_FAIL; } } +#endif + ret = adll_calibration(dev_num, ACCESS_TYPE_MULTICAST, 0, freq); + if (ret != MV_OK) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("adll_calibration failure\n")); + if (debug_mode == 0) + return MV_FAIL; + } if (mask_tune_func & SET_LOW_FREQ_MASK_BIT) { training_stage = SET_LOW_FREQ; + + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + ddr3_tip_adll_regs_bypass(dev_num, 0, 0x1f); + adll_bypass_flag = 1; + } + effective_cs = 0; + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("SET_LOW_FREQ_MASK_BIT %d\n", freq_val[low_freq])); @@ -2020,6 +2225,21 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) } } + if (mask_tune_func & WRITE_LEVELING_LF_MASK_BIT) { + training_stage = WRITE_LEVELING_LF; + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, + ("WRITE_LEVELING_LF_MASK_BIT\n")); + ret = ddr3_tip_dynamic_write_leveling(dev_num, 1); + if (is_reg_dump != 0) + ddr3_tip_reg_dump(dev_num); + if (ret != MV_OK) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("ddr3_tip_dynamic_write_leveling LF failure\n")); + if (debug_mode == 0) + return MV_FAIL; + } + } + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { if (mask_tune_func & LOAD_PATTERN_MASK_BIT) { training_stage = LOAD_PATTERN; @@ -2038,6 +2258,14 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) } } } + + if (adll_bypass_flag == 1) { + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + ddr3_tip_adll_regs_bypass(dev_num, phy_reg1_val, 0); + adll_bypass_flag = 0; + } + } + /* Set to 0 after each loop to avoid illegal value may be used */ effective_cs = 0; @@ -2064,7 +2292,7 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("WRITE_LEVELING_MASK_BIT\n")); if ((rl_mid_freq_wa == 0) || (freq_val[medium_freq] == 533)) { - ret = ddr3_tip_dynamic_write_leveling(dev_num); + ret = ddr3_tip_dynamic_write_leveling(dev_num, 0); } else { /* Use old WL */ ret = ddr3_tip_legacy_dynamic_write_leveling(dev_num); @@ -2188,6 +2416,12 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) PARAM_NOT_CARE, tm->interface_params[first_active_if]. memory_freq); +#if defined(A70X0) || defined(A80X0) + if (apn806_rev_id_get() == APN806_REV_ID_A0) { + reg_write(0x6f812c, extension_avs); + reg_write(0x6f8130, nominal_avs); + } +#endif /* #if defined(A70X0) || defined(A80X0) */ if (is_reg_dump != 0) ddr3_tip_reg_dump(dev_num); if (ret != MV_OK) { @@ -2202,7 +2436,7 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) training_stage = WRITE_LEVELING_TF; DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("WRITE_LEVELING_TF_MASK_BIT\n")); - ret = ddr3_tip_dynamic_write_leveling(dev_num); + ret = ddr3_tip_dynamic_write_leveling(dev_num, 0); if (is_reg_dump != 0) ddr3_tip_reg_dump(dev_num); if (ret != MV_OK) { @@ -2244,6 +2478,21 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) } } + if (mask_tune_func & RL_DQS_BURST_MASK_BIT) { + training_stage = READ_LEVELING_TF; + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, + ("RL_DQS_BURST_MASK_BIT\n")); + ret = mv_ddr_rl_dqs_burst(0, 0, tm->interface_params[0].memory_freq); + if (is_reg_dump != 0) + ddr3_tip_reg_dump(dev_num); + if (ret != MV_OK) { + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, + ("mv_ddr_rl_dqs_burst TF failure\n")); + if (debug_mode == 0) + return MV_FAIL; + } + } + if (mask_tune_func & DM_PBS_TX_MASK_BIT) { DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, ("DM_PBS_TX_MASK_BIT\n")); } @@ -2311,6 +2560,7 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) /* Set to 0 after each loop to avoid illegal value may be used */ effective_cs = 0; + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { if (mask_tune_func & CENTRALIZATION_TX_MASK_BIT) { training_stage = CENTRALIZATION_TX; @@ -2347,7 +2597,8 @@ static int ddr3_tip_ddr3_training_main_flow(u32 dev_num) */ static int ddr3_tip_ddr3_auto_tune(u32 dev_num) { - u32 if_id, stage, ret; + int status; + u32 if_id, stage; int is_if_fail = 0, is_auto_tune_fail = 0; training_stage = INIT_CONTROLLER; @@ -2357,7 +2608,7 @@ static int ddr3_tip_ddr3_auto_tune(u32 dev_num) training_result[stage][if_id] = NO_TEST_DONE; } - ret = ddr3_tip_ddr3_training_main_flow(dev_num); + status = ddr3_tip_ddr3_training_main_flow(dev_num); /* activate XSB test */ if (xsb_validate_type != 0) { @@ -2371,9 +2622,11 @@ static int ddr3_tip_ddr3_auto_tune(u32 dev_num) /* print log */ CHECK_STATUS(ddr3_tip_print_log(dev_num, window_mem_addr)); - if (ret != MV_OK) { +#ifndef EXCLUDE_DEBUG_PRINTS + if (status != MV_OK) { CHECK_STATUS(ddr3_tip_print_stability_log(dev_num)); } +#endif /* EXCLUDE_DEBUG_PRINTS */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { is_if_fail = 0; @@ -2389,7 +2642,20 @@ static int ddr3_tip_ddr3_auto_tune(u32 dev_num) } } - if ((ret == MV_FAIL) || (is_auto_tune_fail == 1)) + if (((status == MV_FAIL) && (is_auto_tune_fail == 0)) || + ((status == MV_OK) && (is_auto_tune_fail == 1))) { + /* + * If MainFlow result and trainingResult DB not in sync, + * issue warning (caused by no update of trainingResult DB + * when failed) + */ + DEBUG_TRAINING_IP(DEBUG_LEVEL_INFO, + ("Warning: Algorithm return value and Result DB" + "are not synced (status 0x%x result DB %d)\n", + status, is_auto_tune_fail)); + } + + if ((status != MV_OK) || (is_auto_tune_fail == 1)) return MV_FAIL; else return MV_OK; @@ -2402,18 +2668,19 @@ int ddr3_tip_enable_init_sequence(u32 dev_num) { int is_fail = 0; u32 if_id = 0, mem_mask = 0, bus_index = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* Enable init sequence */ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, 0, - SDRAM_INIT_CONTROL_REG, 0x1, 0x1)); + SDRAM_INIT_CTRL_REG, 0x1, 0x1)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1, - SDRAM_INIT_CONTROL_REG, + SDRAM_INIT_CTRL_REG, MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("polling failed IF %d\n", @@ -2423,9 +2690,9 @@ int ddr3_tip_enable_init_sequence(u32 dev_num) } mem_mask = 0; - for (bus_index = 0; bus_index < GET_TOPOLOGY_NUM_OF_BUSES(); + for (bus_index = 0; bus_index < octets_per_if_num; bus_index++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_index); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_index); mem_mask |= tm->interface_params[if_id]. as_bus_params[bus_index].mirror_enable_bitmask; @@ -2435,7 +2702,7 @@ int ddr3_tip_enable_init_sequence(u32 dev_num) /* Disable Multi CS */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, - if_id, CS_ENABLE_REG, 1 << 3, + if_id, DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3)); } } @@ -2512,7 +2779,7 @@ u8 ddr3_tip_get_buf_max(u8 *buf_ptr) u32 hws_ddr3_get_bus_width(void) { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); return (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 1) ? 16 : 32; @@ -2520,18 +2787,18 @@ u32 hws_ddr3_get_bus_width(void) u32 hws_ddr3_get_device_width(u32 if_id) { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); return (tm->interface_params[if_id].bus_width == - BUS_WIDTH_8) ? 8 : 16; + MV_DDR_DEV_WIDTH_8BIT) ? 8 : 16; } u32 hws_ddr3_get_device_size(u32 if_id) { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (tm->interface_params[if_id].memory_size >= - MEM_SIZE_LAST) { + MV_DDR_DIE_CAP_LAST) { DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("Error: Wrong device size of Cs: %d", tm->interface_params[if_id].memory_size)); @@ -2585,14 +2852,13 @@ int hws_ddr3_cs_base_adr_calc(u32 if_id, u32 cs, u32 *cs_base_addr) return MV_FAIL; #ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * if number of address pins doesn't allow to use max mem size that * is defined in topology mem size is defined by * DEVICE_MAX_DRAM_ADDRESS_SIZE */ - physical_mem_size = - mv_hwsmem_size[tm->interface_params[0].memory_size]; + physical_mem_size = mem_size[tm->interface_params[0].memory_size]; if (hws_ddr3_get_device_width(cs) == 16) { /* diff --git a/drivers/ddr/marvell/a38x/ddr3_training_bist.c b/drivers/ddr/marvell/a38x/ddr3_training_bist.c index ae2f44d0d9..e29b1713f9 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_bist.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_bist.c @@ -3,12 +3,6 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" static u32 bist_offset = 32; @@ -24,7 +18,7 @@ static int ddr3_tip_bist_operation(u32 dev_num, */ int ddr3_tip_bist_activate(u32 dev_num, enum hws_pattern pattern, enum hws_access_type access_type, u32 if_num, - enum hws_dir direction, + enum hws_dir dir, enum hws_stress_jump addr_stress_jump, enum hws_pattern_duration duration, enum hws_bist_operation oper_type, @@ -32,103 +26,43 @@ int ddr3_tip_bist_activate(u32 dev_num, enum hws_pattern pattern, { u32 tx_burst_size; u32 delay_between_burst; - u32 rd_mode, val; - u32 poll_cnt = 0, max_poll = 1000, i, start_if, end_if; + u32 rd_mode; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); - u32 read_data[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - /* ODPG Write enable from BIST */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_DATA_CONTROL_REG, 0x1, 0x1)); - /* ODPG Read enable/disable from BIST */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_DATA_CONTROL_REG, - (direction == OPER_READ) ? - 0x2 : 0, 0x2)); - CHECK_STATUS(ddr3_tip_load_pattern_to_odpg(dev_num, access_type, if_num, - pattern, offset)); - - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_DATA_BUF_SIZE_REG, - pattern_addr_length, MASK_ALL_BITS)); - tx_burst_size = (direction == OPER_WRITE) ? + + /* odpg bist write enable */ + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS), + (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS)); + + /* odpg bist read enable/disable */ + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, + (dir == OPER_READ) ? (ODPG_WRBUF_RD_CTRL_ENA << ODPG_WRBUF_RD_CTRL_OFFS) : + (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS), + (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS)); + + ddr3_tip_load_pattern_to_odpg(0, access_type, 0, pattern, offset); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_SIZE_REG, pattern_addr_length, MASK_ALL_BITS); + tx_burst_size = (dir == OPER_WRITE) ? pattern_table[pattern].tx_burst_size : 0; - delay_between_burst = (direction == OPER_WRITE) ? 2 : 0; - rd_mode = (direction == OPER_WRITE) ? 1 : 0; - CHECK_STATUS(ddr3_tip_configure_odpg - (dev_num, access_type, if_num, direction, + delay_between_burst = (dir == OPER_WRITE) ? 2 : 0; + rd_mode = (dir == OPER_WRITE) ? 1 : 0; + ddr3_tip_configure_odpg(0, access_type, 0, dir, pattern_table[pattern].num_of_phases_tx, tx_burst_size, pattern_table[pattern].num_of_phases_rx, delay_between_burst, - rd_mode, cs_num, addr_stress_jump, duration)); - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_PATTERN_ADDR_OFFSET_REG, - offset, MASK_ALL_BITS)); + rd_mode, cs_num, addr_stress_jump, duration); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_OFFS_REG, offset, MASK_ALL_BITS); + if (oper_type == BIST_STOP) { - CHECK_STATUS(ddr3_tip_bist_operation(dev_num, access_type, - if_num, BIST_STOP)); + ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP); } else { - CHECK_STATUS(ddr3_tip_bist_operation(dev_num, access_type, - if_num, BIST_START)); - if (duration != DURATION_CONT) { - /* - * This pdelay is a WA, becuase polling fives "done" - * also the odpg did nmot finish its task - */ - if (access_type == ACCESS_TYPE_MULTICAST) { - start_if = 0; - end_if = MAX_INTERFACE_NUM - 1; - } else { - start_if = if_num; - end_if = if_num; - } - - for (i = start_if; i <= end_if; i++) { - VALIDATE_ACTIVE(tm-> - if_act_mask, i); - - for (poll_cnt = 0; poll_cnt < max_poll; - poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, - ACCESS_TYPE_UNICAST, - if_num, ODPG_BIST_DONE, - read_data, - MASK_ALL_BITS)); - val = read_data[i]; - if ((val & 0x1) == 0x0) { - /* - * In SOC type devices this bit - * is self clear so, if it was - * cleared all good - */ - break; - } - } - - if (poll_cnt >= max_poll) { - DEBUG_TRAINING_BIST_ENGINE - (DEBUG_LEVEL_ERROR, - ("Bist poll failure 2\n")); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, - ACCESS_TYPE_UNICAST, - if_num, - ODPG_DATA_CONTROL_REG, 0, - MASK_ALL_BITS)); - return MV_FAIL; - } - } - - CHECK_STATUS(ddr3_tip_bist_operation - (dev_num, access_type, if_num, BIST_STOP)); - } + ddr3_tip_bist_operation(0, access_type, 0, BIST_START); + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) + return MV_FAIL; + ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP); } - - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_num, - ODPG_DATA_CONTROL_REG, 0, - MASK_ALL_BITS)); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); return MV_OK; } @@ -141,34 +75,34 @@ int ddr3_tip_bist_read_result(u32 dev_num, u32 if_id, { int ret; u32 read_data[MAX_INTERFACE_NUM]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) + if (IS_IF_ACTIVE(tm->if_act_mask, if_id) == 0) return MV_NOT_SUPPORTED; DEBUG_TRAINING_BIST_ENGINE(DEBUG_LEVEL_TRACE, ("ddr3_tip_bist_read_result if_id %d\n", if_id)); ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_FAILED_DATA_HI_REG, read_data, + ODPG_DATA_RX_WORD_ERR_DATA_HIGH_REG, read_data, MASK_ALL_BITS); if (ret != MV_OK) return ret; pst_bist_result->bist_fail_high = read_data[if_id]; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_FAILED_DATA_LOW_REG, read_data, + ODPG_DATA_RX_WORD_ERR_DATA_LOW_REG, read_data, MASK_ALL_BITS); if (ret != MV_OK) return ret; pst_bist_result->bist_fail_low = read_data[if_id]; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_LAST_FAIL_ADDR_REG, read_data, + ODPG_DATA_RX_WORD_ERR_ADDR_REG, read_data, MASK_ALL_BITS); if (ret != MV_OK) return ret; pst_bist_result->bist_last_fail_addr = read_data[if_id]; ret = ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_DATA_ERROR_COUNTER_REG, read_data, + ODPG_DATA_RX_WORD_ERR_CNTR_REG, read_data, MASK_ALL_BITS); if (ret != MV_OK) return ret; @@ -187,10 +121,10 @@ int hws_ddr3_run_bist(u32 dev_num, enum hws_pattern pattern, u32 *result, u32 i = 0; u32 win_base; struct bist_result st_bist_result; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (i = 0; i < MAX_INTERFACE_NUM; i++) { - VALIDATE_ACTIVE(tm->if_act_mask, i); + VALIDATE_IF_ACTIVE(tm->if_act_mask, i); hws_ddr3_cs_base_adr_calc(i, cs_num, &win_base); ret = ddr3_tip_bist_activate(dev_num, pattern, ACCESS_TYPE_UNICAST, @@ -233,13 +167,10 @@ static int ddr3_tip_bist_operation(u32 dev_num, enum hws_access_type access_type, u32 if_id, enum hws_bist_operation oper_type) { - if (oper_type == BIST_STOP) { - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODPG_BIST_DONE, 1 << 8, 1 << 8)); - } else { - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODPG_BIST_DONE, 1, 1)); - } + if (oper_type == BIST_STOP) + mv_ddr_odpg_disable(); + else + mv_ddr_odpg_enable(); return MV_OK; } @@ -253,11 +184,10 @@ void ddr3_tip_print_bist_res(void) u32 i; struct bist_result st_bist_result[MAX_INTERFACE_NUM]; int res; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (i = 0; i < MAX_INTERFACE_NUM; i++) { - if (IS_ACTIVE(tm->if_act_mask, i) == 0) - continue; + VALIDATE_IF_ACTIVE(tm->if_act_mask, i); res = ddr3_tip_bist_read_result(dev_num, i, &st_bist_result[i]); if (res != MV_OK) { @@ -273,9 +203,7 @@ void ddr3_tip_print_bist_res(void) ("interface | error_cnt | fail_low | fail_high | fail_addr\n")); for (i = 0; i < MAX_INTERFACE_NUM; i++) { - if (IS_ACTIVE(tm->if_act_mask, i) == - 0) - continue; + VALIDATE_IF_ACTIVE(tm->if_act_mask, i); DEBUG_TRAINING_BIST_ENGINE( DEBUG_LEVEL_INFO, @@ -286,3 +214,389 @@ void ddr3_tip_print_bist_res(void) st_bist_result[i].bist_last_fail_addr)); } } + +enum { + PASS, + FAIL +}; +#define TIP_ITERATION_NUM 31 +static int mv_ddr_tip_bist(enum hws_dir dir, u32 val, enum hws_pattern pattern, u32 cs, u32 *result) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + enum hws_training_ip_stat training_result; + u16 *reg_map = ddr3_tip_get_mask_results_pup_reg_map(); + u32 max_subphy = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + u32 subphy, read_data; + + ddr3_tip_ip_training(0, ACCESS_TYPE_MULTICAST, 0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + RESULT_PER_BYTE, HWS_CONTROL_ELEMENT_ADLL, HWS_LOW2HIGH, dir, tm->if_act_mask, val, + TIP_ITERATION_NUM, pattern, EDGE_FP, CS_SINGLE, cs, &training_result); + + for (subphy = 0; subphy < max_subphy; subphy++) { + ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0, reg_map[subphy], &read_data, MASK_ALL_BITS); + if (((read_data >> BLOCK_STATUS_OFFS) & BLOCK_STATUS_MASK) == BLOCK_STATUS_NOT_LOCKED) + *result |= (FAIL << subphy); + } + + return MV_OK; +} + +struct interval { + u8 *vector; + u8 lendpnt; /* interval's left endpoint */ + u8 rendpnt; /* interval's right endpoint */ + u8 size; /* interval's size */ + u8 lmarker; /* left marker */ + u8 rmarker; /* right marker */ + u8 pass_lendpnt; /* left endpoint of internal pass interval */ + u8 pass_rendpnt; /* right endpoint of internal pass interval */ +}; + +static int interval_init(u8 *vector, u8 lendpnt, u8 rendpnt, + u8 lmarker, u8 rmarker, struct interval *intrvl) +{ + if (intrvl == NULL) { + printf("%s: NULL intrvl pointer found\n", __func__); + return MV_FAIL; + } + + if (vector == NULL) { + printf("%s: NULL vector pointer found\n", __func__); + return MV_FAIL; + } + intrvl->vector = vector; + + if (lendpnt >= rendpnt) { + printf("%s: incorrect lendpnt and/or rendpnt parameters found\n", __func__); + return MV_FAIL; + } + intrvl->lendpnt = lendpnt; + intrvl->rendpnt = rendpnt; + intrvl->size = rendpnt - lendpnt + 1; + + if ((lmarker < lendpnt) || (lmarker > rendpnt)) { + printf("%s: incorrect lmarker parameter found\n", __func__); + return MV_FAIL; + } + intrvl->lmarker = lmarker; + + if ((rmarker < lmarker) || (rmarker > (intrvl->rendpnt + intrvl->size))) { + printf("%s: incorrect rmarker parameter found\n", __func__); + return MV_FAIL; + } + intrvl->rmarker = rmarker; + + return MV_OK; +} +static int interval_set(u8 pass_lendpnt, u8 pass_rendpnt, struct interval *intrvl) +{ + if (intrvl == NULL) { + printf("%s: NULL intrvl pointer found\n", __func__); + return MV_FAIL; + } + + intrvl->pass_lendpnt = pass_lendpnt; + intrvl->pass_rendpnt = pass_rendpnt; + + return MV_OK; +} + +static int interval_proc(struct interval *intrvl) +{ + int curr; + int pass_lendpnt, pass_rendpnt; + int lmt; + int fcnt = 0, pcnt = 0; + + if (intrvl == NULL) { + printf("%s: NULL intrvl pointer found\n", __func__); + return MV_FAIL; + } + + /* count fails and passes */ + curr = intrvl->lendpnt; + while (curr <= intrvl->rendpnt) { + if (intrvl->vector[curr] == PASS) + pcnt++; + else + fcnt++; + curr++; + } + + /* check for all fail */ + if (fcnt == intrvl->size) { + printf("%s: no pass found\n", __func__); + return MV_FAIL; + } + + /* check for all pass */ + if (pcnt == intrvl->size) { + if (interval_set(intrvl->lendpnt, intrvl->rendpnt, intrvl) != MV_OK) + return MV_FAIL; + return MV_OK; + } + + /* proceed with rmarker */ + curr = intrvl->rmarker; + if (intrvl->vector[curr % intrvl->size] == PASS) { /* pass at rmarker */ + /* search for fail on right */ + if (intrvl->rmarker > intrvl->rendpnt) + lmt = intrvl->rendpnt + intrvl->size; + else + lmt = intrvl->rmarker + intrvl->size - 1; + while ((curr <= lmt) && + (intrvl->vector[curr % intrvl->size] == PASS)) + curr++; + if (curr > lmt) { /* fail not found */ + printf("%s: rmarker: fail following pass not found\n", __func__); + return MV_FAIL; + } + /* fail found */ + pass_rendpnt = curr - 1; + } else { /* fail at rmarker */ + /* search for pass on left */ + if (intrvl->rmarker > intrvl->rendpnt) + lmt = intrvl->rmarker - intrvl->size + 1; + else + lmt = intrvl->lendpnt; + while ((curr >= lmt) && + (intrvl->vector[curr % intrvl->size] == FAIL)) + curr--; + if (curr < lmt) { /* pass not found */ + printf("%s: rmarker: pass preceding fail not found\n", __func__); + return MV_FAIL; + } + /* pass found */ + pass_rendpnt = curr; + } + + /* search for fail on left */ + curr = pass_rendpnt; + if (pass_rendpnt > intrvl->rendpnt) + lmt = pass_rendpnt - intrvl->size + 1; + else + lmt = intrvl->lendpnt; + while ((curr >= lmt) && + (intrvl->vector[curr % intrvl->size] == PASS)) + curr--; + if (curr < lmt) { /* fail not found */ + printf("%s: rmarker: fail preceding pass not found\n", __func__); + return MV_FAIL; + } + /* fail found */ + pass_lendpnt = curr + 1; + if (interval_set(pass_lendpnt, pass_rendpnt, intrvl) != MV_OK) + return MV_FAIL; + + return MV_OK; +} + +#define ADLL_TAPS_PER_PERIOD 64 +int mv_ddr_dm_to_dq_diff_get(u8 vw_sphy_hi_lmt, u8 vw_sphy_lo_lmt, u8 *vw_vector, + int *vw_sphy_hi_diff, int *vw_sphy_lo_diff) +{ + struct interval intrvl; + + /* init interval structure */ + if (interval_init(vw_vector, 0, ADLL_TAPS_PER_PERIOD - 1, + vw_sphy_lo_lmt, vw_sphy_hi_lmt, &intrvl) != MV_OK) + return MV_FAIL; + + /* find pass sub-interval */ + if (interval_proc(&intrvl) != MV_OK) + return MV_FAIL; + + /* check for all pass */ + if ((intrvl.pass_rendpnt == intrvl.rendpnt) && + (intrvl.pass_lendpnt == intrvl.lendpnt)) { + printf("%s: no fail found\n", __func__); + return MV_FAIL; + } + + *vw_sphy_hi_diff = intrvl.pass_rendpnt - vw_sphy_hi_lmt; + *vw_sphy_lo_diff = vw_sphy_lo_lmt - intrvl.pass_lendpnt; + + return MV_OK; +} + +static int mv_ddr_bist_tx(enum hws_access_type access_type) +{ + mv_ddr_odpg_done_clr(); + + ddr3_tip_bist_operation(0, access_type, 0, BIST_START); + + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) + return MV_FAIL; + + ddr3_tip_bist_operation(0, access_type, 0, BIST_STOP); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); + + return MV_OK; +} + +/* prepare odpg for bist operation */ +#define WR_OP_ODPG_DATA_CMD_BURST_DLY 2 +static int mv_ddr_odpg_bist_prepare(enum hws_pattern pattern, enum hws_access_type access_type, + enum hws_dir dir, enum hws_stress_jump stress_jump_addr, + enum hws_pattern_duration duration, u32 offset, u32 cs, + u32 pattern_addr_len, enum dm_direction dm_dir) +{ + struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + u32 tx_burst_size; + u32 burst_delay; + u32 rd_mode; + + /* odpg bist write enable */ + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS), + (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS)); + + /* odpg bist read enable/disable */ + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_CTRL_REG, + (dir == OPER_READ) ? (ODPG_WRBUF_RD_CTRL_ENA << ODPG_WRBUF_RD_CTRL_OFFS) : + (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS), + (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS)); + + if (pattern == PATTERN_00 || pattern == PATTERN_FF) + ddr3_tip_load_pattern_to_odpg(0, access_type, 0, pattern, offset); + else + mv_ddr_load_dm_pattern_to_odpg(access_type, pattern, dm_dir); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_BUFFER_SIZE_REG, pattern_addr_len, MASK_ALL_BITS); + if (dir == OPER_WRITE) { + tx_burst_size = pattern_table[pattern].tx_burst_size; + burst_delay = WR_OP_ODPG_DATA_CMD_BURST_DLY; + rd_mode = ODPG_MODE_TX; + } else { + tx_burst_size = 0; + burst_delay = 0; + rd_mode = ODPG_MODE_RX; + } + ddr3_tip_configure_odpg(0, access_type, 0, dir, pattern_table[pattern].num_of_phases_tx, + tx_burst_size, pattern_table[pattern].num_of_phases_rx, burst_delay, + rd_mode, cs, stress_jump_addr, duration); + + return MV_OK; +} + +#define BYTES_PER_BURST_64BIT 0x20 +#define BYTES_PER_BURST_32BIT 0x10 +int mv_ddr_dm_vw_get(enum hws_pattern pattern, u32 cs, u8 *vw_vector) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + u32 adll_tap; + u32 wr_ctrl_adll[MAX_BUS_NUM] = {0}; + u32 rd_ctrl_adll[MAX_BUS_NUM] = {0}; + u32 subphy; + u32 subphy_max = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + u32 odpg_addr = 0x0; + u32 result; + u32 idx; + /* burst length in bytes */ + u32 burst_len = (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask) ? + BYTES_PER_BURST_64BIT : BYTES_PER_BURST_32BIT); + + /* save dqs values to restore after algorithm's run */ + ddr3_tip_read_adll_value(0, wr_ctrl_adll, CTX_PHY_REG(cs), MASK_ALL_BITS); + ddr3_tip_read_adll_value(0, rd_ctrl_adll, CRX_PHY_REG(cs), MASK_ALL_BITS); + + /* fill memory with base pattern */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); + mv_ddr_odpg_bist_prepare(pattern, ACCESS_TYPE_UNICAST, OPER_WRITE, STRESS_NONE, DURATION_SINGLE, + bist_offset, cs, pattern_table[pattern].num_of_phases_tx, + (pattern == PATTERN_00) ? DM_DIR_DIRECT : DM_DIR_INVERSE); + + for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) { + /* change target odpg address */ + odpg_addr = adll_tap * burst_len; + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_BUFFER_OFFS_REG, + odpg_addr, MASK_ALL_BITS); + + ddr3_tip_configure_odpg(0, ACCESS_TYPE_UNICAST, 0, OPER_WRITE, + pattern_table[pattern].num_of_phases_tx, + pattern_table[pattern].tx_burst_size, + pattern_table[pattern].num_of_phases_rx, + WR_OP_ODPG_DATA_CMD_BURST_DLY, + ODPG_MODE_TX, cs, STRESS_NONE, DURATION_SINGLE); + + /* odpg bist write enable */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS), + (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS)); + + /* odpg bist read disable */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS), + (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS)); + + /* trigger odpg */ + mv_ddr_bist_tx(ACCESS_TYPE_MULTICAST); + } + + /* fill memory with vref pattern to increment addr using odpg bist */ + mv_ddr_odpg_bist_prepare(PATTERN_VREF, ACCESS_TYPE_UNICAST, OPER_WRITE, STRESS_NONE, DURATION_SINGLE, + bist_offset, cs, pattern_table[pattern].num_of_phases_tx, + (pattern == PATTERN_00) ? DM_DIR_DIRECT : DM_DIR_INVERSE); + + for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) { + ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_MULTICAST, 0, + DDR_PHY_DATA, CTX_PHY_REG(cs), adll_tap); + /* change target odpg address */ + odpg_addr = adll_tap * burst_len; + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_BUFFER_OFFS_REG, + odpg_addr, MASK_ALL_BITS); + ddr3_tip_configure_odpg(0, ACCESS_TYPE_UNICAST, 0, OPER_WRITE, + pattern_table[pattern].num_of_phases_tx, + pattern_table[pattern].tx_burst_size, + pattern_table[pattern].num_of_phases_rx, + WR_OP_ODPG_DATA_CMD_BURST_DLY, + ODPG_MODE_TX, cs, STRESS_NONE, DURATION_SINGLE); + + /* odpg bist write enable */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_WR_CTRL_ENA << ODPG_WRBUF_WR_CTRL_OFFS), + (ODPG_WRBUF_WR_CTRL_MASK << ODPG_WRBUF_WR_CTRL_OFFS)); + + /* odpg bist read disable */ + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, ODPG_DATA_CTRL_REG, + (ODPG_WRBUF_RD_CTRL_DIS << ODPG_WRBUF_RD_CTRL_OFFS), + (ODPG_WRBUF_RD_CTRL_MASK << ODPG_WRBUF_RD_CTRL_OFFS)); + + /* trigger odpg */ + mv_ddr_bist_tx(ACCESS_TYPE_MULTICAST); + } + + /* restore subphy's tx adll_tap to its position */ + for (subphy = 0; subphy < subphy_max; subphy++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy); + ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST, + subphy, DDR_PHY_DATA, CTX_PHY_REG(cs), + wr_ctrl_adll[subphy]); + } + + /* read and validate bist (comparing with the base pattern) */ + for (adll_tap = 0; adll_tap < ADLL_TAPS_PER_PERIOD; adll_tap++) { + result = 0; + odpg_addr = adll_tap * burst_len; + /* change addr to fit write */ + mv_ddr_pattern_start_addr_set(pattern_table, pattern, odpg_addr); + mv_ddr_tip_bist(OPER_READ, 0, pattern, 0, &result); + for (subphy = 0; subphy < subphy_max; subphy++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy); + idx = ADLL_TAPS_PER_PERIOD * subphy + adll_tap; + vw_vector[idx] |= ((result >> subphy) & 0x1); + } + } + + /* restore subphy's rx adll_tap to its position */ + for (subphy = 0; subphy < subphy_max; subphy++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy); + ddr3_tip_bus_write(0, ACCESS_TYPE_UNICAST, 0, ACCESS_TYPE_UNICAST, + subphy, DDR_PHY_DATA, CRX_PHY_REG(cs), + rd_ctrl_adll[subphy]); + } + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_training_centralization.c b/drivers/ddr/marvell/a38x/ddr3_training_centralization.c index 614a478bf6..03e5c9fdce 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_centralization.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_centralization.c @@ -3,12 +3,6 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" #define VALIDATE_WIN_LENGTH(e1, e2, maxsize) \ @@ -22,6 +16,7 @@ #define NUM_OF_CENTRAL_TYPES 2 u32 start_pattern = PATTERN_KILLER_DQ0, end_pattern = PATTERN_KILLER_DQ7; + u32 start_if = 0, end_if = (MAX_INTERFACE_NUM - 1); u8 bus_end_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 bus_start_window[NUM_OF_CENTRAL_TYPES][MAX_INTERFACE_NUM][MAX_BUS_NUM]; @@ -65,7 +60,8 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) u8 current_window[BUS_WIDTH_IN_BITS]; u8 opt_window, waste_window, start_window_skew, end_window_skew; u8 final_pup_window[MAX_INTERFACE_NUM][BUS_WIDTH_IN_BITS]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); enum hws_training_result result_type = RESULT_PER_BIT; enum hws_dir direction; u32 *result[HWS_SEARCH_DIR_LIMIT]; @@ -81,33 +77,33 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) u8 cons_tap = (mode == CENTRAL_TX) ? (64) : (0); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val, MASK_ALL_BITS)); + DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } if (mode == CENTRAL_TX) { max_win_size = MAX_WINDOW_SIZE_TX; - reg_phy_off = WRITE_CENTRALIZATION_PHY_REG + (effective_cs * 4); + reg_phy_off = CTX_PHY_REG(effective_cs); direction = OPER_WRITE; } else { max_win_size = MAX_WINDOW_SIZE_RX; - reg_phy_off = READ_CENTRALIZATION_PHY_REG + (effective_cs * 4); + reg_phy_off = CRX_PHY_REG(effective_cs); direction = OPER_READ; } /* DB initialization */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_id = 0; - bus_id < tm->num_of_bus_per_interface; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); centralization_state[if_id][bus_id] = 0; bus_end_window[mode][if_id][bus_id] = (max_win_size - 1) + cons_tap; @@ -133,11 +129,11 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) PARAM_NOT_CARE, training_result); for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_id = 0; - bus_id <= tm->num_of_bus_per_interface - 1; + bus_id <= octets_per_if_num - 1; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW; @@ -336,8 +332,10 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) [if_id][bus_id])); centralization_state[if_id] [bus_id] = 1; - if (debug_mode == 0) + if (debug_mode == 0) { + flow_result[if_id] = TEST_FAILED; return MV_FAIL; + } } } /* ddr3_tip_centr_skip_min_win_check */ } /* pup */ @@ -345,15 +343,14 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) } /* pattern */ for (if_id = start_if; if_id <= end_if; if_id++) { - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) - continue; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); is_if_fail = 0; flow_result[if_id] = TEST_SUCCESS; for (bus_id = 0; - bus_id <= (tm->num_of_bus_per_interface - 1); bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + bus_id <= (octets_per_if_num - 1); bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); /* continue only if lock */ if (centralization_state[if_id][bus_id] != 1) { @@ -440,21 +437,21 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - RESULT_DB_PHY_REG_ADDR + + RESULT_PHY_REG + effective_cs, ®); reg = (reg & (~0x1f << ((mode == CENTRAL_TX) ? - (RESULT_DB_PHY_REG_TX_OFFSET) : - (RESULT_DB_PHY_REG_RX_OFFSET)))) + (RESULT_PHY_TX_OFFS) : + (RESULT_PHY_RX_OFFS)))) | pup_win_length << ((mode == CENTRAL_TX) ? - (RESULT_DB_PHY_REG_TX_OFFSET) : - (RESULT_DB_PHY_REG_RX_OFFSET)); + (RESULT_PHY_TX_OFFS) : + (RESULT_PHY_RX_OFFS)); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - RESULT_DB_PHY_REG_ADDR + + RESULT_PHY_REG + effective_cs, reg)); /* offset per CS is calculated earlier */ @@ -480,9 +477,9 @@ static int ddr3_tip_centralization(u32 dev_num, u32 mode) for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { /* restore cs enable value */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, - if_id, CS_ENABLE_REG, + if_id, DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); } @@ -508,29 +505,30 @@ int ddr3_tip_special_rx(u32 dev_num) u32 cs_enable_reg_val[MAX_INTERFACE_NUM]; u32 temp = 0; int pad_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (ddr3_tip_special_rx_run_once_flag != 0) + if ((ddr3_tip_special_rx_run_once_flag & (1 << effective_cs)) == (1 << effective_cs)) return MV_OK; - ddr3_tip_special_rx_run_once_flag = 1; + ddr3_tip_special_rx_run_once_flag |= (1 << effective_cs); for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, - if_id, CS_ENABLE_REG, + if_id, DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_UNICAST, - if_id, CS_ENABLE_REG, + if_id, DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } max_win_size = MAX_WINDOW_SIZE_RX; direction = OPER_READ; - pattern_id = PATTERN_VREF; + pattern_id = PATTERN_FULL_SSO1; /* start flow */ ddr3_tip_ip_training_wrapper(dev_num, ACCESS_TYPE_MULTICAST, @@ -544,10 +542,10 @@ int ddr3_tip_special_rx(u32 dev_num) PARAM_NOT_CARE, training_result); for (if_id = start_if; if_id <= end_if; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup_id = 0; - pup_id <= tm->num_of_bus_per_interface; pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); + pup_id <= octets_per_if_num; pup_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_id); for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW; @@ -620,13 +618,12 @@ int ddr3_tip_special_rx(u32 dev_num) BUS_WIDTH_IN_BITS + if_id * BUS_WIDTH_IN_BITS * - tm-> - num_of_bus_per_interface]; + MAX_BUS_NUM]; CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup_id, DDR_PHY_DATA, - PBS_RX_PHY_REG + pad_num, + PBS_RX_PHY_REG(effective_cs, pad_num), &temp)); temp = (temp + 0xa > 31) ? (31) : (temp + 0xa); @@ -636,7 +633,7 @@ int ddr3_tip_special_rx(u32 dev_num) if_id, ACCESS_TYPE_UNICAST, pup_id, DDR_PHY_DATA, - PBS_RX_PHY_REG + pad_num, + PBS_RX_PHY_REG(effective_cs, pad_num), temp)); } DEBUG_CENTRALIZATION_ENGINE( @@ -649,25 +646,29 @@ int ddr3_tip_special_rx(u32 dev_num) CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup_id, - DDR_PHY_DATA, PBS_RX_PHY_REG + 4, + DDR_PHY_DATA, + PBS_RX_PHY_REG(effective_cs, 4), &temp)); temp += 0xa; CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, pup_id, DDR_PHY_DATA, - PBS_RX_PHY_REG + 4, temp)); + PBS_RX_PHY_REG(effective_cs, 4), + temp)); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup_id, - DDR_PHY_DATA, PBS_RX_PHY_REG + 5, + DDR_PHY_DATA, + PBS_RX_PHY_REG(effective_cs, 5), &temp)); temp += 0xa; CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, pup_id, DDR_PHY_DATA, - PBS_RX_PHY_REG + 5, temp)); + PBS_RX_PHY_REG(effective_cs, 5), + temp)); DEBUG_CENTRALIZATION_ENGINE( DEBUG_LEVEL_INFO, ("Special: PBS:: I/F# %d , Bus# %d fix align to the right\n", @@ -694,15 +695,16 @@ int ddr3_tip_special_rx(u32 dev_num) int ddr3_tip_print_centralization_result(u32 dev_num) { u32 if_id = 0, bus_id = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); printf("Centralization Results\n"); printf("I/F0 Result[0 - success 1-fail 2 - state_2 3 - state_3] ...\n"); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); printf("%d ,\n", centralization_state[if_id][bus_id]); } } diff --git a/drivers/ddr/marvell/a38x/ddr3_training_db.c b/drivers/ddr/marvell/a38x/ddr3_training_db.c index 27473acae3..c0089f67f2 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_db.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_db.c @@ -3,16 +3,25 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" +/* Device attributes structures */ +enum mv_ddr_dev_attribute ddr_dev_attributes[MAX_DEVICE_NUM][MV_ATTR_LAST]; +int ddr_dev_attr_init_done[MAX_DEVICE_NUM] = { 0 }; + +static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index); +static inline u32 pattern_table_get_sso_word(u8 sso, u8 index); +static inline u32 pattern_table_get_vref_word(u8 index); +static inline u32 pattern_table_get_vref_word16(u8 index); +static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index); +static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index); +static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index); +static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index); +static inline u32 pattern_table_get_isi_word(u8 index); +static inline u32 pattern_table_get_isi_word16(u8 index); + /* List of allowed frequency listed in order of enum hws_ddr_freq */ -u32 freq_val[DDR_FREQ_LIMIT] = { +u32 freq_val[DDR_FREQ_LAST] = { 0, /*DDR_FREQ_LOW_FREQ */ 400, /*DDR_FREQ_400, */ 533, /*DDR_FREQ_533, */ @@ -151,18 +160,18 @@ u8 twr_mask_table[] = { 10, 10, 10, - 1, /*5*/ - 2, /*6*/ - 3, /*7*/ - 4, /*8*/ + 1, /* 5 */ + 2, /* 6 */ + 3, /* 7 */ + 4, /* 8 */ 10, - 5, /*10*/ + 5, /* 10 */ 10, - 6, /*12*/ + 6, /* 12 */ 10, - 7, /*14*/ + 7, /* 14 */ 10, - 0 /*16*/ + 0 /* 16 */ }; u8 cl_mask_table[] = { @@ -209,7 +218,11 @@ u16 rfc_table[] = { 110, /* 1G */ 160, /* 2G */ 260, /* 4G */ - 350 /* 8G */ + 350, /* 8G */ + 0, /* TODO: placeholder for 16-Mbit dev width */ + 0, /* TODO: placeholder for 32-Mbit dev width */ + 0, /* TODO: placeholder for 12-Mbit dev width */ + 0 /* TODO: placeholder for 24-Mbit dev width */ }; u32 speed_bin_table_t_rc[] = { @@ -233,7 +246,7 @@ u32 speed_bin_table_t_rc[] = { 43285, 44220, 45155, - 46900 + 46090 }; u32 speed_bin_table_t_rcd_t_rp[] = { @@ -255,7 +268,7 @@ u32 speed_bin_table_t_rcd_t_rp[] = { 12840, 13910, 10285, - 11022, + 11220, 12155, 13090, }; @@ -356,13 +369,13 @@ u32 speed_bin_table(u8 index, enum speed_bin_table_elements element) result = speed_bin_table_t_rcd_t_rp[index]; break; case SPEED_BIN_TRAS: - if (index < 6) + if (index < SPEED_BIN_DDR_1066G) result = 37500; - else if (index < 10) + else if (index < SPEED_BIN_DDR_1333J) result = 36000; - else if (index < 14) + else if (index < SPEED_BIN_DDR_1600K) result = 35000; - else if (index < 18) + else if (index < SPEED_BIN_DDR_1866M) result = 34000; else result = 33000; @@ -371,49 +384,49 @@ u32 speed_bin_table(u8 index, enum speed_bin_table_elements element) result = speed_bin_table_t_rc[index]; break; case SPEED_BIN_TRRD1K: - if (index < 3) + if (index < SPEED_BIN_DDR_800E) result = 10000; - else if (index < 6) - result = 7005; - else if (index < 14) + else if (index < SPEED_BIN_DDR_1066G) + result = 7500; + else if (index < SPEED_BIN_DDR_1600K) result = 6000; else result = 5000; break; case SPEED_BIN_TRRD2K: - if (index < 6) + if (index < SPEED_BIN_DDR_1066G) result = 10000; - else if (index < 14) - result = 7005; + else if (index < SPEED_BIN_DDR_1600K) + result = 7500; else result = 6000; break; case SPEED_BIN_TPD: - if (index < 3) + if (index < SPEED_BIN_DDR_800E) result = 7500; - else if (index < 10) + else if (index < SPEED_BIN_DDR_1333J) result = 5625; else result = 5000; break; case SPEED_BIN_TFAW1K: - if (index < 3) + if (index < SPEED_BIN_DDR_800E) result = 40000; - else if (index < 6) + else if (index < SPEED_BIN_DDR_1066G) result = 37500; - else if (index < 14) + else if (index < SPEED_BIN_DDR_1600K) result = 30000; - else if (index < 18) + else if (index < SPEED_BIN_DDR_1866M) result = 27000; else result = 25000; break; case SPEED_BIN_TFAW2K: - if (index < 6) + if (index < SPEED_BIN_DDR_1066G) result = 50000; - else if (index < 10) + else if (index < SPEED_BIN_DDR_1333J) result = 45000; - else if (index < 14) + else if (index < SPEED_BIN_DDR_1600K) result = 40000; else result = 35000; @@ -465,14 +478,7 @@ static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index) (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) : (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM); byte0 |= pattern_killer_pattern_table_map[index * 2][role] << i; - } - - for (i = 0; i < 8; i++) { - role = (i == dqs) ? - (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) : - (PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM); - byte1 |= pattern_killer_pattern_table_map - [index * 2 + 1][role] << i; + byte1 |= pattern_killer_pattern_table_map[index * 2 + 1][role] << i; } return byte0 | (byte0 << 8) | (byte1 << 16) | (byte1 << 24); @@ -488,6 +494,79 @@ static inline u32 pattern_table_get_sso_word(u8 sso, u8 index) return 0xffffffff; } +static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index) +{ + u8 byte = (1 << bit); + + if ((index & 1) == 1) + byte = ~byte; + + return byte | (byte << 8) | (byte << 16) | (byte << 24); + +} + +static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index) +{ + u8 byte = (1 << bit); + + if ((index & 1) == 1) + byte = 0; + + return byte | (byte << 8) | (byte << 16) | (byte << 24); +} + +static inline u32 pattern_table_get_isi_word(u8 index) +{ + u8 i0 = index % 32; + u8 i1 = index % 8; + u32 word; + + if (i0 > 15) + word = ((i1 == 5) | (i1 == 7)) ? 0xffffffff : 0x0; + else + word = (i1 == 6) ? 0xffffffff : 0x0; + + word = ((i0 % 16) > 7) ? ~word : word; + + return word; +} + +static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index) +{ + u8 byte = (1 << bit); + + if ((index & 1) == 1) + byte = ~byte; + + return byte | (byte << 8) | ((~byte) << 16) | ((~byte) << 24); +} + +static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index) +{ + u8 byte = (1 << bit); + + if ((index & 1) == 0) + return (byte << 16) | (byte << 24); + else + return byte | (byte << 8); +} + +static inline u32 pattern_table_get_isi_word16(u8 index) +{ + u8 i0 = index % 16; + u8 i1 = index % 4; + u32 word; + + if (i0 > 7) + word = (i1 > 1) ? 0x0000ffff : 0x0; + else + word = (i1 == 3) ? 0xffff0000 : 0x0; + + word = ((i0 % 8) > 3) ? ~word : word; + + return word; +} + static inline u32 pattern_table_get_vref_word(u8 index) { if (0 == ((pattern_vref_pattern_table_map[index / 8] >> @@ -527,13 +606,13 @@ static inline u32 pattern_table_get_static_pbs_word(u8 index) return temp | (temp << 8) | (temp << 16) | (temp << 24); } -inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) +u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) { u32 pattern; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) { - /* 32bit patterns */ + /* 32/64-bit patterns */ switch (type) { case PATTERN_PBS1: case PATTERN_PBS2: @@ -577,9 +656,9 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) break; case PATTERN_TEST: if (index > 1 && index < 6) - pattern = PATTERN_20; - else pattern = PATTERN_00; + else + pattern = PATTERN_FF; break; case PATTERN_FULL_SSO0: case PATTERN_FULL_SSO1: @@ -591,7 +670,34 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) case PATTERN_VREF: pattern = pattern_table_get_vref_word(index); break; + case PATTERN_SSO_FULL_XTALK_DQ0: + case PATTERN_SSO_FULL_XTALK_DQ1: + case PATTERN_SSO_FULL_XTALK_DQ2: + case PATTERN_SSO_FULL_XTALK_DQ3: + case PATTERN_SSO_FULL_XTALK_DQ4: + case PATTERN_SSO_FULL_XTALK_DQ5: + case PATTERN_SSO_FULL_XTALK_DQ6: + case PATTERN_SSO_FULL_XTALK_DQ7: + pattern = pattern_table_get_sso_full_xtalk_word( + (u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index); + break; + case PATTERN_SSO_XTALK_FREE_DQ0: + case PATTERN_SSO_XTALK_FREE_DQ1: + case PATTERN_SSO_XTALK_FREE_DQ2: + case PATTERN_SSO_XTALK_FREE_DQ3: + case PATTERN_SSO_XTALK_FREE_DQ4: + case PATTERN_SSO_XTALK_FREE_DQ5: + case PATTERN_SSO_XTALK_FREE_DQ6: + case PATTERN_SSO_XTALK_FREE_DQ7: + pattern = pattern_table_get_sso_xtalk_free_word( + (u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index); + break; + case PATTERN_ISI_XTALK_FREE: + pattern = pattern_table_get_isi_word(index); + break; default: + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("Error: %s: pattern type [%d] not supported\n", + __func__, (int)type)); pattern = 0; break; } @@ -630,7 +736,10 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) pattern = PATTERN_01; break; case PATTERN_TEST: - pattern = PATTERN_0080; + if ((index == 0) || (index == 3)) + pattern = 0x00000000; + else + pattern = 0xFFFFFFFF; break; case PATTERN_FULL_SSO0: pattern = 0x0000ffff; @@ -644,7 +753,34 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) case PATTERN_VREF: pattern = pattern_table_get_vref_word16(index); break; + case PATTERN_SSO_FULL_XTALK_DQ0: + case PATTERN_SSO_FULL_XTALK_DQ1: + case PATTERN_SSO_FULL_XTALK_DQ2: + case PATTERN_SSO_FULL_XTALK_DQ3: + case PATTERN_SSO_FULL_XTALK_DQ4: + case PATTERN_SSO_FULL_XTALK_DQ5: + case PATTERN_SSO_FULL_XTALK_DQ6: + case PATTERN_SSO_FULL_XTALK_DQ7: + pattern = pattern_table_get_sso_full_xtalk_word16( + (u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index); + break; + case PATTERN_SSO_XTALK_FREE_DQ0: + case PATTERN_SSO_XTALK_FREE_DQ1: + case PATTERN_SSO_XTALK_FREE_DQ2: + case PATTERN_SSO_XTALK_FREE_DQ3: + case PATTERN_SSO_XTALK_FREE_DQ4: + case PATTERN_SSO_XTALK_FREE_DQ5: + case PATTERN_SSO_XTALK_FREE_DQ6: + case PATTERN_SSO_XTALK_FREE_DQ7: + pattern = pattern_table_get_sso_xtalk_free_word16( + (u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index); + break; + case PATTERN_ISI_XTALK_FREE: + pattern = pattern_table_get_isi_word16(index); + break; default: + DEBUG_TRAINING_IP(DEBUG_LEVEL_ERROR, ("Error: %s: pattern type [%d] not supported\n", + __func__, (int)type)); pattern = 0; break; } @@ -652,3 +788,30 @@ inline u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index) return pattern; } + +/* Device attribute functions */ +void ddr3_tip_dev_attr_init(u32 dev_num) +{ + u32 attr_id; + + for (attr_id = 0; attr_id < MV_ATTR_LAST; attr_id++) + ddr_dev_attributes[dev_num][attr_id] = 0xFF; + + ddr_dev_attr_init_done[dev_num] = 1; +} + +u32 ddr3_tip_dev_attr_get(u32 dev_num, enum mv_ddr_dev_attribute attr_id) +{ + if (ddr_dev_attr_init_done[dev_num] == 0) + ddr3_tip_dev_attr_init(dev_num); + + return ddr_dev_attributes[dev_num][attr_id]; +} + +void ddr3_tip_dev_attr_set(u32 dev_num, enum mv_ddr_dev_attribute attr_id, u32 value) +{ + if (ddr_dev_attr_init_done[dev_num] == 0) + ddr3_tip_dev_attr_init(dev_num); + + ddr_dev_attributes[dev_num][attr_id] = value; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c b/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c index fff1d799ce..6b8aae83d7 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_hw_algo.c @@ -3,12 +3,6 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" #define VREF_INITIAL_STEP 3 @@ -16,9 +10,8 @@ #define VREF_MAX_INDEX 7 #define MAX_VALUE (1024 - 1) #define MIN_VALUE (-MAX_VALUE) -#define GET_RD_SAMPLE_DELAY(data, cs) ((data >> rd_sample_mask[cs]) & 0x1f) +#define GET_RD_SAMPLE_DELAY(data, cs) ((data >> rd_sample_mask[cs]) & 0xf) -u32 ck_delay = (u32)-1, ck_delay_16 = (u32)-1; u32 ca_delay; int ddr3_tip_centr_skip_min_win_check = 0; u8 current_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM]; @@ -48,45 +41,41 @@ static u32 rd_sample_mask[] = { */ int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id) { - u32 cs_num = 0, max_cs = 0, max_read_sample = 0, min_read_sample = 0x1f; + u32 cs_num = 0, max_read_sample = 0, min_read_sample = 0x1f; u32 data_read[MAX_INTERFACE_NUM] = { 0 }; u32 read_sample[MAX_CS_NUM]; u32 val; u32 pup_index; int max_phase = MIN_VALUE, current_phase; enum hws_access_type access_type = ACCESS_TYPE_UNICAST; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - DUNIT_ODT_CONTROL_REG, + DUNIT_ODT_CTRL_REG, 0 << 8, 0x3 << 8)); CHECK_STATUS(ddr3_tip_if_read(dev_num, access_type, if_id, - READ_DATA_SAMPLE_DELAY, + RD_DATA_SMPL_DLYS_REG, data_read, MASK_ALL_BITS)); val = data_read[if_id]; - max_cs = hws_ddr3_tip_max_cs_get(); - - for (cs_num = 0; cs_num < max_cs; cs_num++) { + for (cs_num = 0; cs_num < MAX_CS_NUM; cs_num++) { read_sample[cs_num] = GET_RD_SAMPLE_DELAY(val, cs_num); /* find maximum of read_samples */ if (read_sample[cs_num] >= max_read_sample) { - if (read_sample[cs_num] == max_read_sample) { - /* search for max phase */; - } else { - max_read_sample = read_sample[cs_num]; + if (read_sample[cs_num] == max_read_sample) max_phase = MIN_VALUE; - } + else + max_read_sample = read_sample[cs_num]; for (pup_index = 0; - pup_index < tm->num_of_bus_per_interface; + pup_index < octets_per_if_num; pup_index++) { CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup_index, DDR_PHY_DATA, - RL_PHY_REG + CS_REG_VALUE(cs_num), + RL_PHY_REG(cs_num), &val)); current_phase = ((int)val & 0xe0) >> 6; @@ -100,21 +89,19 @@ int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id) min_read_sample = read_sample[cs_num]; } - if (min_read_sample <= tm->interface_params[if_id].cas_l) { - min_read_sample = (int)tm->interface_params[if_id].cas_l; - } - min_read_sample = min_read_sample - 1; max_read_sample = max_read_sample + 4 + (max_phase + 1) / 2 + 1; + if (min_read_sample >= 0xf) + min_read_sample = 0xf; if (max_read_sample >= 0x1f) max_read_sample = 0x1f; CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODT_TIMING_LOW, + DDR_ODT_TIMING_LOW_REG, ((min_read_sample - 1) << 12), 0xf << 12)); CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id, - ODT_TIMING_LOW, + DDR_ODT_TIMING_LOW_REG, (max_read_sample << 16), 0x1f << 16)); @@ -123,7 +110,7 @@ int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id) int get_valid_win_rx(u32 dev_num, u32 if_id, u8 res[4]) { - u32 reg_pup = RESULT_DB_PHY_REG_ADDR; + u32 reg_pup = RESULT_PHY_REG; u32 reg_data; u32 cs_num; int i; @@ -138,7 +125,7 @@ int get_valid_win_rx(u32 dev_num, u32 if_id, u8 res[4]) ACCESS_TYPE_UNICAST, i, DDR_PHY_DATA, reg_pup, ®_data)); - res[i] = (reg_data >> RESULT_DB_PHY_REG_RX_OFFSET) & 0x1f; + res[i] = (reg_data >> RESULT_PHY_RX_OFFS) & 0x1f; } return 0; @@ -176,7 +163,8 @@ int ddr3_tip_vref(u32 dev_num) u32 copy_start_pattern, copy_end_pattern; enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage); u8 res[4]; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); CHECK_STATUS(ddr3_tip_special_rx(dev_num)); @@ -190,9 +178,9 @@ int ddr3_tip_vref(u32 dev_num) /* init params */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup = 0; - pup < tm->num_of_bus_per_interface; pup++) { + pup < octets_per_if_num; pup++) { current_vref[pup][if_id] = 0; last_vref[pup][if_id] = 0; lim_vref[pup][if_id] = 0; @@ -228,7 +216,7 @@ int ddr3_tip_vref(u32 dev_num) } /* TODO: Set number of active interfaces */ - num_pup = tm->num_of_bus_per_interface * MAX_INTERFACE_NUM; + num_pup = octets_per_if_num * MAX_INTERFACE_NUM; while ((algo_run_flag <= num_pup) & (while_count < 10)) { while_count++; @@ -239,13 +227,13 @@ int ddr3_tip_vref(u32 dev_num) /* Read Valid window results only for non converge pups */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (interface_state[if_id] != 4) { get_valid_win_rx(dev_num, if_id, res); for (pup = 0; - pup < tm->num_of_bus_per_interface; + pup < octets_per_if_num; pup++) { - VALIDATE_ACTIVE + VALIDATE_BUS_ACTIVE (tm->bus_act_mask, pup); if (pup_st[pup] [if_id] == @@ -263,14 +251,14 @@ int ddr3_tip_vref(u32 dev_num) } for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_TRAINING_HW_ALG( DEBUG_LEVEL_TRACE, ("current_valid_window: IF[ %d ] - ", if_id)); for (pup = 0; - pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("%d ", current_valid_window @@ -281,10 +269,10 @@ int ddr3_tip_vref(u32 dev_num) /* Compare results and respond as function of state */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup = 0; - pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("I/F[ %d ], pup[ %d ] STATE #%d (%d)\n", if_id, pup, @@ -609,10 +597,10 @@ int ddr3_tip_vref(u32 dev_num) } for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup = 0; - pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup, @@ -640,7 +628,7 @@ int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap) { u32 if_id = 0; u32 ck_num_adll_tap = 0, ca_num_adll_tap = 0, data = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * ck_delay_table is delaying the of the clock signal only. @@ -653,22 +641,18 @@ int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap) */ /* Calc ADLL Tap */ - if ((ck_delay == -1) || (ck_delay_16 == -1)) { + if (ck_delay == PARAM_UNDEFINED) DEBUG_TRAINING_HW_ALG( DEBUG_LEVEL_ERROR, - ("ERROR: One of ck_delay values not initialized!!!\n")); - } + ("ERROR: ck_delay is not initialized!\n")); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - /* Calc delay ps in ADLL tap */ - if (tm->interface_params[if_id].bus_width == - BUS_WIDTH_16) - ck_num_adll_tap = ck_delay_16 / adll_tap; - else - ck_num_adll_tap = ck_delay / adll_tap; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + /* Calc delay ps in ADLL tap */ + ck_num_adll_tap = ck_delay / adll_tap; ca_num_adll_tap = ca_delay / adll_tap; + data = (ck_num_adll_tap & 0x3f) + ((ca_num_adll_tap & 0x3f) << 10); diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip.h b/drivers/ddr/marvell/a38x/ddr3_training_ip.h index 0102e69194..531103c1ab 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip.h @@ -10,11 +10,10 @@ #include "ddr_topology_def.h" #include "ddr_training_ip_db.h" -#define DDR3_TIP_VERSION_STRING "DDR3 Training Sequence - Ver TIP-1.29." - #define MAX_CS_NUM 4 #define MAX_TOTAL_BUS_NUM (MAX_INTERFACE_NUM * MAX_BUS_NUM) -#define MAX_DQ_NUM 40 +#define TIP_ENG_LOCK 0x02000000 +#define TIP_TX_DLL_RANGE_MAX 64 #define GET_MIN(arg1, arg2) ((arg1) < (arg2)) ? (arg1) : (arg2) #define GET_MAX(arg1, arg2) ((arg1) < (arg2)) ? (arg2) : (arg1) @@ -38,11 +37,15 @@ #define READ_LEVELING_TF_MASK_BIT 0x00010000 #define WRITE_LEVELING_SUPP_TF_MASK_BIT 0x00020000 #define DM_PBS_TX_MASK_BIT 0x00040000 +#define RL_DQS_BURST_MASK_BIT 0x00080000 #define CENTRALIZATION_RX_MASK_BIT 0x00100000 #define CENTRALIZATION_TX_MASK_BIT 0x00200000 #define TX_EMPHASIS_MASK_BIT 0x00400000 #define PER_BIT_READ_LEVELING_TF_MASK_BIT 0x00800000 #define VREF_CALIBRATION_MASK_BIT 0x01000000 +#define WRITE_LEVELING_LF_MASK_BIT 0x02000000 + +/* DDR4 Specific Training Mask bits */ enum hws_result { TEST_FAILED = 0, @@ -79,6 +82,7 @@ enum auto_tune_stage { TX_EMPHASIS, LOAD_PATTERN_HIGH, PER_BIT_READ_LEVELING_TF, + WRITE_LEVELING_LF, MAX_STAGE_LIMIT }; @@ -110,7 +114,7 @@ struct pattern_info { /* CL value for each frequency */ struct cl_val_per_freq { - u8 cl_val[DDR_FREQ_LIMIT]; + u8 cl_val[DDR_FREQ_LAST]; }; struct cs_element { @@ -167,11 +171,14 @@ int hws_ddr3_tip_select_ddr_controller(u32 dev_num, int enable); int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_prm); int hws_ddr3_tip_load_topology_map(u32 dev_num, - struct hws_topology_map *topology); + struct mv_ddr_topology_map *topology); int hws_ddr3_tip_run_alg(u32 dev_num, enum hws_algo_type algo_type); int hws_ddr3_tip_mode_read(u32 dev_num, struct mode_info *mode_info); +int hws_ddr3_tip_read_training_result(u32 dev_num, + enum hws_result result[MAX_STAGE_LIMIT][MAX_INTERFACE_NUM]); int ddr3_tip_is_pup_lock(u32 *pup_buf, enum hws_training_result read_mode); u8 ddr3_tip_get_buf_min(u8 *buf_ptr); u8 ddr3_tip_get_buf_max(u8 *buf_ptr); - +uint64_t mv_ddr_get_memory_size_per_cs_in_bits(void); +uint64_t mv_ddr_get_total_memory_size_in_bits(void); #endif /* _DDR3_TRAINING_IP_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h index 1d7af4dcd3..38058cba8a 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_bist.h @@ -45,9 +45,13 @@ int hws_ddr3_run_bist(u32 dev_num, enum hws_pattern pattern, u32 *result, u32 cs_num); int ddr3_tip_run_sweep_test(int dev_num, u32 repeat_num, u32 direction, u32 mode); +int ddr3_tip_run_leveling_sweep_test(int dev_num, u32 repeat_num, + u32 direction, u32 mode); int ddr3_tip_print_regs(u32 dev_num); int ddr3_tip_reg_dump(u32 dev_num); int run_xsb_test(u32 dev_num, u32 mem_addr, u32 write_type, u32 read_type, u32 burst_length); - +int mv_ddr_dm_to_dq_diff_get(u8 adll_byte_high, u8 adll_byte_low, u8 *vw_vector, + int *delta_h_adll, int *delta_l_adll); +int mv_ddr_dm_vw_get(enum hws_pattern pattern, u32 cs, u8 *vw_vector); #endif /* _DDR3_TRAINING_IP_BIST_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h index 18e4f98ff7..e28b7ecee1 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_db.h @@ -9,7 +9,10 @@ enum hws_pattern { PATTERN_PBS1, PATTERN_PBS2, + PATTERN_PBS3, + PATTERN_TEST, PATTERN_RL, + PATTERN_RL2, PATTERN_STATIC_PBS, PATTERN_KILLER_DQ0, PATTERN_KILLER_DQ1, @@ -19,15 +22,73 @@ enum hws_pattern { PATTERN_KILLER_DQ5, PATTERN_KILLER_DQ6, PATTERN_KILLER_DQ7, - PATTERN_PBS3, - PATTERN_RL2, - PATTERN_TEST, + PATTERN_VREF, PATTERN_FULL_SSO0, PATTERN_FULL_SSO1, PATTERN_FULL_SSO2, PATTERN_FULL_SSO3, - PATTERN_VREF, - PATTERN_LIMIT + PATTERN_LAST, + PATTERN_SSO_FULL_XTALK_DQ0, + PATTERN_SSO_FULL_XTALK_DQ1, + PATTERN_SSO_FULL_XTALK_DQ2, + PATTERN_SSO_FULL_XTALK_DQ3, + PATTERN_SSO_FULL_XTALK_DQ4, + PATTERN_SSO_FULL_XTALK_DQ5, + PATTERN_SSO_FULL_XTALK_DQ6, + PATTERN_SSO_FULL_XTALK_DQ7, + PATTERN_SSO_XTALK_FREE_DQ0, + PATTERN_SSO_XTALK_FREE_DQ1, + PATTERN_SSO_XTALK_FREE_DQ2, + PATTERN_SSO_XTALK_FREE_DQ3, + PATTERN_SSO_XTALK_FREE_DQ4, + PATTERN_SSO_XTALK_FREE_DQ5, + PATTERN_SSO_XTALK_FREE_DQ6, + PATTERN_SSO_XTALK_FREE_DQ7, + PATTERN_ISI_XTALK_FREE }; +enum mv_wl_supp_mode { + WRITE_LEVELING_SUPP_REG_MODE, + WRITE_LEVELING_SUPP_ECC_MODE_DATA_PUPS, + WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP4, + WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP3, + WRITE_LEVELING_SUPP_ECC_MODE_ECC_PUP8 +}; + +enum mv_ddr_dev_attribute { + MV_ATTR_TIP_REV, + MV_ATTR_PHY_EDGE, + MV_ATTR_OCTET_PER_INTERFACE, + MV_ATTR_PLL_BEFORE_INIT, + MV_ATTR_TUNE_MASK, + MV_ATTR_INIT_FREQ, + MV_ATTR_MID_FREQ, + MV_ATTR_DFS_LOW_FREQ, + MV_ATTR_DFS_LOW_PHY, + MV_ATTR_DELAY_ENABLE, + MV_ATTR_CK_DELAY, + MV_ATTR_CA_DELAY, + MV_ATTR_INTERLEAVE_WA, + MV_ATTR_LAST +}; + +enum mv_ddr_tip_revison { + MV_TIP_REV_NA, + MV_TIP_REV_1, /* NP5 */ + MV_TIP_REV_2, /* BC2 */ + MV_TIP_REV_3, /* AC3 */ + MV_TIP_REV_4, /* A-380/A-390 */ + MV_TIP_REV_LAST +}; + +enum mv_ddr_phy_edge { + MV_DDR_PHY_EDGE_POSITIVE, + MV_DDR_PHY_EDGE_NEGATIVE +}; + +/* Device attribute functions */ +void ddr3_tip_dev_attr_init(u32 dev_num); +u32 ddr3_tip_dev_attr_get(u32 dev_num, enum mv_ddr_dev_attribute attr_id); +void ddr3_tip_dev_attr_set(u32 dev_num, enum mv_ddr_dev_attribute attr_id, u32 value); + #endif /* _DDR3_TRAINING_IP_DB_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h index 2a30f80f79..2318ceba29 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_def.h @@ -6,8 +6,6 @@ #ifndef _DDR3_TRAINING_IP_DEF_H #define _DDR3_TRAINING_IP_DEF_H -#include "silicon_if.h" - #define PATTERN_55 0x55555555 #define PATTERN_AA 0xaaaaaaaa #define PATTERN_80 0x80808080 @@ -35,6 +33,7 @@ #define ADLL_RX_LENGTH 32 #define PARAM_NOT_CARE 0 +#define PARAM_UNDEFINED 0xffffffff #define READ_LEVELING_PHY_OFFSET 2 #define WRITE_LEVELING_PHY_OFFSET 0 @@ -99,6 +98,8 @@ #define _1G 0x40000000 #define _2G 0x80000000 +#define _4G 0x100000000 +#define _8G 0x200000000 #define ADDR_SIZE_512MB 0x04000000 #define ADDR_SIZE_1GB 0x08000000 @@ -163,10 +164,33 @@ enum hws_wl_supp { ALIGN_SHIFT }; +enum mv_ddr_tip_bit_state { + BIT_LOW_UI, + BIT_HIGH_UI, + BIT_SPLIT_IN, + BIT_SPLIT_OUT, + BIT_STATE_LAST +}; + +enum mv_ddr_tip_byte_state{ + BYTE_NOT_DEFINED, + BYTE_HOMOGENEOUS_LOW = 0x1, + BYTE_HOMOGENEOUS_HIGH = 0x2, + BYTE_HOMOGENEOUS_SPLIT_IN = 0x4, + BYTE_HOMOGENEOUS_SPLIT_OUT = 0x8, + BYTE_SPLIT_OUT_MIX = 0x10, + BYTE_STATE_LAST +}; + struct reg_data { - u32 reg_addr; - u32 reg_data; - u32 reg_mask; + unsigned int reg_addr; + unsigned int reg_data; + unsigned int reg_mask; +}; + +enum dm_direction { + DM_DIR_INVERSE, + DM_DIR_DIRECT }; #endif /* _DDR3_TRAINING_IP_DEF_H */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c index 89318a48d9..334c2906fd 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c @@ -3,12 +3,6 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" #define PATTERN_1 0x55555555 @@ -21,6 +15,7 @@ u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * HWS_SEARCH_DIR_LIMIT]; +u8 byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM]; /* holds the bit status in the byte in wrapper function*/ u16 mask_results_dq_reg_map[] = { RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG, @@ -43,14 +38,39 @@ u16 mask_results_dq_reg_map[] = { RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, +#if MAX_BUS_NUM == 9 + RESULT_CONTROL_PUP_5_BIT_0_REG, RESULT_CONTROL_PUP_5_BIT_1_REG, + RESULT_CONTROL_PUP_5_BIT_2_REG, RESULT_CONTROL_PUP_5_BIT_3_REG, + RESULT_CONTROL_PUP_5_BIT_4_REG, RESULT_CONTROL_PUP_5_BIT_5_REG, + RESULT_CONTROL_PUP_5_BIT_6_REG, RESULT_CONTROL_PUP_5_BIT_7_REG, + RESULT_CONTROL_PUP_6_BIT_0_REG, RESULT_CONTROL_PUP_6_BIT_1_REG, + RESULT_CONTROL_PUP_6_BIT_2_REG, RESULT_CONTROL_PUP_6_BIT_3_REG, + RESULT_CONTROL_PUP_6_BIT_4_REG, RESULT_CONTROL_PUP_6_BIT_5_REG, + RESULT_CONTROL_PUP_6_BIT_6_REG, RESULT_CONTROL_PUP_6_BIT_7_REG, + RESULT_CONTROL_PUP_7_BIT_0_REG, RESULT_CONTROL_PUP_7_BIT_1_REG, + RESULT_CONTROL_PUP_7_BIT_2_REG, RESULT_CONTROL_PUP_7_BIT_3_REG, + RESULT_CONTROL_PUP_7_BIT_4_REG, RESULT_CONTROL_PUP_7_BIT_5_REG, + RESULT_CONTROL_PUP_7_BIT_6_REG, RESULT_CONTROL_PUP_7_BIT_7_REG, + RESULT_CONTROL_PUP_8_BIT_0_REG, RESULT_CONTROL_PUP_8_BIT_1_REG, + RESULT_CONTROL_PUP_8_BIT_2_REG, RESULT_CONTROL_PUP_8_BIT_3_REG, + RESULT_CONTROL_PUP_8_BIT_4_REG, RESULT_CONTROL_PUP_8_BIT_5_REG, + RESULT_CONTROL_PUP_8_BIT_6_REG, RESULT_CONTROL_PUP_8_BIT_7_REG, +#endif + 0xffff }; u16 mask_results_pup_reg_map[] = { RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG, RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG, - RESULT_CONTROL_BYTE_PUP_4_REG + RESULT_CONTROL_BYTE_PUP_4_REG, +#if MAX_BUS_NUM == 9 + RESULT_CONTROL_BYTE_PUP_5_REG, RESULT_CONTROL_BYTE_PUP_6_REG, + RESULT_CONTROL_BYTE_PUP_7_REG, RESULT_CONTROL_BYTE_PUP_8_REG, +#endif + 0xffff }; +#if MAX_BUS_NUM == 5 u16 mask_results_dq_reg_map_pup3_ecc[] = { RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG, RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG, @@ -68,17 +88,120 @@ u16 mask_results_dq_reg_map_pup3_ecc[] = { RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, - RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG, - RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG, - RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG, - RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG, + RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG, + RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG, + RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG, + RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG }; +#endif +#if MAX_BUS_NUM == 5 u16 mask_results_pup_reg_map_pup3_ecc[] = { RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG, RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG, RESULT_CONTROL_BYTE_PUP_4_REG }; +#endif + +struct pattern_info pattern_table_64[] = { + /* + * num_of_phases_tx, tx_burst_size; + * delay_between_bursts, num_of_phases_rx, + * start_addr, pattern_len + */ + {0x7, 0x7, 2, 0x7, 0x00000, 8}, /* PATTERN_PBS1 */ + {0x7, 0x7, 2, 0x7, 0x00080, 8}, /* PATTERN_PBS2 */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_PBS3 */ + {0x7, 0x7, 2, 0x7, 0x00030, 8}, /* PATTERN_TEST */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_RL */ + {0x7, 0x7, 2, 0x7, 0x00100, 8}, /* PATTERN_RL2 */ + {0x1f, 0xf, 2, 0xf, 0x00680, 32}, /* PATTERN_STATIC_PBS */ + {0x1f, 0xf, 2, 0xf, 0x00a80, 32}, /* PATTERN_KILLER_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x01280, 32}, /* PATTERN_KILLER_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x01a80, 32}, /* PATTERN_KILLER_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x02280, 32}, /* PATTERN_KILLER_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x02a80, 32}, /* PATTERN_KILLER_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x03280, 32}, /* PATTERN_KILLER_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x03a80, 32}, /* PATTERN_KILLER_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x04280, 32}, /* PATTERN_KILLER_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x00e80, 32}, /* PATTERN_KILLER_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x01680, 32}, /* PATTERN_KILLER_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x01e80, 32}, /* PATTERN_KILLER_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x02680, 32}, /* PATTERN_KILLER_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x02e80, 32}, /* PATTERN_KILLER_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x03680, 32}, /* PATTERN_KILLER_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x03e80, 32}, /* PATTERN_KILLER_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x04680, 32}, /* PATTERN_KILLER_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x04a80, 32}, /* PATTERN_KILLER_DQ0_INV */ + {0x1f, 0xf, 2, 0xf, 0x05280, 32}, /* PATTERN_KILLER_DQ1_INV */ + {0x1f, 0xf, 2, 0xf, 0x05a80, 32}, /* PATTERN_KILLER_DQ2_INV */ + {0x1f, 0xf, 2, 0xf, 0x06280, 32}, /* PATTERN_KILLER_DQ3_INV */ + {0x1f, 0xf, 2, 0xf, 0x06a80, 32}, /* PATTERN_KILLER_DQ4_INV */ + {0x1f, 0xf, 2, 0xf, 0x07280, 32}, /* PATTERN_KILLER_DQ5_INV */ + {0x1f, 0xf, 2, 0xf, 0x07a80, 32}, /* PATTERN_KILLER_DQ6_INV */ + {0x1f, 0xf, 2, 0xf, 0x08280, 32}, /* PATTERN_KILLER_DQ7_INV */ + {0x1f, 0xf, 2, 0xf, 0x04e80, 32}, /* PATTERN_KILLER_DQ0_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x05680, 32}, /* PATTERN_KILLER_DQ1_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x05e80, 32}, /* PATTERN_KILLER_DQ2_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x06680, 32}, /* PATTERN_KILLER_DQ3_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x06e80, 32}, /* PATTERN_KILLER_DQ4_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x07680, 32}, /* PATTERN_KILLER_DQ5_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x07e80, 32}, /* PATTERN_KILLER_DQ6_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x08680, 32}, /* PATTERN_KILLER_DQ7_INV_64 */ + {0x1f, 0xf, 2, 0xf, 0x08a80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x09280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x09a80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x0a280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x0aa80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x0b280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x0ba80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x0c280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x08e80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x09680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x09e80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x0a680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ae80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x0b680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x0be80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x0c680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ca80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0x1f, 0xf, 2, 0xf, 0x0d280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0x1f, 0xf, 2, 0xf, 0x0da80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0x1f, 0xf, 2, 0xf, 0x0e280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0x1f, 0xf, 2, 0xf, 0x0ea80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0x1f, 0xf, 2, 0xf, 0x0f280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0x1f, 0xf, 2, 0xf, 0x0fa80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0x1f, 0xf, 2, 0xf, 0x10280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0x1f, 0xf, 2, 0xf, 0x0ce80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0_64 */ + {0x1f, 0xf, 2, 0xf, 0x0d680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1_64 */ + {0x1f, 0xf, 2, 0xf, 0x0de80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2_64 */ + {0x1f, 0xf, 2, 0xf, 0x0e680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3_64 */ + {0x1f, 0xf, 2, 0xf, 0x0ee80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4_64 */ + {0x1f, 0xf, 2, 0xf, 0x0f680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5_64 */ + {0x1f, 0xf, 2, 0xf, 0x0fe80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6_64 */ + {0x1f, 0xf, 2, 0xf, 0x10680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7_64 */ + {0x1f, 0xf, 2, 0xf, 0x10a80, 32}, /* PATTERN_ISI_XTALK_FREE */ + {0x1f, 0xf, 2, 0xf, 0x10e80, 32}, /* PATTERN_ISI_XTALK_FREE_64 */ + {0x1f, 0xf, 2, 0xf, 0x11280, 32}, /* PATTERN_VREF */ + {0x1f, 0xf, 2, 0xf, 0x11680, 32}, /* PATTERN_VREF_64 */ + {0x1f, 0xf, 2, 0xf, 0x11a80, 32}, /* PATTERN_VREF_INV */ + {0x1f, 0xf, 2, 0xf, 0x11e80, 32}, /* PATTERN_FULL_SSO_0T */ + {0x1f, 0xf, 2, 0xf, 0x12280, 32}, /* PATTERN_FULL_SSO_1T */ + {0x1f, 0xf, 2, 0xf, 0x12680, 32}, /* PATTERN_FULL_SSO_2T */ + {0x1f, 0xf, 2, 0xf, 0x12a80, 32}, /* PATTERN_FULL_SSO_3T */ + {0x1f, 0xf, 2, 0xf, 0x12e80, 32}, /* PATTERN_RESONANCE_1T */ + {0x1f, 0xf, 2, 0xf, 0x13280, 32}, /* PATTERN_RESONANCE_2T */ + {0x1f, 0xf, 2, 0xf, 0x13680, 32}, /* PATTERN_RESONANCE_3T */ + {0x1f, 0xf, 2, 0xf, 0x13a80, 32}, /* PATTERN_RESONANCE_4T */ + {0x1f, 0xf, 2, 0xf, 0x13e80, 32}, /* PATTERN_RESONANCE_5T */ + {0x1f, 0xf, 2, 0xf, 0x14280, 32}, /* PATTERN_RESONANCE_6T */ + {0x1f, 0xf, 2, 0xf, 0x14680, 32}, /* PATTERN_RESONANCE_7T */ + {0x1f, 0xf, 2, 0xf, 0x14a80, 32}, /* PATTERN_RESONANCE_8T */ + {0x1f, 0xf, 2, 0xf, 0x14e80, 32}, /* PATTERN_RESONANCE_9T */ + {0x1f, 0xf, 2, 0xf, 0x15280, 32}, /* PATTERN_ZERO */ + {0x1f, 0xf, 2, 0xf, 0x15680, 32} /* PATTERN_ONE */ + /* Note: actual start_address is "<< 3" of defined address */ +}; struct pattern_info pattern_table_16[] = { /* @@ -87,7 +210,10 @@ struct pattern_info pattern_table_16[] = { */ {1, 1, 2, 1, 0x0080, 2}, /* PATTERN_PBS1 */ {1, 1, 2, 1, 0x00c0, 2}, /* PATTERN_PBS2 */ + {1, 1, 2, 1, 0x0380, 2}, /* PATTERN_PBS3 */ + {1, 1, 2, 1, 0x0040, 2}, /* PATTERN_TEST */ {1, 1, 2, 1, 0x0100, 2}, /* PATTERN_RL */ + {1, 1, 2, 1, 0x0000, 2}, /* PATTERN_RL2 */ {0xf, 0x7, 2, 0x7, 0x0140, 16}, /* PATTERN_STATIC_PBS */ {0xf, 0x7, 2, 0x7, 0x0190, 16}, /* PATTERN_KILLER_DQ0 */ {0xf, 0x7, 2, 0x7, 0x01d0, 16}, /* PATTERN_KILLER_DQ1 */ @@ -97,15 +223,29 @@ struct pattern_info pattern_table_16[] = { {0xf, 0x7, 2, 0x7, 0x02d0, 16}, /* PATTERN_KILLER_DQ5 */ {0xf, 0x7, 2, 0x7, 0x0310, 16}, /* PATTERN_KILLER_DQ6 */ {0xf, 0x7, 2, 0x7, 0x0350, 16}, /* PATTERN_KILLER_DQ7 */ - {1, 1, 2, 1, 0x0380, 2}, /* PATTERN_PBS3 */ - {1, 1, 2, 1, 0x0000, 2}, /* PATTERN_RL2 */ - {1, 1, 2, 1, 0x0040, 2}, /* PATTERN_TEST */ + {0xf, 0x7, 2, 0x7, 0x04c0, 16}, /* PATTERN_VREF */ {0xf, 0x7, 2, 0x7, 0x03c0, 16}, /* PATTERN_FULL_SSO_1T */ {0xf, 0x7, 2, 0x7, 0x0400, 16}, /* PATTERN_FULL_SSO_2T */ {0xf, 0x7, 2, 0x7, 0x0440, 16}, /* PATTERN_FULL_SSO_3T */ {0xf, 0x7, 2, 0x7, 0x0480, 16}, /* PATTERN_FULL_SSO_4T */ - {0xf, 0x7, 2, 0x7, 0x04c0, 16} /* PATTERN_VREF */ - /*Note: actual start_address is <<3 of defined addess */ + {0xf, 7, 2, 7, 0x6280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0xf, 7, 2, 7, 0x6680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0xf, 7, 2, 7, 0x6A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0xf, 7, 2, 7, 0x6E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0xf, 7, 2, 7, 0x7280, 16}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0xf, 7, 2, 7, 0x7680, 16}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0xf, 7, 2, 7, 0x7A80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0xf, 7, 2, 7, 0x7E80, 16}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0xf, 7, 2, 7, 0x8280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0xf, 7, 2, 7, 0x8680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0xf, 7, 2, 7, 0x8A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0xf, 7, 2, 7, 0x8E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0xf, 7, 2, 7, 0x9280, 16}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0xf, 7, 2, 7, 0x9680, 16}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0xf, 7, 2, 7, 0x9A80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0xf, 7, 2, 7, 0x9E80, 16}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0xf, 7, 2, 7, 0xA280, 16} /* PATTERN_ISI_XTALK_FREE */ + /* Note: actual start_address is "<< 3" of defined address */ }; struct pattern_info pattern_table_32[] = { @@ -115,7 +255,10 @@ struct pattern_info pattern_table_32[] = { */ {3, 3, 2, 3, 0x0080, 4}, /* PATTERN_PBS1 */ {3, 3, 2, 3, 0x00c0, 4}, /* PATTERN_PBS2 */ + {3, 3, 2, 3, 0x0380, 4}, /* PATTERN_PBS3 */ + {3, 3, 2, 3, 0x0040, 4}, /* PATTERN_TEST */ {3, 3, 2, 3, 0x0100, 4}, /* PATTERN_RL */ + {3, 3, 2, 3, 0x0000, 4}, /* PATTERN_RL2 */ {0x1f, 0xf, 2, 0xf, 0x0140, 32}, /* PATTERN_STATIC_PBS */ {0x1f, 0xf, 2, 0xf, 0x0190, 32}, /* PATTERN_KILLER_DQ0 */ {0x1f, 0xf, 2, 0xf, 0x01d0, 32}, /* PATTERN_KILLER_DQ1 */ @@ -125,15 +268,29 @@ struct pattern_info pattern_table_32[] = { {0x1f, 0xf, 2, 0xf, 0x02d0, 32}, /* PATTERN_KILLER_DQ5 */ {0x1f, 0xf, 2, 0xf, 0x0310, 32}, /* PATTERN_KILLER_DQ6 */ {0x1f, 0xf, 2, 0xf, 0x0350, 32}, /* PATTERN_KILLER_DQ7 */ - {3, 3, 2, 3, 0x0380, 4}, /* PATTERN_PBS3 */ - {3, 3, 2, 3, 0x0000, 4}, /* PATTERN_RL2 */ - {3, 3, 2, 3, 0x0040, 4}, /* PATTERN_TEST */ + {0x1f, 0xf, 2, 0xf, 0x04c0, 32}, /* PATTERN_VREF */ {0x1f, 0xf, 2, 0xf, 0x03c0, 32}, /* PATTERN_FULL_SSO_1T */ {0x1f, 0xf, 2, 0xf, 0x0400, 32}, /* PATTERN_FULL_SSO_2T */ {0x1f, 0xf, 2, 0xf, 0x0440, 32}, /* PATTERN_FULL_SSO_3T */ {0x1f, 0xf, 2, 0xf, 0x0480, 32}, /* PATTERN_FULL_SSO_4T */ - {0x1f, 0xf, 2, 0xf, 0x04c0, 32} /* PATTERN_VREF */ - /*Note: actual start_address is <<3 of defined addess */ + {0x1f, 0xF, 2, 0xf, 0x6280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ0 */ + {0x1f, 0xF, 2, 0xf, 0x6680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ1 */ + {0x1f, 0xF, 2, 0xf, 0x6A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ2 */ + {0x1f, 0xF, 2, 0xf, 0x6E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ3 */ + {0x1f, 0xF, 2, 0xf, 0x7280, 32}, /* PATTERN_SSO_FULL_XTALK_DQ4 */ + {0x1f, 0xF, 2, 0xf, 0x7680, 32}, /* PATTERN_SSO_FULL_XTALK_DQ5 */ + {0x1f, 0xF, 2, 0xf, 0x7A80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ6 */ + {0x1f, 0xF, 2, 0xf, 0x7E80, 32}, /* PATTERN_SSO_FULL_XTALK_DQ7 */ + {0x1f, 0xF, 2, 0xf, 0x8280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ0 */ + {0x1f, 0xF, 2, 0xf, 0x8680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ1 */ + {0x1f, 0xF, 2, 0xf, 0x8A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ2 */ + {0x1f, 0xF, 2, 0xf, 0x8E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ3 */ + {0x1f, 0xF, 2, 0xf, 0x9280, 32}, /* PATTERN_SSO_XTALK_FREE_DQ4 */ + {0x1f, 0xF, 2, 0xf, 0x9680, 32}, /* PATTERN_SSO_XTALK_FREE_DQ5 */ + {0x1f, 0xF, 2, 0xf, 0x9A80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ6 */ + {0x1f, 0xF, 2, 0xf, 0x9E80, 32}, /* PATTERN_SSO_XTALK_FREE_DQ7 */ + {0x1f, 0xF, 2, 0xf, 0xA280, 32} /* PATTERN_ISI_XTALK_FREE */ + /* Note: actual start_address is "<< 3" of defined address */ }; u32 train_dev_num; @@ -165,6 +322,10 @@ u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search, return buf_ptr; } +enum { + PASS, + FAIL +}; /* * IP Training search * Note: for one edge search only from fail to pass, else jitter can @@ -182,18 +343,19 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, enum hws_ddr_cs cs_type, u32 cs_num, enum hws_training_ip_stat *train_status) { - u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, poll_cnt, + u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, reg_data, pup_id; u32 tx_burst_size; u32 delay_between_burst; u32 rd_mode; - u32 read_data[MAX_INTERFACE_NUM]; + u32 data; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (pup_num >= tm->num_of_bus_per_interface) { + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, ("pup_num %d not valid\n", pup_num)); } @@ -213,20 +375,20 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, /* All CSs to CS0 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - CS_ENABLE_REG, 1 << 3, 1 << 3)); + DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3)); /* All CSs to CS0 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_DATA_CONTROL_REG, + ODPG_DATA_CTRL_REG, (0x3 | (effective_cs << 26)), 0xc000003)); } else { CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - CS_ENABLE_REG, 0, 1 << 3)); + DUAL_DUNIT_CFG_REG, 0, 1 << 3)); /* CS select */ CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_DATA_CONTROL_REG, 0x3 | cs_num << 26, + ODPG_DATA_CTRL_REG, 0x3 | cs_num << 26, 0x3 | 3 << 26)); } @@ -248,7 +410,7 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa; CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_WRITE_READ_MODE_ENABLE_REG, reg_data, + ODPG_WR_RD_MODE_ENA_REG, reg_data, MASK_ALL_BITS)); reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6; reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ? @@ -271,13 +433,13 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, - ODPG_TRAINING_CONTROL_REG, + GENERAL_TRAINING_OPCODE_REG, reg_data | (0x7 << 8) | (0x7 << 11), (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) | (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20)))); reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, interface_num, ODPG_OBJ1_OPCODE_REG, + (dev_num, access_type, interface_num, OPCODE_REG0_REG(1), 1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26), 0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26))); @@ -286,7 +448,7 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Max number of iterations */ CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num, - ODPG_OBJ1_ITER_CNT_REG, num_iter, + OPCODE_REG1_REG(1), num_iter, 0xffff)); if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW && direction == OPER_READ) { @@ -294,12 +456,10 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Write2_dunit(0x10c0, 0x5f , [7:0]) * MC PBS Reg Address at DDR PHY */ - reg_data = 0x5f + - effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET; + reg_data = PBS_RX_BCAST_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW && direction == OPER_WRITE) { - reg_data = 0x1f + - effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET; + reg_data = PBS_TX_BCAST_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_ADLL && direction == OPER_WRITE) { /* @@ -310,11 +470,11 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, * Write2_dunit(0x10c0, 0x1 , [7:0]) * ADLL WR Reg Address at DDR PHY */ - reg_data = 1 + effective_cs * CS_REGISTER_ADDR_OFFSET; + reg_data = CTX_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_ADLL && direction == OPER_READ) { /* ADLL RD Reg Address at DDR PHY */ - reg_data = 3 + effective_cs * CS_REGISTER_ADDR_OFFSET; + reg_data = CRX_PHY_REG(effective_cs); } else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW && direction == OPER_WRITE) { /* TBD not defined in 0.5.0 requirement */ @@ -325,12 +485,12 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, reg_data |= (0x6 << 28); CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, interface_num, CALIB_OBJ_PRFA_REG, + (dev_num, access_type, interface_num, CAL_PHY_REG(1), reg_data | (init_value << 8), 0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28))); - mask_dq_num_of_regs = tm->num_of_bus_per_interface * BUS_WIDTH_IN_BITS; - mask_pup_num_of_regs = tm->num_of_bus_per_interface; + mask_dq_num_of_regs = octets_per_if_num * BUS_WIDTH_IN_BITS; + mask_pup_num_of_regs = octets_per_if_num; if (result_type == RESULT_PER_BIT) { for (index_cnt = 0; index_cnt < mask_dq_num_of_regs; @@ -342,15 +502,12 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, } /* Mask disabled buses */ - for (pup_id = 0; pup_id < tm->num_of_bus_per_interface; + for (pup_id = 0; pup_id < octets_per_if_num; pup_id++) { - if (IS_ACTIVE(tm->bus_act_mask, pup_id) == 1) + if (IS_BUS_ACTIVE(tm->bus_act_mask, pup_id) == 1) continue; - for (index_cnt = (mask_dq_num_of_regs - pup_id * 8); - index_cnt < - (mask_dq_num_of_regs - (pup_id + 1) * 8); - index_cnt++) { + for (index_cnt = (pup_id * 8); index_cnt < (pup_id + 1) * 8; index_cnt++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, interface_num, @@ -384,89 +541,24 @@ int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type, } } - /* Start Training Trigger */ - CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num, - ODPG_TRAINING_TRIGGER_REG, 1, 1)); - /* wait for all RFU tests to finish (or timeout) */ - /* WA for 16 bit mode, more investigation needed */ - mdelay(1); - - /* Training "Done ?" */ - for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) { - if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0) - continue; - - if (interface_mask & (1 << index_cnt)) { - /* need to check results for this Dunit */ - for (poll_cnt = 0; poll_cnt < max_polling_for_done; - poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - index_cnt, - ODPG_TRAINING_STATUS_REG, - ®_data, MASK_ALL_BITS)); - if ((reg_data & 0x2) != 0) { - /*done */ - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_SUCCESS; - break; - } - } - - if (poll_cnt == max_polling_for_done) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_TIMEOUT; - } - } - /* Be sure that ODPG done */ - CHECK_STATUS(is_odpg_access_done(dev_num, index_cnt)); - } - - /* Write ODPG done in Dunit */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_STATUS_DONE_REG, 0, 0x1)); + /* trigger training */ + mv_ddr_training_enable(); - /* wait for all Dunit tests to finish (or timeout) */ - /* Training "Done ?" */ - /* Training "Pass ?" */ - for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) { - if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0) - continue; - - if (interface_mask & (1 << index_cnt)) { - /* need to check results for this Dunit */ - for (poll_cnt = 0; poll_cnt < max_polling_for_done; - poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - index_cnt, - ODPG_TRAINING_TRIGGER_REG, - read_data, MASK_ALL_BITS)); - reg_data = read_data[index_cnt]; - if ((reg_data & 0x2) != 0) { - /* done */ - if ((reg_data & 0x4) == 0) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_SUCCESS; - } else { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_FAIL; - } - break; - } - } + /* wa for 16-bit mode: wait for all rfu tests to finish or timeout */ + mdelay(1); - if (poll_cnt == max_polling_for_done) { - train_status[index_cnt] = - HWS_TRAINING_IP_STATUS_TIMEOUT; - } - } + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) { + train_status[0] = HWS_TRAINING_IP_STATUS_TIMEOUT; + } else { /* training done; check for pass */ + if (data == PASS) + train_status[0] = HWS_TRAINING_IP_STATUS_SUCCESS; + else + train_status[0] = HWS_TRAINING_IP_STATUS_FAIL; } - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); return MV_OK; } @@ -480,32 +572,47 @@ int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type, { u32 pattern_length_cnt = 0; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (pattern_length_cnt = 0; pattern_length_cnt < pattern_table[pattern].pattern_len; - pattern_length_cnt++) { - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - ODPG_PATTERN_DATA_LOW_REG, - pattern_table_get_word(dev_num, pattern, - (u8) (pattern_length_cnt * - 2)), MASK_ALL_BITS)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, access_type, if_id, - ODPG_PATTERN_DATA_HI_REG, - pattern_table_get_word(dev_num, pattern, - (u8) (pattern_length_cnt * - 2 + 1)), - MASK_ALL_BITS)); + pattern_length_cnt++) { /* FIXME: the ecc patch below is only for a7040 A0 */ + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)/* || tm->bus_act_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK*/) { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_LOW_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt)), + MASK_ALL_BITS)); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_HIGH_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt)), + MASK_ALL_BITS)); + } else { + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_LOW_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt * 2)), + MASK_ALL_BITS)); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, access_type, if_id, + ODPG_DATA_WR_DATA_HIGH_REG, + pattern_table_get_word(dev_num, pattern, + (u8) (pattern_length_cnt * 2 + 1)), + MASK_ALL_BITS)); + } CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - ODPG_PATTERN_ADDR_REG, pattern_length_cnt, + ODPG_DATA_WR_ADDR_REG, pattern_length_cnt, MASK_ALL_BITS)); } CHECK_STATUS(ddr3_tip_if_write (dev_num, access_type, if_id, - ODPG_PATTERN_ADDR_OFFSET_REG, load_addr, MASK_ALL_BITS)); + ODPG_DATA_BUFFER_OFFS_REG, load_addr, MASK_ALL_BITS)); return MV_OK; } @@ -527,7 +634,7 @@ int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type, (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) | (addr_stress_jump << 29)); ret = ddr3_tip_if_write(dev_num, access_type, if_id, - ODPG_DATA_CONTROL_REG, data_value, 0xaffffffc); + ODPG_DATA_CTRL_REG, data_value, 0xaffffffc); if (ret != MV_OK) return ret; @@ -597,7 +704,8 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, u32 read_data[MAX_INTERFACE_NUM]; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * Agreed assumption: all CS mask contain same number of bits, @@ -605,11 +713,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, * all pups */ CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, CS_ENABLE_REG, + (dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG, (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3))); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_DATA_CONTROL_REG, (cs_num_type << 26), (3 << 26))); + ODPG_DATA_CTRL_REG, (cs_num_type << 26), (3 << 26))); DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE, ("Read_from_d_b %d cs_type %d oper %d result_type %d direction %d search %d pup_num %d if_id %d pup_access_type %d\n", is_read_from_db, cs_num_type, operation, @@ -621,7 +729,7 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, ("ddr3_tip_read_training_result load_res = NULL")); return MV_FAIL; } - if (pup_num >= tm->num_of_bus_per_interface) { + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, ("pup_num %d not valid\n", pup_num)); } @@ -639,11 +747,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, } else { /*pup_access_type == ACCESS_TYPE_MULTICAST) */ start_pup = 0; - end_pup = tm->num_of_bus_per_interface - 1; + end_pup = octets_per_if_num - 1; } for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_cnt); DEBUG_TRAINING_IP_ENGINE( DEBUG_LEVEL_TRACE, ("if_id %d start_pup %d end_pup %d pup_cnt %d\n", @@ -689,11 +797,11 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, MASK_ALL_BITS)); if (is_check_result_validity == 1) { if ((read_data[if_id] & - 0x02000000) == 0) { + TIP_ENG_LOCK) == 0) { interface_train_res [reg_offset] = - 0x02000000 + - 64 + cons_tap; + TIP_ENG_LOCK + + TIP_TX_DLL_RANGE_MAX; } else { interface_train_res [reg_offset] = @@ -737,60 +845,27 @@ int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, int ddr3_tip_load_all_pattern_to_mem(u32 dev_num) { u32 pattern = 0, if_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } - for (pattern = 0; pattern < PATTERN_LIMIT; pattern++) + for (pattern = 0; pattern < PATTERN_LAST; pattern++) ddr3_tip_load_pattern_to_mem(dev_num, pattern); return MV_OK; } -/* - * Wait till ODPG access is ready - */ -int is_odpg_access_done(u32 dev_num, u32 if_id) -{ - u32 poll_cnt = 0, data_value; - u32 read_data[MAX_INTERFACE_NUM]; - - for (poll_cnt = 0; poll_cnt < MAX_POLLING_ITERATIONS; poll_cnt++) { - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_BIST_DONE, read_data, MASK_ALL_BITS)); - data_value = read_data[if_id]; - if (((data_value >> ODPG_BIST_DONE_BIT_OFFS) & 0x1) == - ODPG_BIST_DONE_BIT_VALUE) { - data_value = data_value & 0xfffffffe; - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, ODPG_BIST_DONE, data_value, - MASK_ALL_BITS)); - break; - } - } - - if (poll_cnt >= MAX_POLLING_ITERATIONS) { - DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("Bist Activate: poll failure 2\n")); - return MV_FAIL; - } - - return MV_OK; -} - /* * Load specific pattern to memory using ODPG */ @@ -798,7 +873,7 @@ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern) { u32 reg_data, if_id; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* load pattern to memory */ /* @@ -813,73 +888,65 @@ int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern) (effective_cs << 26); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, reg_data, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, reg_data, MASK_ALL_BITS)); /* ODPG Write enable from BIST */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, (0x1 | (effective_cs << 26)), + ODPG_DATA_CTRL_REG, (0x1 | (effective_cs << 26)), 0xc000003)); /* disable error injection */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_DATA_ERROR_REG, 0, 0x1)); + ODPG_DATA_WR_DATA_ERR_REG, 0, 0x1)); /* load pattern to ODPG */ ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, pattern, pattern_table[pattern].start_addr); - for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - if (IS_ACTIVE(tm->if_act_mask, if_id) == 0) - continue; + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + SDRAM_ODT_CTRL_HIGH_REG, + 0x3, 0xf)); + } + + mv_ddr_odpg_enable(); + } else { CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1498, - 0x3, 0xf)); + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, (u32)(0x1 << 31), + (u32)(0x1 << 31))); } - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_ENABLE_REG, 0x1 << ODPG_ENABLE_OFFS, - (0x1 << ODPG_ENABLE_OFFS))); - mdelay(1); - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(is_odpg_access_done(dev_num, if_id)); - } + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) + return MV_FAIL; /* Disable ODPG and stop write to memory */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, (0x1 << 30), (u32) (0x3 << 30))); + ODPG_DATA_CTRL_REG, (0x1 << 30), (u32) (0x3 << 30))); /* return to default */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); - - /* Disable odt0 for CS0 training - need to adjust for multy CS */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x1498, - 0x0, 0xf)); + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + /* Disable odt0 for CS0 training - need to adjust for multy CS */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf)); + } /* temporary added */ mdelay(1); return MV_OK; } -/* - * Load specific pattern to memory using CPU - */ -int ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num, enum hws_pattern pattern, - u32 offset) -{ - /* eranba - TBD */ - return MV_OK; -} - /* * Training search routine */ @@ -902,8 +969,9 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, u32 interface_num = 0, start_if, end_if, init_value_used; enum hws_search_dir search_dir_id, start_search, end_search; enum hws_edge_compare edge_comp_used; - u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u8 cons_tap = 0; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (train_status == NULL) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, @@ -913,12 +981,12 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, if ((train_cs_type > CS_NON_SINGLE) || (edge_comp >= EDGE_PFP) || - (pattern >= PATTERN_LIMIT) || + (pattern >= PATTERN_LAST) || (direction > OPER_WRITE_AND_READ) || (search_dir > HWS_HIGH2LOW) || (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) || (result_type > RESULT_PER_BYTE) || - (pup_num >= tm->num_of_bus_per_interface) || + (pup_num >= octets_per_if_num) || (pup_access_type > ACCESS_TYPE_MULTICAST) || (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) { DEBUG_TRAINING_IP_ENGINE( @@ -968,7 +1036,7 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, for (interface_num = start_if; interface_num <= end_if; interface_num++) { - VALIDATE_ACTIVE(tm->if_act_mask, interface_num); + VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num); cs_num = 0; CHECK_STATUS(ddr3_tip_read_training_result (dev_num, interface_num, pup_access_type, @@ -982,48 +1050,99 @@ int ddr3_tip_ip_training_wrapper_int(u32 dev_num, return MV_OK; } - /* * Training search & read result routine + * This function implements the search algorithm + * first it calls the function ddr3_tip_ip_training_wrapper_int which triggers the search from l2h and h2l + * this function handles rx and tx search cases + * in case of rx it only triggers the search (l2h and h2l) + * in case of tx there are 3 optional algorithm phases: + * phase 1: + * it first triggers the search and handles the results as following (phase 1): + * each bit, which defined by the search two edges (e1 or VW_L and e2 or VW_H), match on of cases: + * 1. BIT_LOW_UI 0 =< VW =< 31 in case of jitter use: VW_L <= 31, VW_H <= 31 + * 2. BIT_HIGH_UI 32 =< VW =< 63 in case of jitter use: VW_L >= 32, VW_H >= 32 + * 3. BIT_SPLIT_IN VW_L <= 31 & VW_H >= 32 + * 4. BIT_SPLIT_OUT* VW_H < 32 & VW_L > 32 + * note: the VW units is adll taps + * phase 2: + * only bit case BIT_SPLIT_OUT requires another search (phase 2) from the middle range in two directions h2l and l2h + * because only this case is not locked by the search engine in the first search trigger (phase 1). + * phase 3: + * each subphy is categorized according to its bits definition. + * the sub-phy cases are as follows: + * 1.BYTE_NOT_DEFINED the byte has not yet been categorized + * 2.BYTE_HOMOGENEOUS_LOW 0 =< VW =< 31 + * 3.BYTE_HOMOGENEOUS_HIGH 32 =< VW =< 63 + * 4.BYTE_HOMOGENEOUS_SPLIT_IN VW_L <= 31 & VW_H >= 32 + * or the center of all bits in the byte =< 31 + * 5.BYTE_HOMOGENEOUS_SPLIT_OUT VW_H < 32 & VW_L > 32 + * 6.BYTE_SPLIT_OUT_MIX at least one bits is in split out state and one bit is in other + * or the center of all bits in the byte => 32 + * after the two phases above a center valid window for each subphy is calculated accordingly: + * center valid window = maximum center of all bits in the subphy - minimum center of all bits in the subphy. + * now decisions are made in each subphy as following: + * all subphys which are homogeneous remains as is + * all subphys which are homogeneous low | homogeneous high and the subphy center valid window is less than 32 + * mark this subphy as homogeneous split in. + * now the bits in the bytes which are BYTE_SPLIT_OUT_MIX needed to be reorganized and handles as following + * all bits which are BIT_LOW_UI will be added with 64 adll, + * this will hopefully ensures that all the bits in the sub phy can be sampled by the dqs */ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, - u32 if_id, - enum hws_access_type pup_access_type, - u32 pup_num, - enum hws_training_result result_type, - enum hws_control_element control_element, - enum hws_search_dir search_dir, - enum hws_dir direction, u32 interface_mask, - u32 init_value_l2h, u32 init_value_h2l, - u32 num_iter, enum hws_pattern pattern, - enum hws_edge_compare edge_comp, - enum hws_ddr_cs train_cs_type, u32 cs_num, - enum hws_training_ip_stat *train_status) + u32 if_id, + enum hws_access_type pup_access_type, + u32 pup_num, + enum hws_training_result result_type, + enum hws_control_element control_element, + enum hws_search_dir search_dir, + enum hws_dir direction, u32 interface_mask, + u32 init_value_l2h, u32 init_value_h2l, + u32 num_iter, enum hws_pattern pattern, + enum hws_edge_compare edge_comp, + enum hws_ddr_cs train_cs_type, u32 cs_num, + enum hws_training_ip_stat *train_status) { u8 e1, e2; - u32 interface_cnt, bit_id, start_if, end_if, bit_end = 0; + u32 bit_id, start_if, end_if, bit_end = 0; u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 }; u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0); u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0; - u8 pup_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (pup_num >= tm->num_of_bus_per_interface) { + u8 bit_state[MAX_BUS_NUM * BUS_WIDTH_IN_BITS] = {0}; + u8 h2l_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; + u8 l2h_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS]; + u8 center_subphy_adll_window[MAX_BUS_NUM]; + u8 min_center_subphy_adll[MAX_BUS_NUM]; + u8 max_center_subphy_adll[MAX_BUS_NUM]; + u32 *l2h_if_train_res = NULL; + u32 *h2l_if_train_res = NULL; + enum hws_search_dir search_dir_id; + int status; + u32 bit_lock_result; + + u8 sybphy_id; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + if (pup_num >= octets_per_if_num) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("pup_num %d not valid\n", pup_num)); + ("pup_num %d not valid\n", pup_num)); } if (if_id >= MAX_INTERFACE_NUM) { DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR, - ("if_id %d not valid\n", if_id)); + ("if_id %d not valid\n", if_id)); } - CHECK_STATUS(ddr3_tip_ip_training_wrapper_int - (dev_num, access_type, if_id, pup_access_type, pup_num, - ALL_BITS_PER_PUP, result_type, control_element, - search_dir, direction, interface_mask, init_value_l2h, - init_value_h2l, num_iter, pattern, edge_comp, - train_cs_type, cs_num, train_status)); + status = ddr3_tip_ip_training_wrapper_int + (dev_num, access_type, if_id, pup_access_type, pup_num, + ALL_BITS_PER_PUP, result_type, control_element, + search_dir, direction, interface_mask, init_value_l2h, + init_value_h2l, num_iter, pattern, edge_comp, + train_cs_type, cs_num, train_status); + + if (MV_OK != status) + return status; if (access_type == ACCESS_TYPE_MULTICAST) { start_if = 0; @@ -1033,181 +1152,337 @@ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, end_if = if_id; } - for (interface_cnt = start_if; interface_cnt <= end_if; - interface_cnt++) { - VALIDATE_ACTIVE(tm->if_act_mask, interface_cnt); - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); + for (if_id = start_if; if_id <= end_if; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + /* zero the database */ + bit_bit_mask_active = 0; /* clean the flag for level2 search */ + memset(bit_state, 0, sizeof(bit_state)); + /* phase 1 */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); if (result_type == RESULT_PER_BIT) - bit_end = BUS_WIDTH_IN_BITS - 1; + bit_end = BUS_WIDTH_IN_BITS; else bit_end = 0; - bit_bit_mask[pup_id] = 0; - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - enum hws_search_dir search_dir_id; - for (search_dir_id = HWS_LOW2HIGH; - search_dir_id <= HWS_HIGH2LOW; - search_dir_id++) { - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, search_dir_id, - direction, result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, - &result[search_dir_id], - 1, 0, 0)); + /* zero the data base */ + bit_bit_mask[sybphy_id] = 0; + byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED; + for (bit_id = 0; bit_id < bit_end; bit_id++) { + h2l_adll_value[sybphy_id][bit_id] = 64; + l2h_adll_value[sybphy_id][bit_id] = 0; + for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW; + search_dir_id++) { + status = ddr3_tip_read_training_result + (dev_num, if_id, + ACCESS_TYPE_UNICAST, sybphy_id, bit_id, + search_dir_id, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &result[search_dir_id], 1, 0, 0); + + if (MV_OK != status) + return status; } - e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], - EDGE_1); - e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], - EDGE_1); - DEBUG_TRAINING_IP_ENGINE( - DEBUG_LEVEL_INFO, - ("wrapper if_id %d pup_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n", - interface_cnt, pup_id, bit_id, - result[HWS_LOW2HIGH][0], e1, + + e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], EDGE_1); + e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], EDGE_1); + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_INFO, + ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n", + if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1, result[HWS_HIGH2LOW][0], e2)); - /* TBD validate is valid only for tx */ - if (VALIDATE_TRAINING_LIMIT(e1, e2) == 1 && - GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) && - GET_LOCK_RESULT(result[HWS_LOW2HIGH][0])) { - /* Mark problem bits */ - bit_bit_mask[pup_id] |= 1 << bit_id; - bit_bit_mask_active = 1; + bit_lock_result = + (GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) && + GET_LOCK_RESULT(result[HWS_HIGH2LOW][0])); + + if (bit_lock_result) { + /* in case of read operation set the byte status as homogeneous low */ + if (direction == OPER_READ) { + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW; + } else if ((e2 - e1) > 32) { /* oper_write */ + /* split out */ + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_SPLIT_OUT; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_SPLIT_OUT; + /* mark problem bits */ + bit_bit_mask[sybphy_id] |= (1 << bit_id); + bit_bit_mask_active = 1; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_SPLIT_OUT\n", + if_id, sybphy_id, bit_id)); + } else { + /* low ui */ + if (e1 <= 31 && e2 <= 31) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_LOW_UI; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_LOW_UI\n", + if_id, sybphy_id, bit_id)); + } + /* high ui */ + if (e1 >= 32 && e2 >= 32) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_HIGH_UI; + byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_HIGH; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_HIGH_UI\n", + if_id, sybphy_id, bit_id)); + } + /* split in */ + if (e1 <= 31 && e2 >= 32) { + bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] = + BIT_SPLIT_IN; + byte_status[if_id][sybphy_id] |= + BYTE_HOMOGENEOUS_SPLIT_IN; + l2h_adll_value[sybphy_id][bit_id] = e1; + h2l_adll_value[sybphy_id][bit_id] = e2; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d BIT_SPLIT_IN\n", + if_id, sybphy_id, bit_id)); + } + } + } else { + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_INFO, + ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x)" + "h2l 0x%x (e2 0x%x): bit cannot be categorized\n", + if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1, + result[HWS_HIGH2LOW][0], e2)); + /* mark the byte as not defined */ + byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED; + break; /* continue to next pup - no reason to analyze this byte */ } - } /* For all bits */ - } /* For all PUPs */ + } /* for all bits */ + } /* for all PUPs */ - /* Fix problem bits */ + /* phase 2 will occur only in write operation */ if (bit_bit_mask_active != 0) { - u32 *l2h_if_train_res = NULL; - u32 *h2l_if_train_res = NULL; - l2h_if_train_res = - ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, - result_type, - interface_cnt); - h2l_if_train_res = - ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, - result_type, - interface_cnt); - - ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST, - interface_cnt, - ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, result_type, - control_element, HWS_LOW2HIGH, - direction, interface_mask, - num_iter / 2, num_iter / 2, - pattern, EDGE_FP, train_cs_type, - cs_num, train_status); - - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); - pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); - - if (bit_bit_mask[pup_id] == 0) - continue; - - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - if ((bit_bit_mask[pup_id] & - (1 << bit_id)) == 0) + l2h_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, result_type, if_id); + h2l_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, result_type, if_id); + /* search from middle to end */ + ddr3_tip_ip_training + (dev_num, ACCESS_TYPE_UNICAST, + if_id, ACCESS_TYPE_MULTICAST, + PARAM_NOT_CARE, result_type, + control_element, HWS_LOW2HIGH, + direction, interface_mask, + num_iter / 2, num_iter / 2, + pattern, EDGE_FP, train_cs_type, + cs_num, train_status); + + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) { + if (bit_bit_mask[sybphy_id] == 0) + continue; /* this byte bits have no split out state */ + + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0) + continue; /* this bit is non split goto next bit */ + + /* enter the result to the data base */ + status = ddr3_tip_read_training_result + (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id, + bit_id, HWS_LOW2HIGH, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &l2h_if_train_res, 0, 0, 1); + + if (MV_OK != status) + return status; + + l2h_adll_value[sybphy_id][bit_id] = + l2h_if_train_res[sybphy_id * + BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK; + } + } + } + /* Search from middle to start */ + ddr3_tip_ip_training + (dev_num, ACCESS_TYPE_UNICAST, + if_id, ACCESS_TYPE_MULTICAST, + PARAM_NOT_CARE, result_type, + control_element, HWS_HIGH2LOW, + direction, interface_mask, + num_iter / 2, num_iter / 2, + pattern, EDGE_FP, train_cs_type, + cs_num, train_status); + + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) { + if (bit_bit_mask[sybphy_id] == 0) continue; - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, HWS_LOW2HIGH, - direction, - result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, &l2h_if_train_res, - 0, 0, 1)); + + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0) + continue; + + status = ddr3_tip_read_training_result + (dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id, + bit_id, HWS_HIGH2LOW, direction, result_type, + TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE, + &h2l_if_train_res, 0, cons_tap, 1); + + if (MV_OK != status) + return status; + + h2l_adll_value[sybphy_id][bit_id] = + h2l_if_train_res[sybphy_id * + BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK; + } } } + } /* end if bit_bit_mask_active */ + /* + * phase 3 will occur only in write operation + * find the maximum and the minimum center of each subphy + */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + + if ((byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) && (direction == OPER_WRITE)) { + /* clear the arrays and parameters */ + center_subphy_adll_window[sybphy_id] = 0; + max_center_subphy_adll[sybphy_id] = 0; + min_center_subphy_adll[sybphy_id] = 64; + /* find the max and min center adll value in the current subphy */ + for (bit_id = 0; bit_id < bit_end; bit_id++) { + /* debug print all the bit edges after alignment */ + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit %d l2h %d h2l %d\n", + if_id, sybphy_id, bit_id, l2h_adll_value[sybphy_id][bit_id], + h2l_adll_value[sybphy_id][bit_id])); + + if (((l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2) > + max_center_subphy_adll[sybphy_id]) + max_center_subphy_adll[sybphy_id] = + (l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2; + if (((l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2) < + min_center_subphy_adll[sybphy_id]) + min_center_subphy_adll[sybphy_id] = + (l2h_adll_value[sybphy_id][bit_id] + + h2l_adll_value[sybphy_id][bit_id]) / 2; + } - ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST, - interface_cnt, - ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, result_type, - control_element, HWS_HIGH2LOW, - direction, interface_mask, - num_iter / 2, num_iter / 2, - pattern, EDGE_FP, train_cs_type, - cs_num, train_status); - - for (pup_id = 0; - pup_id <= (tm->num_of_bus_per_interface - 1); - pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup_id); - - if (bit_bit_mask[pup_id] == 0) - continue; - - for (bit_id = 0; bit_id <= bit_end; bit_id++) { - if ((bit_bit_mask[pup_id] & - (1 << bit_id)) == 0) - continue; - CHECK_STATUS - (ddr3_tip_read_training_result - (dev_num, interface_cnt, - ACCESS_TYPE_UNICAST, pup_id, - bit_id, HWS_HIGH2LOW, direction, - result_type, - TRAINING_LOAD_OPERATION_UNLOAD, - CS_SINGLE, &h2l_if_train_res, - 0, cons_tap, 1)); + /* calculate the center of the current subphy */ + center_subphy_adll_window[sybphy_id] = + max_center_subphy_adll[sybphy_id] - + min_center_subphy_adll[sybphy_id]; + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d min center %d max center %d center %d\n", + if_id, sybphy_id, min_center_subphy_adll[sybphy_id], + max_center_subphy_adll[sybphy_id], + center_subphy_adll_window[sybphy_id])); + } + } + /* + * check byte state and fix bits state if needed + * in case the level 1 and 2 above subphy results are + * homogeneous continue to the next subphy + */ + for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id); + if ((byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_LOW) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_HIGH) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_IN) || + (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_OUT) || + (byte_status[if_id][sybphy_id] == BYTE_NOT_DEFINED)) + continue; + + /* + * in case all of the bits in the current subphy are + * less than 32 which will find alignment in the subphy bits + * mark this subphy as homogeneous split in + */ + if (center_subphy_adll_window[sybphy_id] <= 31) + byte_status[if_id][sybphy_id] = BYTE_HOMOGENEOUS_SPLIT_IN; + + /* + * in case the current byte is split_out and the center is bigger than 31 + * the byte can be aligned. in this case add 64 to the the low ui bits aligning it + * to the other ui bits + */ + if (center_subphy_adll_window[sybphy_id] >= 32) { + byte_status[if_id][sybphy_id] = BYTE_SPLIT_OUT_MIX; + + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d byte state 0x%x\n", + if_id, sybphy_id, byte_status[if_id][sybphy_id])); + for (bit_id = 0; bit_id < bit_end; bit_id++) { + if (bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] == BIT_LOW_UI) { + l2h_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64; + h2l_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64; + } + DEBUG_TRAINING_IP_ENGINE + (DEBUG_LEVEL_TRACE, + ("if_id %d sybphy_id %d bit_id %d added 64 adlls\n", + if_id, sybphy_id, bit_id)); } } - } /* if bit_bit_mask_active */ - } /* For all Interfacess */ + } + } /* for all interfaces */ return MV_OK; } +u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id) +{ + return byte_status[if_id][subphy_id]; +} + +void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data) +{ + byte_status[if_id][subphy_id] = byte_status_data; +} + /* * Load phy values */ int ddr3_tip_load_phy_values(int b_load) { u32 bus_cnt = 0, if_id, dev_num = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES(); - bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); if (b_load == 1) { CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CTX_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [0])); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - RL_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + RL_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [1])); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CRX_PHY_REG(effective_cs), &phy_reg_bk[if_id][bus_cnt] [2])); } else { @@ -1215,27 +1490,21 @@ int ddr3_tip_load_phy_values(int b_load) (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CTX_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [0])); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - RL_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + RL_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [1])); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG + - (effective_cs * - CS_REGISTER_ADDR_OFFSET), + CRX_PHY_REG(effective_cs), phy_reg_bk[if_id][bus_cnt] [2])); } @@ -1257,7 +1526,8 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM]; u32 *res = NULL; u32 search_state = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); ddr3_tip_load_phy_values(1); @@ -1279,11 +1549,11 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (pup_id = 0; pup_id < - tm->num_of_bus_per_interface; + octets_per_if_num; pup_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_id); CHECK_STATUS (ddr3_tip_read_training_result @@ -1322,11 +1592,20 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, return MV_OK; } +int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr) +{ + pattern_tbl[pattern].start_addr = addr; + + return 0; +} + struct pattern_info *ddr3_tip_get_pattern_table() { - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) + return pattern_table_64; + else if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) return pattern_table_32; else return pattern_table_16; @@ -1334,20 +1613,63 @@ struct pattern_info *ddr3_tip_get_pattern_table() u16 *ddr3_tip_get_mask_results_dq_reg() { - struct hws_topology_map *tm = ddr3_get_topology_map(); +#if MAX_BUS_NUM == 5 + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) return mask_results_dq_reg_map_pup3_ecc; else +#endif return mask_results_dq_reg_map; } u16 *ddr3_tip_get_mask_results_pup_reg_map() { - struct hws_topology_map *tm = ddr3_get_topology_map(); +#if MAX_BUS_NUM == 5 + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask)) return mask_results_pup_reg_map_pup3_ecc; else +#endif return mask_results_pup_reg_map; } + +/* load expected dm pattern to odpg */ +#define LOW_NIBBLE_BYTE_MASK 0xf +#define HIGH_NIBBLE_BYTE_MASK 0xf0 +int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern, + enum dm_direction dm_dir) +{ + struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 pattern_len = 0; + u32 data_low, data_high; + u8 dm_data; + + for (pattern_len = 0; + pattern_len < pattern_table[pattern].pattern_len; + pattern_len++) { + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) { + data_low = pattern_table_get_word(0, pattern, (u8)pattern_len); + data_high = data_low; + } else { + data_low = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2)); + data_high = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2 + 1)); + } + + /* odpg mbus dm definition is opposite to ddr4 protocol */ + if (dm_dir == DM_DIR_INVERSE) + dm_data = ~((data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK)); + else + dm_data = (data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK); + + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_LOW_REG, data_low, MASK_ALL_BITS); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_HIGH_REG, data_high, MASK_ALL_BITS); + ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_ADDR_REG, + pattern_len | ((dm_data & ODPG_DATA_WR_DATA_MASK) << ODPG_DATA_WR_DATA_OFFS), + MASK_ALL_BITS); + } + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h index b19bab1ef1..8fbcff50bb 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.h @@ -37,8 +37,6 @@ int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type, u32 num_of_iterations, u32 start_pattern, u32 end_pattern); int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern); -int ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num, enum hws_pattern pattern, - u32 offset); int ddr3_tip_load_all_pattern_to_mem(u32 dev_num); int ddr3_tip_read_training_result(u32 dev_num, u32 if_id, enum hws_access_type pup_access_type, @@ -75,10 +73,13 @@ int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type, enum hws_edge_compare edge_comp, enum hws_ddr_cs train_cs_type, u32 cs_num, enum hws_training_ip_stat *train_status); -int is_odpg_access_done(u32 dev_num, u32 if_id); +u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id); +void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data); void ddr3_tip_print_bist_res(void); struct pattern_info *ddr3_tip_get_pattern_table(void); u16 *ddr3_tip_get_mask_results_dq_reg(void); u16 *ddr3_tip_get_mask_results_pup_reg_map(void); - +int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern, + enum dm_direction dm_dir); +int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr); #endif /* _DDR3_TRAINING_IP_ENGINE_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h index 06e08dc34d..6a9ef35f64 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_flow.h @@ -8,45 +8,73 @@ #include "ddr3_training_ip.h" #include "ddr3_training_ip_pbs.h" - -#define MRS0_CMD 0x3 -#define MRS1_CMD 0x4 -#define MRS2_CMD 0x8 -#define MRS3_CMD 0x9 - -/* - * Definitions of INTERFACE registers - */ - -#define READ_BUFFER_SELECT 0x14a4 - -/* - * Definitions of PHY registers - */ +#include "mv_ddr_regs.h" #define KILLER_PATTERN_LENGTH 32 #define EXT_ACCESS_BURST_LENGTH 8 -#define IS_ACTIVE(if_mask , if_id) \ - ((if_mask) & (1 << (if_id))) +#define IS_ACTIVE(mask, id) \ + ((mask) & (1 << (id))) + #define VALIDATE_ACTIVE(mask, id) \ { \ if (IS_ACTIVE(mask, id) == 0) \ continue; \ } -#define GET_TOPOLOGY_NUM_OF_BUSES() \ - (ddr3_get_topology_map()->num_of_bus_per_interface) +#define IS_IF_ACTIVE(if_mask, if_id) \ + ((if_mask) & (1 << (if_id))) + +#define VALIDATE_IF_ACTIVE(mask, id) \ + { \ + if (IS_IF_ACTIVE(mask, id) == 0) \ + continue; \ + } + +#define IS_BUS_ACTIVE(if_mask , if_id) \ + (((if_mask) >> (if_id)) & 1) + +#define VALIDATE_BUS_ACTIVE(mask, id) \ + { \ + if (IS_BUS_ACTIVE(mask, id) == 0) \ + continue; \ + } #define DDR3_IS_ECC_PUP3_MODE(if_mask) \ - (((if_mask) == 0xb) ? 1 : 0) + (((if_mask) == BUS_MASK_16BIT_ECC_PUP3) ? 1 : 0) + #define DDR3_IS_ECC_PUP4_MODE(if_mask) \ - (((((if_mask) & 0x10) == 0)) ? 0 : 1) + ((if_mask == BUS_MASK_32BIT_ECC || if_mask == BUS_MASK_16BIT_ECC) ? 1 : 0) + #define DDR3_IS_16BIT_DRAM_MODE(mask) \ - (((((mask) & 0x4) == 0)) ? 1 : 0) + ((mask == BUS_MASK_16BIT || mask == BUS_MASK_16BIT_ECC || mask == BUS_MASK_16BIT_ECC_PUP3) ? 1 : 0) +#define DDR3_IS_ECC_PUP8_MODE(if_mask) \ + ((if_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK || if_mask == MV_DDR_64BIT_ECC_PUP8_BUS_MASK) ? 1 : 0) + +#define MV_DDR_IS_64BIT_DRAM_MODE(mask) \ + ((((mask) & MV_DDR_64BIT_BUS_MASK) == MV_DDR_64BIT_BUS_MASK) || \ + (((mask) & MV_DDR_64BIT_ECC_PUP8_BUS_MASK) == MV_DDR_64BIT_ECC_PUP8_BUS_MASK) ? 1 : 0) + +#define MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(mask, octets_per_if_num/* FIXME: get from ATF */) \ + ((octets_per_if_num == 9/* FIXME: get from ATF */) && \ + ((mask == BUS_MASK_32BIT) || \ + (mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK)) ? 1 : 0) + +#define MV_DDR_IS_HALF_BUS_DRAM_MODE(mask, octets_per_if_num/* FIXME: get from ATF */) \ + (MV_DDR_IS_32BIT_IN_64BIT_DRAM_MODE(mask, octets_per_if_num) || DDR3_IS_16BIT_DRAM_MODE(mask)) + +#define ECC_READ_BUS_0 0 +#define ECC_PHY_ACCESS_3 3 +#define ECC_PHY_ACCESS_4 4 +#define ECC_PHY_ACCESS_8 8 #define MEGA 1000000 #define BUS_WIDTH_IN_BITS 8 +#define MAX_POLLING_ITERATIONS 1000000 +#define NUM_OF_CS 4 +#define ADLL_LENGTH 32 + +#define GP_RSVD0_REG 0x182e0 /* * DFX address Space @@ -66,205 +94,20 @@ /* nsec */ #define TREFI_LOW 7800 #define TREFI_HIGH 3900 +#define AUTO_ZQC_TIMING 15384 + +enum mr_number { + MR_CMD0, + MR_CMD1, + MR_CMD2, + MR_CMD3, + MR_LAST +}; -#define TR2R_VALUE_REG 0x180 -#define TR2R_MASK_REG 0x180 -#define TRFC_MASK_REG 0x7f -#define TR2W_MASK_REG 0x600 -#define TW2W_HIGH_VALUE_REG 0x1800 -#define TW2W_HIGH_MASK_REG 0xf800 -#define TRFC_HIGH_VALUE_REG 0x20000 -#define TRFC_HIGH_MASK_REG 0x70000 -#define TR2R_HIGH_VALUE_REG 0x0 -#define TR2R_HIGH_MASK_REG 0x380000 -#define TMOD_VALUE_REG 0x16000000 -#define TMOD_MASK_REG 0x1e000000 -#define T_VALUE_REG 0x40000000 -#define T_MASK_REG 0xc0000000 -#define AUTO_ZQC_TIMING 15384 -#define WRITE_XBAR_PORT1 0xc03f8077 -#define READ_XBAR_PORT1 0xc03f8073 -#define DISABLE_DDR_TUNING_DATA 0x02294285 -#define ENABLE_DDR_TUNING_DATA 0x12294285 - -#define ODPG_TRAINING_STATUS_REG 0x18488 -#define ODPG_TRAINING_TRIGGER_REG 0x1030 -#define ODPG_STATUS_DONE_REG 0x16fc -#define ODPG_ENABLE_REG 0x186d4 -#define ODPG_ENABLE_OFFS 0 -#define ODPG_DISABLE_OFFS 8 - -#define ODPG_TRAINING_CONTROL_REG 0x1034 -#define ODPG_OBJ1_OPCODE_REG 0x103c -#define ODPG_OBJ1_ITER_CNT_REG 0x10b4 -#define CALIB_OBJ_PRFA_REG 0x10c4 -#define ODPG_WRITE_LEVELING_DONE_CNTR_REG 0x10f8 -#define ODPG_WRITE_READ_MODE_ENABLE_REG 0x10fc -#define TRAINING_OPCODE_1_REG 0x10b4 -#define SDRAM_CONFIGURATION_REG 0x1400 -#define DDR_CONTROL_LOW_REG 0x1404 -#define SDRAM_TIMING_LOW_REG 0x1408 -#define SDRAM_TIMING_HIGH_REG 0x140c -#define SDRAM_ACCESS_CONTROL_REG 0x1410 -#define SDRAM_OPEN_PAGE_CONTROL_REG 0x1414 -#define SDRAM_OPERATION_REG 0x1418 -#define DUNIT_CONTROL_HIGH_REG 0x1424 -#define ODT_TIMING_LOW 0x1428 -#define DDR_TIMING_REG 0x142c -#define ODT_TIMING_HI_REG 0x147c -#define SDRAM_INIT_CONTROL_REG 0x1480 -#define SDRAM_ODT_CONTROL_HIGH_REG 0x1498 -#define DUNIT_ODT_CONTROL_REG 0x149c -#define READ_BUFFER_SELECT_REG 0x14a4 -#define DUNIT_MMASK_REG 0x14b0 -#define CALIB_MACHINE_CTRL_REG 0x14cc -#define DRAM_DLL_TIMING_REG 0x14e0 -#define DRAM_ZQ_INIT_TIMIMG_REG 0x14e4 -#define DRAM_ZQ_TIMING_REG 0x14e8 -#define DFS_REG 0x1528 -#define READ_DATA_SAMPLE_DELAY 0x1538 -#define READ_DATA_READY_DELAY 0x153c -#define TRAINING_REG 0x15b0 -#define TRAINING_SW_1_REG 0x15b4 -#define TRAINING_SW_2_REG 0x15b8 -#define TRAINING_PATTERN_BASE_ADDRESS_REG 0x15bc -#define TRAINING_DBG_1_REG 0x15c0 -#define TRAINING_DBG_2_REG 0x15c4 -#define TRAINING_DBG_3_REG 0x15c8 -#define RANK_CTRL_REG 0x15e0 -#define TIMING_REG 0x15e4 -#define DRAM_PHY_CONFIGURATION 0x15ec -#define MR0_REG 0x15d0 -#define MR1_REG 0x15d4 -#define MR2_REG 0x15d8 -#define MR3_REG 0x15dc -#define TIMING_REG 0x15e4 -#define ODPG_CTRL_CONTROL_REG 0x1600 -#define ODPG_DATA_CONTROL_REG 0x1630 -#define ODPG_PATTERN_ADDR_OFFSET_REG 0x1638 -#define ODPG_DATA_BUF_SIZE_REG 0x163c -#define PHY_LOCK_STATUS_REG 0x1674 -#define PHY_REG_FILE_ACCESS 0x16a0 -#define TRAINING_WRITE_LEVELING_REG 0x16ac -#define ODPG_PATTERN_ADDR_REG 0x16b0 -#define ODPG_PATTERN_DATA_HI_REG 0x16b4 -#define ODPG_PATTERN_DATA_LOW_REG 0x16b8 -#define ODPG_BIST_LAST_FAIL_ADDR_REG 0x16bc -#define ODPG_BIST_DATA_ERROR_COUNTER_REG 0x16c0 -#define ODPG_BIST_FAILED_DATA_HI_REG 0x16c4 -#define ODPG_BIST_FAILED_DATA_LOW_REG 0x16c8 -#define ODPG_WRITE_DATA_ERROR_REG 0x16cc -#define CS_ENABLE_REG 0x16d8 -#define WR_LEVELING_DQS_PATTERN_REG 0x16dc - -#define ODPG_BIST_DONE 0x186d4 -#define ODPG_BIST_DONE_BIT_OFFS 0 -#define ODPG_BIST_DONE_BIT_VALUE 0 - -#define RESULT_CONTROL_BYTE_PUP_0_REG 0x1830 -#define RESULT_CONTROL_BYTE_PUP_1_REG 0x1834 -#define RESULT_CONTROL_BYTE_PUP_2_REG 0x1838 -#define RESULT_CONTROL_BYTE_PUP_3_REG 0x183c -#define RESULT_CONTROL_BYTE_PUP_4_REG 0x18b0 - -#define RESULT_CONTROL_PUP_0_BIT_0_REG 0x18b4 -#define RESULT_CONTROL_PUP_0_BIT_1_REG 0x18b8 -#define RESULT_CONTROL_PUP_0_BIT_2_REG 0x18bc -#define RESULT_CONTROL_PUP_0_BIT_3_REG 0x18c0 -#define RESULT_CONTROL_PUP_0_BIT_4_REG 0x18c4 -#define RESULT_CONTROL_PUP_0_BIT_5_REG 0x18c8 -#define RESULT_CONTROL_PUP_0_BIT_6_REG 0x18cc -#define RESULT_CONTROL_PUP_0_BIT_7_REG 0x18f0 -#define RESULT_CONTROL_PUP_1_BIT_0_REG 0x18f4 -#define RESULT_CONTROL_PUP_1_BIT_1_REG 0x18f8 -#define RESULT_CONTROL_PUP_1_BIT_2_REG 0x18fc -#define RESULT_CONTROL_PUP_1_BIT_3_REG 0x1930 -#define RESULT_CONTROL_PUP_1_BIT_4_REG 0x1934 -#define RESULT_CONTROL_PUP_1_BIT_5_REG 0x1938 -#define RESULT_CONTROL_PUP_1_BIT_6_REG 0x193c -#define RESULT_CONTROL_PUP_1_BIT_7_REG 0x19b0 -#define RESULT_CONTROL_PUP_2_BIT_0_REG 0x19b4 -#define RESULT_CONTROL_PUP_2_BIT_1_REG 0x19b8 -#define RESULT_CONTROL_PUP_2_BIT_2_REG 0x19bc -#define RESULT_CONTROL_PUP_2_BIT_3_REG 0x19c0 -#define RESULT_CONTROL_PUP_2_BIT_4_REG 0x19c4 -#define RESULT_CONTROL_PUP_2_BIT_5_REG 0x19c8 -#define RESULT_CONTROL_PUP_2_BIT_6_REG 0x19cc -#define RESULT_CONTROL_PUP_2_BIT_7_REG 0x19f0 -#define RESULT_CONTROL_PUP_3_BIT_0_REG 0x19f4 -#define RESULT_CONTROL_PUP_3_BIT_1_REG 0x19f8 -#define RESULT_CONTROL_PUP_3_BIT_2_REG 0x19fc -#define RESULT_CONTROL_PUP_3_BIT_3_REG 0x1a30 -#define RESULT_CONTROL_PUP_3_BIT_4_REG 0x1a34 -#define RESULT_CONTROL_PUP_3_BIT_5_REG 0x1a38 -#define RESULT_CONTROL_PUP_3_BIT_6_REG 0x1a3c -#define RESULT_CONTROL_PUP_3_BIT_7_REG 0x1ab0 -#define RESULT_CONTROL_PUP_4_BIT_0_REG 0x1ab4 -#define RESULT_CONTROL_PUP_4_BIT_1_REG 0x1ab8 -#define RESULT_CONTROL_PUP_4_BIT_2_REG 0x1abc -#define RESULT_CONTROL_PUP_4_BIT_3_REG 0x1ac0 -#define RESULT_CONTROL_PUP_4_BIT_4_REG 0x1ac4 -#define RESULT_CONTROL_PUP_4_BIT_5_REG 0x1ac8 -#define RESULT_CONTROL_PUP_4_BIT_6_REG 0x1acc -#define RESULT_CONTROL_PUP_4_BIT_7_REG 0x1af0 - -#define WL_PHY_REG 0x0 -#define WRITE_CENTRALIZATION_PHY_REG 0x1 -#define RL_PHY_REG 0x2 -#define READ_CENTRALIZATION_PHY_REG 0x3 -#define PBS_RX_PHY_REG 0x50 -#define PBS_TX_PHY_REG 0x10 -#define PHY_CONTROL_PHY_REG 0x90 -#define BW_PHY_REG 0x92 -#define RATE_PHY_REG 0x94 -#define CMOS_CONFIG_PHY_REG 0xa2 -#define PAD_ZRI_CALIB_PHY_REG 0xa4 -#define PAD_ODT_CALIB_PHY_REG 0xa6 -#define PAD_CONFIG_PHY_REG 0xa8 -#define PAD_PRE_DISABLE_PHY_REG 0xa9 -#define TEST_ADLL_REG 0xbf -#define CSN_IOB_VREF_REG(cs) (0xdb + (cs * 12)) -#define CSN_IO_BASE_VREF_REG(cs) (0xd0 + (cs * 12)) - -#define RESULT_DB_PHY_REG_ADDR 0xc0 -#define RESULT_DB_PHY_REG_RX_OFFSET 5 -#define RESULT_DB_PHY_REG_TX_OFFSET 0 - -/* TBD - for NP5 use only CS 0 */ -#define PHY_WRITE_DELAY(cs) WL_PHY_REG -/*( ( _cs_ == 0 ) ? 0x0 : 0x4 )*/ -/* TBD - for NP5 use only CS 0 */ -#define PHY_READ_DELAY(cs) RL_PHY_REG - -#define DDR0_ADDR_1 0xf8258 -#define DDR0_ADDR_2 0xf8254 -#define DDR1_ADDR_1 0xf8270 -#define DDR1_ADDR_2 0xf8270 -#define DDR2_ADDR_1 0xf825c -#define DDR2_ADDR_2 0xf825c -#define DDR3_ADDR_1 0xf8264 -#define DDR3_ADDR_2 0xf8260 -#define DDR4_ADDR_1 0xf8274 -#define DDR4_ADDR_2 0xf8274 - -#define GENERAL_PURPOSE_RESERVED0_REG 0x182e0 - -#define GET_BLOCK_ID_MAX_FREQ(dev_num, block_id) 800000 -#define CS0_RD_LVL_REF_DLY_OFFS 0 -#define CS0_RD_LVL_REF_DLY_LEN 0 -#define CS0_RD_LVL_PH_SEL_OFFS 0 -#define CS0_RD_LVL_PH_SEL_LEN 0 - -#define CS_REGISTER_ADDR_OFFSET 4 -#define CALIBRATED_OBJECTS_REG_ADDR_OFFSET 0x10 - -#define MAX_POLLING_ITERATIONS 100000 - -#define PHASE_REG_OFFSET 32 -#define NUM_BYTES_IN_BURST 31 -#define NUM_OF_CS 4 -#define CS_REG_VALUE(cs_num) (cs_mask_reg[cs_num]) -#define ADLL_LENGTH 32 +struct mv_ddr_mr_data { + u32 cmd; + u32 reg_addr; +}; struct write_supp_result { enum hws_wl_supp stage; @@ -314,10 +157,11 @@ int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr, int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr, u32 num_of_bursts, u32 *addr); int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 ui_freq); +int mv_ddr_rl_dqs_burst(u32 dev_num, u32 if_id, u32 freq); int ddr3_tip_legacy_dynamic_read_leveling(u32 dev_num); int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 ui_freq); int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num); -int ddr3_tip_dynamic_write_leveling(u32 dev_num); +int ddr3_tip_dynamic_write_leveling(u32 dev_num, int phase_remove); int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num); int ddr3_tip_static_init_controller(u32 dev_num); int ddr3_tip_configure_phy(u32 dev_num); @@ -331,18 +175,21 @@ int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type, u32 delay_between_burst, u32 rd_mode, u32 cs_num, u32 addr_stress_jump, u32 single_pattern); int ddr3_tip_set_atr(u32 dev_num, u32 flag_id, u32 value); -int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, u32 cmd, u32 data, - u32 mask); +int ddr3_tip_write_mrs_cmd(u32 dev_num, u32 *cs_mask_arr, enum mr_number mr_num, u32 data, u32 mask); int ddr3_tip_write_cs_result(u32 dev_num, u32 offset); int ddr3_tip_get_first_active_if(u8 dev_num, u32 interface_mask, u32 *if_id); int ddr3_tip_reset_fifo_ptr(u32 dev_num); -int read_pup_value(int pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr, u32 mask); -int read_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr, u32 mask); -int write_adll_value(u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], - int reg_addr); +int ddr3_tip_read_pup_value(u32 dev_num, + u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + int reg_addr, u32 mask); +int ddr3_tip_read_adll_value(u32 dev_num, + u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 reg_addr, u32 mask); +int ddr3_tip_write_adll_value(u32 dev_num, + u32 pup_values[MAX_INTERFACE_NUM * MAX_BUS_NUM], + u32 reg_addr); int ddr3_tip_tune_training_params(u32 dev_num, struct tune_train_params *params); +struct page_element *mv_ddr_page_tbl_get(void); #endif /* _DDR3_TRAINING_IP_FLOW_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h index 352bc0ce26..f614d688c9 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_ip_prv_if.h @@ -62,7 +62,7 @@ typedef int (*HWS_TRAINING_IP_PBS_TX_FUNC_PTR)(u32 dev_num); typedef int (*HWS_TRAINING_IP_SELECT_CONTROLLER_FUNC_PTR)( u32 dev_num, int enable); typedef int (*HWS_TRAINING_IP_TOPOLOGY_MAP_LOAD_FUNC_PTR)( - u32 dev_num, struct hws_topology_map *topology_map); + u32 dev_num, struct mv_ddr_topology_map *tm); typedef int (*HWS_TRAINING_IP_STATIC_CONFIG_FUNC_PTR)( u32 dev_num, enum hws_ddr_freq frequency, enum hws_static_config_type static_config_type, u32 if_id); @@ -83,16 +83,27 @@ typedef int (*HWS_TRAINING_IP_LOAD_TOPOLOGY)(u32 dev_num, u32 config_num); typedef int (*HWS_TRAINING_IP_READ_LEVELING)(u32 dev_num, u32 config_num); typedef int (*HWS_TRAINING_IP_WRITE_LEVELING)(u32 dev_num, u32 config_num); typedef u32 (*HWS_TRAINING_IP_GET_TEMP)(u8 dev_num); +typedef u8 (*HWS_TRAINING_IP_GET_RATIO)(u32 freq); struct hws_tip_config_func_db { HWS_TIP_DUNIT_MUX_SELECT_FUNC_PTR tip_dunit_mux_select_func; - HWS_TIP_DUNIT_REG_READ_FUNC_PTR tip_dunit_read_func; - HWS_TIP_DUNIT_REG_WRITE_FUNC_PTR tip_dunit_write_func; + void (*mv_ddr_dunit_read)(u32 addr, u32 mask, u32 *data); + void (*mv_ddr_dunit_write)(u32 addr, u32 mask, u32 data); HWS_TIP_GET_FREQ_CONFIG_INFO tip_get_freq_config_info_func; HWS_TIP_GET_DEVICE_INFO tip_get_device_info_func; HWS_SET_FREQ_DIVIDER_FUNC_PTR tip_set_freq_divider_func; HWS_GET_CS_CONFIG_FUNC_PTR tip_get_cs_config_info; HWS_TRAINING_IP_GET_TEMP tip_get_temperature; + HWS_TRAINING_IP_GET_RATIO tip_get_clock_ratio; + HWS_TRAINING_IP_EXTERNAL_READ_PTR tip_external_read; + HWS_TRAINING_IP_EXTERNAL_WRITE_PTR tip_external_write; + int (*mv_ddr_phy_read)(enum hws_access_type phy_access, + u32 phy, enum hws_ddr_phy phy_type, + u32 reg_addr, u32 *data); + int (*mv_ddr_phy_write)(enum hws_access_type phy_access, + u32 phy, enum hws_ddr_phy phy_type, + u32 reg_addr, u32 data, + enum hws_operation op_type); }; int ddr3_tip_init_config_func(u32 dev_num, diff --git a/drivers/ddr/marvell/a38x/ddr3_training_ip_static.h b/drivers/ddr/marvell/a38x/ddr3_training_ip_static.h deleted file mode 100644 index d5760fce08..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_training_ip_static.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#ifndef _DDR3_TRAINING_IP_STATIC_H_ -#define _DDR3_TRAINING_IP_STATIC_H_ - -#include "ddr3_training_ip_def.h" -#include "ddr3_training_ip.h" - -struct trip_delay_element { - u32 dqs_delay; /* DQS delay (m_sec) */ - u32 ck_delay; /* CK Delay (m_sec) */ -}; - -struct hws_tip_static_config_info { - u32 silicon_delay; - struct trip_delay_element *package_trace_arr; - struct trip_delay_element *board_trace_arr; -}; - -int ddr3_tip_run_static_alg(u32 dev_num, enum hws_ddr_freq freq); -int ddr3_tip_init_static_config_db( - u32 dev_num, struct hws_tip_static_config_info *static_config_info); -int ddr3_tip_init_specific_reg_config(u32 dev_num, - struct reg_data *reg_config_arr); -int ddr3_tip_static_phy_init_controller(u32 dev_num); - -#endif /* _DDR3_TRAINING_IP_STATIC_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_leveling.c b/drivers/ddr/marvell/a38x/ddr3_training_leveling.c index 3a9e81f1b7..6248ffc3fb 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_leveling.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_leveling.c @@ -3,17 +3,9 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" -#define WL_ITERATION_NUM 10 -#define ONE_CLOCK_ERROR_SHIFT 2 -#define ALIGN_ERROR_SHIFT -2 +#define WL_ITERATION_NUM 10 static u32 pup_mask_table[] = { 0x000000ff, @@ -27,26 +19,30 @@ static struct write_supp_result wr_supp_res[MAX_INTERFACE_NUM][MAX_BUS_NUM]; static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num); static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num); static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num); -static int ddr3_tip_wl_supp_align_err_shift(u32 dev_num, u32 if_id, u32 bus_id, - u32 bus_id_delta); static int ddr3_tip_wl_supp_align_phase_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 offset, - u32 bus_id_delta); + u32 bus_id); static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id, - u32 edge_offset, u32 bus_id_delta); -static int ddr3_tip_wl_supp_one_clk_err_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 bus_id_delta); + u32 edge_offset); -u32 hws_ddr3_tip_max_cs_get(void) +u32 ddr3_tip_max_cs_get(u32 dev_num) { - u32 c_cs; + u32 c_cs, if_id, bus_id; static u32 max_cs; - struct hws_topology_map *tm = ddr3_get_topology_map(); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); if (!max_cs) { + CHECK_STATUS(ddr3_tip_get_first_active_if((u8)dev_num, + tm->if_act_mask, + &if_id)); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); + break; + } + for (c_cs = 0; c_cs < NUM_OF_CS; c_cs++) { VALIDATE_ACTIVE(tm-> - interface_params[0].as_bus_params[0]. + interface_params[if_id].as_bus_params[bus_id]. cs_bitmask, c_cs); max_cs++; } @@ -55,13 +51,17 @@ u32 hws_ddr3_tip_max_cs_get(void) return max_cs; } +enum { + PASS, + FAIL +}; /***************************************************************************** Dynamic read leveling ******************************************************************************/ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) { u32 data, mask; - u32 max_cs = hws_ddr3_tip_max_cs_get(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); u32 bus_num, if_id, cl_val; enum hws_speed_bin speed_bin_index; /* save current CS value */ @@ -71,82 +71,9 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) u8 rl_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM]; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); - struct hws_topology_map *tm = ddr3_get_topology_map(); - - if (rl_version == 0) { - /* OLD RL machine */ - data = 0x40; - data |= (1 << 20); - - /* TBD multi CS */ - CHECK_STATUS(ddr3_tip_if_write( - dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, TRAINING_REG, - data, 0x11ffff)); - CHECK_STATUS(ddr3_tip_if_write( - dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, - TRAINING_PATTERN_BASE_ADDRESS_REG, - 0, 0xfffffff8)); - CHECK_STATUS(ddr3_tip_if_write( - dev_num, ACCESS_TYPE_MULTICAST, - PARAM_NOT_CARE, TRAINING_REG, - (u32)(1 << 31), (u32)(1 << 31))); - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - training_result[training_stage][if_id] = TEST_SUCCESS; - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, - (u32)(1 << 31), TRAINING_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING( - DEBUG_LEVEL_ERROR, - ("RL: DDR3 poll failed(1) IF %d\n", - if_id)); - training_result[training_stage][if_id] = - TEST_FAILED; - - if (debug_mode == 0) - return MV_FAIL; - } - } - - /* read read-leveling result */ - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_REG, data_read, 1 << 30)); - /* exit read leveling mode */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_SW_2_REG, 0x8, 0x9)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_SW_1_REG, 1 << 16, 1 << 16)); - - /* disable RL machine all Trn_CS[3:0] , [16:0] */ - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_REG, 0, 0xf1ffff)); - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - if ((data_read[if_id] & (1 << 30)) == 0) { - DEBUG_LEVELING( - DEBUG_LEVEL_ERROR, - ("\n_read Leveling failed for IF %d\n", - if_id)); - training_result[training_stage][if_id] = - TEST_FAILED; - if (debug_mode == 0) - return MV_FAIL; - } - } - return MV_OK; - } + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); - /* NEW RL machine */ for (effective_cs = 0; effective_cs < NUM_OF_CS; effective_cs++) for (bus_num = 0; bus_num < MAX_BUS_NUM; bus_num++) for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) @@ -154,18 +81,18 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val, + DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } ddr3_tip_reset_fifo_ptr(dev_num); @@ -183,7 +110,7 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) /* BUS count is 0 shifted 26 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x3, 0x3)); + ODPG_DATA_CTRL_REG, 0x3, 0x3)); CHECK_STATUS(ddr3_tip_configure_odpg (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0, pattern_table[PATTERN_RL].num_of_phases_tx, 0, @@ -203,17 +130,17 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) /* General Training Opcode register */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_READ_MODE_ENABLE_REG, 0, + ODPG_WR_RD_MODE_ENA_REG, 0, MASK_ALL_BITS)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_CONTROL_REG, + GENERAL_TRAINING_OPCODE_REG, (0x301b01 | effective_cs << 2), 0x3c3fef)); /* Object1 opcode register 0 & 1 */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); speed_bin_index = tm->interface_params[if_id].speed_bin_index; cl_val = @@ -222,13 +149,13 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) mask = (0xff << 9) | (0x1f << 17) | (0x3 << 25); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_OBJ1_OPCODE_REG, data, mask)); + OPCODE_REG0_REG(1), data, mask)); } /* Set iteration count to max value */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_OPCODE_1_REG, 0xd00, 0xd00)); + OPCODE_REG1_REG(1), 0xd00, 0xd00)); /* * Phase 2: Mask config @@ -252,11 +179,11 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) /* data pup rd reset enable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - SDRAM_CONFIGURATION_REG, 0, (1 << 30))); + SDRAM_CFG_REG, 0, (1 << 30))); /* data pup rd reset disable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - SDRAM_CONFIGURATION_REG, (1 << 30), (1 << 30))); + SDRAM_CFG_REG, (1 << 30), (1 << 30))); /* training SW override & training RL mode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, @@ -270,72 +197,46 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_REG, (u32)(1 << 31), (u32)(1 << 31))); - /********* trigger training *******************/ - /* Trigger, poll on status and disable ODPG */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_TRIGGER_REG, 0x1, 0x1)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_STATUS_REG, 0x1, 0x1)); + /* trigger training */ + mv_ddr_training_enable(); - /* check for training done + results pass */ - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x2, 0x2, - ODPG_TRAINING_STATUS_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Training Done Failed\n")); + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n")); return MV_FAIL; } + /* check for training pass */ + if (data != PASS) + DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n")); - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - if_id, - ODPG_TRAINING_TRIGGER_REG, data_read, - 0x4)); - data = data_read[if_id]; - if (data != 0x0) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Training Result Failed\n")); - } - } + /* disable odpg; switch back to functional mode */ + mv_ddr_odpg_disable(); - /*disable ODPG - Back to functional mode */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_ENABLE_REG, 0x1 << ODPG_DISABLE_OFFS, - (0x1 << ODPG_DISABLE_OFFS))); - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x0, 0x1, - ODPG_ENABLE_REG, MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("ODPG disable failed ")); + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("odpg disable failed\n")); return MV_FAIL; } - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); + + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); /* double loop on bus, pup */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* check training done */ is_any_pup_fail = 0; for (bus_num = 0; - bus_num < tm->num_of_bus_per_interface; + bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, (1 << 25), (1 << 25), mask_results_pup_reg_map[bus_num], MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("\n_r_l: DDR3 poll failed(2) for bus %d", - bus_num)); + ("\n_r_l: DDR3 poll failed(2) for IF %d CS %d bus %d", + if_id, effective_cs, bus_num)); is_any_pup_fail = 1; } else { /* read result per pup */ @@ -374,26 +275,26 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) /* set ODPG to functional */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x0, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS)); /* * Copy the result from the effective CS search to the * real Functional CS */ - /*ddr3_tip_write_cs_result(dev_num, RL_PHY_REG); */ + /*ddr3_tip_write_cs_result(dev_num, RL_PHY_REG(0); */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x0, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS)); } for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { /* double loop on bus, pup */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_num = 0; - bus_num < tm->num_of_bus_per_interface; + bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); /* read result per pup from arry */ data = rl_values[effective_cs][bus_num][if_id]; data = (data & 0x1f) | @@ -403,9 +304,8 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) if_id, ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, - RL_PHY_REG + - ((effective_cs == - 0) ? 0x0 : 0x4), data); + RL_PHY_REG(effective_cs), + data); } } } @@ -413,11 +313,11 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) effective_cs = 0; for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* restore cs enable value */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); if (odt_config != 0) { CHECK_STATUS(ddr3_tip_write_additional_odt_setting @@ -426,7 +326,7 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (training_result[training_stage][if_id] == TEST_FAILED) return MV_FAIL; } @@ -440,8 +340,8 @@ int ddr3_tip_dynamic_read_leveling(u32 dev_num, u32 freq) int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num) { u32 c_cs, if_id, cs_mask = 0; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * In TRAINIUNG reg (0x15b0) write 0x80000008 | cs_mask: @@ -456,7 +356,7 @@ int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num) cs_mask = cs_mask | 1 << (20 + c_cs); for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, 0, TRAINING_REG, (0x80000008 | cs_mask), @@ -481,8 +381,8 @@ int ddr3_tip_legacy_dynamic_write_leveling(u32 dev_num) int ddr3_tip_legacy_dynamic_read_leveling(u32 dev_num) { u32 c_cs, if_id, cs_mask = 0; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* * In TRAINIUNG reg (0x15b0) write 0x80000040 | cs_mask: @@ -502,7 +402,7 @@ int ddr3_tip_legacy_dynamic_read_leveling(u32 dev_num) mdelay(100); for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, (u32)0x80000000, TRAINING_REG, @@ -535,38 +435,39 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) u32 data2_write[MAX_INTERFACE_NUM][MAX_BUS_NUM]; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_num = 0; - bus_num <= tm->num_of_bus_per_interface; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + bus_num <= octets_per_if_num; bus_num++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); per_bit_rl_pup_status[if_id][bus_num] = 0; data2_write[if_id][bus_num] = 0; /* read current value of phy register 0x3 */ CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG, + CRX_PHY_REG(0), &phyreg3_arr[if_id][bus_num])); } } /* NEW RL machine */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, &cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, &cs_enable_reg_val[if_id], MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } ddr3_tip_reset_fifo_ptr(dev_num); @@ -584,7 +485,7 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* BUS count is 0 shifted 26 */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x3, 0x3)); + ODPG_DATA_CTRL_REG, 0x3, 0x3)); CHECK_STATUS(ddr3_tip_configure_odpg (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0, pattern_table[PATTERN_TEST].num_of_phases_tx, 0, @@ -604,15 +505,15 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* General Training Opcode register */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_READ_MODE_ENABLE_REG, 0, + ODPG_WR_RD_MODE_ENA_REG, 0, MASK_ALL_BITS)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_CONTROL_REG, 0x301b01, 0x3c3fef)); + GENERAL_TRAINING_OPCODE_REG, 0x301b01, 0x3c3fef)); /* Object1 opcode register 0 & 1 */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); speed_bin_index = tm->interface_params[if_id].speed_bin_index; cl_val = @@ -621,13 +522,13 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) mask = (0xff << 9) | (0x1f << 17) | (0x3 << 25); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - ODPG_OBJ1_OPCODE_REG, data, mask)); + OPCODE_REG0_REG(1), data, mask)); } /* Set iteration count to max value */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_OPCODE_1_REG, 0xd00, 0xd00)); + OPCODE_REG1_REG(1), 0xd00, 0xd00)); /* * Phase 2: Mask config @@ -651,11 +552,11 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* data pup rd reset enable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - SDRAM_CONFIGURATION_REG, 0, (1 << 30))); + SDRAM_CFG_REG, 0, (1 << 30))); /* data pup rd reset disable */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - SDRAM_CONFIGURATION_REG, (1 << 30), (1 << 30))); + SDRAM_CFG_REG, (1 << 30), (1 << 30))); /* training SW override & training RL mode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, @@ -669,63 +570,37 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_REG, (u32)(1 << 31), (u32)(1 << 31))); - /********* trigger training *******************/ - /* Trigger, poll on status and disable ODPG */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_TRIGGER_REG, 0x1, 0x1)); - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_STATUS_REG, 0x1, 0x1)); + /* trigger training */ + mv_ddr_training_enable(); - /*check for training done + results pass */ - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x2, 0x2, - ODPG_TRAINING_STATUS_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Training Done Failed\n")); + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n")); return MV_FAIL; } + /* check for training pass */ + if (data != PASS) + DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n")); - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - if_id, - ODPG_TRAINING_TRIGGER_REG, data_read, - 0x4)); - data = data_read[if_id]; - if (data != 0x0) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Training Result Failed\n")); - } - } + /* disable odpg; switch back to functional mode */ + mv_ddr_odpg_disable(); - /*disable ODPG - Back to functional mode */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_ENABLE_REG, 0x1 << ODPG_DISABLE_OFFS, - (0x1 << ODPG_DISABLE_OFFS))); - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x0, 0x1, - ODPG_ENABLE_REG, MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("ODPG disable failed ")); + if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("odpg disable failed\n")); return MV_FAIL; } - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS)); + + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS); /* double loop on bus, pup */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* check training done */ for (bus_num = 0; - bus_num < tm->num_of_bus_per_interface; + bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); if (per_bit_rl_pup_status[if_id][bus_num] == 0) { @@ -795,11 +670,11 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* if there is DLL that is not checked yet */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bus_num = 0; - bus_num < tm->num_of_bus_per_interface; + bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); if (per_bit_rl_pup_status[if_id] [bus_num] != 1) { @@ -811,7 +686,7 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) if_id, ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, - READ_CENTRALIZATION_PHY_REG, + CRX_PHY_REG(0), (phyreg3_arr[if_id] [bus_num] + adll_array[curr_numb]))); @@ -828,18 +703,17 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) } /* for ( curr_numb = 0; curr_numb <3; curr_numb++) */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_num = 0; bus_num < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_num = 0; bus_num < octets_per_if_num; bus_num++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_num); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_num); if (per_bit_rl_pup_status[if_id][bus_num] == 1) ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_num, DDR_PHY_DATA, - RL_PHY_REG + - CS_REG_VALUE(effective_cs), + RL_PHY_REG(effective_cs), data2_write[if_id] [bus_num]); else @@ -881,22 +755,22 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) /* set ODPG to functional */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x0, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS)); /* * Copy the result from the effective CS search to the real * Functional CS */ - ddr3_tip_write_cs_result(dev_num, RL_PHY_REG); + ddr3_tip_write_cs_result(dev_num, RL_PHY_REG(0)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_DATA_CONTROL_REG, 0x0, MASK_ALL_BITS)); + ODPG_DATA_CTRL_REG, 0x0, MASK_ALL_BITS)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* restore cs enable value */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); if (odt_config != 0) { CHECK_STATUS(ddr3_tip_write_additional_odt_setting @@ -905,7 +779,7 @@ int ddr3_tip_dynamic_per_bit_read_leveling(u32 dev_num, u32 freq) } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (training_result[training_stage][if_id] == TEST_FAILED) return MV_FAIL; } @@ -918,7 +792,8 @@ int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs, { u32 all_bus_cs = 0, same_bus_cs; u32 bus_cnt; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); *cs_mask = same_bus_cs = CS_BIT_MASK; @@ -931,8 +806,8 @@ int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs, * If they are they are not the same then it's mixed mode so all CS * should be configured (when configuring the MRS) */ - for (bus_cnt = 0; bus_cnt < tm->num_of_bus_per_interface; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); all_bus_cs |= tm->interface_params[if_id]. as_bus_params[bus_cnt].cs_bitmask; @@ -953,9 +828,9 @@ int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs, /* * Dynamic write leveling */ -int ddr3_tip_dynamic_write_leveling(u32 dev_num) +int ddr3_tip_dynamic_write_leveling(u32 dev_num, int phase_remove) { - u32 reg_data = 0, iter, if_id, bus_cnt; + u32 reg_data = 0, temp = 0, iter, if_id, bus_cnt; u32 cs_enable_reg_val[MAX_INTERFACE_NUM] = { 0 }; u32 cs_mask[MAX_INTERFACE_NUM]; u32 read_data_sample_delay_vals[MAX_INTERFACE_NUM] = { 0 }; @@ -967,28 +842,36 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) u8 wl_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM]; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u32 cs_mask0[MAX_INTERFACE_NUM] = { 0 }; - u32 max_cs = hws_ddr3_tip_max_cs_get(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); training_result[training_stage][if_id] = TEST_SUCCESS; /* save Read Data Sample Delay */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_SAMPLE_DELAY, + RD_DATA_SMPL_DLYS_REG, read_data_sample_delay_vals, MASK_ALL_BITS)); /* save Read Data Ready Delay */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_READY_DELAY, read_data_ready_delay_vals, + RD_DATA_RDY_DLYS_REG, read_data_ready_delay_vals, MASK_ALL_BITS)); /* save current cs reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val, MASK_ALL_BITS)); + DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); + } + + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) < MV_TIP_REV_3) { + /* Enable multi-CS */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_UNICAST, if_id, + DUAL_DUNIT_CFG_REG, 0, (1 << 3))); } /* @@ -998,19 +881,19 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) /*Assert 10 refresh commands to DRAM to all CS */ for (iter = 0; iter < WL_ITERATION_NUM; iter++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, - if_id, SDRAM_OPERATION_REG, + if_id, SDRAM_OP_REG, (u32)((~(0xf) << 8) | 0x2), 0xf1f)); } } /* check controller back to normal */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (ddr3_tip_if_polling (dev_num, ACCESS_TYPE_UNICAST, if_id, 0, 0x1f, - SDRAM_OPERATION_REG, MAX_POLLING_ITERATIONS) != MV_OK) { + SDRAM_OP_REG, MAX_POLLING_ITERATIONS) != MV_OK) { DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("WL: DDR3 poll failed(3)")); } @@ -1019,24 +902,30 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { /*enable write leveling to all cs - Q off , WL n */ /* calculate interface cs mask */ - CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MRS1_CMD, + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1, 0x1000, 0x1080)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* cs enable is active low */ ddr3_tip_calc_cs_mask(dev_num, if_id, effective_cs, &cs_mask[if_id]); } - /* Enable Output buffer to relevant CS - Q on , WL on */ - CHECK_STATUS(ddr3_tip_write_mrs_cmd - (dev_num, cs_mask, MRS1_CMD, 0x80, 0x1080)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + /* Enable Output buffer to relevant CS - Q on , WL on */ + CHECK_STATUS(ddr3_tip_write_mrs_cmd + (dev_num, cs_mask, MR_CMD1, 0x80, 0x1080)); - /*enable odt for relevant CS */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - 0x1498, (0x3 << (effective_cs * 2)), 0xf)); + /*enable odt for relevant CS */ + CHECK_STATUS(ddr3_tip_if_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + 0x1498, (0x3 << (effective_cs * 2)), 0xf)); + } else { + /* FIXME: should be the same as _CPU case */ + CHECK_STATUS(ddr3_tip_write_mrs_cmd + (dev_num, cs_mask, MR_CMD1, 0xc0, 0x12c4)); + } /* * Phase 2: Set training IP to write leveling mode @@ -1044,110 +933,91 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) CHECK_STATUS(ddr3_tip_dynamic_write_leveling_seq(dev_num)); + /* phase 3: trigger training */ + mv_ddr_training_enable(); + + /* check for training done */ + if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, data_read) != MV_OK) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, ("training done failed\n")); + } else { /* check for training pass */ + reg_data = data_read[0]; +#if defined(CONFIG_ARMADA_38X) /* JIRA #1498 for 16 bit with ECC */ + if (tm->bus_act_mask == 0xb) /* set to data to 0 to skip the check */ + reg_data = 0; +#endif + if (reg_data != PASS) + DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("training result failed\n")); + + /* check for training completion per bus */ + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + /* training status */ + ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0, + mask_results_pup_reg_map[bus_cnt], + data_read, MASK_ALL_BITS); + reg_data = data_read[0]; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("WL: IF %d BUS %d reg 0x%x\n", + 0, bus_cnt, reg_data)); + if ((reg_data & (1 << 25)) == 0) + res_values[bus_cnt] = 1; + ddr3_tip_if_read(0, ACCESS_TYPE_UNICAST, 0, + mask_results_pup_reg_map[bus_cnt], + data_read, 0xff); + /* + * Save the read value that should be + * write to PHY register + */ + wl_values[effective_cs][bus_cnt][0] = (u8)data_read[0]; + } + } + /* - * Phase 3: Trigger training + * Phase 3.5: Validate result */ - - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_TRIGGER_REG, 0x1, 0x1)); - for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - - /* training done */ - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_UNICAST, if_id, - (1 << 1), (1 << 1), ODPG_TRAINING_STATUS_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING( - DEBUG_LEVEL_ERROR, - ("WL: DDR3 poll (4) failed (Data: 0x%x)\n", - reg_data)); - } -#if !defined(CONFIG_ARMADA_38X) /*Disabled. JIRA #1498 */ - else { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); + /* + * Read result control register according to subphy + * "16" below is for a half-phase + */ + reg_data = wl_values[effective_cs][bus_cnt][if_id] + 16; + /* + * Write to WL register: ADLL [4:0], Phase [8:6], + * Centralization ADLL [15:10] + 0x10 + */ + reg_data = (reg_data & 0x1f) | + (((reg_data & 0xe0) >> 5) << 6) | + (((reg_data & 0x1f) + phy_reg1_val) << 10); + /* Search with WL CS0 subphy reg */ + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_cnt, + DDR_PHY_DATA, WL_PHY_REG(0), reg_data); + /* + * Check for change in data read from DRAM. + * If changed, fix the result + */ CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, + (dev_num, + ACCESS_TYPE_UNICAST, if_id, - ODPG_TRAINING_TRIGGER_REG, - ®_data, (1 << 2))); - if (reg_data != 0) { + TRAINING_WL_REG, + data_read, MASK_ALL_BITS)); + if (((data_read[if_id] & (1 << (bus_cnt + 20))) >> + (bus_cnt + 20)) == 0) { DEBUG_LEVELING( DEBUG_LEVEL_ERROR, - ("WL: WL failed IF %d reg_data=0x%x\n", - if_id, reg_data)); - } - } -#endif - } - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - /* training done */ - if (ddr3_tip_if_polling - (dev_num, ACCESS_TYPE_UNICAST, if_id, - (1 << 1), (1 << 1), ODPG_TRAINING_STATUS_REG, - MAX_POLLING_ITERATIONS) != MV_OK) { - DEBUG_LEVELING( - DEBUG_LEVEL_ERROR, - ("WL: DDR3 poll (4) failed (Data: 0x%x)\n", - reg_data)); - } else { -#if !defined(CONFIG_ARMADA_38X) /*Disabled. JIRA #1498 */ - CHECK_STATUS(ddr3_tip_if_read - (dev_num, ACCESS_TYPE_UNICAST, - if_id, - ODPG_TRAINING_STATUS_REG, - data_read, (1 << 2))); - reg_data = data_read[if_id]; - if (reg_data != 0) { + ("WLValues was changed from 0x%X", + wl_values[effective_cs] + [bus_cnt][if_id])); + wl_values[effective_cs] + [bus_cnt][if_id] += 32; DEBUG_LEVELING( DEBUG_LEVEL_ERROR, - ("WL: WL failed IF %d reg_data=0x%x\n", - if_id, reg_data)); - } -#endif - - /* check for training completion per bus */ - for (bus_cnt = 0; - bus_cnt < tm->num_of_bus_per_interface; - bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, - bus_cnt); - /* training status */ - CHECK_STATUS(ddr3_tip_if_read - (dev_num, - ACCESS_TYPE_UNICAST, - if_id, - mask_results_pup_reg_map - [bus_cnt], data_read, - (1 << 25))); - reg_data = data_read[if_id]; - DEBUG_LEVELING( - DEBUG_LEVEL_TRACE, - ("WL: IF %d BUS %d reg 0x%x\n", - if_id, bus_cnt, reg_data)); - if (reg_data == 0) { - res_values[ - (if_id * - tm->num_of_bus_per_interface) - + bus_cnt] = 1; - } - CHECK_STATUS(ddr3_tip_if_read - (dev_num, - ACCESS_TYPE_UNICAST, - if_id, - mask_results_pup_reg_map - [bus_cnt], data_read, - 0xff)); - /* - * Save the read value that should be - * write to PHY register - */ - wl_values[effective_cs] - [bus_cnt][if_id] = - (u8)data_read[if_id]; + ("to 0x%X", + wl_values[effective_cs] + [bus_cnt][if_id])); } } } @@ -1159,15 +1029,21 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) /* disable DQs toggling */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - WR_LEVELING_DQS_PATTERN_REG, 0x0, 0x1)); + WL_DQS_PATTERN_REG, 0x0, 0x1)); /* Update MRS 1 (WL off) */ - CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MRS1_CMD, - 0x1000, 0x1080)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1, + 0x1000, 0x1080)); + } else { + /* FIXME: should be same as _CPU case */ + CHECK_STATUS(ddr3_tip_write_mrs_cmd(dev_num, cs_mask0, MR_CMD1, + 0x1000, 0x12c4)); + } /* Update MRS 1 (return to functional mode - Q on , WL off) */ CHECK_STATUS(ddr3_tip_write_mrs_cmd - (dev_num, cs_mask0, MRS1_CMD, 0x0, 0x1080)); + (dev_num, cs_mask0, MR_CMD1, 0x0, 0x1080)); /* set phy to normal mode */ CHECK_STATUS(ddr3_tip_if_write @@ -1186,16 +1062,16 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); test_res = 0; for (bus_cnt = 0; - bus_cnt < tm->num_of_bus_per_interface; + bus_cnt < octets_per_if_num; bus_cnt++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt); /* check if result == pass */ if (res_values [(if_id * - tm->num_of_bus_per_interface) + + octets_per_if_num) + bus_cnt] == 0) { /* * read result control register @@ -1214,6 +1090,18 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) (((reg_data & 0xe0) >> 5) << 6) | (((reg_data & 0x1f) + phy_reg1_val) << 10); + /* + * in case phase remove should be executed + * need to remove more than one phase. + * this will take place only in low frequency, + * where there could be more than one phase between sub-phys + */ + if (phase_remove == 1) { + temp = (reg_data >> WR_LVL_PH_SEL_OFFS) & WR_LVL_PH_SEL_PHASE1; + reg_data &= ~(WR_LVL_PH_SEL_MASK << WR_LVL_PH_SEL_OFFS); + reg_data |= (temp << WR_LVL_PH_SEL_OFFS); + } + ddr3_tip_bus_write( dev_num, ACCESS_TYPE_UNICAST, @@ -1221,9 +1109,7 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) ACCESS_TYPE_UNICAST, bus_cnt, DDR_PHY_DATA, - WL_PHY_REG + - effective_cs * - CS_REGISTER_ADDR_OFFSET, + WL_PHY_REG(effective_cs), reg_data); } else { test_res = 1; @@ -1259,38 +1145,48 @@ int ddr3_tip_dynamic_write_leveling(u32 dev_num) * Copy the result from the effective CS search to the real * Functional CS */ - /* ddr3_tip_write_cs_result(dev_num, WL_PHY_REG); */ + /* ddr3_tip_write_cs_result(dev_num, WL_PHY_REG(0); */ /* restore saved values */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* restore Read Data Sample Delay */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_SAMPLE_DELAY, + RD_DATA_SMPL_DLYS_REG, read_data_sample_delay_vals[if_id], MASK_ALL_BITS)); /* restore Read Data Ready Delay */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - READ_DATA_READY_DELAY, + RD_DATA_RDY_DLYS_REG, read_data_ready_delay_vals[if_id], MASK_ALL_BITS)); /* enable multi cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); } - /* Disable modt0 for CS0 training - need to adjust for multy CS */ - CHECK_STATUS(ddr3_tip_if_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x1498, - 0x0, 0xf)); + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) { + /* Disable modt0 for CS0 training - need to adjust for multi-CS + * in case of ddr4 set 0xf else 0 + */ + if (odt_config != 0) { + CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf)); + } + else { + CHECK_STATUS(ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + SDRAM_ODT_CTRL_HIGH_REG, 0xf, 0xf)); + } + + } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (training_result[training_stage][if_id] == TEST_FAILED) return MV_FAIL; } @@ -1306,28 +1202,27 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) int adll_offset; u32 if_id, bus_id, data, data_tmp; int is_if_fail = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); is_if_fail = 0; - for (bus_id = 0; bus_id < GET_TOPOLOGY_NUM_OF_BUSES(); - bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); wr_supp_res[if_id][bus_id].is_pup_fail = 1; CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), &data)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: adll_offset=0 data delay = %d\n", data)); if (ddr3_tip_wl_supp_align_phase_shift - (dev_num, if_id, bus_id, 0, 0) == MV_OK) { + (dev_num, if_id, bus_id) == MV_OK) { DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: IF %d bus_id %d adll_offset=0 Success !\n", @@ -1340,14 +1235,12 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), data + adll_offset)); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), &data_tmp)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, @@ -1355,7 +1248,7 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) adll_offset, data_tmp)); if (ddr3_tip_wl_supp_align_phase_shift - (dev_num, if_id, bus_id, adll_offset, 0) == MV_OK) { + (dev_num, if_id, bus_id) == MV_OK) { DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: IF %d bus_id %d adll_offset= %d Success !\n", @@ -1368,21 +1261,19 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), data + adll_offset)); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, - WRITE_CENTRALIZATION_PHY_REG + - effective_cs * CS_REGISTER_ADDR_OFFSET, + CTX_PHY_REG(effective_cs), &data_tmp)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: adll_offset= %d data delay = %d\n", adll_offset, data_tmp)); if (ddr3_tip_wl_supp_align_phase_shift - (dev_num, if_id, bus_id, adll_offset, 0) == MV_OK) { + (dev_num, if_id, bus_id) == MV_OK) { DEBUG_LEVELING( DEBUG_LEVEL_TRACE, ("WL Supp: IF %d bus_id %d adll_offset= %d Success !\n", @@ -1396,13 +1287,11 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) is_if_fail = 1; } } - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, - ("WL Supp: IF %d bus_id %d is_pup_fail %d\n", - if_id, bus_id, is_if_fail)); if (is_if_fail == 1) { DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("WL Supp: IF %d failed\n", if_id)); + ("WL Supp: CS# %d: IF %d failed\n", + effective_cs, if_id)); training_result[training_stage][if_id] = TEST_FAILED; } else { training_result[training_stage][if_id] = TEST_SUCCESS; @@ -1410,7 +1299,7 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) } for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (training_result[training_stage][if_id] == TEST_FAILED) return MV_FAIL; } @@ -1422,87 +1311,129 @@ int ddr3_tip_dynamic_write_leveling_supp(u32 dev_num) * Phase Shift */ static int ddr3_tip_wl_supp_align_phase_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 offset, - u32 bus_id_delta) + u32 bus_id) { + u32 original_phase; + u32 data, write_data; + wr_supp_res[if_id][bus_id].stage = PHASE_SHIFT; - if (ddr3_tip_xsb_compare_test(dev_num, if_id, bus_id, - 0, bus_id_delta) == MV_OK) { - wr_supp_res[if_id][bus_id].is_pup_fail = 0; - return MV_OK; - } else if (ddr3_tip_xsb_compare_test(dev_num, if_id, bus_id, - ONE_CLOCK_ERROR_SHIFT, - bus_id_delta) == MV_OK) { - /* 1 clock error */ - wr_supp_res[if_id][bus_id].stage = CLOCK_SHIFT; - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, - ("Supp: 1 error clock for if %d pup %d with ofsset %d success\n", - if_id, bus_id, offset)); - ddr3_tip_wl_supp_one_clk_err_shift(dev_num, if_id, bus_id, 0); - wr_supp_res[if_id][bus_id].is_pup_fail = 0; - return MV_OK; - } else if (ddr3_tip_xsb_compare_test(dev_num, if_id, bus_id, - ALIGN_ERROR_SHIFT, - bus_id_delta) == MV_OK) { - /* align error */ - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, - ("Supp: align error for if %d pup %d with ofsset %d success\n", - if_id, bus_id, offset)); - wr_supp_res[if_id][bus_id].stage = ALIGN_SHIFT; - ddr3_tip_wl_supp_align_err_shift(dev_num, if_id, bus_id, 0); - wr_supp_res[if_id][bus_id].is_pup_fail = 0; + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, 0) == MV_OK) return MV_OK; - } else { - wr_supp_res[if_id][bus_id].is_pup_fail = 1; - return MV_FAIL; + + /* Read current phase */ + CHECK_STATUS(ddr3_tip_bus_read + (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, + DDR_PHY_DATA, WL_PHY_REG(effective_cs), &data)); + original_phase = (data >> 6) & 0x7; + + /* Set phase (0x0[6-8]) -2 */ + if (original_phase >= 1) { + if (original_phase == 1) + write_data = data & ~0x1df; + else + write_data = (data & ~0x1c0) | + ((original_phase - 2) << 6); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), write_data); + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, -2) == MV_OK) + return MV_OK; } + + /* Set phase (0x0[6-8]) +2 */ + if (original_phase <= 5) { + write_data = (data & ~0x1c0) | + ((original_phase + 2) << 6); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), write_data); + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, 2) == MV_OK) + return MV_OK; + } + + /* Set phase (0x0[6-8]) +4 */ + if (original_phase <= 3) { + write_data = (data & ~0x1c0) | + ((original_phase + 4) << 6); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), write_data); + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, 4) == MV_OK) + return MV_OK; + } + + /* Set phase (0x0[6-8]) +6 */ + if (original_phase <= 1) { + write_data = (data & ~0x1c0) | + ((original_phase + 6) << 6); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), write_data); + if (ddr3_tip_xsb_compare_test + (dev_num, if_id, bus_id, 6) == MV_OK) + return MV_OK; + } + + /* Write original WL result back */ + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST, if_id, + ACCESS_TYPE_UNICAST, bus_id, DDR_PHY_DATA, + WL_PHY_REG(effective_cs), data); + wr_supp_res[if_id][bus_id].is_pup_fail = 1; + + return MV_FAIL; } /* * Compare Test */ static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id, - u32 edge_offset, u32 bus_id_delta) + u32 edge_offset) { - u32 num_of_succ_byte_compare, word_in_pattern, abs_offset; - u32 word_offset, i; + u32 num_of_succ_byte_compare, word_in_pattern; + u32 word_offset, i, num_of_word_mult; u32 read_pattern[TEST_PATTERN_LENGTH * 2]; struct pattern_info *pattern_table = ddr3_tip_get_pattern_table(); u32 pattern_test_pattern_table[8]; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* 3 below for INTERFACE_BUS_MASK_16BIT */ + num_of_word_mult = (tm->bus_act_mask == 3) ? 1 : 2; for (i = 0; i < 8; i++) { pattern_test_pattern_table[i] = pattern_table_get_word(dev_num, PATTERN_TEST, (u8)i); } - /* extern write, than read and compare */ - CHECK_STATUS(ddr3_tip_ext_write - (dev_num, if_id, - (pattern_table[PATTERN_TEST].start_addr + - ((SDRAM_CS_SIZE + 1) * effective_cs)), 1, - pattern_test_pattern_table)); + /* External write, read and compare */ + CHECK_STATUS(ddr3_tip_load_pattern_to_mem(dev_num, PATTERN_TEST)); CHECK_STATUS(ddr3_tip_reset_fifo_ptr(dev_num)); CHECK_STATUS(ddr3_tip_ext_read (dev_num, if_id, - (pattern_table[PATTERN_TEST].start_addr + + ((pattern_table[PATTERN_TEST].start_addr << 3) + ((SDRAM_CS_SIZE + 1) * effective_cs)), 1, read_pattern)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, - ("XSB-compt: IF %d bus_id %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", - if_id, bus_id, read_pattern[0], read_pattern[1], - read_pattern[2], read_pattern[3], read_pattern[4], - read_pattern[5], read_pattern[6], read_pattern[7])); + ("XSB-compt CS#%d: IF %d bus_id %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + effective_cs, if_id, bus_id, + read_pattern[0], read_pattern[1], + read_pattern[2], read_pattern[3], + read_pattern[4], read_pattern[5], + read_pattern[6], read_pattern[7])); /* compare byte per pup */ num_of_succ_byte_compare = 0; for (word_in_pattern = start_xsb_offset; - word_in_pattern < (TEST_PATTERN_LENGTH * 2); word_in_pattern++) { - word_offset = word_in_pattern + edge_offset; - if ((word_offset > (TEST_PATTERN_LENGTH * 2 - 1)) || - (word_offset < 0)) + word_in_pattern < (TEST_PATTERN_LENGTH * num_of_word_mult); + word_in_pattern++) { + word_offset = word_in_pattern; + if ((word_offset > (TEST_PATTERN_LENGTH * 2 - 1))) continue; if ((read_pattern[word_in_pattern] & pup_mask_table[bus_id]) == @@ -1511,19 +1442,20 @@ static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id, num_of_succ_byte_compare++; } - abs_offset = (edge_offset > 0) ? edge_offset : -edge_offset; - if (num_of_succ_byte_compare == ((TEST_PATTERN_LENGTH * 2) - - abs_offset - start_xsb_offset)) { - DEBUG_LEVELING( - DEBUG_LEVEL_TRACE, - ("XSB-compt: IF %d bus_id %d num_of_succ_byte_compare %d - Success\n", - if_id, bus_id, num_of_succ_byte_compare)); + if ((TEST_PATTERN_LENGTH * num_of_word_mult - start_xsb_offset) == + num_of_succ_byte_compare) { + wr_supp_res[if_id][bus_id].stage = edge_offset; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("supplementary: shift to %d for if %d pup %d success\n", + edge_offset, if_id, bus_id)); + wr_supp_res[if_id][bus_id].is_pup_fail = 0; + return MV_OK; } else { DEBUG_LEVELING( DEBUG_LEVEL_TRACE, - ("XSB-compt: IF %d bus_id %d num_of_succ_byte_compare %d - Fail !\n", - if_id, bus_id, num_of_succ_byte_compare)); + ("XSB-compt CS#%d: IF %d bus_id %d num_of_succ_byte_compare %d - Fail!\n", + effective_cs, if_id, bus_id, num_of_succ_byte_compare)); DEBUG_LEVELING( DEBUG_LEVEL_TRACE, @@ -1544,116 +1476,10 @@ static int ddr3_tip_xsb_compare_test(u32 dev_num, u32 if_id, u32 bus_id, read_pattern[4], read_pattern[5], read_pattern[6], read_pattern[7])); - DEBUG_LEVELING( - DEBUG_LEVEL_TRACE, - ("XSB-compt: IF %d bus_id %d num_of_succ_byte_compare %d - Fail !\n", - if_id, bus_id, num_of_succ_byte_compare)); - return MV_FAIL; } } -/* - * Clock error shift - function moves the write leveling delay 1cc forward - */ -static int ddr3_tip_wl_supp_one_clk_err_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 bus_id_delta) -{ - int phase, adll; - u32 data; - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("One_clk_err_shift\n")); - - CHECK_STATUS(ddr3_tip_bus_read - (dev_num, if_id, ACCESS_TYPE_UNICAST, bus_id, - DDR_PHY_DATA, WL_PHY_REG, &data)); - phase = ((data >> 6) & 0x7); - adll = data & 0x1f; - DEBUG_LEVELING(DEBUG_LEVEL_TRACE, - ("One_clk_err_shift: IF %d bus_id %d phase %d adll %d\n", - if_id, bus_id, phase, adll)); - - if ((phase == 0) || (phase == 1)) { - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_id, - DDR_PHY_DATA, 0, (phase + 2), 0x1f)); - } else if (phase == 2) { - if (adll < 6) { - data = (3 << 6) + (0x1f); - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - bus_id, DDR_PHY_DATA, 0, data, - (0x7 << 6 | 0x1f))); - data = 0x2f; - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, - bus_id, DDR_PHY_DATA, 1, data, 0x3f)); - } - } else { - /* phase 3 */ - return MV_FAIL; - } - - return MV_OK; -} - -/* - * Align error shift - */ -static int ddr3_tip_wl_supp_align_err_shift(u32 dev_num, u32 if_id, - u32 bus_id, u32 bus_id_delta) -{ - int phase, adll; - u32 data; - - /* Shift WL result 1 phase back */ - CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, - bus_id, DDR_PHY_DATA, WL_PHY_REG, - &data)); - phase = ((data >> 6) & 0x7); - adll = data & 0x1f; - DEBUG_LEVELING( - DEBUG_LEVEL_TRACE, - ("Wl_supp_align_err_shift: IF %d bus_id %d phase %d adll %d\n", - if_id, bus_id, phase, adll)); - - if (phase < 2) { - if (adll > 0x1a) { - if (phase == 0) - return MV_FAIL; - - if (phase == 1) { - data = 0; - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, bus_id, DDR_PHY_DATA, - 0, data, (0x7 << 6 | 0x1f))); - data = 0xf; - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, bus_id, DDR_PHY_DATA, - 1, data, 0x1f)); - return MV_OK; - } - } else { - return MV_FAIL; - } - } else if ((phase == 2) || (phase == 3)) { - phase = phase - 2; - data = (phase << 6) + (adll & 0x1f); - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, if_id, bus_id, - DDR_PHY_DATA, 0, data, (0x7 << 6 | 0x1f))); - return MV_OK; - } else { - DEBUG_LEVELING(DEBUG_LEVEL_ERROR, - ("Wl_supp_align_err_shift: unexpected phase\n")); - - return MV_FAIL; - } - - return MV_OK; -} - /* * Dynamic write leveling sequence */ @@ -1662,32 +1488,33 @@ static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num) u32 bus_id, dq_id; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_SW_2_REG, 0x1, 0x5)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_WRITE_LEVELING_REG, 0x50, 0xff)); + TRAINING_WL_REG, 0x50, 0xff)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_WRITE_LEVELING_REG, 0x5c, 0xff)); + TRAINING_WL_REG, 0x5c, 0xff)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_TRAINING_CONTROL_REG, 0x381b82, 0x3c3faf)); + GENERAL_TRAINING_OPCODE_REG, 0x381b82, 0x3c3faf)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_OBJ1_OPCODE_REG, (0x3 << 25), (0x3ffff << 9))); + OPCODE_REG0_REG(1), (0x3 << 25), (0x3ffff << 9))); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_OBJ1_ITER_CNT_REG, 0x80, 0xffff)); + OPCODE_REG1_REG(1), 0x80, 0xffff)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_LEVELING_DONE_CNTR_REG, 0x14, 0xff)); + WL_DONE_CNTR_REF_REG, 0x14, 0xff)); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - TRAINING_WRITE_LEVELING_REG, 0xff5c, 0xffff)); + TRAINING_WL_REG, 0xff5c, 0xffff)); /* mask PBS */ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) { @@ -1698,7 +1525,7 @@ static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num) } /* Mask all results */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0x1 << 24, @@ -1706,8 +1533,8 @@ static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num) } /* Unmask only wanted */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0, 0x1 << 24)); @@ -1715,7 +1542,7 @@ static int ddr3_tip_dynamic_write_leveling_seq(u32 dev_num) CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - WR_LEVELING_DQS_PATTERN_REG, 0x1, 0x1)); + WL_DQS_PATTERN_REG, 0x1, 0x1)); return MV_OK; } @@ -1728,7 +1555,8 @@ static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num) u32 bus_id, dq_id; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* mask PBS */ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) { @@ -1739,7 +1567,7 @@ static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num) } /* Mask all results */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0x1 << 24, @@ -1747,8 +1575,8 @@ static int ddr3_tip_dynamic_read_leveling_seq(u32 dev_num) } /* Unmask only wanted */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0, 0x1 << 24)); @@ -1765,7 +1593,8 @@ static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num) u32 bus_id, dq_id; u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map(); u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* mask PBS */ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) { @@ -1776,7 +1605,7 @@ static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num) } /* Mask all results */ - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; bus_id++) { + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_pup_reg_map[bus_id], 0x1 << 24, @@ -1785,7 +1614,7 @@ static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num) /* Unmask only wanted */ for (dq_id = 0; dq_id < MAX_DQ_NUM; dq_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, dq_id / 8); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, dq_id / 8); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, mask_results_dq_reg_map[dq_id], 0x0 << 24, @@ -1801,16 +1630,17 @@ static int ddr3_tip_dynamic_per_bit_read_leveling_seq(u32 dev_num) int ddr3_tip_print_wl_supp_result(u32 dev_num) { u32 bus_id = 0, if_id = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("I/F0 PUP0 Result[0 - success, 1-fail] ...\n")); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("%d ,", wr_supp_res[if_id] [bus_id].is_pup_fail)); @@ -1821,10 +1651,10 @@ int ddr3_tip_print_wl_supp_result(u32 dev_num) ("I/F0 PUP0 Stage[0-phase_shift, 1-clock_shift, 2-align_shift] ...\n")); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (bus_id = 0; bus_id < tm->num_of_bus_per_interface; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (bus_id = 0; bus_id < octets_per_if_num; bus_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, bus_id); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_id); DEBUG_LEVELING(DEBUG_LEVEL_INFO, ("%d ,", wr_supp_res[if_id] [bus_id].stage)); @@ -1833,3 +1663,324 @@ int ddr3_tip_print_wl_supp_result(u32 dev_num) return MV_OK; } + +#define RD_FIFO_PTR_LOW_STAT_INDIR_ADDR 0x9a +#define RD_FIFO_PTR_HIGH_STAT_INDIR_ADDR 0x9b +/* position of falling dqs edge in fifo; walking 1 */ +#define RD_FIFO_DQS_FALL_EDGE_POS_0 0x1 +#define RD_FIFO_DQS_FALL_EDGE_POS_1 0x2 +#define RD_FIFO_DQS_FALL_EDGE_POS_2 0x4 +#define RD_FIFO_DQS_FALL_EDGE_POS_3 0x8 +#define RD_FIFO_DQS_FALL_EDGE_POS_4 0x10 /* lock */ +/* position of rising dqs edge in fifo; walking 0 */ +#define RD_FIFO_DQS_RISE_EDGE_POS_0 0x1fff +#define RD_FIFO_DQS_RISE_EDGE_POS_1 0x3ffe +#define RD_FIFO_DQS_RISE_EDGE_POS_2 0x3ffd +#define RD_FIFO_DQS_RISE_EDGE_POS_3 0x3ffb +#define RD_FIFO_DQS_RISE_EDGE_POS_4 0x3ff7 /* lock */ +#define TEST_ADDR 0x8 +#define TAPS_PER_UI 32 +#define UI_PER_RD_SAMPLE 4 +#define TAPS_PER_RD_SAMPLE ((UI_PER_RD_SAMPLE) * (TAPS_PER_UI)) +#define MAX_RD_SAMPLES 32 +#define MAX_RL_VALUE ((MAX_RD_SAMPLES) * (TAPS_PER_RD_SAMPLE)) +#define RD_FIFO_DLY 8 +#define STEP_SIZE 64 +#define RL_JITTER_WIDTH_LMT 20 +#define ADLL_TAPS_IN_CYCLE 64 + +enum rl_dqs_burst_state { + RL_AHEAD = 0, + RL_INSIDE, + RL_BEHIND +}; +int mv_ddr_rl_dqs_burst(u32 dev_num, u32 if_id, u32 freq) +{ + enum rl_dqs_burst_state rl_state[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } }; + enum hws_ddr_phy subphy_type = DDR_PHY_DATA; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + int cl_val = tm->interface_params[0].cas_l; + int rl_adll_val, rl_phase_val, sdr_cycle_incr, rd_sample, rd_ready; + int final_rd_sample, final_rd_ready; + int i, subphy_id, step; + int pass_lock_num = 0; + int init_pass_lock_num; + int phase_delta; + int min_phase, max_phase; + u32 max_cs = ddr3_tip_max_cs_get(dev_num); + u32 rl_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } }; + u32 rl_min_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } }; + u32 rl_max_values[NUM_OF_CS][MAX_BUS_NUM][MAX_INTERFACE_NUM] = { { {0} } }; + u32 rl_val, rl_min_val[NUM_OF_CS], rl_max_val[NUM_OF_CS]; + u32 reg_val_low, reg_val_high; + u32 reg_val, reg_mask; + uintptr_t test_addr = TEST_ADDR; + + /* initialization */ + if (ddr3_if_ecc_enabled()) { + ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, TRAINING_SW_2_REG, + ®_val, MASK_ALL_BITS); + reg_mask = (TRAINING_ECC_MUX_MASK << TRAINING_ECC_MUX_OFFS) | + (TRAINING_SW_OVRD_MASK << TRAINING_SW_OVRD_OFFS); + reg_val &= ~reg_mask; + reg_val |= (TRAINING_ECC_MUX_DIS << TRAINING_ECC_MUX_OFFS) | + (TRAINING_SW_OVRD_ENA << TRAINING_SW_OVRD_OFFS); + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_SW_2_REG, + reg_val, MASK_ALL_BITS); + ddr3_tip_if_read(dev_num, ACCESS_TYPE_UNICAST, if_id, TRAINING_REG, + ®_val, MASK_ALL_BITS); + reg_mask = (TRN_START_MASK << TRN_START_OFFS); + reg_val &= ~reg_mask; + reg_val |= TRN_START_ENA << TRN_START_OFFS; + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, TRAINING_REG, + reg_val, MASK_ALL_BITS); + } + + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) + for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) + if (IS_BUS_ACTIVE(tm->bus_act_mask, subphy_id) == 0) + pass_lock_num++; /* increment on inactive subphys */ + + init_pass_lock_num = pass_lock_num / max_cs; + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + training_result[training_stage][if_id] = TEST_SUCCESS; + } + } + + /* search for dqs edges per subphy */ + if_id = 0; + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + pass_lock_num = init_pass_lock_num; + ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ODPG_DATA_CTRL_REG, + effective_cs << ODPG_DATA_CS_OFFS, + ODPG_DATA_CS_MASK << ODPG_DATA_CS_OFFS); + rl_min_val[effective_cs] = MAX_RL_VALUE; + rl_max_val[effective_cs] = 0; + step = STEP_SIZE; + for (i = 0; i < MAX_RL_VALUE; i += step) { + rl_val = 0; + sdr_cycle_incr = i / TAPS_PER_RD_SAMPLE; /* sdr cycle increment */ + rd_sample = cl_val + 2 * sdr_cycle_incr; + /* fifo out to in delay in search is constant */ + rd_ready = rd_sample + RD_FIFO_DLY; + + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_SMPL_DLYS_REG, + rd_sample << RD_SMPL_DLY_CS_OFFS(effective_cs), + RD_SMPL_DLY_CS_MASK << RD_SMPL_DLY_CS_OFFS(effective_cs)); + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_RDY_DLYS_REG, + rd_ready << RD_RDY_DLY_CS_OFFS(effective_cs), + RD_RDY_DLY_CS_MASK << RD_RDY_DLY_CS_OFFS(effective_cs)); + + /* one sdr (single data rate) cycle incremented on every four phases of ddr clock */ + sdr_cycle_incr = i % TAPS_PER_RD_SAMPLE; + rl_adll_val = sdr_cycle_incr % MAX_RD_SAMPLES; + rl_phase_val = sdr_cycle_incr / MAX_RD_SAMPLES; + rl_val = ((rl_adll_val & RL_REF_DLY_MASK) << RL_REF_DLY_OFFS) | + ((rl_phase_val & RL_PH_SEL_MASK) << RL_PH_SEL_OFFS); + + /* write to all subphys (even to not connected or locked) */ + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_MULTICAST, + 0, DDR_PHY_DATA, RL_PHY_REG(effective_cs), rl_val); + + /* reset read fifo assertion */ + ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG, + DATA_PUP_RD_RESET_ENA << DATA_PUP_RD_RESET_OFFS, + DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS); + + /* reset read fifo deassertion */ + ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG, + DATA_PUP_RD_RESET_DIS << DATA_PUP_RD_RESET_OFFS, + DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS); + + /* perform one read burst */ + if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) + readq(test_addr); + else + readl(test_addr); + + /* progress read ptr; decide on rl state per byte */ + for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) { + if (rl_state[effective_cs][subphy_id][if_id] == RL_BEHIND) + continue; /* skip locked subphys */ + ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_id, DDR_PHY_DATA, + RD_FIFO_PTR_LOW_STAT_INDIR_ADDR, ®_val_low); + ddr3_tip_bus_read(dev_num, if_id, ACCESS_TYPE_UNICAST, subphy_id, DDR_PHY_DATA, + RD_FIFO_PTR_HIGH_STAT_INDIR_ADDR, ®_val_high); + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("%s: cs %d, step %d, subphy %d, state %d, low 0x%04x, high 0x%04x; move to ", + __func__, effective_cs, i, subphy_id, + rl_state[effective_cs][subphy_id][if_id], + reg_val_low, reg_val_high)); + + switch (rl_state[effective_cs][subphy_id][if_id]) { + case RL_AHEAD: + /* improve search resolution getting closer to the window */ + if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_4 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_4) { + rl_state[effective_cs][subphy_id][if_id] = RL_INSIDE; + rl_values[effective_cs][subphy_id][if_id] = i; + rl_min_values[effective_cs][subphy_id][if_id] = i; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new state %d\n", + rl_state[effective_cs][subphy_id][if_id])); + } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_3 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_3) { + step = (step < 2) ? step : 2; + } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_2 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_2) { + step = (step < 16) ? step : 16; + } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_1 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_1) { + step = (step < 32) ? step : 32; + } else if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_0 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_0) { + step = (step < 64) ? step : 64; + } else { + /* otherwise, step is unchanged */ + } + break; + case RL_INSIDE: + if (reg_val_low == RD_FIFO_DQS_FALL_EDGE_POS_4 && + reg_val_high == RD_FIFO_DQS_RISE_EDGE_POS_4) { + rl_max_values[effective_cs][subphy_id][if_id] = i; + if ((rl_max_values[effective_cs][subphy_id][if_id] - + rl_min_values[effective_cs][subphy_id][if_id]) > + ADLL_TAPS_IN_CYCLE) { + rl_state[effective_cs][subphy_id][if_id] = RL_BEHIND; + rl_values[effective_cs][subphy_id][if_id] = + (i + rl_values[effective_cs][subphy_id][if_id]) / 2; + pass_lock_num++; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new lock %d\n", pass_lock_num)); + if (rl_min_val[effective_cs] > + rl_values[effective_cs][subphy_id][if_id]) + rl_min_val[effective_cs] = + rl_values[effective_cs][subphy_id][if_id]; + if (rl_max_val[effective_cs] < + rl_values[effective_cs][subphy_id][if_id]) + rl_max_val[effective_cs] = + rl_values[effective_cs][subphy_id][if_id]; + step = 2; + } + } + if (reg_val_low != RD_FIFO_DQS_FALL_EDGE_POS_4 || + reg_val_high != RD_FIFO_DQS_RISE_EDGE_POS_4) { + if ((i - rl_values[effective_cs][subphy_id][if_id]) < + RL_JITTER_WIDTH_LMT) { + /* inside the jitter; not valid segment */ + rl_state[effective_cs][subphy_id][if_id] = RL_AHEAD; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new state %d; jitter on mask\n", + rl_state[effective_cs][subphy_id][if_id])); + } else { /* finished valid segment */ + rl_state[effective_cs][subphy_id][if_id] = RL_BEHIND; + rl_values[effective_cs][subphy_id][if_id] = + (i + rl_values[effective_cs][subphy_id][if_id]) / 2; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new state %d, solution %d\n", + rl_state[effective_cs][subphy_id][if_id], + rl_values[effective_cs][subphy_id][if_id])); + pass_lock_num++; + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, + ("new lock %d\n", pass_lock_num)); + if (rl_min_val[effective_cs] > + rl_values[effective_cs][subphy_id][if_id]) + rl_min_val[effective_cs] = + rl_values[effective_cs][subphy_id][if_id]; + if (rl_max_val[effective_cs] < + rl_values[effective_cs][subphy_id][if_id]) + rl_max_val[effective_cs] = + rl_values[effective_cs][subphy_id][if_id]; + step = 2; + } + } + break; + case RL_BEHIND: /* do nothing */ + break; + } + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("\n")); + } + DEBUG_LEVELING(DEBUG_LEVEL_TRACE, ("pass_lock_num %d\n", pass_lock_num)); + /* exit condition */ + if (pass_lock_num == MAX_BUS_NUM) + break; + } /* for-loop on i */ + + if (pass_lock_num != MAX_BUS_NUM) { + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, + ("%s: cs %d, pass_lock_num %d, max_bus_num %d, init_pass_lock_num %d\n", + __func__, effective_cs, pass_lock_num, MAX_BUS_NUM, init_pass_lock_num)); + for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_id); + DEBUG_LEVELING(DEBUG_LEVEL_ERROR, + ("%s: subphy %d %s\n", + __func__, subphy_id, + (rl_state[effective_cs][subphy_id][if_id] == RL_BEHIND) ? + "locked" : "not locked")); + } + } + } /* for-loop on effective_cs */ + + /* post-processing read leveling results */ + if_id = 0; + for (effective_cs = 0; effective_cs < max_cs; effective_cs++) { + phase_delta = 0; + i = rl_min_val[effective_cs]; + sdr_cycle_incr = i / TAPS_PER_RD_SAMPLE; /* sdr cycle increment */ + rd_sample = cl_val + 2 * sdr_cycle_incr; + rd_ready = rd_sample + RD_FIFO_DLY; + min_phase = (rl_min_val[effective_cs] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE)) % MAX_RD_SAMPLES; + max_phase = (rl_max_val[effective_cs] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE)) % MAX_RD_SAMPLES; + final_rd_sample = rd_sample; + final_rd_ready = rd_ready; + + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_SMPL_DLYS_REG, + rd_sample << RD_SMPL_DLY_CS_OFFS(effective_cs), + RD_SMPL_DLY_CS_MASK << RD_SMPL_DLY_CS_OFFS(effective_cs)); + ddr3_tip_if_write(0, ACCESS_TYPE_UNICAST, 0, RD_DATA_RDY_DLYS_REG, + rd_ready << RD_RDY_DLY_CS_OFFS(effective_cs), + RD_RDY_DLY_CS_MASK << RD_RDY_DLY_CS_OFFS(effective_cs)); + DEBUG_LEVELING(DEBUG_LEVEL_INFO, + ("%s: cs %d, min phase %d, max phase %d, read sample %d\n", + __func__, effective_cs, min_phase, max_phase, rd_sample)); + + for (subphy_id = 0; subphy_id < MAX_BUS_NUM; subphy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, subphy_id); + /* reduce sdr cycle per cs; extract rl adll and phase values */ + i = rl_values[effective_cs][subphy_id][if_id] - (sdr_cycle_incr * TAPS_PER_RD_SAMPLE); + rl_adll_val = i % MAX_RD_SAMPLES; + rl_phase_val = i / MAX_RD_SAMPLES; + rl_phase_val -= phase_delta; + DEBUG_LEVELING(DEBUG_LEVEL_INFO, + ("%s: final results: cs %d, subphy %d, read sample %d read ready %d, rl_phase_val %d, rl_adll_val %d\n", + __func__, effective_cs, subphy_id, final_rd_sample, + final_rd_ready, rl_phase_val, rl_adll_val)); + + rl_val = ((rl_adll_val & RL_REF_DLY_MASK) << RL_REF_DLY_OFFS) | + ((rl_phase_val & RL_PH_SEL_MASK) << RL_PH_SEL_OFFS); + ddr3_tip_bus_write(dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, ACCESS_TYPE_UNICAST, + subphy_id, subphy_type, RL_PHY_REG(effective_cs), rl_val); + } + } /* for-loop on effective cs */ + + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + if (odt_config != 0) + CHECK_STATUS(ddr3_tip_write_additional_odt_setting(dev_num, if_id)); + } + + /* reset read fifo assertion */ + ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG, + DATA_PUP_RD_RESET_ENA << DATA_PUP_RD_RESET_OFFS, + DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS); + + /* reset read fifo deassertion */ + ddr3_tip_if_write(dev_num, ACCESS_TYPE_MULTICAST, if_id, SDRAM_CFG_REG, + DATA_PUP_RD_RESET_DIS << DATA_PUP_RD_RESET_OFFS, + DATA_PUP_RD_RESET_MASK << DATA_PUP_RD_RESET_OFFS); + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/ddr3_training_leveling.h b/drivers/ddr/marvell/a38x/ddr3_training_leveling.h index 4c3c417773..96d945a33d 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_leveling.h +++ b/drivers/ddr/marvell/a38x/ddr3_training_leveling.h @@ -11,6 +11,6 @@ int ddr3_tip_print_wl_supp_result(u32 dev_num); int ddr3_tip_calc_cs_mask(u32 dev_num, u32 if_id, u32 effective_cs, u32 *cs_mask); -u32 hws_ddr3_tip_max_cs_get(void); +u32 ddr3_tip_max_cs_get(u32 dev_num); #endif /* _DDR3_TRAINING_LEVELING_H_ */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training_pbs.c b/drivers/ddr/marvell/a38x/ddr3_training_pbs.c index da7a9d143d..0511026afb 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training_pbs.c +++ b/drivers/ddr/marvell/a38x/ddr3_training_pbs.c @@ -3,12 +3,6 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include - #include "ddr3_init.h" #define TYPICAL_PBS_VALUE 12 @@ -23,7 +17,7 @@ u8 max_pbs_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 min_pbs_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 max_adll_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 min_adll_per_pup[MAX_INTERFACE_NUM][MAX_BUS_NUM]; -u32 pbsdelay_per_pup[NUM_OF_PBS_MODES][MAX_INTERFACE_NUM][MAX_BUS_NUM]; +u32 pbsdelay_per_pup[NUM_OF_PBS_MODES][MAX_INTERFACE_NUM][MAX_BUS_NUM][MAX_CS_NUM]; u8 adll_shift_lock[MAX_INTERFACE_NUM][MAX_BUS_NUM]; u8 adll_shift_val[MAX_INTERFACE_NUM][MAX_BUS_NUM]; enum hws_pattern pbs_pattern = PATTERN_VREF; @@ -49,34 +43,33 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) int init_val = (search_dir == HWS_LOW2HIGH) ? 0 : iterations; enum hws_edge_compare search_edge = EDGE_FP; u32 pup = 0, bit = 0, if_id = 0, all_lock = 0, cs_num = 0; - int reg_addr = 0; + u32 reg_addr = 0; u32 validation_val = 0; u32 cs_enable_reg_val[MAX_INTERFACE_NUM]; u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg(); u8 temp = 0; - struct hws_topology_map *tm = ddr3_get_topology_map(); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); /* save current cs enable reg val */ for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* save current cs enable reg val */ CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val, MASK_ALL_BITS)); + DUAL_DUNIT_CFG_REG, cs_enable_reg_val, MASK_ALL_BITS)); /* enable single cs */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, (1 << 3), (1 << 3))); + DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3))); } reg_addr = (pbs_mode == PBS_RX_MODE) ? - (READ_CENTRALIZATION_PHY_REG + - (effective_cs * CS_REGISTER_ADDR_OFFSET)) : - (WRITE_CENTRALIZATION_PHY_REG + - (effective_cs * CS_REGISTER_ADDR_OFFSET)); - read_adll_value(nominal_adll, reg_addr, MASK_ALL_BITS); + CRX_PHY_REG(effective_cs) : + CTX_PHY_REG(effective_cs); + ddr3_tip_read_adll_value(dev_num, nominal_adll, reg_addr, MASK_ALL_BITS); /* stage 1 shift ADLL */ ddr3_tip_ip_training(dev_num, ACCESS_TYPE_MULTICAST, @@ -87,10 +80,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) pbs_pattern, search_edge, CS_SINGLE, cs_num, train_status); validation_val = (pbs_mode == PBS_RX_MODE) ? 0x1f : 0; - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); min_adll_per_pup[if_id][pup] = (pbs_mode == PBS_RX_MODE) ? 0x1f : 0x3f; pup_state[if_id][pup] = 0x3; @@ -100,8 +93,8 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) } /* EBA */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { CHECK_STATUS(ddr3_tip_if_read (dev_num, ACCESS_TYPE_MULTICAST, @@ -111,7 +104,7 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) res0, MASK_ALL_BITS)); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE, ("FP I/F %d, bit:%d, pup:%d res0 0x%x\n", if_id, bit, pup, @@ -176,10 +169,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) } /* EEBA */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (pup_state[if_id][pup] != 4) continue; @@ -335,10 +328,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) } /* Print Stage result */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); DEBUG_PBS_ENGINE(DEBUG_LEVEL_TRACE, ("FP I/F %d, ADLL Shift for EBA: pup[%d] Lock status = %d Lock Val = %d,%d\n", if_id, pup, @@ -350,10 +343,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO, ("Update ADLL Shift of all pups:\n")); - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (adll_shift_lock[if_id][pup] != 1) continue; /* if pup not locked continue to next pup */ @@ -373,10 +366,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* PBS EEBA&EBA */ /* Start the Per Bit Skew search */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); max_pbs_per_pup[if_id][pup] = 0x0; min_pbs_per_pup[if_id][pup] = 0x1f; for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { @@ -400,10 +393,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) iterations, pbs_pattern, search_edge, CS_SINGLE, cs_num, train_status); - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (adll_shift_lock[if_id][pup] != 1) { /* if pup not lock continue to next pup */ continue; @@ -461,10 +454,10 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* Check all Pup lock */ all_lock = 1; - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); all_lock = all_lock * adll_shift_lock[if_id][pup]; } } @@ -478,11 +471,11 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) search_dir = (pbs_mode == PBS_RX_MODE) ? HWS_LOW2HIGH : HWS_HIGH2LOW; init_val = (search_dir == HWS_LOW2HIGH) ? 0 : iterations; - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); if (adll_shift_lock[if_id][pup] == 1) { /*if pup lock continue to next pup */ continue; @@ -627,11 +620,11 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) search_edge, CS_SINGLE, cs_num, train_status); - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { CHECK_STATUS(ddr3_tip_if_read (dev_num, @@ -696,7 +689,7 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* Check all Pup state */ all_lock = 1; - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { + for (pup = 0; pup < octets_per_if_num; pup++) { /* * DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO, * ("pup_state[%d][%d] = %d\n",if_id,pup,pup_state @@ -707,12 +700,12 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* END OF SBA */ /* Norm */ - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); /* if pup not lock continue to next pup */ if (adll_shift_lock[if_id][pup] != 1) { DEBUG_PBS_ENGINE( @@ -753,9 +746,9 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) /* DQ PBS register update with the final result */ for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (pup = 0; pup < tm->num_of_bus_per_interface; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); DEBUG_PBS_ENGINE( DEBUG_LEVEL_INFO, @@ -771,28 +764,32 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) pad_num = dq_map_table[ bit + pup * BUS_WIDTH_IN_BITS + if_id * BUS_WIDTH_IN_BITS * - tm->num_of_bus_per_interface]; + MAX_BUS_NUM]; DEBUG_PBS_ENGINE(DEBUG_LEVEL_INFO, ("result_mat: %d ", result_mat[if_id][pup] [bit])); reg_addr = (pbs_mode == PBS_RX_MODE) ? - (PBS_RX_PHY_REG + effective_cs * 0x10) : - (PBS_TX_PHY_REG + effective_cs * 0x10); + PBS_RX_PHY_REG(effective_cs, 0) : + PBS_TX_PHY_REG(effective_cs, 0); CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, if_id, ACCESS_TYPE_UNICAST, pup, DDR_PHY_DATA, reg_addr + pad_num, result_mat[if_id][pup][bit])); } - pbsdelay_per_pup[pbs_mode][if_id][pup] = - (max_pbs_per_pup[if_id][pup] == - min_pbs_per_pup[if_id][pup]) ? - TYPICAL_PBS_VALUE : - ((max_adll_per_pup[if_id][pup] - - min_adll_per_pup[if_id][pup]) * adll_tap / - (max_pbs_per_pup[if_id][pup] - - min_pbs_per_pup[if_id][pup])); + + if (max_pbs_per_pup[if_id][pup] == min_pbs_per_pup[if_id][pup]) { + temp = TYPICAL_PBS_VALUE; + } else { + temp = ((max_adll_per_pup[if_id][pup] - + min_adll_per_pup[if_id][pup]) * + adll_tap / + (max_pbs_per_pup[if_id][pup] - + min_pbs_per_pup[if_id][pup])); + } + pbsdelay_per_pup[pbs_mode] + [if_id][pup][effective_cs] = temp; /* RX results ready, write RX also */ if (pbs_mode == PBS_TX_MODE) { @@ -842,18 +839,18 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) DEBUG_PBS_ENGINE( DEBUG_LEVEL_INFO, (", PBS tap=%d [psec] ==> skew observed = %d\n", - pbsdelay_per_pup[pbs_mode][if_id][pup], + temp, ((max_pbs_per_pup[if_id][pup] - min_pbs_per_pup[if_id][pup]) * - pbsdelay_per_pup[pbs_mode][if_id][pup]))); + temp))); } } /* Write back to the phy the default values */ reg_addr = (pbs_mode == PBS_RX_MODE) ? - (READ_CENTRALIZATION_PHY_REG + effective_cs * 4) : - (WRITE_CENTRALIZATION_PHY_REG + effective_cs * 4); - write_adll_value(nominal_adll, reg_addr); + CRX_PHY_REG(effective_cs) : + CTX_PHY_REG(effective_cs); + ddr3_tip_write_adll_value(dev_num, nominal_adll, reg_addr); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { reg_addr = (pbs_mode == PBS_RX_MODE) ? @@ -865,24 +862,29 @@ int ddr3_tip_pbs(u32 dev_num, enum pbs_dir pbs_mode) 0)); /* restore cs enable value */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_UNICAST, if_id, - CS_ENABLE_REG, cs_enable_reg_val[if_id], + DUAL_DUNIT_CFG_REG, cs_enable_reg_val[if_id], MASK_ALL_BITS)); } /* exit test mode */ CHECK_STATUS(ddr3_tip_if_write (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ODPG_WRITE_READ_MODE_ENABLE_REG, 0xffff, MASK_ALL_BITS)); + ODPG_WR_RD_MODE_ENA_REG, 0xffff, MASK_ALL_BITS)); + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - /* - * meaning that there is no VW exist at all (No lock at - * the EBA ADLL shift at EBS) - */ - if (pup_state[if_id][pup] == 1) - return MV_FAIL; + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); + /* + * no valid window found + * (no lock at EBA ADLL shift at EBS) + */ + if (pup_state[if_id][pup] == 1) + return MV_FAIL; + } } return MV_OK; @@ -912,14 +914,14 @@ int ddr3_tip_pbs_tx(u32 uidev_num) return ddr3_tip_pbs(uidev_num, PBS_TX_MODE); } -#ifndef EXCLUDE_SWITCH_DEBUG +#ifdef DDR_VIEWER_TOOL /* * Print PBS Result */ int ddr3_tip_print_all_pbs_result(u32 dev_num) { u32 curr_cs; - u32 max_cs = hws_ddr3_tip_max_cs_get(); + u32 max_cs = ddr3_tip_max_cs_get(dev_num); for (curr_cs = 0; curr_cs < max_cs; curr_cs++) { ddr3_tip_print_pbs_result(dev_num, curr_cs, PBS_RX_MODE); @@ -936,21 +938,33 @@ int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode) { u32 data_value = 0, bit = 0, if_id = 0, pup = 0; u32 reg_addr = (pbs_mode == PBS_RX_MODE) ? - (PBS_RX_PHY_REG + cs_num * 0x10) : - (PBS_TX_PHY_REG + cs_num * 0x10); - struct hws_topology_map *tm = ddr3_get_topology_map(); + PBS_RX_PHY_REG(cs_num, 0) : + PBS_TX_PHY_REG(cs_num , 0); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + printf("%s,CS%d,PBS,ADLLRATIO,,,", + (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx", cs_num); + for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = 0; pup < octets_per_if_num; pup++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); + printf("%d,", + pbsdelay_per_pup[pbs_mode][if_id][pup][cs_num]); + } + } printf("CS%d, %s ,PBS\n", cs_num, (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx"); for (bit = 0; bit < BUS_WIDTH_IN_BITS; bit++) { printf("%s, DQ", (pbs_mode == PBS_RX_MODE) ? "Rx" : "Tx"); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); printf("%d ,PBS,,, ", bit); - for (pup = 0; pup <= tm->num_of_bus_per_interface; + for (pup = 0; pup <= octets_per_if_num; pup++) { - VALIDATE_ACTIVE(tm->bus_act_mask, pup); + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup); CHECK_STATUS(ddr3_tip_bus_read (dev_num, if_id, ACCESS_TYPE_UNICAST, pup, @@ -965,7 +979,7 @@ int ddr3_tip_print_pbs_result(u32 dev_num, u32 cs_num, enum pbs_dir pbs_mode) return MV_OK; } -#endif +#endif /* DDR_VIEWER_TOOL */ /* * Fixup PBS Result @@ -974,13 +988,14 @@ int ddr3_tip_clean_pbs_result(u32 dev_num, enum pbs_dir pbs_mode) { u32 if_id, pup, bit; u32 reg_addr = (pbs_mode == PBS_RX_MODE) ? - (PBS_RX_PHY_REG + effective_cs * 0x10) : - (PBS_TX_PHY_REG + effective_cs * 0x10); - struct hws_topology_map *tm = ddr3_get_topology_map(); + PBS_RX_PHY_REG(effective_cs, 0) : + PBS_TX_PHY_REG(effective_cs, 0); + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - for (pup = 0; pup <= tm->num_of_bus_per_interface; pup++) { + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + for (pup = 0; pup <= octets_per_if_num; pup++) { for (bit = 0; bit <= BUS_WIDTH_IN_BITS + 3; bit++) { CHECK_STATUS(ddr3_tip_bus_write (dev_num, ACCESS_TYPE_UNICAST, diff --git a/drivers/ddr/marvell/a38x/ddr3_training_static.c b/drivers/ddr/marvell/a38x/ddr3_training_static.c deleted file mode 100644 index 1b4bfb2e02..0000000000 --- a/drivers/ddr/marvell/a38x/ddr3_training_static.c +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#include -#include -#include -#include -#include - -#include "ddr3_init.h" - -/* Design Guidelines parameters */ -u32 g_zpri_data = 123; /* controller data - P drive strength */ -u32 g_znri_data = 123; /* controller data - N drive strength */ -u32 g_zpri_ctrl = 74; /* controller C/A - P drive strength */ -u32 g_znri_ctrl = 74; /* controller C/A - N drive strength */ -u32 g_zpodt_data = 45; /* controller data - P ODT */ -u32 g_znodt_data = 45; /* controller data - N ODT */ -u32 g_zpodt_ctrl = 45; /* controller data - P ODT */ -u32 g_znodt_ctrl = 45; /* controller data - N ODT */ -u32 g_odt_config_2cs = 0x120012; -u32 g_odt_config_1cs = 0x10000; -u32 g_rtt_nom = 0x44; -u32 g_dic = 0x2; - - -/* - * Configure phy (called by static init controller) for static flow - */ -int ddr3_tip_configure_phy(u32 dev_num) -{ - u32 if_id, phy_id; - struct hws_topology_map *tm = ddr3_get_topology_map(); - - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, - PAD_ZRI_CALIB_PHY_REG, - ((0x7f & g_zpri_data) << 7 | (0x7f & g_znri_data)))); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, - PAD_ZRI_CALIB_PHY_REG, - ((0x7f & g_zpri_ctrl) << 7 | (0x7f & g_znri_ctrl)))); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, - PAD_ODT_CALIB_PHY_REG, - ((0x3f & g_zpodt_data) << 6 | (0x3f & g_znodt_data)))); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, - PAD_ODT_CALIB_PHY_REG, - ((0x3f & g_zpodt_ctrl) << 6 | (0x3f & g_znodt_ctrl)))); - - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, - PAD_PRE_DISABLE_PHY_REG, 0)); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, - CMOS_CONFIG_PHY_REG, 0)); - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, - CMOS_CONFIG_PHY_REG, 0)); - - for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { - /* check if the interface is enabled */ - VALIDATE_ACTIVE(tm->if_act_mask, if_id); - - for (phy_id = 0; - phy_id < tm->num_of_bus_per_interface; - phy_id++) { - VALIDATE_ACTIVE(tm->bus_act_mask, phy_id); - /* Vref & clamp */ - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, phy_id, DDR_PHY_DATA, - PAD_CONFIG_PHY_REG, - ((clamp_tbl[if_id] << 4) | vref), - ((0x7 << 4) | 0x7))); - /* clamp not relevant for control */ - CHECK_STATUS(ddr3_tip_bus_read_modify_write - (dev_num, ACCESS_TYPE_UNICAST, - if_id, phy_id, DDR_PHY_CONTROL, - PAD_CONFIG_PHY_REG, 0x4, 0x7)); - } - } - - CHECK_STATUS(ddr3_tip_bus_write - (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, - ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, 0x90, - 0x6002)); - - return MV_OK; -} diff --git a/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h b/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h new file mode 100644 index 0000000000..5bf3239921 --- /dev/null +++ b/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h @@ -0,0 +1,148 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#ifndef _DDR_ML_WRAPPER_H +#define _DDR_ML_WRAPPER_H + +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) +#define INTER_REGS_BASE SOC_REGS_PHY_BASE +#endif + +/* + * MV_DEBUG_INIT need to be defines, otherwise the output of the + * DDR2 training code is not complete and misleading + */ +#define MV_DEBUG_INIT + +#ifdef MV_DEBUG_INIT +#define DEBUG_INIT_S(s) puts(s) +#define DEBUG_INIT_D(d, l) printf("%x", d) +#define DEBUG_INIT_D_10(d, l) printf("%d", d) +#else +#define DEBUG_INIT_S(s) +#define DEBUG_INIT_D(d, l) +#define DEBUG_INIT_D_10(d, l) +#endif + +#ifdef MV_DEBUG_INIT_FULL +#define DEBUG_INIT_FULL_S(s) puts(s) +#define DEBUG_INIT_FULL_D(d, l) printf("%x", d) +#define DEBUG_INIT_FULL_D_10(d, l) printf("%d", d) +#define DEBUG_WR_REG(reg, val) \ + { DEBUG_INIT_S("Write Reg: 0x"); DEBUG_INIT_D((reg), 8); \ + DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); } +#define DEBUG_RD_REG(reg, val) \ + { DEBUG_INIT_S("Read Reg: 0x"); DEBUG_INIT_D((reg), 8); \ + DEBUG_INIT_S("= "); DEBUG_INIT_D((val), 8); DEBUG_INIT_S("\n"); } +#else +#define DEBUG_INIT_FULL_S(s) +#define DEBUG_INIT_FULL_D(d, l) +#define DEBUG_INIT_FULL_D_10(d, l) +#define DEBUG_WR_REG(reg, val) +#define DEBUG_RD_REG(reg, val) +#endif + +#define DEBUG_INIT_FULL_C(s, d, l) \ + { DEBUG_INIT_FULL_S(s); \ + DEBUG_INIT_FULL_D(d, l); \ + DEBUG_INIT_FULL_S("\n"); } +#define DEBUG_INIT_C(s, d, l) \ + { DEBUG_INIT_S(s); DEBUG_INIT_D(d, l); DEBUG_INIT_S("\n"); } + +/* + * Debug (Enable/Disable modules) and Error report + */ + +#ifdef BASIC_DEBUG +#define MV_DEBUG_WL +#define MV_DEBUG_RL +#define MV_DEBUG_DQS_RESULTS +#endif + +#ifdef FULL_DEBUG +#define MV_DEBUG_WL +#define MV_DEBUG_RL +#define MV_DEBUG_DQS + +#define MV_DEBUG_PBS +#define MV_DEBUG_DFS +#define MV_DEBUG_MAIN_FULL +#define MV_DEBUG_DFS_FULL +#define MV_DEBUG_DQS_FULL +#define MV_DEBUG_RL_FULL +#define MV_DEBUG_WL_FULL +#endif + + +/* The following is a list of Marvell status */ +#define MV_ERROR (-1) +#define MV_OK (0x00) /* Operation succeeded */ +#define MV_FAIL (0x01) /* Operation failed */ +#define MV_BAD_VALUE (0x02) /* Illegal value (general) */ +#define MV_OUT_OF_RANGE (0x03) /* The value is out of range */ +#define MV_BAD_PARAM (0x04) /* Illegal parameter in function called */ +#define MV_BAD_PTR (0x05) /* Illegal pointer value */ +#define MV_BAD_SIZE (0x06) /* Illegal size */ +#define MV_BAD_STATE (0x07) /* Illegal state of state machine */ +#define MV_SET_ERROR (0x08) /* Set operation failed */ +#define MV_GET_ERROR (0x09) /* Get operation failed */ +#define MV_CREATE_ERROR (0x0a) /* Fail while creating an item */ +#define MV_NOT_FOUND (0x0b) /* Item not found */ +#define MV_NO_MORE (0x0c) /* No more items found */ +#define MV_NO_SUCH (0x0d) /* No such item */ +#define MV_TIMEOUT (0x0e) /* Time Out */ +#define MV_NO_CHANGE (0x0f) /* Parameter(s) is already in this value */ +#define MV_NOT_SUPPORTED (0x10) /* This request is not support */ +#define MV_NOT_IMPLEMENTED (0x11) /* Request supported but not implemented*/ +#define MV_NOT_INITIALIZED (0x12) /* The item is not initialized */ +#define MV_NO_RESOURCE (0x13) /* Resource not available (memory ...) */ +#define MV_FULL (0x14) /* Item is full (Queue or table etc...) */ +#define MV_EMPTY (0x15) /* Item is empty (Queue or table etc...) */ +#define MV_INIT_ERROR (0x16) /* Error occured while INIT process */ +#define MV_HW_ERROR (0x17) /* Hardware error */ +#define MV_TX_ERROR (0x18) /* Transmit operation not succeeded */ +#define MV_RX_ERROR (0x19) /* Recieve operation not succeeded */ +#define MV_NOT_READY (0x1a) /* The other side is not ready yet */ +#define MV_ALREADY_EXIST (0x1b) /* Tried to create existing item */ +#define MV_OUT_OF_CPU_MEM (0x1c) /* Cpu memory allocation failed. */ +#define MV_NOT_STARTED (0x1d) /* Not started yet */ +#define MV_BUSY (0x1e) /* Item is busy. */ +#define MV_TERMINATE (0x1f) /* Item terminates it's work. */ +#define MV_NOT_ALIGNED (0x20) /* Wrong alignment */ +#define MV_NOT_ALLOWED (0x21) /* Operation NOT allowed */ +#define MV_WRITE_PROTECT (0x22) /* Write protected */ +#define MV_INVALID (int)(-1) + +/* + * Accessor functions for the registers + */ +static inline void reg_write(u32 addr, u32 val) +{ + writel(val, INTER_REGS_BASE + addr); +} + +static inline u32 reg_read(u32 addr) +{ + return readl(INTER_REGS_BASE + addr); +} + +static inline void reg_bit_set(u32 addr, u32 mask) +{ + setbits_le32(INTER_REGS_BASE + addr, mask); +} + +static inline void reg_bit_clr(u32 addr, u32 mask) +{ + clrbits_le32(INTER_REGS_BASE + addr, mask); +} + +#endif /* _DDR_ML_WRAPPER_H */ diff --git a/drivers/ddr/marvell/a38x/ddr_topology_def.h b/drivers/ddr/marvell/a38x/ddr_topology_def.h index aa98774e78..2c589eb3a6 100644 --- a/drivers/ddr/marvell/a38x/ddr_topology_def.h +++ b/drivers/ddr/marvell/a38x/ddr_topology_def.h @@ -9,38 +9,13 @@ #include "ddr3_training_ip_def.h" #include "ddr3_topology_def.h" -#if defined(CONFIG_ARMADA_38X) -#include "ddr3_a38x.h" +#if defined(CONFIG_ARMADA_38X) || defined(CONFIG_ARMADA_39X) +#include "mv_ddr_plat.h" #endif -/* bus width in bits */ -enum hws_bus_width { - BUS_WIDTH_4, - BUS_WIDTH_8, - BUS_WIDTH_16, - BUS_WIDTH_32 -}; - -enum hws_temperature { - HWS_TEMP_LOW, - HWS_TEMP_NORMAL, - HWS_TEMP_HIGH -}; - -enum hws_mem_size { - MEM_512M, - MEM_1G, - MEM_2G, - MEM_4G, - MEM_8G, - MEM_SIZE_LAST -}; - -enum hws_timing { - HWS_TIM_DEFAULT, - HWS_TIM_1T, - HWS_TIM_2T -}; +#include "mv_ddr_topology.h" +#include "mv_ddr_spd.h" +#include "ddr3_logging_def.h" struct bus_params { /* Chip Select (CS) bitmask (bits 0-CS0, bit 1- CS1 ...) */ @@ -66,11 +41,11 @@ struct if_params { /* Speed Bin Table */ enum hws_speed_bin speed_bin_index; - /* bus width of memory */ - enum hws_bus_width bus_width; + /* sdram device width */ + enum mv_ddr_dev_width bus_width; - /* Bus memory size (MBit) */ - enum hws_mem_size memory_size; + /* total sdram capacity per die, megabits */ + enum mv_ddr_die_capacity memory_size; /* The DDR frequency for each interfaces */ enum hws_ddr_freq memory_freq; @@ -88,33 +63,49 @@ struct if_params { u8 cas_l; /* operation temperature */ - enum hws_temperature interface_temp; - - /* 2T vs 1T mode (by default computed from number of CSs) */ - enum hws_timing timing; + enum mv_ddr_temperature interface_temp; }; -struct hws_topology_map { +struct mv_ddr_topology_map { + /* debug level configuration */ + enum mv_ddr_debug_level debug_level; + /* Number of interfaces (default is 12) */ u8 if_act_mask; /* Controller configuration per interface */ struct if_params interface_params[MAX_INTERFACE_NUM]; - /* BUS per interface (default is 4) */ - u8 num_of_bus_per_interface; - /* Bit mask for active buses */ - u8 bus_act_mask; + u16 bus_act_mask; + + /* source of ddr configuration data */ + enum mv_ddr_cfg_src cfg_src; + + /* raw spd data */ + union mv_ddr_spd_data spd_data; + + /* timing parameters */ + unsigned int timing_data[MV_DDR_TDATA_LAST]; }; /* DDR3 training global configuration parameters */ struct tune_train_params { u32 ck_delay; - u32 ck_delay_16; - u32 p_finger; - u32 n_finger; u32 phy_reg3_val; + u32 g_zpri_data; + u32 g_znri_data; + u32 g_zpri_ctrl; + u32 g_znri_ctrl; + u32 g_zpodt_data; + u32 g_znodt_data; + u32 g_zpodt_ctrl; + u32 g_znodt_ctrl; + u32 g_dic; + u32 g_odt_config; + u32 g_rtt_nom; + u32 g_rtt_wr; + u32 g_rtt_park; }; #endif /* _DDR_TOPOLOGY_DEF_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_build_message.c b/drivers/ddr/marvell/a38x/mv_ddr_build_message.c new file mode 100644 index 0000000000..8e60448318 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_build_message.c @@ -0,0 +1 @@ +const char mv_ddr_build_message[] = ""; const char mv_ddr_version_string[] = "mv_ddr: mv_ddr-armada-17.10.4"; diff --git a/drivers/ddr/marvell/a38x/mv_ddr_common.c b/drivers/ddr/marvell/a38x/mv_ddr_common.c new file mode 100644 index 0000000000..7afabbfd88 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_common.c @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#include "mv_ddr_common.h" +#include "ddr_ml_wrapper.h" + +void mv_ddr_ver_print(void) +{ + printf("%s %s\n", mv_ddr_version_string, mv_ddr_build_message); +} + +/* ceiling division for positive integers */ +unsigned int ceil_div(unsigned int x, unsigned int y) +{ + return (x % y) ? (x / y + 1) : (x / y); +} + +/* + * time to number of clocks calculation based on the rounding algorithm + * using 97.4% inverse factor per JEDEC Standard No. 21-C, 4.1.2.L-4: + * Serial Presence Detect (SPD) for DDR4 SDRAM Modules + */ +unsigned int time_to_nclk(unsigned int t, unsigned int tclk) +{ + /* t & tclk parameters are in ps */ + return ((unsigned long)t * 1000 / tclk + 974) / 1000; +} + +/* round division of two positive integers to the nearest whole number */ +int round_div(unsigned int dividend, unsigned int divisor, unsigned int *quotient) +{ + if (quotient == NULL) { + printf("%s: error: NULL quotient pointer found\n", __func__); + return MV_FAIL; + } + + if (divisor == 0) { + printf("%s: error: division by zero\n", __func__); + return MV_FAIL; + } else { + *quotient = (dividend + divisor / 2) / divisor; + } + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_common.h b/drivers/ddr/marvell/a38x/mv_ddr_common.h new file mode 100644 index 0000000000..c71ff442ed --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_common.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#ifndef _MV_DDR_COMMON_H +#define _MV_DDR_COMMON_H + +extern const char mv_ddr_build_message[]; +extern const char mv_ddr_version_string[]; + +#define MV_DDR_NUM_BITS_IN_BYTE 8 +#define MV_DDR_MEGA_BITS (1024 * 1024) +#define MV_DDR_32_BITS_MASK 0xffffffff + +unsigned int ceil_div(unsigned int x, unsigned int y); +unsigned int time_to_nclk(unsigned int t, unsigned int tclk); +int round_div(unsigned int dividend, unsigned int divisor, unsigned int *quotient); + +#endif /* _MV_DDR_COMMON_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.c b/drivers/ddr/marvell/a38x/mv_ddr_plat.c new file mode 100644 index 0000000000..ce672e9dd4 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.c @@ -0,0 +1,1455 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#include "ddr3_init.h" + +#include "mv_ddr_sys_env_lib.h" + +#define DDR_INTERFACES_NUM 1 +#define DDR_INTERFACE_OCTETS_NUM 5 + +/* + * 1. L2 filter should be set at binary header to 0xD000000, + * to avoid conflict with internal register IO. + * 2. U-Boot modifies internal registers base to 0xf100000, + * and than should update L2 filter accordingly to 0xf000000 (3.75 GB) + */ +#define L2_FILTER_FOR_MAX_MEMORY_SIZE 0xC0000000 /* temporary limit l2 filter to 3gb (LSP issue) */ +#define ADDRESS_FILTERING_END_REGISTER 0x8c04 + +#define DYNAMIC_CS_SIZE_CONFIG +#define DISABLE_L2_FILTERING_DURING_DDR_TRAINING + +/* Termal Sensor Registers */ +#define TSEN_CONTROL_LSB_REG 0xE4070 +#define TSEN_CONTROL_LSB_TC_TRIM_OFFSET 0 +#define TSEN_CONTROL_LSB_TC_TRIM_MASK (0x7 << TSEN_CONTROL_LSB_TC_TRIM_OFFSET) +#define TSEN_CONTROL_MSB_REG 0xE4074 +#define TSEN_CONTROL_MSB_RST_OFFSET 8 +#define TSEN_CONTROL_MSB_RST_MASK (0x1 << TSEN_CONTROL_MSB_RST_OFFSET) +#define TSEN_STATUS_REG 0xe4078 +#define TSEN_STATUS_READOUT_VALID_OFFSET 10 +#define TSEN_STATUS_READOUT_VALID_MASK (0x1 << \ + TSEN_STATUS_READOUT_VALID_OFFSET) +#define TSEN_STATUS_TEMP_OUT_OFFSET 0 +#define TSEN_STATUS_TEMP_OUT_MASK (0x3ff << TSEN_STATUS_TEMP_OUT_OFFSET) + +static struct dlb_config ddr3_dlb_config_table[] = { + {DLB_CTRL_REG, 0x2000005c}, + {DLB_BUS_OPT_WT_REG, 0x00880000}, + {DLB_AGING_REG, 0x0f7f007f}, + {DLB_EVICTION_CTRL_REG, 0x0000129f}, + {DLB_EVICTION_TIMERS_REG, 0x00ff0000}, + {DLB_WTS_DIFF_CS_REG, 0x04030802}, + {DLB_WTS_DIFF_BG_REG, 0x00000a02}, + {DLB_WTS_SAME_BG_REG, 0x09000a01}, + {DLB_WTS_CMDS_REG, 0x00020005}, + {DLB_WTS_ATTR_PRIO_REG, 0x00060f10}, + {DLB_QUEUE_MAP_REG, 0x00000543}, + {DLB_SPLIT_REG, 0x00000000}, + {DLB_USER_CMD_REG, 0x00000000}, + {0x0, 0x0} +}; + +static struct dlb_config *sys_env_dlb_config_ptr_get(void) +{ + return &ddr3_dlb_config_table[0]; +} + +static u8 a38x_bw_per_freq[DDR_FREQ_LAST] = { + 0x3, /* DDR_FREQ_100 */ + 0x4, /* DDR_FREQ_400 */ + 0x4, /* DDR_FREQ_533 */ + 0x5, /* DDR_FREQ_667 */ + 0x5, /* DDR_FREQ_800 */ + 0x5, /* DDR_FREQ_933 */ + 0x5, /* DDR_FREQ_1066 */ + 0x3, /* DDR_FREQ_311 */ + 0x3, /* DDR_FREQ_333 */ + 0x4, /* DDR_FREQ_467 */ + 0x5, /* DDR_FREQ_850 */ + 0x5, /* DDR_FREQ_600 */ + 0x3, /* DDR_FREQ_300 */ + 0x5, /* DDR_FREQ_900 */ + 0x3, /* DDR_FREQ_360 */ + 0x5 /* DDR_FREQ_1000 */ +}; + +static u8 a38x_rate_per_freq[DDR_FREQ_LAST] = { + 0x1, /* DDR_FREQ_100 */ + 0x2, /* DDR_FREQ_400 */ + 0x2, /* DDR_FREQ_533 */ + 0x2, /* DDR_FREQ_667 */ + 0x2, /* DDR_FREQ_800 */ + 0x3, /* DDR_FREQ_933 */ + 0x3, /* DDR_FREQ_1066 */ + 0x1, /* DDR_FREQ_311 */ + 0x1, /* DDR_FREQ_333 */ + 0x2, /* DDR_FREQ_467 */ + 0x2, /* DDR_FREQ_850 */ + 0x2, /* DDR_FREQ_600 */ + 0x1, /* DDR_FREQ_300 */ + 0x2, /* DDR_FREQ_900 */ + 0x1, /* DDR_FREQ_360 */ + 0x2 /* DDR_FREQ_1000 */ +}; + +static u16 a38x_vco_freq_per_sar_ref_clk_25_mhz[] = { + 666, /* 0 */ + 1332, + 800, + 1600, + 1066, + 2132, + 1200, + 2400, + 1332, + 1332, + 1500, + 1500, + 1600, /* 12 */ + 1600, + 1700, + 1700, + 1866, + 1866, + 1800, /* 18 */ + 2000, + 2000, + 4000, + 2132, + 2132, + 2300, + 2300, + 2400, + 2400, + 2500, + 2500, + 800 +}; + +static u16 a38x_vco_freq_per_sar_ref_clk_40_mhz[] = { + 666, /* 0 */ + 1332, + 800, + 800, /* 0x3 */ + 1066, + 1066, /* 0x5 */ + 1200, + 2400, + 1332, + 1332, + 1500, /* 10 */ + 1600, /* 0xB */ + 1600, + 1600, + 1700, + 1560, /* 0xF */ + 1866, + 1866, + 1800, + 2000, + 2000, /* 20 */ + 4000, + 2132, + 2132, + 2300, + 2300, + 2400, + 2400, + 2500, + 2500, + 1800 /* 30 - 0x1E */ +}; + + +static u32 async_mode_at_tf; + +static u32 dq_bit_map_2_phy_pin[] = { + 1, 0, 2, 6, 9, 8, 3, 7, /* 0 */ + 8, 9, 1, 7, 2, 6, 3, 0, /* 1 */ + 3, 9, 7, 8, 1, 0, 2, 6, /* 2 */ + 1, 0, 6, 2, 8, 3, 7, 9, /* 3 */ + 0, 1, 2, 9, 7, 8, 3, 6, /* 4 */ +}; + +void mv_ddr_mem_scrubbing(void) +{ +} + +static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id, + enum hws_ddr_freq freq); + +/* + * Read temperature TJ value + */ +static u32 ddr3_ctrl_get_junc_temp(u8 dev_num) +{ + int reg = 0; + + /* Initiates TSEN hardware reset once */ + if ((reg_read(TSEN_CONTROL_MSB_REG) & TSEN_CONTROL_MSB_RST_MASK) == 0) { + reg_bit_set(TSEN_CONTROL_MSB_REG, TSEN_CONTROL_MSB_RST_MASK); + /* set Tsen Tc Trim to correct default value (errata #132698) */ + reg = reg_read(TSEN_CONTROL_LSB_REG); + reg &= ~TSEN_CONTROL_LSB_TC_TRIM_MASK; + reg |= 0x3 << TSEN_CONTROL_LSB_TC_TRIM_OFFSET; + reg_write(TSEN_CONTROL_LSB_REG, reg); + } + mdelay(10); + + /* Check if the readout field is valid */ + if ((reg_read(TSEN_STATUS_REG) & TSEN_STATUS_READOUT_VALID_MASK) == 0) { + printf("%s: TSEN not ready\n", __func__); + return 0; + } + + reg = reg_read(TSEN_STATUS_REG); + reg = (reg & TSEN_STATUS_TEMP_OUT_MASK) >> TSEN_STATUS_TEMP_OUT_OFFSET; + + return ((((10000 * reg) / 21445) * 1000) - 272674) / 1000; +} + +/* + * Name: ddr3_tip_a38x_get_freq_config. + * Desc: + * Args: + * Notes: + * Returns: MV_OK if success, other error code if fail. + */ +static int ddr3_tip_a38x_get_freq_config(u8 dev_num, enum hws_ddr_freq freq, + struct hws_tip_freq_config_info + *freq_config_info) +{ + if (a38x_bw_per_freq[freq] == 0xff) + return MV_NOT_SUPPORTED; + + if (freq_config_info == NULL) + return MV_BAD_PARAM; + + freq_config_info->bw_per_freq = a38x_bw_per_freq[freq]; + freq_config_info->rate_per_freq = a38x_rate_per_freq[freq]; + freq_config_info->is_supported = 1; + + return MV_OK; +} + +static void dunit_read(u32 addr, u32 mask, u32 *data) +{ + *data = reg_read(addr) & mask; +} + +static void dunit_write(u32 addr, u32 mask, u32 data) +{ + u32 reg_val = data; + + if (mask != MASK_ALL_BITS) { + dunit_read(addr, MASK_ALL_BITS, ®_val); + reg_val &= (~mask); + reg_val |= (data & mask); + } + + reg_write(addr, reg_val); +} + +#define ODPG_ENABLE_REG 0x186d4 +#define ODPG_EN_OFFS 0 +#define ODPG_EN_MASK 0x1 +#define ODPG_EN_ENA 1 +#define ODPG_EN_DONE 0 +#define ODPG_DIS_OFFS 8 +#define ODPG_DIS_MASK 0x1 +#define ODPG_DIS_DIS 1 +void mv_ddr_odpg_enable(void) +{ + dunit_write(ODPG_ENABLE_REG, + ODPG_EN_MASK << ODPG_EN_OFFS, + ODPG_EN_ENA << ODPG_EN_OFFS); +} + +void mv_ddr_odpg_disable(void) +{ + dunit_write(ODPG_ENABLE_REG, + ODPG_DIS_MASK << ODPG_DIS_OFFS, + ODPG_DIS_DIS << ODPG_DIS_OFFS); +} + +void mv_ddr_odpg_done_clr(void) +{ + return; +} + +int mv_ddr_is_odpg_done(u32 count) +{ + u32 i, data; + + for (i = 0; i < count; i++) { + dunit_read(ODPG_ENABLE_REG, MASK_ALL_BITS, &data); + if (((data >> ODPG_EN_OFFS) & ODPG_EN_MASK) == + ODPG_EN_DONE) + break; + } + + if (i >= count) { + printf("%s: timeout\n", __func__); + return MV_FAIL; + } + + return MV_OK; +} + +void mv_ddr_training_enable(void) +{ + dunit_write(GLOB_CTRL_STATUS_REG, + TRAINING_TRIGGER_MASK << TRAINING_TRIGGER_OFFS, + TRAINING_TRIGGER_ENA << TRAINING_TRIGGER_OFFS); +} + +#define DRAM_INIT_CTRL_STATUS_REG 0x18488 +#define TRAINING_TRIGGER_OFFS 0 +#define TRAINING_TRIGGER_MASK 0x1 +#define TRAINING_TRIGGER_ENA 1 +#define TRAINING_DONE_OFFS 1 +#define TRAINING_DONE_MASK 0x1 +#define TRAINING_DONE_DONE 1 +#define TRAINING_DONE_NOT_DONE 0 +#define TRAINING_RESULT_OFFS 2 +#define TRAINING_RESULT_MASK 0x1 +#define TRAINING_RESULT_PASS 0 +#define TRAINING_RESULT_FAIL 1 +int mv_ddr_is_training_done(u32 count, u32 *result) +{ + u32 i, data; + + if (result == NULL) { + printf("%s: NULL result pointer found\n", __func__); + return MV_FAIL; + } + + for (i = 0; i < count; i++) { + dunit_read(DRAM_INIT_CTRL_STATUS_REG, MASK_ALL_BITS, &data); + if (((data >> TRAINING_DONE_OFFS) & TRAINING_DONE_MASK) == + TRAINING_DONE_DONE) + break; + } + + if (i >= count) { + printf("%s: timeout\n", __func__); + return MV_FAIL; + } + + *result = (data >> TRAINING_RESULT_OFFS) & TRAINING_RESULT_MASK; + + return MV_OK; +} + +#define DM_PAD 10 +u32 mv_ddr_dm_pad_get(void) +{ + return DM_PAD; +} + +/* + * Name: ddr3_tip_a38x_select_ddr_controller. + * Desc: Enable/Disable access to Marvell's server. + * Args: dev_num - device number + * enable - whether to enable or disable the server + * Notes: + * Returns: MV_OK if success, other error code if fail. + */ +static int ddr3_tip_a38x_select_ddr_controller(u8 dev_num, int enable) +{ + u32 reg; + + reg = reg_read(DUAL_DUNIT_CFG_REG); + + if (enable) + reg |= (1 << 6); + else + reg &= ~(1 << 6); + + reg_write(DUAL_DUNIT_CFG_REG, reg); + + return MV_OK; +} + +static u8 ddr3_tip_clock_mode(u32 frequency) +{ + if ((frequency == DDR_FREQ_LOW_FREQ) || (freq_val[frequency] <= 400)) + return 1; + + return 2; +} + +static int mv_ddr_sar_freq_get(int dev_num, enum hws_ddr_freq *freq) +{ + u32 reg, ref_clk_satr; + + /* Read sample at reset setting */ + reg = (reg_read(REG_DEVICE_SAR1_ADDR) >> + RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & + RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; + + ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG); + if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) == + DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) { + switch (reg) { + case 0x1: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 333Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0x0: + *freq = DDR_FREQ_333; + break; + case 0x3: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 400Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0x2: + *freq = DDR_FREQ_400; + break; + case 0xd: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 533Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0x4: + *freq = DDR_FREQ_533; + break; + case 0x6: + *freq = DDR_FREQ_600; + break; + case 0x11: + case 0x14: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 667Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0x8: + *freq = DDR_FREQ_667; + break; + case 0x15: + case 0x1b: + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("Warning: Unsupported freq mode for 800Mhz configured(%d)\n", + reg)); + /* fallthrough */ + case 0xc: + *freq = DDR_FREQ_800; + break; + case 0x10: + *freq = DDR_FREQ_933; + break; + case 0x12: + *freq = DDR_FREQ_900; + break; + case 0x13: + *freq = DDR_FREQ_933; + break; + default: + *freq = 0; + return MV_NOT_SUPPORTED; + } + } else { /* REFCLK 40MHz case */ + switch (reg) { + case 0x3: + *freq = DDR_FREQ_400; + break; + case 0x5: + *freq = DDR_FREQ_533; + break; + case 0xb: + *freq = DDR_FREQ_800; + break; + case 0x1e: + *freq = DDR_FREQ_900; + break; + default: + *freq = 0; + return MV_NOT_SUPPORTED; + } + } + + return MV_OK; +} + +static int ddr3_tip_a38x_get_medium_freq(int dev_num, enum hws_ddr_freq *freq) +{ + u32 reg, ref_clk_satr; + + /* Read sample at reset setting */ + reg = (reg_read(REG_DEVICE_SAR1_ADDR) >> + RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & + RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; + + ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG); + if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) == + DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) { + switch (reg) { + case 0x0: + case 0x1: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_333; + break; + case 0x2: + case 0x3: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_400; + break; + case 0x4: + case 0xd: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_533; + break; + case 0x8: + case 0x10: + case 0x11: + case 0x14: + *freq = DDR_FREQ_333; + break; + case 0xc: + case 0x15: + case 0x1b: + *freq = DDR_FREQ_400; + break; + case 0x6: + *freq = DDR_FREQ_300; + break; + case 0x12: + *freq = DDR_FREQ_360; + break; + case 0x13: + *freq = DDR_FREQ_400; + break; + default: + *freq = 0; + return MV_NOT_SUPPORTED; + } + } else { /* REFCLK 40MHz case */ + switch (reg) { + case 0x3: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_400; + break; + case 0x5: + /* Medium is same as TF to run PBS in this freq */ + *freq = DDR_FREQ_533; + break; + case 0xb: + *freq = DDR_FREQ_400; + break; + case 0x1e: + *freq = DDR_FREQ_360; + break; + default: + *freq = 0; + return MV_NOT_SUPPORTED; + } + } + + return MV_OK; +} + +static int ddr3_tip_a38x_get_device_info(u8 dev_num, struct ddr3_device_info *info_ptr) +{ +#if defined(CONFIG_ARMADA_39X) + info_ptr->device_id = 0x6900; +#else + info_ptr->device_id = 0x6800; +#endif + info_ptr->ck_delay = ck_delay; + + return MV_OK; +} + +/* check indirect access to phy register file completed */ +static int is_prfa_done(void) +{ + u32 reg_val; + u32 iter = 0; + + do { + if (iter++ > MAX_POLLING_ITERATIONS) { + printf("error: %s: polling timeout\n", __func__); + return MV_FAIL; + } + dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, ®_val); + reg_val >>= PRFA_REQ_OFFS; + reg_val &= PRFA_REQ_MASK; + } while (reg_val == PRFA_REQ_ENA); /* request pending */ + + return MV_OK; +} + +/* write to phy register thru indirect access */ +static int prfa_write(enum hws_access_type phy_access, u32 phy, + enum hws_ddr_phy phy_type, u32 addr, + u32 data, enum hws_operation op_type) +{ + u32 reg_val = ((data & PRFA_DATA_MASK) << PRFA_DATA_OFFS) | + ((addr & PRFA_REG_NUM_MASK) << PRFA_REG_NUM_OFFS) | + ((phy & PRFA_PUP_NUM_MASK) << PRFA_PUP_NUM_OFFS) | + ((phy_type & PRFA_PUP_CTRL_DATA_MASK) << PRFA_PUP_CTRL_DATA_OFFS) | + ((phy_access & PRFA_PUP_BCAST_WR_ENA_MASK) << PRFA_PUP_BCAST_WR_ENA_OFFS) | + (((addr >> 6) & PRFA_REG_NUM_HI_MASK) << PRFA_REG_NUM_HI_OFFS) | + ((op_type & PRFA_TYPE_MASK) << PRFA_TYPE_OFFS); + dunit_write(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, reg_val); + reg_val |= (PRFA_REQ_ENA << PRFA_REQ_OFFS); + dunit_write(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, reg_val); + + /* polling for prfa request completion */ + if (is_prfa_done() != MV_OK) + return MV_FAIL; + + return MV_OK; +} + +/* read from phy register thru indirect access */ +static int prfa_read(enum hws_access_type phy_access, u32 phy, + enum hws_ddr_phy phy_type, u32 addr, u32 *data) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + u32 max_phy = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + u32 i, reg_val; + + if (phy_access == ACCESS_TYPE_MULTICAST) { + for (i = 0; i < max_phy; i++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, i); + if (prfa_write(ACCESS_TYPE_UNICAST, i, phy_type, addr, 0, OPERATION_READ) != MV_OK) + return MV_FAIL; + dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, ®_val); + data[i] = (reg_val >> PRFA_DATA_OFFS) & PRFA_DATA_MASK; + } + } else { + if (prfa_write(phy_access, phy, phy_type, addr, 0, OPERATION_READ) != MV_OK) + return MV_FAIL; + dunit_read(PHY_REG_FILE_ACCESS_REG, MASK_ALL_BITS, ®_val); + *data = (reg_val >> PRFA_DATA_OFFS) & PRFA_DATA_MASK; + } + + return MV_OK; +} + +static int mv_ddr_sw_db_init(u32 dev_num, u32 board_id) +{ + struct hws_tip_config_func_db config_func; + + /* new read leveling version */ + config_func.mv_ddr_dunit_read = dunit_read; + config_func.mv_ddr_dunit_write = dunit_write; + config_func.tip_dunit_mux_select_func = + ddr3_tip_a38x_select_ddr_controller; + config_func.tip_get_freq_config_info_func = + ddr3_tip_a38x_get_freq_config; + config_func.tip_set_freq_divider_func = ddr3_tip_a38x_set_divider; + config_func.tip_get_device_info_func = ddr3_tip_a38x_get_device_info; + config_func.tip_get_temperature = ddr3_ctrl_get_junc_temp; + config_func.tip_get_clock_ratio = ddr3_tip_clock_mode; + config_func.tip_external_read = ddr3_tip_ext_read; + config_func.tip_external_write = ddr3_tip_ext_write; + config_func.mv_ddr_phy_read = prfa_read; + config_func.mv_ddr_phy_write = prfa_write; + + ddr3_tip_init_config_func(dev_num, &config_func); + + ddr3_tip_register_dq_table(dev_num, dq_bit_map_2_phy_pin); + + /* set device attributes*/ + ddr3_tip_dev_attr_init(dev_num); + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_TIP_REV, MV_TIP_REV_4); + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_PHY_EDGE, MV_DDR_PHY_EDGE_POSITIVE); + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_OCTET_PER_INTERFACE, DDR_INTERFACE_OCTETS_NUM); +#ifdef CONFIG_ARMADA_39X + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_INTERLEAVE_WA, 1); +#else + ddr3_tip_dev_attr_set(dev_num, MV_ATTR_INTERLEAVE_WA, 0); +#endif + + ca_delay = 0; + delay_enable = 1; + dfs_low_freq = DFS_LOW_FREQ_VALUE; + calibration_update_control = 1; + +#ifdef CONFIG_ARMADA_38X + /* For a38x only, change to 2T mode to resolve low freq instability */ + mode_2t = 1; +#endif + + ddr3_tip_a38x_get_medium_freq(dev_num, &medium_freq); + + return MV_OK; +} + +static int mv_ddr_training_mask_set(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + enum hws_ddr_freq ddr_freq = tm->interface_params[0].memory_freq; + + mask_tune_func = (SET_LOW_FREQ_MASK_BIT | + LOAD_PATTERN_MASK_BIT | + SET_MEDIUM_FREQ_MASK_BIT | WRITE_LEVELING_MASK_BIT | + WRITE_LEVELING_SUPP_MASK_BIT | + READ_LEVELING_MASK_BIT | + PBS_RX_MASK_BIT | + PBS_TX_MASK_BIT | + SET_TARGET_FREQ_MASK_BIT | + WRITE_LEVELING_TF_MASK_BIT | + WRITE_LEVELING_SUPP_TF_MASK_BIT | + READ_LEVELING_TF_MASK_BIT | + CENTRALIZATION_RX_MASK_BIT | + CENTRALIZATION_TX_MASK_BIT); + rl_mid_freq_wa = 1; + + if ((ddr_freq == DDR_FREQ_333) || (ddr_freq == DDR_FREQ_400)) { + mask_tune_func = (WRITE_LEVELING_MASK_BIT | + LOAD_PATTERN_2_MASK_BIT | + WRITE_LEVELING_SUPP_MASK_BIT | + READ_LEVELING_MASK_BIT | + PBS_RX_MASK_BIT | + PBS_TX_MASK_BIT | + CENTRALIZATION_RX_MASK_BIT | + CENTRALIZATION_TX_MASK_BIT); + rl_mid_freq_wa = 0; /* WA not needed if 333/400 is TF */ + } + + /* Supplementary not supported for ECC modes */ + if (1 == ddr3_if_ecc_enabled()) { + mask_tune_func &= ~WRITE_LEVELING_SUPP_TF_MASK_BIT; + mask_tune_func &= ~WRITE_LEVELING_SUPP_MASK_BIT; + mask_tune_func &= ~PBS_TX_MASK_BIT; + mask_tune_func &= ~PBS_RX_MASK_BIT; + } + + return MV_OK; +} + +/* function: mv_ddr_set_calib_controller + * this function sets the controller which will control + * the calibration cycle in the end of the training. + * 1 - internal controller + * 2 - external controller + */ +void mv_ddr_set_calib_controller(void) +{ + calibration_update_control = CAL_UPDATE_CTRL_INT; +} + +static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id, + enum hws_ddr_freq frequency) +{ + u32 divider = 0; + u32 sar_val, ref_clk_satr; + u32 async_val; + + if (if_id != 0) { + DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR, + ("A38x does not support interface 0x%x\n", + if_id)); + return MV_BAD_PARAM; + } + + /* get VCO freq index */ + sar_val = (reg_read(REG_DEVICE_SAR1_ADDR) >> + RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) & + RST2_CPU_DDR_CLOCK_SELECT_IN_MASK; + + ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG); + if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) == + DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ) + divider = a38x_vco_freq_per_sar_ref_clk_25_mhz[sar_val] / freq_val[frequency]; + else + divider = a38x_vco_freq_per_sar_ref_clk_40_mhz[sar_val] / freq_val[frequency]; + + if ((async_mode_at_tf == 1) && (freq_val[frequency] > 400)) { + /* Set async mode */ + dunit_write(0x20220, 0x1000, 0x1000); + dunit_write(0xe42f4, 0x200, 0x200); + + /* Wait for async mode setup */ + mdelay(5); + + /* Set KNL values */ + switch (frequency) { +#ifdef CONFIG_DDR3 + case DDR_FREQ_467: + async_val = 0x806f012; + break; + case DDR_FREQ_533: + async_val = 0x807f012; + break; + case DDR_FREQ_600: + async_val = 0x805f00a; + break; +#endif + case DDR_FREQ_667: + async_val = 0x809f012; + break; + case DDR_FREQ_800: + async_val = 0x807f00a; + break; +#ifdef CONFIG_DDR3 + case DDR_FREQ_850: + async_val = 0x80cb012; + break; +#endif + case DDR_FREQ_900: + async_val = 0x80d7012; + break; + case DDR_FREQ_933: + async_val = 0x80df012; + break; + case DDR_FREQ_1000: + async_val = 0x80ef012; + break; + case DDR_FREQ_1066: + async_val = 0x80ff012; + break; + default: + /* set DDR_FREQ_667 as default */ + async_val = 0x809f012; + } + dunit_write(0xe42f0, 0xffffffff, async_val); + } else { + /* Set sync mode */ + dunit_write(0x20220, 0x1000, 0x0); + dunit_write(0xe42f4, 0x200, 0x0); + + /* cpupll_clkdiv_reset_mask */ + dunit_write(0xe4264, 0xff, 0x1f); + + /* cpupll_clkdiv_reload_smooth */ + dunit_write(0xe4260, (0xff << 8), (0x2 << 8)); + + /* cpupll_clkdiv_relax_en */ + dunit_write(0xe4260, (0xff << 24), (0x2 << 24)); + + /* write the divider */ + dunit_write(0xe4268, (0x3f << 8), (divider << 8)); + + /* set cpupll_clkdiv_reload_ratio */ + dunit_write(0xe4264, (1 << 8), (1 << 8)); + + /* undet cpupll_clkdiv_reload_ratio */ + dunit_write(0xe4264, (1 << 8), 0x0); + + /* clear cpupll_clkdiv_reload_force */ + dunit_write(0xe4260, (0xff << 8), 0x0); + + /* clear cpupll_clkdiv_relax_en */ + dunit_write(0xe4260, (0xff << 24), 0x0); + + /* clear cpupll_clkdiv_reset_mask */ + dunit_write(0xe4264, 0xff, 0x0); + } + + /* Dunit training clock + 1:1/2:1 mode */ + dunit_write(0x18488, (1 << 16), ((ddr3_tip_clock_mode(frequency) & 0x1) << 16)); + dunit_write(0x1524, (1 << 15), ((ddr3_tip_clock_mode(frequency) - 1) << 15)); + + return MV_OK; +} + +/* + * external read from memory + */ +int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr, + u32 num_of_bursts, u32 *data) +{ + u32 burst_num; + + for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++) + data[burst_num] = readl(reg_addr + 4 * burst_num); + + return MV_OK; +} + +/* + * external write to memory + */ +int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr, + u32 num_of_bursts, u32 *data) { + u32 burst_num; + + for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++) + writel(data[burst_num], reg_addr + 4 * burst_num); + + return MV_OK; +} + +int mv_ddr_early_init(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* FIXME: change this configuration per ddr type + * configure a380 and a390 to work with receiver odt timing + * the odt_config is defined: + * '1' in ddr4 + * '0' in ddr3 + * here the parameter is run over in ddr4 and ddr3 to '1' (in ddr4 the default is '1') + * to configure the odt to work with timing restrictions + */ + + mv_ddr_sw_db_init(0, 0); + + if (tm->interface_params[0].memory_freq != DDR_FREQ_SAR) + async_mode_at_tf = 1; + + return MV_OK; +} + +int mv_ddr_early_init2(void) +{ + mv_ddr_training_mask_set(); + + return MV_OK; +} + +int mv_ddr_pre_training_fixup(void) +{ + return 0; +} + +int mv_ddr_post_training_fixup(void) +{ + return 0; +} + +int ddr3_post_run_alg(void) +{ + return MV_OK; +} + +int ddr3_silicon_post_init(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + /* Set half bus width */ + if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask)) { + CHECK_STATUS(ddr3_tip_if_write + (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE, + SDRAM_CFG_REG, 0x0, 0x8000)); + } + + return MV_OK; +} + +u32 mv_ddr_init_freq_get(void) +{ + enum hws_ddr_freq freq; + + mv_ddr_sar_freq_get(0, &freq); + + return freq; +} + +static u32 ddr3_get_bus_width(void) +{ + u32 bus_width; + + bus_width = (reg_read(SDRAM_CFG_REG) & 0x8000) >> + BUS_IN_USE_OFFS; + + return (bus_width == 0) ? 16 : 32; +} + +static u32 ddr3_get_device_width(u32 cs) +{ + u32 device_width; + + device_width = (reg_read(SDRAM_ADDR_CTRL_REG) & + (CS_STRUCT_MASK << CS_STRUCT_OFFS(cs))) >> + CS_STRUCT_OFFS(cs); + + return (device_width == 0) ? 8 : 16; +} + +static u32 ddr3_get_device_size(u32 cs) +{ + u32 device_size_low, device_size_high, device_size; + u32 data, cs_low_offset, cs_high_offset; + + cs_low_offset = CS_SIZE_OFFS(cs); + cs_high_offset = CS_SIZE_HIGH_OFFS(cs); + + data = reg_read(SDRAM_ADDR_CTRL_REG); + device_size_low = (data >> cs_low_offset) & 0x3; + device_size_high = (data >> cs_high_offset) & 0x1; + + device_size = device_size_low | (device_size_high << 2); + + switch (device_size) { + case 0: + return 2048; + case 2: + return 512; + case 3: + return 1024; + case 4: + return 4096; + case 5: + return 8192; + case 1: + default: + DEBUG_INIT_C("Error: Wrong device size of Cs: ", cs, 1); + /* zeroes mem size in ddr3_calc_mem_cs_size */ + return 0; + } +} + +static int ddr3_calc_mem_cs_size(u32 cs, uint64_t *cs_size) +{ + u32 cs_mem_size; + + /* Calculate in MiB */ + cs_mem_size = ((ddr3_get_bus_width() / ddr3_get_device_width(cs)) * + ddr3_get_device_size(cs)) / 8; + + /* + * Multiple controller bus width, 2x for 64 bit + * (SoC controller may be 32 or 64 bit, + * so bit 15 in 0x1400, that means if whole bus used or only half, + * have a differnt meaning + */ + cs_mem_size *= DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER; + + if ((cs_mem_size < 128) || (cs_mem_size > 4096)) { + DEBUG_INIT_C("Error: Wrong Memory size of Cs: ", cs, 1); + return MV_BAD_VALUE; + } + + *cs_size = cs_mem_size << 20; /* write cs size in bytes */ + + return MV_OK; +} + +static int ddr3_fast_path_dynamic_cs_size_config(u32 cs_ena) +{ + u32 reg, cs; + uint64_t mem_total_size = 0; + uint64_t cs_mem_size = 0; + uint64_t mem_total_size_c, cs_mem_size_c; + +#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE + u32 physical_mem_size; + u32 max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); +#endif + + /* Open fast path windows */ + for (cs = 0; cs < MAX_CS_NUM; cs++) { + if (cs_ena & (1 << cs)) { + /* get CS size */ + if (ddr3_calc_mem_cs_size(cs, &cs_mem_size) != MV_OK) + return MV_FAIL; + +#ifdef DEVICE_MAX_DRAM_ADDRESS_SIZE + /* + * if number of address pins doesn't allow to use max + * mem size that is defined in topology + * mem size is defined by DEVICE_MAX_DRAM_ADDRESS_SIZE + */ + physical_mem_size = mem_size + [tm->interface_params[0].memory_size]; + + if (ddr3_get_device_width(cs) == 16) { + /* + * 16bit mem device can be twice more - no need + * in less significant pin + */ + max_mem_size = DEVICE_MAX_DRAM_ADDRESS_SIZE * 2; + } + + if (physical_mem_size > max_mem_size) { + cs_mem_size = max_mem_size * + (ddr3_get_bus_width() / + ddr3_get_device_width(cs)); + printf("Updated Physical Mem size is from 0x%x to %x\n", + physical_mem_size, + DEVICE_MAX_DRAM_ADDRESS_SIZE); + } +#endif + + /* set fast path window control for the cs */ + reg = 0xffffe1; + reg |= (cs << 2); + reg |= (cs_mem_size - 1) & 0xffff0000; + /*Open fast path Window */ + reg_write(REG_FASTPATH_WIN_CTRL_ADDR(cs), reg); + + /* Set fast path window base address for the cs */ + reg = ((cs_mem_size) * cs) & 0xffff0000; + /* Set base address */ + reg_write(REG_FASTPATH_WIN_BASE_ADDR(cs), reg); + + /* + * Since memory size may be bigger than 4G the summ may + * be more than 32 bit word, + * so to estimate the result divide mem_total_size and + * cs_mem_size by 0x10000 (it is equal to >> 16) + */ + mem_total_size_c = (mem_total_size >> 16) & 0xffffffffffff; + cs_mem_size_c = (cs_mem_size >> 16) & 0xffffffffffff; + /* if the sum less than 2 G - calculate the value */ + if (mem_total_size_c + cs_mem_size_c < 0x10000) + mem_total_size += cs_mem_size; + else /* put max possible size */ + mem_total_size = L2_FILTER_FOR_MAX_MEMORY_SIZE; + } + } + + /* Set L2 filtering to Max Memory size */ + reg_write(ADDRESS_FILTERING_END_REGISTER, mem_total_size); + + return MV_OK; +} + +static int ddr3_restore_and_set_final_windows(u32 *win, const char *ddr_type) +{ + u32 win_ctrl_reg, num_of_win_regs; + u32 cs_ena = mv_ddr_sys_env_get_cs_ena_from_reg(); + u32 ui; + + win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; + num_of_win_regs = 16; + + /* Return XBAR windows 4-7 or 16-19 init configuration */ + for (ui = 0; ui < num_of_win_regs; ui++) + reg_write((win_ctrl_reg + 0x4 * ui), win[ui]); + + printf("%s Training Sequence - Switching XBAR Window to FastPath Window\n", + ddr_type); + +#if defined DYNAMIC_CS_SIZE_CONFIG + if (ddr3_fast_path_dynamic_cs_size_config(cs_ena) != MV_OK) + printf("ddr3_fast_path_dynamic_cs_size_config FAILED\n"); +#else + u32 reg, cs; + reg = 0x1fffffe1; + for (cs = 0; cs < MAX_CS_NUM; cs++) { + if (cs_ena & (1 << cs)) { + reg |= (cs << 2); + break; + } + } + /* Open fast path Window to - 0.5G */ + reg_write(REG_FASTPATH_WIN_CTRL_ADDR(0), reg); +#endif + + return MV_OK; +} + +static int ddr3_save_and_set_training_windows(u32 *win) +{ + u32 cs_ena; + u32 reg, tmp_count, cs, ui; + u32 win_ctrl_reg, win_base_reg, win_remap_reg; + u32 num_of_win_regs, win_jump_index; + win_ctrl_reg = REG_XBAR_WIN_4_CTRL_ADDR; + win_base_reg = REG_XBAR_WIN_4_BASE_ADDR; + win_remap_reg = REG_XBAR_WIN_4_REMAP_ADDR; + win_jump_index = 0x10; + num_of_win_regs = 16; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + +#ifdef DISABLE_L2_FILTERING_DURING_DDR_TRAINING + /* + * Disable L2 filtering during DDR training + * (when Cross Bar window is open) + */ + reg_write(ADDRESS_FILTERING_END_REGISTER, 0); +#endif + + cs_ena = tm->interface_params[0].as_bus_params[0].cs_bitmask; + + /* Close XBAR Window 19 - Not needed */ + /* {0x000200e8} - Open Mbus Window - 2G */ + reg_write(REG_XBAR_WIN_19_CTRL_ADDR, 0); + + /* Save XBAR Windows 4-19 init configurations */ + for (ui = 0; ui < num_of_win_regs; ui++) + win[ui] = reg_read(win_ctrl_reg + 0x4 * ui); + + /* Open XBAR Windows 4-7 or 16-19 for other CS */ + reg = 0; + tmp_count = 0; + for (cs = 0; cs < MAX_CS_NUM; cs++) { + if (cs_ena & (1 << cs)) { + switch (cs) { + case 0: + reg = 0x0e00; + break; + case 1: + reg = 0x0d00; + break; + case 2: + reg = 0x0b00; + break; + case 3: + reg = 0x0700; + break; + } + reg |= (1 << 0); + reg |= (SDRAM_CS_SIZE & 0xffff0000); + + reg_write(win_ctrl_reg + win_jump_index * tmp_count, + reg); + reg = (((SDRAM_CS_SIZE + 1) * (tmp_count)) & + 0xffff0000); + reg_write(win_base_reg + win_jump_index * tmp_count, + reg); + + if (win_remap_reg <= REG_XBAR_WIN_7_REMAP_ADDR) + reg_write(win_remap_reg + + win_jump_index * tmp_count, 0); + + tmp_count++; + } + } + + return MV_OK; +} + +static u32 win[16]; + +int mv_ddr_pre_training_soc_config(const char *ddr_type) +{ + u32 soc_num; + u32 reg_val; + + /* Switching CPU to MRVL ID */ + soc_num = (reg_read(REG_SAMPLE_RESET_HIGH_ADDR) & SAR1_CPU_CORE_MASK) >> + SAR1_CPU_CORE_OFFSET; + switch (soc_num) { + case 0x3: + reg_bit_set(CPU_CONFIGURATION_REG(3), CPU_MRVL_ID_OFFSET); + reg_bit_set(CPU_CONFIGURATION_REG(2), CPU_MRVL_ID_OFFSET); + /* fallthrough */ + case 0x1: + reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET); + /* fallthrough */ + case 0x0: + reg_bit_set(CPU_CONFIGURATION_REG(0), CPU_MRVL_ID_OFFSET); + /* fallthrough */ + default: + break; + } + + /* + * Set DRAM Reset Mask in case detected GPIO indication of wakeup from + * suspend i.e the DRAM values will not be overwritten / reset when + * waking from suspend + */ + if (mv_ddr_sys_env_suspend_wakeup_check() == + SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED) { + reg_bit_set(SDRAM_INIT_CTRL_REG, + DRAM_RESET_MASK_MASKED << DRAM_RESET_MASK_OFFS); + } + + /* Check if DRAM is already initialized */ + if (reg_read(REG_BOOTROM_ROUTINE_ADDR) & + (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)) { + printf("%s Training Sequence - 2nd boot - Skip\n", ddr_type); + return MV_OK; + } + + /* Fix read ready phases for all SOC in reg 0x15c8 */ + reg_val = reg_read(TRAINING_DBG_3_REG); + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(0)); + reg_val |= (0x4 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(0)); /* phase 0 */ + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(1)); + reg_val |= (0x4 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(1)); /* phase 1 */ + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(3)); + reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(3)); /* phase 3 */ + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(4)); + reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(4)); /* phase 4 */ + + reg_val &= ~(TRN_DBG_RDY_INC_PH_2TO1_MASK << TRN_DBG_RDY_INC_PH_2TO1_OFFS(5)); + reg_val |= (0x6 << TRN_DBG_RDY_INC_PH_2TO1_OFFS(5)); /* phase 5 */ + + reg_write(TRAINING_DBG_3_REG, reg_val); + + /* + * Axi_bresp_mode[8] = Compliant, + * Axi_addr_decode_cntrl[11] = Internal, + * Axi_data_bus_width[0] = 128bit + * */ + /* 0x14a8 - AXI Control Register */ + reg_write(AXI_CTRL_REG, 0); + + /* + * Stage 2 - Training Values Setup + */ + /* Set X-BAR windows for the training sequence */ + ddr3_save_and_set_training_windows(win); + + return MV_OK; +} + +static int ddr3_new_tip_dlb_config(void) +{ + u32 reg, i = 0; + struct dlb_config *config_table_ptr = sys_env_dlb_config_ptr_get(); + + /* Write the configuration */ + while (config_table_ptr[i].reg_addr != 0) { + reg_write(config_table_ptr[i].reg_addr, + config_table_ptr[i].reg_data); + i++; + } + + + /* Enable DLB */ + reg = reg_read(DLB_CTRL_REG); + reg &= ~(DLB_EN_MASK << DLB_EN_OFFS) & + ~(WR_COALESCE_EN_MASK << WR_COALESCE_EN_OFFS) & + ~(AXI_PREFETCH_EN_MASK << AXI_PREFETCH_EN_OFFS) & + ~(MBUS_PREFETCH_EN_MASK << MBUS_PREFETCH_EN_OFFS) & + ~(PREFETCH_NXT_LN_SZ_TRIG_MASK << PREFETCH_NXT_LN_SZ_TRIG_OFFS); + + reg |= (DLB_EN_ENA << DLB_EN_OFFS) | + (WR_COALESCE_EN_ENA << WR_COALESCE_EN_OFFS) | + (AXI_PREFETCH_EN_ENA << AXI_PREFETCH_EN_OFFS) | + (MBUS_PREFETCH_EN_ENA << MBUS_PREFETCH_EN_OFFS) | + (PREFETCH_NXT_LN_SZ_TRIG_ENA << PREFETCH_NXT_LN_SZ_TRIG_OFFS); + + reg_write(DLB_CTRL_REG, reg); + + return MV_OK; +} + +int mv_ddr_post_training_soc_config(const char *ddr_type) +{ + u32 reg_val; + + /* Restore and set windows */ + ddr3_restore_and_set_final_windows(win, ddr_type); + + /* Update DRAM init indication in bootROM register */ + reg_val = reg_read(REG_BOOTROM_ROUTINE_ADDR); + reg_write(REG_BOOTROM_ROUTINE_ADDR, + reg_val | (1 << REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS)); + + /* DLB config */ + ddr3_new_tip_dlb_config(); + + return MV_OK; +} + +void mv_ddr_mc_config(void) +{ + /* Memory controller initializations */ + struct init_cntr_param init_param; + int status; + + init_param.do_mrs_phy = 1; + init_param.is_ctrl64_bit = 0; + init_param.init_phy = 1; + init_param.msys_init = 1; + status = hws_ddr3_tip_init_controller(0, &init_param); + if (status != MV_OK) + printf("DDR3 init controller - FAILED 0x%x\n", status); + + status = mv_ddr_mc_init(); + if (status != MV_OK) + printf("DDR3 init_sequence - FAILED 0x%x\n", status); +} +/* function: mv_ddr_mc_init + * this function enables the dunit after init controller configuration + */ +int mv_ddr_mc_init(void) +{ + CHECK_STATUS(ddr3_tip_enable_init_sequence(0)); + + return MV_OK; +} + +/* function: ddr3_tip_configure_phy + * configures phy and electrical parameters + */ +int ddr3_tip_configure_phy(u32 dev_num) +{ + u32 if_id, phy_id; + u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, + PAD_ZRI_CAL_PHY_REG, + ((0x7f & g_zpri_data) << 7 | (0x7f & g_znri_data)))); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, + PAD_ZRI_CAL_PHY_REG, + ((0x7f & g_zpri_ctrl) << 7 | (0x7f & g_znri_ctrl)))); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, + PAD_ODT_CAL_PHY_REG, + ((0x3f & g_zpodt_data) << 6 | (0x3f & g_znodt_data)))); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, + PAD_ODT_CAL_PHY_REG, + ((0x3f & g_zpodt_ctrl) << 6 | (0x3f & g_znodt_ctrl)))); + + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, + PAD_PRE_DISABLE_PHY_REG, 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_DATA, + CMOS_CONFIG_PHY_REG, 0)); + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, DDR_PHY_CONTROL, + CMOS_CONFIG_PHY_REG, 0)); + + for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) { + /* check if the interface is enabled */ + VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id); + + for (phy_id = 0; + phy_id < octets_per_if_num; + phy_id++) { + VALIDATE_BUS_ACTIVE(tm->bus_act_mask, phy_id); + /* Vref & clamp */ + CHECK_STATUS(ddr3_tip_bus_read_modify_write + (dev_num, ACCESS_TYPE_UNICAST, + if_id, phy_id, DDR_PHY_DATA, + PAD_CFG_PHY_REG, + ((clamp_tbl[if_id] << 4) | vref_init_val), + ((0x7 << 4) | 0x7))); + /* clamp not relevant for control */ + CHECK_STATUS(ddr3_tip_bus_read_modify_write + (dev_num, ACCESS_TYPE_UNICAST, + if_id, phy_id, DDR_PHY_CONTROL, + PAD_CFG_PHY_REG, 0x4, 0x7)); + } + } + + if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_PHY_EDGE) == + MV_DDR_PHY_EDGE_POSITIVE) + CHECK_STATUS(ddr3_tip_bus_write + (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, + DDR_PHY_DATA, 0x90, 0x6002)); + + + return MV_OK; +} + + +int mv_ddr_manual_cal_do(void) +{ + return 0; +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.h b/drivers/ddr/marvell/a38x/mv_ddr_plat.h new file mode 100644 index 0000000000..61f10302fc --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.h @@ -0,0 +1,235 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#ifndef _MV_DDR_PLAT_H +#define _MV_DDR_PLAT_H + +#define MAX_INTERFACE_NUM 1 +#define MAX_BUS_NUM 5 +#define DDR_IF_CTRL_SUBPHYS_NUM 3 + +#define DFS_LOW_FREQ_VALUE 120 +#define SDRAM_CS_SIZE 0xfffffff /* FIXME: implement a function for cs size for each platform */ + +#define INTER_REGS_BASE SOC_REGS_PHY_BASE +#define AP_INT_REG_START_ADDR 0xd0000000 +#define AP_INT_REG_END_ADDR 0xd0100000 + +/* Controler bus divider 1 for 32 bit, 2 for 64 bit */ +#define DDR_CONTROLLER_BUS_WIDTH_MULTIPLIER 1 + +/* Tune internal training params values */ +#define TUNE_TRAINING_PARAMS_CK_DELAY 160 +#define TUNE_TRAINING_PARAMS_PHYREG3VAL 0xA +#define TUNE_TRAINING_PARAMS_PRI_DATA 123 +#define TUNE_TRAINING_PARAMS_NRI_DATA 123 +#define TUNE_TRAINING_PARAMS_PRI_CTRL 74 +#define TUNE_TRAINING_PARAMS_NRI_CTRL 74 +#define TUNE_TRAINING_PARAMS_P_ODT_DATA 45 +#define TUNE_TRAINING_PARAMS_N_ODT_DATA 45 +#define TUNE_TRAINING_PARAMS_P_ODT_CTRL 45 +#define TUNE_TRAINING_PARAMS_N_ODT_CTRL 45 +#define TUNE_TRAINING_PARAMS_DIC 0x2 +#define TUNE_TRAINING_PARAMS_ODT_CONFIG_2CS 0x120012 +#define TUNE_TRAINING_PARAMS_ODT_CONFIG_1CS 0x10000 +#define TUNE_TRAINING_PARAMS_RTT_NOM 0x44 + +#define TUNE_TRAINING_PARAMS_RTT_WR_1CS 0x0 /*off*/ +#define TUNE_TRAINING_PARAMS_RTT_WR_2CS 0x0 /*off*/ + +#define MARVELL_BOARD MARVELL_BOARD_ID_BASE + + +#define REG_DEVICE_SAR1_ADDR 0xe4204 +#define RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET 17 +#define RST2_CPU_DDR_CLOCK_SELECT_IN_MASK 0x1f +#define DEVICE_SAMPLE_AT_RESET2_REG 0x18604 + +#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET 0 +#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ 0 +#define DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_40MHZ 1 + +/* DRAM Windows */ +#define REG_XBAR_WIN_5_CTRL_ADDR 0x20050 +#define REG_XBAR_WIN_5_BASE_ADDR 0x20054 + +/* DRAM Windows */ +#define REG_XBAR_WIN_4_CTRL_ADDR 0x20040 +#define REG_XBAR_WIN_4_BASE_ADDR 0x20044 +#define REG_XBAR_WIN_4_REMAP_ADDR 0x20048 +#define REG_XBAR_WIN_7_REMAP_ADDR 0x20078 +#define REG_XBAR_WIN_16_CTRL_ADDR 0x200d0 +#define REG_XBAR_WIN_16_BASE_ADDR 0x200d4 +#define REG_XBAR_WIN_16_REMAP_ADDR 0x200dc +#define REG_XBAR_WIN_19_CTRL_ADDR 0x200e8 + +#define REG_FASTPATH_WIN_BASE_ADDR(win) (0x20180 + (0x8 * win)) +#define REG_FASTPATH_WIN_CTRL_ADDR(win) (0x20184 + (0x8 * win)) + +#define CPU_CONFIGURATION_REG(id) (0x21800 + (id * 0x100)) +#define CPU_MRVL_ID_OFFSET 0x10 +#define SAR1_CPU_CORE_MASK 0x00000018 +#define SAR1_CPU_CORE_OFFSET 3 + +/* SatR defined too change topology busWidth and ECC configuration */ +#define DDR_SATR_CONFIG_MASK_WIDTH 0x8 +#define DDR_SATR_CONFIG_MASK_ECC 0x10 +#define DDR_SATR_CONFIG_MASK_ECC_PUP 0x20 + +#define REG_SAMPLE_RESET_HIGH_ADDR 0x18600 + +#define MV_BOARD_REFCLK_25MHZ 25000000 +#define MV_BOARD_REFCLK MV_BOARD_REFCLK_25MHZ + +#define MAX_DQ_NUM 40 + +/* dram line buffer registers */ +#define DLB_CTRL_REG 0x1700 +#define DLB_EN_OFFS 0 +#define DLB_EN_MASK 0x1 +#define DLB_EN_ENA 1 +#define DLB_EN_DIS 0 +#define WR_COALESCE_EN_OFFS 2 +#define WR_COALESCE_EN_MASK 0x1 +#define WR_COALESCE_EN_ENA 1 +#define WR_COALESCE_EN_DIS 0 +#define AXI_PREFETCH_EN_OFFS 3 +#define AXI_PREFETCH_EN_MASK 0x1 +#define AXI_PREFETCH_EN_ENA 1 +#define AXI_PREFETCH_EN_DIS 0 +#define MBUS_PREFETCH_EN_OFFS 4 +#define MBUS_PREFETCH_EN_MASK 0x1 +#define MBUS_PREFETCH_EN_ENA 1 +#define MBUS_PREFETCH_EN_DIS 0 +#define PREFETCH_NXT_LN_SZ_TRIG_OFFS 6 +#define PREFETCH_NXT_LN_SZ_TRIG_MASK 0x1 +#define PREFETCH_NXT_LN_SZ_TRIG_ENA 1 +#define PREFETCH_NXT_LN_SZ_TRIG_DIS 0 + +#define DLB_BUS_OPT_WT_REG 0x1704 +#define DLB_AGING_REG 0x1708 +#define DLB_EVICTION_CTRL_REG 0x170c +#define DLB_EVICTION_TIMERS_REG 0x1710 +#define DLB_USER_CMD_REG 0x1714 +#define DLB_WTS_DIFF_CS_REG 0x1770 +#define DLB_WTS_DIFF_BG_REG 0x1774 +#define DLB_WTS_SAME_BG_REG 0x1778 +#define DLB_WTS_CMDS_REG 0x177c +#define DLB_WTS_ATTR_PRIO_REG 0x1780 +#define DLB_QUEUE_MAP_REG 0x1784 +#define DLB_SPLIT_REG 0x1788 + +/* Subphy result control per byte registers */ +#define RESULT_CONTROL_BYTE_PUP_0_REG 0x1830 +#define RESULT_CONTROL_BYTE_PUP_1_REG 0x1834 +#define RESULT_CONTROL_BYTE_PUP_2_REG 0x1838 +#define RESULT_CONTROL_BYTE_PUP_3_REG 0x183c +#define RESULT_CONTROL_BYTE_PUP_4_REG 0x18b0 + +/* Subphy result control per bit registers */ +#define RESULT_CONTROL_PUP_0_BIT_0_REG 0x18b4 +#define RESULT_CONTROL_PUP_0_BIT_1_REG 0x18b8 +#define RESULT_CONTROL_PUP_0_BIT_2_REG 0x18bc +#define RESULT_CONTROL_PUP_0_BIT_3_REG 0x18c0 +#define RESULT_CONTROL_PUP_0_BIT_4_REG 0x18c4 +#define RESULT_CONTROL_PUP_0_BIT_5_REG 0x18c8 +#define RESULT_CONTROL_PUP_0_BIT_6_REG 0x18cc +#define RESULT_CONTROL_PUP_0_BIT_7_REG 0x18f0 + +#define RESULT_CONTROL_PUP_1_BIT_0_REG 0x18f4 +#define RESULT_CONTROL_PUP_1_BIT_1_REG 0x18f8 +#define RESULT_CONTROL_PUP_1_BIT_2_REG 0x18fc +#define RESULT_CONTROL_PUP_1_BIT_3_REG 0x1930 +#define RESULT_CONTROL_PUP_1_BIT_4_REG 0x1934 +#define RESULT_CONTROL_PUP_1_BIT_5_REG 0x1938 +#define RESULT_CONTROL_PUP_1_BIT_6_REG 0x193c +#define RESULT_CONTROL_PUP_1_BIT_7_REG 0x19b0 + +#define RESULT_CONTROL_PUP_2_BIT_0_REG 0x19b4 +#define RESULT_CONTROL_PUP_2_BIT_1_REG 0x19b8 +#define RESULT_CONTROL_PUP_2_BIT_2_REG 0x19bc +#define RESULT_CONTROL_PUP_2_BIT_3_REG 0x19c0 +#define RESULT_CONTROL_PUP_2_BIT_4_REG 0x19c4 +#define RESULT_CONTROL_PUP_2_BIT_5_REG 0x19c8 +#define RESULT_CONTROL_PUP_2_BIT_6_REG 0x19cc +#define RESULT_CONTROL_PUP_2_BIT_7_REG 0x19f0 + +#define RESULT_CONTROL_PUP_3_BIT_0_REG 0x19f4 +#define RESULT_CONTROL_PUP_3_BIT_1_REG 0x19f8 +#define RESULT_CONTROL_PUP_3_BIT_2_REG 0x19fc +#define RESULT_CONTROL_PUP_3_BIT_3_REG 0x1a30 +#define RESULT_CONTROL_PUP_3_BIT_4_REG 0x1a34 +#define RESULT_CONTROL_PUP_3_BIT_5_REG 0x1a38 +#define RESULT_CONTROL_PUP_3_BIT_6_REG 0x1a3c +#define RESULT_CONTROL_PUP_3_BIT_7_REG 0x1ab0 + +#define RESULT_CONTROL_PUP_4_BIT_0_REG 0x1ab4 +#define RESULT_CONTROL_PUP_4_BIT_1_REG 0x1ab8 +#define RESULT_CONTROL_PUP_4_BIT_2_REG 0x1abc +#define RESULT_CONTROL_PUP_4_BIT_3_REG 0x1ac0 +#define RESULT_CONTROL_PUP_4_BIT_4_REG 0x1ac4 +#define RESULT_CONTROL_PUP_4_BIT_5_REG 0x1ac8 +#define RESULT_CONTROL_PUP_4_BIT_6_REG 0x1acc +#define RESULT_CONTROL_PUP_4_BIT_7_REG 0x1af0 + +/* CPU */ +#define REG_BOOTROM_ROUTINE_ADDR 0x182d0 +#define REG_BOOTROM_ROUTINE_DRAM_INIT_OFFS 12 + +/* Matrix enables DRAM modes (bus width/ECC) per boardId */ +#define TOPOLOGY_UPDATE_32BIT 0 +#define TOPOLOGY_UPDATE_32BIT_ECC 1 +#define TOPOLOGY_UPDATE_16BIT 2 +#define TOPOLOGY_UPDATE_16BIT_ECC 3 +#define TOPOLOGY_UPDATE_16BIT_ECC_PUP3 4 +#define TOPOLOGY_UPDATE { \ + /* 32Bit, 32bit ECC, 16bit, 16bit ECC PUP4, 16bit ECC PUP3 */ \ + {1, 1, 1, 1, 1}, /* RD_NAS_68XX_ID */ \ + {1, 1, 1, 1, 1}, /* DB_68XX_ID */ \ + {1, 0, 1, 0, 1}, /* RD_AP_68XX_ID */ \ + {1, 0, 1, 0, 1}, /* DB_AP_68XX_ID */ \ + {1, 0, 1, 0, 1}, /* DB_GP_68XX_ID */ \ + {0, 0, 1, 1, 0}, /* DB_BP_6821_ID */ \ + {1, 1, 1, 1, 1} /* DB_AMC_6820_ID */ \ + }; + +enum { + CPU_1066MHZ_DDR_400MHZ, + CPU_RESERVED_DDR_RESERVED0, + CPU_667MHZ_DDR_667MHZ, + CPU_800MHZ_DDR_800MHZ, + CPU_RESERVED_DDR_RESERVED1, + CPU_RESERVED_DDR_RESERVED2, + CPU_RESERVED_DDR_RESERVED3, + LAST_FREQ +}; + +/* struct used for DLB configuration array */ +struct dlb_config { + u32 reg_addr; + u32 reg_data; +}; + +#define ACTIVE_INTERFACE_MASK 0x1 + +extern u32 dmin_phy_reg_table[][2]; +extern u16 odt_slope[]; +extern u16 odt_intercept[]; + +int mv_ddr_pre_training_soc_config(const char *ddr_type); +int mv_ddr_post_training_soc_config(const char *ddr_type); +void mv_ddr_mem_scrubbing(void); + +void mv_ddr_odpg_enable(void); +void mv_ddr_odpg_disable(void); +void mv_ddr_odpg_done_clr(void); +int mv_ddr_is_odpg_done(u32 count); +void mv_ddr_training_enable(void); +int mv_ddr_is_training_done(u32 count, u32 *result); +u32 mv_ddr_dm_pad_get(void); +int mv_ddr_pre_training_fixup(void); +int mv_ddr_post_training_fixup(void); +int mv_ddr_manual_cal_do(void); +#endif /* _MV_DDR_PLAT_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_regs.h b/drivers/ddr/marvell/a38x/mv_ddr_regs.h new file mode 100644 index 0000000000..ceda204a49 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_regs.h @@ -0,0 +1,446 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#ifndef _MV_DDR_REGS_H +#define _MV_DDR_REGS_H + +#define GLOB_CTRL_STATUS_REG 0x1030 +#define TRAINING_TRIGGER_OFFS 0 +#define TRAINING_TRIGGER_MASK 0x1 +#define TRAINING_TRIGGER_ENA 1 +#define TRAINING_DONE_OFFS 1 +#define TRAINING_DONE_MASK 0x1 +#define TRAINING_DONE_DONE 1 +#define TRAINING_DONE_NOT_DONE 0 +#define TRAINING_RESULT_OFFS 2 +#define TRAINING_RESULT_MASK 0x1 +#define TRAINING_RESULT_PASS 0 +#define TRAINING_RESULT_FAIL 1 + +#define GENERAL_TRAINING_OPCODE_REG 0x1034 + +#define OPCODE_REG0_BASE 0x1038 +#define OPCODE_REG0_REG(obj) (OPCODE_REG0_BASE + (obj) * 0x4) + +#define OPCODE_REG1_BASE 0x10b0 +#define OPCODE_REG1_REG(obj) (OPCODE_REG1_BASE + (obj) * 0x4) + +#define CAL_PHY_BASE 0x10c0 +#define CAL_PHY_REG(obj) (CAL_PHY_BASE + (obj) * 0x4) + +#define WL_DONE_CNTR_REF_REG 0x10f8 +#define ODPG_WR_RD_MODE_ENA_REG 0x10fc + +#define SDRAM_CFG_REG 0x1400 +#define REFRESH_OFFS 0 +#define REFRESH_MASK 0x3fff +#define DRAM_TYPE_OFFS 14 +#define DRAM_TYPE_MASK 0x1 +#define BUS_IN_USE_OFFS 15 +#define BUS_IN_USE_MASK 0x1 +#define CPU_2DRAM_WR_BUFF_CUT_TH_OFFS 16 +#define CPU_2DRAM_WR_BUFF_CUT_TH_MASK 0x1 +#define REG_DIMM_OFFS 17 +#define REG_DIMM_MASK 0x1 +#define ECC_OFFS 18 +#define ECC_MASK 0x1 +#define IGNORE_ERRORS_OFFS 19 +#define IGNORE_ERRORS_MASK 0x1 +#define DRAM_TYPE_HIGH_OFFS 20 +#define DRAM_TYPE_HIGH_MASK 0x1 +#define SELF_REFRESH_MODE_OFFS 24 +#define SELF_REFRESH_MODE_MASK 0x1 +#define CPU_RD_PER_PROP_OFFS 25 +#define CPU_RD_PER_PROP_MASK 0x1 +#define DDR4_EMULATION_OFFS 26 +#define DDR4_EMULATION_MASK 0x1 +#define PHY_RF_RST_OFFS 27 +#define PHY_RF_RST_MASK 0x1 +#define PUP_RST_DIVIDER_OFFS 28 +#define PUP_RST_DIVIDER_MASK 0x1 +#define DATA_PUP_WR_RESET_OFFS 29 +#define DATA_PUP_WR_RESET_MASK 0x1 +#define DATA_PUP_RD_RESET_OFFS 30 +#define DATA_PUP_RD_RESET_MASK 0x1 +#define DATA_PUP_RD_RESET_ENA 0x0 +#define DATA_PUP_RD_RESET_DIS 0x1 +#define IO_BIST_OFFS 31 +#define DATA_PUP_RD_RESET_MASK 0x1 + +#define DUNIT_CTRL_LOW_REG 0x1404 + +#define SDRAM_TIMING_LOW_REG 0x1408 +#define SDRAM_TIMING_LOW_TRAS_OFFS 0 +#define SDRAM_TIMING_LOW_TRAS_MASK 0xf +#define SDRAM_TIMING_LOW_TRCD_OFFS 4 +#define SDRAM_TIMING_LOW_TRCD_MASK 0xf +#define SDRAM_TIMING_HIGH_TRCD_OFFS 22 +#define SDRAM_TIMING_HIGH_TRCD_MASK 0x1 +#define SDRAM_TIMING_LOW_TRP_OFFS 8 +#define SDRAM_TIMING_LOW_TRP_MASK 0xf +#define SDRAM_TIMING_HIGH_TRP_OFFS 23 +#define SDRAM_TIMING_HIGH_TRP_MASK 0x1 +#define SDRAM_TIMING_LOW_TWR_OFFS 12 +#define SDRAM_TIMING_LOW_TWR_MASK 0xf +#define SDRAM_TIMING_LOW_TWTR_OFFS 16 +#define SDRAM_TIMING_LOW_TWTR_MASK 0xf +#define SDRAM_TIMING_LOW_TRAS_HIGH_OFFS 20 +#define SDRAM_TIMING_LOW_TRAS_HIGH_MASK 0x3 +#define SDRAM_TIMING_LOW_TRRD_OFFS 24 +#define SDRAM_TIMING_LOW_TRRD_MASK 0xf +#define SDRAM_TIMING_LOW_TRTP_OFFS 28 +#define SDRAM_TIMING_LOW_TRTP_MASK 0xf + +#define SDRAM_TIMING_HIGH_REG 0x140c +#define SDRAM_TIMING_HIGH_TRFC_OFFS 0 +#define SDRAM_TIMING_HIGH_TRFC_MASK 0x7f +#define SDRAM_TIMING_HIGH_TR2R_OFFS 7 +#define SDRAM_TIMING_HIGH_TR2R_MASK 0x3 +#define SDRAM_TIMING_HIGH_TR2W_W2R_OFFS 9 +#define SDRAM_TIMING_HIGH_TR2W_W2R_MASK 0x3 +#define SDRAM_TIMING_HIGH_TW2W_OFFS 11 +#define SDRAM_TIMING_HIGH_TW2W_MASK 0x1f +#define SDRAM_TIMING_HIGH_TRFC_HIGH_OFFS 16 +#define SDRAM_TIMING_HIGH_TRFC_HIGH_MASK 0x7 +#define SDRAM_TIMING_HIGH_TR2R_HIGH_OFFS 19 +#define SDRAM_TIMING_HIGH_TR2R_HIGH_MASK 0x7 +#define SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_OFFS 22 +#define SDRAM_TIMING_HIGH_TR2W_W2R_HIGH_MASK 0x7 +#define SDRAM_TIMING_HIGH_TMOD_OFFS 25 +#define SDRAM_TIMING_HIGH_TMOD_MASK 0xf +#define SDRAM_TIMING_HIGH_TMOD_HIGH_OFFS 30 +#define SDRAM_TIMING_HIGH_TMOD_HIGH_MASK 0x3 + +#define SDRAM_ADDR_CTRL_REG 0x1410 +#define CS_STRUCT_BASE 0 +#define CS_STRUCT_OFFS(cs) (CS_STRUCT_BASE + (cs) * 4) +#define CS_STRUCT_MASK 0x3 +#define CS_SIZE_BASE 2 +#define CS_SIZE_OFFS(cs) (CS_SIZE_BASE + (cs) * 4) +#define CS_SIZE_MASK 0x3 +#define CS_SIZE_HIGH_BASE 20 +#define CS_SIZE_HIGH_OFFS(cs) (CS_SIZE_HIGH_BASE + (cs)) +#define CS_SIZE_HIGH_MASK 0x1 +#define T_FAW_OFFS 24 +#define T_FAW_MASK 0x7f + +#define SDRAM_OPEN_PAGES_CTRL_REG 0x1414 + +#define SDRAM_OP_REG 0x1418 +#define SDRAM_OP_CMD_OFFS 0 +#define SDRAM_OP_CMD_MASK 0x1f +#define SDRAM_OP_CMD_CS_BASE 8 +#define SDRAM_OP_CMD_CS_OFFS(cs) (SDRAM_OP_CMD_CS_BASE + (cs)) +#define SDRAM_OP_CMD_CS_MASK 0x1 +enum { + CMD_NORMAL, + CMD_PRECHARGE, + CMD_REFRESH, + CMD_DDR3_DDR4_MR0, + CMD_DDR3_DDR4_MR1, + CMD_NOP, + CMD_RES_0X6, + CMD_SELFREFRESH, + CMD_DDR3_DDR4_MR2, + CMD_DDR3_DDR4_MR3, + CMD_ACT_PDE, + CMD_PRE_PDE, + CMD_ZQCL, + CMD_ZQCS, + CMD_CWA, + CMD_RES_0XF, + CMD_DDR4_MR4, + CMD_DDR4_MR5, + CMD_DDR4_MR6, + DDR4_MPR_WR +}; + +#define DUNIT_CTRL_HIGH_REG 0x1424 +#define CPU_INTERJECTION_ENA_OFFS 3 +#define CPU_INTERJECTION_ENA_MASK 0x1 +#define CPU_INTERJECTION_ENA_SPLIT_ENA 0 +#define CPU_INTERJECTION_ENA_SPLIT_DIS 1 + +#define DDR_ODT_TIMING_LOW_REG 0x1428 + +#define DDR_TIMING_REG 0x142c +#define DDR_TIMING_TCCD_OFFS 18 +#define DDR_TIMING_TCCD_MASK 0x7 +#define DDR_TIMING_TPD_OFFS 0 +#define DDR_TIMING_TPD_MASK 0xf +#define DDR_TIMING_TXPDLL_OFFS 4 +#define DDR_TIMING_TXPDLL_MASK 0x1f + +#define DDR_ODT_TIMING_HIGH_REG 0x147c + +#define SDRAM_INIT_CTRL_REG 0x1480 +#define DRAM_RESET_MASK_OFFS 1 +#define DRAM_RESET_MASK_MASK 0x1 +#define DRAM_RESET_MASK_NORMAL 0 +#define DRAM_RESET_MASK_MASKED 1 + +#define SDRAM_ODT_CTRL_HIGH_REG 0x1498 +#define DUNIT_ODT_CTRL_REG 0x149c +#define RD_BUFFER_SEL_REG 0x14a4 +#define AXI_CTRL_REG 0x14a8 +#define DUNIT_MMASK_REG 0x14b0 + +#define HORZ_SSTL_CAL_MACH_CTRL_REG 0x14c8 +#define HORZ_POD_CAL_MACH_CTRL_REG 0x17c8 +#define VERT_SSTL_CAL_MACH_CTRL_REG 0x1dc8 +#define VERT_POD_CAL_MACH_CTRL_REG 0x1ec8 + +#define MAIN_PADS_CAL_MACH_CTRL_REG 0x14cc +#define DYN_PADS_CAL_ENABLE_OFFS 0 +#define DYN_PADS_CAL_ENABLE_MASK 0x1 +#define DYN_PADS_CAL_ENABLE_DIS 0 +#define DYN_PADS_CAL_ENABLE_ENA 1 +#define PADS_RECAL_OFFS 1 +#define PADS_RECAL_MASK 0x1 +#define DYN_PADS_CAL_BLOCK_OFFS 2 +#define DYN_PADS_CAL_BLOCK_MASK 0x1 +#define CAL_UPDATE_CTRL_OFFS 3 +#define CAL_UPDATE_CTRL_MASK 0x3 +#define CAL_UPDATE_CTRL_INT 1 +#define CAL_UPDATE_CTRL_EXT 2 +#define DYN_PADS_CAL_CNTR_OFFS 13 +#define DYN_PADS_CAL_CNTR_MASK 0x3ffff +#define CAL_MACH_STATUS_OFFS 31 +#define CAL_MACH_STATUS_MASK 0x1 +#define CAL_MACH_BUSY 0 +#define CAL_MACH_RDY 1 + +#define DRAM_DLL_TIMING_REG 0x14e0 +#define DRAM_ZQ_INIT_TIMIMG_REG 0x14e4 +#define DRAM_ZQ_TIMING_REG 0x14e8 + +#define DRAM_LONG_TIMING_REG 0x14ec +#define DDR4_TRRD_L_OFFS 0 +#define DDR4_TRRD_L_MASK 0xf +#define DDR4_TWTR_L_OFFS 4 +#define DDR4_TWTR_L_MASK 0xf + +#define DDR_IO_REG 0x1524 +#define DFS_REG 0x1528 + +#define RD_DATA_SMPL_DLYS_REG 0x1538 +#define RD_SMPL_DLY_CS_BASE 0 +#define RD_SMPL_DLY_CS_OFFS(cs) (RD_SMPL_DLY_CS_BASE + (cs) * 8) +#define RD_SMPL_DLY_CS_MASK 0x1f + +#define RD_DATA_RDY_DLYS_REG 0x153c +#define RD_RDY_DLY_CS_BASE 0 +#define RD_RDY_DLY_CS_OFFS(cs) (RD_RDY_DLY_CS_BASE + (cs) * 8) +#define RD_RDY_DLY_CS_MASK 0x1f + +#define TRAINING_REG 0x15b0 +#define TRN_START_OFFS 31 +#define TRN_START_MASK 0x1 +#define TRN_START_ENA 1 +#define TRN_START_DIS 0 + +#define TRAINING_SW_1_REG 0x15b4 + +#define TRAINING_SW_2_REG 0x15b8 +#define TRAINING_ECC_MUX_OFFS 1 +#define TRAINING_ECC_MUX_MASK 0x1 +#define TRAINING_ECC_MUX_DIS 0 +#define TRAINING_ECC_MUX_ENA 1 +#define TRAINING_SW_OVRD_OFFS 0 +#define TRAINING_SW_OVRD_MASK 0x1 +#define TRAINING_SW_OVRD_DIS 0 +#define TRAINING_SW_OVRD_ENA 1 + +#define TRAINING_PATTERN_BASE_ADDR_REG 0x15bc +#define TRAINING_DBG_1_REG 0x15c0 +#define TRAINING_DBG_2_REG 0x15c4 + +#define TRAINING_DBG_3_REG 0x15c8 +#define TRN_DBG_RDY_INC_PH_2TO1_BASE 0 +#define TRN_DBG_RDY_INC_PH_2TO1_OFFS(phase) (TRN_DBG_RDY_INC_PH_2TO1_BASE + (phase) * 3) +#define TRN_DBG_RDY_INC_PH_2TO1_MASK 0x7 + +#define DDR3_RANK_CTRL_REG 0x15e0 +#define CS_EXIST_BASE 0 +#define CS_EXIST_OFFS(cs) (CS_EXIST_BASE + (cs)) +#define CS_EXIST_MASK 0x1 + +#define ZQC_CFG_REG 0x15e4 +#define DRAM_PHY_CFG_REG 0x15ec +#define ODPG_CTRL_CTRL_REG 0x1600 + +#define ODPG_DATA_CTRL_REG 0x1630 +#define ODPG_WRBUF_WR_CTRL_OFFS 0 +#define ODPG_WRBUF_WR_CTRL_MASK 0x1 +#define ODPG_WRBUF_WR_CTRL_DIS 0 +#define ODPG_WRBUF_WR_CTRL_ENA 1 +#define ODPG_WRBUF_RD_CTRL_OFFS 1 +#define ODPG_WRBUF_RD_CTRL_MASK 0x1 +#define ODPG_WRBUF_RD_CTRL_DIS 0 +#define ODPG_WRBUF_RD_CTRL_ENA 1 +#define ODPG_DATA_CBDEL_OFFS 15 +#define ODPG_DATA_CBDEL_MASK 0x3f +#define ODPG_MODE_OFFS 25 +#define ODPG_MODE_MASK 0x1 +#define ODPG_MODE_RX 0 +#define ODPG_MODE_TX 1 +#define ODPG_DATA_CS_OFFS 26 +#define ODPG_DATA_CS_MASK 0x3 +#define ODPG_DISABLE_OFFS 30 +#define ODPG_DISABLE_MASK 0x1 +#define ODPG_DISABLE_DIS 1 +#define ODPG_ENABLE_OFFS 31 +#define ODPG_ENABLE_MASK 0x1 +#define ODPG_ENABLE_ENA 1 + +#define ODPG_DATA_BUFFER_OFFS_REG 0x1638 +#define ODPG_DATA_BUFFER_SIZE_REG 0x163c +#define PHY_LOCK_STATUS_REG 0x1674 + +#define PHY_REG_FILE_ACCESS_REG 0x16a0 +#define PRFA_DATA_OFFS 0 +#define PRFA_DATA_MASK 0xffff +#define PRFA_REG_NUM_OFFS 16 +#define PRFA_REG_NUM_MASK 0x3f +#define PRFA_PUP_NUM_OFFS 22 +#define PRFA_PUP_NUM_MASK 0xf +#define PRFA_PUP_CTRL_DATA_OFFS 26 +#define PRFA_PUP_CTRL_DATA_MASK 0x1 +#define PRFA_PUP_BCAST_WR_ENA_OFFS 27 +#define PRFA_PUP_BCAST_WR_ENA_MASK 0x1 +#define PRFA_REG_NUM_HI_OFFS 28 +#define PRFA_REG_NUM_HI_MASK 0x3 +#define PRFA_TYPE_OFFS 30 +#define PRFA_TYPE_MASK 0x1 +#define PRFA_REQ_OFFS 31 +#define PRFA_REQ_MASK 0x1 +#define PRFA_REQ_DIS 0x0 +#define PRFA_REQ_ENA 0x1 + +#define TRAINING_WL_REG 0x16ac + +#define ODPG_DATA_WR_ADDR_REG 0x16b0 +#define ODPG_DATA_WR_ACK_OFFS 0 +#define ODPG_DATA_WR_ACK_MASK 0x7f +#define ODPG_DATA_WR_DATA_OFFS 8 +#define ODPG_DATA_WR_DATA_MASK 0xff + +#define ODPG_DATA_WR_DATA_HIGH_REG 0x16b4 +#define ODPG_DATA_WR_DATA_LOW_REG 0x16b8 +#define ODPG_DATA_RX_WORD_ERR_ADDR_REG 0x16bc +#define ODPG_DATA_RX_WORD_ERR_CNTR_REG 0x16c0 +#define ODPG_DATA_RX_WORD_ERR_DATA_HIGH_REG 0x16c4 +#define ODPG_DATA_RX_WORD_ERR_DATA_LOW_REG 0x16c8 +#define ODPG_DATA_WR_DATA_ERR_REG 0x16cc + +#define DUAL_DUNIT_CFG_REG 0x16d8 +#define FC_SAMPLE_STAGES_OFFS 0 +#define FC_SAMPLE_STAGES_MASK 0x7 +#define SINGLE_CS_PIN_OFFS 3 +#define SINGLE_CS_PIN_MASK 0x1 +#define SINGLE_CS_ENA 1 +#define TUNING_ACTIVE_SEL_OFFS 6 +#define TUNING_ACTIVE_SEL_MASK 0x1 +#define TUNING_ACTIVE_SEL_MC 0 +#define TUNING_ACTIVE_SEL_TIP 1 + +#define WL_DQS_PATTERN_REG 0x16dc +#define ODPG_DONE_STATUS_REG 0x16fc +#define ODPG_DONE_STATUS_BIT_OFFS 0 +#define ODPG_DONE_STATUS_BIT_MASK 0x1 +#define ODPG_DONE_STATUS_BIT_CLR 0 +#define ODPG_DONE_STATUS_BIT_SET 1 + +#define RESULT_CTRL_BASE 0x1830 +#define BLOCK_STATUS_OFFS 25 +#define BLOCK_STATUS_MASK 0x1 +#define BLOCK_STATUS_LOCK 1 +#define BLOCK_STATUS_NOT_LOCKED 0 + +#define MR0_REG 0x15d0 +#define MR1_REG 0x15d4 +#define MR2_REG 0x15d8 +#define MR3_REG 0x15dc +#define MRS0_CMD 0x3 +#define MRS1_CMD 0x4 +#define MRS2_CMD 0x8 +#define MRS3_CMD 0x9 + + +#define DRAM_PINS_MUX_REG 0x19d4 +#define CTRL_PINS_MUX_OFFS 0 +#define CTRL_PINS_MUX_MASK 0x3 +enum { + DUNIT_DDR3_ON_BOARD, + DUNIT_DDR3_DIMM, + DUNIT_DDR4_ON_BOARD, + DUNIT_DDR4_DIMM +}; + +/* ddr phy registers */ +#define WL_PHY_BASE 0x0 +#define WL_PHY_REG(cs) (WL_PHY_BASE + (cs) * 0x4) +#define WR_LVL_PH_SEL_OFFS 6 +#define WR_LVL_PH_SEL_MASK 0x7 +#define WR_LVL_PH_SEL_PHASE1 1 +#define WR_LVL_REF_DLY_OFFS 0 +#define WR_LVL_REF_DLY_MASK 0x1f +#define CTRL_CENTER_DLY_OFFS 10 +#define CTRL_CENTER_DLY_MASK 0x1f +#define CTRL_CENTER_DLY_INV_OFFS 15 +#define CTRL_CENTER_DLY_INV_MASK 0x1 + +#define CTX_PHY_BASE 0x1 +#define CTX_PHY_REG(cs) (CTX_PHY_BASE + (cs) * 0x4) + +#define RL_PHY_BASE 0x2 +#define RL_PHY_REG(cs) (RL_PHY_BASE + (cs) * 0x4) +#define RL_REF_DLY_OFFS 0 +#define RL_REF_DLY_MASK 0x1f +#define RL_PH_SEL_OFFS 6 +#define RL_PH_SEL_MASK 0x7 + +#define CRX_PHY_BASE 0x3 +#define CRX_PHY_REG(cs) (CRX_PHY_BASE + (cs) * 0x4) + +#define PHY_CTRL_PHY_REG 0x90 +#define ADLL_CFG0_PHY_REG 0x92 +#define ADLL_CFG1_PHY_REG 0x93 +#define ADLL_CFG2_PHY_REG 0x94 +#define CMOS_CONFIG_PHY_REG 0xa2 +#define PAD_ZRI_CAL_PHY_REG 0xa4 +#define PAD_ODT_CAL_PHY_REG 0xa6 +#define PAD_CFG_PHY_REG 0xa8 +#define PAD_PRE_DISABLE_PHY_REG 0xa9 +#define TEST_ADLL_PHY_REG 0xbf + +#define VREF_PHY_BASE 0xd0 +#define VREF_PHY_REG(cs, bit) (VREF_PHY_BASE + (cs) * 12 + bit) +enum { + DQSP_PAD = 4, + DQSN_PAD +}; + +#define VREF_BCAST_PHY_BASE 0xdb +#define VREF_BCAST_PHY_REG(cs) (VREF_BCAST_PHY_BASE + (cs) * 12) + +#define PBS_TX_PHY_BASE 0x10 +#define PBS_TX_PHY_REG(cs, bit) (PBS_TX_PHY_BASE + (cs) * 0x10 + (bit)) + +#define PBS_TX_BCAST_PHY_BASE 0x1f +#define PBS_TX_BCAST_PHY_REG(cs) (PBS_TX_BCAST_PHY_BASE + (cs) * 0x10) + +#define PBS_RX_PHY_BASE 0x50 +#define PBS_RX_PHY_REG(cs, bit) (PBS_RX_PHY_BASE + (cs) * 0x10 + (bit)) + +#define PBS_RX_BCAST_PHY_BASE 0x5f +#define PBS_RX_BCAST_PHY_REG(cs) (PBS_RX_BCAST_PHY_BASE + (cs) * 0x10) + +#define RESULT_PHY_REG 0xc0 +#define RESULT_PHY_RX_OFFS 5 +#define RESULT_PHY_TX_OFFS 0 + + +#endif /* _MV_DDR_REGS_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_spd.c b/drivers/ddr/marvell/a38x/mv_ddr_spd.c new file mode 100644 index 0000000000..e9e7f18098 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_spd.c @@ -0,0 +1,377 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#include "mv_ddr_spd.h" + +#define MV_DDR_SPD_DATA_MTB 125 /* medium timebase, ps */ +#define MV_DDR_SPD_DATA_FTB 1 /* fine timebase, ps */ +#define MV_DDR_SPD_MSB_OFFS 8 /* most significant byte offset, bits */ + +#define MV_DDR_SPD_SUPPORTED_CLS_NUM 30 + +static unsigned int mv_ddr_spd_supported_cls[MV_DDR_SPD_SUPPORTED_CLS_NUM]; + +int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data) +{ + unsigned int byte, bit, start_cl; + + start_cl = (spd_data->all_bytes[23] & 0x8) ? 23 : 7; + + for (byte = 20; byte < 23; byte++) { + for (bit = 0; bit < 8; bit++) { + if (spd_data->all_bytes[byte] & (1 << bit)) + mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit; + else + mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0; + } + } + + for (byte = 23, bit = 0; bit < 6; bit++) { + if (spd_data->all_bytes[byte] & (1 << bit)) + mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit; + else + mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0; + } + + return 0; +} + +unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl) +{ + unsigned int supported_cl; + int i = 0; + + while (i < MV_DDR_SPD_SUPPORTED_CLS_NUM && + mv_ddr_spd_supported_cls[i] < cl) + i++; + + if (i < MV_DDR_SPD_SUPPORTED_CLS_NUM) + supported_cl = mv_ddr_spd_supported_cls[i]; + else + supported_cl = 0; + + return supported_cl; +} + +int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[]) +{ + int calc_val; + + /* t ck avg min, ps */ + calc_val = spd_data->byte_fields.byte_18 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_125 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TCK_AVG_MIN] = calc_val; + + /* t aa min, ps */ + calc_val = spd_data->byte_fields.byte_24 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_123 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TAA_MIN] = calc_val; + + /* t rfc1 min, ps */ + timing_data[MV_DDR_TRFC1_MIN] = (spd_data->byte_fields.byte_30 + + (spd_data->byte_fields.byte_31 << MV_DDR_SPD_MSB_OFFS)) * MV_DDR_SPD_DATA_MTB; + + /* t wr min, ps */ + timing_data[MV_DDR_TWR_MIN] = (spd_data->byte_fields.byte_42 + + (spd_data->byte_fields.byte_41.bit_fields.t_wr_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + /* FIXME: wa: set twr to a default value, if it's unset on spd */ + if (timing_data[MV_DDR_TWR_MIN] == 0) + timing_data[MV_DDR_TWR_MIN] = 15000; + + /* t rcd min, ps */ + calc_val = spd_data->byte_fields.byte_25 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_122 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRCD_MIN] = calc_val; + + /* t rp min, ps */ + calc_val = spd_data->byte_fields.byte_26 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_121 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRP_MIN] = calc_val; + + /* t rc min, ps */ + calc_val = (spd_data->byte_fields.byte_29 + + (spd_data->byte_fields.byte_27.bit_fields.t_rc_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_120 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRC_MIN] = calc_val; + + /* t ras min, ps */ + timing_data[MV_DDR_TRAS_MIN] = (spd_data->byte_fields.byte_28 + + (spd_data->byte_fields.byte_27.bit_fields.t_ras_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + + /* t rrd s min, ps */ + calc_val = spd_data->byte_fields.byte_38 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_119 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRRD_S_MIN] = calc_val; + + /* t rrd l min, ps */ + calc_val = spd_data->byte_fields.byte_39 * MV_DDR_SPD_DATA_MTB + + (signed char)spd_data->byte_fields.byte_118 * MV_DDR_SPD_DATA_FTB; + if (calc_val < 0) + return 1; + timing_data[MV_DDR_TRRD_L_MIN] = calc_val; + + /* t faw min, ps */ + timing_data[MV_DDR_TFAW_MIN] = (spd_data->byte_fields.byte_37 + + (spd_data->byte_fields.byte_36.bit_fields.t_faw_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + + /* t wtr s min, ps */ + timing_data[MV_DDR_TWTR_S_MIN] = (spd_data->byte_fields.byte_44 + + (spd_data->byte_fields.byte_43.bit_fields.t_wtr_s_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + /* FIXME: wa: set twtr_s to a default value, if it's unset on spd */ + if (timing_data[MV_DDR_TWTR_S_MIN] == 0) + timing_data[MV_DDR_TWTR_S_MIN] = 2500; + + /* t wtr l min, ps */ + timing_data[MV_DDR_TWTR_L_MIN] = (spd_data->byte_fields.byte_45 + + (spd_data->byte_fields.byte_43.bit_fields.t_wtr_l_min_msn << MV_DDR_SPD_MSB_OFFS)) * + MV_DDR_SPD_DATA_MTB; + /* FIXME: wa: set twtr_l to a default value, if it's unset on spd */ + if (timing_data[MV_DDR_TWTR_L_MIN] == 0) + timing_data[MV_DDR_TWTR_L_MIN] = 7500; + + return 0; +} + +enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char dev_width = spd_data->byte_fields.byte_12.bit_fields.device_width; + enum mv_ddr_dev_width ret_val; + + switch (dev_width) { + case 0x00: + ret_val = MV_DDR_DEV_WIDTH_4BIT; + break; + case 0x01: + ret_val = MV_DDR_DEV_WIDTH_8BIT; + break; + case 0x02: + ret_val = MV_DDR_DEV_WIDTH_16BIT; + break; + case 0x03: + ret_val = MV_DDR_DEV_WIDTH_32BIT; + break; + default: + ret_val = MV_DDR_DEV_WIDTH_LAST; + } + + return ret_val; +} + +enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char die_cap = spd_data->byte_fields.byte_4.bit_fields.die_capacity; + enum mv_ddr_die_capacity ret_val; + + switch (die_cap) { + case 0x00: + ret_val = MV_DDR_DIE_CAP_256MBIT; + break; + case 0x01: + ret_val = MV_DDR_DIE_CAP_512MBIT; + break; + case 0x02: + ret_val = MV_DDR_DIE_CAP_1GBIT; + break; + case 0x03: + ret_val = MV_DDR_DIE_CAP_2GBIT; + break; + case 0x04: + ret_val = MV_DDR_DIE_CAP_4GBIT; + break; + case 0x05: + ret_val = MV_DDR_DIE_CAP_8GBIT; + break; + case 0x06: + ret_val = MV_DDR_DIE_CAP_16GBIT; + break; + case 0x07: + ret_val = MV_DDR_DIE_CAP_32GBIT; + break; + case 0x08: + ret_val = MV_DDR_DIE_CAP_12GBIT; + break; + case 0x09: + ret_val = MV_DDR_DIE_CAP_24GBIT; + break; + default: + ret_val = MV_DDR_DIE_CAP_LAST; + } + + return ret_val; +} + +unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char mem_mirror = spd_data->byte_fields.byte_131.bit_fields.rank_1_mapping; + + return mem_mirror; +} + +enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char pri_bus_width = spd_data->byte_fields.byte_13.bit_fields.primary_bus_width; + enum mv_ddr_pri_bus_width ret_val; + + switch (pri_bus_width) { + case 0x00: + ret_val = MV_DDR_PRI_BUS_WIDTH_8; + break; + case 0x01: + ret_val = MV_DDR_PRI_BUS_WIDTH_16; + break; + case 0x02: + ret_val = MV_DDR_PRI_BUS_WIDTH_32; + break; + case 0x03: + ret_val = MV_DDR_PRI_BUS_WIDTH_64; + break; + default: + ret_val = MV_DDR_PRI_BUS_WIDTH_LAST; + } + + return ret_val; +} + +enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char bus_width_ext = spd_data->byte_fields.byte_13.bit_fields.bus_width_ext; + enum mv_ddr_bus_width_ext ret_val; + + switch (bus_width_ext) { + case 0x00: + ret_val = MV_DDR_BUS_WIDTH_EXT_0; + break; + case 0x01: + ret_val = MV_DDR_BUS_WIDTH_EXT_8; + break; + default: + ret_val = MV_DDR_BUS_WIDTH_EXT_LAST; + } + + return ret_val; +} + +static enum mv_ddr_pkg_rank mv_ddr_spd_pkg_rank_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char pkg_rank = spd_data->byte_fields.byte_12.bit_fields.dimm_pkg_ranks_num; + enum mv_ddr_pkg_rank ret_val; + + switch (pkg_rank) { + case 0x00: + ret_val = MV_DDR_PKG_RANK_1; + break; + case 0x01: + ret_val = MV_DDR_PKG_RANK_2; + break; + case 0x02: + ret_val = MV_DDR_PKG_RANK_3; + break; + case 0x03: + ret_val = MV_DDR_PKG_RANK_4; + break; + case 0x04: + ret_val = MV_DDR_PKG_RANK_5; + break; + case 0x05: + ret_val = MV_DDR_PKG_RANK_6; + break; + case 0x06: + ret_val = MV_DDR_PKG_RANK_7; + break; + case 0x07: + ret_val = MV_DDR_PKG_RANK_8; + break; + default: + ret_val = MV_DDR_PKG_RANK_LAST; + } + + return ret_val; +} + +static enum mv_ddr_die_count mv_ddr_spd_die_count_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char die_count = spd_data->byte_fields.byte_6.bit_fields.die_count; + enum mv_ddr_die_count ret_val; + + switch (die_count) { + case 0x00: + ret_val = MV_DDR_DIE_CNT_1; + break; + case 0x01: + ret_val = MV_DDR_DIE_CNT_2; + break; + case 0x02: + ret_val = MV_DDR_DIE_CNT_3; + break; + case 0x03: + ret_val = MV_DDR_DIE_CNT_4; + break; + case 0x04: + ret_val = MV_DDR_DIE_CNT_5; + break; + case 0x05: + ret_val = MV_DDR_DIE_CNT_6; + break; + case 0x06: + ret_val = MV_DDR_DIE_CNT_7; + break; + case 0x07: + ret_val = MV_DDR_DIE_CNT_8; + break; + default: + ret_val = MV_DDR_DIE_CNT_LAST; + } + + return ret_val; +} + +unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char cs_bit_mask = 0x0; + enum mv_ddr_pkg_rank pkg_rank = mv_ddr_spd_pkg_rank_get(spd_data); + enum mv_ddr_die_count die_cnt = mv_ddr_spd_die_count_get(spd_data); + + if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_1) + cs_bit_mask = 0x1; + else if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_2) + cs_bit_mask = 0x3; + else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_1) + cs_bit_mask = 0x3; + else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_2) + cs_bit_mask = 0xf; + + return cs_bit_mask; +} + +unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char dev_type = spd_data->byte_fields.byte_2; + + return dev_type; +} + +unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data) +{ + unsigned char module_type = spd_data->byte_fields.byte_3.bit_fields.module_type; + + return module_type; +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_spd.h b/drivers/ddr/marvell/a38x/mv_ddr_spd.h new file mode 100644 index 0000000000..b4bfef3103 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_spd.h @@ -0,0 +1,289 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#ifndef _MV_DDR_SPD_H +#define _MV_DDR_SPD_H + +#include "mv_ddr_topology.h" + +/* + * Based on JEDEC Standard No. 21-C, 4.1.2.L-4: + * Serial Presence Detect (SPD) for DDR4 SDRAM Modules + */ + +/* block 0: base configuration and dram parameters */ +#define MV_DDR_SPD_DATA_BLOCK0_SIZE 128 +/* block 1: module specific parameters sub-block */ +#define MV_DDR_SPD_DATA_BLOCK1M_SIZE 64 +/* block 1: hybrid memory parameters sub-block */ +#define MV_DDR_SPD_DATA_BLOCK1H_SIZE 64 +/* block 2: extended function parameter block */ +#define MV_DDR_SPD_DATA_BLOCK2E_SIZE 64 +/* block 2: manufacturing information */ +#define MV_DDR_SPD_DATA_BLOCK2M_SIZE 64 +/* block 3: end user programmable */ +#define MV_DDR_SPD_DATA_BLOCK3_SIZE 128 + +#define MV_DDR_SPD_DEV_TYPE_DDR4 0xc +#define MV_DDR_SPD_MODULE_TYPE_UDIMM 0x2 +#define MV_DDR_SPD_MODULE_TYPE_SO_DIMM 0x3 +#define MV_DDR_SPD_MODULE_TYPE_MINI_UDIMM 0x6 +#define MV_DDR_SPD_MODULE_TYPE_72BIT_SO_UDIMM 0x9 +#define MV_DDR_SPD_MODULE_TYPE_16BIT_SO_DIMM 0xc +#define MV_DDR_SPD_MODULE_TYPE_32BIT_SO_DIMM 0xd + +/* + * TODO: For now, the struct contains block 0 & block 1 with module specific + * parameters for unbuffered memory module types only. + */ +union mv_ddr_spd_data { + unsigned char all_bytes[MV_DDR_SPD_DATA_BLOCK0_SIZE + + MV_DDR_SPD_DATA_BLOCK1M_SIZE]; + struct { + /* block 0 */ + union { /* num of bytes used/num of bytes in spd device/crc coverage */ + unsigned char all_bits; + struct { + unsigned char spd_bytes_used:4, + spd_bytes_total:3, + reserved:1; + } bit_fields; + } byte_0; + union { /* spd revision */ + unsigned char all_bits; + struct { + unsigned char addtions_level:4, + encoding_level:4; + } bit_fields; + } byte_1; + unsigned char byte_2; /* key_byte/dram device type */ + union { /* key byte/module type */ + unsigned char all_bits; + struct { + unsigned char module_type:4, + hybrid_media:3, + hybrid:1; + } bit_fields; + } byte_3; + union { /* sdram density & banks */ + unsigned char all_bits; + struct { + unsigned char die_capacity:4, + bank_address:2, + bank_group:2; + } bit_fields; + } byte_4; + union { /* sdram addressing */ + unsigned char all_bits; + struct { + unsigned char col_address:3, + row_address:3, + reserved:2; + } bit_fields; + } byte_5; + union { /* sdram package type */ + unsigned char all_bits; + struct { + unsigned char signal_loading:2, + reserved:2, + die_count:3, + sdram_package_type:1; + } bit_fields; + } byte_6; + union { /* sdram optional features */ + unsigned char all_bits; + struct { + unsigned char mac:4, /* max activate count */ + t_maw:2, /* max activate window */ + reserved:2; /* all 0s */ + } bit_fields; + } byte_7; + unsigned char byte_8; /* sdram thermal & refresh options; reserved; 0x00 */ + union { /* other sdram optional features */ + unsigned char all_bits; + struct { + unsigned char reserved:5, /* all 0s */ + soft_ppr:1, + ppr:2; /* post package repair */ + } bit_fields; + } byte_9; + union { /* secondary sdram package type */ + unsigned char all_bits; + struct { + unsigned char signal_loading:2, + density_ratio:2, /* dram density ratio */ + die_count:3, + sdram_package_type:1; + } bit_fields; + } byte_10; + union { /* module nominal voltage, vdd */ + unsigned char all_bits; + struct { + unsigned char operable:1, + endurant:1, + reserved:5; /* all 0s */ + } bit_fields; + } byte_11; + union { /* module organization*/ + unsigned char all_bits; + struct { + unsigned char device_width:3, + dimm_pkg_ranks_num:3, /* package ranks per dimm number */ + rank_mix:1, + reserved:1; /* 0 */ + } bit_fields; + } byte_12; + union { /* module memory bus width */ + unsigned char all_bits; + struct { + unsigned char primary_bus_width:3, /* in bits */ + bus_width_ext:2, /* in bits */ + reserved:3; /* all 0s */ + } bit_fields; + } byte_13; + union { /* module thernal sensor */ + unsigned char all_bits; + struct { + unsigned char reserved:7, + thermal_sensor:1; + } bit_fields; + } byte_14; + union { /* extended module type */ + unsigned char all_bits; + struct { + unsigned char ext_base_module_type:4, + reserved:4; /* all 0s */ + } bit_fields; + } byte_15; + unsigned char byte_16; /* reserved; 0x00 */ + union { /* timebases */ + unsigned char all_bits; + struct { + unsigned char ftb:2, /* fine timebase */ + mtb:2, /* medium timebase */ + reserved:4; /* all 0s */ + } bit_fields; + } byte_17; + unsigned char byte_18; /* sdram min cycle time (t ck avg min), mtb */ + unsigned char byte_19; /* sdram max cycle time (t ck avg max), mtb */ + unsigned char byte_20; /* cas latencies supported, first byte */ + unsigned char byte_21; /* cas latencies supported, second byte */ + unsigned char byte_22; /* cas latencies supported, third byte */ + unsigned char byte_23; /* cas latencies supported, fourth byte */ + unsigned char byte_24; /* min cas latency time (t aa min), mtb */ + unsigned char byte_25; /* min ras to cas delay time (t rcd min), mtb */ + unsigned char byte_26; /* min row precharge delay time (t rp min), mtb */ + union { /* upper nibbles for t ras min & t rc min */ + unsigned char all_bits; + struct { + unsigned char t_ras_min_msn:4, /* t ras min most significant nibble */ + t_rc_min_msn:4; /* t rc min most significant nibble */ + } bit_fields; + } byte_27; + unsigned char byte_28; /* min active to precharge delay time (t ras min), l-s-byte, mtb */ + unsigned char byte_29; /* min active to active/refresh delay time (t rc min), l-s-byte, mtb */ + unsigned char byte_30; /* min refresh recovery delay time (t rfc1 min), l-s-byte, mtb */ + unsigned char byte_31; /* min refresh recovery delay time (t rfc1 min), m-s-byte, mtb */ + unsigned char byte_32; /* min refresh recovery delay time (t rfc2 min), l-s-byte, mtb */ + unsigned char byte_33; /* min refresh recovery delay time (t rfc2 min), m-s-byte, mtb */ + unsigned char byte_34; /* min refresh recovery delay time (t rfc4 min), l-s-byte, mtb */ + unsigned char byte_35; /* min refresh recovery delay time (t rfc4 min), m-s-byte, mtb */ + union { /* upper nibble for t faw */ + unsigned char all_bits; + struct { + unsigned char t_faw_min_msn:4, /* t faw min most significant nibble */ + reserved:4; + } bit_fields; + } byte_36; + unsigned char byte_37; /* min four activate window delay time (t faw min), l-s-byte, mtb */ + /* byte 38: min activate to activate delay time (t rrd_s min), diff bank group, mtb */ + unsigned char byte_38; + /* byte 39: min activate to activate delay time (t rrd_l min), same bank group, mtb */ + unsigned char byte_39; + unsigned char byte_40; /* min cas to cas delay time (t ccd_l min), same bank group, mtb */ + union { /* upper nibble for t wr min */ + unsigned char all_bits; + struct { + unsigned char t_wr_min_msn:4, /* t wr min most significant nibble */ + reserved:4; + } bit_fields; + } byte_41; + unsigned char byte_42; /* min write recovery time (t wr min) */ + union { /* upper nibbles for t wtr min */ + unsigned char all_bits; + struct { + unsigned char t_wtr_s_min_msn:4, /* t wtr s min most significant nibble */ + t_wtr_l_min_msn:4; /* t wtr l min most significant nibble */ + } bit_fields; + } byte_43; + unsigned char byte_44; /* min write to read time (t wtr s min), diff bank group, mtb */ + unsigned char byte_45; /* min write to read time (t wtr l min), same bank group, mtb */ + unsigned char bytes_46_59[14]; /* reserved; all 0s */ + unsigned char bytes_60_77[18]; /* TODO: connector to sdram bit mapping */ + unsigned char bytes_78_116[39]; /* reserved; all 0s */ + /* fine offset for min cas to cas delay time (t ccd_l min), same bank group, ftb */ + unsigned char byte_117; + /* fine offset for min activate to activate delay time (t rrd_l min), same bank group, ftb */ + unsigned char byte_118; + /* fine offset for min activate to activate delay time (t rrd_s min), diff bank group, ftb */ + unsigned char byte_119; + /* fine offset for min active to active/refresh delay time (t rc min), ftb */ + unsigned char byte_120; + unsigned char byte_121; /* fine offset for min row precharge delay time (t rp min), ftb */ + unsigned char byte_122; /* fine offset for min ras to cas delay time (t rcd min), ftb */ + unsigned char byte_123; /* fine offset for min cas latency time (t aa min), ftb */ + unsigned char byte_124; /* fine offset for sdram max cycle time (t ck avg max), ftb */ + unsigned char byte_125; /* fine offset for sdram min cycle time (t ck avg min), ftb */ + unsigned char byte_126; /* crc for base configuration section, l-s-byte */ + unsigned char byte_127; /* crc for base configuration section, m-s-byte */ + /* + * block 1: module specific parameters for unbuffered memory module types only + */ + union { /* (unbuffered) raw card extension, module nominal height */ + unsigned char all_bits; + struct { + unsigned char nom_height_max:5, /* in mm */ + raw_cad_ext:3; + } bit_fields; + } byte_128; + union { /* (unbuffered) module maximum thickness */ + unsigned char all_bits; + struct { + unsigned char front_thickness_max:4, /* in mm */ + back_thickness_max:4; /* in mm */ + } bit_fields; + } byte_129; + union { /* (unbuffered) reference raw card used */ + unsigned char all_bits; + struct { + unsigned char ref_raw_card:5, + ref_raw_card_rev:2, + ref_raw_card_ext:1; + } bit_fields; + } byte_130; + union { /* (unbuffered) address mapping from edge connector to dram */ + unsigned char all_bits; + struct { + unsigned char rank_1_mapping:1, + reserved:7; + } bit_fields; + } byte_131; + unsigned char bytes_132_191[60]; /* reserved; all 0s */ + } byte_fields; +}; + +int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[]); +enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data); +enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data); +unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data); +unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data); +unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data); +unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data); +int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data); +unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl); +enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data); +enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data); + +#endif /* _MV_DDR_SPD_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c b/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c new file mode 100644 index 0000000000..c9c6899e72 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#include "mv_ddr_regs.h" +#include "mv_ddr_sys_env_lib.h" + +static u32 mv_ddr_board_id_get(void) +{ +#if defined(CONFIG_TARGET_DB_88F6820_GP) + return DB_GP_68XX_ID; +#else + /* + * Return 0 here for custom board as this should not be used + * for custom boards. + */ + return 0; +#endif +} + +static u32 mv_ddr_board_id_index_get(u32 board_id) +{ + /* + * Marvell Boards use 0x10 as base for Board ID: + * mask MSB to receive index for board ID + */ + return board_id & (MARVELL_BOARD_ID_MASK - 1); +} + +/* + * read gpio input for suspend-wakeup indication + * return indicating suspend wakeup status: + * 0 - not supported, + * 1 - supported: read magic word detect wakeup, + * 2 - detected wakeup from gpio + */ +enum suspend_wakeup_status mv_ddr_sys_env_suspend_wakeup_check(void) +{ + u32 reg, board_id_index, gpio; + struct board_wakeup_gpio board_gpio[] = MV_BOARD_WAKEUP_GPIO_INFO; + + board_id_index = mv_ddr_board_id_index_get(mv_ddr_board_id_get()); + if (!(sizeof(board_gpio) / sizeof(struct board_wakeup_gpio) > + board_id_index)) { + printf("\n_failed loading Suspend-Wakeup information (invalid board ID)\n"); + return SUSPEND_WAKEUP_DISABLED; + } + + /* + * - Detect if Suspend-Wakeup is supported on current board + * - Fetch the GPIO number for wakeup status input indication + */ + if (board_gpio[board_id_index].gpio_num == -1) { + /* Suspend to RAM is not supported */ + return SUSPEND_WAKEUP_DISABLED; + } else if (board_gpio[board_id_index].gpio_num == -2) { + /* + * Suspend to RAM is supported but GPIO indication is + * not implemented - Skip + */ + return SUSPEND_WAKEUP_ENABLED; + } else { + gpio = board_gpio[board_id_index].gpio_num; + } + + /* Initialize MPP for GPIO (set MPP = 0x0) */ + reg = reg_read(MPP_CONTROL_REG(MPP_REG_NUM(gpio))); + /* reset MPP21 to 0x0, keep rest of MPP settings*/ + reg &= ~MPP_MASK(gpio); + reg_write(MPP_CONTROL_REG(MPP_REG_NUM(gpio)), reg); + + /* Initialize GPIO as input */ + reg = reg_read(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio))); + reg |= GPP_MASK(gpio); + reg_write(GPP_DATA_OUT_EN_REG(GPP_REG_NUM(gpio)), reg); + + /* + * Check GPP for input status from PIC: 0 - regular init, + * 1 - suspend wakeup + */ + reg = reg_read(GPP_DATA_IN_REG(GPP_REG_NUM(gpio))); + + /* if GPIO is ON: wakeup from S2RAM indication detected */ + return (reg & GPP_MASK(gpio)) ? SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED : + SUSPEND_WAKEUP_DISABLED; +} + +/* + * get bit mask of enabled cs + * return bit mask of enabled cs: + * 1 - only cs0 enabled, + * 3 - both cs0 and cs1 enabled + */ +u32 mv_ddr_sys_env_get_cs_ena_from_reg(void) +{ + return reg_read(DDR3_RANK_CTRL_REG) & + ((CS_EXIST_MASK << CS_EXIST_OFFS(0)) | + (CS_EXIST_MASK << CS_EXIST_OFFS(1)) | + (CS_EXIST_MASK << CS_EXIST_OFFS(2)) | + (CS_EXIST_MASK << CS_EXIST_OFFS(3))); +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h b/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h new file mode 100644 index 0000000000..dc6977c334 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_sys_env_lib.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#ifndef _MV_DDR_SYS_ENV_LIB_H +#define _MV_DDR_SYS_ENV_LIB_H + +#include "ddr_ml_wrapper.h" + +/* device revision */ +#define DEV_ID_REG 0x18238 +#define DEV_VERSION_ID_REG 0x1823c +#define REVISON_ID_OFFS 8 +#define REVISON_ID_MASK 0xf00 + +#define MPP_CONTROL_REG(id) (0x18000 + (id * 4)) +#define GPP_DATA_OUT_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x00) +#define GPP_DATA_OUT_EN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x04) +#define GPP_DATA_IN_REG(grp) (MV_GPP_REGS_BASE(grp) + 0x10) +#define MV_GPP_REGS_BASE(unit) (0x18100 + ((unit) * 0x40)) + +#define MPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 8) +#define MPP_MASK(GPIO_NUM) (0xf << 4 * (GPIO_NUM - \ + (MPP_REG_NUM(GPIO_NUM) * 8))); +#define GPP_REG_NUM(GPIO_NUM) (GPIO_NUM / 32) +#define GPP_MASK(GPIO_NUM) (1 << GPIO_NUM % 32) + +/* device ID */ +/* Board ID numbers */ +#define MARVELL_BOARD_ID_MASK 0x10 + +/* Customer boards for A38x */ +#define A38X_CUSTOMER_BOARD_ID_BASE 0x0 +#define A38X_CUSTOMER_BOARD_ID0 (A38X_CUSTOMER_BOARD_ID_BASE + 0) +#define A38X_CUSTOMER_BOARD_ID1 (A38X_CUSTOMER_BOARD_ID_BASE + 1) +#define A38X_MV_MAX_CUSTOMER_BOARD_ID (A38X_CUSTOMER_BOARD_ID_BASE + 2) +#define A38X_MV_CUSTOMER_BOARD_NUM (A38X_MV_MAX_CUSTOMER_BOARD_ID - \ + A38X_CUSTOMER_BOARD_ID_BASE) + +/* Marvell boards for A38x */ +#define A38X_MARVELL_BOARD_ID_BASE 0x10 +#define RD_NAS_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 0) +#define DB_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 1) +#define RD_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 2) +#define DB_AP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 3) +#define DB_GP_68XX_ID (A38X_MARVELL_BOARD_ID_BASE + 4) +#define DB_BP_6821_ID (A38X_MARVELL_BOARD_ID_BASE + 5) +#define DB_AMC_6820_ID (A38X_MARVELL_BOARD_ID_BASE + 6) +#define A38X_MV_MAX_MARVELL_BOARD_ID (A38X_MARVELL_BOARD_ID_BASE + 7) +#define A38X_MV_MARVELL_BOARD_NUM (A38X_MV_MAX_MARVELL_BOARD_ID - \ + A38X_MARVELL_BOARD_ID_BASE) + +/* Marvell boards for A39x */ +#define A39X_MARVELL_BOARD_ID_BASE 0x30 +#define A39X_DB_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 0) +#define A39X_RD_69XX_ID (A39X_MARVELL_BOARD_ID_BASE + 1) +#define A39X_MV_MAX_MARVELL_BOARD_ID (A39X_MARVELL_BOARD_ID_BASE + 2) +#define A39X_MV_MARVELL_BOARD_NUM (A39X_MV_MAX_MARVELL_BOARD_ID - \ + A39X_MARVELL_BOARD_ID_BASE) + +struct board_wakeup_gpio { + u32 board_id; + int gpio_num; +}; + +enum suspend_wakeup_status { + SUSPEND_WAKEUP_DISABLED, + SUSPEND_WAKEUP_ENABLED, + SUSPEND_WAKEUP_ENABLED_GPIO_DETECTED, +}; + +/* + * GPIO status indication for Suspend Wakeup: + * If suspend to RAM is supported and GPIO inidcation is implemented, + * set the gpio number + * If suspend to RAM is supported but GPIO indication is not implemented + * set '-2' + * If suspend to RAM is not supported set '-1' + */ +#ifdef CONFIG_CUSTOMER_BOARD_SUPPORT +#ifdef CONFIG_ARMADA_38X +#define MV_BOARD_WAKEUP_GPIO_INFO { \ + {A38X_CUSTOMER_BOARD_ID0, -1 }, \ + {A38X_CUSTOMER_BOARD_ID0, -1 }, \ +}; +#else +#define MV_BOARD_WAKEUP_GPIO_INFO { \ + {A39X_CUSTOMER_BOARD_ID0, -1 }, \ + {A39X_CUSTOMER_BOARD_ID0, -1 }, \ +}; +#endif /* CONFIG_ARMADA_38X */ + +#else + +#ifdef CONFIG_ARMADA_38X +#define MV_BOARD_WAKEUP_GPIO_INFO { \ + {RD_NAS_68XX_ID, -2 }, \ + {DB_68XX_ID, -1 }, \ + {RD_AP_68XX_ID, -2 }, \ + {DB_AP_68XX_ID, -2 }, \ + {DB_GP_68XX_ID, -2 }, \ + {DB_BP_6821_ID, -2 }, \ + {DB_AMC_6820_ID, -2 }, \ +}; +#else +#define MV_BOARD_WAKEUP_GPIO_INFO { \ + {A39X_RD_69XX_ID, -1 }, \ + {A39X_DB_69XX_ID, -1 }, \ +}; +#endif /* CONFIG_ARMADA_38X */ +#endif /* CONFIG_CUSTOMER_BOARD_SUPPORT */ + +enum suspend_wakeup_status mv_ddr_sys_env_suspend_wakeup_check(void); +u32 mv_ddr_sys_env_get_cs_ena_from_reg(void); + +#endif /* _MV_DDR_SYS_ENV_LIB_H */ diff --git a/drivers/ddr/marvell/a38x/mv_ddr_topology.c b/drivers/ddr/marvell/a38x/mv_ddr_topology.c new file mode 100644 index 0000000000..f56ce06770 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_topology.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#include "mv_ddr_topology.h" +#include "mv_ddr_common.h" +#include "mv_ddr_spd.h" +#include "ddr3_init.h" +#include "ddr_topology_def.h" +#include "ddr3_training_ip_db.h" +#include "ddr3_training_ip.h" + + +unsigned int mv_ddr_cl_calc(unsigned int taa_min, unsigned int tclk) +{ + unsigned int cl = ceil_div(taa_min, tclk); + + return mv_ddr_spd_supported_cl_get(cl); + +} + +unsigned int mv_ddr_cwl_calc(unsigned int tclk) +{ + unsigned int cwl; + + if (tclk >= 1250) + cwl = 9; + else if (tclk >= 1071) + cwl = 10; + else if (tclk >= 938) + cwl = 11; + else if (tclk >= 833) + cwl = 12; + else + cwl = 0; + + return cwl; +} + +struct mv_ddr_topology_map *mv_ddr_topology_map_update(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + unsigned int octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + enum hws_speed_bin speed_bin_index; + enum hws_ddr_freq freq = DDR_FREQ_LAST; + unsigned int tclk; + unsigned char val = 0; + int i; + + + if (tm->interface_params[0].memory_freq == DDR_FREQ_SAR) + tm->interface_params[0].memory_freq = mv_ddr_init_freq_get(); + + if (tm->cfg_src == MV_DDR_CFG_SPD) { + /* check dram device type */ + val = mv_ddr_spd_dev_type_get(&tm->spd_data); + if (val != MV_DDR_SPD_DEV_TYPE_DDR4) { + printf("mv_ddr: unsupported dram device type found\n"); + return NULL; + } + + /* update topology map with timing data */ + if (mv_ddr_spd_timing_calc(&tm->spd_data, tm->timing_data) > 0) { + printf("mv_ddr: negative timing data found\n"); + return NULL; + } + + /* update device width in topology map */ + tm->interface_params[0].bus_width = mv_ddr_spd_dev_width_get(&tm->spd_data); + + /* update die capacity in topology map */ + tm->interface_params[0].memory_size = mv_ddr_spd_die_capacity_get(&tm->spd_data); + + /* update bus bit mask in topology map */ + tm->bus_act_mask = mv_ddr_bus_bit_mask_get(); + + /* update cs bit mask in topology map */ + val = mv_ddr_spd_cs_bit_mask_get(&tm->spd_data); + for (i = 0; i < octets_per_if_num; i++) { + tm->interface_params[0].as_bus_params[i].cs_bitmask = val; + } + + /* check dram module type */ + val = mv_ddr_spd_module_type_get(&tm->spd_data); + switch (val) { + case MV_DDR_SPD_MODULE_TYPE_UDIMM: + case MV_DDR_SPD_MODULE_TYPE_SO_DIMM: + case MV_DDR_SPD_MODULE_TYPE_MINI_UDIMM: + case MV_DDR_SPD_MODULE_TYPE_72BIT_SO_UDIMM: + case MV_DDR_SPD_MODULE_TYPE_16BIT_SO_DIMM: + case MV_DDR_SPD_MODULE_TYPE_32BIT_SO_DIMM: + break; + default: + printf("mv_ddr: unsupported dram module type found\n"); + return NULL; + } + + /* update mirror bit mask in topology map */ + val = mv_ddr_spd_mem_mirror_get(&tm->spd_data); + for (i = 0; i < octets_per_if_num; i++) { + tm->interface_params[0].as_bus_params[i].mirror_enable_bitmask = val << 1; + } + + tclk = 1000000 / freq_val[tm->interface_params[0].memory_freq]; + /* update cas write latency (cwl) */ + val = mv_ddr_cwl_calc(tclk); + if (val == 0) { + printf("mv_ddr: unsupported cas write latency value found\n"); + return NULL; + } + tm->interface_params[0].cas_wl = val; + + /* update cas latency (cl) */ + mv_ddr_spd_supported_cls_calc(&tm->spd_data); + val = mv_ddr_cl_calc(tm->timing_data[MV_DDR_TAA_MIN], tclk); + if (val == 0) { + printf("mv_ddr: unsupported cas latency value found\n"); + return NULL; + } + tm->interface_params[0].cas_l = val; + } else if (tm->cfg_src == MV_DDR_CFG_DEFAULT) { + /* set cas and cas-write latencies per speed bin, if they unset */ + speed_bin_index = tm->interface_params[0].speed_bin_index; + freq = tm->interface_params[0].memory_freq; + + if (tm->interface_params[0].cas_l == 0) + tm->interface_params[0].cas_l = + cas_latency_table[speed_bin_index].cl_val[freq]; + + if (tm->interface_params[0].cas_wl == 0) + tm->interface_params[0].cas_wl = + cas_write_latency_table[speed_bin_index].cl_val[freq]; + } + + + return tm; +} + +unsigned short mv_ddr_bus_bit_mask_get(void) +{ + unsigned short pri_and_ext_bus_width = 0x0; + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + unsigned int octets_per_if_num = ddr3_tip_dev_attr_get(0, MV_ATTR_OCTET_PER_INTERFACE); + + if (tm->cfg_src == MV_DDR_CFG_SPD) { + enum mv_ddr_pri_bus_width pri_bus_width = mv_ddr_spd_pri_bus_width_get(&tm->spd_data); + enum mv_ddr_bus_width_ext bus_width_ext = mv_ddr_spd_bus_width_ext_get(&tm->spd_data); + + switch (pri_bus_width) { + case MV_DDR_PRI_BUS_WIDTH_16: + pri_and_ext_bus_width = BUS_MASK_16BIT; + break; + case MV_DDR_PRI_BUS_WIDTH_32: + pri_and_ext_bus_width = BUS_MASK_32BIT; + break; + case MV_DDR_PRI_BUS_WIDTH_64: + pri_and_ext_bus_width = MV_DDR_64BIT_BUS_MASK; + break; + default: + pri_and_ext_bus_width = 0x0; + } + + if (bus_width_ext == MV_DDR_BUS_WIDTH_EXT_8) + pri_and_ext_bus_width |= 1 << (octets_per_if_num - 1); + } + + return pri_and_ext_bus_width; +} + +unsigned int mv_ddr_if_bus_width_get(void) +{ + struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); + unsigned int bus_width; + + switch (tm->bus_act_mask) { + case BUS_MASK_16BIT: + case BUS_MASK_16BIT_ECC: + case BUS_MASK_16BIT_ECC_PUP3: + bus_width = 16; + break; + case BUS_MASK_32BIT: + case BUS_MASK_32BIT_ECC: + case MV_DDR_32BIT_ECC_PUP8_BUS_MASK: + bus_width = 32; + break; + case MV_DDR_64BIT_BUS_MASK: + case MV_DDR_64BIT_ECC_PUP8_BUS_MASK: + bus_width = 64; + break; + default: + printf("mv_ddr: unsupported bus active mask parameter found\n"); + bus_width = 0; + } + + return bus_width; +} diff --git a/drivers/ddr/marvell/a38x/mv_ddr_topology.h b/drivers/ddr/marvell/a38x/mv_ddr_topology.h new file mode 100644 index 0000000000..eb017a1497 --- /dev/null +++ b/drivers/ddr/marvell/a38x/mv_ddr_topology.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#ifndef _MV_DDR_TOPOLOGY_H +#define _MV_DDR_TOPOLOGY_H + +/* ddr bus masks */ +#define BUS_MASK_32BIT 0xf +#define BUS_MASK_32BIT_ECC 0x1f +#define BUS_MASK_16BIT 0x3 +#define BUS_MASK_16BIT_ECC 0x13 +#define BUS_MASK_16BIT_ECC_PUP3 0xb +#define MV_DDR_64BIT_BUS_MASK 0xff +#define MV_DDR_64BIT_ECC_PUP8_BUS_MASK 0x1ff +#define MV_DDR_32BIT_ECC_PUP8_BUS_MASK 0x10f + +/* source of ddr configuration data */ +enum mv_ddr_cfg_src { + MV_DDR_CFG_DEFAULT, /* based on data in mv_ddr_topology_map structure */ + MV_DDR_CFG_SPD, /* based on data in spd */ + MV_DDR_CFG_USER, /* based on data from user */ + MV_DDR_CFG_STATIC, /* based on data from user in register-value format */ + MV_DDR_CFG_LAST +}; + +enum mv_ddr_num_of_sub_phys_per_ddr_unit { + SINGLE_SUB_PHY = 1, + TWO_SUB_PHYS = 2 +}; + +enum mv_ddr_temperature { + MV_DDR_TEMP_LOW, + MV_DDR_TEMP_NORMAL, + MV_DDR_TEMP_HIGH +}; + +enum mv_ddr_timing_data { + MV_DDR_TCK_AVG_MIN, /* sdram min cycle time (t ck avg min) */ + MV_DDR_TAA_MIN, /* min cas latency time (t aa min) */ + MV_DDR_TRFC1_MIN, /* min refresh recovery delay time (t rfc1 min) */ + MV_DDR_TWR_MIN, /* min write recovery time (t wr min) */ + MV_DDR_TRCD_MIN, /* min ras to cas delay time (t rcd min) */ + MV_DDR_TRP_MIN, /* min row precharge delay time (t rp min) */ + MV_DDR_TRC_MIN, /* min active to active/refresh delay time (t rc min) */ + MV_DDR_TRAS_MIN, /* min active to precharge delay time (t ras min) */ + MV_DDR_TRRD_S_MIN, /* min activate to activate delay time (t rrd_s min), diff bank group */ + MV_DDR_TRRD_L_MIN, /* min activate to activate delay time (t rrd_l min), same bank group */ + MV_DDR_TFAW_MIN, /* min four activate window delay time (t faw min) */ + MV_DDR_TWTR_S_MIN, /* min write to read time (t wtr s min), diff bank group */ + MV_DDR_TWTR_L_MIN, /* min write to read time (t wtr l min), same bank group */ + MV_DDR_TDATA_LAST +}; + +enum mv_ddr_dev_width { /* sdram device width */ + MV_DDR_DEV_WIDTH_4BIT, + MV_DDR_DEV_WIDTH_8BIT, + MV_DDR_DEV_WIDTH_16BIT, + MV_DDR_DEV_WIDTH_32BIT, + MV_DDR_DEV_WIDTH_LAST +}; + +enum mv_ddr_die_capacity { /* total sdram capacity per die, megabits */ + MV_DDR_DIE_CAP_256MBIT, + MV_DDR_DIE_CAP_512MBIT = 0, + MV_DDR_DIE_CAP_1GBIT, + MV_DDR_DIE_CAP_2GBIT, + MV_DDR_DIE_CAP_4GBIT, + MV_DDR_DIE_CAP_8GBIT, + MV_DDR_DIE_CAP_16GBIT, + MV_DDR_DIE_CAP_32GBIT, + MV_DDR_DIE_CAP_12GBIT, + MV_DDR_DIE_CAP_24GBIT, + MV_DDR_DIE_CAP_LAST +}; + +enum mv_ddr_pkg_rank { /* number of package ranks per dimm */ + MV_DDR_PKG_RANK_1, + MV_DDR_PKG_RANK_2, + MV_DDR_PKG_RANK_3, + MV_DDR_PKG_RANK_4, + MV_DDR_PKG_RANK_5, + MV_DDR_PKG_RANK_6, + MV_DDR_PKG_RANK_7, + MV_DDR_PKG_RANK_8, + MV_DDR_PKG_RANK_LAST +}; + +enum mv_ddr_pri_bus_width { /* number of primary bus width bits */ + MV_DDR_PRI_BUS_WIDTH_8, + MV_DDR_PRI_BUS_WIDTH_16, + MV_DDR_PRI_BUS_WIDTH_32, + MV_DDR_PRI_BUS_WIDTH_64, + MV_DDR_PRI_BUS_WIDTH_LAST +}; + +enum mv_ddr_bus_width_ext { /* number of extension bus width bits */ + MV_DDR_BUS_WIDTH_EXT_0, + MV_DDR_BUS_WIDTH_EXT_8, + MV_DDR_BUS_WIDTH_EXT_LAST +}; + +enum mv_ddr_die_count { + MV_DDR_DIE_CNT_1, + MV_DDR_DIE_CNT_2, + MV_DDR_DIE_CNT_3, + MV_DDR_DIE_CNT_4, + MV_DDR_DIE_CNT_5, + MV_DDR_DIE_CNT_6, + MV_DDR_DIE_CNT_7, + MV_DDR_DIE_CNT_8, + MV_DDR_DIE_CNT_LAST +}; + +unsigned int mv_ddr_cl_calc(unsigned int taa_min, unsigned int tclk); +unsigned int mv_ddr_cwl_calc(unsigned int tclk); +struct mv_ddr_topology_map *mv_ddr_topology_map_update(void); +struct dram_config *mv_ddr_dram_config_update(void); +unsigned short mv_ddr_bus_bit_mask_get(void); +unsigned int mv_ddr_if_bus_width_get(void); + +#endif /* _MV_DDR_TOPOLOGY_H */ diff --git a/drivers/ddr/marvell/a38x/seq_exec.h b/drivers/ddr/marvell/a38x/seq_exec.h new file mode 100644 index 0000000000..fe0cb8f75d --- /dev/null +++ b/drivers/ddr/marvell/a38x/seq_exec.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Marvell International Ltd. and its affiliates + */ + +#ifndef _SEQ_EXEC_H +#define _SEQ_EXEC_H + +#define NA 0xff +#define DEFAULT_PARAM 0 +#define MV_BOARD_TCLK_ERROR 0xffffffff + +#define NO_DATA 0xffffffff +#define MAX_DATA_ARRAY 5 +#define FIRST_CELL 0 + +/* Operation types */ +enum mv_op { + WRITE_OP, + DELAY_OP, + POLL_OP, +}; + +/* Operation parameters */ +struct op_params { + u32 unit_base_reg; + u32 unit_offset; + u32 mask; + u32 data[MAX_DATA_ARRAY]; /* data array */ + u8 wait_time; /* msec */ + u16 num_of_loops; /* for polling only */ +}; + +/* + * Sequence parameters. Each sequence contains: + * 1. Sequence id. + * 2. Sequence size (total amount of operations during the sequence) + * 3. a series of operations. operations can be write, poll or delay + * 4. index in the data array (the entry where the relevant data sits) + */ +struct cfg_seq { + struct op_params *op_params_ptr; + u8 cfg_seq_size; + u8 data_arr_idx; +}; + +extern struct cfg_seq serdes_seq_db[]; + +/* + * A generic function type for executing an operation (write, poll or delay) + */ +typedef int (*op_execute_func_ptr)(u32 serdes_num, struct op_params *params, + u32 data_arr_idx); + +/* Specific functions for executing each operation */ +int write_op_execute(u32 serdes_num, struct op_params *params, + u32 data_arr_idx); +int delay_op_execute(u32 serdes_num, struct op_params *params, + u32 data_arr_idx); +int poll_op_execute(u32 serdes_num, struct op_params *params, u32 data_arr_idx); +enum mv_op get_cfg_seq_op(struct op_params *params); +int mv_seq_exec(u32 serdes_num, u32 seq_id); + +#endif /*_SEQ_EXEC_H*/ diff --git a/drivers/ddr/marvell/a38x/silicon_if.h b/drivers/ddr/marvell/a38x/silicon_if.h deleted file mode 100644 index 4efd9b8b01..0000000000 --- a/drivers/ddr/marvell/a38x/silicon_if.h +++ /dev/null @@ -1,16 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Copyright (C) Marvell International Ltd. and its affiliates - */ - -#ifndef __silicon_if_H -#define __silicon_if_H - -/* max number of devices supported by driver */ -#ifdef CO_CPU_RUN -#define HWS_MAX_DEVICE_NUM (1) -#else -#define HWS_MAX_DEVICE_NUM (16) -#endif - -#endif /* __silicon_if_H */ diff --git a/drivers/ddr/marvell/a38x/xor.c b/drivers/ddr/marvell/a38x/xor.c index e53834f54a..024cecd777 100644 --- a/drivers/ddr/marvell/a38x/xor.c +++ b/drivers/ddr/marvell/a38x/xor.c @@ -3,13 +3,6 @@ * Copyright (C) Marvell International Ltd. and its affiliates */ -#include -#include -#include -#include -#include -#include - #include "ddr3_init.h" #include "xor_regs.h" @@ -21,39 +14,48 @@ #endif static u32 ui_xor_regs_ctrl_backup; -static u32 ui_xor_regs_base_backup[MAX_CS]; -static u32 ui_xor_regs_mask_backup[MAX_CS]; +static u32 ui_xor_regs_base_backup[MAX_CS_NUM + 1]; +static u32 ui_xor_regs_mask_backup[MAX_CS_NUM + 1]; -void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, u32 cs_size, u32 base_delta) +void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, uint64_t cs_size, u32 base_delta) { - u32 reg, ui, base, cs_count; + u32 reg, ui, cs_count; + uint64_t base, size_mask; ui_xor_regs_ctrl_backup = reg_read(XOR_WINDOW_CTRL_REG(0, 0)); - for (ui = 0; ui < MAX_CS; ui++) + for (ui = 0; ui < MAX_CS_NUM + 1; ui++) ui_xor_regs_base_backup[ui] = reg_read(XOR_BASE_ADDR_REG(0, ui)); - for (ui = 0; ui < MAX_CS; ui++) + for (ui = 0; ui < MAX_CS_NUM + 1; ui++) ui_xor_regs_mask_backup[ui] = reg_read(XOR_SIZE_MASK_REG(0, ui)); reg = 0; - for (ui = 0; ui < (num_of_cs); ui++) { - /* Enable Window x for each CS */ - reg |= (0x1 << (ui)); - /* Enable Window x for each CS */ - reg |= (0x3 << ((ui * 2) + 16)); + for (ui = 0, cs_count = 0; + (cs_count < num_of_cs) && (ui < 8); + ui++, cs_count++) { + if (cs_ena & (1 << ui)) { + /* Enable Window x for each CS */ + reg |= (0x1 << (ui)); + /* Enable Window x for each CS */ + reg |= (0x3 << ((ui * 2) + 16)); + } } reg_write(XOR_WINDOW_CTRL_REG(0, 0), reg); cs_count = 0; - for (ui = 0; ui < num_of_cs; ui++) { + for (ui = 0, cs_count = 0; + (cs_count < num_of_cs) && (ui < 8); + ui++, cs_count++) { if (cs_ena & (1 << ui)) { /* * window x - Base - 0x00000000, * Attribute 0x0e - DRAM */ base = cs_size * ui + base_delta; + /* fixed size 2GB for each CS */ + size_mask = 0x7FFF0000; switch (ui) { case 0: base |= 0xe00; @@ -67,13 +69,19 @@ void mv_sys_xor_init(u32 num_of_cs, u32 cs_ena, u32 cs_size, u32 base_delta) case 3: base |= 0x700; break; + case 4: /* SRAM */ + base = 0x40000000; + /* configure as shared transaction */ + base |= 0x1F00; + size_mask = 0xF0000; + break; } - reg_write(XOR_BASE_ADDR_REG(0, cs_count), base); - + reg_write(XOR_BASE_ADDR_REG(0, ui), (u32)base); + size_mask = (cs_size / _64K) - 1; + size_mask = (size_mask << XESMRX_SIZE_MASK_OFFS) & XESMRX_SIZE_MASK_MASK; /* window x - Size */ - reg_write(XOR_SIZE_MASK_REG(0, cs_count), 0x7fff0000); - cs_count++; + reg_write(XOR_SIZE_MASK_REG(0, ui), (u32)size_mask); } } @@ -87,10 +95,10 @@ void mv_sys_xor_finish(void) u32 ui; reg_write(XOR_WINDOW_CTRL_REG(0, 0), ui_xor_regs_ctrl_backup); - for (ui = 0; ui < MAX_CS; ui++) + for (ui = 0; ui < MAX_CS_NUM + 1; ui++) reg_write(XOR_BASE_ADDR_REG(0, ui), ui_xor_regs_base_backup[ui]); - for (ui = 0; ui < MAX_CS; ui++) + for (ui = 0; ui < MAX_CS_NUM + 1; ui++) reg_write(XOR_SIZE_MASK_REG(0, ui), ui_xor_regs_mask_backup[ui]); @@ -153,11 +161,14 @@ int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl) return MV_OK; } -int mv_xor_mem_init(u32 chan, u32 start_ptr, u32 block_size, +int mv_xor_mem_init(u32 chan, u32 start_ptr, unsigned long long block_size, u32 init_val_high, u32 init_val_low) { u32 temp; + if (block_size == _4G) + block_size -= 1; + /* Parameter checking */ if (chan >= MV_XOR_MAX_CHAN) return MV_BAD_PARAM; @@ -328,28 +339,123 @@ void ddr3_new_tip_ecc_scrub(void) { u32 cs_c, max_cs; u32 cs_ena = 0; + u32 dev_num = 0; + uint64_t total_mem_size, cs_mem_size = 0; - printf("DDR3 Training Sequence - Start scrubbing\n"); - - max_cs = hws_ddr3_tip_max_cs_get(); + printf("DDR Training Sequence - Start scrubbing\n"); + max_cs = ddr3_tip_max_cs_get(dev_num); for (cs_c = 0; cs_c < max_cs; cs_c++) cs_ena |= 1 << cs_c; - mv_sys_xor_init(max_cs, cs_ena, 0x80000000, 0); - - mv_xor_mem_init(0, 0x00000000, 0x80000000, 0xdeadbeef, 0xdeadbeef); - /* wait for previous transfer completion */ - while (mv_xor_state_get(0) != MV_IDLE) - ; - - mv_xor_mem_init(0, 0x80000000, 0x40000000, 0xdeadbeef, 0xdeadbeef); - + mv_sys_xor_init(max_cs, cs_ena, cs_mem_size, 0); + total_mem_size = max_cs * cs_mem_size; + mv_xor_mem_init(0, 0, total_mem_size, 0xdeadbeef, 0xdeadbeef); /* wait for previous transfer completion */ while (mv_xor_state_get(0) != MV_IDLE) ; - /* Return XOR State */ mv_sys_xor_finish(); printf("DDR3 Training Sequence - End scrubbing\n"); } + +/* +* mv_xor_transfer - Transfer data from source to destination in one of +* three modes: XOR, CRC32 or DMA +* +* DESCRIPTION: +* This function initiates XOR channel, according to function parameters, +* in order to perform XOR, CRC32 or DMA transaction. +* To gain maximum performance the user is asked to keep the following +* restrictions: +* 1) Selected engine is available (not busy). +* 2) This module does not take into consideration CPU MMU issues. +* In order for the XOR engine to access the appropriate source +* and destination, address parameters must be given in system +* physical mode. +* 3) This API does not take care of cache coherency issues. The source, +* destination and, in case of chain, the descriptor list are assumed +* to be cache coherent. +* 4) Parameters validity. +* +* INPUT: +* chan - XOR channel number. +* type - One of three: XOR, CRC32 and DMA operations. +* xor_chain_ptr - address of chain pointer +* +* OUTPUT: +* None. +* +* RETURN: +* MV_BAD_PARAM if parameters to function invalid, MV_OK otherwise. +* +*******************************************************************************/ +int mv_xor_transfer(u32 chan, enum xor_type type, u32 xor_chain_ptr) +{ + u32 temp; + + /* Parameter checking */ + if (chan >= MV_XOR_MAX_CHAN) { + DB(printf("%s: ERR. Invalid chan num %d\n", __func__, chan)); + return MV_BAD_PARAM; + } + if (mv_xor_state_get(chan) == MV_ACTIVE) { + DB(printf("%s: ERR. Channel is already active\n", __func__)); + return MV_BUSY; + } + if (xor_chain_ptr == 0x0) { + DB(printf("%s: ERR. xor_chain_ptr is NULL pointer\n", __func__)); + return MV_BAD_PARAM; + } + + /* read configuration register and mask the operation mode field */ + temp = reg_read(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan))); + temp &= ~XEXCR_OPERATION_MODE_MASK; + + switch (type) { + case MV_XOR: + if ((xor_chain_ptr & XEXDPR_DST_PTR_XOR_MASK) != 0) { + DB(printf("%s: ERR. Invalid chain pointer (bits [5:0] must be cleared)\n", + __func__)); + return MV_BAD_PARAM; + } + /* set the operation mode to XOR */ + temp |= XEXCR_OPERATION_MODE_XOR; + break; + case MV_DMA: + if ((xor_chain_ptr & XEXDPR_DST_PTR_DMA_MASK) != 0) { + DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n", + __func__)); + return MV_BAD_PARAM; + } + /* set the operation mode to DMA */ + temp |= XEXCR_OPERATION_MODE_DMA; + break; + case MV_CRC32: + if ((xor_chain_ptr & XEXDPR_DST_PTR_CRC_MASK) != 0) { + DB(printf("%s: ERR. Invalid chain pointer (bits [4:0] must be cleared)\n", + __func__)); + return MV_BAD_PARAM; + } + /* set the operation mode to CRC32 */ + temp |= XEXCR_OPERATION_MODE_CRC; + break; + default: + return MV_BAD_PARAM; + } + + /* write the operation mode to the register */ + reg_write(XOR_CONFIG_REG(XOR_UNIT(chan), XOR_CHAN(chan)), temp); + /* + * update the NextDescPtr field in the XOR Engine [0..1] Next Descriptor + * Pointer Register (XExNDPR) + */ + reg_write(XOR_NEXT_DESC_PTR_REG(XOR_UNIT(chan), XOR_CHAN(chan)), + xor_chain_ptr); + + /* start transfer */ + reg_bit_set(XOR_ACTIVATION_REG(XOR_UNIT(chan), XOR_CHAN(chan)), + XEXACTR_XESTART_MASK); + + return MV_OK; +} diff --git a/drivers/ddr/marvell/a38x/xor.h b/drivers/ddr/marvell/a38x/xor.h index 9ca9735040..1e02650369 100644 --- a/drivers/ddr/marvell/a38x/xor.h +++ b/drivers/ddr/marvell/a38x/xor.h @@ -8,8 +8,6 @@ #define SRAM_BASE 0x40000000 -#include "ddr3_hws_hw_training_def.h" - #define MV_XOR_MAX_UNIT 2 /* XOR unit == XOR engine */ #define MV_XOR_MAX_CHAN 4 /* total channels for all units */ #define MV_XOR_MAX_CHAN_PER_UNIT 2 /* channels for units */ @@ -87,5 +85,6 @@ int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl); int mv_xor_command_set(u32 chan, enum mv_command command); int mv_xor_override_set(u32 chan, enum xor_override_target target, u32 win_num, int enable); +int mv_xor_transfer(u32 chan, enum xor_type type, u32 xor_chain_ptr); #endif -- cgit From e6f61622d32327907f824154c7f88ddce3c700cc Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 May 2018 13:28:30 +1200 Subject: ARM: mvebu: a38x: restore support for setting timing This restores support for configuring the timing mode based on the ddr_topology. This was originally implemented in commit 90bcc3d38d2b ("driver/ddr: Add support for setting timing in hws_topology_map") but was removed as part of the upstream sync. Signed-off-by: Chris Packham Signed-off-by: Stefan Roese --- board/CZ.NIC/turris_omnia/turris_omnia.c | 6 ++++-- board/Marvell/db-88f6820-amc/db-88f6820-amc.c | 3 ++- board/Marvell/db-88f6820-gp/db-88f6820-gp.c | 3 ++- board/gdsys/a38x/controlcenterdc.c | 3 ++- board/solidrun/clearfog/clearfog.c | 3 ++- drivers/ddr/marvell/a38x/ddr3_training.c | 8 ++++++++ drivers/ddr/marvell/a38x/ddr_topology_def.h | 3 +++ drivers/ddr/marvell/a38x/mv_ddr_plat.c | 5 ----- drivers/ddr/marvell/a38x/mv_ddr_topology.h | 6 ++++++ 9 files changed, 29 insertions(+), 11 deletions(-) diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 29f81cdccf..da663cf1bb 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -214,7 +214,8 @@ static struct mv_ddr_topology_map board_topology_map_1g = { MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - MV_DDR_TEMP_NORMAL} }, /* temperature */ + MV_DDR_TEMP_NORMAL, /* temperature */ + MV_DDR_TIM_2T} }, /* timing */ BUS_MASK_32BIT, /* Busses mask */ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ { {0} }, /* raw spd data */ @@ -235,7 +236,8 @@ static struct mv_ddr_topology_map board_topology_map_2g = { MV_DDR_DIE_CAP_8GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - MV_DDR_TEMP_NORMAL} }, /* temperature */ + MV_DDR_TEMP_NORMAL, /* temperature */ + MV_DDR_TIM_2T} }, /* timing */ BUS_MASK_32BIT, /* Busses mask */ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ { {0} }, /* raw spd data */ diff --git a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c index e39dc75f92..92d7ae77f0 100644 --- a/board/Marvell/db-88f6820-amc/db-88f6820-amc.c +++ b/board/Marvell/db-88f6820-amc/db-88f6820-amc.c @@ -69,7 +69,8 @@ static struct mv_ddr_topology_map board_topology_map = { MV_DDR_DIE_CAP_2GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - MV_DDR_TEMP_LOW} }, /* temperature */ + MV_DDR_TEMP_LOW, /* temperature */ + MV_DDR_TIM_DEFAULT} }, /* timing */ BUS_MASK_32BIT, /* Busses mask */ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ { {0} }, /* raw spd data */ diff --git a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c index ee12ca68ec..a8cfe8af0a 100644 --- a/board/Marvell/db-88f6820-gp/db-88f6820-gp.c +++ b/board/Marvell/db-88f6820-gp/db-88f6820-gp.c @@ -90,7 +90,8 @@ static struct mv_ddr_topology_map board_topology_map = { MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - MV_DDR_TEMP_LOW} }, /* temperature */ + MV_DDR_TEMP_LOW, /* temperature */ + MV_DDR_TIM_DEFAULT} }, /* timing */ BUS_MASK_32BIT, /* Busses mask */ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ { {0} }, /* raw spd data */ diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c index f750e47b72..320bc100c9 100644 --- a/board/gdsys/a38x/controlcenterdc.c +++ b/board/gdsys/a38x/controlcenterdc.c @@ -53,7 +53,8 @@ static struct mv_ddr_topology_map ddr_topology_map = { MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_533, /* frequency */ 0, 0, /* cas_wl cas_l */ - MV_DDR_TEMP_LOW} }, /* temperature */ + MV_DDR_TEMP_LOW, /* temperature */ + MV_DDR_TIM_DEFAULT} }, /* timing */ BUS_MASK_32BIT, /* Busses mask */ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ { {0} }, /* raw spd data */ diff --git a/board/solidrun/clearfog/clearfog.c b/board/solidrun/clearfog/clearfog.c index cc11feb85e..ede303d4eb 100644 --- a/board/solidrun/clearfog/clearfog.c +++ b/board/solidrun/clearfog/clearfog.c @@ -83,7 +83,8 @@ static struct mv_ddr_topology_map board_topology_map = { MV_DDR_DIE_CAP_4GBIT, /* mem_size */ DDR_FREQ_800, /* frequency */ 0, 0, /* cas_wl cas_l */ - MV_DDR_TEMP_LOW} }, /* temperature */ + MV_DDR_TEMP_LOW, /* temperature */ + MV_DDR_TIM_DEFAULT} }, /* timing */ BUS_MASK_32BIT, /* Busses mask */ MV_DDR_CFG_DEFAULT, /* ddr configuration data source */ { {0} }, /* raw spd data */ diff --git a/drivers/ddr/marvell/a38x/ddr3_training.c b/drivers/ddr/marvell/a38x/ddr3_training.c index 1f26d506da..799c5ba089 100644 --- a/drivers/ddr/marvell/a38x/ddr3_training.c +++ b/drivers/ddr/marvell/a38x/ddr3_training.c @@ -365,6 +365,7 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); enum hws_ddr_freq freq = tm->interface_params[0].memory_freq; + enum mv_ddr_timing timing; DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("Init_controller, do_mrs_phy=%d, is_ctrl64_bit=%d\n", @@ -603,8 +604,12 @@ int hws_ddr3_tip_init_controller(u32 dev_num, struct init_cntr_param *init_cntr_ DUNIT_CTRL_HIGH_REG, (init_cntr_prm->msys_init << 7), (1 << 7))); + timing = tm->interface_params[if_id].timing; + if (mode_2t != 0xff) { t2t = mode_2t; + } else if (timing != MV_DDR_TIM_DEFAULT) { + t2t = (timing == MV_DDR_TIM_2T) ? 1 : 0; } else { /* calculate number of CS (per interface) */ CHECK_STATUS(calc_cs_num @@ -1268,6 +1273,7 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE); struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get(); unsigned int tclk; + enum mv_ddr_timing timing = tm->interface_params[if_id].timing; DEBUG_TRAINING_IP(DEBUG_LEVEL_TRACE, ("dev %d access %d IF %d freq %d\n", dev_num, @@ -1410,6 +1416,8 @@ int ddr3_tip_freq_set(u32 dev_num, enum hws_access_type access_type, /* Calculate 2T mode */ if (mode_2t != 0xff) { t2t = mode_2t; + } else if (timing != MV_DDR_TIM_DEFAULT) { + t2t = (timing == MV_DDR_TIM_2T) ? 1 : 0; } else { /* Calculate number of CS per interface */ CHECK_STATUS(calc_cs_num(dev_num, if_id, &cs_num)); diff --git a/drivers/ddr/marvell/a38x/ddr_topology_def.h b/drivers/ddr/marvell/a38x/ddr_topology_def.h index 2c589eb3a6..812224909a 100644 --- a/drivers/ddr/marvell/a38x/ddr_topology_def.h +++ b/drivers/ddr/marvell/a38x/ddr_topology_def.h @@ -64,6 +64,9 @@ struct if_params { /* operation temperature */ enum mv_ddr_temperature interface_temp; + + /* 2T vs 1T mode (by default computed from number of CSs) */ + enum mv_ddr_timing timing; }; struct mv_ddr_topology_map { diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.c b/drivers/ddr/marvell/a38x/mv_ddr_plat.c index ce672e9dd4..2070bb38b0 100644 --- a/drivers/ddr/marvell/a38x/mv_ddr_plat.c +++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.c @@ -674,11 +674,6 @@ static int mv_ddr_sw_db_init(u32 dev_num, u32 board_id) dfs_low_freq = DFS_LOW_FREQ_VALUE; calibration_update_control = 1; -#ifdef CONFIG_ARMADA_38X - /* For a38x only, change to 2T mode to resolve low freq instability */ - mode_2t = 1; -#endif - ddr3_tip_a38x_get_medium_freq(dev_num, &medium_freq); return MV_OK; diff --git a/drivers/ddr/marvell/a38x/mv_ddr_topology.h b/drivers/ddr/marvell/a38x/mv_ddr_topology.h index eb017a1497..7bef2d1e0e 100644 --- a/drivers/ddr/marvell/a38x/mv_ddr_topology.h +++ b/drivers/ddr/marvell/a38x/mv_ddr_topology.h @@ -36,6 +36,12 @@ enum mv_ddr_temperature { MV_DDR_TEMP_HIGH }; +enum mv_ddr_timing { + MV_DDR_TIM_DEFAULT, + MV_DDR_TIM_1T, + MV_DDR_TIM_2T +}; + enum mv_ddr_timing_data { MV_DDR_TCK_AVG_MIN, /* sdram min cycle time (t ck avg min) */ MV_DDR_TAA_MIN, /* min cas latency time (t aa min) */ -- cgit From db363dbce705d3092f05a622ddea1d007ececca6 Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Thu, 10 May 2018 13:28:31 +1200 Subject: ARM: mvebu: a38x: use non-zero size for ddr scrubbing Make ddr3_calc_mem_cs_size() global scope and use it in ddr3_new_tip_ecc_scrub to correctly initialize all of DDR memory. Signed-off-by: Chris Packham Signed-off-by: Stefan Roese --- drivers/ddr/marvell/a38x/mv_ddr_plat.c | 2 +- drivers/ddr/marvell/a38x/mv_ddr_plat.h | 1 + drivers/ddr/marvell/a38x/xor.c | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.c b/drivers/ddr/marvell/a38x/mv_ddr_plat.c index 2070bb38b0..2f318cb9ea 100644 --- a/drivers/ddr/marvell/a38x/mv_ddr_plat.c +++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.c @@ -995,7 +995,7 @@ static u32 ddr3_get_device_size(u32 cs) } } -static int ddr3_calc_mem_cs_size(u32 cs, uint64_t *cs_size) +int ddr3_calc_mem_cs_size(u32 cs, uint64_t *cs_size) { u32 cs_mem_size; diff --git a/drivers/ddr/marvell/a38x/mv_ddr_plat.h b/drivers/ddr/marvell/a38x/mv_ddr_plat.h index 61f10302fc..9c5fdecd93 100644 --- a/drivers/ddr/marvell/a38x/mv_ddr_plat.h +++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.h @@ -232,4 +232,5 @@ u32 mv_ddr_dm_pad_get(void); int mv_ddr_pre_training_fixup(void); int mv_ddr_post_training_fixup(void); int mv_ddr_manual_cal_do(void); +int ddr3_calc_mem_cs_size(u32 cs, uint64_t *cs_size); #endif /* _MV_DDR_PLAT_H */ diff --git a/drivers/ddr/marvell/a38x/xor.c b/drivers/ddr/marvell/a38x/xor.c index 024cecd777..f859596d89 100644 --- a/drivers/ddr/marvell/a38x/xor.c +++ b/drivers/ddr/marvell/a38x/xor.c @@ -347,6 +347,9 @@ void ddr3_new_tip_ecc_scrub(void) for (cs_c = 0; cs_c < max_cs; cs_c++) cs_ena |= 1 << cs_c; + /* assume that all CS have same size */ + ddr3_calc_mem_cs_size(0, &cs_mem_size); + mv_sys_xor_init(max_cs, cs_ena, cs_mem_size, 0); total_mem_size = max_cs * cs_mem_size; mv_xor_mem_init(0, 0, total_mem_size, 0xdeadbeef, 0xdeadbeef); -- cgit From ca734a875dec089c3978663a0ce303d776365b20 Mon Sep 17 00:00:00 2001 From: Marek Behún Date: Fri, 11 May 2018 10:03:39 +0200 Subject: phy: marvell: a3700: Fix compatible string for ehci The DTS file for armada-37xx uses the string "marvell,armada3700-ehci", but the code searched for "marvell,armada-3700-ehci". Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 50167a69af..3b2902f362 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -900,7 +900,7 @@ void comphy_dedicated_phys_init(void) */ if (usb32 == 0) { node = fdt_node_offset_by_compatible( - blob, -1, "marvell,armada-3700-ehci"); + blob, -1, "marvell,armada3700-ehci"); } else { node = fdt_node_offset_by_compatible( blob, -1, "marvell,armada3700-xhci"); -- cgit