in imx8m-ddrc.c [283:327]
static int imx8m_ddrc_init_freq_info(struct device *dev)
{
struct imx8m_ddrc *priv = dev_get_drvdata(dev);
struct arm_smccc_res res;
int index;
/* An error here means DDR DVFS API not supported by firmware */
arm_smccc_smc(IMX_SIP_DDR_DVFS, IMX_SIP_DDR_DVFS_GET_FREQ_COUNT,
0, 0, 0, 0, 0, 0, &res);
priv->freq_count = res.a0;
if (priv->freq_count <= 0 ||
priv->freq_count > IMX8M_DDRC_MAX_FREQ_COUNT)
return -ENODEV;
for (index = 0; index < priv->freq_count; ++index) {
struct imx8m_ddrc_freq *freq = &priv->freq_table[index];
arm_smccc_smc(IMX_SIP_DDR_DVFS, IMX_SIP_DDR_DVFS_GET_FREQ_INFO,
index, 0, 0, 0, 0, 0, &res);
/* Result should be strictly positive */
if ((long)res.a0 <= 0)
return -ENODEV;
freq->rate = res.a0;
freq->smcarg = index;
freq->dram_core_parent_index = res.a1;
freq->dram_alt_parent_index = res.a2;
freq->dram_apb_parent_index = res.a3;
/* dram_core has 2 options: dram_pll or dram_alt_root */
if (freq->dram_core_parent_index != 1 &&
freq->dram_core_parent_index != 2)
return -ENODEV;
/* dram_apb and dram_alt have exactly 8 possible parents */
if (freq->dram_alt_parent_index > 8 ||
freq->dram_apb_parent_index > 8)
return -ENODEV;
/* dram_core from alt requires explicit dram_alt parent */
if (freq->dram_core_parent_index == 2 &&
freq->dram_alt_parent_index == 0)
return -ENODEV;
}
return 0;
}