From b2647cbe2fbc104c8240203a11889aabb5928c23 Mon Sep 17 00:00:00 2001
From: Manuel Traut <manut@linutronix.de>
Date: Thu, 10 Jan 2019 13:40:28 +0100
Subject: Device Tree: initial version

This is the initial version of a Device Tree Presentation.

The Presentation includes Background, Scope and Advantages
of Device Tree usage as well as a short explanation of the
Syntax and Usage.

It ends with information about current developments and
references to further information.

Also an excercise for the attendees is defined.

Signed-off-by: Manuel Traut <manut@linutronix.de>
---
 kernel-devel/dts/pres_devicetree_en.tex | 460 ++++++++++++++++++++++++++++++++
 1 file changed, 460 insertions(+)
 create mode 100644 kernel-devel/dts/pres_devicetree_en.tex

(limited to 'kernel-devel/dts/pres_devicetree_en.tex')

diff --git a/kernel-devel/dts/pres_devicetree_en.tex b/kernel-devel/dts/pres_devicetree_en.tex
new file mode 100644
index 0000000..6b6ba5a
--- /dev/null
+++ b/kernel-devel/dts/pres_devicetree_en.tex
@@ -0,0 +1,460 @@
+\input{configpres}
+
+\title{Device Tree}
+\maketitle
+
+\subsection{Device Tree}
+
+\begin{frame}
+\frametitle{Overview}
+\tableofcontents
+\end{frame}
+
+\subsubsection{Background, Scope, Advantages}
+\begin{frame}
+\frametitle{Open Firmware (OF)}
+\begin{itemize}
+\item Designed by Sun in the late 1980's
+\item Popular on PowerPCs
+\item Similar to BIOS or EFI
+\item Integrated shell
+\item Supports FCode: platform/architecture independent bytecode
+\begin{itemize}
+\item Boot-time diagnostics
+\item Configuration code
+\item Device drivers
+\end{itemize}
+\item Defines a standard way to describe the hardware of a system (Device Tree)
+\end{itemize}
+\end{frame}
+
+\begin{frame}
+\frametitle{Device Tree (DT)}
+\begin{itemize}
+\item HW initialization was hardcoded in C before.
+\pause
+\item Derived from the device tree format used by OF.
+\pause
+\item DT spec \url{https://www.devicetree.org/specifications/}
+\pause
+\item DT spec is implemented by Linux, FreeBSD, zephyr, u-boot, Android.
+\pause
+\item Human readable source files: .dts and .dtsi
+\pause
+\item DT compile (dtc) transfers between source and binary (.dtb).
+\pause
+\item The binary format is called Flattened Device Tree (FDT).
+\pause
+\item FDT is passed to the kernel, kernel transfers it into an Expandable Device Tree (EDT).
+\pause
+\item EDT snippets are passed to 'matching' probe functions.
+\end{itemize}
+\end{frame}
+
+\begin{frame}
+\frametitle{DT and Linux}
+\begin{description}
+\item[1995] sparc/prom/tree.c written by David S. Miller
+\pause
+\item[2002] ppc64/kernel/prom.c Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner (IBM)
+\pause
+\item[2005] powerpc/kernel/prom.c copied from ppc64 to powerpc
+\pause
+\item[2007] Stephen Rothwell started to merge code from different architectures into drivers/of/base.c
+\pause
+\item[2009] 98 dts files in v2.6.30 (arm64, microblaze, powerpc)
+\pause
+\item[2011] Grant Likely added OF/DTS support for ARM (32-bit)
+\pause
+\item[2012] 165 dts files in v3.2 (+x86, +openrisc, +arm)
+\pause
+\item[2014] 648 dts files in v3.16 (+metag +c6x +arc +xtensa +mips)
+\pause
+\item[2016] 1199 dts files in v4.9 (+nios2 +h8300 +cris +sh)
+\pause
+\item[2018] 1612 dts files in v4.20 (-cris -metag +nds32)
+\pause
+\item[2019] there are still some board files (e.g. arch/arm/mach-omap1/board-nokia770.c)
+\end{description}
+\pause
+DTS as a part of OF became the quasi standard for describing non-iteratable
+hardware layouts to the Linux kernel.
+\end{frame}
+
+\begin{frame}
+\frametitle{DT Scope}
+Split HW specific information from Kernel binary
+\begin{itemize}
+\item The number and type of CPUs
+\item Base addresses and size of RAM
+\item Busses and bridges
+\item Peripheral device connections
+\item Interrupt controllers and IRQ line connections
+\item Pin multiplexing
+\end{itemize}
+\end{frame}
+
+\begin{frame}
+\frametitle{Advantages}
+\begin{itemize}
+\item Single kernel can support multiple SoCs
+\item Smaller amount of board support code
+\item Xilinx FPGA tools do DTS generation
+\item U-Boot can inspect and modify FDT before booting
+\end{itemize}
+\end{frame}
+
+\subsubsection{Syntax}
+\begin{frame}[fragile]
+\frametitle{The .dts Syntax}
+\includegraphics[width=8cm]{images/device-tree-syntax.jpg}
+\\ \tiny Source: http://wiki.dreamrunner.org
+\normalsize \\ \url{https://git.kernel.org/pub/scm/utils/dtc/dtc.git/plain/Documentation/dts-format.txt}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Example .dts snippet}
+\begin{lstlisting}
+hello@1 {
+  compatible = "virtual,hello", "virtio,hello";
+  index = <1>;
+};
+\end{lstlisting}
+\begin{description}
+\item[Label] None defined
+\item[Node name] hello
+\item[Unit address] 1
+\item[Property 1]
+  \begin{description}
+  \item[Name] compatible
+  \item[Type] String Array
+  \item[Value] ["virtual,hello", "virtio,hello"]
+  \end{description}
+\item[Property 2]
+  \begin{description}
+  \item[Name] index
+  \item[Type] 32bit Array including 1 Value
+  \item[Value] 1
+  \end{description}
+\end{description}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{The compatible property}
+\begin{lstlisting}
+rtc@58 {
+    compatible = "maxim,ds1338","microchip,mc1338";
+};
+\end{lstlisting}
+\begin{itemize}
+\item List of strings
+\item Needed for each node representing a device
+\item Used by the kernel to find a proper device driver
+\item First string is the Devicename: "<manufacturer>,<model>"
+\item Next strings are compatible devices.
+\item Used to allow reuse of existing drivers, but allowing exact name.
+\item Use manufacturer names from Documentation/devicetree/bindings/vendor-prefixes.txt
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Addressing}
+\begin{lstlisting}
+#address-cells = <1>;
+#size-cells = <0>;
+cpu@0 {
+    compatible = "arm,cortex-a9";
+    reg = <0>;
+};
+\end{lstlisting}
+
+\begin{itemize}
+\item \#address-cells and \#size-cells in the parent node define the format of
+      'reg' of the child nodes.
+\item in the above example reg uses 1 address cell and no size cell
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Overwrite values by label}
+\begin{lstlisting}
+$ cat mynode.dtsi
+/ {
+  soc {
+    pic_3: pic@100 {
+      reg = <0x100 0x20 >;
+    };
+  };
+};
+\end{lstlisting}
+
+\begin{lstlisting}
+$ cat my.dts
+#include "my.dtsi"
+&pic_3 {
+  reg = <0x200 0x30 >;
+};
+\end{lstlisting}
+
+\begin{lstlisting}
+$ dtc -O dts my.dts
+/dts-v1/;
+/ {
+  soc {
+    pic_3: pic@100 {
+      reg = <0x200 0x30>;
+    };
+  };
+};
+\end{lstlisting}
+\end{frame}
+
+
+\begin{frame}
+\frametitle{More complex example}
+If deeper understanding is required,
+
+\url{https://elinux.org/Device_Tree_Usage}
+
+is a good entry point. Also
+
+\url{https://elinux.org/Device_Tree_Linux}
+
+explains some Linux specific details.
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Bindings}
+The format of all device/bus specific properties are documented:
+
+Documentation/devicetree/bindings
+\end{frame}
+
+\subsubsection{Usage}
+
+\begin{frame}[fragile]
+\frametitle{Building a DT binary (FDT)}
+Out-of-tree with the Device Tree Compiler
+
+Build a FDT by given DTS
+\begin{lstlisting}
+$ dtc -o my.dtb my.dts
+\end{lstlisting}
+
+The Device Tree Compilier is also able to convert a FDT binary back to the
+human-readable DTS format:
+\begin{lstlisting}
+$ dtc -o my.dts my.dtb
+\end{lstlisting}
+OR in-tree using the Kernel Buildsystem (see next slide)
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Add a new ARM64 board platform to the kernel}
+\begin{lstlisting}
+diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
+--- a/arch/arm64/Kconfig.platforms
++++ b/arch/arm64/Kconfig.platforms
+@@ -318,4 +318,9 @@ config ARCH_ZYNQMP
++config ARCH_MYNEWBOARD
++       bool "My New Board"
++       help
++         This enables support for my new board
++
+\end{lstlisting}
+\begin{lstlisting}
+diff --git a/arch/arm64/boot/dts/arm/Makefile b/arch/arm64/boot/dts/arm/Makefile
+--- a/arch/arm64/boot/dts/arm/Makefile
++++ b/arch/arm64/boot/dts/arm/Makefile
+@@ -5,3 +5,4 @@ dtb-$(CONFIG_ARCH_VEXPRESS) += \
+ dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2f-1xv7-ca53x2.dtb
++dtb-$(CONFIG_ARCH_MYNEWBOARD) += my-new.dtb
+\end{lstlisting}
+\begin{lstlisting}
+diff --git a/arch/arm64/boot/dts/arm/my-new.dts b/arch/arm64/boot/dts/arm/my-new.dts
+new file mode 100644
+--- /dev/null
++++ b/arch/arm64/boot/dts/arm/my-new.dts
+@@ -0,0 +1,16 @@
++/* ARM64 MY BOARD Platform
+[..]
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Passing FDT to the kernel}
+\begin{itemize}
+\item statically linked into the kernel
+\begin{lstlisting}
+# CONFIG_ARM_APPENDED_DTB and CONFIG_ARM_ATAG_DTB_COMPAT
+# needs to be enabled
+$ cat arch/arm64/boot/Image arch/arm64/boot/dts/arm/my.dtb \
+  >> arch/arm/boot/zImage-dtb
+\end{lstlisting}
+\pause
+\item passed to the kernel at boot time\\
+The bootloader passes the DTB address through r2
+\begin{description}
+\item[U-Boot command] boot[mz] <kernel img addr> - <dtb addr>
+\item[Barebox variables] bootm.image, bootm.oftree
+\end{description}
+\pause
+\item FIT image - topic for its own, more details in this presentation:\\
+      \url{https://elinux.org/images/f/f4/Elc2013_Fernandes.pdf}
+\end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{QEMU and FDT}
+Dump dtb
+\begin{lstlisting}
+$ qemu-system-aarch64 -machine virt -cpu cortex-a57 -nographic -m 512 -smp 2 \
+   -device virtio-net-device,netdev=unet \
+   -device ivshmem-doorbell,vectors=1,chardev=chid1 \
+   -chardev socket,path=/tmp/ivshmem_socket,id=chid1 \
+   -kernel /scratch/linux-arm64/arch/arm64/boot/Image \
+   -append "console=ttyAMA0 ip=dhcp root=/dev/nfs nfsroot=10.0.2.2:/nfs/debian,nfsvers=3 rw" \
+   -machine dumpdtb=my.dtb
+\end{lstlisting}
+Virtio and ivshmem devices are iteratable.
+So they are not dumped into the dtb.
+
+Starting Qemu with a dtb:
+\begin{lstlisting}
+$ qemu-system-aarch64 -machine virt -cpu cortex-a57 -nographic \
+   -device virtio-net-device,netdev=unet \
+   -device ivshmem-doorbell,vectors=1,chardev=chid1 \
+   -chardev socket,path=/tmp/ivshmem_socket,id=chid1 \
+   -kernel /scratch/linux-arm64/arch/arm64/boot/Image \
+   -dtb /tmp/my.dtb
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Match a driver and DT node}
+DTS snippet
+\begin{lstlisting}
+hello@1 {
+  compatible = "virtual,hello";
+};
+\end{lstlisting}
+driver source
+\begin{lstlisting}
+static int hello_probe(struct platform_device *pdev) {
+  return 0;
+}
+static const struct of_device_id hello_match[] = {
+  { .compatible = "virtual,hello", }, { }
+};
+static struct platform_driver hello_driver = {
+  .driver = { .name = "hello",
+              .owner = THIS_MODULE,
+              .of_match_table = hello_match, },
+  .probe = hello_probe,
+};
+static int __init hello_init(void) {
+  return platform_driver_register(&hello_driver);
+}
+module_init(hello_init);
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Reading properties in drivers}
+DTS snippet
+\begin{lstlisting}
+hello@1 {
+  compatible = "virtual,hello";
+  index = <1>;
+};
+\end{lstlisting}
+driver source
+\begin{lstlisting}
+static int hello_probe(struct platform_device *pdev) {
+  int ret;
+  u32 value;
+  ret = of_property_read_u32(pdev->dev.of_node, "index", &value);
+  if (ret < 0)
+    pr_err("no index specified\n");
+  return ret;
+}
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{Reading DT/OF properties from userspace}
+\begin{lstlisting}
+$ tree /proc/device-tree
+$ cat /proc/device-tree/compatible
+OR
+$ tree /sys/firmware/devicetree/base
+$ cat /sys/firmware/devicetree/base/compatible
+\end{lstlisting}
+rebuilding DT from user-space:
+\begin{lstlisting}
+$ dtc -I fs /sys/firmware/devicetree/base -o my.dts
+$ dtc -I fs /sys/firmware/devicetree/base -o my.dtb
+\end{lstlisting}
+\end{frame}
+
+\subsubsection{Linux internals}
+
+\begin{frame}
+\frametitle{Source locations}
+\begin{description}
+\item[DTS files] arch/*/boot/dts/*
+\item[Kernel framework] drivers/of/*
+\item[Userspace components] 'scripts/dtc' are imported from
+     \url{https://git.kernel.org/cgit/utils/dtc/dtc.git}
+\item[Docs] Documentation/devicetree
+\end{description}
+\end{frame}
+
+\subsubsection{Future}
+\begin{frame}
+\frametitle{Current development}
+Device Tree Overlays
+\begin{itemize}
+\item Needed to support shields.
+\item Supported by u-boot, but currently not by the kernel.
+\item Status Plumbers Conference '18 \url{https://elinux.org/images/8/86/Overlay_frank.pdf}
+\end{itemize}
+Device Tree Schema
+\begin{itemize}
+\item \url{https://elinux.org/images/6/67/Hkg18-120-devicetreeschema-grantlikely-180404144834.pdf}
+\end{itemize}
+\end{frame}
+
+\begin{frame}
+\frametitle{Further information}
+\begin{itemize}
+\item elinux.org Device Tree wiki\\
+      \url{https://elinux.org/Device_Tree_Reference}
+\item Thomas Petazzoni - Device Tree for Dummies | ELC 2014\\
+      \url{https://www.youtube.com/watch?v=uzBwHFjJ0vU}\\
+      \url{https://elinux.org/images/f/f9/Petazzoni-device-tree-dummies_0.pdf}
+\item \url{https://elinux.org/Device_tree_future}
+\item Read 'Documentation/devicetree/bindings/submitting-patches.txt' if you
+      consider sending sth. related to DT upstream.
+\end{itemize}
+\end{frame}
+
+\begin{frame}
+\frametitle{Excercise}
+\begin{itemize}
+\item Extend the hello module to become a platform driver including a
+      of match table.
+\item Dump the DTB via Qemu and convert it to DTS format.
+\item Add a proper node to the DTS
+      to trigger the probe function of the hello module.
+\item Convert the DTS to DTB format and use it to start Qemu.
+\item Check that the hello module is loaded automatically
+      and its probe function was called.
+\item Add multiple hello nodes to the Device Tree.
+      Check how often the init and probe functions are called.
+\item Extend the hello module to read a property from the hello DTS node.
+\item Add this property to the DTS and check if it's read.
+\end{itemize}
+\end{frame}
+
+\input{tailpres}
-- 
cgit v1.2.3

