Clock device tree configuration - Bootloader specif

来自百问网嵌入式Linux wiki

Article purpose

本文介绍了由 first stage bootloader 执行的特定RCC internal peripheral 配置:

Warning.png 本文介绍了如何在启动时在 RCC 中配置时钟树。
然后,您可以参考clock device tree configuration 文章来了解如何在Linux中导出每个内部外围设备时钟树® OS from the RCC 时钟树。

配置使用 device tree 机制执行,该机制提供了 RCC 外围设备的硬件描述。

此时钟树仅在引导链FSBL的设备树中使用; 所以在TF-A设备树中为OpenSTLinux正式交付(或在SPL中仅用于DDR调优工具)。

即使 U-Boot 设备树中也存在时钟树信息,该SSBL在引导过程中都不会使用它。

DT bindings documentation

引导加载程序时钟设备树绑定对应于FSBL的clk-stm32mp1驱动程序使用的供应商时钟DT绑定 (TF-AU-Boot SPL), 它基于:

这个绑定文档解释了如何为 bootloader 端的时钟编写设备树文件:

  • TF-A: tf-a/docs/devicetree/bindings/clock/st,stm32mp1-rcc.txt"[1]
  • U-Boot SPL: doc/device-tree-bindings/clock/st,stm32mp1.txt[2]

DT configuration

该硬件描述是 STM32 microprocessor 设备树文件 (扩展名为.dtsi ) 和 board 设备树文件 (.dts extension)的组合。 有关设备树文件拆分的说明,请参阅 Device tree

STM32CubeMX 可用于生成板设备树。有关详细信息,请参阅How to configure the DT using STM32CubeMX

DT configuration (STM32 level)

STM32MP1时钟节点位于 stm32mp157c.dtsi[3] (有关详细信息,请参阅Device tree ):

 / {
 ...
 	clocks {
 		clk_hse: clk-hse {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <24000000>;
 		};
 
 ...
   	};
 ...
 	soc {
 ...
 		rcc: rcc@50000000 {
 			compatible = "st,stm32mp1-rcc", "syscon";
 			reg = <0x50000000 0x1000>;
 			#clock-cells = <1>;
 			#reset-cells = <1>;
 			interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
 		};
...
 
 	};
 
 };

有关Linux®内核常见的绑定,请参考 clock device tree configuration

DT configuration (board level)

Clock node

时钟树也基于时钟节点中的五个固定时钟。它们用于定义相关ST32MP1振荡器的状态:

  • clk-lsi
  • clk-lse
  • clk-hsi
  • clk-hse
  • clk-csi

详细信息请参考clock device tree configuration

在引导时,时钟树初始化执行以下任务:

  • 启用设备树中存在的且未禁用的振荡器(状态为“ disabled”的节点),
  • 如果节点不存在或被禁用,则禁用HSI振荡器(HSI始终由ROM代码激活)。

此信息位于以下文件中:

  • STM32MP157C-EV:
  • STM32MP157X-DK:
Optional properties for "clk-lse" and "clk-hse" external oscillators

对于外部振荡器HSE和LSE,默认时钟配置是外部晶体/陶瓷谐振器。

支持四个可选字段:

  • "st,bypass" 配置外部模拟时钟源 (set HSEBYP, LSEBYP),
  • "st,digbypass" 配置外部数字时钟源 (set DIGBYP and HSEBYP, LSEBYP),
  • "st,css" 启动时钟安全系统 (HSECSSON, LSECSSON),
  • "st,drive" (LSE only) 包含振荡器的驱动器值 (请参阅文件“stm32mp1-clksrc.h”中定义的LSEDRV_[8]).
DT configuration for HSE

HSE可以在OSC_IN上接受数字或模拟的外部晶体/陶瓷或外部时钟源:用户需要根据硬件设置在设备树中选择正确的频率和正确的配置。

所有ST板均使用数字外部时钟配置 (因此,设备树中包含 = st,digbypass).

例如,在相同的24MHz频率下,我们有3种配置:

