diff mbox series

[6/6] clk: imx8mp: inform CCF of maximum frequency of clocks

Message ID 20241219-imx8m-clk-v1-6-cfaffa087da6@pengutronix.de (mailing list archive)
State Under Review
Headers show
Series arm64: dts: freescale: imx8mp-skov: switch to nominal drive mode | expand

Commit Message

Ahmad Fatoum Dec. 19, 2024, 7:27 a.m. UTC
The IMX8MPCEC datasheet lists maximum frequencies allowed for different
modules. Some of these limits are universal, but some depend on
whether the SoC is operating in nominal or in overdrive mode.

The imx8mp.dtsi currently assumes overdrive mode and configures some
clocks in accordance with this. Boards wishing to make use of nominal
mode will need to override some of the clock rates manually.

As operating the clocks outside of their allowed range can lead to
difficult to debug issues, it makes sense to register the maximum rates
allowed in the driver, so the CCF can take them into account.

Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 drivers/clk/imx/clk-imx8mp.c | 147 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 147 insertions(+)

Comments

Peng Fan Dec. 20, 2024, 6:18 a.m. UTC | #1
On Thu, Dec 19, 2024 at 08:27:37AM +0100, Ahmad Fatoum wrote:
>The IMX8MPCEC datasheet lists maximum frequencies allowed for different
>modules. Some of these limits are universal, but some depend on
>whether the SoC is operating in nominal or in overdrive mode.
>
>The imx8mp.dtsi currently assumes overdrive mode and configures some
>clocks in accordance with this. Boards wishing to make use of nominal
>mode will need to override some of the clock rates manually.
>
>As operating the clocks outside of their allowed range can lead to
>difficult to debug issues, it makes sense to register the maximum rates
>allowed in the driver, so the CCF can take them into account.
>
>Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
>---
> drivers/clk/imx/clk-imx8mp.c | 147 +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 147 insertions(+)
>
>diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
>index 516dbd170c8a..3b06990b73ad 100644
>--- a/drivers/clk/imx/clk-imx8mp.c
>+++ b/drivers/clk/imx/clk-imx8mp.c
>@@ -8,6 +8,7 @@
> #include <linux/err.h>
> #include <linux/io.h>
> #include <linux/module.h>
>+#include <linux/units.h>
> #include <linux/of_address.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
>@@ -405,6 +406,145 @@ static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_
> static struct clk_hw **hws;
> static struct clk_hw_onecell_data *clk_hw_data;
> 
>+struct imx8mp_clock_constraints {
>+	int clkid;
>+	u32 maxrate;
>+};
>+
>+/*
>+ * Below tables are taken from IMX8MPCEC Rev. 2.1, 07/2023
>+ * Table 13. Maximum frequency of modules.
>+ * Probable typos fixed are marked with a comment.
>+ */
>+static const struct imx8mp_clock_constraints imx8mp_clock_common_constraints[] = {
>+	{ IMX8MP_CLK_A53_DIV,             1000 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ENET_AXI,             266666667 }, /* Datasheet claims 266MHz */
>+	{ IMX8MP_CLK_NAND_USDHC_BUS,       266666667 }, /* Datasheet claims 266MHz */
>+	{ IMX8MP_CLK_MEDIA_APB,            200 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_HDMI_APB,             133333333 }, /* Datasheet claims 133MHz */
>+	{ IMX8MP_CLK_ML_AXI,               800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_AHB,                  133333333 },
>+	{ IMX8MP_CLK_IPG_ROOT,              66666667 },
>+	{ IMX8MP_CLK_AUDIO_AHB,            400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_DISP2_PIX,      170 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_DRAM_ALT,             666666667 },
>+	{ IMX8MP_CLK_DRAM_APB,             200 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_CAN1,                  80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_CAN2,                  80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_PCIE_AUX,              10 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_I2C5,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_I2C6,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_SAI1,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_SAI2,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_SAI3,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_SAI5,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_SAI6,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_ENET_QOS,             125 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ENET_QOS_TIMER,       200 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ENET_REF,             125 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ENET_TIMER,           125 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ENET_PHY_REF,         125 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_NAND,                 500 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_QSPI,                 400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_USDHC1,               400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_USDHC2,               400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_I2C1,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_I2C2,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_I2C3,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_I2C4,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_UART1,                 80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_UART2,                 80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_UART3,                 80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_UART4,                 80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ECSPI1,                80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ECSPI2,                80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_PWM1,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_PWM2,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_PWM3,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_PWM4,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_GPT1,                 100 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPT2,                 100 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPT3,                 100 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPT4,                 100 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPT5,                 100 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPT6,                 100 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_WDOG,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_IPP_DO_CLKO1,         200 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_IPP_DO_CLKO2,         200 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_HDMI_REF_266M,        266 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_USDHC3,               400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_MIPI_PHY1_REF,  300 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_DISP1_PIX,      250 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_CAM2_PIX,       277 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_LDB,            595 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE, 200 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ECSPI3,                80 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_PDM,                  200 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_SAI7,                  66666667 }, /* Datasheet claims 66MHz */
>+	{ IMX8MP_CLK_MAIN_AXI,             400 * HZ_PER_MHZ },
>+	{ /* sentinel */ },
>+};
>+
>+static const struct imx8mp_clock_constraints imx8mp_clock_nominal_constraints[] = {
>+	{ IMX8MP_CLK_M7_CORE,           600 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ML_CORE,           800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU3D_CORE,        800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU3D_SHADER_CORE, 800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU2D_CORE,        800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_AUDIO_AXI_SRC,     600 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_HSIO_AXI,          400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_ISP,         400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_VPU_BUS,           600 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_AXI,         400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_HDMI_AXI,          400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU_AXI,           600 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU_AHB,           300 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_NOC,               800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_NOC_IO,            600 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ML_AHB,            300 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_VPU_G1,            600 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_VPU_G2,            500 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_CAM1_PIX,    400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_VPU_VC8000E,       400 * HZ_PER_MHZ }, /* Datasheet claims 500MHz */
>+	{ IMX8MP_CLK_DRAM_CORE,         800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GIC,               400 * HZ_PER_MHZ },
>+	{ /* sentinel */ },
>+};
>+
>+static const struct imx8mp_clock_constraints imx8mp_clock_overdrive_constraints[] = {
>+	{ IMX8MP_CLK_M7_CORE,            800 * HZ_PER_MHZ},
>+	{ IMX8MP_CLK_ML_CORE,           1000 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU3D_CORE,        1000 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU3D_SHADER_CORE, 1000 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU2D_CORE,        1000 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_AUDIO_AXI_SRC,      800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_HSIO_AXI,           500 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_ISP,          500 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_VPU_BUS,            800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_AXI,          500 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_HDMI_AXI,           500 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU_AXI,            800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GPU_AHB,            400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_NOC,               1000 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_NOC_IO,             800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_ML_AHB,             400 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_VPU_G1,             800 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_VPU_G2,             700 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_MEDIA_CAM1_PIX,     500 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_VPU_VC8000E,        500 * HZ_PER_MHZ }, /* Datasheet claims 400MHz */
>+	{ IMX8MP_CLK_DRAM_CORE,         1000 * HZ_PER_MHZ },
>+	{ IMX8MP_CLK_GIC,                500 * HZ_PER_MHZ },
>+	{ /* sentinel */ },
>+};
>+
>+static void imx8mp_clocks_apply_constraints(const struct imx8mp_clock_constraints constraints[])
>+{
>+	const struct imx8mp_clock_constraints *constr;
>+
>+	for (constr = constraints; constr->clkid; constr++)
>+		clk_hw_set_rate_range(hws[constr->clkid], 0, constr->maxrate);
>+}
>+
> static int imx8mp_clocks_probe(struct platform_device *pdev)
> {
> 	struct device *dev = &pdev->dev;
>@@ -714,6 +854,13 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
> 
> 	imx_check_clk_hws(hws, IMX8MP_CLK_END);
> 
>+	imx8mp_clocks_apply_constraints(imx8mp_clock_common_constraints);
>+
>+	if (of_property_read_bool(np, "fsl,nominal-mode"))
>+		imx8mp_clocks_apply_constraints(imx8mp_clock_nominal_constraints);
>+	else if (of_property_read_bool(np, "fsl,overdrive-mode"))
>+		imx8mp_clocks_apply_constraints(imx8mp_clock_overdrive_constraints);

As I replied, a boot parameter should be better? the mode is a soc level mode,
not just clock controller.

Thanks,
Peng

>+
> 	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
> 	if (err < 0) {
> 		dev_err(dev, "failed to register hws for i.MX8MP\n");
>
>-- 
>2.39.5
>
Ahmad Fatoum Dec. 20, 2024, 6:30 a.m. UTC | #2
Hi Peng,

On 20.12.24 07:18, Peng Fan wrote:
> On Thu, Dec 19, 2024 at 08:27:37AM +0100, Ahmad Fatoum wrote:
>> The IMX8MPCEC datasheet lists maximum frequencies allowed for different
>> modules. Some of these limits are universal, but some depend on
>> whether the SoC is operating in nominal or in overdrive mode.
>>
>> The imx8mp.dtsi currently assumes overdrive mode and configures some
>> clocks in accordance with this. Boards wishing to make use of nominal
>> mode will need to override some of the clock rates manually.
>>
>> As operating the clocks outside of their allowed range can lead to
>> difficult to debug issues, it makes sense to register the maximum rates
>> allowed in the driver, so the CCF can take them into account.
>>
>> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>

>> +	imx8mp_clocks_apply_constraints(imx8mp_clock_common_constraints);
>> +
>> +	if (of_property_read_bool(np, "fsl,nominal-mode"))
>> +		imx8mp_clocks_apply_constraints(imx8mp_clock_nominal_constraints);
>> +	else if (of_property_read_bool(np, "fsl,overdrive-mode"))
>> +		imx8mp_clocks_apply_constraints(imx8mp_clock_overdrive_constraints);
> 
> As I replied, a boot parameter should be better? the mode is a soc level mode,
> not just clock controller.

I think it's counterproductive for a sanity check to be enforced via kernel
command-line.

The Skov board shouldn't run with overdrive frequencies and I prefer to encode
that in the same device tree, where I define the permissible VDD_SOC range
and configure the initial clock rates.

The mode is selected by the VDD_SOC voltage, but affects AFAICS only the clock
tree. IMO, the clock controller module is thus a natural place for the property.

Cheers,
Ahmad

> 
> Thanks,
> Peng
> 
>> +
>> 	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
>> 	if (err < 0) {
>> 		dev_err(dev, "failed to register hws for i.MX8MP\n");
>>
>> -- 
>> 2.39.5
>>
>
diff mbox series

Patch

diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index 516dbd170c8a..3b06990b73ad 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -8,6 +8,7 @@ 
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/units.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -405,6 +406,145 @@  static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_
 static struct clk_hw **hws;
 static struct clk_hw_onecell_data *clk_hw_data;
 
+struct imx8mp_clock_constraints {
+	int clkid;
+	u32 maxrate;
+};
+
+/*
+ * Below tables are taken from IMX8MPCEC Rev. 2.1, 07/2023
+ * Table 13. Maximum frequency of modules.
+ * Probable typos fixed are marked with a comment.
+ */
+static const struct imx8mp_clock_constraints imx8mp_clock_common_constraints[] = {
+	{ IMX8MP_CLK_A53_DIV,             1000 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ENET_AXI,             266666667 }, /* Datasheet claims 266MHz */
+	{ IMX8MP_CLK_NAND_USDHC_BUS,       266666667 }, /* Datasheet claims 266MHz */
+	{ IMX8MP_CLK_MEDIA_APB,            200 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_HDMI_APB,             133333333 }, /* Datasheet claims 133MHz */
+	{ IMX8MP_CLK_ML_AXI,               800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_AHB,                  133333333 },
+	{ IMX8MP_CLK_IPG_ROOT,              66666667 },
+	{ IMX8MP_CLK_AUDIO_AHB,            400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_DISP2_PIX,      170 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_DRAM_ALT,             666666667 },
+	{ IMX8MP_CLK_DRAM_APB,             200 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_CAN1,                  80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_CAN2,                  80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_PCIE_AUX,              10 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_I2C5,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_I2C6,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_SAI1,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_SAI2,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_SAI3,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_SAI5,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_SAI6,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_ENET_QOS,             125 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ENET_QOS_TIMER,       200 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ENET_REF,             125 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ENET_TIMER,           125 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ENET_PHY_REF,         125 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_NAND,                 500 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_QSPI,                 400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_USDHC1,               400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_USDHC2,               400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_I2C1,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_I2C2,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_I2C3,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_I2C4,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_UART1,                 80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_UART2,                 80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_UART3,                 80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_UART4,                 80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ECSPI1,                80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ECSPI2,                80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_PWM1,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_PWM2,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_PWM3,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_PWM4,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_GPT1,                 100 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPT2,                 100 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPT3,                 100 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPT4,                 100 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPT5,                 100 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPT6,                 100 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_WDOG,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_IPP_DO_CLKO1,         200 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_IPP_DO_CLKO2,         200 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_HDMI_REF_266M,        266 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_USDHC3,               400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_MIPI_PHY1_REF,  300 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_DISP1_PIX,      250 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_CAM2_PIX,       277 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_LDB,            595 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE, 200 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ECSPI3,                80 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_PDM,                  200 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_SAI7,                  66666667 }, /* Datasheet claims 66MHz */
+	{ IMX8MP_CLK_MAIN_AXI,             400 * HZ_PER_MHZ },
+	{ /* sentinel */ },
+};
+
+static const struct imx8mp_clock_constraints imx8mp_clock_nominal_constraints[] = {
+	{ IMX8MP_CLK_M7_CORE,           600 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ML_CORE,           800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU3D_CORE,        800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU3D_SHADER_CORE, 800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU2D_CORE,        800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_AUDIO_AXI_SRC,     600 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_HSIO_AXI,          400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_ISP,         400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_VPU_BUS,           600 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_AXI,         400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_HDMI_AXI,          400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU_AXI,           600 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU_AHB,           300 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_NOC,               800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_NOC_IO,            600 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ML_AHB,            300 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_VPU_G1,            600 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_VPU_G2,            500 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_CAM1_PIX,    400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_VPU_VC8000E,       400 * HZ_PER_MHZ }, /* Datasheet claims 500MHz */
+	{ IMX8MP_CLK_DRAM_CORE,         800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GIC,               400 * HZ_PER_MHZ },
+	{ /* sentinel */ },
+};
+
+static const struct imx8mp_clock_constraints imx8mp_clock_overdrive_constraints[] = {
+	{ IMX8MP_CLK_M7_CORE,            800 * HZ_PER_MHZ},
+	{ IMX8MP_CLK_ML_CORE,           1000 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU3D_CORE,        1000 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU3D_SHADER_CORE, 1000 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU2D_CORE,        1000 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_AUDIO_AXI_SRC,      800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_HSIO_AXI,           500 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_ISP,          500 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_VPU_BUS,            800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_AXI,          500 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_HDMI_AXI,           500 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU_AXI,            800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GPU_AHB,            400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_NOC,               1000 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_NOC_IO,             800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_ML_AHB,             400 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_VPU_G1,             800 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_VPU_G2,             700 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_MEDIA_CAM1_PIX,     500 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_VPU_VC8000E,        500 * HZ_PER_MHZ }, /* Datasheet claims 400MHz */
+	{ IMX8MP_CLK_DRAM_CORE,         1000 * HZ_PER_MHZ },
+	{ IMX8MP_CLK_GIC,                500 * HZ_PER_MHZ },
+	{ /* sentinel */ },
+};
+
+static void imx8mp_clocks_apply_constraints(const struct imx8mp_clock_constraints constraints[])
+{
+	const struct imx8mp_clock_constraints *constr;
+
+	for (constr = constraints; constr->clkid; constr++)
+		clk_hw_set_rate_range(hws[constr->clkid], 0, constr->maxrate);
+}
+
 static int imx8mp_clocks_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -714,6 +854,13 @@  static int imx8mp_clocks_probe(struct platform_device *pdev)
 
 	imx_check_clk_hws(hws, IMX8MP_CLK_END);
 
+	imx8mp_clocks_apply_constraints(imx8mp_clock_common_constraints);
+
+	if (of_property_read_bool(np, "fsl,nominal-mode"))
+		imx8mp_clocks_apply_constraints(imx8mp_clock_nominal_constraints);
+	else if (of_property_read_bool(np, "fsl,overdrive-mode"))
+		imx8mp_clocks_apply_constraints(imx8mp_clock_overdrive_constraints);
+
 	err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
 	if (err < 0) {
 		dev_err(dev, "failed to register hws for i.MX8MP\n");