學習 DT device tree 以 ST 的開發板 STM32F429i-disc1 為例

目標

因為對 device tree 不是很熟悉,
所以就將 device tree,
設為學習目標。

啟動

注意,
這篇隨筆的解說都放在最下面,會標 Explanation_XX,只要搜尋 Explanation_XX 往上找,就可以看到 source code 要解說的點,
總之就是多找幾遍,如 Explanation_13,就會出現 source code 及 解說。

那要如何開始呢?
從 spec?
從 公司的案子 Uxxxxxx 的 device tree code 開始,
kernel-3.18/arch/arm64/boot/dts/mtXX.dtsi


   1 /*
   2  * Mediatek's MTXXXX SoC device tree source
   3  *
   4  * Copyright (c) 2013 MediaTek Co., Ltd.
   5  *              http://www.mediatek.com
   6  *
   7  */
   8 
   ...
   ...
   ...
   3178 #include "mtXXXX.dtsi"
   3179 #else
   3180 #include "mtXXXX.dtsi"
   3181 #endif

3千多行,
oh! my god!
換個平台好了!
順道一提,
*.dts 是 device tree source code,
*.dtsi 是常用的 device tree source code,類似 c 語言的 .h,
*.dtb (b : blob)是 device tree source code 編譯後的二進制檔,
*.dts 及 *.dtsi 可以看到 device tree source code,
也可以將 *.dtb decompile 成 device tree source code,

$ ./out/target/product/project_name/obj/KERNEL_OBJ/scripts/dtc/dtc -I dtb -O dts -o decompiled.dts ~/project/linux_repo/out/target/product/project_name/obj/KERNEL_OBJ/arch/arm64/boot/dts/your.dtb

也就是

kernel-3.18/out/***/scripts/dtc/dtc   -I   dtb   -O   dts   -o   you_want.dts   your.dtb

Usage: dtc [options] <input file>

  • -I, --in-format <arg>
    Input formats are:
    dts - device tree source text
    dtb - device tree blob
    fs - /proc/device-tree style directory

  • -O, --out-format <arg>
    Output formats are:
    dts - device tree source text
    dtb - device tree blob
    asm - assembler source

  • -o, --out <arg>
    Output file

from

$ kernel-3.18/out/***/scripts/dtc/dtc -h
注意

一個是大寫 O
一個是小寫 o

有同事問我 device tree 的 decompile 在工作上有什麼用途、作用?
建議先參考 Explanation_6,
以下方為例 clk-hse 的 clock-frequency 可以在其它檔案設定,
如果 dts include dtsi 又再 include dtsi ....
你不會知道 clock-frequency 在那裡被設定,
而 dtb 是最終被 compile 出來的 binary file,
這時 decompile dtb 就可以知道最終的設定值。

linux-4.11.3/arch/arm/boot/dts/stm32f429.dtsi

        clk_hse: clk-hse {
              ...
              clock-frequency = <0>;
              ...
        };

原因就在於 8Mhz 是在另一檔案設定的,

linux-4.11.3/arch/arm/boot/dts/stm32f429-disco.dts

&clk_hse {
        clock-frequency = <8000000>;
};

Uxxxxxx 的 .dtb ./target/product/ukulele/obj/KERNEL_OBJ/arch/arm64/boot/dts/XXXXX.dtb,
decompile 後,將近有 4千 行,這更加確定我要換一個小平台,


   1 /dts-v1/;
   2 
   3 / {
   4         model = "MTXXXX";
   5         compatible = "mediatek,MTXXXX";
   6         interrupt-parent = <0x1>;
   7         #address-cells = <0x2>;
   8         #size-cells = <0x2>;
   ...
   ...
   ...
   3905         };
   3906 };

小平台

市面上有很多 arm 的開發板,
如 Arduino、Raspberry Pi、BeagleBone Black,st,等等,
天龍書局都有賣,
而且有很多書 kernel、linux、開發板 趕快去看看,
要不然 googleplay 圖書 也有喔!
我選了 st 的開發板,
原因是價錢還可以接受,但不是在天龍買的,

環境架設

linux kernel support STM32F429i-disc1 開發板,
所以我就想說要 setup 一個 build code 環境,
一個是用 公司的 現有 build code 環境,
一個是用安裝 virtual machine,和現有 build code 環境區隔,避免發生問題,
那 virtual machine 有二種軟體,
一個是 virtual box 這是 open source,
一個是 VMware® Workstation Player,

我選擇 virtual box https://www.virtualbox.org/、
Ubuntu 14.04.5 LTS (Trusty Tahr) http://releases.ubuntu.com/14.04/
這裡有教您安裝環境
http://elinux.org/STM32#Bootloaders
我是使用
GNU ARM Embedded Toolchain https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
順道一提,什麼是 tool chain?
一堆工具,如下。
Projects included in the GNU toolchain are:

  • GNU make: an automation tool for compilation and build
  • GNU Compiler Collection (GCC): a suite of compilers for several programming languages
  • GNU Binutils: a suite of tools including linker, assembler and other tools
  • GNU Bison: a parser generator, often used with the Flex lexical analyser
  • GNU m4: an m4 macro processor
  • GNU Debugger (GDB): a code debugging tool
  • GNU build system (autotools): Autoconf, Automake and Libtool
    https://en.wikipedia.org/wiki/GNU_toolchain

Step

  1. Download GNU ARM Embedded Toolchain
    from https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
$tar xjf gcc-arm-none-eabi-6-2017-q1-update-linux.tar.bz2
$ export PATH=$PATH:$your_path/gcc-arm-none-eabi-6-2017-q1-update/bin
  1. Download newer kernel than v4.2-rc1
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
$ export PATH=$PATH:$your_path/gcc-arm-none-eabi-6-2017-q1-update/bin
make ARCH=arm CROSS_COMPILE=arm-none-eabi- stm32_defconfig        // Explanation_1,請搜尋 "Explanation_1" 下面有解釋。
make ARCH=arm CROSS_COMPILE=arm-none-eabi-        // Explanation_2,請搜尋 "Explanation_2" 下面有解釋。

解釋 make instruction

make 小知識

在解釋 make instruction 之前,先帶些 make 相關的小知識,
執行 make 指令時,
make 會依序尋找以下 3 個檔案,左邊優先最高,只會執行一個檔案,
GNUmakefile makefile Makefile

Reference

GNU make Version 4.2
https://www.gnu.org/software/make/manual/make.pdf
3.2 What Name to Give Your Makefile

Makefile parameters pass 參數傳遞

Makefile content
$(warning $(ARCH))
command
$make ARCH=7777777777777777777777777777777
output
Makefile:1: 7777777777777777777777777777777
make: *** No targets.  Stop.

make command explaination 編譯命令解釋

Explanation_1 Creating .config file

make    ARCH=arm    CROSS_COMPILE=arm-none-eabi-    stm32_defconfig

