static int imx8m_ddrc_init_freq_info()

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;
}