\documentclass[aspectratio=169,obeyspaces,spaces,hyphens,dvipsnames]{beamer}
\usepackage[utf8]{inputenc}
\usepackage{minted}
\usepackage{hyperref}

\mode<presentation>
\usetheme{Bootlin}

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

\def\signed #1{{\leavevmode\unskip\nobreak\hfil\penalty50\hskip2em
  \hbox{}\nobreak\hfil(#1)%
  \parfillskip=0pt \finalhyphendemerits=0 \endgraf}}

\newsavebox\mybox
\newenvironment{aquote}[1]
  {\savebox\mybox{#1}\begin{quotation}}
  {\signed{\usebox\mybox}\end{quotation}}

\title{Your newer ARM SoC Linux support check-list!}
\conference{Embedded Linux Conference 2016}
\authors{Gregory CLEMENT}
\email{gregory@bootlin.com}
\institute{Bootlin}
\slidesurl{http://bootlin.com/pub/conferences/2016/elce/clement-arm64-soc-checklist}

\begin{document}
\addtocontents{toc}{\protect\setcounter{tocdepth}{-1}}
\section{Your newer ARM64 SoC Linux check list!}
\addtocontents{toc}{\protect\setcounter{tocdepth}{2}}

\subsection{What is new in the ARM linux kernel since our last check list ?}

\begin{frame}{Gregory CLEMENT}
  \begin{columns}
    \column{0.7\textwidth}
    \begin{itemize}
    \item Embedded Linux engineer and trainer at {\bf Bootlin}
      \begin{itemize}
      \item Embedded Linux {\bf expertise}
      \item {\bf Development}, consulting and training
      \item Strong open-source focus
      \end{itemize}
    \item Open-source contributor
      \begin{itemize}
      \item Contributing to {\bf kernel support} for the Armada 370,
        375, 38x, 39x and Armada XP ARM SoCs and {\bf Armada 3700
        ARM64 SoCs} from Marvell.
      \item Co-maintainer of mvebu sub-architecture (SoCs from Marvell
        Engineering Business Unit)
      \item Living near {\bf Lyon}, France
      \end{itemize}
    \end{itemize}
    \column{0.3\textwidth}
    \includegraphics[width=\textwidth]{common/logo-square.pdf}\\
  \end{columns}
\end{frame}


\begin{frame}[fragile]{Background}
% AArch64 Linux kernel port
%http://lists.infradead.org/pipermail/linux-arm-kernel/2012-September/118539.html
% in 3.7
% https://kernelnewbies.org/Linux_3.7
% https://lwn.net/Articles/506148/


  \begin{columns}
    \column{0.5\textwidth}
    \begin{itemize}
    \item December 2012, initial support for ARM 64-bits merged in the
      kernel 3.7.
    \item No real hardware at this stage.
    \item Support for first \code{arm64} SoC in 3.11 (June 2013).
    \item Support for second \code{arm64} SoC in 3.18 (December 2014 through
      arm-soc).
    \end{itemize}
    \column{0.5\textwidth}
    \begin{block}{}
    \fontsize{6}{7}\selectfont
    \begin{verbatim}
commit 81f56e5375e84689b891e0e6c5a02ec12a1f18d9
Merge: 6c09931b3f98 27aa55c5e512
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Mon Oct 1 11:51:57 2012 -0700

    Pull arm64 support from Catalin Marinas:
     "Linux support for the 64-bit ARM architecture (AArch64)

      Features currently supported:
       - 39-bit address space for user and kernel (each)
       - 4KB and 64KB page configurations
       - Compat (32-bit) user applications (ARMv7, EABI only)
       - Flattened Device Tree (mandated for all AArch64 platforms)
       - ARM generic timers"
\end{verbatim}

    \end{block}
  \end{columns}
\end{frame}

\begin{frame}{Why?}
  \begin{itemize}
  \item New architecture usually comes with new requirements and a new
    development process.
  \item However \code{arm64} is still an ARM architecture.
  \item This talk is an {\bf attempt} to {\bf summarize some of the
      differences and similarities with ARM 32-bits}, and {\bf provide
      guidelines} for developers willing to add support for new ARM
    64-bits SoCs in the mainline Linux kernel.
    \begin{itemize}
    \item but it might be useful for people porting Linux on new
      boards as well.
    \end{itemize}
  \item Part of the talk will be based on Thomas Petazzoni talk at ELC
    2013: "Your new ARM SoC Linux support check-list!" but focusing on
    \code{arm64} and updated for the common part.
  \end{itemize}
\end{frame}


\begin{frame}{ARM 32-bits vs ARM 64-bits}
  \begin{itemize}
    \item ARM 32-bits in kernel: from ARMv4 to ARMv7.
    \item ARM 64-bits: one mode of the ARMv8.
    \item 64-bits mode of ARMv8 is called AARCH64 (gcc).
    \item ARM64 comes with virtualization instructions and other
      improvements.
  \item New Linux kernel architecture not merged with ARM 32-bits:
    \begin{itemize}
    \item Assembly code is different.
    \item System call interface: uses a new ABI.
    \item Platform support already moved in the drivers.
    \item Basic infrastructure should move too.
    \end{itemize}
  \end{itemize}
\end{frame}



\begin{frame}{Know who are the maintainers}
  \begin{itemize}
  \item {\bf Catalin Marinas} and {\bf Will Deacon} are the
    maintainers for the core ARM 64 support.
  \item {\bf Arnd Bergmann} and {\bf Olof Johansson} are the {\em
      arm-soc} maintainers. All the \code{arm64} (and still \code{arm}) SoC code
    must go through them. They ensure consistency between how the
    various SoC families handle similar problems.
% for arm64 mainly config and dt
% drivers soc
  \item Also need to interact with the subsystem maintainers:
    \begin{itemize}
    \item \code{drivers/clocksource}, {\bf Daniel Lezcano}, {\bf Thomas Gleixner}.
    \item \code{drivers/irqchip}, {\bf Thomas Gleixner}, {\bf Jason Cooper}, {\bf Marc Zyngier}.
    \item \code{drivers/pinctrl}, {\bf Linus Walleij}.
    \item \code{drivers/gpio}, {\bf Linus Walleij}, {\bf Alexandre Courbot}.
    \item \code{drivers/clk}, {\bf Stephen Boyd}, {\bf Mike Turquette}.
    \end{itemize}
  \item Primary mailing list:
    \code{linux-arm-kernel@lists.infradead.org}
  \end{itemize}
\end{frame}

\begin{frame}{Where is the code, when to submit?}

  No change since last talk for \code{arm}.

  \begin{itemize}
  \item The {\bf arm-soc} Git tree is at
    \url{https://git.kernel.org/?p=linux/kernel/git/arm/arm-soc.git;a=summary}.
  \item Watch the {\bf for-next} branch that contains what will be
    submitted by the ARM SoC maintainers during the next merge window.
  \item Generally, the ARM SoC maintainers want to have integrated all
    the code from the different ARM sub-architectures a few (two?)
    weeks before Linus opens the merge window.
  \item If you submit your code {\em during} the Linus merge window,
    there is no way it will get integrated at this point: it will have
    to wait for the next merge window.
  \item Usual Linux contribution guidelines apply: people will make
    comments on your code, take them into account, repost. Find the
    good balance between {\bf patience} and {\bf perseverance}.
  \end{itemize}
\end{frame}

\begin{frame}{Existing code?}

  \begin{itemize}
  \item You have existing Linux kernel code to support your SoC?
  \item There are {\bf 50\% chances that you should throw it away
      completely}.
    \begin{itemize}
    \item SoC support code written by SoC vendors used to not comply
      with the Linux coding rules, the Linux infrastructures, to have
      major design issues, to be ugly, etc.
    \item \code{arm64} is still pretty new and SoC vendors didn't have
      time to be too creative.
    \item For \code{arm} some SoC vendors have reduced the gap between
      their internal tree and the mainline kernel.
    \item However some of them still rely on sources based on the old
      fashion kernel.
    \end{itemize}
  \item Of course, existing code is useful as a reference to know how the
    hardware works. But the code to be submitted should still often be
    {\bf written from scratch}.
  \end{itemize}

\end{frame}

\begin{frame}{Step 1: start minimal}
  \begin{center}
    \includegraphics[width=\textwidth]{elements-step1.pdf}
  \end{center}
\end{frame}

\begin{frame}{Device Tree}
  \begin{itemize}
  \item The purpose of the Device Tree is to move a significant part
    of the {\bf hardware description} into a data structure that is no
    longer part of the kernel binary itself.
  \item This data structure, the {\bf Device Tree Source} is compiled
    into a binary {\bf Device Tree Blob}
  \item The {\bf Device Tree Blob} is loaded into memory by the
    bootloader, and passed to the kernel.
  \item Usage of the Device Tree is {\bf mandatory} for all new ARM
    SoCs. No way around it.
  \item For \code{arm64} it is the only part of the port which goes
    under the \code{arch/arm64} directory.
  \end{itemize}
\end{frame}

\begin{frame}{Writing your Device Tree}
  \begin{itemize}
  \item Add one \code{<soc>.dtsi} file in
    \code{arch/arm64/boot/dts/<vendor>/} that describes the devices in
    your SoC.
    \begin{itemize}
    \item You can also have multiple \code{<soc>.dtsi} files including
      each other with the \code{/include/} directive, if you have an
      SoC family with multiple SoCs having common things, but also
      specific things.
    \item The \code{.dtsi} files are also used to keep big amount of
      data like the pinctrl.
    \end{itemize}
  \item Add one \code{<board>.dts} file in
    \code{arch/arm64/boot/dts/<vendor>/} for each of the boards you
    support. It should \code{/include/} the appropriate \code{.dtsi}
    file.
  \item Add a \codehack{dtb-\$(CONFIG\_ARCH\_<yourarch>)} line in
    \code{arch/arm64/boot/dts/<vendor>/Makefile} for all your board
    \code{.dts} files so that all the \code{.dtb}s are automatically
    built.
  \item The main difference with \code{arch/arm}, is the use of a
    directory by vendor. For ARM 32-bits, all the device tree files are
    located in \code{arch/arm/boot/dts/}.
  \end{itemize}
\end{frame}

\begin{frame}{Example on Armada 3700 support}
  \code{armada-37xx.dtsi}
    \begin{itemize}
    \item \code{armada-371x.dtsi}
    \item \code{armada-372x.dtsi}
      \begin{itemize}
      \item Board \code{armada-3720-db.dts}
      \item Board \code{armada-3720-espressobin.dts}
      \end{itemize}
    \end{itemize}
\end{frame}

\begin{frame}[fragile]{{\tt vulcan.dtsi}}
  \begin{columns}
    \column{0.5\textwidth}
    \begin{block}{}
      \fontsize{6}{6}\selectfont
      \begin{minted}{c}
#include <dt-bindings/interrupt-controller/arm-gic.h>

/ {
    model = "Broadcom Vulcan";
    compatible = "brcm,vulcan-soc";
    interrupt-parent = <&gic>;
    #address-cells = <2>;
    #size-cells = <2>;

    /* just 4 cpus now, 128 needed in full config */
    cpus {
        #address-cells = <0x2>;
        #size-cells = <0x0>;

        cpu@0 {
            device_type = "cpu";
            compatible = "brcm,vulcan", "arm,armv8";
            reg = <0x0 0x0>;
            enable-method = "psci";
        };
[...]
    };

    psci {
        compatible = "arm,psci-0.2";
        method = "smc";
    };

      \end{minted}
    \end{block}
    \column{0.5\textwidth}
    \begin{block}{}
      \fontsize{6}{6}\selectfont
      \begin{minted}{perl}
    gic: interrupt-controller@400080000 {
        compatible = "arm,gic-v3";
        #interrupt-cells = <3>;
        #address-cells = <2>;
        #size-cells = <2>;
[...]
    };

    timer {
        compatible = "arm,armv8-timer";
        interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_PPI 14 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>,
                 <GIC_PPI 10 IRQ_TYPE_LEVEL_HIGH>;
    };
[...]
    soc {
        compatible = "simple-bus";
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;

        uart0: serial@402020000 {
            compatible = "arm,pl011", "arm,primecell";
            reg = <0x04 0x02020000 0x0 0x1000>;
            interrupt-parent = <&gic>;
            interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
[...]
        };
    };
};
        \end{minted}
      \end{block}
    \end{columns}
\end{frame}

\begin{frame}[fragile]{{\tt vulcan-eval.dts}}
 \begin{block}{} 
     \fontsize{9}{10}\selectfont
      \begin{minted}{perl}
#include "vulcan.dtsi"

/ {
    model = "Broadcom Vulcan Eval Platform";
    compatible = "brcm,vulcan-eval", "brcm,vulcan-soc";

    memory {
        device_type = "memory";
        reg = <0x00000000 0x80000000 0x0 0x80000000>,  /* 2G @ 2G  */
              <0x00000008 0x80000000 0x0 0x80000000>;  /* 2G @ 34G */
    };

    aliases {
        serial0 = &uart0;
    };

    chosen {
        stdout-path = "serial0:115200n8";
    };
};
      \end{minted}
    \end{block}
\end{frame}

\begin{frame}{No {\tt arch/arm64/mach-<yourarch>} for \code{arm64}}
  \begin{itemize}
  \item \code{ARCH_<yourarch>} option, as well as sub-options for each
    SoC is now directly in the \code{arch/arm64/Kconfig.platforms}
    file
  \item No more C files specific to an SoC family under
    \code{arch/arm64}.
    \begin{itemize}
    \item The SoC features should be handled by the drivers.
    \item If the feature of the SoC can't fit an existing class
      driver, then the code could go to \code{drivers/soc/}.
    \end{itemize}
  \end{itemize}
\end{frame}


\begin{frame}[fragile]{{\tt arch/arm64/Kconfig.platform}}
 \begin{block}{}
    \footnotesize
    \begin{minted}{c}
config ARCH_MYSOC
        bool "Wonderful SoC"
        select CLKSRC_OF
        select GENERIC_IRQ_CHIP
        select GPIOLIB
        select MYSOC_CLK
        select PINCTRL
        select PINCTRL_MYSOC
    \end{minted}
 \end{block}
  \begin{itemize}
  \item Less \code{CONFIG_} symbols that used to be needed for \code{ARM}.
  \item Many symbols are now set by default with \code{ARM64}.
  \end{itemize}

\end{frame}

\begin{frame}{Earlycon support}
  \begin{itemize}
  \item The first thing to have is obviously a mean to get early
    messages from the kernel.
  \item For \code{arm}, {\em earlyprintk} used to be the way to achieve
    this.
    \begin{itemize}
    \item Need to setup the UARTs address at SoCs level early during
      the boot.
    \item Usage of {\em earlyprintk} was not compatible with multiarch
      kernel.
    \end{itemize}
  \item For \code{arm64}, {\em earlycon} is mandatory.
  \item At serial driver level.
  \item Part of \code{console} support.
  \item Declared in the driver by using \code{EARLYCON_DECLARE} and
    \code{OF_EARLYCON_DECLARE}
  \end{itemize}
\end{frame}

\begin{frame}{IRQ controller support}
  \begin{itemize}
  \item If your platform uses the GIC v2 or v3 interrupt controllers,
    there are already drivers in \code{drivers/irqchip}.
  \item Otherwise, implement a new one at the same location.
  \item It must support the \code{SPARSE_IRQ} and \code{irqdomain}
    mechanisms: no more fixed number of IRQs \code{NR_IRQS}: an {\em
      IRQ domain} is dynamically allocated for each interrupt
    controller.
  \item It must support the \code{MULTI_IRQ_HANDLER} mechanism, where
    your \code{DT_MACHINE_START} structure references the {\em IRQ
      controller handler} through its \code{->handle_irq()} field.
  \item In your \code{DT_MACHINE_START} structure, also call the
    initialization function of your IRQ controller driver using the
    \code{->init_irq()} field.
%% new things in the irqchip world?
  \item Instantiated from your Device Tree \code{.dtsi} file.
  \end{itemize}
\end{frame}

\begin{frame}{Timer driver}
  \begin{itemize}
  \item Should be implemented in \code{drivers/clocksource}.
  \item It must register:
    \begin{itemize}
    \item A {\em clocksource} device, which using a free-running
      timer, provides a way for the kernel to keep track of passing
      time. See \code{clocksource_mmio_init()} if your timer value
      can be read from a simple memory-mapped register, or
      \code{clocksource_register_hz()} for a more generic solution.
    \item A {\em clockevents} device, which allows the kernel to
      program a timer for one-shot or periodic events notified by an
      interrupt. See \code{clockevents_config_and_register()}
    \end{itemize}
  \item The driver must have a Device Tree binding, and the device be
    instantiated from your Device Tree \code{.dtsi} file.
  \end{itemize}
\end{frame}

\begin{frame}{Serial port driver}
  \begin{itemize}
  \item These days, many \code{arm} and \code{arm64} SoCs use either a
    8250-compatible UART, or the PL011 UART controller from ARM. In
    both cases, Linux already has a driver.
    \begin{itemize}
    \item Just need to instantiate devices in your \code{.dtsi} file,
      and mark those that are available on a particular board with
      \code{status = "okay"} in the \code{.dts} file.
    \end{itemize}
  \item If you have a custom UART controller, then get ready for more
    fun. You'll have to write a complete driver in
    \code{drivers/tty/serial}.
    \begin{itemize}
    \item A platform driver, with Device Tree binding, integrated with
      the {\em uart} and {\em console} subsystems
    \item Do not forget to include the {\em earlycon} support.
    \item The maintainer is Greg Kroah-Hartmann.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{End of step 1}
  \begin{itemize}
  \item At this point, your system should boot all the way to a shell
  \item You don't have any storage device driver for now, but you can
    boot into a minimal root filesystem embedded inside an {\em
      initramfs}.
  \item For \code{arm64}, the kernel does not decompress itself, so if
    there is no support in the bootloader too, the kernel image can be
    pretty large: around 20MB.
  \item Time to submit your basic \code{arm64} SoC support. Don't wait to have
    all the drivers and all the features: submit something minimal
    {\bf as soon as possible}.
  \end{itemize}
\end{frame}

\begin{frame}{Step 2: more core infrastructure}
  \begin{center}
    \includegraphics[width=\textwidth]{elements-step2.pdf}
  \end{center}
\end{frame}

\begin{frame}{The clock framework}
  \begin{itemize}
  \item A proper {\em 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.
    \item Provides a {\em debugfs} representation of the clock tree.
    \item Is implemented in \path{drivers/clk}.
    \item See \code{Documentation/clk.txt}.
    \item See also  http://bootlin.com/pub/conferences/2013/elce/common-clock-framework-how-to-use-it/common-clock-framework-how-to-use-it.pdf
    \item The new trend is to only have one node in the device tree
      which will expose all the clocks that can be consumed.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}[fragile]{Clock framework, the driver side}
  From \path{drivers/serial/tty/amba-pl011.c}.
  \begin{columns}
    \column{0.5\textwidth}
    \begin{block}{}
      \tiny
      \begin{minted}{c}
pl011_startup()
{
        [...]
        clk_prepare_enable(uap->clk);
        uap->port.uartclk = clk_get_rate(uap->clk);
        [...]
}
pl011_shutdown()
{
        [...]
        clk_disable_unprepare(uap->clk);
}
pl011_probe()
{
        [...]
        uap->clk = clk_get(&dev->dev, NULL);
        [...]
}
pl011_remove()
{
        [...]
        clk_put(uap->clk);
        [...]
}
      \end{minted}
    \end{block}
    \column{0.5\textwidth}
    \begin{itemize}
    \item The \code{remove()} part could be avoided by using the
      managed API: \code{devm_clk_get()}
    \end{itemize}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{Clock framework, declaration of clocks in DT}
  From \path{arch/arm/boot/dts/sun6i-a31.dtsi}
  \begin{columns}
    \column{0.5\textwidth}
    \begin{block}{}
      \tiny
      \begin{minted}{perl}
clocks {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    osc24M: osc24M {
        #clock-cells = <0>;
        compatible = "fixed-clock";
        clock-frequency = <24000000>;
    };

    osc32k: clk@0 {
        #clock-cells = <0>;
        compatible = "fixed-clock";
        clock-frequency = <32768>;
        clock-output-names = "osc32k";
    };
      \end{minted}
    \end{block}
    \column{0.5\textwidth}
    \begin{block}{}
      \tiny
      \begin{minted}{perl}
[...]
}
soc@01c00000 {
[...]
        ccu: clock@01c20000 {
        compatible = "allwinner,sun6i-a31-ccu";
        reg = <0x01c20000 0x400>;
        clocks = <&osc24M>, <&osc32k>;
        clock-names = "hosc", "losc";
        #clock-cells = <1>;
        #reset-cells = <1>;
    };
[...]
};
      \end{minted}
    \end{block}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{Clock framework, devices referencing their clocks}
  From \path{arch/arm/boot/dts/sun6i-a31.dtsi}
  \small
  \begin{block}{}
    \begin{minted}{perl}
[...]
uart0: serial@01c28000 {
    compatible = "snps,dw-apb-uart";
    reg = <0x01c28000 0x400>;
    interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
    reg-shift = <2>;
    reg-io-width = <4>;
    clocks = <&ccu CLK_APB2_UART0>;
    resets = <&ccu RST_APB2_UART0>;
    dmas = <&dma 6>, <&dma 6>;
    dma-names = "rx", "tx";
    status = "disabled";
};
[...]
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}{Clock framework: summary}
  \begin{center}
    \includegraphics[width=\textwidth]{clock-framework.pdf}
  \end{center}
\end{frame}

\begin{frame}{Introduction to pin muxing}
  \begin{itemize}
  \item SoCs integrate many more peripherals than the number of
    available pins allows to expose.
  \item Many of those pins are therefore {\bf multiplexed}: they can
    either be used as function A, {\em or} function B, {\em or}
    function C, {\em or} a GPIO.
  \item Example of functions are:
    \begin{itemize}
      \item parallel LCD lines
      \item SDA/SCL lines for I2C buses
      \item MISO/MOSI/CLK lines for SPI
      \item RX/TX/CTS/DTS lines for UARTs
      \end{itemize}
    \item This muxing is {\bf software-configurable}, and depends on
      {\bf how the SoC is used on each particular board}.
  \end{itemize}
\end{frame}

\begin{frame}{Pin muxing: principle}
  \begin{center}
    \includegraphics[height=0.7\textheight]{pin-muxing-principle.pdf}
  \end{center}
\end{frame}

\begin{frame}{The pin-muxing subsystem}
  \begin{itemize}
  \item The new {\bf pinctrl} subsystem aims at solving those problems
  \item Mainly developed and maintained by Linus Walleij, from
    Linaro/ST-Ericsson
  \item Implemented in \path{drivers/pinctrl}
  \item Provides:
    \begin{itemize}
    \item An API to register {\em pinctrl driver}, i.e. entities
      knowing the list of pins, their functions, and how to configure
      them. Used by SoC-specific drivers to expose pin-muxing
      capabilities.
    \item An API for {\em device drivers} to request the muxing of a
      certain set of pins.
    \item An interaction with the {\em GPIO} framework.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{The pin-muxing subsystem: diagram}
  \begin{center}
    \includegraphics[width=\textwidth]{pinctrl-subsystem.pdf}
  \end{center}
\end{frame}

\begin{frame}[fragile]{Declaring pin groups in the SoC {\tt dtsi}}
  \begin{itemize}
  \item From \path{arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi}.
  \item Declares the {\em pinctrl} device and various pin groups.
  \end{itemize}
  \tiny
  \begin{columns}
    \column{0.5\textwidth}
    \begin{block}{}
      \begin{minted}{perl}
pinctrl_aobus: pinctrl@14 {
    compatible = "amlogic,meson-gxbb-aobus-pinctrl";
    #address-cells = <2>;
    #size-cells = <2>;
    ranges;

    gpio_ao: bank@14 {
        reg = <0x0 0x00014 0x0 0x8>,
              <0x0 0x0002c 0x0 0x4>,
              <0x0 0x00024 0x0 0x8>;
        reg-names = "mux", "pull", "gpio";
        gpio-controller;
        #gpio-cells = <2>;
    };
      \end{minted}
    \end{block}
    \column{0.5\textwidth}
    \begin{block}{}
      \begin{minted}{perl}
    uart_ao_a_pins: uart_ao_a {
        mux {
            groups = "uart_tx_ao_a", "uart_rx_ao_a";
            function = "uart_ao";
        };
    };
[...]
    i2c_ao_pins: i2c_ao {
    mux {
        groups = "i2c_sck_ao", "i2c_sda_ao";
        function = "i2c_ao";
    };
};
      \end{minted}
    \end{block}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{Associating devices with pin groups, board {\tt dts}}
  \begin{itemize}
  \item From \path{arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts}.
  \end{itemize}
  \scriptsize
  \begin{block}{}
    \begin{minted}{perl}
[...]
&uart_AO {
    status = "okay";
    pinctrl-0 = <&uart_ao_a_pins>;
    pinctrl-names = "default";
};

[...]
&i2c_A {
    status = "okay";
    pinctrl-0 = <&i2c_a_pins>;
    pinctrl-names = "default";
};

    \end{minted}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Device drivers requesting pin muxing}

  \begin{itemize}
  \item From \path{drivers/mmc/host/mxs-mmc.c}
  \end{itemize}
  \small
  \begin{block}{}
    \begin{minted}{c}
static int mxs_mmc_probe(struct platform_device *pdev)
{
    [...]
    pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
    if (IS_ERR(pinctrl)) {
        ret = PTR_ERR(pinctrl);
        goto out_mmc_free;
    }
    [...]
}
    \end{minted}
  \end{block}
\end{frame}

\begin{frame}{GPIO}

  \begin{itemize}
  \item All GPIO drivers, including drivers for GPIO controllers
    internal to the SoC must be in \code{drivers/gpio}.
  \item If the GPIO pins are muxed, the driver must interact with the
    {\em pinctrl} subsystem to get the proper muxing:
    \code{pinctrl_request_gpio()} and \code{pinctrl_free_gpio()}.
  \end{itemize}
\end{frame}

\begin{frame}{Step 3: more drivers, advanced features}
  \begin{center}
    \includegraphics[width=\textwidth]{elements-step3.pdf}
  \end{center}
\end{frame}

\begin{frame}{Device drivers}
  \begin{itemize}
  \item Each device driver must have a {\bf device tree binding}.
    \begin{itemize}
    \item A {\em binding} describes the {\em compatible} string and
      the properties that a DT node instantiating the device must
      carry.
    \item The binding must be documented in
      \code{Documentation/devicetree/bindings}.
    \end{itemize}
  \item Pay attention of the 64-bits support
    \begin{itemize}
    \item \code{arm64} SoCs reused driver developed for ARM 32-bits.
    \item Driver supposed to be portable,
    \item However being used only on 32-bits architecture some bugs
      could have been missed.
    \item Use \code{uintptr_t} to cast pointer.
    \item Pay attention to the peripheral bus which can have a smaller
      size than the CPU bus.
    \end{itemize}
  \end{itemize}
\end{frame}

\begin{frame}{Conclusion}
  \begin{itemize}
  \item The code in the \code{arch/arm64} tree is cleaner than the one
    in \code{arm/soc}.
  \item It benefits on all the consolidation done in \code{arch/arm}
    without having to deal with legacy code.
  \item Adding an initial support for a new ARM64 SoCs needs very few
    line of code now.
  \item However some of the complexity is hidden in a firmware (SCPI
    and PSCI) and power management is still challenging.
  \end{itemize}
\end{frame}

\begin{frame}
  \begin{center}
  \Huge
  Questions?\\
  \vspace{1.5cm}
  \huge
  Gregory CLEMENT\\
  \large
  \vspace{0.5cm}
  \code{gregory.clement@bootlin.com}
  \vspace{0.5cm}
  \newline Slides under CC-BY-SA 3.0\\
  \scriptsize
  \url{http://bootlin.com/pub/conferences/2016/elce/clement-arm64-soc-checklist}
  \end{center}
\end{frame}

\end{document}
