// SPDX-License-Identifier: BSD-3-Clause /****************************************************************************** * Copyright (C) 2012-2018 Cadence Design Systems, Inc. * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ * * lpddr4.c * ***************************************************************************** */ #include "cps_drv_lpddr4.h" #include "lpddr4_ctl_regs.h" #include "lpddr4_if.h" #include "lpddr4_private.h" #include "lpddr4_sanity.h" #include "lpddr4_structs_if.h" #define LPDDR4_CUSTOM_TIMEOUT_DELAY 100000000U /** * Internal Function:Poll for status of interrupt received by the Controller. * @param[in] pD Driver state info specific to this instance. * @param[in] irqBit Interrupt status bit to be checked. * @param[in] delay time delay. * @return CDN_EOK on success (Interrupt status high). * @return EIO on poll time out. * @return EINVAL checking status was not successful. */ static uint32_t lpddr4_pollctlirq(const lpddr4_privatedata * pd, lpddr4_ctlinterrupt irqbit, uint32_t delay) { uint32_t result = 0U; uint32_t timeout = 0U; bool irqstatus = false; /* Loop until irqStatus found to be 1 or if value of 'result' !=CDN_EOK */ do { if (++timeout == delay) { result = EIO; break; } /* cps_delayns(10000000U); */ result = lpddr4_checkctlinterrupt(pd, irqbit, &irqstatus); } while ((irqstatus == false) && (result == (uint32_t) CDN_EOK)); return result; } /** * Internal Function:Poll for status of interrupt received by the PHY Independent Module. * @param[in] pD Driver state info specific to this instance. * @param[in] irqBit Interrupt status bit to be checked. * @param[in] delay time delay. * @return CDN_EOK on success (Interrupt status high). * @return EIO on poll time out. * @return EINVAL checking status was not successful. */ static uint32_t lpddr4_pollphyindepirq(const lpddr4_privatedata * pd, lpddr4_phyindepinterrupt irqbit, uint32_t delay) { uint32_t result = 0U; uint32_t timeout = 0U; bool irqstatus = false; /* Loop until irqStatus found to be 1 or if value of 'result' !=CDN_EOK */ do { if (++timeout == delay) { result = EIO; break; } /* cps_delayns(10000000U); */ result = lpddr4_checkphyindepinterrupt(pd, irqbit, &irqstatus); } while ((irqstatus == false) && (result == (uint32_t) CDN_EOK)); return result; } /** * Internal Function:Trigger function to poll and Ack IRQs * @param[in] pD Driver state info specific to this instance. * @return CDN_EOK on success (Interrupt status high). * @return EIO on poll time out. * @return EINVAL checking status was not successful. */ static uint32_t lpddr4_pollandackirq(const lpddr4_privatedata * pd) { uint32_t result = 0U; /* Wait for PhyIndependent module to finish up ctl init sequence */ result = lpddr4_pollphyindepirq(pd, LPDDR4_PHY_INDEP_INIT_DONE_BIT, LPDDR4_CUSTOM_TIMEOUT_DELAY); /* Ack to clear the PhyIndependent interrupt bit */ if (result == (uint32_t) CDN_EOK) { result = lpddr4_ackphyindepinterrupt(pd, LPDDR4_PHY_INDEP_INIT_DONE_BIT); } /* Wait for the CTL end of initialization */ if (result == (uint32_t) CDN_EOK) { result = lpddr4_pollctlirq(pd, LPDDR4_MC_INIT_DONE, LPDDR4_CUSTOM_TIMEOUT_DELAY); } /* Ack to clear the Ctl interrupt bit */ if (result == (uint32_t) CDN_EOK) { result = lpddr4_ackctlinterrupt(pd, LPDDR4_MC_INIT_DONE); } return result; } /** * Internal Function: Controller start sequence. * @param[in] pD Driver state info specific to this instance. * @return CDN_EOK on success. * @return EINVAL starting controller was not successful. */ static uint32_t lpddr4_startsequencecontroller(const lpddr4_privatedata * pd) { uint32_t result = 0U; uint32_t regval = 0U; lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; lpddr4_infotype infotype; /* Set the PI_start to initiate leveling procedure */ regval = CPS_FLD_SET(LPDDR4__PI_START__FLD, CPS_REG_READ(&(ctlregbase->LPDDR4__PI_START__REG))); CPS_REG_WRITE((&(ctlregbase->LPDDR4__PI_START__REG)), regval); /* Set the Ctl_start */ regval = CPS_FLD_SET(LPDDR4__START__FLD, CPS_REG_READ(&(ctlregbase->LPDDR4__START__REG))); CPS_REG_WRITE(&(ctlregbase->LPDDR4__START__REG), regval); if (pd->infohandler != NULL) { /* If a handler is registered, call it with the relevant information type */ infotype = LPDDR4_DRV_SOC_PLL_UPDATE; pd->infohandler(pd, infotype); } result = lpddr4_pollandackirq(pd); return result; } /** * Internal Function: To add the offset to given address. * @param[in] addr Address to which the offset has to be added. * @param[in] regOffset The offset * @return regAddr The address value after the summation. */ static volatile uint32_t *lpddr4_addoffset(volatile uint32_t * addr, uint32_t regoffset) { volatile uint32_t *local_addr = addr; /* Declaring as array to add the offset value. */ volatile uint32_t *regaddr = &local_addr[regoffset]; return regaddr; } /** * Checks configuration object. * @param[in] config Driver/hardware configuration required. * @param[out] configSize Size of memory allocations required. * @return CDN_EOK on success (requirements structure filled). * @return ENOTSUP if configuration cannot be supported due to driver/hardware constraints. */ uint32_t lpddr4_probe(const lpddr4_config * config, uint16_t * configsize) { uint32_t result; result = (uint32_t) (lpddr4_probesf(config, configsize)); if (result == (uint32_t) CDN_EOK) { *configsize = (uint16_t) (sizeof(lpddr4_privatedata)); } return result; } /** * Init function to be called after LPDDR4_probe() to set up the driver configuration. * Memory should be allocated for drv_data (using the size determined using LPDDR4_probe) before * calling this API, init_settings should be initialized with base addresses for PHY Independent Module, * Controller and PHY before calling this function. * If callbacks are required for interrupt handling, these should also be configured in init_settings. * @param[in] pD Driver state info specific to this instance. * @param[in] cfg Specifies driver/hardware configuration. * @return CDN_EOK on success * @return EINVAL if illegal/inconsistent values in cfg. * @return ENOTSUP if hardware has an inconsistent configuration or doesn't support feature(s) * required by 'config' parameters. */ uint32_t lpddr4_init(lpddr4_privatedata * pd, const lpddr4_config * cfg) { uint32_t result = 0U; uint16_t productid = 0U; uint32_t version[2] = { 0, 0 }; result = lpddr4_initsf(pd, cfg); if (result == (uint32_t) CDN_EOK) { /* Validate Magic number */ lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) cfg->ctlbase; productid = (uint16_t) (CPS_FLD_READ(LPDDR4__CONTROLLER_ID__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__CONTROLLER_ID__REG)))); version[0] = (uint32_t) (CPS_FLD_READ (LPDDR4__CONTROLLER_VERSION_0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__CONTROLLER_VERSION_0__REG)))); version[1] = (uint32_t) (CPS_FLD_READ (LPDDR4__CONTROLLER_VERSION_1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__CONTROLLER_VERSION_1__REG)))); if ((productid == PRODUCT_ID) && (version[0] == VERSION_0) && (version[1] == VERSION_1)) { /* Populating configuration data to pD */ pd->ctlbase = ctlregbase; pd->infohandler = (lpddr4_infocallback) cfg->infohandler; pd->ctlinterrupthandler = (lpddr4_ctlcallback) cfg->ctlinterrupthandler; pd->phyindepinterrupthandler = (lpddr4_phyindepcallback) cfg-> phyindepinterrupthandler; } else { /* Magic number validation failed - Driver doesn't support given IP version */ result = (uint32_t) EOPNOTSUPP; } } return result; } /** * Start the driver. * @param[in] pD Driver state info specific to this instance. */ uint32_t lpddr4_start(const lpddr4_privatedata * pd) { uint32_t result = 0U; uint32_t regval = 0U; result = lpddr4_startsf(pd); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Enable PI as the initiator for DRAM */ regval = CPS_FLD_SET(LPDDR4__PI_INIT_LVL_EN__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__PI_INIT_LVL_EN__REG))); regval = CPS_FLD_SET(LPDDR4__PI_NORMAL_LVL_SEQ__FLD, regval); CPS_REG_WRITE((&(ctlregbase->LPDDR4__PI_INIT_LVL_EN__REG)), regval); /* Start PI init sequence. */ result = lpddr4_startsequencecontroller(pd); } return result; } /** * Read a register from the controller, PHY or PHY Independent Module * @param[in] pD Driver state info specific to this instance. * @param[in] cpp Indicates whether controller, PHY or PHY Independent Module register * @param[in] regOffset Register offset * @param[out] regValue Register value read * @return CDN_EOK on success. * @return EINVAL if regOffset if out of range or regValue is NULL */ uint32_t lpddr4_readreg(const lpddr4_privatedata * pd, lpddr4_regblock cpp, uint32_t regoffset, uint32_t * regvalue) { uint32_t result = 0U; result = lpddr4_readregsf(pd, cpp, regvalue); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; if (cpp == LPDDR4_CTL_REGS) { if (regoffset >= LPDDR4_CTL_REG_COUNT) { /* Return if user provider invalid register number */ result = EINVAL; } else { *regvalue = CPS_REG_READ(lpddr4_addoffset (&(ctlregbase->DENALI_CTL_0), regoffset)); } } else if (cpp == LPDDR4_PHY_REGS) { if (regoffset >= LPDDR4_PHY_REG_COUNT) { /* Return if user provider invalid register number */ result = EINVAL; } else { *regvalue = CPS_REG_READ(lpddr4_addoffset (&(ctlregbase->DENALI_PHY_0), regoffset)); } } else { if (regoffset >= LPDDR4_PHY_INDEP_REG_COUNT) { /* Return if user provider invalid register number */ result = EINVAL; } else { *regvalue = CPS_REG_READ(lpddr4_addoffset (&(ctlregbase->DENALI_PI_0), regoffset)); } } } return result; } uint32_t lpddr4_writereg(const lpddr4_privatedata * pd, lpddr4_regblock cpp, uint32_t regoffset, uint32_t regvalue) { uint32_t result = 0U; result = lpddr4_writeregsf(pd, cpp); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; if (cpp == LPDDR4_CTL_REGS) { if (regoffset >= LPDDR4_CTL_REG_COUNT) { /* Return if user provider invalid register number */ result = EINVAL; } else { CPS_REG_WRITE(lpddr4_addoffset (&(ctlregbase->DENALI_CTL_0), regoffset), regvalue); } } else if (cpp == LPDDR4_PHY_REGS) { if (regoffset >= LPDDR4_PHY_REG_COUNT) { /* Return if user provider invalid register number */ result = EINVAL; } else { CPS_REG_WRITE(lpddr4_addoffset (&(ctlregbase->DENALI_PHY_0), regoffset), regvalue); } } else { if (regoffset >= LPDDR4_PHY_INDEP_REG_COUNT) { /* Return if user provider invalid register number */ result = EINVAL; } else { CPS_REG_WRITE(lpddr4_addoffset (&(ctlregbase->DENALI_PI_0), regoffset), regvalue); } } } return result; } static uint32_t lpddr4_checkmmrreaderror(const lpddr4_privatedata * pd, uint64_t * mmrvalue, uint8_t * mrrstatus) { uint64_t lowerdata; lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; uint32_t result = (uint32_t) CDN_EOK; /* Check if mode register read error interrupt occurred */ if (lpddr4_pollctlirq(pd, LPDDR4_MRR_ERROR, 100) == 0U) { /* Mode register read error interrupt, read MRR status register and return. */ *mrrstatus = (uint8_t) CPS_FLD_READ(LPDDR4__MRR_ERROR_STATUS__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__MRR_ERROR_STATUS__REG))); *mmrvalue = 0; result = EIO; } else { *mrrstatus = 0; /* Mode register read was successful, read DATA */ lowerdata = CPS_REG_READ(& (ctlregbase-> LPDDR4__PERIPHERAL_MRR_DATA_0__REG)); *mmrvalue = CPS_REG_READ(& (ctlregbase-> LPDDR4__PERIPHERAL_MRR_DATA_1__REG)); *mmrvalue = (uint64_t) ((*mmrvalue << WORD_SHIFT) | lowerdata); /* Acknowledge MR_READ_DONE interrupt to clear it */ result = lpddr4_ackctlinterrupt(pd, LPDDR4_MR_READ_DONE); } return result; } uint32_t lpddr4_getmmrregister(const lpddr4_privatedata * pd, uint32_t readmoderegval, uint64_t * mmrvalue, uint8_t * mmrstatus) { uint32_t result = 0U; uint32_t tdelay = 1000U; uint32_t regval = 0U; result = lpddr4_getmmrregistersf(pd, mmrvalue, mmrstatus); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Populate the calculated value to the register */ regval = CPS_FLD_WRITE(LPDDR4__READ_MODEREG__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__READ_MODEREG__REG)), readmoderegval); CPS_REG_WRITE(&(ctlregbase->LPDDR4__READ_MODEREG__REG), regval); /* Wait until the Read is done */ result = lpddr4_pollctlirq(pd, LPDDR4_MR_READ_DONE, tdelay); } if (result == (uint32_t) CDN_EOK) { result = lpddr4_checkmmrreaderror(pd, mmrvalue, mmrstatus); } return result; } static uint32_t lpddr4_writemmrregister(const lpddr4_privatedata * pd, uint32_t writemoderegval) { uint32_t result = (uint32_t) CDN_EOK; uint32_t tdelay = 1000U; uint32_t regval = 0U; lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Populate the calculated value to the register */ regval = CPS_FLD_WRITE(LPDDR4__WRITE_MODEREG__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__WRITE_MODEREG__REG)), writemoderegval); CPS_REG_WRITE(&(ctlregbase->LPDDR4__WRITE_MODEREG__REG), regval); result = lpddr4_pollctlirq(pd, LPDDR4_MR_WRITE_DONE, tdelay); return result; } uint32_t lpddr4_setmmrregister(const lpddr4_privatedata * pd, uint32_t writemoderegval, uint8_t * mrwstatus) { uint32_t result = 0U; result = lpddr4_setmmrregistersf(pd, mrwstatus); if (result == (uint32_t) CDN_EOK) { /* Function call to trigger Mode register write */ result = lpddr4_writemmrregister(pd, writemoderegval); if (result == (uint32_t) CDN_EOK) { result = lpddr4_ackctlinterrupt(pd, LPDDR4_MR_WRITE_DONE); } /* Read the status of mode register write */ if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; *mrwstatus = (uint8_t) CPS_FLD_READ(LPDDR4__MRW_STATUS__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__MRW_STATUS__REG))); if ((*mrwstatus) != 0U) { result = EIO; } } } return result; } uint32_t lpddr4_writectlconfig(const lpddr4_privatedata * pd, const lpddr4_reginitdata * regvalues) { uint32_t result; uint32_t regnum; result = lpddr4_writectlconfigsf(pd, regvalues); if (result == (uint32_t) CDN_EOK) { /* Iterate through CTL register numbers. */ for (regnum = 0; regnum < LPDDR4_CTL_REG_COUNT; regnum++) { /* Check if the user has requested update */ if (regvalues->updatectlreg[regnum]) { result = lpddr4_writereg(pd, LPDDR4_CTL_REGS, regnum, (uint32_t) (regvalues-> denalictlreg [regnum])); } } } return result; } uint32_t lpddr4_writephyindepconfig(const lpddr4_privatedata * pd, const lpddr4_reginitdata * regvalues) { uint32_t result; uint32_t regnum; result = lpddr4_writephyindepconfigsf(pd, regvalues); if (result == (uint32_t) CDN_EOK) { /* Iterate through PHY Independent module register numbers. */ for (regnum = 0; regnum < LPDDR4_PHY_INDEP_REG_COUNT; regnum++) { /* Check if the user has requested update */ if (regvalues->updatephyindepreg[regnum]) { result = lpddr4_writereg(pd, LPDDR4_PHY_INDEP_REGS, regnum, (uint32_t) (regvalues-> denaliphyindepreg [regnum])); } } } return result; } uint32_t lpddr4_writephyconfig(const lpddr4_privatedata * pd, const lpddr4_reginitdata * regvalues) { uint32_t result; uint32_t regnum; result = lpddr4_writephyconfigsf(pd, regvalues); if (result == (uint32_t) CDN_EOK) { /* Iterate through PHY register numbers. */ for (regnum = 0; regnum < LPDDR4_PHY_REG_COUNT; regnum++) { /* Check if the user has requested update */ if (regvalues->updatephyreg[regnum]) { result = lpddr4_writereg(pd, LPDDR4_PHY_REGS, regnum, (uint32_t) (regvalues-> denaliphyreg [regnum])); } } } return result; } uint32_t lpddr4_readctlconfig(const lpddr4_privatedata * pd, lpddr4_reginitdata * regvalues) { uint32_t result; uint32_t regnum; result = lpddr4_readctlconfigsf(pd, regvalues); if (result == (uint32_t) CDN_EOK) { /* Iterate through CTL register numbers. */ for (regnum = 0; regnum < LPDDR4_CTL_REG_COUNT; regnum++) { /* Check if the user has requested read (updateCtlReg=1) */ if (regvalues->updatectlreg[regnum]) { result = lpddr4_readreg(pd, LPDDR4_CTL_REGS, regnum, (uint32_t *) (®values-> denalictlreg [regnum])); } } } return result; } uint32_t lpddr4_readphyindepconfig(const lpddr4_privatedata * pd, lpddr4_reginitdata * regvalues) { uint32_t result; uint32_t regnum; result = lpddr4_readphyindepconfigsf(pd, regvalues); if (result == (uint32_t) CDN_EOK) { /* Iterate through PHY Independent module register numbers. */ for (regnum = 0; regnum < LPDDR4_PHY_INDEP_REG_COUNT; regnum++) { /* Check if the user has requested read (updateCtlReg=1) */ if (regvalues->updatephyindepreg[regnum]) { result = lpddr4_readreg(pd, LPDDR4_PHY_INDEP_REGS, regnum, (uint32_t *) (®values-> denaliphyindepreg [regnum])); } } } return result; } uint32_t lpddr4_readphyconfig(const lpddr4_privatedata * pd, lpddr4_reginitdata * regvalues) { uint32_t result; uint32_t regnum; result = lpddr4_readphyconfigsf(pd, regvalues); if (result == (uint32_t) CDN_EOK) { /* Iterate through PHY register numbers. */ for (regnum = 0; regnum < LPDDR4_PHY_REG_COUNT; regnum++) { /* Check if the user has requested read (updateCtlReg=1) */ if (regvalues->updatephyreg[regnum]) { result = lpddr4_readreg(pd, LPDDR4_PHY_REGS, regnum, (uint32_t *) (®values-> denaliphyreg [regnum])); } } } return result; } uint32_t lpddr4_getctlinterruptmask(const lpddr4_privatedata * pd, uint64_t * mask) { uint32_t result = 0U; uint64_t lowermask = 0U; result = lpddr4_getctlinterruptmasksf(pd, mask); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Reading the lower mask register */ lowermask = (uint64_t) (CPS_FLD_READ (LPDDR4__INT_MASK_0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__INT_MASK_0__REG)))); /* Reading the upper mask register */ *mask = (uint64_t) (CPS_FLD_READ (LPDDR4__INT_MASK_1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__INT_MASK_1__REG)))); /* Concatenate both register informations */ *mask = (uint64_t) ((*mask << WORD_SHIFT) | lowermask); } return result; } uint32_t lpddr4_setctlinterruptmask(const lpddr4_privatedata * pd, const uint64_t * mask) { uint32_t result; uint32_t regval = 0; const uint64_t ui64one = 1ULL; const uint32_t ui32irqcount = (uint32_t) LPDDR4_LOR_BITS + 1U; result = lpddr4_setctlinterruptmasksf(pd, mask); if ((result == (uint32_t) CDN_EOK) && (ui32irqcount < 64U)) { /* Return if the user given value is higher than the field width */ if (*mask >= (ui64one << ui32irqcount)) { result = EINVAL; } } if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Extracting the lower 32 bits and writing to lower mask register */ regval = (uint32_t) (*mask & WORD_MASK); regval = CPS_FLD_WRITE(LPDDR4__INT_MASK_0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__INT_MASK_0__REG)), regval); CPS_REG_WRITE(&(ctlregbase->LPDDR4__INT_MASK_0__REG), regval); /* Extracting the upper 32 bits and writing to upper mask register */ regval = (uint32_t) ((*mask >> WORD_SHIFT) & WORD_MASK); regval = CPS_FLD_WRITE(LPDDR4__INT_MASK_1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__INT_MASK_1__REG)), regval); CPS_REG_WRITE(&(ctlregbase->LPDDR4__INT_MASK_1__REG), regval); } return result; } uint32_t lpddr4_checkctlinterrupt(const lpddr4_privatedata * pd, lpddr4_ctlinterrupt intr, bool * irqstatus) { uint32_t result; uint32_t ctlirqstatus = 0; uint32_t fieldshift = 0; /* NOTE:This function assume irq status is mentioned in NOT more than 2 registers. * Value of 'interrupt' should be less than 64 */ result = lpddr4_checkctlinterruptsf(pd, intr, irqstatus); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; if ((uint32_t) intr >= WORD_SHIFT) { ctlirqstatus = CPS_REG_READ(& (ctlregbase-> LPDDR4__INT_STATUS_1__REG)); /* Reduce the shift value as we are considering upper register */ fieldshift = (uint32_t) intr - ((uint32_t) WORD_SHIFT); } else { ctlirqstatus = CPS_REG_READ(& (ctlregbase-> LPDDR4__INT_STATUS_0__REG)); /* The shift value remains same for lower interrupt register */ fieldshift = (uint32_t) intr; } /* MISRA compliance (Shifting operation) check */ if (fieldshift < WORD_SHIFT) { if (((ctlirqstatus >> fieldshift) & BIT_MASK) > 0U) { *irqstatus = true; } else { *irqstatus = false; } } } return result; } uint32_t lpddr4_ackctlinterrupt(const lpddr4_privatedata * pd, lpddr4_ctlinterrupt intr) { uint32_t result = 0; uint32_t regval = 0; uint32_t localinterrupt = (uint32_t) intr; /* NOTE:This function assume irq status is mentioned in NOT more than 2 registers. * Value of 'interrupt' should be less than 64 */ result = lpddr4_ackctlinterruptsf(pd, intr); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Check if the requested bit is in upper register */ if (localinterrupt > WORD_SHIFT) { localinterrupt = (localinterrupt - (uint32_t) WORD_SHIFT); regval = ((uint32_t) BIT_MASK << localinterrupt); CPS_REG_WRITE(&(ctlregbase->LPDDR4__INT_ACK_1__REG), regval); } else { regval = ((uint32_t) BIT_MASK << localinterrupt); CPS_REG_WRITE(&(ctlregbase->LPDDR4__INT_ACK_0__REG), regval); } } return result; } uint32_t lpddr4_getphyindepinterruptmask(const lpddr4_privatedata * pd, uint32_t * mask) { uint32_t result; result = lpddr4_getphyindepinterruptmsf(pd, mask); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Reading mask register */ *mask = CPS_FLD_READ(LPDDR4__PI_INT_MASK__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__PI_INT_MASK__REG))); } return result; } uint32_t lpddr4_setphyindepinterruptmask(const lpddr4_privatedata * pd, const uint32_t * mask) { uint32_t result; uint32_t regval = 0; const uint32_t ui32irqcount = (uint32_t) LPDDR4_PHY_INDEP_DLL_LOCK_STATE_CHANGE_BIT + 1U; result = lpddr4_setphyindepinterruptmsf(pd, mask); if ((result == (uint32_t) CDN_EOK) && (ui32irqcount < WORD_SHIFT)) { /* Return if the user given value is higher than the field width */ if (*mask >= (1U << ui32irqcount)) { result = EINVAL; } } if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Writing to the user requested interrupt mask */ regval = CPS_FLD_WRITE(LPDDR4__PI_INT_MASK__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__PI_INT_MASK__REG)), *mask); CPS_REG_WRITE(&(ctlregbase->LPDDR4__PI_INT_MASK__REG), regval); } return result; } uint32_t lpddr4_checkphyindepinterrupt(const lpddr4_privatedata * pd, lpddr4_phyindepinterrupt intr, bool * irqstatus) { uint32_t result = 0; uint32_t phyindepirqstatus = 0; result = lpddr4_checkphyindepinterrupsf(pd, intr, irqstatus); /* Confirming that the value of interrupt is less than register width */ if ((result == (uint32_t) CDN_EOK) && ((uint32_t) intr < WORD_SHIFT)) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Reading the requested bit to check interrupt status */ phyindepirqstatus = CPS_REG_READ(&(ctlregbase->LPDDR4__PI_INT_STATUS__REG)); *irqstatus = (((phyindepirqstatus >> (uint32_t) intr) & BIT_MASK) > 0U); } return result; } uint32_t lpddr4_ackphyindepinterrupt(const lpddr4_privatedata * pd, lpddr4_phyindepinterrupt intr) { uint32_t result = 0U; uint32_t regval = 0U; uint32_t ui32shiftinterrupt = (uint32_t) intr; result = lpddr4_ackphyindepinterruptsf(pd, intr); /* Confirming that the value of interrupt is less than register width */ if ((result == (uint32_t) CDN_EOK) && (ui32shiftinterrupt < WORD_SHIFT)) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Write 1 to the requested bit to ACk the interrupt */ regval = ((uint32_t) BIT_MASK << ui32shiftinterrupt); CPS_REG_WRITE(&(ctlregbase->LPDDR4__PI_INT_ACK__REG), regval); } return result; } /* Check for caTrainingError */ static void lpddr4_checkcatrainingerror(lpddr4_ctlregs * ctlregbase, lpddr4_debuginfo * debuginfo, bool * errfoundptr) { uint32_t regval; uint32_t errbitmask = 0U; uint32_t snum; volatile uint32_t *regaddress; regaddress = (volatile uint32_t *)(&(ctlregbase->LPDDR4__PHY_ADR_CALVL_OBS1_0__REG)); errbitmask = (CA_TRAIN_RL) | (NIBBLE_MASK); /* PHY_ADR_CALVL_OBS1[4] – Right found PHY_ADR_CALVL_OBS1[5] – left found both the above fields should be high and below field should be zero. PHY_ADR_CALVL_OBS1[3:0] – calvl_state */ for (snum = 0U; snum < ASLICE_NUM; snum++) { regval = CPS_REG_READ(regaddress); if ((regval & errbitmask) != CA_TRAIN_RL) { debuginfo->catraingerror = true; *errfoundptr = true; } regaddress = lpddr4_addoffset(regaddress, (uint32_t) SLICE_WIDTH); } } /* Check for wrLvlError */ static void lpddr4_checkwrlvlerror(lpddr4_ctlregs * ctlregbase, lpddr4_debuginfo * debuginfo, bool * errfoundptr) { uint32_t regval; uint32_t errbitmask = 0U; uint32_t snum; volatile uint32_t *regaddress; regaddress = (volatile uint32_t *)(&(ctlregbase->LPDDR4__PHY_WRLVL_ERROR_OBS_0__REG)); /* PHY_WRLVL_ERROR_OBS_X[1:0] should be zero */ errbitmask = (BIT_MASK << 1) | (BIT_MASK); for (snum = 0U; snum < DSLICE_NUM; snum++) { regval = CPS_REG_READ(regaddress); if ((regval & errbitmask) != 0U) { debuginfo->wrlvlerror = true; *errfoundptr = true; } regaddress = lpddr4_addoffset(regaddress, (uint32_t) SLICE_WIDTH); } } /* Check for GateLvlError */ static void lpddr4_checkgatelvlerror(lpddr4_ctlregs * ctlregbase, lpddr4_debuginfo * debuginfo, bool * errfoundptr) { uint32_t regval; uint32_t errbitmask = 0U; uint32_t snum; volatile uint32_t *regaddress; regaddress = (volatile uint32_t *)(&(ctlregbase->LPDDR4__PHY_GTLVL_STATUS_OBS_0__REG)); /* PHY_GTLVL_STATUS_OBS[6] – gate_level min error * PHY_GTLVL_STATUS_OBS[7] – gate_level max error * All the above bit fields should be zero */ errbitmask = GATE_LVL_ERROR_FIELDS; for (snum = 0U; snum < DSLICE_NUM; snum++) { regval = CPS_REG_READ(regaddress); if ((regval & errbitmask) != 0U) { debuginfo->gatelvlerror = true; *errfoundptr = true; } regaddress = lpddr4_addoffset(regaddress, (uint32_t) SLICE_WIDTH); } } /* Check for ReadLvlError */ static void lpddr4_checkreadlvlerror(lpddr4_ctlregs * ctlregbase, lpddr4_debuginfo * debuginfo, bool * errfoundptr) { uint32_t regval; uint32_t errbitmask = 0U; uint32_t snum; volatile uint32_t *regaddress; regaddress = (volatile uint32_t *)(&(ctlregbase->LPDDR4__PHY_RDLVL_STATUS_OBS_0__REG)); /* PHY_RDLVL_STATUS_OBS[23:16] – failed bits : should be zero. PHY_RDLVL_STATUS_OBS[31:28] – rdlvl_state : should be zero */ errbitmask = READ_LVL_ERROR_FIELDS; for (snum = 0U; snum < DSLICE_NUM; snum++) { regval = CPS_REG_READ(regaddress); if ((regval & errbitmask) != 0U) { debuginfo->readlvlerror = true; *errfoundptr = true; } regaddress = lpddr4_addoffset(regaddress, (uint32_t) SLICE_WIDTH); } } /* Check for DqTrainingError */ static void lpddr4_checkdqtrainingerror(lpddr4_ctlregs * ctlregbase, lpddr4_debuginfo * debuginfo, bool * errfoundptr) { uint32_t regval; uint32_t errbitmask = 0U; uint32_t snum; volatile uint32_t *regaddress; regaddress = (volatile uint32_t *)(&(ctlregbase->LPDDR4__PHY_WDQLVL_STATUS_OBS_0__REG)); /* PHY_WDQLVL_STATUS_OBS[26:18] should all be zero. */ errbitmask = DQ_LVL_STATUS; for (snum = 0U; snum < DSLICE_NUM; snum++) { regval = CPS_REG_READ(regaddress); if ((regval & errbitmask) != 0U) { debuginfo->dqtrainingerror = true; *errfoundptr = true; } regaddress = lpddr4_addoffset(regaddress, (uint32_t) SLICE_WIDTH); } } /** * Internal Function:For checking errors in training/levelling sequence. * @param[in] pD Driver state info specific to this instance. * @param[in] debugInfo pointer to debug information. * @param[out] errFoundPtr pointer to return if error found. * @return CDN_EOK on success (Interrupt status high). * @return EINVAL checking or unmasking was not successful. */ static bool lpddr4_checklvlerrors(const lpddr4_privatedata * pd, lpddr4_debuginfo * debuginfo, bool errfound) { bool localerrfound = errfound; lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; if (localerrfound == false) { /* Check for ca training error */ lpddr4_checkcatrainingerror(ctlregbase, debuginfo, &localerrfound); } if (localerrfound == false) { /* Check for Write leveling error */ lpddr4_checkwrlvlerror(ctlregbase, debuginfo, &localerrfound); } if (localerrfound == false) { /* Check for Gate leveling error */ lpddr4_checkgatelvlerror(ctlregbase, debuginfo, &localerrfound); } if (localerrfound == false) { /* Check for Read leveling error */ lpddr4_checkreadlvlerror(ctlregbase, debuginfo, &localerrfound); } if (localerrfound == false) { /* Check for DQ training error */ lpddr4_checkdqtrainingerror(ctlregbase, debuginfo, &localerrfound); } return localerrfound; } static bool lpddr4_seterror(volatile uint32_t * reg, uint32_t errbitmask, bool * errfoundptr, const uint32_t errorinfobits) { uint32_t regval = 0U; /* Read the respective observation register */ regval = CPS_REG_READ(reg); /* Compare the error bit values */ if ((regval & errbitmask) != errorinfobits) { *errfoundptr = true; } return *errfoundptr; } static void lpddr4_seterrors(lpddr4_ctlregs * ctlregbase, lpddr4_debuginfo * debuginfo, bool * errfoundptr) { uint32_t errbitmask = (BIT_MASK << 0x1U) | (BIT_MASK); /* Check PLL observation registers for PLL lock errors */ debuginfo->pllerror = lpddr4_seterror(&(ctlregbase->LPDDR4__PHY_PLL_OBS_0__REG), errbitmask, errfoundptr, PLL_READY); if (*errfoundptr == false) { debuginfo->pllerror = lpddr4_seterror(&(ctlregbase->LPDDR4__PHY_PLL_OBS_1__REG), errbitmask, errfoundptr, PLL_READY); } /* Check for IO Calibration errors */ if (*errfoundptr == false) { debuginfo->iocaliberror = lpddr4_seterror(& (ctlregbase-> LPDDR4__PHY_CAL_RESULT_OBS_0__REG), IO_CALIB_DONE, errfoundptr, IO_CALIB_DONE); } if (*errfoundptr == false) { debuginfo->iocaliberror = lpddr4_seterror(& (ctlregbase-> LPDDR4__PHY_CAL_RESULT2_OBS_0__REG), IO_CALIB_DONE, errfoundptr, IO_CALIB_DONE); } if (*errfoundptr == false) { debuginfo->iocaliberror = lpddr4_seterror(& (ctlregbase-> LPDDR4__PHY_CAL_RESULT3_OBS_0__REG), IO_CALIB_FIELD, errfoundptr, IO_CALIB_STATE); } } static void lpddr4_setphysnapsettings(lpddr4_ctlregs * ctlregbase, const bool errorfound) { uint32_t snum = 0U; volatile uint32_t *regaddress; uint32_t regval = 0U; /* Setting SC_PHY_SNAP_OBS_REGS_x to get a snapshot */ if (errorfound == false) { regaddress = (volatile uint32_t *)(&(ctlregbase->LPDDR4__SC_PHY_SNAP_OBS_REGS_0__REG)); /* Iterate through each PHY Data Slice */ for (snum = 0U; snum < DSLICE_NUM; snum++) { regval = CPS_FLD_SET(LPDDR4__SC_PHY_SNAP_OBS_REGS_0__FLD, CPS_REG_READ(regaddress)); CPS_REG_WRITE(regaddress, regval); regaddress = lpddr4_addoffset(regaddress, (uint32_t) SLICE_WIDTH); } } } static void lpddr4_setphyadrsnapsettings(lpddr4_ctlregs * ctlregbase, const bool errorfound) { uint32_t snum = 0U; volatile uint32_t *regaddress; uint32_t regval = 0U; /* Setting SC_PHY ADR_SNAP_OBS_REGS_x to get a snapshot */ if (errorfound == false) { regaddress = (volatile uint32_t *)(&(ctlregbase->LPDDR4__SC_PHY_ADR_SNAP_OBS_REGS_0__REG)); /* Iterate through each PHY Address Slice */ for (snum = 0U; snum < ASLICE_NUM; snum++) { regval = CPS_FLD_SET(LPDDR4__SC_PHY_ADR_SNAP_OBS_REGS_0__FLD, CPS_REG_READ(regaddress)); CPS_REG_WRITE(regaddress, regval); regaddress = lpddr4_addoffset(regaddress, (uint32_t) SLICE_WIDTH); } } } static void lpddr4_setsettings(lpddr4_ctlregs * ctlregbase, const bool errorfound) { /* Calling functions to enable snap shots of OBS registers */ lpddr4_setphysnapsettings(ctlregbase, errorfound); lpddr4_setphyadrsnapsettings(ctlregbase, errorfound); } static void lpddr4_setrxoffseterror(lpddr4_ctlregs * ctlregbase, lpddr4_debuginfo * debuginfo, bool * errorfound) { volatile uint32_t *regaddress; uint32_t snum = 0U; uint32_t errbitmask = 0U; uint32_t regval = 0U; /* Check for rxOffsetError */ if (*errorfound == false) { regaddress = (volatile uint32_t *)(&(ctlregbase->LPDDR4__PHY_RX_CAL_LOCK_OBS_0__REG)); errbitmask = (RX_CAL_DONE) | (NIBBLE_MASK); /* PHY_RX_CAL_LOCK_OBS_x[4] – RX_CAL_DONE : should be high phy_rx_cal_lock_obs_x[3:0] – RX_CAL_STATE : should be zero. */ for (snum = 0U; snum < DSLICE_NUM; snum++) { regval = CPS_FLD_READ(LPDDR4__PHY_RX_CAL_LOCK_OBS_0__FLD, CPS_REG_READ(regaddress)); if ((regval & errbitmask) != RX_CAL_DONE) { debuginfo->rxoffseterror = true; *errorfound = true; } regaddress = lpddr4_addoffset(regaddress, (uint32_t) SLICE_WIDTH); } } } uint32_t lpddr4_getdebuginitinfo(const lpddr4_privatedata * pd, lpddr4_debuginfo * debuginfo) { uint32_t result = 0U; bool errorfound = false; /* Calling Sanity Function to verify the input variables */ result = lpddr4_getdebuginitinfosf(pd, debuginfo); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; lpddr4_seterrors(ctlregbase, debuginfo, &errorfound); /* Function to setup Snap for OBS registers */ lpddr4_setsettings(ctlregbase, errorfound); /* Function to check for Rx offset error */ lpddr4_setrxoffseterror(ctlregbase, debuginfo, &errorfound); /* Function Check various levelling errors */ errorfound = lpddr4_checklvlerrors(pd, debuginfo, errorfound); } if (errorfound == true) { result = (uint32_t) EPROTO; } return result; } static void readpdwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, uint32_t * cycles) { /* Read the appropriate register, based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { *cycles = CPS_FLD_READ(LPDDR4__LPI_PD_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_PD_WAKEUP_F0__REG))); } else if (*fspnum == LPDDR4_FSP_1) { *cycles = CPS_FLD_READ(LPDDR4__LPI_PD_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_PD_WAKEUP_F1__REG))); } else { /* Default register (sanity function already confirmed the variable value) */ *cycles = CPS_FLD_READ(LPDDR4__LPI_PD_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_PD_WAKEUP_F2__REG))); } } static void readsrshortwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, uint32_t * cycles) { /* Read the appropriate register, based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_SHORT_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_SHORT_WAKEUP_F0__REG))); } else if (*fspnum == LPDDR4_FSP_1) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_SHORT_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_SHORT_WAKEUP_F1__REG))); } else { /* Default register (sanity function already confirmed the variable value) */ *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_SHORT_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_SHORT_WAKEUP_F2__REG))); } } static void readsrlongwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, uint32_t * cycles) { /* Read the appropriate register, based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_LONG_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_WAKEUP_F0__REG))); } else if (*fspnum == LPDDR4_FSP_1) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_LONG_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_WAKEUP_F1__REG))); } else { /* Default register (sanity function already confirmed the variable value) */ *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_LONG_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_WAKEUP_F2__REG))); } } static void readsrlonggatewakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, uint32_t * cycles) { /* Read the appropriate register, based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F0__REG))); } else if (*fspnum == LPDDR4_FSP_1) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F1__REG))); } else { /* Default register (sanity function already confirmed the variable value) */ *cycles = CPS_FLD_READ(LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F2__REG))); } } static void readsrdpshortwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, uint32_t * cycles) { /* Read the appropriate register, based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SRPD_SHORT_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F0__REG))); } else if (*fspnum == LPDDR4_FSP_1) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SRPD_SHORT_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F1__REG))); } else { /* Default register (sanity function already confirmed the variable value) */ *cycles = CPS_FLD_READ(LPDDR4__LPI_SRPD_SHORT_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F2__REG))); } } static void readsrdplongwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, uint32_t * cycles) { /* Read the appropriate register, based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SRPD_LONG_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F0__REG))); } else if (*fspnum == LPDDR4_FSP_1) { *cycles = CPS_FLD_READ(LPDDR4__LPI_SRPD_LONG_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F1__REG))); } else { /* Default register (sanity function already confirmed the variable value) */ *cycles = CPS_FLD_READ(LPDDR4__LPI_SRPD_LONG_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F2__REG))); } } static void readsrdplonggatewakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, uint32_t * cycles) { /* Read the appropriate register, based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { *cycles = CPS_FLD_READ (LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F0__REG))); } else if (*fspnum == LPDDR4_FSP_1) { *cycles = CPS_FLD_READ (LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F1__REG))); } else { /* Default register (sanity function already confirmed the variable value) */ *cycles = CPS_FLD_READ (LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F2__REG))); } } static void lpddr4_readlpiwakeuptime(lpddr4_ctlregs * ctlregbase, const lpddr4_lpiwakeupparam * lpiwakeupparam, const lpddr4_ctlfspnum * fspnum, uint32_t * cycles) { /* Iterate through each of the Wake up parameter type */ if (*lpiwakeupparam == LPDDR4_LPI_PD_WAKEUP_FN) { /* Calling appropriate function for register read */ readpdwakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SR_SHORT_WAKEUP_FN) { readsrshortwakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SR_LONG_WAKEUP_FN) { readsrlongwakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SR_LONG_MCCLK_GATE_WAKEUP_FN) { readsrlonggatewakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SRPD_SHORT_WAKEUP_FN) { readsrdpshortwakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SRPD_LONG_WAKEUP_FN) { readsrdplongwakeup(fspnum, ctlregbase, cycles); } else { /* Default function (sanity function already confirmed the variable value) */ readsrdplonggatewakeup(fspnum, ctlregbase, cycles); } } uint32_t lpddr4_getlpiwakeuptime(const lpddr4_privatedata * pd, const lpddr4_lpiwakeupparam * lpiwakeupparam, const lpddr4_ctlfspnum * fspnum, uint32_t * cycles) { uint32_t result = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_getlpiwakeuptimesf(pd, lpiwakeupparam, fspnum, cycles); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; lpddr4_readlpiwakeuptime(ctlregbase, lpiwakeupparam, fspnum, cycles); } return result; } static void writepdwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, const uint32_t * cycles) { uint32_t regval = 0U; /* Write to appropriate register ,based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { regval = CPS_FLD_WRITE(LPDDR4__LPI_PD_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_PD_WAKEUP_F0__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__LPI_PD_WAKEUP_F0__REG), regval); } else if (*fspnum == LPDDR4_FSP_1) { regval = CPS_FLD_WRITE(LPDDR4__LPI_PD_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_PD_WAKEUP_F1__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__LPI_PD_WAKEUP_F1__REG), regval); } else { /* Default register (sanity function already confirmed the variable value) */ regval = CPS_FLD_WRITE(LPDDR4__LPI_PD_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_PD_WAKEUP_F2__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__LPI_PD_WAKEUP_F2__REG), regval); } } static void writesrshortwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, const uint32_t * cycles) { uint32_t regval = 0U; /* Write to appropriate register ,based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_SHORT_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_SHORT_WAKEUP_F0__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase->LPDDR4__LPI_SR_SHORT_WAKEUP_F0__REG), regval); } else if (*fspnum == LPDDR4_FSP_1) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_SHORT_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_SHORT_WAKEUP_F1__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase->LPDDR4__LPI_SR_SHORT_WAKEUP_F1__REG), regval); } else { /* Default register (sanity function already confirmed the variable value) */ regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_SHORT_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_SHORT_WAKEUP_F2__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase->LPDDR4__LPI_SR_SHORT_WAKEUP_F2__REG), regval); } } static void writesrlongwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, const uint32_t * cycles) { uint32_t regval = 0U; /* Write to appropriate register ,based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_LONG_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_WAKEUP_F0__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__LPI_SR_LONG_WAKEUP_F0__REG), regval); } else if (*fspnum == LPDDR4_FSP_1) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_LONG_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_WAKEUP_F1__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__LPI_SR_LONG_WAKEUP_F1__REG), regval); } else { /* Default register (sanity function already confirmed the variable value) */ regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_LONG_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_WAKEUP_F2__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__LPI_SR_LONG_WAKEUP_F2__REG), regval); } } static void writesrlonggatewakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, const uint32_t * cycles) { uint32_t regval = 0U; /* Write to appropriate register ,based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F0__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F0__REG), regval); } else if (*fspnum == LPDDR4_FSP_1) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F1__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F1__REG), regval); } else { /* Default register (sanity function already confirmed the variable value) */ regval = CPS_FLD_WRITE(LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F2__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SR_LONG_MCCLK_GATE_WAKEUP_F2__REG), regval); } } static void writesrdpshortwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, const uint32_t * cycles) { uint32_t regval = 0U; /* Write to appropriate register ,based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SRPD_SHORT_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F0__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F0__REG), regval); } else if (*fspnum == LPDDR4_FSP_1) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SRPD_SHORT_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F1__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F1__REG), regval); } else { /* Default register (sanity function already confirmed the variable value) */ regval = CPS_FLD_WRITE(LPDDR4__LPI_SRPD_SHORT_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F2__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_SHORT_WAKEUP_F2__REG), regval); } } static void writesrdplongwakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, const uint32_t * cycles) { uint32_t regval = 0U; /* Write to appropriate register ,based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SRPD_LONG_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F0__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F0__REG), regval); } else if (*fspnum == LPDDR4_FSP_1) { regval = CPS_FLD_WRITE(LPDDR4__LPI_SRPD_LONG_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F1__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F1__REG), regval); } else { /* Default register (sanity function already confirmed the variable value) */ regval = CPS_FLD_WRITE(LPDDR4__LPI_SRPD_LONG_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F2__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_WAKEUP_F2__REG), regval); } } static void writesrdplonggatewakeup(const lpddr4_ctlfspnum * fspnum, lpddr4_ctlregs * ctlregbase, const uint32_t * cycles) { uint32_t regval = 0U; /* Write to appropriate register ,based on user given frequency. */ if (*fspnum == LPDDR4_FSP_0) { regval = CPS_FLD_WRITE (LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F0__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F0__REG), regval); } else if (*fspnum == LPDDR4_FSP_1) { regval = CPS_FLD_WRITE (LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F1__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F1__REG), regval); } else { /* Default register (sanity function already confirmed the variable value) */ regval = CPS_FLD_WRITE (LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F2__REG)), *cycles); CPS_REG_WRITE(& (ctlregbase-> LPDDR4__LPI_SRPD_LONG_MCCLK_GATE_WAKEUP_F2__REG), regval); } } static void lpddr4_writelpiwakeuptime(lpddr4_ctlregs * ctlregbase, const lpddr4_lpiwakeupparam * lpiwakeupparam, const lpddr4_ctlfspnum * fspnum, const uint32_t * cycles) { /* Iterate through each of the Wake up parameter type */ if (*lpiwakeupparam == LPDDR4_LPI_PD_WAKEUP_FN) { /* Calling appropriate function for register write */ writepdwakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SR_SHORT_WAKEUP_FN) { writesrshortwakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SR_LONG_WAKEUP_FN) { writesrlongwakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SR_LONG_MCCLK_GATE_WAKEUP_FN) { writesrlonggatewakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SRPD_SHORT_WAKEUP_FN) { writesrdpshortwakeup(fspnum, ctlregbase, cycles); } else if (*lpiwakeupparam == LPDDR4_LPI_SRPD_LONG_WAKEUP_FN) { writesrdplongwakeup(fspnum, ctlregbase, cycles); } else { /* Default function (sanity function already confirmed the variable value) */ writesrdplonggatewakeup(fspnum, ctlregbase, cycles); } } uint32_t lpddr4_setlpiwakeuptime(const lpddr4_privatedata * pd, const lpddr4_lpiwakeupparam * lpiwakeupparam, const lpddr4_ctlfspnum * fspnum, const uint32_t * cycles) { uint32_t result = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_setlpiwakeuptimesf(pd, lpiwakeupparam, fspnum, cycles); if (result == (uint32_t) CDN_EOK) { /* Return if the user given value is higher than the field width */ if (*cycles > NIBBLE_MASK) { result = EINVAL; } } if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; lpddr4_writelpiwakeuptime(ctlregbase, lpiwakeupparam, fspnum, cycles); } return result; } uint32_t lpddr4_geteccenable(const lpddr4_privatedata * pd, lpddr4_eccenable * eccparam) { uint32_t result = 0U; uint32_t fldval = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_geteccenablesf(pd, eccparam); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Reading the ECC_Enable field from the register. */ fldval = CPS_FLD_READ(LPDDR4__ECC_ENABLE__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__ECC_ENABLE__REG))); switch (fldval) { case 3: *eccparam = LPDDR4_ECC_ERR_DETECT_CORRECT; break; case 2: *eccparam = LPDDR4_ECC_ERR_DETECT; break; case 1: *eccparam = LPDDR4_ECC_ENABLED; break; default: /* Default ECC (Sanity function already confirmed the value to be in expected range.) */ *eccparam = LPDDR4_ECC_DISABLED; break; } } return result; } uint32_t lpddr4_seteccenable(const lpddr4_privatedata * pd, const lpddr4_eccenable * eccparam) { uint32_t result = 0U; uint32_t regval = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_seteccenablesf(pd, eccparam); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Updating the ECC_Enable field based on the user given value. */ regval = CPS_FLD_WRITE(LPDDR4__ECC_ENABLE__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__ECC_ENABLE__REG)), *eccparam); CPS_REG_WRITE(&(ctlregbase->LPDDR4__ECC_ENABLE__REG), regval); } return result; } uint32_t lpddr4_getreducmode(const lpddr4_privatedata * pd, lpddr4_reducmode * mode) { uint32_t result = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_getreducmodesf(pd, mode); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Read the value of reduc parameter. */ if (CPS_FLD_READ (LPDDR4__REDUC__FLD, CPS_REG_READ(&(ctlregbase->LPDDR4__REDUC__REG))) == 0U) { *mode = LPDDR4_REDUC_ON; } else { *mode = LPDDR4_REDUC_OFF; } } return result; } uint32_t lpddr4_setreducmode(const lpddr4_privatedata * pd, const lpddr4_reducmode * mode) { uint32_t result = 0U; uint32_t regval = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_setreducmodesf(pd, mode); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Setting to enable Half data path. */ regval = CPS_FLD_WRITE(LPDDR4__REDUC__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__REDUC__REG)), *mode); CPS_REG_WRITE(&(ctlregbase->LPDDR4__REDUC__REG), regval); } return result; } uint32_t lpddr4_getdbireadmode(const lpddr4_privatedata * pd, bool * on_off) { uint32_t result = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_getdbireadmodesf(pd, on_off); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Reading the field value from the register. */ if (CPS_FLD_READ (LPDDR4__RD_DBI_EN__FLD, CPS_REG_READ(&(ctlregbase->LPDDR4__RD_DBI_EN__REG))) == 0U) { *on_off = false; } else { *on_off = true; } } return result; } uint32_t lpddr4_getdbiwritemode(const lpddr4_privatedata * pd, bool * on_off) { uint32_t result = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_getdbireadmodesf(pd, on_off); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Reading the field value from the register. */ if (CPS_FLD_READ (LPDDR4__WR_DBI_EN__FLD, CPS_REG_READ(&(ctlregbase->LPDDR4__WR_DBI_EN__REG))) == 0U) { *on_off = false; } else { *on_off = true; } } return result; } uint32_t lpddr4_setdbimode(const lpddr4_privatedata * pd, const lpddr4_dbimode * mode) { uint32_t result = 0U; uint32_t regval = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_setdbimodesf(pd, mode); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Updating the appropriate field value based on the user given mode */ if (*mode == LPDDR4_DBI_RD_ON) { regval = CPS_FLD_WRITE(LPDDR4__RD_DBI_EN__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__RD_DBI_EN__REG)), 1U); } else if (*mode == LPDDR4_DBI_RD_OFF) { regval = CPS_FLD_WRITE(LPDDR4__RD_DBI_EN__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__RD_DBI_EN__REG)), 0U); } else if (*mode == LPDDR4_DBI_WR_ON) { regval = CPS_FLD_WRITE(LPDDR4__WR_DBI_EN__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__WR_DBI_EN__REG)), 1U); } else { /* Default field (Sanity function already confirmed the value to be in expected range.) */ regval = CPS_FLD_WRITE(LPDDR4__WR_DBI_EN__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__WR_DBI_EN__REG)), 0U); } CPS_REG_WRITE(&(ctlregbase->LPDDR4__RD_DBI_EN__REG), regval); } return result; } uint32_t lpddr4_getrefreshrate(const lpddr4_privatedata * pd, const lpddr4_ctlfspnum * fspnum, uint32_t * cycles) { uint32_t result = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_getrefreshratesf(pd, fspnum, cycles); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Selecting the appropriate register for the user requested Frequency */ switch (*fspnum) { case LPDDR4_FSP_2: *cycles = CPS_FLD_READ(LPDDR4__TREF_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__TREF_F2__REG))); break; case LPDDR4_FSP_1: *cycles = CPS_FLD_READ(LPDDR4__TREF_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__TREF_F1__REG))); break; default: /* FSP_0 is considered as the default (sanity check already confirmed it as valid FSP) */ *cycles = CPS_FLD_READ(LPDDR4__TREF_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__TREF_F0__REG))); break; } } return result; } uint32_t lpddr4_setrefreshrate(const lpddr4_privatedata * pd, const lpddr4_ctlfspnum * fspnum, const uint32_t * cycles) { uint32_t result = 0U; uint32_t regval = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_setrefreshratesf(pd, fspnum, cycles); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Selecting the appropriate register for the user requested Frequency */ switch (*fspnum) { case LPDDR4_FSP_2: regval = CPS_FLD_WRITE(LPDDR4__TREF_F2__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__TREF_F2__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__TREF_F2__REG), regval); break; case LPDDR4_FSP_1: regval = CPS_FLD_WRITE(LPDDR4__TREF_F1__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__TREF_F1__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__TREF_F1__REG), regval); break; default: /* FSP_0 is considered as the default (sanity check already confirmed it as valid FSP) */ regval = CPS_FLD_WRITE(LPDDR4__TREF_F0__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__TREF_F0__REG)), *cycles); CPS_REG_WRITE(&(ctlregbase->LPDDR4__TREF_F0__REG), regval); break; } } return result; } uint32_t lpddr4_refreshperchipselect(const lpddr4_privatedata * pd, const uint32_t trefinterval) { uint32_t result = 0U; uint32_t regval = 0U; /* Calling Sanity Function to verify the input variables */ result = lpddr4_refreshperchipselectsf(pd); if (result == (uint32_t) CDN_EOK) { lpddr4_ctlregs *ctlregbase = (lpddr4_ctlregs *) pd->ctlbase; /* Setting tref_interval parameter to enable/disable Refresh per chip select. */ regval = CPS_FLD_WRITE(LPDDR4__TREF_INTERVAL__FLD, CPS_REG_READ(& (ctlregbase-> LPDDR4__TREF_INTERVAL__REG)), trefinterval); CPS_REG_WRITE(&(ctlregbase->LPDDR4__TREF_INTERVAL__REG), regval); } return result; }