Hi Akashdeep, On Wed Jul 2, 2025 at 8:49 AM CEST, Akashdeep Kaur wrote: > Hi Markus, > > On 23/06/25 17:38, Markus Schneider-Pargmann wrote: >> In IO+DDR the DDR is kept in self-refresh while the SoC cores are >> powered off completely. During boot the normal initialization routine of >> DDR is slightly different to exit self-refresh and keep the DDR contents. >> >> Signed-off-by: Markus Schneider-Pargmann <m...@baylibre.com> >> --- >> drivers/ram/k3-ddrss/k3-ddrss.c | 177 >> ++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 177 insertions(+) >> >> diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c >> b/drivers/ram/k3-ddrss/k3-ddrss.c >> index >> 6590d57ad84f3c4dc5c72c6c5889038c463b0469..874614140c6d4a785fcca6eda4a8736e1183e193 >> 100644 >> --- a/drivers/ram/k3-ddrss/k3-ddrss.c >> +++ b/drivers/ram/k3-ddrss/k3-ddrss.c >> @@ -57,6 +57,16 @@ >> #define DDRSS_V2A_INT_SET_REG_ECC2BERR_EN BIT(4) >> #define DDRSS_V2A_INT_SET_REG_ECCM1BERR_EN BIT(5 >> +static void k3_ddrss_self_refresh_exit(struct k3_ddrss_desc *ddrss) >> +{ >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_CTL_169, >> + >> K3_DDRSS_CFG_DENALI_CTL_169_LP_AUTO_EXIT_EN_MASK | >> + >> K3_DDRSS_CFG_DENALI_CTL_169_LP_AUTO_ENTRY_EN_MASK, >> + 0x0); >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_PHY_1820, >> + 0, >> + BIT(2) << >> K3_DDRSS_CFG_DENALI_PHY_1820_SET_DFI_INPUT_2_SHIFT); >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_CTL_106, >> + 0, >> + >> K3_DDRSS_CFG_DENALI_CTL_106_PWRUP_SREFRESH_EXIT); >> + writel(0, ddrss->ddrss_ctl_cfg + K3_DDRSS_CFG_DENALI_PI_146); > > Can we change this writel also to reg update function based call?
Yes, that would be possible, but it would transform a single write into a read/update/write. > >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_PI_150, >> + K3_DDRSS_CFG_DENALI_PI_150_PI_DRAM_INIT_EN, >> + 0x0); >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_PI_6, >> + 0, >> + >> K3_DDRSS_CFG_DENALI_PI_6_PI_DFI_PHYMSTR_STATE_SEL_R); >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_CTL_21, >> + K3_DDRSS_CFG_DENALI_CTL_21_PHY_INDEP_INIT_MODE, >> + 0); >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_CTL_20, >> + 0, >> + >> K3_DDRSS_CFG_DENALI_CTL_20_PHY_INDEP_TRAIN_MODE); >> +} >> + >> +static void k3_ddrss_lpm_resume(struct k3_ddrss_desc *ddrss) >> +{ >> + int ret; >> + unsigned long timeout_start; >> + >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_CTL_160, >> + K3_DDRSS_CFG_DENALI_CTL_160_LP_CMD_MASK, >> + K3_DDRSS_CFG_DENALI_CTL_160_LP_CMD_ENTRY); >> + ret = wait_for_bit_32(ddrss->ddrss_ctl_cfg + >> K3_DDRSS_CFG_DENALI_CTL_345, >> + (1 << >> K3_DDRSS_CFG_DENALI_CTL_345_INT_STATUS_LOWPOWER_SHIFT), >> + true, 5000, false); >> + if (ret) >> + panic("Failed waiting for low power command %d\n", ret); >> + >> + k3_ddrss_reg_update_bits(ddrss->ddrss_ctl_cfg, >> + K3_DDRSS_CFG_DENALI_CTL_353, >> + 0, >> + 1 << >> K3_DDRSS_CFG_DENALI_CTL_353_INT_ACK_LOWPOWER_SHIFT); >> + >> + timeout_start = get_timer(0); >> + while (1) { >> + if (get_timer(timeout_start) > 5000) >> + panic("Failed waiting for low power state\n"); >> + >> + if ((readl(ddrss->ddrss_ctl_cfg + K3_DDRSS_CFG_DENALI_CTL_169) & >> + K3_DDRSS_CFG_DENALI_CTL_169_LP_STATE_MASK) == >> + 0x40 << K3_DDRSS_CFG_DENALI_CTL_169_LP_STATE_SHIFT) >> + break; > > As i see, wait for bit function can wait on mask also, can we use wait > on the bit transition with timeout in this case? If I see it correctly wait_for_bit_32 accepts a mask but can only check if the full mask is set or not. In the example above we would need separate arguments for mask and expected value, e.g. K3_DDRSS_CFG_DENALI_CTL_169_LP_STATE_MASK as mask and 0x40 shifted as the expected value. >> + } >> +} >> + >> +static void k3_ddrss_deassert_retention(struct k3_ddrss_desc *ddrss) >> +{ >> + int ret; >> + >> + k3_ddrss_reg_update_bits((void *)K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL, >> + 0x0, >> + K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD | >> + >> K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RETENTION_MASK, >> + 0); >> + k3_ddrss_reg_update_bits((void *)K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL, >> + 0x0, >> + K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD, >> + K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD); >> + >> + ret = wait_for_bit_32((void *)K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL, >> + K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD, >> + true, 5000, false); >> + if (ret) >> + panic("Failed waiting for latching of retention %d\n", ret); >> + >> + k3_ddrss_reg_update_bits((void *)K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL, >> + 0x0, >> + K3_WKUP_CTRL_MMR0_DDR16SS_PMCTRL_DATA_RET_LD, >> + 0); >> +} >> + >> +static bool k3_ddrss_wkup_conf_canuart_wakeup_active(struct k3_ddrss_desc >> *ddrss) >> +{ >> + u32 active; >> + >> + active = readl(ddrss->ddrss_ctrl_mmr + >> K3_WKUP_CTRL_MMR_CANUART_WAKE_STAT1); > > As seen in > https://elixir.bootlin.com/u-boot/v2025.07-rc5/source/arch/arm/dts/k3-am62a-ddr.dtsi#L10 > > - the address range for CTRL MMR is starting from 0x43014000 and has a > size of 0x100 but the address we want to access is outside that range. > (0x43018318) > We need to increase the address range in this node in dt file as well. Thanks for pointing this out. I am trying to push for a syscon node upstream without success yet. The CTRL_MMR register definition is overlapping with the wkup_conf device node in the upstream dts k3-am62a-wakeup.dtsi, so I chose to didn't increase the size. Best Markus
signature.asc
Description: PGP signature