How to enable TPM6 in device tree for IMX8ULP

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to enable TPM6 in device tree for IMX8ULP

100 Views
graycan00
Contributor I

How do I configure the imx8ulp device tree to enable TPM6 on the A35, and what device tree settings are required to clock TPM6 from the free running oscillator (FRO)?

0 Kudos
Reply
2 Replies

38 Views
Bio_TICFSL
NXP TechSupport
NXP TechSupport

Hello,

To enable TPM6 on the A35 core for the i.MX8ULP and configure it to use the free running oscillator (FRO) as its clock source, you need to make specific modifications to your device tree.

## Device Tree Configuration

1. First, locate the device tree files for the i.MX8ULP in your Linux kernel source directory:
- Main path: `arch/arm64/boot/dts/freescale/`

2. Add or modify the TPM6 node in your device tree:

```
tpm6: tpm@2da0000 {
compatible = "fsl,imx8ulp-tpm";
reg = ;
interrupts = ;
clocks = ,
;
clock-names = "ipg", "per";
assigned-clocks = ;
assigned-clock-parents = ;
status = "okay";
};
```

3. Make sure to reference the TPM6 clock definitions from:
- `include/dt-bindings/clock/imx8ulp-clock.h`

## Important Notes

- TPM6 must be accessible from the A35 core according to the i.MX8ULP memory map
- The FRO (Free Running Oscillator) must be properly configured in the CGC (Clock Generation and Control)
- You'll need to manually adjust the device tree based on the block diagram (Figure 6) and memory mapping tables in the i.MX8ULP Reference Manual

regards

0 Kudos
Reply

14 Views
graycan00
Contributor I

Initially I followed the steps in this post and applied the patches provided from this solution:

https://community.nxp.com/t5/i-MX-Processors/i-MX8ULP-linux-clocksource-precision/m-p/2139659/highli...

This however seemed to only allow for use of the system oscillator and not the FRO. 

I made the following changes after using the patch from the solution linked above.

1)  Configure the Peripheral Clock Controller (PCC4) for TPM6, imx8ulp_bl31_setup.c

#if defined(IMX8ULP_TPM_TIMERS)
    /* config the TPM6 clock with FRODIV2*/
    mmio_write_32(IMX_CGC1_BASE + 0x908, 0x3);
    mmio_write_32(IMX_PCC4_BASE + 0x08, 0x94000000);
    mmio_write_32(IMX_PCC4_BASE + 0x08, 0xd4000000);
#endif


2) Modified the patch from solution linked above to use frosc_div2 instead of sosc_div2:

From 6db58f97ab7fb7cff89a5386dee7c392f1fdd7cb Mon Sep 17 00:00:00 2001
From: chong feng <chong.feng@nxp.com>
Date: Thu, 7 Aug 2025 23:17:29 +0530
Subject: [PATCH 1/3] drivers: clk: imx8ulp tpm4, tpm6 fixed clk gate only

Add clk imx8ulp tpm6 fixed clock gate only

Signed-off-by: Adrian Alonso <adrian.alonso@nxp.com>
Reviewed-by: Jacky Bai <ping.bai@nxp.com>
---
 drivers/clk/imx/clk-imx8ulp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/imx/clk-imx8ulp.c b/drivers/clk/imx/clk-imx8ulp.c
index 535b6364ca7e..1abef4c54c2e 100644
--- a/drivers/clk/imx/clk-imx8ulp.c
+++ b/drivers/clk/imx/clk-imx8ulp.c
@@ -413,7 +413,8 @@ static int imx8ulp_clk_pcc4_init(struct platform_device *pdev)
 		return PTR_ERR(base);
 
 	clks[IMX8ULP_CLK_FLEXSPI2] = imx8ulp_clk_hw_composite("flexspi2", pcc4_periph_plat_sels, ARRAY_SIZE(pcc4_periph_plat_sels), true, true, true, base + 0x4, 1);
-	clks[IMX8ULP_CLK_TPM6] = imx8ulp_clk_hw_composite("tpm6", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), true, true, true, base + 0x8, 1);
+	// clks[IMX8ULP_CLK_TPM6] = imx8ulp_clk_hw_composite("tpm6", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), true, true, true, base + 0x8, 1);
+	// clks[IMX8ULP_CLK_TPM6] = imx_clk_hw_gate_flags("tpm6", "sosc_div2",  base + 0x08, 30, CLK_IS_CRITICAL);
+	clks[IMX8ULP_CLK_TPM6] = imx_clk_hw_gate_flags("tpm6", "frosc_div2",  base + 0x08, 30, CLK_IS_CRITICAL);
 	clks[IMX8ULP_CLK_TPM7] = imx8ulp_clk_hw_composite("tpm7", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), true, true, true, base + 0xc, 1);
 	clks[IMX8ULP_CLK_LPI2C6] = imx8ulp_clk_hw_composite("lpi2c6", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), true, true, true, base + 0x10, 1);
 	clks[IMX8ULP_CLK_LPI2C7] = imx8ulp_clk_hw_composite("lpi2c7", pcc4_periph_bus_sels, ARRAY_SIZE(pcc4_periph_bus_sels), true, true, true, base + 0x14, 1);
-- 
2.25.1


3) Update device tree. 

       tpm6: tpm@29820000 {
            compatible = "nxp,tpm-timer";
            timer-rating = <410>;
            status = "okay";     
            reg = <0x29820000 0x1000>;
            interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
            clock-names = "ipg", "per";
            clocks = <&frosc>, <&frosc>;         
        };   



These steps get the linux clock summary to show a clock rate of 192MHz on TPM6. This is good, but it should be 48MHz because of the divisor 2 setting. 

What are the next steps to get the 48MHz clock rate on TPM6? Do I need to amend any of the steps described above? 

0 Kudos
Reply
%3CLINGO-SUB%20id%3D%22lingo-sub-2255443%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%3EHow%20to%20enable%20TPM6%20in%20device%20tree%20for%20IMX8ULP%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2255443%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%3E%3CP%3EHow%20do%20I%20configure%20the%20imx8ulp%20device%20tree%20to%20enable%20TPM6%20on%20the%20A35%2C%20and%20what%20device%20tree%20settings%20are%20required%20to%20clock%20TPM6%20from%20the%20free%20running%20oscillator%20(FRO)%3F%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-LABS%20id%3D%22lingo-labs-2255443%22%20slang%3D%22en-US%22%20mode%3D%22CREATE%22%3E%3CLINGO-LABEL%3Ei.MX%208%20Family%20%7C%20i.MX%208QuadMax%20(8QM)%20%7C%208QuadPlus%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Ei.MX%208M%20%7C%20i.MX%208M%20Mini%20%7C%20i.MX%208M%20Nano%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3Ei.MX8ULP%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3ELinux%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E