Skip to content

Commit 06a61b5

Browse files
a3fabelvesa
authored andcommitted
clk: imx8mp: inform CCF of maximum frequency of clocks
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. Reviewed-by: Peng Fan <peng.fan@nxp.com> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.kernel.org/r/20250218-imx8m-clk-v4-6-b7697dc2dcd0@pengutronix.de Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
1 parent d5992f1 commit 06a61b5

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

drivers/clk/imx/clk-imx8mp.c

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/err.h>
99
#include <linux/io.h>
1010
#include <linux/module.h>
11+
#include <linux/units.h>
1112
#include <linux/of_address.h>
1213
#include <linux/platform_device.h>
1314
#include <linux/slab.h>
@@ -406,11 +407,151 @@ static const char * const imx8mp_clkout_sels[] = {"audio_pll1_out", "audio_pll2_
406407
static struct clk_hw **hws;
407408
static struct clk_hw_onecell_data *clk_hw_data;
408409

410+
struct imx8mp_clock_constraints {
411+
unsigned int clkid;
412+
u32 maxrate;
413+
};
414+
415+
/*
416+
* Below tables are taken from IMX8MPCEC Rev. 2.1, 07/2023
417+
* Table 13. Maximum frequency of modules.
418+
* Probable typos fixed are marked with a comment.
419+
*/
420+
static const struct imx8mp_clock_constraints imx8mp_clock_common_constraints[] = {
421+
{ IMX8MP_CLK_A53_DIV, 1000 * HZ_PER_MHZ },
422+
{ IMX8MP_CLK_ENET_AXI, 266666667 }, /* Datasheet claims 266MHz */
423+
{ IMX8MP_CLK_NAND_USDHC_BUS, 266666667 }, /* Datasheet claims 266MHz */
424+
{ IMX8MP_CLK_MEDIA_APB, 200 * HZ_PER_MHZ },
425+
{ IMX8MP_CLK_HDMI_APB, 133333333 }, /* Datasheet claims 133MHz */
426+
{ IMX8MP_CLK_ML_AXI, 800 * HZ_PER_MHZ },
427+
{ IMX8MP_CLK_AHB, 133333333 },
428+
{ IMX8MP_CLK_IPG_ROOT, 66666667 },
429+
{ IMX8MP_CLK_AUDIO_AHB, 400 * HZ_PER_MHZ },
430+
{ IMX8MP_CLK_MEDIA_DISP2_PIX, 170 * HZ_PER_MHZ },
431+
{ IMX8MP_CLK_DRAM_ALT, 666666667 },
432+
{ IMX8MP_CLK_DRAM_APB, 200 * HZ_PER_MHZ },
433+
{ IMX8MP_CLK_CAN1, 80 * HZ_PER_MHZ },
434+
{ IMX8MP_CLK_CAN2, 80 * HZ_PER_MHZ },
435+
{ IMX8MP_CLK_PCIE_AUX, 10 * HZ_PER_MHZ },
436+
{ IMX8MP_CLK_I2C5, 66666667 }, /* Datasheet claims 66MHz */
437+
{ IMX8MP_CLK_I2C6, 66666667 }, /* Datasheet claims 66MHz */
438+
{ IMX8MP_CLK_SAI1, 66666667 }, /* Datasheet claims 66MHz */
439+
{ IMX8MP_CLK_SAI2, 66666667 }, /* Datasheet claims 66MHz */
440+
{ IMX8MP_CLK_SAI3, 66666667 }, /* Datasheet claims 66MHz */
441+
{ IMX8MP_CLK_SAI5, 66666667 }, /* Datasheet claims 66MHz */
442+
{ IMX8MP_CLK_SAI6, 66666667 }, /* Datasheet claims 66MHz */
443+
{ IMX8MP_CLK_ENET_QOS, 125 * HZ_PER_MHZ },
444+
{ IMX8MP_CLK_ENET_QOS_TIMER, 200 * HZ_PER_MHZ },
445+
{ IMX8MP_CLK_ENET_REF, 125 * HZ_PER_MHZ },
446+
{ IMX8MP_CLK_ENET_TIMER, 125 * HZ_PER_MHZ },
447+
{ IMX8MP_CLK_ENET_PHY_REF, 125 * HZ_PER_MHZ },
448+
{ IMX8MP_CLK_NAND, 500 * HZ_PER_MHZ },
449+
{ IMX8MP_CLK_QSPI, 400 * HZ_PER_MHZ },
450+
{ IMX8MP_CLK_USDHC1, 400 * HZ_PER_MHZ },
451+
{ IMX8MP_CLK_USDHC2, 400 * HZ_PER_MHZ },
452+
{ IMX8MP_CLK_I2C1, 66666667 }, /* Datasheet claims 66MHz */
453+
{ IMX8MP_CLK_I2C2, 66666667 }, /* Datasheet claims 66MHz */
454+
{ IMX8MP_CLK_I2C3, 66666667 }, /* Datasheet claims 66MHz */
455+
{ IMX8MP_CLK_I2C4, 66666667 }, /* Datasheet claims 66MHz */
456+
{ IMX8MP_CLK_UART1, 80 * HZ_PER_MHZ },
457+
{ IMX8MP_CLK_UART2, 80 * HZ_PER_MHZ },
458+
{ IMX8MP_CLK_UART3, 80 * HZ_PER_MHZ },
459+
{ IMX8MP_CLK_UART4, 80 * HZ_PER_MHZ },
460+
{ IMX8MP_CLK_ECSPI1, 80 * HZ_PER_MHZ },
461+
{ IMX8MP_CLK_ECSPI2, 80 * HZ_PER_MHZ },
462+
{ IMX8MP_CLK_PWM1, 66666667 }, /* Datasheet claims 66MHz */
463+
{ IMX8MP_CLK_PWM2, 66666667 }, /* Datasheet claims 66MHz */
464+
{ IMX8MP_CLK_PWM3, 66666667 }, /* Datasheet claims 66MHz */
465+
{ IMX8MP_CLK_PWM4, 66666667 }, /* Datasheet claims 66MHz */
466+
{ IMX8MP_CLK_GPT1, 100 * HZ_PER_MHZ },
467+
{ IMX8MP_CLK_GPT2, 100 * HZ_PER_MHZ },
468+
{ IMX8MP_CLK_GPT3, 100 * HZ_PER_MHZ },
469+
{ IMX8MP_CLK_GPT4, 100 * HZ_PER_MHZ },
470+
{ IMX8MP_CLK_GPT5, 100 * HZ_PER_MHZ },
471+
{ IMX8MP_CLK_GPT6, 100 * HZ_PER_MHZ },
472+
{ IMX8MP_CLK_WDOG, 66666667 }, /* Datasheet claims 66MHz */
473+
{ IMX8MP_CLK_IPP_DO_CLKO1, 200 * HZ_PER_MHZ },
474+
{ IMX8MP_CLK_IPP_DO_CLKO2, 200 * HZ_PER_MHZ },
475+
{ IMX8MP_CLK_HDMI_REF_266M, 266 * HZ_PER_MHZ },
476+
{ IMX8MP_CLK_USDHC3, 400 * HZ_PER_MHZ },
477+
{ IMX8MP_CLK_MEDIA_MIPI_PHY1_REF, 300 * HZ_PER_MHZ },
478+
{ IMX8MP_CLK_MEDIA_DISP1_PIX, 250 * HZ_PER_MHZ },
479+
{ IMX8MP_CLK_MEDIA_CAM2_PIX, 277 * HZ_PER_MHZ },
480+
{ IMX8MP_CLK_MEDIA_LDB, 595 * HZ_PER_MHZ },
481+
{ IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE, 200 * HZ_PER_MHZ },
482+
{ IMX8MP_CLK_ECSPI3, 80 * HZ_PER_MHZ },
483+
{ IMX8MP_CLK_PDM, 200 * HZ_PER_MHZ },
484+
{ IMX8MP_CLK_SAI7, 66666667 }, /* Datasheet claims 66MHz */
485+
{ IMX8MP_CLK_MAIN_AXI, 400 * HZ_PER_MHZ },
486+
{ /* Sentinel */ }
487+
};
488+
489+
static const struct imx8mp_clock_constraints imx8mp_clock_nominal_constraints[] = {
490+
{ IMX8MP_CLK_M7_CORE, 600 * HZ_PER_MHZ },
491+
{ IMX8MP_CLK_ML_CORE, 800 * HZ_PER_MHZ },
492+
{ IMX8MP_CLK_GPU3D_CORE, 800 * HZ_PER_MHZ },
493+
{ IMX8MP_CLK_GPU3D_SHADER_CORE, 800 * HZ_PER_MHZ },
494+
{ IMX8MP_CLK_GPU2D_CORE, 800 * HZ_PER_MHZ },
495+
{ IMX8MP_CLK_AUDIO_AXI_SRC, 600 * HZ_PER_MHZ },
496+
{ IMX8MP_CLK_HSIO_AXI, 400 * HZ_PER_MHZ },
497+
{ IMX8MP_CLK_MEDIA_ISP, 400 * HZ_PER_MHZ },
498+
{ IMX8MP_CLK_VPU_BUS, 600 * HZ_PER_MHZ },
499+
{ IMX8MP_CLK_MEDIA_AXI, 400 * HZ_PER_MHZ },
500+
{ IMX8MP_CLK_HDMI_AXI, 400 * HZ_PER_MHZ },
501+
{ IMX8MP_CLK_GPU_AXI, 600 * HZ_PER_MHZ },
502+
{ IMX8MP_CLK_GPU_AHB, 300 * HZ_PER_MHZ },
503+
{ IMX8MP_CLK_NOC, 800 * HZ_PER_MHZ },
504+
{ IMX8MP_CLK_NOC_IO, 600 * HZ_PER_MHZ },
505+
{ IMX8MP_CLK_ML_AHB, 300 * HZ_PER_MHZ },
506+
{ IMX8MP_CLK_VPU_G1, 600 * HZ_PER_MHZ },
507+
{ IMX8MP_CLK_VPU_G2, 500 * HZ_PER_MHZ },
508+
{ IMX8MP_CLK_MEDIA_CAM1_PIX, 400 * HZ_PER_MHZ },
509+
{ IMX8MP_CLK_VPU_VC8000E, 400 * HZ_PER_MHZ }, /* Datasheet claims 500MHz */
510+
{ IMX8MP_CLK_DRAM_CORE, 800 * HZ_PER_MHZ },
511+
{ IMX8MP_CLK_GIC, 400 * HZ_PER_MHZ },
512+
{ /* Sentinel */ }
513+
};
514+
515+
static const struct imx8mp_clock_constraints imx8mp_clock_overdrive_constraints[] = {
516+
{ IMX8MP_CLK_M7_CORE, 800 * HZ_PER_MHZ},
517+
{ IMX8MP_CLK_ML_CORE, 1000 * HZ_PER_MHZ },
518+
{ IMX8MP_CLK_GPU3D_CORE, 1000 * HZ_PER_MHZ },
519+
{ IMX8MP_CLK_GPU3D_SHADER_CORE, 1000 * HZ_PER_MHZ },
520+
{ IMX8MP_CLK_GPU2D_CORE, 1000 * HZ_PER_MHZ },
521+
{ IMX8MP_CLK_AUDIO_AXI_SRC, 800 * HZ_PER_MHZ },
522+
{ IMX8MP_CLK_HSIO_AXI, 500 * HZ_PER_MHZ },
523+
{ IMX8MP_CLK_MEDIA_ISP, 500 * HZ_PER_MHZ },
524+
{ IMX8MP_CLK_VPU_BUS, 800 * HZ_PER_MHZ },
525+
{ IMX8MP_CLK_MEDIA_AXI, 500 * HZ_PER_MHZ },
526+
{ IMX8MP_CLK_HDMI_AXI, 500 * HZ_PER_MHZ },
527+
{ IMX8MP_CLK_GPU_AXI, 800 * HZ_PER_MHZ },
528+
{ IMX8MP_CLK_GPU_AHB, 400 * HZ_PER_MHZ },
529+
{ IMX8MP_CLK_NOC, 1000 * HZ_PER_MHZ },
530+
{ IMX8MP_CLK_NOC_IO, 800 * HZ_PER_MHZ },
531+
{ IMX8MP_CLK_ML_AHB, 400 * HZ_PER_MHZ },
532+
{ IMX8MP_CLK_VPU_G1, 800 * HZ_PER_MHZ },
533+
{ IMX8MP_CLK_VPU_G2, 700 * HZ_PER_MHZ },
534+
{ IMX8MP_CLK_MEDIA_CAM1_PIX, 500 * HZ_PER_MHZ },
535+
{ IMX8MP_CLK_VPU_VC8000E, 500 * HZ_PER_MHZ }, /* Datasheet claims 400MHz */
536+
{ IMX8MP_CLK_DRAM_CORE, 1000 * HZ_PER_MHZ },
537+
{ IMX8MP_CLK_GIC, 500 * HZ_PER_MHZ },
538+
{ /* Sentinel */ }
539+
};
540+
541+
static void imx8mp_clocks_apply_constraints(const struct imx8mp_clock_constraints constraints[])
542+
{
543+
const struct imx8mp_clock_constraints *constr;
544+
545+
for (constr = constraints; constr->clkid; constr++)
546+
clk_hw_set_rate_range(hws[constr->clkid], 0, constr->maxrate);
547+
}
548+
409549
static int imx8mp_clocks_probe(struct platform_device *pdev)
410550
{
411551
struct device *dev = &pdev->dev;
412552
struct device_node *np;
413553
void __iomem *anatop_base, *ccm_base;
554+
const char *opmode;
414555
int err;
415556

416557
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mp-anatop");
@@ -715,6 +856,16 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
715856

716857
imx_check_clk_hws(hws, IMX8MP_CLK_END);
717858

859+
imx8mp_clocks_apply_constraints(imx8mp_clock_common_constraints);
860+
861+
err = of_property_read_string(np, "fsl,operating-mode", &opmode);
862+
if (!err) {
863+
if (!strcmp(opmode, "nominal"))
864+
imx8mp_clocks_apply_constraints(imx8mp_clock_nominal_constraints);
865+
else if (!strcmp(opmode, "overdrive"))
866+
imx8mp_clocks_apply_constraints(imx8mp_clock_overdrive_constraints);
867+
}
868+
718869
err = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
719870
if (err < 0) {
720871
dev_err(dev, "failed to register hws for i.MX8MP\n");

0 commit comments

Comments
 (0)