stm32_defconfig 裡的 config 和 Kconfig 檔的 config 做結合,Creating .config file,build code 時使用的,
將變數 ARCH=arm,CROSS_COMPILE=arm-none-eabi- 傳進 Makefile 裡使用,
在 ./arch/arm/configs下有一隻給 stm32 board 使用的設定檔 stm32_defconfig

  1 CONFIG_NO_HZ_IDLE=y
  2 CONFIG_HIGH_RES_TIMERS=y
  3 CONFIG_LOG_BUF_SHIFT=16
  4 CONFIG_BLK_DEV_INITRD=y
  5 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
  6 # CONFIG_UID16 is not set
  ...
  ...
  29 CONFIG_ZBOOT_ROM_TEXT=0x0    <<<====================

  ...
  ...
  ...

linux-4.11.3/arch/arm/Kconfig 一段小內容如下。

...
...
1878 # Compressed boot loader in ROM.  Yes, we really want to ask about
1879 # TEXT and BSS so we preserve their values in the config files.
1880 config ZBOOT_ROM_TEXT
1881         hex "Compressed ROM boot loader base address"
1882         default "0"    <<<====================================
1883         help
1884           The physical address at which the ROM-able zImage is to be
1885           placed in the target.  Platforms which normally make use of
1886           ROM-able zImage formats normally set this to a suitable
1887           value in their defconfig file.
1888
1889           If ZBOOT_ROM is not enabled, this has no effect.
1890
...
...

使用 stm32_defconfig 再加上 Kconfig 所產生的設定生成 kernel folder 下的 ./.config
若 stm32_defconfig 的設定與 Kconfig 設定有所衝突,以stm32_defconfig 為優先,
如上面,stm32_defconfig 有一個 config CONFIG_ZBOOT_ROM_TEXT=0x0,
Kconfig 有一個 ZBOOT_ROM_TEST,default value 是 0,parsing 後會成為 CONFIG_ZBOOT_ROM_TEXT,
若 Kconfig 和 stm32_defconfig 的 config 值 不一致,會以stm32_defconfig 為優先,
若 Kconfig 有的 config,而 stm32_defconfig 沒有,會以 Kconfig 的 config 會優先。

生成後的 .config 與 stm32_defconfig 的比較

Explanation_2 Compiling kernel

make ARCH=arm CROSS_COMPILE=arm-none-eabi-

以上的命令,是使用 kernel folder 下的 ./.config 設定值去編譯 kernel 。

Device Tree Source Code

linux-4.11.3/arch/arm/boot/dts/stm32f429.dtsi

/*        // Explanation_3
 * Copyright 2015 - Maxime Coquelin <mcoquelin.stm32@gmail.com>
 *
 * This file is dual-licensed: you can use it either under the terms
 * of the GPL or the X11 license, at your option. Note that this dual
 * licensing only applies to this file, and not this project as a
 * whole.
 *
 *  a) This file is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2 of the
 *     License, or (at your option) any later version.
 *
 *     This file is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public
 *     License along with this file; if not, write to the Free
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 *     MA 02110-1301 USA
 *
 * Or, alternatively,
 *
 *  b) Permission is hereby granted, free of charge, to any person
 *     obtaining a copy of this software and associated documentation
 *     files (the "Software"), to deal in the Software without
 *     restriction, including without limitation the rights to use,
 *     copy, modify, merge, publish, distribute, sublicense, and/or
 *     sell copies of the Software, and to permit persons to whom the
 *     Software is furnished to do so, subject to the following
 *     conditions:
 *
 *     The above copyright notice and this permission notice shall be
 *     included in all copies or substantial portions of the Software.
 *
 *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *     OTHER DEALINGS IN THE SOFTWARE.
 */

#include "skeleton.dtsi"        // Explanation_3
#include "armv7-m.dtsi"
#include <dt-bindings/pinctrl/stm32f429-pinfunc.h>
#include <dt-bindings/clock/stm32fx-clock.h>
#include <dt-bindings/mfd/stm32f4-rcc.h>

