\documentclass[obeyspaces,spaces,hyphens]{beamer}
\usepackage[utf8]{inputenc}
\usepackage{minted}

\mode<presentation>
\usetheme{Bootlin}

\newcommand{\codehack}[1]{{\usebeamercolor[fg]{code} {\tt #1}}}

\title{ARM support in the Linux kernel}
\authors{Thomas Petazzoni}
\institute{Bootlin}

\usepackage{hyperref}

\begin{document}

\begin{frame}{FOSDEM 2013}
  \begin{columns}[c]
   \column{0.6\textwidth}
     \huge
     ARM support in the Linux kernel\\
     \vspace{2cm}
     \normalsize
     Thomas Petazzoni\\
     {\bf Bootlin}\\
     {\em thomas.petazzoni@bootlin.com}
     \column{0.4\textwidth}
     \includegraphics[width=\textwidth]{armada.jpg}
   \end{columns}
\end{frame}

\begin{frame}{Thomas Petazzoni}
  \begin{itemize}
  \item Embedded Linux engineer and trainer at Bootlin since
    2008
    \begin{itemize}
    \item Embedded Linux {\bf development}: kernel and driver
      development, system integration, boot time and power
      consumption optimization, consulting, etc.
    \item Embedded Linux {\bf training}, Linux driver development training
      and Android system development training, with materials freely
      available under a Creative Commons license.
    \item \url{http://bootlin.com}
    \end{itemize}
  \item Contributing the {\bf kernel support for the new Armada 370
      and Armada XP} ARM SoCs from Marvell.
  \item Major contributor to {\bf Buildroot}, an open-source, simple and
    fast embedded Linux build system
  \item Living in {\bf Toulouse}, south west of France
  \end{itemize}
\end{frame}

\begin{frame}{Agenda}
  \begin{itemize}
  \item Background on the ARM architecture and Linux support
  \item The problems
  \item Changes in the ARM kernel support
  \item Getting the support for a SoC in mainline, story of Armada
    370/XP
  \end{itemize}
\end{frame}

\begin{frame}{From the ARM architecture to a board}
  \begin{center}
    \includegraphics[width=\textwidth]{from-arch-to-board.pdf}
  \end{center}
\end{frame}

\begin{frame}{From the ARM architecture to a board, examples}
  \begin{center}
    \includegraphics[width=\textwidth]{from-arch-to-board-examples.pdf}
  \end{center}
\end{frame}

\begin{frame}{Schematic view of a board}
  \begin{center}
    \includegraphics[height=0.8\textheight]{arm-soc.pdf}
  \end{center}
\end{frame}

\begin{frame}{No standardization}
  \begin{itemize}
  \item Beyond the ARM core itself, a lot of freedom is left to the
    SoC vendor.
  \item There is {\bf no standard} for the devices, the management of
    clocks, pinmuxing, IRQ controllers, timers, etc.
    \begin{itemize}
    \item Note: some things like IRQ controllers and timers are now
      standardized.
    \end{itemize}
  \item There {\bf isn't a mechanism} to enumerate the devices
    available inside the SoC. All devices have to be known by the
    kernel.
  \end{itemize}
\end{frame}

\begin{frame}{``Old'' ARM code organization in the Linux kernel}
  \begin{itemize}
  \item \code{arch/arm/}
    \begin{itemize}
    \item \code{arch/arm/{kernel,mm,lib,boot}/}\\
      The core ARM kernel. Contains the code related to the ARM core
      itself (MMU, interrupts, caches, etc.). Relatively small
      compared to the SoC-specific code.
    \item \code{arch/arm/mach-<foo>/}\\
      The SoC-specific code, and board-specific code, for a given SoC
      family.
      \begin{itemize}
      \item \code{arch/arm/mach-<foo>/board-<bar>.c}.\\
        The board-specific code.
      \end{itemize}
    \end{itemize}
  \item \code{drivers/}\\
    The device drivers themselves.
  \end{itemize}
\end{frame}

\begin{frame}{Issue \#1: too much code, lack of review}

  \begin{itemize}
  \item {\bf Exploding number of ARM SoC}, from different vendors
  \item The historical maintainer, Russell King, got {\bf overflowed
      by the amount of code} to review.
  \item Code started to flow directly from sub-architecture
    maintainers directly to Linus Torvalds.
  \item Focus of each sub-architecture teams on {\bf their own
      problems}, no vision of the other sub-architectures.
  \item Consequences: lot of code {\bf duplication}, {\bf missing
      common infrastructures}, maintenability problems, etc.
  \item Linus, March 2011: {\em Gaah. Guys, this whole ARM thing is a
      f*cking pain in the ass}.
  \end{itemize}

\end{frame}

\begin{frame}{Issue \#2: the need for multiplatform kernel}

  \begin{itemize}
  \item On x86 PC, one can build a {\bf single kernel image} (with
    many modules) that boots and work on all PCs
  \item Good for distributions: they can ship a single kernel image.
  \item On ARM, it was {\bf impossible to build a single kernel} that
    would boot on systems using different SoCs.
  \item Issue for distributions: they have to build and maintain a
    kernel image almost for each ARM hardware platform they want to
    support.
  \item Need for {\bf ARM multiplatform support} in the kernel.
  \end{itemize}

\end{frame}

\begin{frame}{Change \#1: {\em arm-soc} and maintainers}

  \begin{columns}
    \column{0.6\textwidth}
    \begin{itemize}
    \item A new maintainer team for the ARM sub-architectures: Arnd
      Bergmann (Linaro) and Olof Johansson (Google)
    \item All the ARM SoC-specific code goes through them, in a tree
      called {\bf arm-soc}
    \end{itemize}
    \column{0.4\textwidth}
    \includegraphics[width=\textwidth]{maintainers.pdf}
  \end{columns}
  \begin{itemize}
  \item They send the changes accumulated in {\bf arm-soc} to Linus
    Torvalds.
  \item Those maintainers have a cross-SoC view: detection of things
    that should be factorized, consistency accross SoC-specific code.
  \item Core ARM changes continue to go through Russell King.
  \end{itemize}
\end{frame}

\begin{frame}{Change \#2: Device Tree}
  \begin{itemize}
  \item Most devices inside an ARM SoC and on the board cannot be
    dynamically enumerated: they have to be {\bf statically
      described}.
  \item The old way of doing this description was by using {\bf C
      code}, registering \code{platform_device} structures for each
    hardware device.
  \item This has been replaced by a hardware description done in
    structure separated from the kernel, called the {\bf Device Tree}.
    \begin{itemize}
      \item Also used on PowerPC, Microblaze, ARM64, Xtensa, OpenRisc, etc.
      \end{itemize}
  \item The {\em Device Tree Source}, in text format, gets compiled
    into a {\em Device Tree Blob}, in binary format, thanks to the
    {\em Device Tree Compiler}.
    \begin{itemize}
    \item Sources are stored in \code{arch/arm/boot/dts}
    \end{itemize}
  \item At boot time, the kernel parses the {\em Device Tree} to
    instantiate the available devices.
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Change \#2: Before the Device Tree...}
  From \code{arch/arm/mach-at91/at91sam9263_devices.c}
  \tiny
  \begin{minted}{c}
static struct resource udc_resources[] = {
        [0] = {
                .start  = AT91SAM9263_BASE_UDP,
                .end    = AT91SAM9263_BASE_UDP + SZ_16K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
                .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
                .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
};

static struct platform_device at91_udc_device = {
        .name           = "at91_udc",
        .id             = -1,
        .dev            = {
                                .platform_data          = &udc_data,
        },
        .resource       = udc_resources,
        .num_resources  = ARRAY_SIZE(udc_resources),
};

some_init_code() {
        platform_device_register(&at91_udc_device);
}
\end{minted}
\end{frame}

\begin{frame}[fragile]{Change \#2: SoC Device Tree example}
\tiny
\begin{verbatim}
/include/ "skeleton.dtsi"
/ {
        compatible = "brcm,bcm2835";
        model = "BCM2835";
        interrupt-parent = <&intc>;

        chosen {
                bootargs = "earlyprintk console=ttyAMA0";
        };

        soc {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
                ranges = <0x7e000000 0x20000000 0x02000000>;

                [...]
                intc: interrupt-controller {
                        compatible = "brcm,bcm2835-armctrl-ic";
                        reg = <0x7e00b200 0x200>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
                };
                uart@20201000 {
                        compatible = "brcm,bcm2835-pl011", "arm,pl011", "arm,primecell";
                        reg = <0x7e201000 0x1000>;
                        interrupts = <2 25>;
                        clock-frequency = <3000000>;
                        status = "disabled";
                };
        };
};
\end{verbatim}
\end{frame}

\begin{frame}[fragile]{Change \#2: Board Device Tree example}
\tiny
\begin{verbatim}
/dts-v1/;
/memreserve/ 0x0c000000 0x04000000;
/include/ "bcm2835.dtsi"

/ {
        compatible = "raspberrypi,model-b", "brcm,bcm2835";
        model = "Raspberry Pi Model B";

        memory {
                reg = <0 0x10000000>;
        };
        soc {
                uart@20201000 {
                      status = "okay";
                };
        };
};
\end{verbatim}
\end{frame}

\begin{frame}{Change \#2: Device Tree inheritance}
  \begin{center}
    \includegraphics[width=\textwidth]{dts-hierarchy.pdf}
  \end{center}
\end{frame}

\begin{frame}{Change \#2: Booting with a Device Tree}
  \begin{center}
    \includegraphics[width=\textwidth]{kernel-and-dtb.pdf}
  \end{center}
\end{frame}

\begin{frame}{Change \#3: Multiplatform kernel}
  \begin{itemize}
  \item Fits the need of distributions willing to build a single
    kernel image that works on many ARM platforms.
  \item The SoC choice now contains a {\bf Allow multiple platforms to
      be selected} option, and all the SoC families that are
    compatible with this can be compiled together in the same kernel.
    \begin{itemize}
    \item There is still a split between ARMv4/ARMv5 on one side, and
      ARMv6/ARMv7 on the other side.
    \end{itemize}
  \item A {\bf lot of changes} have been done in the ARM kernel to
    make this possible: avoid two different platforms from defining
    the same symbol, from using the same header names, no more
    {\tt \#ifdef} but runtime detection instead.
  \item The support for all new SoCs {\bf must use the multiplatform}
    mechanism.
  \end{itemize}
\end{frame}

\begin{frame}{Change \#4: Pinctrl subsystem, introduction}
  \begin{center}
    \includegraphics[width=0.8\textwidth]{pin-muxing-principle.pdf}
  \end{center}
\end{frame}

\begin{frame}{Change \#4: Pinctrl subsystem, old code}
  \begin{itemize}
  \item Each ARM sub-architecture had its own pin-muxing code
  \item The API was specific to each sub-architecture
  \item A lot of similar functionality implemented in different ways
  \item The pin-muxing had to be done at the SoC level, and couldn't
    be requested by device drivers
  \end{itemize}
\end{frame}

\begin{frame}{Change \#4: Pinctrl subsystem, new subsystem}
  \begin{center}
    \includegraphics[width=\textwidth]{pinctrl-subsystem.pdf}
  \end{center}
\end{frame}

\begin{frame}{Change \#5: Clocks}
  \begin{itemize}
  \item In a System-on-Chip, all peripherals are driven by one or more
    {\bf clocks}.
  \item Those clocks are organized in a {\bf tree}, and often are {\bf
      software configurable}.
  \item Since quite some time, the kernel had a simple API:
    \code{clk_get}, \code{clk_enable}, \code{clk_disable},
    \code{clk_put} that were used by device drivers.
  \item Each ARM sub-architecture had its {\bf own implementation} of this
    API.
  \item Does not work for {\bf multiplatform} kernels.
  \item Does not allow {\bf code sharing}, and common mechanisms.
  \end{itemize}
\end{frame}

\begin{frame}{Change \#5: Common clock framework}
  \begin{itemize}
  \item A proper {\bf common clock framework} has been added in kernel
    3.4, released in May 2012
  \item This framework:
    \begin{itemize}
    \item Implements the \path{clk_get}, \path{clk_put},
      \path{clk_prepare}, \path{clk_unprepare}, \path{clk_enable},
      \path{clk_disable}, \path{clk_get_rate}, etc. {\bf API for usage
        by device drivers}
    \item Implements {\bf some basic clock drivers} (fixed rate,
      gatable, divider, fixed factor, etc.) and allows the
      implementation of {\bf custom clock drivers} using
      \code{struct clk_hw} and \code{struct clk_ops}
    \item Allows to declare the available clocks and their association
      to devices in the Device Tree (preferred) or statically in the
      source code (old method)
    \item Provides a {\em debugfs} representation of the clock tree
    \item Is implemented in \path{drivers/clk}
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Change \#5: Common clock framework architecture}
  \begin{center}
    \includegraphics[width=\textwidth]{clock-framework.pdf}
  \end{center}
\end{frame}

\begin{frame}{Change \#6: More things in {\tt drivers/}}
  \begin{itemize}
  \item Another goal of the ARM cleanup is to have less code in
    \code{arch/arm} and create proper drivers and related
    infrastructures.
  \item For example
    \begin{tabular}{|c|c|}
      \hline
      IRQ controller drivers & \code{drivers/irqchip/} \\
      Timer drivers & \code{drivers/clocksource/} \\
      PCI host controller drivers & \code{drivers/pci/host/} \\
      Clock drivers & \code{drivers/clk/} \\
      Pinmux drivers & \code{drivers/pinctrl/} \\
      \hline
    \end{tabular}
  \end{itemize}
\end{frame}

\begin{frame}{Armada 370/XP, step 1}
  \begin{center}
    \includegraphics[width=0.8\textwidth]{armada-370-xp-step1.pdf}
  \end{center}
  Went into Linux 3.6, 10 patches
\end{frame}

\begin{frame}{Armada 370/XP, step 2}
  \begin{center}
    \includegraphics[width=0.8\textwidth]{armada-370-xp-step2.pdf}
  \end{center}
  Went into Linux 3.7, 35 patches
\end{frame}

\begin{frame}{Armada 370/XP, step 3}
  \begin{center}
    \includegraphics[width=0.8\textwidth]{armada-370-xp-step3.pdf}
  \end{center}
  Went into Linux 3.8, 99 patches
\end{frame}

\begin{frame}{Armada 370/XP, step 4}
  \begin{center}
    \includegraphics[width=0.8\textwidth]{armada-370-xp-step4.pdf}
  \end{center}
  Hopefully going in 3.9 :-)
\end{frame}

\begin{frame}{Getting an ARM SoC in mainline}
  \begin{itemize}
  \item {\bf Throw away the vendor BSP code}. Most likely it is
    completely crappy. You have to start from scratch.
  \item {\bf Start small}, and send code piece by piece. Don't wait to
    have everything fully working.
  \item {\bf Comply with the latest infrastructure changes}: Device
    Tree, clock framework, pinctrl subsystem. They are mandatory.
  \item {\bf Read and post to the LAKML}, Linux ARM Kernel Mailing
    List
  \item {\bf Listen to reviews and comments}, and repost updated
    versions regularly.
  \end{itemize}
\end{frame}

\begin{frame}
  \begin{center}
  \Huge
  Questions?\\
  \vspace{1.5cm}
  \huge
  Thomas Petazzoni\\
  \large
  \vspace{0.5cm}
  \code{thomas.petazzoni@bootlin.com}
  \vspace{1.0cm}\\
  \normalsize
  Thanks to Gregory Clement (Bootlin, working with me on
  Marvell mainlining), Lior Amsalem and Maen Suleiman (Marvell)\\
  \vspace{0.5cm}
  Slides under CC-BY-SA 3.0\\
  \scriptsize
  \url{http://bootlin.com/pub/conferences/2013/fosdem/arm-support-kernel/}
  \end{center}
\end{frame}

\end{document}
