mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-25 04:23:46 +00:00
3bb3f266ee
The J721E DDR subsystem comprises DDR controller, DDR PHY and wrapper logic to integrate these blocks in the device. The DDR subsystem is used to provide an interface to external SDRAM devices which can be utilized for storing program or data. Introduce support for the DDR controller and DDR phy within the DDR subsystem. Signed-off-by: Kevin Scholz <k-scholz@ti.com Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
2119 lines
61 KiB
C
2119 lines
61 KiB
C
// 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;
|
||
}
|