Hse config.jpg
  • 数字外部时钟 = st,digbypass
 	/ {
 		clocks {
 			clk_hse: clk-hse {
 				#clock-cells = <0>;
 				compatible = "fixed-clock";
 				clock-frequency = <24000000>;
 				st,digbypass;
 			};
 	};
  • 模拟外部时钟 = st,bypass
 	/ {
 		clocks {
 			clk_hse: clk-hse {
 				#clock-cells = <0>;
 				compatible = "fixed-clock";
 				clock-frequency = <24000000>;
 				st,bypass;
			};
 	};
  • 晶体/陶瓷谐振器配置
 	/ {
 		clocks {
 			clk_hse: clk-hse {
 				#clock-cells = <0>;
 				compatible = "fixed-clock";
 				clock-frequency = <24000000>;
 			};
 	};
DT configuration for LSE

下面是一个带有 32768 kHz 晶体谐振器的LSE板上文件示例,该驱动器设置为中高电平,并具有激活的时钟安全系统。

 	/ {
 		clocks {
 			clk_lse: clk-lse {
 				#clock-cells = <0>;
 				compatible = "fixed-clock";
 				clock-frequency = <32768>;
 				st,css;
 				st,drive = <LSEDRV_MEDIUM_HIGH>;
 			};
 	};
Optional property for "clk-hsi" internal oscillator

对于STM32MP15设备,HSI时钟频率在内部固定为64 MHz。

在设备树中,clk-hsi是HSIDIV分频器之后的时钟 (有关clk_hsi的更多信息,请参见 reference manual中的RCC章节)。
因此,该固定时钟的频率用于计算时钟树初始化的预期HSIDIV。

以下是HSIDIV的示例 = 1/1:

 	/ {
 		clocks {
 			clk_hsi: clk-hsi {
 				#clock-cells = <0>;
 				compatible = "fixed-clock";
 				clock-frequency = <64000000>;
 			};
 	};

以下是HSIDIV的示例 = 1/2:

 	/ {
 		clocks {
 			clk_hsi: clk-hsi {
 				#clock-cells = <0>;
 				compatible = "fixed-clock";
 				clock-frequency = <32000000>;
 			};
 	};
Clock node example

时钟节点的示例包括:

  • 所有振荡器打开(HSE, HSI, LSE, LSI, CSI)
  • 64MHZ时的HSI (HSIDIV = 1/1)
  • 使用24MHz数字外部时钟的HSE
  • LSE使用外部晶体a 32.768kHz(典型频率)

我们重点介绍定制部件:

 / {
 	clocks {
 		clk_hse: clk-hse {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <24000000>;
 			st,digbypass;
 		};
 
 		clk_hsi: clk-hsi {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <64000000>;
 		};
 
 		clk_lse: clk-lse {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <32768>;
 		};
 
 		clk_lsi: clk-lsi {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <32000>;
 		};
 
 		clk_csi: clk-csi {
 			#clock-cells = <0>;
 			compatible = "fixed-clock";
 			clock-frequency = <4000000>;
 		};
 	};
 };

因此,基于SoC设备树“ stm32mp157c.dtsi”的最终电路板设备树为:

 #include "stm32mp157c.dtsi"
 &clk_hse {
 	clock-frequency = <24000000>;
 	st,digbypass;
 };
 
 &clk_hsi {
 	clock-frequency = <64000000>;
 };
 
 &clk_lse {
 	clock-frequency = <32768>;
 };

它是TF-A用于STM32MP157C-EV [4]的配置

STM32MP1 clock node

有关如何在时钟说明符中指定单元数的信息,请参考clock device tree configuration

引导加载程序执行全局时钟初始化,如下所述。与给定电路板相关的信息可以在clock node中列出的板特定设备树文件中找到。

引导加载程序使用RCC节点的其他属性 ("st,stm32mp1-rcc" 兼容):

  • secure-status: 与RCC_TZCR寄存器中的TZEN位配置有关,允许限制RCC和PWR寄存器的写访问
  • st,clksrc: 时钟源配置阵列
  • st,clkdiv: 时钟分频器配置阵列
  • st,pll: 特定PLL配置
  • st,pkcs: 外围内核时钟分布配置阵列。

所有可用的时钟都在stm32mp1-clks.h[9] 并且可以在设备树源中使用。

Defining clock source distribution with st,clksrc property

此属性可用于配置时钟分配树。使用时,它必须描述整个分发树。

STM32MP15设备有九个时钟源选择器。它们必须按以下顺序配置:MPU、AXI、MCU、PLL12、PLL3、PLL4、RTC、MCO1和MCO2。

时钟源配置值由位于 stm32mp1-clksrc.h[8]中的CLK_ <NAME> _ <SOURCE>宏定义。

例如:

        st,clksrc = <
                CLK_MPU_PLL1P
                CLK_AXI_PLL2P
                CLK_MCU_PLL3P
                CLK_PLL12_HSE
                CLK_PLL3_HSE
                CLK_PLL4_HSE
                CLK_RTC_LSE
                CLK_MCO1_DISABLED
                CLK_MCO2_DISABLED
        >;
Defining clock dividers with st,clkdiv property

此属性可用于配置时钟主分频器的值。 使用时,它必须描述整个时钟分频器树。

STM32MP15器件有11个分频器值。 必须按照以下顺序进行配置:MPU,AXI,MCU,APB1,APB2,APB3,APB4,APB5,RTC,MCO1和MCO2。

每个分频器值都使用 RCC 关联寄存器RCC_xxxDIVR中定义的DIV编码。 在大多数情况下,该值如下:

  • 0x0: not divided
  • 0x1: division by 2
  • 0x2: division by 4
  • 0x3: division by 8
  • ...

请注意,RTC MCO1和MCO2的编码不同

  • 0x0: not divided
  • 0x1: division by 2
  • 0x2: division by 3
  • 0x3: division by 4
  • ...

示例:

        st,clkdiv = <
                1 /*MPU*/
                0 /*AXI*/
                0 /*MCU*/
                1 /*APB1*/
                1 /*APB2*/
                1 /*APB3*/
                1 /*APB4*/
                2 /*APB5*/
                23 /*RTC*/
                0 /*MCO1*/
                0 /*MCO2*/
        >;
Defining peripheral PLL frequencies with st,pll property

此属性可用于配置PLL频率。

PLL1至PLL4的PLL子节点 (有关详细信息,请参见 reference manual ) 与从0到3(st,pll@0 to st,pll@3)的索引相关联。当关联节点不存在时,PLLx关闭。

对于 ecosystem release ≥ v1.2.0{{#set:Ecosystem release=revision of a previous flow 1.2.0}} , TF-A会自动选择最适合平台的工作点(请参考 如何更改CPU频率), 因此不再需要PLL1节点。

下面是每个PLL节点的可用属性:

  • cfg按以下顺序包含PLL配置参数:DIVM,DIVN,DIVP,DIVQ,DIVR,output.
DIVx 值定义为RCC:
  • 0x0: bypass (division by 1)
  • 0x1: division by 2
  • 0x2: division by 3
  • 0x3: division by 4
  • ...
输出包含每个输出值的位字段 (1:ON / 0:OFF)
  • BIT(0) → output P : DIVPEN
  • BIT(1) → output Q : DIVQEN
  • BIT(2) → output R : DIVREN
Note: PQR(p,q,r) macro can be used to build this value with p, q, r = 0 or 1.
  • frac: 乘法因子的小数部分 (可选,当缺少PLL时,它处于整数模式).
  • csg 包含时钟扩展发生器参数(可选),顺序如下:MOD_PER,INC_STEP和SSCG_MODE。
MOD_PER: modulation period adjustment
INC_STEP: modulation depth adjustment
SSCG_MODE: 扩频时钟发生器模式,在stm32mp1-clksrc.h[8]中定义:
  • SSCG_MODE_CENTER_SPREAD = 0
  • SSCG_MODE_DOWN_SPREAD = 1

Example:

	st,pll@0 {
		cfg = < 1 53 0 0 0 1 >;
		frac = < 0x810 >;
	};
	st,pll@1 {
		cfg = < 1 43 1 0 0 PQR(0,1,1) >;
		csg = < 10 20 1 >;
	};
	st,pll@2 {
		cfg = < 2 85 3 13 3 0 >;
		csg = < 10 20 SSCG_MODE_CENTER_SPREAD >;
	};
	st,pll@3 {
		cfg = < 2 78 4 7 9 3 >;
	};
Defining peripheral kernel clock tree distribution with st,pkcs property

此属性可用于配置外围内核时钟选择。


它是由stm32mp1-clksrc.h[8] 头文件中的CLK_<KERNEL-CLOCK>_<PARENT-CLOCK>宏定义的外围内核时钟源标识符的列表。

st,pkcs可能没有列出所有的内核时钟。无需具体订单。

Example:

	st,pkcs = <
		CLK_STGEN_HSE
		CLK_CKPER_HSI
		CLK_USBPHY_PLL2P
		CLK_DSI_PLL2Q
                CLK_I2C46_HSI
                CLK_UART1_HSI
                CLK_UART24_HSI
	>;
HSI and CSI clocks calibration

The calibration 是一个可选功能,可以从设备树中启用。 允许通过多种方式请求HSI或CSI时钟校准:

  • SiP SMC 服务
  • 每X秒定期校准一次
  • MCU引发的中断

此功能要求为校准序列分配硬件计时器。

必须使用“mcu_sev”名称定义专用中断,以便在检测到MCU引发的中断时开始校准。

  • st,hsi-cal: 用于启用HSI时钟校准功能。
  • st,csi-cal; 用于启用CSI时钟校准功能。
  • st,cal-sec: 用于启用来自安全监视器的指定时间间隔的定期校准。 时间间隔必须以秒为单位。如果未指定,则仅对每个传入请求进行校准。

示例:

	&rcc {
		st,hsi-cal;
		st,csi-cal;
		st,cal-sec = <15>;
		secure-interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
				<GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
		interrupt-names = "mcu_sev", "wakeup";
	};

How to configure the DT using STM32CubeMX

The STM32CubeMX 工具可用于配置STM32MPU设备并获取相应的 platform configuration device tree 文件。

STM32CubeMX可能不支持上述DT bindings documentation 段中描述的所有属性。
如果是,该工具将在生成的设备树中插入“用户部分”。
然后可以编辑这些部分以添加一些属性,并将它们一代一代地保留下来。

有关详细信息,请参阅 STM32CubeMX 用户手册。

References

有关其他信息,请参阅以下链接