iMX8MP: Generating clock at pin 91 CLKO2 pin

Hi,

We want to generate 100Mhz CLK output from the SoM to an external FPGA.
For that we have planned to use pin 91 (CLKO2) of iMX8M-Plus SoM and I configured DTS file as below:

    pinctrl_additionalgpio: additionalgpios {
        fsl,pins = <
            ..
            // according to 8.2.4.299 SW_PAD_CTL_PAD_CLKOUT2 SW PAD Control Register
            MX8MP_IOMUXC_GPIO1_IO15__CCM_CLKO2          0x16               /* SODIMM 91    - CLKOUT2 */
        >;

But I see just zero on the pin. Do you know what shall we do to get clock out at 100 Mhz from this pin?

Thank you.

Hi @Fide !

Sorry for the delay.

But I have been trying to make the GPIO1_IO15-CLKO2 (and actually GPIO1_IO14-CLKO1 as well for testing purposes) output clock. But without success until now.

I am basing myself on this question from NXP forum: https://community.nxp.com/t5/i-MX-Processors/enable-CLKO2-for-24MHz-output-clock-on-iMX8MN/m-p/1281678

Be aware that this question targets IMX8MN and not IMX8MP.

Here are the modifications that I did until now. I set 24MHz as a parent for both pins just for testing.

With this, CLKO2 stays always high, and CLKO1 outputs a clock that seems unstable to me.

Explanation about PAD_CTL used:

0x110 - 0b100010000
DSE_X1 (tried with DSE_X6 also)
FSEL_1_ FAST_SLEW_RATE
ODE_0_ OPEN_DRAIN_DISABLE (tried with enabled as well)
PUE_0_WEAK_ PULL_DOWN
HYS_0_ CMOS
PE_1_ PULL_ENABLE

diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
index e44bfb5efe9d..0b49af65b345 100755
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
@@ -216,7 +216,7 @@

 &usb_dwc3_1 {
        disable-over-current;
-       status = "okay";
+       status = "disabled";
 };

 /* Verdin SD_1 */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi
index e7b3fe432de5..9bbb38698978 100755
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-wifi.dtsi
@@ -56,7 +56,8 @@
                    <&pinctrl_gpio3>, <&pinctrl_gpio4>,
                    <&pinctrl_gpio7>, <&pinctrl_gpio8>,
                    <&pinctrl_gpio_hog2>, <&pinctrl_gpio_hog3>, <&pinctrl_gpio_hog4>,
-                   <&pinctrl_hdmi_hog>;
+                   <&pinctrl_hdmi_hog>,
+            <&pinctrl_usb2_en>;
 };

 /* On-module Bluetooth */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
index be5b89a89157..bd8525cb5d79 100755
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
@@ -1095,8 +1095,7 @@
        pinctrl_gpio_hog3: gpiohog3grp {
                fsl,pins = <
                        MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13             0x1c4   /* SODIMM 157 */
-                       /* CSI_1_MCLK */
-                       MX8MP_IOMUXC_GPIO1_IO15__GPIO1_IO15             0x1c4   /* SODIMM 91 */
+            MX8MP_IOMUXC_GPIO1_IO15__CCM_CLKO2      0x116    /* SODIMM 91 */
                >;
        };

@@ -1309,7 +1308,7 @@

        pinctrl_usb2_en: usb2engrp {
                fsl,pins = <
-                       MX8MP_IOMUXC_GPIO1_IO14__USB2_PWR               0x184   /* SODIMM 185 */
+                       MX8MP_IOMUXC_GPIO1_IO14__CCM_CLKO1              0x116       /* SODIMM 185 */
                >;
        };

diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index a92cf772720a..7abb48651ebb 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -864,6 +864,14 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
        clk_prepare_enable(clks[IMX8MP_CLK_QOS_ENET_ROOT]);
        clk_prepare_enable(clks[IMX8MP_CLK_ENET_QOS_ROOT]);

+       //set and enable clko1 24mhz
+       clk_set_parent(clks[IMX8MP_CLK_IPP_DO_CLKO1], clks[IMX8MP_CLK_24M]);
+       clk_prepare_enable(clks[IMX8MP_CLK_IPP_DO_CLKO1]);
+
+    //set and enable CLKO2 24MHZ
+    clk_set_parent(clks[IMX8MP_CLK_IPP_DO_CLKO2], clks[IMX8MP_CLK_24M]);
+    clk_prepare_enable(clks[IMX8MP_CLK_IPP_DO_CLKO2]);
+
        imx_register_uart_clocks();

        pr_info("i.MX8MP clock driver probe done\n");

Best regards,

Please find below an example of how to use such a clock upstream for a OV5640 camera. Note that clocks should usually not be pulled neither up nor down as they are push/pull driven. And, yeah, they are open-drain neither. I hope that helps.

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=9f046930657e9e231a2f9139cdcb611805b19d7c

Hello everyone,

Sorry for re-using the same topic, but I’m trying to do a very similar thing.
I wanted to generate a custom lower frequency on MX8MP_IOMUXC_ECSPI2_MISO__CCM_CLKO1 pin. Just for intro, I was able to achieve the 24MHz by this settings:

  • device-tree:
    • pinctrl_test_signals: testsignalsgrp {
      	fsl,pins = <
      		MX8MP_IOMUXC_ECSPI2_MISO__CCM_CLKO1	0x10	// GPIO01.15: J12.B8, output, no-pull, fast, x1
      	>;
      };
      
  • clk-imx8mp.c
    •  }
       imx_clk_init_on(np, hws);
      
      +clk_set_parent(hws[IMX8MP_CLK_IPP_DO_CLKO1]->clk, hws[IMX8MP_CLK_24M]->clk);
      +clk_prepare_enable(hws[IMX8MP_CLK_IPP_DO_CLKO1]->clk);
      
       imx_register_uart_clocks(4);
      
       return 0;
      

According to clk-imx8mp.c a valid clocks options are:

static const char * const imx8mp_ipp_do_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_133m", "sys_pll1_200m", "audio_pll2_out", "sys_pll2_500m", "vpu_pll_out", "sys_pll1_80m" };

so I changed IMX8MP_CLK_24M → IMX8MP_SYS_PLL1_80M and the frequency has been changed to 80MHz, which was ok.
But as I said I wanted to achieve a different lower frequency, lets say 10MHz. So I removed the clk-imx8mp.c modifications and tried to do it by dts


osc_10m: clock-osc-10m {
    compatible = "fixed-clock";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_test_signals>;
    clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO1>;
    clock-names = "per";
    assigned-clocks = <&clk IMX8MP_CLK_IPP_DO_CLKO1>;
    assigned-clock-parents = <&clk IMX8MP_CLK_24M>;
    assigned-clock-rates = <10000000>;
};

but without any success.

So the general question is if it’s even possible or not? Maybe use a PLL somehow, or … .

Many thanks,
Andy

1 Like

Hello @Andy99,

In these situations we prefer that another topic is opened and this one is referenced there.

Can you please do that?

Best Regards,
Bruno

Sure, but meanwhile I found an “solution”.

	// set and enable 10MHZ
	clk_set_parent(hws[IMX8MP_CLK_IPP_DO_CLKO1]->clk, hws[IMX8MP_CLK_24M]->clk);
	clk_set_rate(hws[IMX8MP_CLK_IPP_DO_CLKO1]->clk, 10000000);
	clk_prepare_enable(hws[IMX8MP_CLK_IPP_DO_CLKO1]->clk);

So the key was to use clk_set_rate which allows to divide the clock.

But there is still some one point missing. Of there is a way to do it in DTB. But this is enough for my purposes.

Andy