/ {        // Explanation_4
	clocks {        // Explanation_5
		clk_hse: clk-hse {        // Explanation_6
    			#clock-cells = <0>;        // Explanation_7
			compatible = "fixed-clock";        // Explanation_8
			clock-frequency = <0>;        // Explanation_8
		};

		clk-lse {        // Explanation_9
			#clock-cells = <0>;
			compatible = "fixed-clock";
			clock-frequency = <32768>;
		};

		clk-lsi {
			#clock-cells = <0>;
			compatible = "fixed-clock";
			clock-frequency = <32000>;
		};

		clk_i2s_ckin: i2s-ckin {
			#clock-cells = <0>;
			compatible = "fixed-clock";
			clock-frequency = <0>;
		};
	};

	soc {
		timer2: timer@40000000 {        // Explanation_11
			compatible = "st,stm32-timer";
			reg = <0x40000000 0x400>;        // Explanation_11
			interrupts = <28>;        // Explanation_12
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM2)>;
			status = "disabled";        // Explanation_13
		};

		timers2: timers@40000000 {
			#address-cells = <1>;        // Explanation_10
			#size-cells = <0>;              // Explanation_10
			compatible = "st,stm32-timers";
			reg = <0x40000000 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM2)>;        // Explanation_14
			clock-names = "int";        // Explanation_15
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};

			timer@1 {
				compatible = "st,stm32-timer-trigger";
				reg = <1>;
				status = "disabled";
			};
		};

		timer3: timer@40000400 {
			compatible = "st,stm32-timer";
			reg = <0x40000400 0x400>;
			interrupts = <29>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM3)>;
			status = "disabled";
		};

		timers3: timers@40000400 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40000400 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM3)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};

			timer@2 {
				compatible = "st,stm32-timer-trigger";
				reg = <2>;
				status = "disabled";
			};
		};

		timer4: timer@40000800 {
			compatible = "st,stm32-timer";
			reg = <0x40000800 0x400>;
			interrupts = <30>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM4)>;
			status = "disabled";
		};

		timers4: timers@40000800 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40000800 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM4)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};

			timer@3 {
				compatible = "st,stm32-timer-trigger";
				reg = <3>;
				status = "disabled";
			};
		};

		timer5: timer@40000c00 {
			compatible = "st,stm32-timer";
			reg = <0x40000c00 0x400>;
			interrupts = <50>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM5)>;
		};

		timers5: timers@40000c00 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40000C00 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM5)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};

			timer@4 {
				compatible = "st,stm32-timer-trigger";
				reg = <4>;
				status = "disabled";
			};
		};

		timer6: timer@40001000 {
			compatible = "st,stm32-timer";
			reg = <0x40001000 0x400>;
			interrupts = <54>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM6)>;
			status = "disabled";
		};

		timers6: timers@40001000 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40001000 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM6)>;
			clock-names = "int";
			status = "disabled";

			timer@5 {
				compatible = "st,stm32-timer-trigger";
				reg = <5>;
				status = "disabled";
			};
		};

		timer7: timer@40001400 {
			compatible = "st,stm32-timer";
			reg = <0x40001400 0x400>;
			interrupts = <55>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM7)>;
			status = "disabled";
		};

		timers7: timers@40001400 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40001400 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM7)>;
			clock-names = "int";
			status = "disabled";

			timer@6 {
				compatible = "st,stm32-timer-trigger";
				reg = <6>;
				status = "disabled";
			};
		};

		timers12: timers@40001800 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40001800 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM12)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};

			timer@11 {
				compatible = "st,stm32-timer-trigger";
				reg = <11>;
				status = "disabled";
			};
		};

		timers13: timers@40001c00 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40001C00 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM13)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};
		};

		timers14: timers@40002000 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40002000 0x400>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM14)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};
		};

		rtc: rtc@40002800 {
			compatible = "st,stm32-rtc";
			reg = <0x40002800 0x400>;
			clocks = <&rcc 1 CLK_RTC>;
			clock-names = "ck_rtc";
			assigned-clocks = <&rcc 1 CLK_RTC>;        // Explanation_16
			assigned-clock-parents = <&rcc 1 CLK_LSE>;        // Explanation_17
			interrupt-parent = <&exti>;
			interrupts = <17 1>;        // Explanation_18
			interrupt-names = "alarm";        // Explanation_19
			st,syscfg = <&pwrcfg>;        // Explanation_20
			status = "disabled";
		};

		usart2: serial@40004400 {
			compatible = "st,stm32-usart", "st,stm32-uart";
			reg = <0x40004400 0x400>;
			interrupts = <38>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(UART2)>;
			status = "disabled";
		};

		usart3: serial@40004800 {
			compatible = "st,stm32-usart", "st,stm32-uart";
			reg = <0x40004800 0x400>;
			interrupts = <39>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(UART3)>;
			status = "disabled";
			dmas = <&dma1 1 4 0x400 0x0>,
			       <&dma1 3 4 0x400 0x0>;
			dma-names = "rx", "tx";
		};

		usart4: serial@40004c00 {
			compatible = "st,stm32-uart";
			reg = <0x40004c00 0x400>;
			interrupts = <52>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(UART4)>;
			status = "disabled";
		};

		usart5: serial@40005000 {
			compatible = "st,stm32-uart";
			reg = <0x40005000 0x400>;
			interrupts = <53>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(UART5)>;
			status = "disabled";
		};

		i2c1: i2c@40005400 {
			compatible = "st,stm32f4-i2c";
			reg = <0x40005400 0x400>;
			interrupts = <31>,
				     <32>;
			resets = <&rcc STM32F4_APB1_RESET(I2C1)>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(I2C1)>;
			#address-cells = <1>;
			#size-cells = <0>;
			status = "disabled";
		};

		usart7: serial@40007800 {
			compatible = "st,stm32-usart", "st,stm32-uart";
			reg = <0x40007800 0x400>;
			interrupts = <82>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(UART7)>;
			status = "disabled";
		};

		usart8: serial@40007c00 {
			compatible = "st,stm32-usart", "st,stm32-uart";
			reg = <0x40007c00 0x400>;
			interrupts = <83>;
			clocks = <&rcc 0 STM32F4_APB1_CLOCK(UART8)>;
			status = "disabled";
		};

		timers1: timers@40010000 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40010000 0x400>;
			clocks = <&rcc 0 STM32F4_APB2_CLOCK(TIM1)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};

			timer@0 {
				compatible = "st,stm32-timer-trigger";
				reg = <0>;
				status = "disabled";
			};
		};

		timers8: timers@40010400 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40010400 0x400>;
			clocks = <&rcc 0 STM32F4_APB2_CLOCK(TIM8)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};

			timer@7 {
				compatible = "st,stm32-timer-trigger";
				reg = <7>;
				status = "disabled";
			};
		};

		usart1: serial@40011000 {
			compatible = "st,stm32-usart", "st,stm32-uart";
			reg = <0x40011000 0x400>;
			interrupts = <37>;
			clocks = <&rcc 0 STM32F4_APB2_CLOCK(USART1)>;
			status = "disabled";
			dmas = <&dma2 2 4 0x400 0x0>,
			       <&dma2 7 4 0x400 0x0>;
			dma-names = "rx", "tx";
		};

		usart6: serial@40011400 {
			compatible = "st,stm32-usart", "st,stm32-uart";
			reg = <0x40011400 0x400>;
			interrupts = <71>;
			clocks = <&rcc 0 STM32F4_APB2_CLOCK(USART6)>;
			status = "disabled";
		};

		adc: adc@40012000 {
			compatible = "st,stm32f4-adc-core";
			reg = <0x40012000 0x400>;
			interrupts = <18>;
			clocks = <&rcc 0 STM32F4_APB2_CLOCK(ADC1)>;
			clock-names = "adc";
			interrupt-controller;
			#interrupt-cells = <1>;        // Explanation_27
			#address-cells = <1>;
			#size-cells = <0>;
			status = "disabled";

			adc1: adc@0 {
				compatible = "st,stm32f4-adc";
				#io-channel-cells = <1>;
				reg = <0x0>;
				clocks = <&rcc 0 STM32F4_APB2_CLOCK(ADC1)>;
				interrupt-parent = <&adc>;
				interrupts = <0>;
				status = "disabled";
			};

			adc2: adc@100 {
				compatible = "st,stm32f4-adc";
				#io-channel-cells = <1>;
				reg = <0x100>;
				clocks = <&rcc 0 STM32F4_APB2_CLOCK(ADC2)>;
				interrupt-parent = <&adc>;
				interrupts = <1>;
				status = "disabled";
			};

			adc3: adc@200 {
				compatible = "st,stm32f4-adc";
				#io-channel-cells = <1>;
				reg = <0x200>;
				clocks = <&rcc 0 STM32F4_APB2_CLOCK(ADC3)>;
				interrupt-parent = <&adc>;
				interrupts = <2>;
				status = "disabled";
			};
		};

		syscfg: system-config@40013800 {
			compatible = "syscon";
			reg = <0x40013800 0x400>;
		};

		exti: interrupt-controller@40013c00 {
			compatible = "st,stm32-exti";
			interrupt-controller;
			#interrupt-cells = <2>;
			reg = <0x40013C00 0x400>;
			interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
		};

		timers9: timers@40014000 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40014000 0x400>;
			clocks = <&rcc 0 STM32F4_APB2_CLOCK(TIM9)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};

			timer@8 {
				compatible = "st,stm32-timer-trigger";
				reg = <8>;
				status = "disabled";
			};
		};

		timers10: timers@40014400 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40014400 0x400>;
			clocks = <&rcc 0 STM32F4_APB2_CLOCK(TIM10)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};
		};

		timers11: timers@40014800 {
			#address-cells = <1>;
			#size-cells = <0>;
			compatible = "st,stm32-timers";
			reg = <0x40014800 0x400>;
			clocks = <&rcc 0 STM32F4_APB2_CLOCK(TIM11)>;
			clock-names = "int";
			status = "disabled";

			pwm {
				compatible = "st,stm32-pwm";
				status = "disabled";
			};
		};

		pwrcfg: power-config@40007000 {
			compatible = "syscon";
			reg = <0x40007000 0x400>;
		};

		pin-controller {        // Explanation_32
			#address-cells = <1>;
			#size-cells = <1>;
			compatible = "st,stm32f429-pinctrl";
			ranges = <0 0x40020000 0x3000>;
			interrupt-parent = <&exti>;
			st,syscfg = <&syscfg 0x8>;
			pins-are-numbered;

			gpioa: gpio@40020000 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x0 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)>;
				st,bank-name = "GPIOA";
			};

			gpiob: gpio@40020400 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x400 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOB)>;
				st,bank-name = "GPIOB";
			};

			gpioc: gpio@40020800 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x800 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOC)>;
				st,bank-name = "GPIOC";
			};

			gpiod: gpio@40020c00 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0xc00 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOD)>;
				st,bank-name = "GPIOD";
			};

			gpioe: gpio@40021000 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x1000 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOE)>;
				st,bank-name = "GPIOE";
			};

			gpiof: gpio@40021400 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x1400 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOF)>;
				st,bank-name = "GPIOF";
			};

			gpiog: gpio@40021800 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x1800 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOG)>;
				st,bank-name = "GPIOG";
			};

			gpioh: gpio@40021c00 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x1c00 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOH)>;
				st,bank-name = "GPIOH";
			};

			gpioi: gpio@40022000 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x2000 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOI)>;
				st,bank-name = "GPIOI";
			};

			gpioj: gpio@40022400 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x2400 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOJ)>;
				st,bank-name = "GPIOJ";
			};

			gpiok: gpio@40022800 {
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x2800 0x400>;
				clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOK)>;
				st,bank-name = "GPIOK";
			};

			usart1_pins_a: usart1@0 {
				pins1 {
					pinmux = <STM32F429_PA9_FUNC_USART1_TX>;
					bias-disable;
					drive-push-pull;
					slew-rate = <0>;
				};
				pins2 {
					pinmux = <STM32F429_PA10_FUNC_USART1_RX>;
					bias-disable;
				};
			};

			usart3_pins_a: usart3@0 {
				pins1 {
					pinmux = <STM32F429_PB10_FUNC_USART3_TX>;
					bias-disable;
					drive-push-pull;
					slew-rate = <0>;
				};
				pins2 {
					pinmux = <STM32F429_PB11_FUNC_USART3_RX>;
					bias-disable;
				};
			};

			usbotg_hs_pins_a: usbotg_hs@0 {
				pins {
					pinmux = <STM32F429_PH4_FUNC_OTG_HS_ULPI_NXT>,
						 <STM32F429_PI11_FUNC_OTG_HS_ULPI_DIR>,
						 <STM32F429_PC0_FUNC_OTG_HS_ULPI_STP>,
						 <STM32F429_PA5_FUNC_OTG_HS_ULPI_CK>,
						 <STM32F429_PA3_FUNC_OTG_HS_ULPI_D0>,
						 <STM32F429_PB0_FUNC_OTG_HS_ULPI_D1>,
						 <STM32F429_PB1_FUNC_OTG_HS_ULPI_D2>,
						 <STM32F429_PB10_FUNC_OTG_HS_ULPI_D3>,
						 <STM32F429_PB11_FUNC_OTG_HS_ULPI_D4>,
						 <STM32F429_PB12_FUNC_OTG_HS_ULPI_D5>,
						 <STM32F429_PB13_FUNC_OTG_HS_ULPI_D6>,
						 <STM32F429_PB5_FUNC_OTG_HS_ULPI_D7>;
					bias-disable;
					drive-push-pull;
					slew-rate = <2>;
				};
			};

			ethernet_mii: mii@0 {
				pins {
					pinmux = <STM32F429_PG13_FUNC_ETH_MII_TXD0_ETH_RMII_TXD0>,
						 <STM32F429_PG14_FUNC_ETH_MII_TXD1_ETH_RMII_TXD1>,
						 <STM32F429_PC2_FUNC_ETH_MII_TXD2>,
						 <STM32F429_PB8_FUNC_ETH_MII_TXD3>,
						 <STM32F429_PC3_FUNC_ETH_MII_TX_CLK>,
						 <STM32F429_PG11_FUNC_ETH_MII_TX_EN_ETH_RMII_TX_EN>,
						 <STM32F429_PA2_FUNC_ETH_MDIO>,
						 <STM32F429_PC1_FUNC_ETH_MDC>,
						 <STM32F429_PA1_FUNC_ETH_MII_RX_CLK_ETH_RMII_REF_CLK>,
						 <STM32F429_PA7_FUNC_ETH_MII_RX_DV_ETH_RMII_CRS_DV>,
						 <STM32F429_PC4_FUNC_ETH_MII_RXD0_ETH_RMII_RXD0>,
						 <STM32F429_PC5_FUNC_ETH_MII_RXD1_ETH_RMII_RXD1>,
						 <STM32F429_PH6_FUNC_ETH_MII_RXD2>,
						 <STM32F429_PH7_FUNC_ETH_MII_RXD3>;
					slew-rate = <2>;
				};
			};

			adc3_in8_pin: adc@200 {
				pins {
					pinmux = <STM32F429_PF10_FUNC_ANALOG>;
				};
			};

			pwm1_pins: pwm@1 {
				pins {
					pinmux = <STM32F429_PA8_FUNC_TIM1_CH1>,
						 <STM32F429_PB13_FUNC_TIM1_CH1N>,
						 <STM32F429_PB12_FUNC_TIM1_BKIN>;
				};
			};

			pwm3_pins: pwm@3 {
				pins {
					pinmux = <STM32F429_PB4_FUNC_TIM3_CH1>,
						 <STM32F429_PB5_FUNC_TIM3_CH2>;
				};
			};

			i2c1_pins: i2c1@0 {
				pins {
					pinmux = <STM32F429_PB9_FUNC_I2C1_SDA>,
						 <STM32F429_PB6_FUNC_I2C1_SCL>;
					bias-disable;
					drive-open-drain;
					slew-rate = <3>;
				};
			};
		};

		rcc: rcc@40023810 {        // Explanation_29
			#reset-cells = <1>;
			#clock-cells = <2>;        // Explanation_21
			compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
			reg = <0x40023800 0x400>;
			clocks = <&clk_hse>, <&clk_i2s_ckin>;        // Explanation_22
			st,syscfg = <&pwrcfg>;        // Explanation_23
			assigned-clocks = <&rcc 1 CLK_HSE_RTC>;        // Explanation_24
			assigned-clock-rates = <1000000>;        // Explanation_25
		};

		dma1: dma-controller@40026000 {        // Explanation_28
			compatible = "st,stm32-dma";
			reg = <0x40026000 0x400>;
			interrupts = <11>,
				     <12>,
				     <13>,
				     <14>,
				     <15>,
				     <16>,
				     <17>,
				     <47>;
			clocks = <&rcc 0 STM32F4_AHB1_CLOCK(DMA1)>;
			#dma-cells = <4>;        //Explanation_26
		};

		dma2: dma-controller@40026400 {        // Explanation_28
			compatible = "st,stm32-dma";
			reg = <0x40026400 0x400>;
			interrupts = <56>,
				     <57>,
				     <58>,
				     <59>,
				     <60>,
				     <68>,
				     <69>,
				     <70>;
			clocks = <&rcc 0 STM32F4_AHB1_CLOCK(DMA2)>;
			#dma-cells = <4>;
			st,mem2mem;
		};

		mac: ethernet@40028000 {        // Explanation_30
			compatible = "st,stm32-dwmac", "snps,dwmac-3.50a";
			reg = <0x40028000 0x8000>;
			reg-names = "stmmaceth";
			interrupts = <61>;
			interrupt-names = "macirq";
			clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
			clocks = <&rcc 0 STM32F4_AHB1_CLOCK(ETHMAC)>,
					<&rcc 0 STM32F4_AHB1_CLOCK(ETHMACTX)>,
					<&rcc 0 STM32F4_AHB1_CLOCK(ETHMACRX)>;
			st,syscon = <&syscfg 0x4>;
			snps,pbl = <8>;
			snps,mixed-burst;
			status = "disabled";
		};

		usbotg_hs: usb@40040000 {        // Explanation_31
			compatible = "snps,dwc2";
			reg = <0x40040000 0x40000>;
			interrupts = <77>;
			clocks = <&rcc 0 STM32F4_AHB1_CLOCK(OTGHS)>;
			clock-names = "otg";
			status = "disabled";
		};

		rng: rng@50060800 {        // Explanation_31
			compatible = "st,stm32-rng";
			reg = <0x50060800 0x400>;
			interrupts = <80>;
			clocks = <&rcc 0 STM32F4_AHB2_CLOCK(RNG)>;

		};
	};
};

