+ All Categories
Home > Documents > Embedded Linux: an overview of a modern kernel approach · 2019. 9. 10. · Embedded Linux: an...

Embedded Linux: an overview of a modern kernel approach · 2019. 9. 10. · Embedded Linux: an...

Date post: 20-Oct-2020
Category:
Upload: others
View: 8 times
Download: 0 times
Share this document with a friend
44
Embedded Linux: an overview of a modern kernel approach Fabio Estevam Fabio Estevam Freescale Semiconductors Freescale Semiconductors [email protected] [email protected]
Transcript
  • Embedded Linux: an overview of a modern kernel approach

    Fabio EstevamFabio EstevamFreescale Semiconductors Freescale Semiconductors [email protected]@gmail.com

  • Agenda

    ● The need for code standardization in the ARM world

    ● Device Tree● Pinctrl● Common clock framework● Regmap / kexec● Hints for getting started with Embedded Linux

  • Typical ARM SoC

  • Diversity in the ARM kernel

    ● ARM9, ARM11, Cortex A8, A9, A7, M4, etc● Several ARM silicon vendors● Several ARM families within the same vendor● ARM is the core architecture, but it is up to the

    silicon vendor to put all the 'pieces' together into the SoC

  • Main components of an Embedded Linux system

    ● Bootloader● Kernel● Root file system

  • Mainline kernel vs vendor kernel

    ● Mainline kernel is the official kernel that is maintained by Linus Torvalds available at kernel.orgkernel.org

    ● Vendor kernel is usually stuck at an old kernel revision and it is not supported by the kernel community

  • The need for putting order in the chaos

    • Linus Torvald’s message in the ARM kernel list (April, 2011):

    “Hint for anybody on the arm list… People need to realize that the endless amounts of new pointless platform code is a problem, and since my only recourse is to say ‘if you don’t seem to try to make an effort to fix it, I won’t pull from you’, that is what I’ll eventually be doing.”

  • Lots of consolidation work in the ARM kernel

    • Wide adoption of device tree• Common clock framework• Pinctrl framework• ARM subsystem maintainers: Olof Johansson and Arnd Bergmann

    • Quote from Linus at LinuxCon SanDiego (August,2012)

    “ARM has gone from a constant headache every merge window to an outstanding Linux citizen.”

  • Device Tree Concept

    • Standard Hardware representation to the operational system

    • Operational system agnostic• Located at arch/arm/boot/dts• Power.org™ Standard for Embedded Power Architecture™ Platform Requirements (ePAPR) http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf

    • Presentation from Free-Electrons: https://www.youtube.com/watch?v=m_NyYEBxfn8

    http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdfhttp://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdfhttp://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf

  • The ‘Old’ Board File Method

    • arch/arm/mach-mx6/board-mx6sl_evk.cstatic int mx6_evk_spi_cs[] = {

    MX6_BRD_ECSPI1_CS0,};

    static const struct spi_imx_master mx6_evk_spi_data __initconst = {.chipselect = mx6_evk_spi_cs,.num_chipselect = ARRAY_SIZE(mx6_evk_spi_cs),

    };

    static struct flash_platform_data m25p32_spi_flash_data = {.name = "m25p32",.parts = m25p32_partitions,.nr_parts = ARRAY_SIZE(m25p32_partitions),.type = "m25p32",

    };

    static struct spi_board_info m25p32_spi0_board_info[] __initdata = {{/* The modalias must be the same as spi device driver name */.modalias = "m25p80",.max_speed_hz = 20000000,.bus_num = 0,.chip_select = 0,.platform_data = &m25p32_spi_flash_data,},

    static void spi_device_init(void){#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)

    spi_register_board_info(m25p32_spi0_board_info,ARRAY_SIZE(m25p32_spi0_board_info));

    #endif}

  • The ‘Old’ Board File Method (Continued)

    • Not standard among the various ARM SoCs• Kernel size increase• Does not scale well and hard to maintain

  • Switching to Device Tree

    • How does it look like? • Example taken from arch/arm/boot/dts/imx6sl-evk.dts

    &ecspi1 {fsl,spi-num-chipselects = ;cs-gpios = ;pinctrl-names = "default";pinctrl-0 = ;status = "okay";

    flash: m25p80@0 {#address-cells = ;#size-cells = ;compatible = "st,m25p32";spi-max-frequency = ;reg = ;

    };};

  • Device Tree Concepts

    • Node, properties, child node

    &ecspi1 {fsl,spi-num-chipselects = ;cs-gpios = ;pinctrl-names = "default";pinctrl-0 = ;status = "okay";

    flash: m25p80@0 {#address-cells = ;#size-cells = ;compatible = "st,m25p32";spi-max-frequency = ;reg = ;

    };};

    node

    property value

    property

    child node compatible string

  • Representing the SoC: dtsi Files

    • Each SoC is represented by a .dtsi file• Number of CPUs, interrupts, clocks, memory map• Bus hierarchy • Compatible strings• Example: arch/arm/boot/dts/imx6qdl.dtsi

    i2c1: i2c@021a0000 {#address-cells = ;#size-cells = ;compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";reg = ;interrupts = ;clocks = ;status = "disabled";

    };

  • Device Tree Documentation

    • Example from Documentation/devicetree/bindings/tty/serial/fsl-imx-uart.txt:* Freescale i.MX Universal Asynchronous Receiver/Transmitter (UART)

    Required properties:- compatible : Should be "fsl,-uart"- reg : Address and length of the register set for the device- interrupts : Should contain uart interrupt

    Optional properties:- fsl,uart-has-rtscts : Indicate the uart has rts and cts- fsl,irda-mode : Indicate the uart supports irda mode

    Example:

    uart@73fbc000 {compatible = "fsl,imx51-uart", "fsl,imx21-uart";reg = ;interrupts = ;fsl,uart-has-rtscts;

    };

  • How to boot via device tree?

    ● Build the dtb

    make imx6q-sabresd.dtbmake imx6q-sabresd.dtb● Build the kernel

    make imx_v6_v7_defconfigmake imx_v6_v7_defconfig

    makemake (==> this generates a zImage)● Load dtb and kernel into memory and boot

    bootz 0x12000000 - 0x18000000bootz 0x12000000 - 0x18000000

  • Booting dtb with Old Bootloader

    • Select CONFIG_ARM_APPENDED_DTB and CONFIG_ARM_ATAG_DTB_COMPAT

    • Generate a kernel image that contains both dtb and kernel in a single binary:

    cat zImage imx27-pdk.dtb > zImage.combinedmv zImage.combined zImage

    • Then boot the final zImage as usual

    • If uImage is required than run mkimage

  • Pinctrl framework

    ● Configures the operational modemode of a pin and its electrical characteristicscharacteristics such as pull down, pull up, drive strength.

  • Example of UART IOMUX Setup

    • Details are documented at:Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt

    pinctrl_uart3: uart3grp {fsl,pins = <

    MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1

    >;};

  • Should IOMUX be Configured in Bootloader or Kernel?

    • For development boards it is better not to rely on the bootloader for performing the IOMUX setup (we can’t be sure on the bootloader version)

    • For a custom product it is OK if the IOMUX setup is done at the bootloader, then kernel can skip it

    • We can also tell the kernel to use the SW_PAD settings from the bootloader by passing 0x8000000

    MX6QDL_PAD_CSI0_DAT12__IPU1_CSI0_DATA12 0x80000000

  • Device Tree Examples – eSDHC

    • i.MX 6Quad SABRE SD

  • Device Tree Examples – eSDHC• From arch/arm/boot/dts/imx6qdl-sabresd.dtsi

    &usdhc2 {pinctrl-names = "default";pinctrl-0 = ;bus-width = ;cd-gpios = ;wp-gpios = ;no-1-8-v;keep-power-in-suspend;enable-sdio-wakeup;status = "okay";

    };pinctrl_usdhc2: usdhc2grp {

    fsl,pins = <MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059MX6QDL_PAD_NANDF_D4__SD2_DATA4 0x17059MX6QDL_PAD_NANDF_D5__SD2_DATA5 0x17059MX6QDL_PAD_NANDF_D6__SD2_DATA6 0x17059MX6QDL_PAD_NANDF_D7__SD2_DATA7 0x17059

    >;};

  • Device Tree Examples – Ethernet

    • AR8031 PHY on MX6Q sabresd

  • Device Tree Examples – Ethernet

    • From arch/arm/boot/dts/imx6qdl-sabresd.dtsi

    &fec {pinctrl-names = "default";pinctrl-0 = ;phy-mode = "rgmii";phy-reset-gpios = ;status = "okay";

    };

    pinctrl_enet: enetgrp {fsl,pins = <

    MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8

    >;};

  • Device Tree Examples – USB OTG

    • MX6SL EVK

  • Device Tree Examples – USB OTG

    • From arch/arm/boot/dts/imx6sl-evk.dts

    regulators {compatible = "simple-bus";#address-cells = ;#size-cells = ;

    reg_usb_otg1_vbus: regulator@0 {compatible = "regulator-fixed";reg = ;regulator-name = "usb_otg1_vbus";regulator-min-microvolt = ;regulator-max-microvolt = ;gpio = ;enable-active-high;

    };

    &usbotg1 {vbus-supply = ;pinctrl-names = "default";pinctrl-0 = ;disable-over-current;status = "okay";

    };

  • Device Tree Examples – USB OTG

    • USB OTG1 ID pin: allows to switch roles (host and peripheral)

    pinctrl_usbotg1: usbotg1grp {fsl,pins = <

    MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059>;

    };

  • Device Tree Examples – Wifi/Bluetooth● Wifi/BT support on imx6 cubox-i (4.2-rc1)

    commit dca97cee92736e1c48f6c2ecb543200d1353373eAuthor: Fabio Estevam Date: Mon May 11 12:38:33 2015 -0300

    ARM: dts: cubox-i: add support for Broadcom Wifi/Bluetooth devices Add DT support for the Broadcom Wifi/Bluetooth devices found on the microsom board. [Modified original Russell King's patch to use mmc-pwrseq] Signed-off-by: Russell King Signed-off-by: Fabio Estevam Tested-by: Jon Nettleton Tested-by: Russell King Signed-off-by: Shawn Guo

  • Device Tree Examples – Wifi/Bluetooth● Wifi/BT support on imx6 cubox-i+ usdhc1_pwrseq: usdhc1_pwrseq {+ compatible = "mmc-pwrseq-simple";+ reset-gpios = ,+ ;+ clocks = ;+ clock-names = "ext_clock";+ };

    +/* UART4 - Connected to optional BRCM Wifi/BT/FM */+&uart4 {+ pinctrl-names = "default";+ pinctrl-0 = ;+ fsl,uart-has-rtscts;+ status = "okay";+};++/* USDHC1 - Connected to optional BRCM Wifi/BT/FM */+&usdhc1 {+ pinctrl-names = "default";+ pinctrl-0 = ;+ bus-width = ;+ mmc-pwrseq = ;+ keep-power-in-suspend;+ non-removable;+ vmmc-supply = ;+ status = "okay";+};

  • Supporting a Board Family

    • As i.MX 6Quad, i.MX 6DualLite and i.MX 6Solo are pin-to-pin compatible, it is common to have boards that support the different chip variant− Examples: mx6sabresd, cubox-i , wandboard, nitrogen

    • imx6qdl-sabresd.dtsi: common part between i.MX 6Quad and i.MX 6DualLite versions

    • imxq-sabresd.dts: specific support that is only present on the i.MX 6Quad version (sata is only present on the i.MX 6Quad)

    &sata {status = "okay";

    };

  • How to Deal with Pin Conflicts?

    • Some boards may have pin conflicts among peripherals• Example: on i.MX 6Q SABRE auto board ecspi1 and i2c3 have pin

    conflict• From arch/arm/boot/dts/imx6q-sabreauto-ecspi.dts:

    #include "imx6q-sabreauto.dts"

    &ecspi1 {status = "okay";

    };

    &i2c3 {/* pin conflict with ecspi1 */status = "disabled";

    };

  • Looking at the Driver Level (FEC)

    • Compatible strings from drivers/net/ethernet/freescale/fec_main.c:

    static const struct of_device_id fec_dt_ids[] = {{ .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },{ .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },{ .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },{ .compatible = "fsl,imx6q-fec", .data = &fec_devtype[IMX6Q_FEC], },{ .compatible = "fsl,mvf600-fec", .data = &fec_devtype[MVF600_FEC], },{ .compatible = "fsl,imx6sx-fec", .data = &fec_devtype[IMX6SX_FEC], },{ /* sentinel */ }

    };MODULE_DEVICE_TABLE(of, fec_dt_ids);

  • Hints for Generating your Own Device Tree

    • Start looking at some dts files of the same SoC• Double check the pin muxing• Check documentation/devicetree/bindings for clarification

  • Common clock framework

    ● Drivers need to acquire clock , enable, disable, set the clock rate

    (clk_get, clk_enable, clk_set_rateclk_get, clk_enable, clk_set_rate)● Each SoC needs to represent its clocks so that

    drivers can make use them● Prior to CCF each SoC had its own way of

    representing the clocks ● drivers/clkdrivers/clk

  • Representing the clock topology

    ● SoC clock driver needs to model the whole clock topology:

    ● Clock gate, clock divider, clock parent

    ● Example: drivers/clk/imx/clk-imx6q.c

    clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata",   "ahb",  base + 0x7c, 4);clk[IMX6QDL_CLK_SDMA] = imx_clk_gate2("sdma",   "ahb",  base + 0x7c, 6);clk[IMX6QDL_CLK_SPBA] = imx_clk_gate2("spba",   "ipg",  base + 0x7c, 12);

  • Dumping the clock tree

    ● Prior to CCF there was not a standard way to output the whole clock tree.

    ● Now this becomes very simple:

    $ mount -t debugfs none /sys/kernel/debug$ mount -t debugfs none /sys/kernel/debug

    $ cat /sys/kernel/debug/clk/clk_summary$ cat /sys/kernel/debug/clk/clk_summary

  • Dumping the clock tree

    clock                         enable_cnt  prepare_cnt        rate   accuracy dummy                                    3            4           0          0    lvds2_sel                             0            0           0          0       lvds2_gate                         0            0           0          0    usbphy2_gate                          1            1           0          0    usbphy1_gate                          1            1           0          0 osc                                      6            6    24000000          0    cko2_sel                              1            1    24000000          0       cko2_podf                          1            1    24000000          0          cko2                            1            1    24000000          0             cko                          1            1    24000000          0    pll7_usb_host                         1            1   480000000          0       usbphy2                            1            1   480000000          0    pll6_enet                             3            3   500000000          0       enet_ref                           1            1    50000000          0

  • Regmap

    ● Provides an abstraction for accessing I2C/SPI devices or memory mapped devices

    ● Takes care of endianess, locking, word transfer size● Very helpful for debugging purposes as it allows easy

    register dumps in userspace

  • Regmap Example

    ● drivers/regulator/pfuze100-regulator.c

    static const struct regmap_config pfuze_regmap_config = {

    .reg_bits = 8,

    .val_bits = 8,

    .max_register = PFUZE_NUMREGS  1,

    .cache_type = REGCACHE_RBTREE,};

    ret = regmap_readregmap_read(pfuze_chip>regmap, PFUZE100_REVID, &value);if (ret)

    return ret;

  • Dumping registers via regmap

    ● Reading the PMIC PF100 registers via I2C:

    $ cat /sys/kernel/debug/regmap/1-0008/registers 00: 1001: 0002: 0003: 1104: 0005: 0106: 3f07: 0108: 0009: 7f0a: 00

  • Booting via kexec

    ● Load and launch a new kernel from a running kernel (no bootloader is involved in this process)

    ● Boot options --->

    [*] Kexec System Call

  • Booting via kexec - Example

    ● kexec -d -l /mnt/zImage --dtb /mnt/imx6dl-wandboard.dtb

    --command-line="console=ttymxc0,115200 root=/dev/mmcblk2p2 rootwait rw"

    ● kexec -e

  • Hints for getting started with Embedded Linux

    ● Get access to one development board. There are many low cost options available

    ● Get familiar with the hardware and the kernel ● Test the kernel for your board● Improve it, fix bugs and submit the fix upstream● Have fun :-)

  • Muito Obrigado!

    Slide 1Slide 2Slide 3Slide 4Slide 5Slide 6Device Tree Motivation for the ARM WorldSlide 8Device Tree ConceptThe ‘Old’ Board File MethodThe ‘Old’ Board File Method (Continued)Switching to Device TreeDevice Tree ConceptsRepresenting the SoC: dtsi FilesDevice Tree DocumentationSlide 16Booting dtb with Old BootloaderSlide 18Example of UART IOMUX SetupShould IOMUX be Configured in Bootloader or Kernel?Device Tree Examples – eSDHCSlide 22Device Tree Examples – EthernetSlide 24Slide 25Slide 26Slide 27Slide 28Slide 29Supporting a Board FamilyHow to Deal with Pin Conflicts?Slide 32Hints for Generating your Own Device TreeSlide 34Slide 35Slide 36Slide 37Slide 38Slide 39Slide 40Slide 41Slide 42Slide 43Slide 44


Recommended