&systick {
	clocks = <&rcc 1 SYSTICK>;
	status = "okay";
};

linux-4.11.3/arch/arm/boot/dts/stm32f429-disco.dts

/*
 * Copyright 2015 - Maxime Coquelin <mcoquelin.stm32@gmail.com>
 *
 * This file is dual-licensed: you can use it either under the terms
 * of the GPL or the X11 license, at your option. Note that this dual
 * licensing only applies to this file, and not this project as a
 * whole.
 *
 *  a) This file is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU General Public License as
 *     published by the Free Software Foundation; either version 2 of the
 *     License, or (at your option) any later version.
 *
 *     This file is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU General Public
 *     License along with this file; if not, write to the Free
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 *     MA 02110-1301 USA
 *
 * Or, alternatively,
 *
 *  b) Permission is hereby granted, free of charge, to any person
 *     obtaining a copy of this software and associated documentation
 *     files (the "Software"), to deal in the Software without
 *     restriction, including without limitation the rights to use,
 *     copy, modify, merge, publish, distribute, sublicense, and/or
 *     sell copies of the Software, and to permit persons to whom the
 *     Software is furnished to do so, subject to the following
 *     conditions:
 *
 *     The above copyright notice and this permission notice shall be
 *     included in all copies or substantial portions of the Software.
 *
 *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *     OTHER DEALINGS IN THE SOFTWARE.
 */

/dts-v1/;
#include "stm32f429.dtsi"
#include <dt-bindings/input/input.h>

/ {
	model = "STMicroelectronics STM32F429i-DISCO board";        // Explanation_8
	compatible = "st,stm32f429i-disco", "st,stm32f429";

	chosen {
		bootargs = "root=/dev/ram rdinit=/linuxrc";
		stdout-path = "serial0:115200n8";
	};

	memory {
		reg = <0x90000000 0x800000>;
	};

	aliases {
		serial0 = &usart1;
	};

	leds {
		compatible = "gpio-leds";
		red {
			gpios = <&gpiog 14 0>;
		};
		green {
			gpios = <&gpiog 13 0>;
			linux,default-trigger = "heartbeat";
		};
	};

	gpio_keys {
		compatible = "gpio-keys";
		#address-cells = <1>;
		#size-cells = <0>;
		autorepeat;
		button@0 {
			label = "User";
			linux,code = <KEY_HOME>;
			gpios = <&gpioa 0 0>;
		};
	};
};

&clk_hse {
	clock-frequency = <8000000>;
};

&rtc {
	assigned-clocks = <&rcc 1 CLK_RTC>;
	assigned-clock-parents = <&rcc 1 CLK_LSI>;
	status = "okay";
};

&usart1 {
	pinctrl-0 = <&usart1_pins_a>;        // Explanation_33
	pinctrl-names = "default";        // Explanation_33
	status = "okay";
};

Explanation_3

第一眼,映入眼簾的 code,不覺得很熟悉嗎?
有注解,有 include,像極了 C 語言,
請問 C 語言的注解、include 是那一個 software component 在處理呢?
是 Preprocessor,

照這個 code 看起來應該也有 enable 類似C語言的 preprocessor,

linux-4.11.3/kernel/scripts/Makefile.lib

...
...
304 quiet_cmd_dtc = DTC     $@
305 cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \
306         $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
307         $(DTC) -O dtb -o $@ -b 0 \
308                 -i $(dir $<) $(DTC_FLAGS) \
309                 -d $(depfile).dtc.tmp $(dtc-tmp) ; \
310         cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile)
...
...

Line 306

-x

The -x option lets you override the default by specifying the language of the source file, rather than
inferring the language from the file suffix.
指定輸入檔案的語言,而不是使用預設的 language。

Reference

assembler-with-cpp

Assembly code that contains C directives, for example #include or #define, must be resolved by the C
preprocessor prior to assembling.
...
...
assembler-with-cpp indicates that the assembly code contains C directives and armclang must run the C preprocessor.
...

Reference

Explanation_4

每一個 device tree 都需要有一個 root node /

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
Chapter three
All devicetrees shall have a root node
piece 21

Explanation_5

定義一個 device node 名為 clocks,
device node 裡面可以再定義一個 child device node。

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
Chapter six
Node and property definitions

[label:] node-name[@unit-address] {
      [properties definitions]
      [child nodes]
}

piece 43

Explanation_6

定義一個 device node 名為 clk-hse,
及定義一個 label 名為 clk_hse,
在程式裡,可以使用 &label 存取這個 device node,
linux-4.11.3/arch/arm/boot/dts/stm32f429.dtsi

...
clk_hse: clk-hse {   // abbreviation High-Speed External user clock
...
             clock-frequency = <0>;
...

linux-4.11.3/arch/arm/boot/dts/stm32f429-disco.dts

&clk_hse {
        clock-frequency = <8000000>;
};

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
Chapter six
Node and property definitions

[label:] node-name[@unit-address] {
      [properties definitions]
      [child nodes]
}

piece 43

Explanation_7

#clock-cells = <0>;

帶有 #clock-cells property 的 device node 是屬於 Clock providers,提供 clock 出去。
#clock-cells 是 Number of cells in a clock specifier,也就是 clock consumer 在使用 clock 時,需要幾個 u32 來表達出所要選擇的 clock source,
0 代表只有一個 clock output,也就是不需要 clock specifier。
1 代表有多個 clock output,需要一個 u32 來表示 clock specifier。

Ex1

Clock provider
clk_hse: clk-hse {
    #clock-cells = 0;
Clock consumer
// clock = <phandle, clock specifier>
clocks = <&clk_hse>;

Ex2

Clock provider
osc: oscillator {
    #clock-cells = <1>;
    clock-output-names = "ckil", "ckih";
};
Clock consumer
// clock = <phandle, clock specifier>
clocks = <&osc 1>;

Ex3

Clock provider
osc: oscillator {
    #clock-cells = <1>;
    clock-output-names = "ckiA", "ckiB","ckiC";
};
Clock consumer
// clock = <phandle, clock specifier>
clocks = <&osc 2>;

Reference

linux-4.11.3/Documentation/devicetree/bindings/clock/clock-bindings.txt
linux-4.11.3/Documentation/devicetree/bindings/clock/fixed-clock.txt

Explanation_8

談到 compatible property,
就要聯想到 model property,
這兩個 property 建議的 value 格式都是 "manufacturer,model",
那有什麼差別呢?
就看 code 的心得,
開發版製造商 製造開發板,
開發板使用很多的零件,
不是每個零件都是開發板製造商製造的,
如,mediatek 製造整個開發板,
但 charger ic 不是 mediatek 製造的。
model 大多用來描述 開發板的製造商 及 開發板的型號,
以我司的 UxxLxxx 為例,
model = "mediatek,UxxLxxx";
compatible 大多用來描述 零件的製造商 及 零件的型號,
以我司的 UxxLxxx project,charger ic 為例,
compatible = "ti,bq25896";

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
2.2. Devicetree Structure and Conventions
piece 11

  • compatible property
    是用來傳遞字串 給 driver code,driver code 檢查字串,判斷 device tree 的 device node 是否屬於該 driver code 所需要驅動的 device。

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
2.2. Devicetree Structure and Conventions
piece 11

  • fixed-clock
    表示這個 device 是 simple fixed-rate clock sources.

Reference

linux-4.11.3/Documentation/devicetree/bindings/clock/fixed-clock.txt

schematic 有一個 oscillator 8Mhz,
oscillator 是固定的 frequency 8Mhz output,符合 fixed-clock,

Reference

http://www.st.com/content/ccc/resource/technical/document/user_manual/6b/25/05/23/a9/45/4d/6a/DM00093903.pdf/files/DM00093903.pdf/jcr:content/translations/en.DM00093903.pdf
piece 32

但 frequency 是 8Mhz,
為什麼 clock-frequency property 是 0 呢?

linux-4.11.3/arch/arm/boot/dts/stm32f429.dtsi

        clk_hse: clk-hse {
              ...
              clock-frequency = <0>;
              ...
        };

原因就在於 8Mhz 是在另一檔案設定的,

linux-4.11.3/arch/arm/boot/dts/stm32f429-disco.dts

&clk_hse {
        clock-frequency = <8000000>;
};

再來看硬體部分,
上面的線路圖,出現 SB18 SB19 SB20,
SB是什麼呢?
解釋一個名詞 solder bridge 錫橋,
兩個焊點間的細小架橋短路。

Reference

https://www.autodesk.com/products/eagle/blog/solder-bridging-pcb/
https://www.researchmfg.com/2011/02/soldering-defect-symptom/

現在要找尋 clock 被連到 那一隻 pin,
這是前面看過的 schematic,
裡面有三個 solder bridge,

Reference

http://www.st.com/content/ccc/resource/technical/document/user_manual/6b/25/05/23/a9/45/4d/6a/DM00093903.pdf/files/DM00093903.pdf/jcr:content/translations/en.DM00093903.pdf
piece 32

這是 solder bridge 的狀態,
SB18、SB19、SB20 都是 off,

http://www.st.com/content/ccc/resource/technical/document/user_manual/6b/25/05/23/a9/45/4d/6a/DM00093903.pdf/files/DM00093903.pdf/jcr:content/translations/en.DM00093903.pdf
piece 19

所以 oscillaor X3 的 clock output pin PH0-OSC_IN 和 PH1-OSC_OUT 接到 主要 IC STM32F429ZIT6 的 PH0-OSC_IN 和 PH1-OSC_OUT。

Reference

http://www.st.com/content/ccc/resource/technical/document/user_manual/6b/25/05/23/a9/45/4d/6a/DM00093903.pdf/files/DM00093903.pdf/jcr:content/translations/en.DM00093903.pdf
piece 32

主要 IC STM32F429ZIT6 的 PH0-OSC_IN pin 和 PH1-OSC_OUT pin,各自對應到 pin position 23 及 24,又對應到 system 的 OSC_IN 及 OSC_OUT function,

http://www.st.com/content/ccc/resource/technical/document/user_manual/6b/25/05/23/a9/45/4d/6a/DM00093903.pdf/files/DM00093903.pdf/jcr:content/translations/en.DM00093903.pdf
piece 25

看到以下的 schematic,
就可以確定前面所討論的 hse oscillator 相關 hardware wire 有連結到 chip 正確的 pin 。

http://www.st.com/content/ccc/resource/technical/document/datasheet/03/b4/b2/36/4c/72/49/29/DM00071990.pdf/files/DM00071990.pdf/jcr:content/translations/en.DM00071990.pdf
piece 120

Explanation_9

查尋 schematic,並沒有使用 frequency 為 32768 的 oscillator,
這有待研究,
也許 driver 有做什麼修改也不一定!

http://www.st.com/content/ccc/resource/technical/document/user_manual/6b/25/05/23/a9/45/4d/6a/DM00093903.pdf/files/DM00093903.pdf/jcr:content/translations/en.DM00093903.pdf
piece 32

Explanation_10

Example_1

/ {
        #address-cells = <0x1>;    // 在 root node 下使用 1 個 u32 來代表 address。
        #size-cells = <0x0>;       // 在 root node 下使用 0 個 u32 來代表 size,這不是一個很好的範例 使用 #size-cells = <0> 在 memory device,只是想讓各位了解 #size-cells = <0x0> 被使用的結果。
        ...
        ...
        memory {        // memory device
                ...
                reg = <0x90000000>;
                // 0x90000000 是存取 memory 的 address
                ...
	};
        ...
        ...
}

Example_2

/ {
        #address-cells = <0x1>;    // 在 root node 下使用 1 個 u32 來代表 address。
        #size-cells = <0x1>;       // 在 root node 下使用 1 個 u32 來代表 size。
        ...
        ...
        memory {        // memory device
                ...
                reg = <0x90000000 0x800000>;
                // 0x90000000 是存取 memory 的 address
                // 0x800000 是 memory 的 size。
                ...
        };
        ...
        ...
}

Example_3

/ {
        #address-cells = <0x2>;    // 在 root node 下使用 2 個 u32 來代表 address。
        #size-cells = <0x1>;       // 在 root node 下使用 1 個 u32 來代表 size。
        ...
        ...
        memory {        // memory device
                ...
                reg = <0x90000000 00000000 0x800000>;
                // 0x90000000 00000000 是存取 memory 的 address
                // 0x800000 是 memory 的 size。
                ...
	};
        ...
        ...
}

Example_4

/ {
        #address-cells = <0x2>;    // 在 root node 下使用 2 個 u32 來代表 address。
        #size-cells = <0x2>;       // 在 root node 下使用 2 個 u32 來代表 size。
        ...
        ...
        memory {        // memory device
                ...
                reg = <0x90000000 00000000 0x800000 00000000>;
                // 0x90000000 00000000 是存取 memory 的 address
                // 0x800000 00000000 是 memory 的 size。
                ...
        };
        ...
        ...
}

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
2.3. Standard Properties
piece 12

Explanation_11

[label:] node-name[@unit-address] {
      [properties definitions]
      [child nodes]
}

40000000 (16進制)是 unit-address,存取 timer register 的 address,
0x400 是 timer register 的範圍。

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
2.3. Standard Properties
piece 13

Explanation_12

28 (10 進制)是中斷號碼。

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
2.4. Interrupts and Interrupt Mapping
piece 16

Explanation_13

這個 device 目前不能操作,但之後可以 enable,譬如需要 plug-in 的 device

Reference

DevicetreeSpecification Release 0.1
https://www.devicetree.org/
2.3. Standard Properties
piece 12

Explanation_14

第 0 個填 clock phandle,
第 1 個填 clock type,
value 0 代表 gated clocks,
value 1 代表 other clocks,

Reference

linux-4.11.3/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt

Explanation_15

傳遞給 timers2 的 clock 命名為 int,在 driver 中可以使用。

Reference

linux-4.11.3/Documentation/devicetree/bindings/clock/clock-bindings.txt

Explanation_16

指定 準備要做修改的 clock source。

Reference

linux-4.11.3/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt

Explanation_17

重新指定 CLK_LSE 為 CLK_RTC 的 parent clock。

Reference

linux-4.11.3/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt

Explanation_18

發出 17 號中斷,1 有可能指定 active high 或是 active low。

Explanation_19

為 17 號中斷 命名為 alarm。

Explanation_20

phandle for pwrcfg, mandatory to disable/enable backup domain (RTC registers) write protection.

Explanation_21

各家 chip 使用方式不盡相同。

Reference

linux-4.11.3/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt

Explanation_22

rcc device 使用了 clk_hse 及 clk_i2s_ckin 二個 clock。

Explanation_23

phandle for pwrcfg, platform power 相關的控制。

Explanation_24

指定要修改的 clock。

Explanation_25

將上述 clock 設定為 1000000 Hz。

Explanation_26

dma device node 規定要填 4 。

Explanation_27

Example1

    interrupt-controller@e000e100 {
        ...
        ...
        #interrupt-cells = <0x1>;    // 使用 1 個 u32 來表示 interrupt number。
        linux,phandle = <0x2>;
        phandle = <0x2>;
        ...
        ...
    };

Example2

    interrupt-controller@e000e100 {
        ...
        ...
        #interrupt-cells = <0x2>;    // 使用 2 個 u32 來表示 interrupt number。
        linux,phandle = <0x2 0>;
        phandle = <0x2 0>;
        ...
        ...
    };

Example3

    interrupt-controller@e000e100 {
        ...
        ...
        #interrupt-cells = <0x3>;    // 使用 3 個 u32 來表示 interrupt number。
        linux,phandle = <0x2 0 0>;
        phandle = <0x2 0 0>;
        ...
        ...
    };

Explanation_28

DMA address


Reference

http://www.st.com/content/ccc/resource/technical/document/datasheet/03/b4/b2/36/4c/72/49/29/DM00071990.pdf/files/DM00071990.pdf/jcr:content/translations/en.DM00071990.pdf

DMA interrupt number

STM32F429i 有二顆 DMA,
DMA interrupt number 要到 interrupts and event 章節去查詢,




Reference

http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

DMA gated clocks

Documentation/devicetree/bindings/clock/st,stm32-rcc.txt

...
...
 35 Specifying gated clocks
 36 =======================
 37 
 38 The primary index must be set to 0.
 39 
 40 The secondary index is the bit number within the RCC register bank, starting
 41 from the first RCC clock enable register (RCC_AHB1ENR, address offset 0x30).
...
...

Reference

http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

dma-cells

Documentation/devicetree/bindings/dma/stm32-dma.txt

...
...

  1 * STMicroelectronics STM32 DMA controller
  2 
  3 The STM32 DMA is a general-purpose direct memory access controller capable of
  4 supporting 8 independent DMA channels. Each channel can have up to 8 requests.
  5 
  6 Required properties:
  7 - compatible: Should be "st,stm32-dma"
  8 - reg: Should contain DMA registers location and length. This should include
  9   all of the per-channel registers.
 10 - interrupts: Should contain all of the per-channel DMA interrupts in
 11   ascending order with respect to the DMA channel index.
 12 - clocks: Should contain the input clock of the DMA instance.
 13 - #dma-cells : Must be <4>. See DMA client paragraph for more details.
...
...
        #dma-cells = <4>;

Reference

Documentation/devicetree/bindings/dma/stm32-dma.txt

st,mem2mem

Documentation/devicetree/bindings/dma/stm32-dma.txt

...
...
 15 Optional properties:
 16 - resets: Reference to a reset controller asserting the DMA controller
 17 - st,mem2mem: boolean; if defined, it indicates that the controller supports
 18   memory-to-memory transfer
...
...
        st,mem2mem;

Reference

Documentation/devicetree/bindings/dma/stm32-dma.txt

Explanation_29

unit-address

        rcc: rcc@40023810 {



Reference

https://cdn.sparkfun.com/datasheets/Dev/dotNET/CD00225773.pdf

reset-cells

Ex

Reset Provider

...
...
        rcc: rcc@40023810 {
                #reset-cells = <1>;
...
...

Reset Consumer

...
...
        i2c1: i2c@40005400 {
            resets = <&rcc STM32F4_APB1_RESET(I2C1)>;
...
...

kernel/Documentation/devicetree/bindings/reset/reset.txt

 35 #reset-cells:   Number of cells in a reset specifier; Typically 0 for nodes
 36                 with a single reset output and 1 for nodes with multiple
 37                 reset outputs.


kernel/Document/devicetree/bindings/clock/st,stm32-rcc.txt

115 Specifying softreset control of devices
116 =======================================
117 
118 Device nodes should specify the reset channel required in their "resets"
119 property, containing a phandle to the reset device node and an index specifying
120 which channel to use.
121 The index is the bit number within the RCC registers bank, starting from RCC
122 base address.
123 It is calculated as: index = register_offset / 4 * 32 + bit_offset.
124 Where bit_offset is the bit offset within the register.
125 For example, for CRC reset:
126   crc = AHB1RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x10 / 4 * 32 + 12 = 140
127 
128 example:
129 
130         timer2 {
131                 resets  = <&rcc STM32F4_APB1_RESET(TIM2)>;
132         };

Reference

kernel/Documentation/devicetree/bindings/reset/reset.txt
http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

i2c1 unit address


http://www.st.com/content/ccc/resource/technical/document/datasheet/ef/92/76/6d/bb/c2/4f/f7/DM00037051.pdf/files/DM00037051.pdf/jcr:content/translations/en.DM00037051.pdf


http://www.st.com/content/ccc/resource/technical/document/datasheet/ef/92/76/6d/bb/c2/4f/f7/DM00037051.pdf/files/DM00037051.pdf/jcr:content/translations/en.DM00037051.pdf

clock-cells

EX

Provider

        rcc: rcc@40023810 {
            #reset-cells = <1>;
            #clock-cells = <2>;    // 有二個 u32 當作 clock specifier。
            ...

Consumer

timer2: timer@40000000 {
            compatible = "st,stm32-timer";
            reg = <0x40000000 0x400>;
            interrupts = <28>;
            clocks = <&rcc 0 STM32F4_APB1_CLOCK(TIM2)>;    // 使用時需要1個 clock device phandle,2個 u32,1個 用來選擇 gated clocks 類別 或 other clocks 類別,1個用來指定那一個 clock 要被使用,也就是一個是指定 type,一個是指定 type 中的某個 clock。
            status = "disabled";
        };

kernel/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt

Explanation_30

        mac: ethernet@40028000 {    // 看下方的圖。
            compatible = "st,stm32-dwmac", "snps,dwmac-3.50a";
            reg = <0x40028000 0x8000>;    // 範圍大小可能有誤。
            reg-names = "stmmaceth";    // names of the registers.
            interrupts = <61>;
            interrupt-names = "macirq";
            clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
            clocks = <&rcc 0 STM32F4_AHB1_CLOCK(ETHMAC)>,
                    <&rcc 0 STM32F4_AHB1_CLOCK(ETHMACTX)>,
                    <&rcc 0 STM32F4_AHB1_CLOCK(ETHMACRX)>;
            st,syscon = <&syscfg 0x4>;    // system configuration controller,關於 remap,mac phy interface 選擇。
            snps,pbl = <8>;
            snps,mixed-burst;
            status = "disabled";
        };



http://www.st.com/content/ccc/resource/technical/document/datasheet/03/b4/b2/36/4c/72/49/29/DM00071990.pdf/files/DM00071990.pdf/jcr:content/translations/en.DM00071990.pdf
devicetree/bindings/media/st,st-hva.txt



http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

snps,pbl
Programmable Burst Length (tx and rx)
kernel/Documentation/devicetree/bindings/net/stmmac.txt

snps,mixed-burst Program the DMA to use the mixed burst mode
kernel/Documentation/devicetree/bindings/net/stmmac.txt

Explanation_31

Random number generator (RNG)

        rng: rng@50060800 {
            compatible = "st,stm32-rng";
            reg = <0x50060800 0x400>;
            interrupts = <80>;
            clocks = <&rcc 0 STM32F4_AHB2_CLOCK(RNG)>;

        };


http://www.st.com/content/ccc/resource/technical/document/datasheet/03/b4/b2/36/4c/72/49/29/DM00071990.pdf/files/DM00071990.pdf/jcr:content/translations/en.DM00071990.pdf


http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

...
#define STM32F4_AHB2_CLOCK(bit)	(STM32F4_RCC_AHB2_##bit + 0x20)
#define STM32F4_RCC_AHB2_RNG	6
...

kernel/include/dt-bindings/mfd/stm32f4-rcc.h



http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

Explanation_31

        usbotg_hs: usb@40040000 {
            compatible = "snps,dwc2";
            reg = <0x40040000 0x40000>;
            interrupts = <77>;
            clocks = <&rcc 0 STM32F4_AHB1_CLOCK(OTGHS)>;
            clock-names = "otg";
            status = "disabled";
        };


Explanation_32

        pin-controller {
            #address-cells = <1>;
            #size-cells = <1>;
            compatible = "st,stm32f429-pinctrl";
            ranges = <0 0x40020000 0x3000>;
            interrupt-parent = <&exti>;
            st,syscfg = <&syscfg 0x8>;
            pins-are-numbered;

            gpioa: gpio@40020000 {
                gpio-controller;    // Indicates this device is a GPIO controller.    from kernel/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
                #gpio-cells = <2>;
                reg = <0x0 0x400>;
                clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)>;
                st,bank-name = "GPIOA";
            };

ranges

Translating between parent address space and child address space.
value type : (child-bus-address, parent-bus-address, length)
Devicetree Specification Release 0.1

interrupt-parent

指定中斷父親
Devicetree Specification Release 0.1

st,syscfg

Should be phandle/offset pair. The phandle to the syscon node which includes IRQ mux selection register, and the offset of the IRQ mux selection register.
kernel/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt

http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

pins-are-numbered

Specify the subnodes are using numbered pinmux to specify pins.
I don't know yet.

unit-address



http://www.st.com/content/ccc/resource/technical/document/datasheet/03/b4/b2/36/4c/72/49/29/DM00071990.pdf/files/DM00071990.pdf/jcr:content/translations/en.DM00071990.pdf

gpio-cells

 24  - #gpio-cells    : Should be two.
 25                         The first cell is the pin number
 26                         The second one is the polarity:
 27                                 - 0 for active high
 28                                 - 1 for active low

gpio-cells 是 gpio provider 使用的。
kernel/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt

single-gpio ::= <gpio-phandle> <gpio-specifier>

gpio-specifier 需由二個 cell 組成。參考上。
linux-4.11.3/Documentation/devicetree/bindings/gpio/gpio.txt

gpios = <&gpiog 14 0>;

gpios 是 gpio consumer 使用的。
Specify GPIO
kernel/Documentation/devicetree/bindings/gpio/gpio.txt

reg

reg = <0x0 0x400>;

gpio 是一個子節點,
從 ranges 可以得知,child space address 是由 0 開始,
而範圍從以下可得知是 0x400,

http://www.st.com/content/ccc/resource/technical/document/datasheet/03/b4/b2/36/4c/72/49/29/DM00071990.pdf/files/DM00071990.pdf/jcr:content/translations/en.DM00071990.pdf

clocks

                clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)>;
#define STM32F4_AHB1_CLOCK(bit) (STM32F4_RCC_AHB1_##bit)
#define STM32F4_RCC_AHB1_GPIOA	0

kernl/include/dt-bindings/mfd/stm32f4-rcc.h






http://www.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf

Explanation_33

&usart1 {
    pinctrl-0 = <&usart1_pins_a>;
    pinctrl-names = "default";
    status = "okay";
};
65 pinctrl-1:      List of phandles, each pointing at a pin configuration
66                     node within a pin controller.
67 ...
68 pinctrl-n:      List of phandles, each pointing at a pin configuration
69                 node within a pin controller.
70 pinctrl-names:  The list of names to assign states.

Example

&example {
    pinctrl-names = "state_0", "state_1", "state_2";
    pinctrl-0 = <&example_pins_state_0>;
    pinctrl-1 = <&example_pins_state_1>;
    pinctrl-2 = <&example_pins_state_2>;
    status = "okay";
};

Reference

linux-4.11.3/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt

心得

若想知道 property 的真正用法,

還是得回到 driver code 的來看使用方式,
因為 property 的 value 最後還是得傳到 driver code。

posted @ 2017-07-13 19:46  wangchangruei  阅读(8036)  评论(0编辑  收藏  举报