diff --git a/Makefile b/Makefile index ce50bf4b3b..75b7b87d65 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ STYLESHEET = common/beamerthemeBootlin.sty # in .pdf in the output directory. This is used to compute the list of # .pdf files that need to be generated from .dia or .svg files. PICTURES_WITH_TRANSFORMATION = \ - $(patsubst %.$(2),$(OUTDIR)/%.pdf,$(foreach s,$(1),$(wildcard $(s)/*.$(2)))) + $(patsubst %.$(2),$(OUTDIR)/%.pdf,$(foreach s,$(1),$(shell find -L $(s) -type f -name '*.$(2)'))) # Function that computes the list of pictures of the extension given # in $(2) from the directories in $(1). This is used for pictures that @@ -94,6 +94,7 @@ SLIDES_COMMON_BEFORE = common/slide-header.tex \ common/$(SLIDES_TRAINING)-title.tex SLIDES_CHAPTERS = $($(call UPPERCASE, $(subst -,_, $(SLIDES_TRAINING)))_SLIDES) SLIDES_COMMON_AFTER = common/slide-footer.tex +SLIDES_VARSFILE = common/$(SLIDES_TRAINING)-labs-vars.tex else SLIDES_TRAINING = $(firstword $(subst -, , $(SLIDES))) ifeq ($(SLIDES_TRAINING),sysdev) @@ -122,6 +123,7 @@ endif # Compute the set of corresponding .tex files and pictures SLIDES_TEX = \ + $(SLIDES_VARSFILE) \ $(SLIDES_COMMON_BEFORE) \ $(foreach s,$(SLIDES_CHAPTERS),$(wildcard slides/$(s)/$(s).tex)) \ $(SLIDES_COMMON_AFTER) diff --git a/common/embedded-linux-imx93-frdm-labs-vars.tex b/common/embedded-linux-imx93-frdm-labs-vars.tex new file mode 100644 index 0000000000..7aeaa11912 --- /dev/null +++ b/common/embedded-linux-imx93-frdm-labs-vars.tex @@ -0,0 +1,15 @@ +\def\labbooktitle{Embedded Linux System Development} +\def\labbooksubtitle{imx93 frdm variant} +\def\labboard{imx93-frdm} +\def\workingkernel{6.15} +\def\labboarddescription{imx93 frdm Discovery kit} +\def\zimageboardaddr{0xc2000000} +\def\dtbboardaddr{0xc4f00000} +\def\dtname{imx93-11x11-frdm} +\def\hosttty{/dev/ttyACM0} +\def\ttyname{ttyLP0} +\def\console{\ttyname,115200} +\def\gpionum{533} +\def\gpioname{PF11} +\def\busname{I2C2} +\def\arch{ARM64} \ No newline at end of file diff --git a/common/embedded-linux-imx93-frdm-title.tex b/common/embedded-linux-imx93-frdm-title.tex new file mode 100644 index 0000000000..a2a7b71b9e --- /dev/null +++ b/common/embedded-linux-imx93-frdm-title.tex @@ -0,0 +1,2 @@ +\def \trainingurl{https://bootlin.com/training/embedded-linux} +\def \trainingtitle{Embedded Linux system development} diff --git a/common/imx93-frdm-connect-nunchuk.jpg b/common/imx93-frdm-connect-nunchuk.jpg new file mode 100644 index 0000000000..8a3cf09b7b Binary files /dev/null and b/common/imx93-frdm-connect-nunchuk.jpg differ diff --git a/common/slide-header.tex b/common/slide-header.tex index 9e5c309813..c574df8afa 100644 --- a/common/slide-header.tex +++ b/common/slide-header.tex @@ -9,6 +9,7 @@ \usepackage{tabularx} \usepackage{stmaryrd} \usepackage{appendixnumberbeamer} +\usepackage{etoolbox} \renewcommand{\thempfootnote}{\arabic{mpfootnote}} diff --git a/lab-data/embedded-linux-imx93-frdm/appdev/nunchuk-mpd-client.c b/lab-data/embedded-linux-imx93-frdm/appdev/nunchuk-mpd-client.c new file mode 100644 index 0000000000..4350eb1b64 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/appdev/nunchuk-mpd-client.c @@ -0,0 +1,170 @@ +/* nunchuk-mpd-client + (c) 2022 Bootlin + + License: Public Domain +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int handle_error(struct mpd_connection *c) +{ + fprintf(stderr, "%s\n", mpd_connection_get_error_message(c)); + mpd_connection_free(c); + return EXIT_FAILURE; +} + +static void change_volume(struct mpd_connection *c, int delta) +{ + int volume; + if (!mpd_run_change_volume(c, delta)) + exit(handle_error(c)); + + volume = mpd_run_get_volume(c); + + if (volume == -1) + exit(handle_error(c)); + + printf("%d\n", volume); +} + +static void print_current_song(struct mpd_connection *c) +{ + struct mpd_song *song; + song = mpd_run_current_song(c); + + if (song) { + printf("%s (%u s)\n", mpd_song_get_uri(song), mpd_song_get_duration(song)); + mpd_song_free(song); + } +} + +static int is_event_device(const struct dirent *dir) { + return (strncmp("event", dir->d_name, 5) == 0); +} + +int main(int argc, char ** argv) +{ + struct mpd_connection *conn; + int i, ndev, ret, fd, quit = 0, num_events = 0; + struct input_event event; + struct dirent **namelist; + + /* Find Nunchuk input device */ + + ndev = scandir("/dev/input", &namelist, is_event_device, alphasort); + + if (ndev <= 0) { + fprintf(stderr, "ERROR: no input event device found\n"); + exit(EXIT_FAILURE); + } + + for (i = 0; i < ndev; i++) + { + char fname[256]; + char name[256]; + + snprintf(fname, sizeof(fname), "/dev/%s", namelist[i]->d_name); + free(namelist[i]); + + fd = open(fname, O_RDONLY); + + if (fd < 0) + continue; + + ioctl(fd, EVIOCGNAME(sizeof(name)), name); + + if (strcmp("Wii Nunchuck", name) == 0) + break; + else + close(fd); + + } + + if (i == ndev) { + fprintf(stderr, "ERROR: didn't manage to find the Nunchuk device in /dev/input. Is the Nunchuk driver loaded?\n"); + exit(EXIT_FAILURE); + } + + /* Connection to MPD on localhost, default port */ + + conn = mpd_connection_new(0, 0, 30000); + + if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) + return handle_error(conn); + + printf("Connection successful\n"); + + /* Main loop */ + + while (!quit) { + ret = read(fd, &event, sizeof(struct input_event)); + num_events++; + + switch (event.type) { + case EV_KEY: + switch (event.code) { + case BTN_Z: + if (event.value == 1) { + printf("Play/Pause\n"); + if (!mpd_run_toggle_pause(conn)) + return handle_error(conn); + } + break; + case BTN_C: + if (event.value == 1) { + printf("Quit\n"); + quit = 1; + free(conn); + } + break; + } + break; + case EV_ABS: + switch (event.code) { + case ABS_Y: + if (event.value > 250) { + printf("Volume up: "); + change_volume(conn, 5); + } else if (event.value < 5) { + printf("Volume down: "); + change_volume(conn, -5); + } + break; + case ABS_X: + if (event.value > 250) { + if (!mpd_run_next(conn)) { + printf("No next song. Aborting\n"); + exit(handle_error(conn)); + } else { + printf("Next song: "); + print_current_song(conn); + } + } + else if (event.value < 5) { + if (!mpd_run_previous(conn)) { + printf("No previous song. Aborting\n"); + exit(handle_error(conn)); + } else { + printf("Previous song: "); + print_current_song(conn); + } + } + break; + } + break; + } + } + + /* Close connection */ + mpd_connection_free(conn); + printf("Connection terminated\n"); + return 0; +} diff --git a/lab-data/embedded-linux-imx93-frdm/bootloader/data/flash.bin b/lab-data/embedded-linux-imx93-frdm/bootloader/data/flash.bin new file mode 100644 index 0000000000..a8fc4531de Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/bootloader/data/flash.bin differ diff --git a/lab-data/embedded-linux-imx93-frdm/bootloader/data/patches/0001-arm-dts-imx93-add-device-tree-for-imx93-11x11-frd.patch b/lab-data/embedded-linux-imx93-frdm/bootloader/data/patches/0001-arm-dts-imx93-add-device-tree-for-imx93-11x11-frd.patch new file mode 100644 index 0000000000..ebd27f12fe --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/bootloader/data/patches/0001-arm-dts-imx93-add-device-tree-for-imx93-11x11-frd.patch @@ -0,0 +1,679 @@ +From 7ece928955d97b7232ae811dc3ba1c3e50668a47 Mon Sep 17 00:00:00 2001 +From: Antoine Picard +Date: Wed, 11 Jun 2025 08:31:42 +0200 +Subject: [PATCH u-boot v1 1/2] arm: dts: imx93: add device tree for + imx93-11x11-frdm board + +Add the following device tree files for the i.MX93 11x11 FRDM board: + + - `imx93-11x11-frdm.dts`: base device tree for the board + - `imx93-11x11-frdm-u-boot.dtsi`: U-Boot specific overrides + - Update to `arch/arm/dts/Makefile` to build the new DTS + +These files provide the initial DT support for U-Boot on the i.MX93 FRDM +platform. + +Signed-off-by: Antoine Picard +--- + arch/arm/dts/Makefile | 1 + + arch/arm/dts/imx93-11x11-frdm-u-boot.dtsi | 53 ++ + arch/arm/dts/imx93-11x11-frdm.dts | 574 ++++++++++++++++++++++ + 3 files changed, 628 insertions(+) + create mode 100644 arch/arm/dts/imx93-11x11-frdm-u-boot.dtsi + create mode 100644 arch/arm/dts/imx93-11x11-frdm.dts + +diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile +index 32b698a7f41..2792a101b51 100644 +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -918,6 +918,7 @@ dtb-$(CONFIG_ARCH_IMX8M) += \ + imx8mq-librem5-r4.dtb + + dtb-$(CONFIG_ARCH_IMX9) += \ ++ imx93-11x11-frdm.dtb \ + imx93-var-som-symphony.dtb \ + imx93-phyboard-segin.dtb + +diff --git a/arch/arm/dts/imx93-11x11-frdm-u-boot.dtsi b/arch/arm/dts/imx93-11x11-frdm-u-boot.dtsi +new file mode 100644 +index 00000000000..5cecc6e4cf8 +--- /dev/null ++++ b/arch/arm/dts/imx93-11x11-frdm-u-boot.dtsi +@@ -0,0 +1,53 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2024-2025 NXP ++ */ ++ ++#include "imx93-u-boot.dtsi" ++ ++&pinctrl_uart1 { ++ bootph-pre-ram; ++}; ++ ++&lpuart1 { ++ bootph-pre-ram; ++}; ++ ++&s4muap { ++ bootph-some-ram; ++ status = "okay"; ++}; ++ ++&clk { ++ bootph-pre-ram; ++}; ++ ++&osc_32k { ++ bootph-pre-ram; ++}; ++ ++&osc_24m { ++ bootph-pre-ram; ++}; ++ ++&clk_ext1 { ++ bootph-pre-ram; ++}; ++ ++&lpi2c2 { ++ bootph-pre-ram; ++ status = "okay"; ++ clock-frequency = <100000>; ++}; ++ ++&pinctrl_lpi2c2 { ++ bootph-pre-ram; ++}; ++ ++&{/soc@0/bus@44000000/i2c@44350000/pmic@25} { ++ bootph-pre-ram; ++}; ++ ++&{/soc@0/bus@44000000/i2c@44350000/pmic@25/regulators} { ++ bootph-pre-ram; ++}; +\ No newline at end of file +diff --git a/arch/arm/dts/imx93-11x11-frdm.dts b/arch/arm/dts/imx93-11x11-frdm.dts +new file mode 100644 +index 00000000000..1e96b1f5605 +--- /dev/null ++++ b/arch/arm/dts/imx93-11x11-frdm.dts +@@ -0,0 +1,574 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright 2024-2025 NXP ++ */ ++ ++/dts-v1/; ++ ++#include ++#include "imx93.dtsi" ++ ++/ { ++ model = "NXP i.MX93 11X11 FRDM board"; ++ compatible = "fsl,imx93-11x11-frdm", "fsl,imx93"; ++ ++ aliases { ++ rtc0 = &pcf2131; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyLP0,115200"; ++ stdout-path = &lpuart1; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ alloc-ranges = <0 0x80000000 0 0x40000000>; ++ size = <0 0x10000000>; ++ linux,cma-default; ++ }; ++ }; ++ ++ reg_can2_stby: regulator-can2-stby { ++ compatible = "regulator-fixed"; ++ regulator-name = "can2-stby"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&pcal6524 23 GPIO_ACTIVE_LOW>; ++ enable-active-high; ++ }; ++ ++ reg_vref_1v8: regulator-adc-vref { ++ compatible = "regulator-fixed"; ++ regulator-name = "vref_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ reg_usdhc2_vmmc: regulator-usdhc2 { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; ++ regulator-name = "VSD_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; ++ off-on-delay-us = <12000>; ++ enable-active-high; ++ }; ++ ++ reg_vdd_12v: regulator-vdd-12v { ++ compatible = "regulator-fixed"; ++ regulator-name = "reg_vdd_12v"; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ gpio = <&pcal6524 14 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_red { ++ label = "led-red"; ++ gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_green { ++ label = "led-green"; ++ gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_blue { ++ label = "led-blue"; ++ gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ }; ++}; ++ ++ ++&adc1 { ++ vref-supply = <®_vref_1v8>; ++ status = "okay"; ++}; ++ ++&mu1 { ++ status = "okay"; ++}; ++ ++&mu2 { ++ status = "okay"; ++}; ++ ++&eqos { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_eqos>; ++ phy-mode = "rgmii-id"; ++ phy-handle = <ðphy1>; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <5000000>; ++ ++ ethphy1: ethernet-phy@1 { ++ reg = <1>; ++ eee-broken-1000t; ++ ++ reset-gpios = <&pcal6524 15 GPIO_ACTIVE_LOW>; ++ reset-assert-us = <15000>; ++ reset-deassert-us = <100000>; ++ }; ++ }; ++}; ++ ++&fec { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_fec>; ++ phy-mode = "rgmii-id"; ++ phy-handle = <ðphy2>; ++ fsl,magic-packet; ++ status = "okay"; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <5000000>; ++ ++ ethphy2: ethernet-phy@2 { ++ reg = <2>; ++ eee-broken-1000t; ++ }; ++ }; ++}; ++ ++&lpi2c1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <400000>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&pinctrl_lpi2c1>; ++ pinctrl-1 = <&pinctrl_lpi2c1>; ++ status = "okay"; ++}; ++ ++&lpi2c2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <400000>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&pinctrl_lpi2c2>; ++ pinctrl-1 = <&pinctrl_lpi2c2>; ++ status = "okay"; ++ ++ pmic@25 { ++ compatible = "nxp,pca9451a"; ++ reg = <0x25>; ++ interrupt-parent = <&pcal6524>; ++ interrupts = <11 IRQ_TYPE_EDGE_FALLING>; ++ ++ regulators { ++ buck1: BUCK1 { ++ regulator-name = "BUCK1"; ++ regulator-min-microvolt = <650000>; ++ regulator-max-microvolt = <2237500>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-ramp-delay = <3125>; ++ }; ++ ++ buck2: BUCK2 { ++ regulator-name = "BUCK2"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <2187500>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-ramp-delay = <3125>; ++ }; ++ ++ buck4: BUCK4{ ++ regulator-name = "BUCK4"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3400000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buck5: BUCK5{ ++ regulator-name = "BUCK5"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3400000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buck6: BUCK6 { ++ regulator-name = "BUCK6"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3400000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo1: LDO1 { ++ regulator-name = "LDO1"; ++ regulator-min-microvolt = <1600000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo4: LDO4 { ++ regulator-name = "LDO4"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo5: LDO5 { ++ regulator-name = "LDO5"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ pcal6524: gpio@22 { ++ compatible = "nxp,pcal6524"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_pcal6524>; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupt-parent = <&gpio3>; ++ interrupts = <27 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ eeprom: eeprom@50 { ++ compatible = "atmel,24c256"; ++ reg = <0x50>; ++ pagesize = <64>; ++ }; ++ ++}; ++ ++&lpi2c3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <400000>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&pinctrl_lpi2c3>; ++ pinctrl-1 = <&pinctrl_lpi2c3>; ++ status = "okay"; ++ ++ pcf2131: rtc@53 { ++ compatible = "nxp,pcf2131"; ++ reg = <0x53>; ++ interrupt-parent = <&pcal6524>; ++ interrupts = <1 IRQ_TYPE_EDGE_FALLING>; ++ status = "okay"; ++ }; ++ ++ ptn5110: tcpc@50 { ++ compatible = "nxp,ptn5110", "tcpci"; ++ reg = <0x50>; ++ interrupt-parent = <&gpio3>; ++ interrupts = <27 IRQ_TYPE_EDGE_FALLING>; ++ status = "okay"; ++ ++ port { ++ typec1_dr_sw: endpoint { ++ remote-endpoint = <&usb1_drd_sw>; ++ }; ++ }; ++ ++ typec1_con: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ power-role = "dual"; ++ data-role = "dual"; ++ try-power-role = "sink"; ++ source-pdos = ; ++ sink-pdos = ; ++ op-sink-microwatt = <15000000>; ++ self-powered; ++ }; ++ }; ++ ++}; ++ ++&lpuart1 { /* console */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_uart1>; ++ status = "okay"; ++}; ++ ++&media_blk_ctrl { ++ status = "okay"; ++}; ++ ++&usbotg1 { ++ dr_mode = "otg"; ++ hnp-disable; ++ srp-disable; ++ adp-disable; ++ usb-role-switch; ++ disable-over-current; ++ samsung,picophy-pre-emp-curr-control = <3>; ++ samsung,picophy-dc-vol-level-adjust = <7>; ++ status = "okay"; ++ ++ port { ++ usb1_drd_sw: endpoint { ++ remote-endpoint = <&typec1_dr_sw>; ++ }; ++ }; ++}; ++ ++&usbotg2 { ++ dr_mode = "host"; ++ disable-over-current; ++ samsung,picophy-pre-emp-curr-control = <3>; ++ samsung,picophy-dc-vol-level-adjust = <7>; ++ status = "okay"; ++}; ++ ++&usdhc1 { ++ pinctrl-names = "default", "state_100mhz", "state_200mhz"; ++ pinctrl-0 = <&pinctrl_usdhc1>; ++ pinctrl-1 = <&pinctrl_usdhc1_100mhz>; ++ pinctrl-2 = <&pinctrl_usdhc1_200mhz>; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ ++&usdhc2 { ++ pinctrl-names = "default", "state_100mhz", "state_200mhz"; ++ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; ++ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; ++ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; ++ cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; ++ vmmc-supply = <®_usdhc2_vmmc>; ++ bus-width = <4>; ++ status = "okay"; ++ no-sdio; ++ no-mmc; ++}; ++ ++&usdhc3 { ++ status = "disabled"; ++}; ++ ++&wdog3 { ++ status = "okay"; ++}; ++ ++&iomuxc { ++ pinctrl_eqos: eqosgrp { ++ fsl,pins = < ++ MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x57e ++ MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x57e ++ MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e ++ MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e ++ MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e ++ MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e ++ MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x5fe ++ MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e ++ MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e ++ MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e ++ MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e ++ MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e ++ MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x5fe ++ MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e ++ >; ++ }; ++ ++ pinctrl_flexspi: flexspigrp { ++ fsl,pins = < ++ MX93_PAD_SD3_CMD__FLEXSPI1_A_SS0_B 0x3fe ++ MX93_PAD_SD3_CLK__FLEXSPI1_A_SCLK 0x3fe ++ MX93_PAD_SD3_DATA0__FLEXSPI1_A_DATA00 0x3fe ++ MX93_PAD_SD3_DATA1__FLEXSPI1_A_DATA01 0x3fe ++ MX93_PAD_SD3_DATA2__FLEXSPI1_A_DATA02 0x3fe ++ MX93_PAD_SD3_DATA3__FLEXSPI1_A_DATA03 0x3fe ++ >; ++ }; ++ ++ pinctrl_fec: fecgrp { ++ fsl,pins = < ++ MX93_PAD_ENET2_MDC__ENET1_MDC 0x57e ++ MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x57e ++ MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e ++ MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e ++ MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e ++ MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e ++ MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x5fe ++ MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e ++ MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x57e ++ MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x57e ++ MX93_PAD_ENET2_TD2__ENET1_RGMII_TD2 0x57e ++ MX93_PAD_ENET2_TD3__ENET1_RGMII_TD3 0x57e ++ MX93_PAD_ENET2_TXC__ENET1_RGMII_TXC 0x5fe ++ MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x57e ++ >; ++ }; ++ ++ pinctrl_lpi2c1: lpi2c1grp { ++ fsl,pins = < ++ MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e ++ MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e ++ >; ++ }; ++ ++ pinctrl_lpi2c2: lpi2c2grp { ++ fsl,pins = < ++ MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e ++ MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e ++ >; ++ }; ++ ++ pinctrl_lpi2c3: lpi2c3grp { ++ fsl,pins = < ++ MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e ++ MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e ++ >; ++ }; ++ ++ pinctrl_pcal6524: pcal6524grp { ++ fsl,pins = < ++ MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e ++ >; ++ }; ++ ++ pinctrl_uart1: uart1grp { ++ fsl,pins = < ++ MX93_PAD_UART1_RXD__LPUART1_RX 0x31e ++ MX93_PAD_UART1_TXD__LPUART1_TX 0x31e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc1: usdhc1grp { ++ fsl,pins = < ++ MX93_PAD_SD1_CLK__USDHC1_CLK 0x1582 ++ MX93_PAD_SD1_CMD__USDHC1_CMD 0x40001382 ++ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x40001382 ++ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x40001382 ++ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x40001382 ++ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x40001382 ++ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x40001382 ++ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x40001382 ++ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x40001382 ++ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x40001382 ++ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1582 ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { ++ fsl,pins = < ++ MX93_PAD_SD1_CLK__USDHC1_CLK 0x158e ++ MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000138e ++ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e ++ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000138e ++ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000138e ++ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000138e ++ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000138e ++ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000138e ++ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000138e ++ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000138e ++ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x158e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { ++ fsl,pins = < ++ MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe ++ MX93_PAD_SD1_CMD__USDHC1_CMD 0x400013fe ++ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x400013fe ++ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013fe ++ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013fe ++ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013fe ++ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013fe ++ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013fe ++ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013fe ++ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013fe ++ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe ++ >; ++ }; ++ ++ pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { ++ fsl,pins = < ++ MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e ++ >; ++ }; ++ ++ pinctrl_usdhc2_gpio: usdhc2gpiogrp { ++ fsl,pins = < ++ MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e ++ >; ++ }; ++ ++ pinctrl_usdhc2_gpio_sleep: usdhc2-gpio-grp { ++ fsl,pins = < ++ MX93_PAD_SD2_CD_B__GPIO3_IO00 0x51e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc2: usdhc2grp { ++ fsl,pins = < ++ MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582 ++ MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382 ++ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382 ++ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382 ++ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382 ++ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382 ++ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { ++ fsl,pins = < ++ MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e ++ MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e ++ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e ++ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e ++ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e ++ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e ++ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { ++ fsl,pins = < ++ MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe ++ MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe ++ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe ++ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe ++ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe ++ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe ++ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e ++ >; ++ }; ++}; +-- +2.43.0 + diff --git a/lab-data/embedded-linux-imx93-frdm/bootloader/data/patches/0002-board-freescale-add-initial-support-for-imx93_frd.patch b/lab-data/embedded-linux-imx93-frdm/bootloader/data/patches/0002-board-freescale-add-initial-support-for-imx93_frd.patch new file mode 100644 index 0000000000..a79ed1cffa --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/bootloader/data/patches/0002-board-freescale-add-initial-support-for-imx93_frd.patch @@ -0,0 +1,4893 @@ +From 80063e1fb35da3eb6c2442c9140efdbfcec2a2c1 Mon Sep 17 00:00:00 2001 +From: Antoine Picard +Date: Wed, 11 Jun 2025 08:41:21 +0200 +Subject: [PATCH u-boot v1 2/2] board: freescale: add initial support for + imx93_frdm board + +Add initial support for the NXP i.MX93 FRDM board, including: + + - Board directory with initialization code + - DRAM timing files for LPDDR4X (2GB, ECC variants) + - SPL support + - Board-specific header and configuration + - i.MX9 Kconfig entry for board enablement + - defconfig for imx93_11x11_frdm + +This enables basic SPL and U-Boot support for the i.MX93 FRDM +development platform. + +Signed-off-by: Antoine Picard +--- + arch/arm/mach-imx/imx9/Kconfig | 6 + + board/freescale/imx93_frdm/Kconfig | 19 + + board/freescale/imx93_frdm/MAINTAINERS | 5 + + board/freescale/imx93_frdm/Makefile | 16 + + board/freescale/imx93_frdm/imx93_frdm.c | 350 +++ + .../freescale/imx93_frdm/lpddr4x_2gb_timing.c | 1996 ++++++++++++++++ + .../imx93_frdm/lpddr4x_ecc_2gb_timing.c | 1997 +++++++++++++++++ + board/freescale/imx93_frdm/spl.c | 201 ++ + configs/imx93_11x11_frdm_defconfig | 158 ++ + include/configs/imx93_frdm.h | 27 + + 10 files changed, 4775 insertions(+) + create mode 100644 board/freescale/imx93_frdm/Kconfig + create mode 100644 board/freescale/imx93_frdm/MAINTAINERS + create mode 100644 board/freescale/imx93_frdm/Makefile + create mode 100644 board/freescale/imx93_frdm/imx93_frdm.c + create mode 100644 board/freescale/imx93_frdm/lpddr4x_2gb_timing.c + create mode 100644 board/freescale/imx93_frdm/lpddr4x_ecc_2gb_timing.c + create mode 100644 board/freescale/imx93_frdm/spl.c + create mode 100644 configs/imx93_11x11_frdm_defconfig + create mode 100644 include/configs/imx93_frdm.h + +diff --git a/arch/arm/mach-imx/imx9/Kconfig b/arch/arm/mach-imx/imx9/Kconfig +index 0fd82dc0811..5b6587486ad 100644 +--- a/arch/arm/mach-imx/imx9/Kconfig ++++ b/arch/arm/mach-imx/imx9/Kconfig +@@ -47,6 +47,11 @@ config TARGET_IMX91_11X11_EVK + imply BOOTSTD_FULL + imply BOOTSTD_BOOTCOMMAND + ++config TARGET_IMX93_11X11_FRDM ++ bool "imx93_11x11_frdm" ++ select OF_BOARD_FIXUP ++ select IMX93 ++ + config TARGET_IMX93_9X9_QSB + bool "imx93_qsb" + select OF_BOARD_FIXUP +@@ -91,6 +96,7 @@ source "board/freescale/imx93_qsb/Kconfig" + source "board/phytec/phycore_imx93/Kconfig" + source "board/variscite/imx93_var_som/Kconfig" + source "board/freescale/imx95_evk/Kconfig" ++source "board/freescale/imx93_frdm/Kconfig" + + endif + +diff --git a/board/freescale/imx93_frdm/Kconfig b/board/freescale/imx93_frdm/Kconfig +new file mode 100644 +index 00000000000..639cb61047f +--- /dev/null ++++ b/board/freescale/imx93_frdm/Kconfig +@@ -0,0 +1,19 @@ ++if TARGET_IMX93_11X11_FRDM ++ ++config SYS_BOARD ++ default "imx93_frdm" ++ ++config SYS_VENDOR ++ default "freescale" ++ ++config SYS_CONFIG_NAME ++ default "imx93_frdm" ++ ++config IMX93_FRDM_LPDDR4X ++ bool "Using LPDDR4X Timing and PMIC voltage" ++ default y ++ select IMX9_LPDDR4X ++ help ++ Select the LPDDR4X timing and 0.6V VDDQ ++ ++endif +diff --git a/board/freescale/imx93_frdm/MAINTAINERS b/board/freescale/imx93_frdm/MAINTAINERS +new file mode 100644 +index 00000000000..6d443f15a1c +--- /dev/null ++++ b/board/freescale/imx93_frdm/MAINTAINERS +@@ -0,0 +1,5 @@ ++i.MX93 FRDM BOARD ++S: Maintained ++F: board/freescale/imx93_frdm/ ++F: include/configs/imx93_frdm.h ++F: configs/imx93_11x11_frdm_defconfig +diff --git a/board/freescale/imx93_frdm/Makefile b/board/freescale/imx93_frdm/Makefile +new file mode 100644 +index 00000000000..adf4a15336c +--- /dev/null ++++ b/board/freescale/imx93_frdm/Makefile +@@ -0,0 +1,16 @@ ++# ++# Copyright 2024-2025 NXP ++# ++# SPDX-License-Identifier: GPL-2.0+ ++# ++ ++obj-y += imx93_frdm.o ++ ++ifdef CONFIG_SPL_BUILD ++obj-y += spl.o ++ifdef CONFIG_IMX9_DRAM_INLINE_ECC ++obj-$(CONFIG_IMX93_FRDM_LPDDR4X) += lpddr4x_ecc_2gb_timing.o ++else ++obj-$(CONFIG_IMX93_FRDM_LPDDR4X) += lpddr4x_2gb_timing.o ++endif ++endif +\ No newline at end of file +diff --git a/board/freescale/imx93_frdm/imx93_frdm.c b/board/freescale/imx93_frdm/imx93_frdm.c +new file mode 100644 +index 00000000000..7b0e68a2ef8 +--- /dev/null ++++ b/board/freescale/imx93_frdm/imx93_frdm.c +@@ -0,0 +1,350 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2024-2025 NXP ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++#define UART_PAD_CTRL (PAD_CTL_DSE(6) | PAD_CTL_FSEL2) ++#define WDOG_PAD_CTRL (PAD_CTL_DSE(6) | PAD_CTL_ODE | PAD_CTL_PUE | PAD_CTL_PE) ++ ++static const iomux_v3_cfg_t uart_pads[] = { ++ MX93_PAD_UART1_RXD__LPUART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL), ++ MX93_PAD_UART1_TXD__LPUART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL), ++}; ++ ++#if CONFIG_IS_ENABLED(EFI_HAVE_CAPSULE_SUPPORT) ++#define IMX_BOOT_IMAGE_GUID \ ++ EFI_GUID(0xbc550d86, 0xda26, 0x4b70, 0xac, 0x05, \ ++ 0x2a, 0x44, 0x8e, 0xda, 0x6f, 0x21) ++ ++struct efi_fw_image fw_images[] = { ++ { ++ .image_type_id = IMX_BOOT_IMAGE_GUID, ++ .fw_name = u"IMX93-11X11-FRDM-RAW", ++ .image_index = 1, ++ }, ++}; ++ ++struct efi_capsule_update_info update_info = { ++ .dfu_string = "mmc 0=flash-bin raw 0 0x2000 mmcpart 1", ++ .num_images = ARRAY_SIZE(fw_images), ++ .images = fw_images, ++}; ++ ++#endif /* EFI_HAVE_CAPSULE_SUPPORT */ ++ ++int board_early_init_f(void) ++{ ++ imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads)); ++ ++ return 0; ++} ++ ++#ifdef CONFIG_USB_TCPC ++struct tcpc_port port1; ++struct tcpc_port portpd; ++ ++static int setup_pd_switch(u8 i2c_bus, u8 addr) ++{ ++ struct udevice *bus; ++ struct udevice *i2c_dev = NULL; ++ int ret; ++ u8 valb; ++ ++ ret = uclass_get_device_by_seq(UCLASS_I2C, i2c_bus, &bus); ++ if (ret) { ++ printf("%s: Can't find bus\n", __func__); ++ return -EINVAL; ++ } ++ ++ ret = dm_i2c_probe(bus, addr, 0, &i2c_dev); ++ if (ret) { ++ printf("%s: Can't find device id=0x%x\n",__func__, addr); ++ return -ENODEV; ++ } ++ ++ ret = dm_i2c_read(i2c_dev, 0xB, &valb, 1); ++ if (ret) { ++ printf("%s dm_i2c_read failed, err %d\n", __func__, ret); ++ return -EIO; ++ } ++ valb |= 0x4; /* Set DB_EXIT to exit dead battery mode */ ++ ret = dm_i2c_write(i2c_dev, 0xB, (const uint8_t *)&valb, 1); ++ if (ret) { ++ printf("%s dm_i2c_write failed, err %d\n", __func__, ret); ++ return -EIO; ++ } ++ ++ /* Set OVP threshold to 23V */ ++ valb = 0x6; ++ ret = dm_i2c_write(i2c_dev, 0x8, (const uint8_t *)&valb, 1); ++ if (ret) { ++ printf("%s dm_i2c_write failed, err %d\n", __func__, ret); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++int pd_switch_snk_enable(struct tcpc_port *port) ++{ ++ if (port == &port1) { ++ debug("Setup pd switch on port 1\n"); ++ return setup_pd_switch(2, 0x71); ++ } else { ++ return -EINVAL; ++ } ++} ++ ++struct tcpc_port_config portpd_config = { ++ .i2c_bus = 2, /*i2c3*/ ++ .addr = 0x52, ++ .port_type = TYPEC_PORT_UFP, ++ .max_snk_mv = 20000, ++ .max_snk_ma = 3000, ++ .max_snk_mw = 15000, ++ .op_snk_mv = 9000, ++}; ++ ++struct tcpc_port_config port1_config = { ++ .i2c_bus = 2, /*i2c3*/ ++ .addr = 0x50, ++ .port_type = TYPEC_PORT_UFP, ++ .max_snk_mv = 5000, ++ .max_snk_ma = 3000, ++ .max_snk_mw = 40000, ++ .op_snk_mv = 9000, ++ .switch_setup_func = &pd_switch_snk_enable, ++ .disable_pd = true, ++}; ++ ++static int setup_typec(void) ++{ ++ int ret; ++ ++ debug("tcpc_init port pd\n"); ++ ret = tcpc_init(&portpd, portpd_config, NULL); ++ if (ret) { ++ printf("%s: tcpc portpd init failed, err=%d\n",__func__, ret); ++ return ret; ++ } ++ ++ debug("tcpc_init port 1\n"); ++ ret = tcpc_init(&port1, port1_config, NULL); ++ if (ret) { ++ printf("%s: tcpc port1 init failed, err=%d\n",__func__, ret); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++int board_usb_init(int index, enum usb_init_type init) ++{ ++ int ret = 0; ++ struct tcpc_port *port_ptr; ++ ++ debug("%s %d, type %d\n", __func__, index, init); ++ ++ if (index == 0) { ++ port_ptr = &port1; ++ ++ if (init == USB_INIT_HOST) ++ tcpc_setup_dfp_mode(port_ptr); ++ else ++ tcpc_setup_ufp_mode(port_ptr); ++ } ++ ++ return ret; ++} ++ ++int board_usb_cleanup(int index, enum usb_init_type init) ++{ ++ int ret = 0; ++ ++ debug("%s %d, type %d\n", __func__, index, init); ++ ++ if (init == USB_INIT_HOST) { ++ if (index == 0) ++ ret = tcpc_disable_src_vbus(&port1); ++ } ++ ++ return ret; ++} ++ ++int board_ehci_usb_phy_mode(struct udevice *dev) ++{ ++ int ret = 0; ++ enum typec_cc_polarity pol; ++ enum typec_cc_state state; ++ struct tcpc_port *port_ptr; ++ ++ debug("%s %d\n", __func__, dev_seq(dev)); ++ ++ if (dev_seq(dev) == 0) { ++ port_ptr = &port1; ++ ++ tcpc_setup_ufp_mode(port_ptr); ++ ++ ret = tcpc_get_cc_status(port_ptr, &pol, &state); ++ ++ tcpc_print_log(port_ptr); ++ if (!ret) { ++ if (state == TYPEC_STATE_SRC_RD_RA || state == TYPEC_STATE_SRC_RD) ++ return USB_INIT_HOST; ++ } ++ } ++ ++ return USB_INIT_DEVICE; ++} ++#endif ++ ++static int setup_fec(void) ++{ ++ return set_clk_enet(ENET_125MHZ); ++} ++ ++int board_phy_config(struct phy_device *phydev) ++{ ++ if (phydev->drv->config) ++ phydev->drv->config(phydev); ++ ++ return 0; ++} ++ ++static void board_gpio_init(void) ++{ ++ struct gpio_desc desc; ++ int ret; ++ ++ /* Enable EXT1_PWREN for PCIE_3.3V */ ++ ret = dm_gpio_lookup_name("gpio@22_13", &desc); ++ if (ret) ++ return; ++ ++ ret = dm_gpio_request(&desc, "EXT1_PWREN"); ++ if (ret) ++ return; ++ ++ dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT); ++ dm_gpio_set_value(&desc, 1); ++ ++ /* Deassert SD3_nRST */ ++ ret = dm_gpio_lookup_name("gpio@22_12", &desc); ++ if (ret) ++ return; ++ ++ ret = dm_gpio_request(&desc, "SD3_nRST"); ++ if (ret) ++ return; ++ ++ dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT); ++ dm_gpio_set_value(&desc, 1); ++} ++ ++static int print_board_version(void) ++{ ++ int i, ret; ++ struct udevice *dev; ++ unsigned int rev[2]; ++ unsigned int data[2]; ++ ++ ret = uclass_first_device_check(UCLASS_ADC, &dev); ++ ++ if (dev) { ++ ret = adc_channel_single_shot(dev->name, 2, &data[0]); ++ if (ret) { ++ printf("BOARD: unknown\n"); ++ return 0; ++ } ++ ret = adc_channel_single_shot(dev->name, 3, &data[1]); ++ if (ret) { ++ printf("BOARD: unknown\n"); ++ return 0; ++ } ++ ++ for (i = 0; i < 2; i++) { ++ if (data[i] < 500) ++ rev[i] = 0; ++ else if (data[i] < 700) ++ rev[i] = 1; ++ else if (data[i] < 1500) ++ rev[i] = 2; ++ else if (data[i] < 2300) ++ rev[i] = 3; ++ else if (data[i] < 3000) ++ rev[i] = 4; ++ else if (data[i] < 3600) ++ rev[i] = 5; ++ else ++ rev[i] = 6; ++ } ++ printf("BOARD: V%d.%d(ADC2:%d,ADC3:%d)\n", rev[0], rev[1], data[0], data[1]); ++ } else { ++ printf("BOARD: unknown\n"); ++ } ++ ++ return 0; ++} ++ ++int board_init(void) ++{ ++#ifdef CONFIG_USB_TCPC ++ setup_typec(); ++#endif ++ print_board_version(); ++ ++ if (IS_ENABLED(CONFIG_FEC_MXC)) ++ setup_fec(); ++ ++ board_gpio_init(); ++ ++ return 0; ++} ++ ++int board_late_init(void) ++{ ++#ifdef CONFIG_ENV_IS_IN_MMC ++ board_late_mmc_env_init(); ++#endif ++ ++ env_set("sec_boot", "no"); ++#ifdef CONFIG_AHAB_BOOT ++ env_set("sec_boot", "yes"); ++#endif ++ ++#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG ++ env_set("board_name", "11X11_FRDM"); ++ env_set("board_rev", "iMX93"); ++#endif ++ return 0; ++} ++ ++#ifdef CONFIG_FSL_FASTBOOT ++#ifdef CONFIG_ANDROID_RECOVERY ++int is_recovery_key_pressing(void) ++{ ++ return 0; ++} ++#endif /*CONFIG_ANDROID_RECOVERY*/ ++#endif /*CONFIG_FSL_FASTBOOT*/ +diff --git a/board/freescale/imx93_frdm/lpddr4x_2gb_timing.c b/board/freescale/imx93_frdm/lpddr4x_2gb_timing.c +new file mode 100644 +index 00000000000..f9da1c6b5f4 +--- /dev/null ++++ b/board/freescale/imx93_frdm/lpddr4x_2gb_timing.c +@@ -0,0 +1,1996 @@ ++/* ++ * Copyright 2024 NXP ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ * Code generated with DDR Tool v3.4.0_8.3-4e2b550a. ++ * DDR PHY FW2022.01 ++ */ ++ ++#include ++#include ++ ++/* Initialize DDRC registers */ ++static struct dram_cfg_param ddr_ddrc_cfg[] = { ++ {0x4e300110, 0x44100001}, ++ {0x4e300000, 0x8000ff}, ++ {0x4e300008, 0x0}, ++ {0x4e300080, 0x80000512}, ++ {0x4e300084, 0x0}, ++ {0x4e300114, 0x1002}, ++ {0x4e300260, 0x80}, ++ {0x4e300f04, 0x80}, ++ {0x4e300800, 0x43b30002}, ++ {0x4e300804, 0x1f1f1f1f}, ++ {0x4e301000, 0x0}, ++ {0x4e301240, 0x0}, ++ {0x4e301244, 0x0}, ++ {0x4e301248, 0x0}, ++ {0x4e30124c, 0x0}, ++ {0x4e301250, 0x0}, ++ {0x4e301254, 0x0}, ++ {0x4e301258, 0x0}, ++ {0x4e30125c, 0x0}, ++}; ++ ++/* dram fsp cfg */ ++static struct dram_fsp_cfg ddr_dram_fsp_cfg[] = { ++ { ++ { ++ {0x4e300100, 0x24AB321B}, ++ {0x4e300104, 0xF8EE001B}, ++ {0x4e300108, 0x2F2EE233}, ++ {0x4e30010C, 0x0005E18B}, ++ {0x4e300124, 0x1C760000}, ++ {0x4e300160, 0x00009102}, ++ {0x4e30016C, 0x35F00000}, ++ {0x4e300170, 0x8B0B0608}, ++ {0x4e300250, 0x00000028}, ++ {0x4e300254, 0x015B015B}, ++ {0x4e300258, 0x00000008}, ++ {0x4e30025C, 0x00000400}, ++ {0x4e300300, 0x224F2213}, ++ {0x4e300304, 0x015B2213}, ++ {0x4e300308, 0x0A3C0E3D}, ++ }, ++ { ++ {0x01, 0xE4}, ++ {0x02, 0x36}, ++ {0x03, 0x32}, ++ {0x0b, 0x46}, ++ {0x0c, 0x11}, ++ {0x0e, 0x11}, ++ {0x16, 0x04}, ++ }, ++ 0, ++ }, ++ { ++ { ++ {0x4e300100, 0x12552100}, ++ {0x4e300104, 0xF877000E}, ++ {0x4e300108, 0x1816B4AA}, ++ {0x4e30010C, 0x005101E6}, ++ {0x4e300124, 0x0E3C0000}, ++ {0x4e300160, 0x00009101}, ++ {0x4e30016C, 0x30900000}, ++ {0x4e300170, 0x8A0A0508}, ++ {0x4e300250, 0x00000014}, ++ {0x4e300254, 0x00AA00AA}, ++ {0x4e300258, 0x00000008}, ++ {0x4e30025C, 0x00000400}, ++ }, ++ { ++ {0x01, 0xB4}, ++ {0x02, 0x1B}, ++ {0x03, 0x32}, ++ {0x0b, 0x46}, ++ {0x0c, 0x11}, ++ {0x0e, 0x11}, ++ {0x16, 0x04}, ++ }, ++ 0, ++ }, ++ { ++ { ++ {0x4e300100, 0x00061000}, ++ {0x4e300104, 0xF855000A}, ++ {0x4e300108, 0x6E62FA48}, ++ {0x4e30010C, 0x0031010D}, ++ {0x4e300124, 0x04C50000}, ++ {0x4e300160, 0x00009100}, ++ {0x4e30016C, 0x30000000}, ++ {0x4e300170, 0x89090408}, ++ {0x4e300250, 0x00000007}, ++ {0x4e300254, 0x00340034}, ++ {0x4e300258, 0x00000008}, ++ {0x4e30025C, 0x00000400}, ++ }, ++ { ++ {0x01, 0x94}, ++ {0x02, 0x9}, ++ {0x03, 0x32}, ++ {0x0b, 0x46}, ++ {0x0c, 0x11}, ++ {0x0e, 0x11}, ++ {0x16, 0x04}, ++ }, ++ 1, ++ }, ++}; ++ ++/* PHY Initialize Configuration */ ++static struct dram_cfg_param ddr_ddrphy_cfg[] = { ++ {0x100a0, 0x4}, ++ {0x100a1, 0x5}, ++ {0x100a2, 0x6}, ++ {0x100a3, 0x7}, ++ {0x100a4, 0x0}, ++ {0x100a5, 0x1}, ++ {0x100a6, 0x2}, ++ {0x100a7, 0x3}, ++ {0x110a0, 0x3}, ++ {0x110a1, 0x2}, ++ {0x110a2, 0x0}, ++ {0x110a3, 0x1}, ++ {0x110a4, 0x7}, ++ {0x110a5, 0x6}, ++ {0x110a6, 0x4}, ++ {0x110a7, 0x5}, ++ {0x1005f, 0x5ff}, ++ {0x1015f, 0x5ff}, ++ {0x1105f, 0x5ff}, ++ {0x1115f, 0x5ff}, ++ {0x11005f, 0x5ff}, ++ {0x11015f, 0x5ff}, ++ {0x11105f, 0x5ff}, ++ {0x11115f, 0x5ff}, ++ {0x21005f, 0x5ff}, ++ {0x21015f, 0x5ff}, ++ {0x21105f, 0x5ff}, ++ {0x21115f, 0x5ff}, ++ {0x55, 0x1ff}, ++ {0x1055, 0x1ff}, ++ {0x2055, 0x1ff}, ++ {0x200c5, 0x19}, ++ {0x1200c5, 0xb}, ++ {0x2200c5, 0x7}, ++ {0x2002e, 0x2}, ++ {0x12002e, 0x2}, ++ {0x22002e, 0x2}, ++ {0x90204, 0x0}, ++ {0x190204, 0x0}, ++ {0x290204, 0x0}, ++ {0x20024, 0x1e3}, ++ {0x2003a, 0x2}, ++ {0x2007d, 0x212}, ++ {0x2007c, 0x61}, ++ {0x120024, 0x1e3}, ++ {0x2003a, 0x2}, ++ {0x12007d, 0x212}, ++ {0x12007c, 0x61}, ++ {0x220024, 0x1e3}, ++ {0x2003a, 0x2}, ++ {0x22007d, 0x212}, ++ {0x22007c, 0x61}, ++ {0x20056, 0x3}, ++ {0x120056, 0x3}, ++ {0x220056, 0x3}, ++ {0x1004d, 0x600}, ++ {0x1014d, 0x600}, ++ {0x1104d, 0x600}, ++ {0x1114d, 0x600}, ++ {0x11004d, 0x600}, ++ {0x11014d, 0x600}, ++ {0x11104d, 0x600}, ++ {0x11114d, 0x600}, ++ {0x21004d, 0x600}, ++ {0x21014d, 0x600}, ++ {0x21104d, 0x600}, ++ {0x21114d, 0x600}, ++ {0x10049, 0xe00}, ++ {0x10149, 0xe00}, ++ {0x11049, 0xe00}, ++ {0x11149, 0xe00}, ++ {0x110049, 0xe00}, ++ {0x110149, 0xe00}, ++ {0x111049, 0xe00}, ++ {0x111149, 0xe00}, ++ {0x210049, 0xe00}, ++ {0x210149, 0xe00}, ++ {0x211049, 0xe00}, ++ {0x211149, 0xe00}, ++ {0x43, 0x60}, ++ {0x1043, 0x60}, ++ {0x2043, 0x60}, ++ {0x20018, 0x1}, ++ {0x20075, 0x4}, ++ {0x20050, 0x0}, ++ {0x2009b, 0x2}, ++ {0x20008, 0x3a5}, ++ {0x120008, 0x1d3}, ++ {0x220008, 0x9c}, ++ {0x20088, 0x9}, ++ {0x200b2, 0x10c}, ++ {0x10043, 0x5a1}, ++ {0x10143, 0x5a1}, ++ {0x11043, 0x5a1}, ++ {0x11143, 0x5a1}, ++ {0x1200b2, 0x10c}, ++ {0x110043, 0x5a1}, ++ {0x110143, 0x5a1}, ++ {0x111043, 0x5a1}, ++ {0x111143, 0x5a1}, ++ {0x2200b2, 0x10c}, ++ {0x210043, 0x5a1}, ++ {0x210143, 0x5a1}, ++ {0x211043, 0x5a1}, ++ {0x211143, 0x5a1}, ++ {0x200fa, 0x2}, ++ {0x1200fa, 0x2}, ++ {0x2200fa, 0x2}, ++ {0x20019, 0x1}, ++ {0x120019, 0x1}, ++ {0x220019, 0x1}, ++ {0x200f0, 0x600}, ++ {0x200f1, 0x0}, ++ {0x200f2, 0x4444}, ++ {0x200f3, 0x8888}, ++ {0x200f4, 0x5655}, ++ {0x200f5, 0x0}, ++ {0x200f6, 0x0}, ++ {0x200f7, 0xf000}, ++ {0x1004a, 0x500}, ++ {0x1104a, 0x500}, ++ {0x20025, 0x0}, ++ {0x2002d, 0x0}, ++ {0x12002d, 0x0}, ++ {0x22002d, 0x0}, ++ {0x2002c, 0x0}, ++ {0x20021, 0x0}, ++ {0x200c7, 0x21}, ++ {0x1200c7, 0x21}, ++ {0x200ca, 0x24}, ++ {0x1200ca, 0x24}, ++}; ++ ++/* ddr phy trained csr */ ++static struct dram_cfg_param ddr_ddrphy_trained_csr[] = { ++ {0x1005f, 0x0}, ++ {0x1015f, 0x0}, ++ {0x1105f, 0x0}, ++ {0x1115f, 0x0}, ++ {0x11005f, 0x0}, ++ {0x11015f, 0x0}, ++ {0x11105f, 0x0}, ++ {0x11115f, 0x0}, ++ {0x21005f, 0x0}, ++ {0x21015f, 0x0}, ++ {0x21105f, 0x0}, ++ {0x21115f, 0x0}, ++ {0x55, 0x0}, ++ {0x1055, 0x0}, ++ {0x2055, 0x0}, ++ {0x200c5, 0x0}, ++ {0x1200c5, 0x0}, ++ {0x2200c5, 0x0}, ++ {0x2002e, 0x0}, ++ {0x12002e, 0x0}, ++ {0x22002e, 0x0}, ++ {0x90204, 0x0}, ++ {0x190204, 0x0}, ++ {0x290204, 0x0}, ++ {0x20024, 0x0}, ++ {0x2003a, 0x0}, ++ {0x2007d, 0x0}, ++ {0x2007c, 0x0}, ++ {0x120024, 0x0}, ++ {0x12007d, 0x0}, ++ {0x12007c, 0x0}, ++ {0x220024, 0x0}, ++ {0x22007d, 0x0}, ++ {0x22007c, 0x0}, ++ {0x20056, 0x0}, ++ {0x120056, 0x0}, ++ {0x220056, 0x0}, ++ {0x1004d, 0x0}, ++ {0x1014d, 0x0}, ++ {0x1104d, 0x0}, ++ {0x1114d, 0x0}, ++ {0x11004d, 0x0}, ++ {0x11014d, 0x0}, ++ {0x11104d, 0x0}, ++ {0x11114d, 0x0}, ++ {0x21004d, 0x0}, ++ {0x21014d, 0x0}, ++ {0x21104d, 0x0}, ++ {0x21114d, 0x0}, ++ {0x10049, 0x0}, ++ {0x10149, 0x0}, ++ {0x11049, 0x0}, ++ {0x11149, 0x0}, ++ {0x110049, 0x0}, ++ {0x110149, 0x0}, ++ {0x111049, 0x0}, ++ {0x111149, 0x0}, ++ {0x210049, 0x0}, ++ {0x210149, 0x0}, ++ {0x211049, 0x0}, ++ {0x211149, 0x0}, ++ {0x43, 0x0}, ++ {0x1043, 0x0}, ++ {0x2043, 0x0}, ++ {0x20018, 0x0}, ++ {0x20075, 0x0}, ++ {0x20050, 0x0}, ++ {0x2009b, 0x0}, ++ {0x20008, 0x0}, ++ {0x120008, 0x0}, ++ {0x220008, 0x0}, ++ {0x20088, 0x0}, ++ {0x200b2, 0x0}, ++ {0x10043, 0x0}, ++ {0x10143, 0x0}, ++ {0x11043, 0x0}, ++ {0x11143, 0x0}, ++ {0x1200b2, 0x0}, ++ {0x110043, 0x0}, ++ {0x110143, 0x0}, ++ {0x111043, 0x0}, ++ {0x111143, 0x0}, ++ {0x2200b2, 0x0}, ++ {0x210043, 0x0}, ++ {0x210143, 0x0}, ++ {0x211043, 0x0}, ++ {0x211143, 0x0}, ++ {0x200fa, 0x0}, ++ {0x1200fa, 0x0}, ++ {0x2200fa, 0x0}, ++ {0x20019, 0x0}, ++ {0x120019, 0x0}, ++ {0x220019, 0x0}, ++ {0x200f0, 0x0}, ++ {0x200f1, 0x0}, ++ {0x200f2, 0x0}, ++ {0x200f3, 0x0}, ++ {0x200f4, 0x0}, ++ {0x200f5, 0x0}, ++ {0x200f6, 0x0}, ++ {0x200f7, 0x0}, ++ {0x1004a, 0x0}, ++ {0x1104a, 0x0}, ++ {0x20025, 0x0}, ++ {0x2002d, 0x0}, ++ {0x12002d, 0x0}, ++ {0x22002d, 0x0}, ++ {0x2002c, 0x0}, ++ {0xd0000, 0x0}, ++ {0x90000, 0x0}, ++ {0x90001, 0x0}, ++ {0x90002, 0x0}, ++ {0x90003, 0x0}, ++ {0x90004, 0x0}, ++ {0x90005, 0x0}, ++ {0x90029, 0x0}, ++ {0x9002a, 0x0}, ++ {0x9002b, 0x0}, ++ {0x9002c, 0x0}, ++ {0x9002d, 0x0}, ++ {0x9002e, 0x0}, ++ {0x9002f, 0x0}, ++ {0x90030, 0x0}, ++ {0x90031, 0x0}, ++ {0x90032, 0x0}, ++ {0x90033, 0x0}, ++ {0x90034, 0x0}, ++ {0x90035, 0x0}, ++ {0x90036, 0x0}, ++ {0x90037, 0x0}, ++ {0x90038, 0x0}, ++ {0x90039, 0x0}, ++ {0x9003a, 0x0}, ++ {0x9003b, 0x0}, ++ {0x9003c, 0x0}, ++ {0x9003d, 0x0}, ++ {0x9003e, 0x0}, ++ {0x9003f, 0x0}, ++ {0x90040, 0x0}, ++ {0x90041, 0x0}, ++ {0x90042, 0x0}, ++ {0x90043, 0x0}, ++ {0x90044, 0x0}, ++ {0x90045, 0x0}, ++ {0x90046, 0x0}, ++ {0x90047, 0x0}, ++ {0x90048, 0x0}, ++ {0x90049, 0x0}, ++ {0x9004a, 0x0}, ++ {0x9004b, 0x0}, ++ {0x9004c, 0x0}, ++ {0x9004d, 0x0}, ++ {0x9004e, 0x0}, ++ {0x9004f, 0x0}, ++ {0x90050, 0x0}, ++ {0x90051, 0x0}, ++ {0x90052, 0x0}, ++ {0x90053, 0x0}, ++ {0x90054, 0x0}, ++ {0x90055, 0x0}, ++ {0x90056, 0x0}, ++ {0x90057, 0x0}, ++ {0x90058, 0x0}, ++ {0x90059, 0x0}, ++ {0x9005a, 0x0}, ++ {0x9005b, 0x0}, ++ {0x9005c, 0x0}, ++ {0x9005d, 0x0}, ++ {0x9005e, 0x0}, ++ {0x9005f, 0x0}, ++ {0x90060, 0x0}, ++ {0x90061, 0x0}, ++ {0x90062, 0x0}, ++ {0x90063, 0x0}, ++ {0x90064, 0x0}, ++ {0x90065, 0x0}, ++ {0x90066, 0x0}, ++ {0x90067, 0x0}, ++ {0x90068, 0x0}, ++ {0x90069, 0x0}, ++ {0x9006a, 0x0}, ++ {0x9006b, 0x0}, ++ {0x9006c, 0x0}, ++ {0x9006d, 0x0}, ++ {0x9006e, 0x0}, ++ {0x9006f, 0x0}, ++ {0x90070, 0x0}, ++ {0x90071, 0x0}, ++ {0x90072, 0x0}, ++ {0x90073, 0x0}, ++ {0x90074, 0x0}, ++ {0x90075, 0x0}, ++ {0x90076, 0x0}, ++ {0x90077, 0x0}, ++ {0x90078, 0x0}, ++ {0x90079, 0x0}, ++ {0x9007a, 0x0}, ++ {0x9007b, 0x0}, ++ {0x9007c, 0x0}, ++ {0x9007d, 0x0}, ++ {0x9007e, 0x0}, ++ {0x9007f, 0x0}, ++ {0x90080, 0x0}, ++ {0x90081, 0x0}, ++ {0x90082, 0x0}, ++ {0x90083, 0x0}, ++ {0x90084, 0x0}, ++ {0x90085, 0x0}, ++ {0x90086, 0x0}, ++ {0x90087, 0x0}, ++ {0x90088, 0x0}, ++ {0x90089, 0x0}, ++ {0x9008a, 0x0}, ++ {0x9008b, 0x0}, ++ {0x9008c, 0x0}, ++ {0x9008d, 0x0}, ++ {0x9008e, 0x0}, ++ {0x9008f, 0x0}, ++ {0x90090, 0x0}, ++ {0x90091, 0x0}, ++ {0x90092, 0x0}, ++ {0x90093, 0x0}, ++ {0x90094, 0x0}, ++ {0x90095, 0x0}, ++ {0x90096, 0x0}, ++ {0x90097, 0x0}, ++ {0x90098, 0x0}, ++ {0x90099, 0x0}, ++ {0x9009a, 0x0}, ++ {0x9009b, 0x0}, ++ {0x9009c, 0x0}, ++ {0x9009d, 0x0}, ++ {0x9009e, 0x0}, ++ {0x9009f, 0x0}, ++ {0x900a0, 0x0}, ++ {0x900a1, 0x0}, ++ {0x900a2, 0x0}, ++ {0x900a3, 0x0}, ++ {0x900a4, 0x0}, ++ {0x900a5, 0x0}, ++ {0x900a6, 0x0}, ++ {0x900a7, 0x0}, ++ {0x900a8, 0x0}, ++ {0x900a9, 0x0}, ++ {0x40000, 0x0}, ++ {0x40020, 0x0}, ++ {0x40040, 0x0}, ++ {0x40060, 0x0}, ++ {0x40001, 0x0}, ++ {0x40021, 0x0}, ++ {0x40041, 0x0}, ++ {0x40061, 0x0}, ++ {0x40002, 0x0}, ++ {0x40022, 0x0}, ++ {0x40042, 0x0}, ++ {0x40062, 0x0}, ++ {0x40003, 0x0}, ++ {0x40023, 0x0}, ++ {0x40043, 0x0}, ++ {0x40063, 0x0}, ++ {0x40004, 0x0}, ++ {0x40024, 0x0}, ++ {0x40044, 0x0}, ++ {0x40064, 0x0}, ++ {0x40005, 0x0}, ++ {0x40025, 0x0}, ++ {0x40045, 0x0}, ++ {0x40065, 0x0}, ++ {0x40006, 0x0}, ++ {0x40026, 0x0}, ++ {0x40046, 0x0}, ++ {0x40066, 0x0}, ++ {0x40007, 0x0}, ++ {0x40027, 0x0}, ++ {0x40047, 0x0}, ++ {0x40067, 0x0}, ++ {0x40008, 0x0}, ++ {0x40028, 0x0}, ++ {0x40048, 0x0}, ++ {0x40068, 0x0}, ++ {0x40009, 0x0}, ++ {0x40029, 0x0}, ++ {0x40049, 0x0}, ++ {0x40069, 0x0}, ++ {0x4000a, 0x0}, ++ {0x4002a, 0x0}, ++ {0x4004a, 0x0}, ++ {0x4006a, 0x0}, ++ {0x4000b, 0x0}, ++ {0x4002b, 0x0}, ++ {0x4004b, 0x0}, ++ {0x4006b, 0x0}, ++ {0x4000c, 0x0}, ++ {0x4002c, 0x0}, ++ {0x4004c, 0x0}, ++ {0x4006c, 0x0}, ++ {0x4000d, 0x0}, ++ {0x4002d, 0x0}, ++ {0x4004d, 0x0}, ++ {0x4006d, 0x0}, ++ {0x4000e, 0x0}, ++ {0x4002e, 0x0}, ++ {0x4004e, 0x0}, ++ {0x4006e, 0x0}, ++ {0x4000f, 0x0}, ++ {0x4002f, 0x0}, ++ {0x4004f, 0x0}, ++ {0x4006f, 0x0}, ++ {0x40010, 0x0}, ++ {0x40030, 0x0}, ++ {0x40050, 0x0}, ++ {0x40070, 0x0}, ++ {0x40011, 0x0}, ++ {0x40031, 0x0}, ++ {0x40051, 0x0}, ++ {0x40071, 0x0}, ++ {0x40012, 0x0}, ++ {0x40032, 0x0}, ++ {0x40052, 0x0}, ++ {0x40072, 0x0}, ++ {0x40013, 0x0}, ++ {0x40033, 0x0}, ++ {0x40053, 0x0}, ++ {0x40073, 0x0}, ++ {0x40014, 0x0}, ++ {0x40034, 0x0}, ++ {0x40054, 0x0}, ++ {0x40074, 0x0}, ++ {0x40015, 0x0}, ++ {0x40035, 0x0}, ++ {0x40055, 0x0}, ++ {0x40075, 0x0}, ++ {0x40016, 0x0}, ++ {0x40036, 0x0}, ++ {0x40056, 0x0}, ++ {0x40076, 0x0}, ++ {0x40017, 0x0}, ++ {0x40037, 0x0}, ++ {0x40057, 0x0}, ++ {0x40077, 0x0}, ++ {0x40018, 0x0}, ++ {0x40038, 0x0}, ++ {0x40058, 0x0}, ++ {0x40078, 0x0}, ++ {0x40019, 0x0}, ++ {0x40039, 0x0}, ++ {0x40059, 0x0}, ++ {0x40079, 0x0}, ++ {0x4001a, 0x0}, ++ {0x4003a, 0x0}, ++ {0x4005a, 0x0}, ++ {0x4007a, 0x0}, ++ {0x900aa, 0x0}, ++ {0x900ab, 0x0}, ++ {0x900ac, 0x0}, ++ {0x900ad, 0x0}, ++ {0x900ae, 0x0}, ++ {0x900af, 0x0}, ++ {0x900b0, 0x0}, ++ {0x900b1, 0x0}, ++ {0x900b2, 0x0}, ++ {0x900b3, 0x0}, ++ {0x900b4, 0x0}, ++ {0x900b5, 0x0}, ++ {0x900b6, 0x0}, ++ {0x900b7, 0x0}, ++ {0x900b8, 0x0}, ++ {0x900b9, 0x0}, ++ {0x900ba, 0x0}, ++ {0x900bb, 0x0}, ++ {0x900bc, 0x0}, ++ {0x900bd, 0x0}, ++ {0x900be, 0x0}, ++ {0x900bf, 0x0}, ++ {0x900c0, 0x0}, ++ {0x900c1, 0x0}, ++ {0x900c2, 0x0}, ++ {0x900c3, 0x0}, ++ {0x900c4, 0x0}, ++ {0x900c5, 0x0}, ++ {0x900c6, 0x0}, ++ {0x900c7, 0x0}, ++ {0x900c8, 0x0}, ++ {0x900c9, 0x0}, ++ {0x900ca, 0x0}, ++ {0x900cb, 0x0}, ++ {0x900cc, 0x0}, ++ {0x900cd, 0x0}, ++ {0x900ce, 0x0}, ++ {0x900cf, 0x0}, ++ {0x900d0, 0x0}, ++ {0x900d1, 0x0}, ++ {0x900d2, 0x0}, ++ {0x900d3, 0x0}, ++ {0x900d4, 0x0}, ++ {0x900d5, 0x0}, ++ {0x900d6, 0x0}, ++ {0x900d7, 0x0}, ++ {0x900d8, 0x0}, ++ {0x900d9, 0x0}, ++ {0x900da, 0x0}, ++ {0x900db, 0x0}, ++ {0x900dc, 0x0}, ++ {0x900dd, 0x0}, ++ {0x900de, 0x0}, ++ {0x900df, 0x0}, ++ {0x900e0, 0x0}, ++ {0x900e1, 0x0}, ++ {0x900e2, 0x0}, ++ {0x900e3, 0x0}, ++ {0x900e4, 0x0}, ++ {0x900e5, 0x0}, ++ {0x900e6, 0x0}, ++ {0x900e7, 0x0}, ++ {0x900e8, 0x0}, ++ {0x900e9, 0x0}, ++ {0x900ea, 0x0}, ++ {0x900eb, 0x0}, ++ {0x900ec, 0x0}, ++ {0x900ed, 0x0}, ++ {0x900ee, 0x0}, ++ {0x900ef, 0x0}, ++ {0x900f0, 0x0}, ++ {0x900f1, 0x0}, ++ {0x900f2, 0x0}, ++ {0x900f3, 0x0}, ++ {0x900f4, 0x0}, ++ {0x900f5, 0x0}, ++ {0x900f6, 0x0}, ++ {0x900f7, 0x0}, ++ {0x900f8, 0x0}, ++ {0x900f9, 0x0}, ++ {0x900fa, 0x0}, ++ {0x900fb, 0x0}, ++ {0x900fc, 0x0}, ++ {0x900fd, 0x0}, ++ {0x900fe, 0x0}, ++ {0x900ff, 0x0}, ++ {0x90100, 0x0}, ++ {0x90101, 0x0}, ++ {0x90102, 0x0}, ++ {0x90103, 0x0}, ++ {0x90104, 0x0}, ++ {0x90105, 0x0}, ++ {0x90106, 0x0}, ++ {0x90107, 0x0}, ++ {0x90108, 0x0}, ++ {0x90109, 0x0}, ++ {0x9010a, 0x0}, ++ {0x9010b, 0x0}, ++ {0x9010c, 0x0}, ++ {0x9010d, 0x0}, ++ {0x9010e, 0x0}, ++ {0x9010f, 0x0}, ++ {0x90110, 0x0}, ++ {0x90111, 0x0}, ++ {0x90112, 0x0}, ++ {0x90113, 0x0}, ++ {0x90114, 0x0}, ++ {0x90115, 0x0}, ++ {0x90116, 0x0}, ++ {0x90117, 0x0}, ++ {0x90118, 0x0}, ++ {0x90119, 0x0}, ++ {0x9011a, 0x0}, ++ {0x9011b, 0x0}, ++ {0x9011c, 0x0}, ++ {0x9011d, 0x0}, ++ {0x9011e, 0x0}, ++ {0x9011f, 0x0}, ++ {0x90120, 0x0}, ++ {0x90121, 0x0}, ++ {0x90122, 0x0}, ++ {0x90123, 0x0}, ++ {0x90124, 0x0}, ++ {0x90125, 0x0}, ++ {0x90126, 0x0}, ++ {0x90127, 0x0}, ++ {0x90128, 0x0}, ++ {0x90129, 0x0}, ++ {0x9012a, 0x0}, ++ {0x9012b, 0x0}, ++ {0x9012c, 0x0}, ++ {0x9012d, 0x0}, ++ {0x9012e, 0x0}, ++ {0x9012f, 0x0}, ++ {0x90130, 0x0}, ++ {0x90131, 0x0}, ++ {0x90132, 0x0}, ++ {0x90133, 0x0}, ++ {0x90134, 0x0}, ++ {0x90135, 0x0}, ++ {0x90136, 0x0}, ++ {0x90137, 0x0}, ++ {0x90138, 0x0}, ++ {0x90139, 0x0}, ++ {0x9013a, 0x0}, ++ {0x9013b, 0x0}, ++ {0x9013c, 0x0}, ++ {0x9013d, 0x0}, ++ {0x9013e, 0x0}, ++ {0x9013f, 0x0}, ++ {0x90140, 0x0}, ++ {0x90141, 0x0}, ++ {0x90142, 0x0}, ++ {0x90143, 0x0}, ++ {0x90144, 0x0}, ++ {0x90145, 0x0}, ++ {0x90146, 0x0}, ++ {0x90147, 0x0}, ++ {0x90148, 0x0}, ++ {0x90149, 0x0}, ++ {0x9014a, 0x0}, ++ {0x9014b, 0x0}, ++ {0x9014c, 0x0}, ++ {0x9014d, 0x0}, ++ {0x9014e, 0x0}, ++ {0x9014f, 0x0}, ++ {0x90150, 0x0}, ++ {0x90151, 0x0}, ++ {0x90152, 0x0}, ++ {0x90153, 0x0}, ++ {0x90154, 0x0}, ++ {0x90155, 0x0}, ++ {0x90156, 0x0}, ++ {0x90157, 0x0}, ++ {0x90158, 0x0}, ++ {0x90159, 0x0}, ++ {0x9015a, 0x0}, ++ {0x9015b, 0x0}, ++ {0x9015c, 0x0}, ++ {0x9015d, 0x0}, ++ {0x9015e, 0x0}, ++ {0x9015f, 0x0}, ++ {0x90160, 0x0}, ++ {0x90161, 0x0}, ++ {0x90162, 0x0}, ++ {0x90163, 0x0}, ++ {0x90164, 0x0}, ++ {0x90165, 0x0}, ++ {0x90166, 0x0}, ++ {0x90167, 0x0}, ++ {0x90168, 0x0}, ++ {0x90169, 0x0}, ++ {0x9016a, 0x0}, ++ {0x9016b, 0x0}, ++ {0x9016c, 0x0}, ++ {0x9016d, 0x0}, ++ {0x9016e, 0x0}, ++ {0x9016f, 0x0}, ++ {0x90170, 0x0}, ++ {0x90171, 0x0}, ++ {0x90172, 0x0}, ++ {0x90173, 0x0}, ++ {0x90174, 0x0}, ++ {0x90175, 0x0}, ++ {0x90176, 0x0}, ++ {0x90177, 0x0}, ++ {0x90178, 0x0}, ++ {0x90179, 0x0}, ++ {0x9017a, 0x0}, ++ {0x9017b, 0x0}, ++ {0x9017c, 0x0}, ++ {0x9017d, 0x0}, ++ {0x9017e, 0x0}, ++ {0x9017f, 0x0}, ++ {0x90180, 0x0}, ++ {0x90181, 0x0}, ++ {0x90182, 0x0}, ++ {0x90183, 0x0}, ++ {0x90184, 0x0}, ++ {0x90006, 0x0}, ++ {0x90007, 0x0}, ++ {0x90008, 0x0}, ++ {0x90009, 0x0}, ++ {0x9000a, 0x0}, ++ {0x9000b, 0x0}, ++ {0xd00e7, 0x0}, ++ {0x90017, 0x0}, ++ {0x9001f, 0x0}, ++ {0x90026, 0x0}, ++ {0x400d0, 0x0}, ++ {0x400d1, 0x0}, ++ {0x400d2, 0x0}, ++ {0x400d3, 0x0}, ++ {0x400d4, 0x0}, ++ {0x400d5, 0x0}, ++ {0x400d6, 0x0}, ++ {0x400d7, 0x0}, ++ {0x200be, 0x0}, ++ {0x2000b, 0x0}, ++ {0x2000c, 0x0}, ++ {0x2000d, 0x0}, ++ {0x2000e, 0x0}, ++ {0x12000b, 0x0}, ++ {0x12000c, 0x0}, ++ {0x12000d, 0x0}, ++ {0x12000e, 0x0}, ++ {0x22000b, 0x0}, ++ {0x22000c, 0x0}, ++ {0x22000d, 0x0}, ++ {0x22000e, 0x0}, ++ {0x9000c, 0x0}, ++ {0x9000d, 0x0}, ++ {0x9000e, 0x0}, ++ {0x9000f, 0x0}, ++ {0x90010, 0x0}, ++ {0x90011, 0x0}, ++ {0x90012, 0x0}, ++ {0x90013, 0x0}, ++ {0x20010, 0x0}, ++ {0x20011, 0x0}, ++ {0x120010, 0x0}, ++ {0x120011, 0x0}, ++ {0x40080, 0x0}, ++ {0x40081, 0x0}, ++ {0x40082, 0x0}, ++ {0x40083, 0x0}, ++ {0x40084, 0x0}, ++ {0x40085, 0x0}, ++ {0x140080, 0x0}, ++ {0x140081, 0x0}, ++ {0x140082, 0x0}, ++ {0x140083, 0x0}, ++ {0x140084, 0x0}, ++ {0x140085, 0x0}, ++ {0x240080, 0x0}, ++ {0x240081, 0x0}, ++ {0x240082, 0x0}, ++ {0x240083, 0x0}, ++ {0x240084, 0x0}, ++ {0x240085, 0x0}, ++ {0x400fd, 0x0}, ++ {0x400f1, 0x0}, ++ {0x10011, 0x0}, ++ {0x10012, 0x0}, ++ {0x10013, 0x0}, ++ {0x10018, 0x0}, ++ {0x10002, 0x0}, ++ {0x100b2, 0x0}, ++ {0x101b4, 0x0}, ++ {0x102b4, 0x0}, ++ {0x103b4, 0x0}, ++ {0x104b4, 0x0}, ++ {0x105b4, 0x0}, ++ {0x106b4, 0x0}, ++ {0x107b4, 0x0}, ++ {0x108b4, 0x0}, ++ {0x11011, 0x0}, ++ {0x11012, 0x0}, ++ {0x11013, 0x0}, ++ {0x11018, 0x0}, ++ {0x11002, 0x0}, ++ {0x110b2, 0x0}, ++ {0x111b4, 0x0}, ++ {0x112b4, 0x0}, ++ {0x113b4, 0x0}, ++ {0x114b4, 0x0}, ++ {0x115b4, 0x0}, ++ {0x116b4, 0x0}, ++ {0x117b4, 0x0}, ++ {0x118b4, 0x0}, ++ {0x20089, 0x0}, ++ {0xc0080, 0x0}, ++ {0x200cb, 0x0}, ++ {0x10068, 0x0}, ++ {0x10069, 0x0}, ++ {0x10168, 0x0}, ++ {0x10169, 0x0}, ++ {0x10268, 0x0}, ++ {0x10269, 0x0}, ++ {0x10368, 0x0}, ++ {0x10369, 0x0}, ++ {0x10468, 0x0}, ++ {0x10469, 0x0}, ++ {0x10568, 0x0}, ++ {0x10569, 0x0}, ++ {0x10668, 0x0}, ++ {0x10669, 0x0}, ++ {0x10768, 0x0}, ++ {0x10769, 0x0}, ++ {0x10868, 0x0}, ++ {0x10869, 0x0}, ++ {0x100aa, 0x0}, ++ {0x10062, 0x0}, ++ {0x10001, 0x0}, ++ {0x100a0, 0x0}, ++ {0x100a1, 0x0}, ++ {0x100a2, 0x0}, ++ {0x100a3, 0x0}, ++ {0x100a4, 0x0}, ++ {0x100a5, 0x0}, ++ {0x100a6, 0x0}, ++ {0x100a7, 0x0}, ++ {0x11068, 0x0}, ++ {0x11069, 0x0}, ++ {0x11168, 0x0}, ++ {0x11169, 0x0}, ++ {0x11268, 0x0}, ++ {0x11269, 0x0}, ++ {0x11368, 0x0}, ++ {0x11369, 0x0}, ++ {0x11468, 0x0}, ++ {0x11469, 0x0}, ++ {0x11568, 0x0}, ++ {0x11569, 0x0}, ++ {0x11668, 0x0}, ++ {0x11669, 0x0}, ++ {0x11768, 0x0}, ++ {0x11769, 0x0}, ++ {0x11868, 0x0}, ++ {0x11869, 0x0}, ++ {0x110aa, 0x0}, ++ {0x11062, 0x0}, ++ {0x11001, 0x0}, ++ {0x110a0, 0x0}, ++ {0x110a1, 0x0}, ++ {0x110a2, 0x0}, ++ {0x110a3, 0x0}, ++ {0x110a4, 0x0}, ++ {0x110a5, 0x0}, ++ {0x110a6, 0x0}, ++ {0x110a7, 0x0}, ++ {0x80, 0x0}, ++ {0x1080, 0x0}, ++ {0x2080, 0x0}, ++ {0x10020, 0x0}, ++ {0x10080, 0x0}, ++ {0x10081, 0x0}, ++ {0x100d0, 0x0}, ++ {0x100d1, 0x0}, ++ {0x1008c, 0x0}, ++ {0x1008d, 0x0}, ++ {0x10180, 0x0}, ++ {0x10181, 0x0}, ++ {0x101d0, 0x0}, ++ {0x101d1, 0x0}, ++ {0x1018c, 0x0}, ++ {0x1018d, 0x0}, ++ {0x100c0, 0x0}, ++ {0x100c1, 0x0}, ++ {0x101c0, 0x0}, ++ {0x101c1, 0x0}, ++ {0x102c0, 0x0}, ++ {0x102c1, 0x0}, ++ {0x103c0, 0x0}, ++ {0x103c1, 0x0}, ++ {0x104c0, 0x0}, ++ {0x104c1, 0x0}, ++ {0x105c0, 0x0}, ++ {0x105c1, 0x0}, ++ {0x106c0, 0x0}, ++ {0x106c1, 0x0}, ++ {0x107c0, 0x0}, ++ {0x107c1, 0x0}, ++ {0x108c0, 0x0}, ++ {0x108c1, 0x0}, ++ {0x100ae, 0x0}, ++ {0x100af, 0x0}, ++ {0x11020, 0x0}, ++ {0x11080, 0x0}, ++ {0x11081, 0x0}, ++ {0x110d0, 0x0}, ++ {0x110d1, 0x0}, ++ {0x1108c, 0x0}, ++ {0x1108d, 0x0}, ++ {0x11180, 0x0}, ++ {0x11181, 0x0}, ++ {0x111d0, 0x0}, ++ {0x111d1, 0x0}, ++ {0x1118c, 0x0}, ++ {0x1118d, 0x0}, ++ {0x110c0, 0x0}, ++ {0x110c1, 0x0}, ++ {0x111c0, 0x0}, ++ {0x111c1, 0x0}, ++ {0x112c0, 0x0}, ++ {0x112c1, 0x0}, ++ {0x113c0, 0x0}, ++ {0x113c1, 0x0}, ++ {0x114c0, 0x0}, ++ {0x114c1, 0x0}, ++ {0x115c0, 0x0}, ++ {0x115c1, 0x0}, ++ {0x116c0, 0x0}, ++ {0x116c1, 0x0}, ++ {0x117c0, 0x0}, ++ {0x117c1, 0x0}, ++ {0x118c0, 0x0}, ++ {0x118c1, 0x0}, ++ {0x110ae, 0x0}, ++ {0x110af, 0x0}, ++ {0x90201, 0x0}, ++ {0x90202, 0x0}, ++ {0x90203, 0x0}, ++ {0x90205, 0x0}, ++ {0x90206, 0x0}, ++ {0x90207, 0x0}, ++ {0x90208, 0x0}, ++ {0x20020, 0x0}, ++ {0x100080, 0x0}, ++ {0x101080, 0x0}, ++ {0x102080, 0x0}, ++ {0x110020, 0x0}, ++ {0x110080, 0x0}, ++ {0x110081, 0x0}, ++ {0x1100d0, 0x0}, ++ {0x1100d1, 0x0}, ++ {0x11008c, 0x0}, ++ {0x11008d, 0x0}, ++ {0x110180, 0x0}, ++ {0x110181, 0x0}, ++ {0x1101d0, 0x0}, ++ {0x1101d1, 0x0}, ++ {0x11018c, 0x0}, ++ {0x11018d, 0x0}, ++ {0x1100c0, 0x0}, ++ {0x1100c1, 0x0}, ++ {0x1101c0, 0x0}, ++ {0x1101c1, 0x0}, ++ {0x1102c0, 0x0}, ++ {0x1102c1, 0x0}, ++ {0x1103c0, 0x0}, ++ {0x1103c1, 0x0}, ++ {0x1104c0, 0x0}, ++ {0x1104c1, 0x0}, ++ {0x1105c0, 0x0}, ++ {0x1105c1, 0x0}, ++ {0x1106c0, 0x0}, ++ {0x1106c1, 0x0}, ++ {0x1107c0, 0x0}, ++ {0x1107c1, 0x0}, ++ {0x1108c0, 0x0}, ++ {0x1108c1, 0x0}, ++ {0x1100ae, 0x0}, ++ {0x1100af, 0x0}, ++ {0x111020, 0x0}, ++ {0x111080, 0x0}, ++ {0x111081, 0x0}, ++ {0x1110d0, 0x0}, ++ {0x1110d1, 0x0}, ++ {0x11108c, 0x0}, ++ {0x11108d, 0x0}, ++ {0x111180, 0x0}, ++ {0x111181, 0x0}, ++ {0x1111d0, 0x0}, ++ {0x1111d1, 0x0}, ++ {0x11118c, 0x0}, ++ {0x11118d, 0x0}, ++ {0x1110c0, 0x0}, ++ {0x1110c1, 0x0}, ++ {0x1111c0, 0x0}, ++ {0x1111c1, 0x0}, ++ {0x1112c0, 0x0}, ++ {0x1112c1, 0x0}, ++ {0x1113c0, 0x0}, ++ {0x1113c1, 0x0}, ++ {0x1114c0, 0x0}, ++ {0x1114c1, 0x0}, ++ {0x1115c0, 0x0}, ++ {0x1115c1, 0x0}, ++ {0x1116c0, 0x0}, ++ {0x1116c1, 0x0}, ++ {0x1117c0, 0x0}, ++ {0x1117c1, 0x0}, ++ {0x1118c0, 0x0}, ++ {0x1118c1, 0x0}, ++ {0x1110ae, 0x0}, ++ {0x1110af, 0x0}, ++ {0x190201, 0x0}, ++ {0x190202, 0x0}, ++ {0x190203, 0x0}, ++ {0x190205, 0x0}, ++ {0x190206, 0x0}, ++ {0x190207, 0x0}, ++ {0x190208, 0x0}, ++ {0x120020, 0x0}, ++ {0x200080, 0x0}, ++ {0x201080, 0x0}, ++ {0x202080, 0x0}, ++ {0x210020, 0x0}, ++ {0x210080, 0x0}, ++ {0x210081, 0x0}, ++ {0x2100d0, 0x0}, ++ {0x2100d1, 0x0}, ++ {0x21008c, 0x0}, ++ {0x21008d, 0x0}, ++ {0x210180, 0x0}, ++ {0x210181, 0x0}, ++ {0x2101d0, 0x0}, ++ {0x2101d1, 0x0}, ++ {0x21018c, 0x0}, ++ {0x21018d, 0x0}, ++ {0x2100c0, 0x0}, ++ {0x2100c1, 0x0}, ++ {0x2101c0, 0x0}, ++ {0x2101c1, 0x0}, ++ {0x2102c0, 0x0}, ++ {0x2102c1, 0x0}, ++ {0x2103c0, 0x0}, ++ {0x2103c1, 0x0}, ++ {0x2104c0, 0x0}, ++ {0x2104c1, 0x0}, ++ {0x2105c0, 0x0}, ++ {0x2105c1, 0x0}, ++ {0x2106c0, 0x0}, ++ {0x2106c1, 0x0}, ++ {0x2107c0, 0x0}, ++ {0x2107c1, 0x0}, ++ {0x2108c0, 0x0}, ++ {0x2108c1, 0x0}, ++ {0x2100ae, 0x0}, ++ {0x2100af, 0x0}, ++ {0x211020, 0x0}, ++ {0x211080, 0x0}, ++ {0x211081, 0x0}, ++ {0x2110d0, 0x0}, ++ {0x2110d1, 0x0}, ++ {0x21108c, 0x0}, ++ {0x21108d, 0x0}, ++ {0x211180, 0x0}, ++ {0x211181, 0x0}, ++ {0x2111d0, 0x0}, ++ {0x2111d1, 0x0}, ++ {0x21118c, 0x0}, ++ {0x21118d, 0x0}, ++ {0x2110c0, 0x0}, ++ {0x2110c1, 0x0}, ++ {0x2111c0, 0x0}, ++ {0x2111c1, 0x0}, ++ {0x2112c0, 0x0}, ++ {0x2112c1, 0x0}, ++ {0x2113c0, 0x0}, ++ {0x2113c1, 0x0}, ++ {0x2114c0, 0x0}, ++ {0x2114c1, 0x0}, ++ {0x2115c0, 0x0}, ++ {0x2115c1, 0x0}, ++ {0x2116c0, 0x0}, ++ {0x2116c1, 0x0}, ++ {0x2117c0, 0x0}, ++ {0x2117c1, 0x0}, ++ {0x2118c0, 0x0}, ++ {0x2118c1, 0x0}, ++ {0x2110ae, 0x0}, ++ {0x2110af, 0x0}, ++ {0x290201, 0x0}, ++ {0x290202, 0x0}, ++ {0x290203, 0x0}, ++ {0x290205, 0x0}, ++ {0x290206, 0x0}, ++ {0x290207, 0x0}, ++ {0x290208, 0x0}, ++ {0x220020, 0x0}, ++ {0x20077, 0x0}, ++ {0x20072, 0x0}, ++ {0x20073, 0x0}, ++ {0x400c0, 0x0}, ++ {0x10040, 0x0}, ++ {0x10140, 0x0}, ++ {0x10240, 0x0}, ++ {0x10340, 0x0}, ++ {0x10440, 0x0}, ++ {0x10540, 0x0}, ++ {0x10640, 0x0}, ++ {0x10740, 0x0}, ++ {0x10840, 0x0}, ++ {0x11040, 0x0}, ++ {0x11140, 0x0}, ++ {0x11240, 0x0}, ++ {0x11340, 0x0}, ++ {0x11440, 0x0}, ++ {0x11540, 0x0}, ++ {0x11640, 0x0}, ++ {0x11740, 0x0}, ++ {0x11840, 0x0}, ++}; ++ ++/* P0 message block parameter for training firmware */ ++static struct dram_cfg_param ddr_fsp0_cfg[] = { ++ {0xd0000, 0x0}, ++ {0x54003, 0xe94}, ++ {0x54004, 0x4}, ++ {0x54006, 0x15}, ++ {0x54008, 0x131f}, ++ {0x54009, 0xc8}, ++ {0x5400b, 0x4}, ++ {0x5400d, 0x100}, ++ {0x5400f, 0x100}, ++ {0x54012, 0x110}, ++ {0x54019, 0x36e4}, ++ {0x5401a, 0x32}, ++ {0x5401b, 0x1146}, ++ {0x5401c, 0x1108}, ++ {0x5401e, 0x4}, ++ {0x5401f, 0x36e4}, ++ {0x54020, 0x32}, ++ {0x54021, 0x1146}, ++ {0x54022, 0x1108}, ++ {0x54024, 0x4}, ++ {0x54032, 0xe400}, ++ {0x54033, 0x3236}, ++ {0x54034, 0x4600}, ++ {0x54035, 0x811}, ++ {0x54036, 0x11}, ++ {0x54037, 0x400}, ++ {0x54038, 0xe400}, ++ {0x54039, 0x3236}, ++ {0x5403a, 0x4600}, ++ {0x5403b, 0x811}, ++ {0x5403c, 0x11}, ++ {0x5403d, 0x400}, ++ {0xd0000, 0x1} ++}; ++ ++/* P1 message block parameter for training firmware */ ++static struct dram_cfg_param ddr_fsp1_cfg[] = { ++ {0xd0000, 0x0}, ++ {0x54002, 0x1}, ++ {0x54003, 0x74a}, ++ {0x54004, 0x4}, ++ {0x54006, 0x15}, ++ {0x54008, 0x121f}, ++ {0x54009, 0xc8}, ++ {0x5400b, 0x4}, ++ {0x5400d, 0x100}, ++ {0x5400f, 0x100}, ++ {0x54012, 0x110}, ++ {0x54019, 0x1bb4}, ++ {0x5401a, 0x32}, ++ {0x5401b, 0x1146}, ++ {0x5401c, 0x1108}, ++ {0x5401e, 0x4}, ++ {0x5401f, 0x1bb4}, ++ {0x54020, 0x32}, ++ {0x54021, 0x1146}, ++ {0x54022, 0x1108}, ++ {0x54024, 0x4}, ++ {0x54032, 0xb400}, ++ {0x54033, 0x321b}, ++ {0x54034, 0x4600}, ++ {0x54035, 0x811}, ++ {0x54036, 0x11}, ++ {0x54037, 0x400}, ++ {0x54038, 0xb400}, ++ {0x54039, 0x321b}, ++ {0x5403a, 0x4600}, ++ {0x5403b, 0x811}, ++ {0x5403c, 0x11}, ++ {0x5403d, 0x400}, ++ {0xd0000, 0x1} ++}; ++ ++/* P2 message block parameter for training firmware */ ++static struct dram_cfg_param ddr_fsp2_cfg[] = { ++ {0xd0000, 0x0}, ++ {0x54002, 0x102}, ++ {0x54003, 0x270}, ++ {0x54004, 0x4}, ++ {0x54006, 0x15}, ++ {0x54008, 0x121f}, ++ {0x54009, 0xc8}, ++ {0x5400b, 0x4}, ++ {0x5400d, 0x100}, ++ {0x5400f, 0x100}, ++ {0x54012, 0x110}, ++ {0x54019, 0x994}, ++ {0x5401a, 0x32}, ++ {0x5401b, 0x1146}, ++ {0x5401c, 0x1100}, ++ {0x5401e, 0x4}, ++ {0x5401f, 0x994}, ++ {0x54020, 0x32}, ++ {0x54021, 0x1146}, ++ {0x54022, 0x1100}, ++ {0x54024, 0x4}, ++ {0x54032, 0x9400}, ++ {0x54033, 0x3209}, ++ {0x54034, 0x4600}, ++ {0x54035, 0x11}, ++ {0x54036, 0x11}, ++ {0x54037, 0x400}, ++ {0x54038, 0x9400}, ++ {0x54039, 0x3209}, ++ {0x5403a, 0x4600}, ++ {0x5403b, 0x11}, ++ {0x5403c, 0x11}, ++ {0x5403d, 0x400}, ++ {0xd0000, 0x1} ++}; ++ ++/* P0 2D message block parameter for training firmware */ ++static struct dram_cfg_param ddr_fsp0_2d_cfg[] = { ++ {0xd0000, 0x0}, ++ {0x54003, 0xe94}, ++ {0x54004, 0x4}, ++ {0x54006, 0x15}, ++ {0x54008, 0x61}, ++ {0x54009, 0xc8}, ++ {0x5400b, 0x4}, ++ {0x5400d, 0x100}, ++ {0x5400f, 0x100}, ++ {0x54010, 0x2080}, ++ {0x54012, 0x110}, ++ {0x54019, 0x36e4}, ++ {0x5401a, 0x32}, ++ {0x5401b, 0x1146}, ++ {0x5401c, 0x1108}, ++ {0x5401e, 0x4}, ++ {0x5401f, 0x36e4}, ++ {0x54020, 0x32}, ++ {0x54021, 0x1146}, ++ {0x54022, 0x1108}, ++ {0x54024, 0x4}, ++ {0x54032, 0xe400}, ++ {0x54033, 0x3236}, ++ {0x54034, 0x4600}, ++ {0x54035, 0x811}, ++ {0x54036, 0x11}, ++ {0x54037, 0x400}, ++ {0x54038, 0xe400}, ++ {0x54039, 0x3236}, ++ {0x5403a, 0x4600}, ++ {0x5403b, 0x811}, ++ {0x5403c, 0x11}, ++ {0x5403d, 0x400}, ++ {0xd0000, 0x1} ++}; ++ ++/* DRAM PHY init engine image */ ++static struct dram_cfg_param ddr_phy_pie[] = { ++ {0xd0000, 0x0}, ++ {0x90000, 0x10}, ++ {0x90001, 0x400}, ++ {0x90002, 0x10e}, ++ {0x90003, 0x0}, ++ {0x90004, 0x0}, ++ {0x90005, 0x8}, ++ {0x90029, 0xb}, ++ {0x9002a, 0x480}, ++ {0x9002b, 0x109}, ++ {0x9002c, 0x8}, ++ {0x9002d, 0x448}, ++ {0x9002e, 0x139}, ++ {0x9002f, 0x8}, ++ {0x90030, 0x478}, ++ {0x90031, 0x109}, ++ {0x90032, 0x0}, ++ {0x90033, 0xe8}, ++ {0x90034, 0x109}, ++ {0x90035, 0x2}, ++ {0x90036, 0x10}, ++ {0x90037, 0x139}, ++ {0x90038, 0xb}, ++ {0x90039, 0x7c0}, ++ {0x9003a, 0x139}, ++ {0x9003b, 0x44}, ++ {0x9003c, 0x633}, ++ {0x9003d, 0x159}, ++ {0x9003e, 0x14f}, ++ {0x9003f, 0x630}, ++ {0x90040, 0x159}, ++ {0x90041, 0x47}, ++ {0x90042, 0x633}, ++ {0x90043, 0x149}, ++ {0x90044, 0x4f}, ++ {0x90045, 0x633}, ++ {0x90046, 0x179}, ++ {0x90047, 0x8}, ++ {0x90048, 0xe0}, ++ {0x90049, 0x109}, ++ {0x9004a, 0x0}, ++ {0x9004b, 0x7c8}, ++ {0x9004c, 0x109}, ++ {0x9004d, 0x0}, ++ {0x9004e, 0x1}, ++ {0x9004f, 0x8}, ++ {0x90050, 0x30}, ++ {0x90051, 0x65a}, ++ {0x90052, 0x9}, ++ {0x90053, 0x0}, ++ {0x90054, 0x45a}, ++ {0x90055, 0x9}, ++ {0x90056, 0x0}, ++ {0x90057, 0x448}, ++ {0x90058, 0x109}, ++ {0x90059, 0x40}, ++ {0x9005a, 0x633}, ++ {0x9005b, 0x179}, ++ {0x9005c, 0x1}, ++ {0x9005d, 0x618}, ++ {0x9005e, 0x109}, ++ {0x9005f, 0x40c0}, ++ {0x90060, 0x633}, ++ {0x90061, 0x149}, ++ {0x90062, 0x8}, ++ {0x90063, 0x4}, ++ {0x90064, 0x48}, ++ {0x90065, 0x4040}, ++ {0x90066, 0x633}, ++ {0x90067, 0x149}, ++ {0x90068, 0x0}, ++ {0x90069, 0x4}, ++ {0x9006a, 0x48}, ++ {0x9006b, 0x40}, ++ {0x9006c, 0x633}, ++ {0x9006d, 0x149}, ++ {0x9006e, 0x0}, ++ {0x9006f, 0x658}, ++ {0x90070, 0x109}, ++ {0x90071, 0x10}, ++ {0x90072, 0x4}, ++ {0x90073, 0x18}, ++ {0x90074, 0x0}, ++ {0x90075, 0x4}, ++ {0x90076, 0x78}, ++ {0x90077, 0x549}, ++ {0x90078, 0x633}, ++ {0x90079, 0x159}, ++ {0x9007a, 0xd49}, ++ {0x9007b, 0x633}, ++ {0x9007c, 0x159}, ++ {0x9007d, 0x94a}, ++ {0x9007e, 0x633}, ++ {0x9007f, 0x159}, ++ {0x90080, 0x441}, ++ {0x90081, 0x633}, ++ {0x90082, 0x149}, ++ {0x90083, 0x42}, ++ {0x90084, 0x633}, ++ {0x90085, 0x149}, ++ {0x90086, 0x1}, ++ {0x90087, 0x633}, ++ {0x90088, 0x149}, ++ {0x90089, 0x0}, ++ {0x9008a, 0xe0}, ++ {0x9008b, 0x109}, ++ {0x9008c, 0xa}, ++ {0x9008d, 0x10}, ++ {0x9008e, 0x109}, ++ {0x9008f, 0x9}, ++ {0x90090, 0x3c0}, ++ {0x90091, 0x149}, ++ {0x90092, 0x9}, ++ {0x90093, 0x3c0}, ++ {0x90094, 0x159}, ++ {0x90095, 0x18}, ++ {0x90096, 0x10}, ++ {0x90097, 0x109}, ++ {0x90098, 0x0}, ++ {0x90099, 0x3c0}, ++ {0x9009a, 0x109}, ++ {0x9009b, 0x18}, ++ {0x9009c, 0x4}, ++ {0x9009d, 0x48}, ++ {0x9009e, 0x18}, ++ {0x9009f, 0x4}, ++ {0x900a0, 0x58}, ++ {0x900a1, 0xb}, ++ {0x900a2, 0x10}, ++ {0x900a3, 0x109}, ++ {0x900a4, 0x1}, ++ {0x900a5, 0x10}, ++ {0x900a6, 0x109}, ++ {0x900a7, 0x5}, ++ {0x900a8, 0x7c0}, ++ {0x900a9, 0x109}, ++ {0x40000, 0x811}, ++ {0x40020, 0x880}, ++ {0x40040, 0x0}, ++ {0x40060, 0x0}, ++ {0x40001, 0x4008}, ++ {0x40021, 0x83}, ++ {0x40041, 0x4f}, ++ {0x40061, 0x0}, ++ {0x40002, 0x4040}, ++ {0x40022, 0x83}, ++ {0x40042, 0x51}, ++ {0x40062, 0x0}, ++ {0x40003, 0x811}, ++ {0x40023, 0x880}, ++ {0x40043, 0x0}, ++ {0x40063, 0x0}, ++ {0x40004, 0x720}, ++ {0x40024, 0xf}, ++ {0x40044, 0x1740}, ++ {0x40064, 0x0}, ++ {0x40005, 0x16}, ++ {0x40025, 0x83}, ++ {0x40045, 0x4b}, ++ {0x40065, 0x0}, ++ {0x40006, 0x716}, ++ {0x40026, 0xf}, ++ {0x40046, 0x2001}, ++ {0x40066, 0x0}, ++ {0x40007, 0x716}, ++ {0x40027, 0xf}, ++ {0x40047, 0x2800}, ++ {0x40067, 0x0}, ++ {0x40008, 0x716}, ++ {0x40028, 0xf}, ++ {0x40048, 0xf00}, ++ {0x40068, 0x0}, ++ {0x40009, 0x720}, ++ {0x40029, 0xf}, ++ {0x40049, 0x1400}, ++ {0x40069, 0x0}, ++ {0x4000a, 0xe08}, ++ {0x4002a, 0xc15}, ++ {0x4004a, 0x0}, ++ {0x4006a, 0x0}, ++ {0x4000b, 0x625}, ++ {0x4002b, 0x15}, ++ {0x4004b, 0x0}, ++ {0x4006b, 0x0}, ++ {0x4000c, 0x4028}, ++ {0x4002c, 0x80}, ++ {0x4004c, 0x0}, ++ {0x4006c, 0x0}, ++ {0x4000d, 0xe08}, ++ {0x4002d, 0xc1a}, ++ {0x4004d, 0x0}, ++ {0x4006d, 0x0}, ++ {0x4000e, 0x625}, ++ {0x4002e, 0x1a}, ++ {0x4004e, 0x0}, ++ {0x4006e, 0x0}, ++ {0x4000f, 0x4040}, ++ {0x4002f, 0x80}, ++ {0x4004f, 0x0}, ++ {0x4006f, 0x0}, ++ {0x40010, 0x2604}, ++ {0x40030, 0x15}, ++ {0x40050, 0x0}, ++ {0x40070, 0x0}, ++ {0x40011, 0x708}, ++ {0x40031, 0x5}, ++ {0x40051, 0x0}, ++ {0x40071, 0x2002}, ++ {0x40012, 0x8}, ++ {0x40032, 0x80}, ++ {0x40052, 0x0}, ++ {0x40072, 0x0}, ++ {0x40013, 0x2604}, ++ {0x40033, 0x1a}, ++ {0x40053, 0x0}, ++ {0x40073, 0x0}, ++ {0x40014, 0x708}, ++ {0x40034, 0xa}, ++ {0x40054, 0x0}, ++ {0x40074, 0x2002}, ++ {0x40015, 0x4040}, ++ {0x40035, 0x80}, ++ {0x40055, 0x0}, ++ {0x40075, 0x0}, ++ {0x40016, 0x60a}, ++ {0x40036, 0x15}, ++ {0x40056, 0x1200}, ++ {0x40076, 0x0}, ++ {0x40017, 0x61a}, ++ {0x40037, 0x15}, ++ {0x40057, 0x1300}, ++ {0x40077, 0x0}, ++ {0x40018, 0x60a}, ++ {0x40038, 0x1a}, ++ {0x40058, 0x1200}, ++ {0x40078, 0x0}, ++ {0x40019, 0x642}, ++ {0x40039, 0x1a}, ++ {0x40059, 0x1300}, ++ {0x40079, 0x0}, ++ {0x4001a, 0x4808}, ++ {0x4003a, 0x880}, ++ {0x4005a, 0x0}, ++ {0x4007a, 0x0}, ++ {0x900aa, 0x0}, ++ {0x900ab, 0x790}, ++ {0x900ac, 0x11a}, ++ {0x900ad, 0x8}, ++ {0x900ae, 0x7aa}, ++ {0x900af, 0x2a}, ++ {0x900b0, 0x10}, ++ {0x900b1, 0x7b2}, ++ {0x900b2, 0x2a}, ++ {0x900b3, 0x0}, ++ {0x900b4, 0x7c8}, ++ {0x900b5, 0x109}, ++ {0x900b6, 0x10}, ++ {0x900b7, 0x10}, ++ {0x900b8, 0x109}, ++ {0x900b9, 0x10}, ++ {0x900ba, 0x2a8}, ++ {0x900bb, 0x129}, ++ {0x900bc, 0x8}, ++ {0x900bd, 0x370}, ++ {0x900be, 0x129}, ++ {0x900bf, 0xa}, ++ {0x900c0, 0x3c8}, ++ {0x900c1, 0x1a9}, ++ {0x900c2, 0xc}, ++ {0x900c3, 0x408}, ++ {0x900c4, 0x199}, ++ {0x900c5, 0x14}, ++ {0x900c6, 0x790}, ++ {0x900c7, 0x11a}, ++ {0x900c8, 0x8}, ++ {0x900c9, 0x4}, ++ {0x900ca, 0x18}, ++ {0x900cb, 0xe}, ++ {0x900cc, 0x408}, ++ {0x900cd, 0x199}, ++ {0x900ce, 0x8}, ++ {0x900cf, 0x8568}, ++ {0x900d0, 0x108}, ++ {0x900d1, 0x18}, ++ {0x900d2, 0x790}, ++ {0x900d3, 0x16a}, ++ {0x900d4, 0x8}, ++ {0x900d5, 0x1d8}, ++ {0x900d6, 0x169}, ++ {0x900d7, 0x10}, ++ {0x900d8, 0x8558}, ++ {0x900d9, 0x168}, ++ {0x900da, 0x1ff8}, ++ {0x900db, 0x85a8}, ++ {0x900dc, 0x1e8}, ++ {0x900dd, 0x50}, ++ {0x900de, 0x798}, ++ {0x900df, 0x16a}, ++ {0x900e0, 0x60}, ++ {0x900e1, 0x7a0}, ++ {0x900e2, 0x16a}, ++ {0x900e3, 0x8}, ++ {0x900e4, 0x8310}, ++ {0x900e5, 0x168}, ++ {0x900e6, 0x8}, ++ {0x900e7, 0xa310}, ++ {0x900e8, 0x168}, ++ {0x900e9, 0xa}, ++ {0x900ea, 0x408}, ++ {0x900eb, 0x169}, ++ {0x900ec, 0x6e}, ++ {0x900ed, 0x0}, ++ {0x900ee, 0x68}, ++ {0x900ef, 0x0}, ++ {0x900f0, 0x408}, ++ {0x900f1, 0x169}, ++ {0x900f2, 0x0}, ++ {0x900f3, 0x8310}, ++ {0x900f4, 0x168}, ++ {0x900f5, 0x0}, ++ {0x900f6, 0xa310}, ++ {0x900f7, 0x168}, ++ {0x900f8, 0x1ff8}, ++ {0x900f9, 0x85a8}, ++ {0x900fa, 0x1e8}, ++ {0x900fb, 0x68}, ++ {0x900fc, 0x798}, ++ {0x900fd, 0x16a}, ++ {0x900fe, 0x78}, ++ {0x900ff, 0x7a0}, ++ {0x90100, 0x16a}, ++ {0x90101, 0x68}, ++ {0x90102, 0x790}, ++ {0x90103, 0x16a}, ++ {0x90104, 0x8}, ++ {0x90105, 0x8b10}, ++ {0x90106, 0x168}, ++ {0x90107, 0x8}, ++ {0x90108, 0xab10}, ++ {0x90109, 0x168}, ++ {0x9010a, 0xa}, ++ {0x9010b, 0x408}, ++ {0x9010c, 0x169}, ++ {0x9010d, 0x58}, ++ {0x9010e, 0x0}, ++ {0x9010f, 0x68}, ++ {0x90110, 0x0}, ++ {0x90111, 0x408}, ++ {0x90112, 0x169}, ++ {0x90113, 0x0}, ++ {0x90114, 0x8b10}, ++ {0x90115, 0x168}, ++ {0x90116, 0x1}, ++ {0x90117, 0xab10}, ++ {0x90118, 0x168}, ++ {0x90119, 0x0}, ++ {0x9011a, 0x1d8}, ++ {0x9011b, 0x169}, ++ {0x9011c, 0x80}, ++ {0x9011d, 0x790}, ++ {0x9011e, 0x16a}, ++ {0x9011f, 0x18}, ++ {0x90120, 0x7aa}, ++ {0x90121, 0x6a}, ++ {0x90122, 0xa}, ++ {0x90123, 0x0}, ++ {0x90124, 0x1e9}, ++ {0x90125, 0x8}, ++ {0x90126, 0x8080}, ++ {0x90127, 0x108}, ++ {0x90128, 0xf}, ++ {0x90129, 0x408}, ++ {0x9012a, 0x169}, ++ {0x9012b, 0xc}, ++ {0x9012c, 0x0}, ++ {0x9012d, 0x68}, ++ {0x9012e, 0x9}, ++ {0x9012f, 0x0}, ++ {0x90130, 0x1a9}, ++ {0x90131, 0x0}, ++ {0x90132, 0x408}, ++ {0x90133, 0x169}, ++ {0x90134, 0x0}, ++ {0x90135, 0x8080}, ++ {0x90136, 0x108}, ++ {0x90137, 0x8}, ++ {0x90138, 0x7aa}, ++ {0x90139, 0x6a}, ++ {0x9013a, 0x0}, ++ {0x9013b, 0x8568}, ++ {0x9013c, 0x108}, ++ {0x9013d, 0xb7}, ++ {0x9013e, 0x790}, ++ {0x9013f, 0x16a}, ++ {0x90140, 0x1f}, ++ {0x90141, 0x0}, ++ {0x90142, 0x68}, ++ {0x90143, 0x8}, ++ {0x90144, 0x8558}, ++ {0x90145, 0x168}, ++ {0x90146, 0xf}, ++ {0x90147, 0x408}, ++ {0x90148, 0x169}, ++ {0x90149, 0xd}, ++ {0x9014a, 0x0}, ++ {0x9014b, 0x68}, ++ {0x9014c, 0x0}, ++ {0x9014d, 0x408}, ++ {0x9014e, 0x169}, ++ {0x9014f, 0x0}, ++ {0x90150, 0x8558}, ++ {0x90151, 0x168}, ++ {0x90152, 0x8}, ++ {0x90153, 0x3c8}, ++ {0x90154, 0x1a9}, ++ {0x90155, 0x3}, ++ {0x90156, 0x370}, ++ {0x90157, 0x129}, ++ {0x90158, 0x20}, ++ {0x90159, 0x2aa}, ++ {0x9015a, 0x9}, ++ {0x9015b, 0x8}, ++ {0x9015c, 0xe8}, ++ {0x9015d, 0x109}, ++ {0x9015e, 0x0}, ++ {0x9015f, 0x8140}, ++ {0x90160, 0x10c}, ++ {0x90161, 0x10}, ++ {0x90162, 0x8138}, ++ {0x90163, 0x104}, ++ {0x90164, 0x8}, ++ {0x90165, 0x448}, ++ {0x90166, 0x109}, ++ {0x90167, 0xf}, ++ {0x90168, 0x7c0}, ++ {0x90169, 0x109}, ++ {0x9016a, 0x0}, ++ {0x9016b, 0xe8}, ++ {0x9016c, 0x109}, ++ {0x9016d, 0x47}, ++ {0x9016e, 0x630}, ++ {0x9016f, 0x109}, ++ {0x90170, 0x8}, ++ {0x90171, 0x618}, ++ {0x90172, 0x109}, ++ {0x90173, 0x8}, ++ {0x90174, 0xe0}, ++ {0x90175, 0x109}, ++ {0x90176, 0x0}, ++ {0x90177, 0x7c8}, ++ {0x90178, 0x109}, ++ {0x90179, 0x8}, ++ {0x9017a, 0x8140}, ++ {0x9017b, 0x10c}, ++ {0x9017c, 0x0}, ++ {0x9017d, 0x478}, ++ {0x9017e, 0x109}, ++ {0x9017f, 0x0}, ++ {0x90180, 0x1}, ++ {0x90181, 0x8}, ++ {0x90182, 0x8}, ++ {0x90183, 0x4}, ++ {0x90184, 0x0}, ++ {0x90006, 0x8}, ++ {0x90007, 0x7c8}, ++ {0x90008, 0x109}, ++ {0x90009, 0x0}, ++ {0x9000a, 0x400}, ++ {0x9000b, 0x106}, ++ {0xd00e7, 0x400}, ++ {0x90017, 0x0}, ++ {0x9001f, 0x2b}, ++ {0x90026, 0x69}, ++ {0x400d0, 0x0}, ++ {0x400d1, 0x101}, ++ {0x400d2, 0x105}, ++ {0x400d3, 0x107}, ++ {0x400d4, 0x10f}, ++ {0x400d5, 0x202}, ++ {0x400d6, 0x20a}, ++ {0x400d7, 0x20b}, ++ {0x2003a, 0x2}, ++ {0x200be, 0x3}, ++ {0x2000b, 0x41a}, ++ {0x2000c, 0xe9}, ++ {0x2000d, 0x91c}, ++ {0x2000e, 0x2c}, ++ {0x12000b, 0x20d}, ++ {0x12000c, 0x74}, ++ {0x12000d, 0x48e}, ++ {0x12000e, 0x2c}, ++ {0x22000b, 0xb0}, ++ {0x22000c, 0x27}, ++ {0x22000d, 0x186}, ++ {0x22000e, 0x10}, ++ {0x9000c, 0x0}, ++ {0x9000d, 0x173}, ++ {0x9000e, 0x60}, ++ {0x9000f, 0x6110}, ++ {0x90010, 0x2152}, ++ {0x90011, 0xdfbd}, ++ {0x90012, 0x2060}, ++ {0x90013, 0x6152}, ++ {0x20010, 0x5a}, ++ {0x20011, 0x3}, ++ {0x120010, 0x5a}, ++ {0x120011, 0x3}, ++ {0x40080, 0xe0}, ++ {0x40081, 0x12}, ++ {0x40082, 0xe0}, ++ {0x40083, 0x12}, ++ {0x40084, 0xe0}, ++ {0x40085, 0x12}, ++ {0x140080, 0xe0}, ++ {0x140081, 0x12}, ++ {0x140082, 0xe0}, ++ {0x140083, 0x12}, ++ {0x140084, 0xe0}, ++ {0x140085, 0x12}, ++ {0x240080, 0xe0}, ++ {0x240081, 0x12}, ++ {0x240082, 0xe0}, ++ {0x240083, 0x12}, ++ {0x240084, 0xe0}, ++ {0x240085, 0x12}, ++ {0x400fd, 0xf}, ++ {0x400f1, 0xe}, ++ {0x10011, 0x1}, ++ {0x10012, 0x1}, ++ {0x10013, 0x180}, ++ {0x10018, 0x1}, ++ {0x10002, 0x6209}, ++ {0x100b2, 0x1}, ++ {0x101b4, 0x1}, ++ {0x102b4, 0x1}, ++ {0x103b4, 0x1}, ++ {0x104b4, 0x1}, ++ {0x105b4, 0x1}, ++ {0x106b4, 0x1}, ++ {0x107b4, 0x1}, ++ {0x108b4, 0x1}, ++ {0x11011, 0x1}, ++ {0x11012, 0x1}, ++ {0x11013, 0x180}, ++ {0x11018, 0x1}, ++ {0x11002, 0x6209}, ++ {0x110b2, 0x1}, ++ {0x111b4, 0x1}, ++ {0x112b4, 0x1}, ++ {0x113b4, 0x1}, ++ {0x114b4, 0x1}, ++ {0x115b4, 0x1}, ++ {0x116b4, 0x1}, ++ {0x117b4, 0x1}, ++ {0x118b4, 0x1}, ++ {0x20089, 0x1}, ++ {0x20088, 0x19}, ++ {0xc0080, 0x0}, ++ {0xd0000, 0x1}, ++}; ++ ++static struct dram_fsp_msg ddr_dram_fsp_msg[] = { ++ { ++ /* P0 3733mts 1D */ ++ .drate = 3733, ++ .fw_type = FW_1D_IMAGE, ++ .fsp_cfg = ddr_fsp0_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg), ++ }, ++ { ++ /* P1 1866mts 1D */ ++ .drate = 1866, ++ .fw_type = FW_1D_IMAGE, ++ .fsp_cfg = ddr_fsp1_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg), ++ }, ++ { ++ /* P2 625mts 1D */ ++ .drate = 625, ++ .fw_type = FW_1D_IMAGE, ++ .fsp_cfg = ddr_fsp2_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg), ++ }, ++ { ++ /* P0 3733mts 2D */ ++ .drate = 3733, ++ .fw_type = FW_2D_IMAGE, ++ .fsp_cfg = ddr_fsp0_2d_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg), ++ }, ++}; ++ ++/* ddr timing config params */ ++struct dram_timing_info dram_timing_2GB = { ++ .ddrc_cfg = ddr_ddrc_cfg, ++ .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg), ++ .ddrphy_cfg = ddr_ddrphy_cfg, ++ .ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg), ++ .fsp_msg = ddr_dram_fsp_msg, ++ .fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg), ++ .ddrphy_trained_csr = ddr_ddrphy_trained_csr, ++ .ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr), ++ .ddrphy_pie = ddr_phy_pie, ++ .ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie), ++ .fsp_table = { 3733, 1866, 625, }, ++ .fsp_cfg = ddr_dram_fsp_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_dram_fsp_cfg), ++}; +diff --git a/board/freescale/imx93_frdm/lpddr4x_ecc_2gb_timing.c b/board/freescale/imx93_frdm/lpddr4x_ecc_2gb_timing.c +new file mode 100644 +index 00000000000..c04e34449d8 +--- /dev/null ++++ b/board/freescale/imx93_frdm/lpddr4x_ecc_2gb_timing.c +@@ -0,0 +1,1997 @@ ++/* ++ * Copyright 2024 NXP ++ * ++ * SPDX-License-Identifier: BSD-3-Clause ++ * ++ * Code generated with DDR Tool v3.4.0_8.3-4e2b550a. ++ * DDR PHY FW2022.01 ++ */ ++ ++#include ++#include ++ ++/* Initialize DDRC registers */ ++static struct dram_cfg_param ddr_ddrc_cfg[] = { ++ {0x4e300110, 0x44100001}, ++ {0x4e300000, 0x8000ef}, ++ {0x4e300008, 0x0}, ++ {0x4e300080, 0x80000512}, ++ {0x4e300084, 0x0}, ++ {0x4e300114, 0x1012}, ++ {0x4e300260, 0x80}, ++ {0x4e300f04, 0x80}, ++ {0x4e300800, 0x43b30d00}, ++ {0x4e300804, 0x1f1f1f1f}, ++ {0x4e301000, 0xc0000000}, ++ {0x4e301240, 0x0}, ++ {0x4e301244, 0x0}, ++ {0x4e301248, 0x0}, ++ {0x4e30124c, 0x0}, ++ {0x4e301250, 0x0}, ++ {0x4e301254, 0x0}, ++ {0x4e301258, 0x0}, ++ {0x4e30125c, 0x0}, ++}; ++ ++/* dram fsp cfg */ ++static struct dram_fsp_cfg ddr_dram_fsp_cfg[] = { ++ { ++ { ++ {0x4e300100, 0x24AB321B}, ++ {0x4e300104, 0xF8EE001B}, ++ {0x4e300108, 0x2F2EE233}, ++ {0x4e30010C, 0x0005E18B}, ++ {0x4e300124, 0x1C760000}, ++ {0x4e300160, 0x00009102}, ++ {0x4e30016C, 0x35F00000}, ++ {0x4e300170, 0x8B0B0608}, ++ {0x4e300250, 0x00000028}, ++ {0x4e300254, 0x015B015B}, ++ {0x4e300258, 0x00000008}, ++ {0x4e30025C, 0x00000400}, ++ {0x4e300300, 0x224F2213}, ++ {0x4e300304, 0x015B2213}, ++ {0x4e300308, 0x0A3C0E3D}, ++ }, ++ { ++ {0x01, 0xE4}, ++ {0x02, 0x36}, ++ {0x03, 0x32}, ++ {0x0b, 0x46}, ++ {0x0c, 0x11}, ++ {0x0e, 0x11}, ++ {0x16, 0x04}, ++ }, ++ 0, ++ }, ++ { ++ { ++ {0x4e300100, 0x12552100}, ++ {0x4e300104, 0xF877000E}, ++ {0x4e300108, 0x1816B4AA}, ++ {0x4e30010C, 0x005101E6}, ++ {0x4e300124, 0x0E3C0000}, ++ {0x4e300160, 0x00009101}, ++ {0x4e30016C, 0x30900000}, ++ {0x4e300170, 0x8A0A0508}, ++ {0x4e300250, 0x00000014}, ++ {0x4e300254, 0x00AA00AA}, ++ {0x4e300258, 0x00000008}, ++ {0x4e30025C, 0x00000400}, ++ }, ++ { ++ {0x01, 0xB4}, ++ {0x02, 0x1B}, ++ {0x03, 0x32}, ++ {0x0b, 0x46}, ++ {0x0c, 0x11}, ++ {0x0e, 0x11}, ++ {0x16, 0x04}, ++ }, ++ 0, ++ }, ++ { ++ { ++ {0x4e300100, 0x00061000}, ++ {0x4e300104, 0xF855000A}, ++ {0x4e300108, 0x6E62FA48}, ++ {0x4e30010C, 0x0031010D}, ++ {0x4e300124, 0x04C50000}, ++ {0x4e300160, 0x00009100}, ++ {0x4e30016C, 0x30000000}, ++ {0x4e300170, 0x89090408}, ++ {0x4e300250, 0x00000007}, ++ {0x4e300254, 0x00340034}, ++ {0x4e300258, 0x00000008}, ++ {0x4e30025C, 0x00000400}, ++ }, ++ { ++ {0x01, 0x94}, ++ {0x02, 0x9}, ++ {0x03, 0x32}, ++ {0x0b, 0x46}, ++ {0x0c, 0x11}, ++ {0x0e, 0x11}, ++ {0x16, 0x04}, ++ }, ++ 1, ++ }, ++ ++}; ++ ++/* PHY Initialize Configuration */ ++static struct dram_cfg_param ddr_ddrphy_cfg[] = { ++ {0x100a0, 0x4}, ++ {0x100a1, 0x5}, ++ {0x100a2, 0x6}, ++ {0x100a3, 0x7}, ++ {0x100a4, 0x0}, ++ {0x100a5, 0x1}, ++ {0x100a6, 0x2}, ++ {0x100a7, 0x3}, ++ {0x110a0, 0x3}, ++ {0x110a1, 0x2}, ++ {0x110a2, 0x0}, ++ {0x110a3, 0x1}, ++ {0x110a4, 0x7}, ++ {0x110a5, 0x6}, ++ {0x110a6, 0x4}, ++ {0x110a7, 0x5}, ++ {0x1005f, 0x5ff}, ++ {0x1015f, 0x5ff}, ++ {0x1105f, 0x5ff}, ++ {0x1115f, 0x5ff}, ++ {0x11005f, 0x5ff}, ++ {0x11015f, 0x5ff}, ++ {0x11105f, 0x5ff}, ++ {0x11115f, 0x5ff}, ++ {0x21005f, 0x5ff}, ++ {0x21015f, 0x5ff}, ++ {0x21105f, 0x5ff}, ++ {0x21115f, 0x5ff}, ++ {0x55, 0x1ff}, ++ {0x1055, 0x1ff}, ++ {0x2055, 0x1ff}, ++ {0x200c5, 0x19}, ++ {0x1200c5, 0xb}, ++ {0x2200c5, 0x7}, ++ {0x2002e, 0x2}, ++ {0x12002e, 0x2}, ++ {0x22002e, 0x2}, ++ {0x90204, 0x0}, ++ {0x190204, 0x0}, ++ {0x290204, 0x0}, ++ {0x20024, 0x1e3}, ++ {0x2003a, 0x2}, ++ {0x2007d, 0x212}, ++ {0x2007c, 0x61}, ++ {0x120024, 0x1e3}, ++ {0x2003a, 0x2}, ++ {0x12007d, 0x212}, ++ {0x12007c, 0x61}, ++ {0x220024, 0x1e3}, ++ {0x2003a, 0x2}, ++ {0x22007d, 0x212}, ++ {0x22007c, 0x61}, ++ {0x20056, 0x3}, ++ {0x120056, 0x3}, ++ {0x220056, 0x3}, ++ {0x1004d, 0x600}, ++ {0x1014d, 0x600}, ++ {0x1104d, 0x600}, ++ {0x1114d, 0x600}, ++ {0x11004d, 0x600}, ++ {0x11014d, 0x600}, ++ {0x11104d, 0x600}, ++ {0x11114d, 0x600}, ++ {0x21004d, 0x600}, ++ {0x21014d, 0x600}, ++ {0x21104d, 0x600}, ++ {0x21114d, 0x600}, ++ {0x10049, 0xe00}, ++ {0x10149, 0xe00}, ++ {0x11049, 0xe00}, ++ {0x11149, 0xe00}, ++ {0x110049, 0xe00}, ++ {0x110149, 0xe00}, ++ {0x111049, 0xe00}, ++ {0x111149, 0xe00}, ++ {0x210049, 0xe00}, ++ {0x210149, 0xe00}, ++ {0x211049, 0xe00}, ++ {0x211149, 0xe00}, ++ {0x43, 0x60}, ++ {0x1043, 0x60}, ++ {0x2043, 0x60}, ++ {0x20018, 0x1}, ++ {0x20075, 0x4}, ++ {0x20050, 0x0}, ++ {0x2009b, 0x2}, ++ {0x20008, 0x3a5}, ++ {0x120008, 0x1d3}, ++ {0x220008, 0x9c}, ++ {0x20088, 0x9}, ++ {0x200b2, 0x10c}, ++ {0x10043, 0x5a1}, ++ {0x10143, 0x5a1}, ++ {0x11043, 0x5a1}, ++ {0x11143, 0x5a1}, ++ {0x1200b2, 0x10c}, ++ {0x110043, 0x5a1}, ++ {0x110143, 0x5a1}, ++ {0x111043, 0x5a1}, ++ {0x111143, 0x5a1}, ++ {0x2200b2, 0x10c}, ++ {0x210043, 0x5a1}, ++ {0x210143, 0x5a1}, ++ {0x211043, 0x5a1}, ++ {0x211143, 0x5a1}, ++ {0x200fa, 0x2}, ++ {0x1200fa, 0x2}, ++ {0x2200fa, 0x2}, ++ {0x20019, 0x1}, ++ {0x120019, 0x1}, ++ {0x220019, 0x1}, ++ {0x200f0, 0x600}, ++ {0x200f1, 0x0}, ++ {0x200f2, 0x4444}, ++ {0x200f3, 0x8888}, ++ {0x200f4, 0x5655}, ++ {0x200f5, 0x0}, ++ {0x200f6, 0x0}, ++ {0x200f7, 0xf000}, ++ {0x1004a, 0x500}, ++ {0x1104a, 0x500}, ++ {0x20025, 0x0}, ++ {0x2002d, 0x0}, ++ {0x12002d, 0x0}, ++ {0x22002d, 0x0}, ++ {0x2002c, 0x0}, ++ {0x20021, 0x0}, ++ {0x200c7, 0x21}, ++ {0x1200c7, 0x21}, ++ {0x200ca, 0x24}, ++ {0x1200ca, 0x24}, ++}; ++ ++/* PHY trained csr */ ++static struct dram_cfg_param ddr_ddrphy_trained_csr[] = { ++ {0x1005f, 0x0}, ++ {0x1015f, 0x0}, ++ {0x1105f, 0x0}, ++ {0x1115f, 0x0}, ++ {0x11005f, 0x0}, ++ {0x11015f, 0x0}, ++ {0x11105f, 0x0}, ++ {0x11115f, 0x0}, ++ {0x21005f, 0x0}, ++ {0x21015f, 0x0}, ++ {0x21105f, 0x0}, ++ {0x21115f, 0x0}, ++ {0x55, 0x0}, ++ {0x1055, 0x0}, ++ {0x2055, 0x0}, ++ {0x200c5, 0x0}, ++ {0x1200c5, 0x0}, ++ {0x2200c5, 0x0}, ++ {0x2002e, 0x0}, ++ {0x12002e, 0x0}, ++ {0x22002e, 0x0}, ++ {0x90204, 0x0}, ++ {0x190204, 0x0}, ++ {0x290204, 0x0}, ++ {0x20024, 0x0}, ++ {0x2003a, 0x0}, ++ {0x2007d, 0x0}, ++ {0x2007c, 0x0}, ++ {0x120024, 0x0}, ++ {0x12007d, 0x0}, ++ {0x12007c, 0x0}, ++ {0x220024, 0x0}, ++ {0x22007d, 0x0}, ++ {0x22007c, 0x0}, ++ {0x20056, 0x0}, ++ {0x120056, 0x0}, ++ {0x220056, 0x0}, ++ {0x1004d, 0x0}, ++ {0x1014d, 0x0}, ++ {0x1104d, 0x0}, ++ {0x1114d, 0x0}, ++ {0x11004d, 0x0}, ++ {0x11014d, 0x0}, ++ {0x11104d, 0x0}, ++ {0x11114d, 0x0}, ++ {0x21004d, 0x0}, ++ {0x21014d, 0x0}, ++ {0x21104d, 0x0}, ++ {0x21114d, 0x0}, ++ {0x10049, 0x0}, ++ {0x10149, 0x0}, ++ {0x11049, 0x0}, ++ {0x11149, 0x0}, ++ {0x110049, 0x0}, ++ {0x110149, 0x0}, ++ {0x111049, 0x0}, ++ {0x111149, 0x0}, ++ {0x210049, 0x0}, ++ {0x210149, 0x0}, ++ {0x211049, 0x0}, ++ {0x211149, 0x0}, ++ {0x43, 0x0}, ++ {0x1043, 0x0}, ++ {0x2043, 0x0}, ++ {0x20018, 0x0}, ++ {0x20075, 0x0}, ++ {0x20050, 0x0}, ++ {0x2009b, 0x0}, ++ {0x20008, 0x0}, ++ {0x120008, 0x0}, ++ {0x220008, 0x0}, ++ {0x20088, 0x0}, ++ {0x200b2, 0x0}, ++ {0x10043, 0x0}, ++ {0x10143, 0x0}, ++ {0x11043, 0x0}, ++ {0x11143, 0x0}, ++ {0x1200b2, 0x0}, ++ {0x110043, 0x0}, ++ {0x110143, 0x0}, ++ {0x111043, 0x0}, ++ {0x111143, 0x0}, ++ {0x2200b2, 0x0}, ++ {0x210043, 0x0}, ++ {0x210143, 0x0}, ++ {0x211043, 0x0}, ++ {0x211143, 0x0}, ++ {0x200fa, 0x0}, ++ {0x1200fa, 0x0}, ++ {0x2200fa, 0x0}, ++ {0x20019, 0x0}, ++ {0x120019, 0x0}, ++ {0x220019, 0x0}, ++ {0x200f0, 0x0}, ++ {0x200f1, 0x0}, ++ {0x200f2, 0x0}, ++ {0x200f3, 0x0}, ++ {0x200f4, 0x0}, ++ {0x200f5, 0x0}, ++ {0x200f6, 0x0}, ++ {0x200f7, 0x0}, ++ {0x1004a, 0x0}, ++ {0x1104a, 0x0}, ++ {0x20025, 0x0}, ++ {0x2002d, 0x0}, ++ {0x12002d, 0x0}, ++ {0x22002d, 0x0}, ++ {0x2002c, 0x0}, ++ {0xd0000, 0x0}, ++ {0x90000, 0x0}, ++ {0x90001, 0x0}, ++ {0x90002, 0x0}, ++ {0x90003, 0x0}, ++ {0x90004, 0x0}, ++ {0x90005, 0x0}, ++ {0x90029, 0x0}, ++ {0x9002a, 0x0}, ++ {0x9002b, 0x0}, ++ {0x9002c, 0x0}, ++ {0x9002d, 0x0}, ++ {0x9002e, 0x0}, ++ {0x9002f, 0x0}, ++ {0x90030, 0x0}, ++ {0x90031, 0x0}, ++ {0x90032, 0x0}, ++ {0x90033, 0x0}, ++ {0x90034, 0x0}, ++ {0x90035, 0x0}, ++ {0x90036, 0x0}, ++ {0x90037, 0x0}, ++ {0x90038, 0x0}, ++ {0x90039, 0x0}, ++ {0x9003a, 0x0}, ++ {0x9003b, 0x0}, ++ {0x9003c, 0x0}, ++ {0x9003d, 0x0}, ++ {0x9003e, 0x0}, ++ {0x9003f, 0x0}, ++ {0x90040, 0x0}, ++ {0x90041, 0x0}, ++ {0x90042, 0x0}, ++ {0x90043, 0x0}, ++ {0x90044, 0x0}, ++ {0x90045, 0x0}, ++ {0x90046, 0x0}, ++ {0x90047, 0x0}, ++ {0x90048, 0x0}, ++ {0x90049, 0x0}, ++ {0x9004a, 0x0}, ++ {0x9004b, 0x0}, ++ {0x9004c, 0x0}, ++ {0x9004d, 0x0}, ++ {0x9004e, 0x0}, ++ {0x9004f, 0x0}, ++ {0x90050, 0x0}, ++ {0x90051, 0x0}, ++ {0x90052, 0x0}, ++ {0x90053, 0x0}, ++ {0x90054, 0x0}, ++ {0x90055, 0x0}, ++ {0x90056, 0x0}, ++ {0x90057, 0x0}, ++ {0x90058, 0x0}, ++ {0x90059, 0x0}, ++ {0x9005a, 0x0}, ++ {0x9005b, 0x0}, ++ {0x9005c, 0x0}, ++ {0x9005d, 0x0}, ++ {0x9005e, 0x0}, ++ {0x9005f, 0x0}, ++ {0x90060, 0x0}, ++ {0x90061, 0x0}, ++ {0x90062, 0x0}, ++ {0x90063, 0x0}, ++ {0x90064, 0x0}, ++ {0x90065, 0x0}, ++ {0x90066, 0x0}, ++ {0x90067, 0x0}, ++ {0x90068, 0x0}, ++ {0x90069, 0x0}, ++ {0x9006a, 0x0}, ++ {0x9006b, 0x0}, ++ {0x9006c, 0x0}, ++ {0x9006d, 0x0}, ++ {0x9006e, 0x0}, ++ {0x9006f, 0x0}, ++ {0x90070, 0x0}, ++ {0x90071, 0x0}, ++ {0x90072, 0x0}, ++ {0x90073, 0x0}, ++ {0x90074, 0x0}, ++ {0x90075, 0x0}, ++ {0x90076, 0x0}, ++ {0x90077, 0x0}, ++ {0x90078, 0x0}, ++ {0x90079, 0x0}, ++ {0x9007a, 0x0}, ++ {0x9007b, 0x0}, ++ {0x9007c, 0x0}, ++ {0x9007d, 0x0}, ++ {0x9007e, 0x0}, ++ {0x9007f, 0x0}, ++ {0x90080, 0x0}, ++ {0x90081, 0x0}, ++ {0x90082, 0x0}, ++ {0x90083, 0x0}, ++ {0x90084, 0x0}, ++ {0x90085, 0x0}, ++ {0x90086, 0x0}, ++ {0x90087, 0x0}, ++ {0x90088, 0x0}, ++ {0x90089, 0x0}, ++ {0x9008a, 0x0}, ++ {0x9008b, 0x0}, ++ {0x9008c, 0x0}, ++ {0x9008d, 0x0}, ++ {0x9008e, 0x0}, ++ {0x9008f, 0x0}, ++ {0x90090, 0x0}, ++ {0x90091, 0x0}, ++ {0x90092, 0x0}, ++ {0x90093, 0x0}, ++ {0x90094, 0x0}, ++ {0x90095, 0x0}, ++ {0x90096, 0x0}, ++ {0x90097, 0x0}, ++ {0x90098, 0x0}, ++ {0x90099, 0x0}, ++ {0x9009a, 0x0}, ++ {0x9009b, 0x0}, ++ {0x9009c, 0x0}, ++ {0x9009d, 0x0}, ++ {0x9009e, 0x0}, ++ {0x9009f, 0x0}, ++ {0x900a0, 0x0}, ++ {0x900a1, 0x0}, ++ {0x900a2, 0x0}, ++ {0x900a3, 0x0}, ++ {0x900a4, 0x0}, ++ {0x900a5, 0x0}, ++ {0x900a6, 0x0}, ++ {0x900a7, 0x0}, ++ {0x900a8, 0x0}, ++ {0x900a9, 0x0}, ++ {0x40000, 0x0}, ++ {0x40020, 0x0}, ++ {0x40040, 0x0}, ++ {0x40060, 0x0}, ++ {0x40001, 0x0}, ++ {0x40021, 0x0}, ++ {0x40041, 0x0}, ++ {0x40061, 0x0}, ++ {0x40002, 0x0}, ++ {0x40022, 0x0}, ++ {0x40042, 0x0}, ++ {0x40062, 0x0}, ++ {0x40003, 0x0}, ++ {0x40023, 0x0}, ++ {0x40043, 0x0}, ++ {0x40063, 0x0}, ++ {0x40004, 0x0}, ++ {0x40024, 0x0}, ++ {0x40044, 0x0}, ++ {0x40064, 0x0}, ++ {0x40005, 0x0}, ++ {0x40025, 0x0}, ++ {0x40045, 0x0}, ++ {0x40065, 0x0}, ++ {0x40006, 0x0}, ++ {0x40026, 0x0}, ++ {0x40046, 0x0}, ++ {0x40066, 0x0}, ++ {0x40007, 0x0}, ++ {0x40027, 0x0}, ++ {0x40047, 0x0}, ++ {0x40067, 0x0}, ++ {0x40008, 0x0}, ++ {0x40028, 0x0}, ++ {0x40048, 0x0}, ++ {0x40068, 0x0}, ++ {0x40009, 0x0}, ++ {0x40029, 0x0}, ++ {0x40049, 0x0}, ++ {0x40069, 0x0}, ++ {0x4000a, 0x0}, ++ {0x4002a, 0x0}, ++ {0x4004a, 0x0}, ++ {0x4006a, 0x0}, ++ {0x4000b, 0x0}, ++ {0x4002b, 0x0}, ++ {0x4004b, 0x0}, ++ {0x4006b, 0x0}, ++ {0x4000c, 0x0}, ++ {0x4002c, 0x0}, ++ {0x4004c, 0x0}, ++ {0x4006c, 0x0}, ++ {0x4000d, 0x0}, ++ {0x4002d, 0x0}, ++ {0x4004d, 0x0}, ++ {0x4006d, 0x0}, ++ {0x4000e, 0x0}, ++ {0x4002e, 0x0}, ++ {0x4004e, 0x0}, ++ {0x4006e, 0x0}, ++ {0x4000f, 0x0}, ++ {0x4002f, 0x0}, ++ {0x4004f, 0x0}, ++ {0x4006f, 0x0}, ++ {0x40010, 0x0}, ++ {0x40030, 0x0}, ++ {0x40050, 0x0}, ++ {0x40070, 0x0}, ++ {0x40011, 0x0}, ++ {0x40031, 0x0}, ++ {0x40051, 0x0}, ++ {0x40071, 0x0}, ++ {0x40012, 0x0}, ++ {0x40032, 0x0}, ++ {0x40052, 0x0}, ++ {0x40072, 0x0}, ++ {0x40013, 0x0}, ++ {0x40033, 0x0}, ++ {0x40053, 0x0}, ++ {0x40073, 0x0}, ++ {0x40014, 0x0}, ++ {0x40034, 0x0}, ++ {0x40054, 0x0}, ++ {0x40074, 0x0}, ++ {0x40015, 0x0}, ++ {0x40035, 0x0}, ++ {0x40055, 0x0}, ++ {0x40075, 0x0}, ++ {0x40016, 0x0}, ++ {0x40036, 0x0}, ++ {0x40056, 0x0}, ++ {0x40076, 0x0}, ++ {0x40017, 0x0}, ++ {0x40037, 0x0}, ++ {0x40057, 0x0}, ++ {0x40077, 0x0}, ++ {0x40018, 0x0}, ++ {0x40038, 0x0}, ++ {0x40058, 0x0}, ++ {0x40078, 0x0}, ++ {0x40019, 0x0}, ++ {0x40039, 0x0}, ++ {0x40059, 0x0}, ++ {0x40079, 0x0}, ++ {0x4001a, 0x0}, ++ {0x4003a, 0x0}, ++ {0x4005a, 0x0}, ++ {0x4007a, 0x0}, ++ {0x900aa, 0x0}, ++ {0x900ab, 0x0}, ++ {0x900ac, 0x0}, ++ {0x900ad, 0x0}, ++ {0x900ae, 0x0}, ++ {0x900af, 0x0}, ++ {0x900b0, 0x0}, ++ {0x900b1, 0x0}, ++ {0x900b2, 0x0}, ++ {0x900b3, 0x0}, ++ {0x900b4, 0x0}, ++ {0x900b5, 0x0}, ++ {0x900b6, 0x0}, ++ {0x900b7, 0x0}, ++ {0x900b8, 0x0}, ++ {0x900b9, 0x0}, ++ {0x900ba, 0x0}, ++ {0x900bb, 0x0}, ++ {0x900bc, 0x0}, ++ {0x900bd, 0x0}, ++ {0x900be, 0x0}, ++ {0x900bf, 0x0}, ++ {0x900c0, 0x0}, ++ {0x900c1, 0x0}, ++ {0x900c2, 0x0}, ++ {0x900c3, 0x0}, ++ {0x900c4, 0x0}, ++ {0x900c5, 0x0}, ++ {0x900c6, 0x0}, ++ {0x900c7, 0x0}, ++ {0x900c8, 0x0}, ++ {0x900c9, 0x0}, ++ {0x900ca, 0x0}, ++ {0x900cb, 0x0}, ++ {0x900cc, 0x0}, ++ {0x900cd, 0x0}, ++ {0x900ce, 0x0}, ++ {0x900cf, 0x0}, ++ {0x900d0, 0x0}, ++ {0x900d1, 0x0}, ++ {0x900d2, 0x0}, ++ {0x900d3, 0x0}, ++ {0x900d4, 0x0}, ++ {0x900d5, 0x0}, ++ {0x900d6, 0x0}, ++ {0x900d7, 0x0}, ++ {0x900d8, 0x0}, ++ {0x900d9, 0x0}, ++ {0x900da, 0x0}, ++ {0x900db, 0x0}, ++ {0x900dc, 0x0}, ++ {0x900dd, 0x0}, ++ {0x900de, 0x0}, ++ {0x900df, 0x0}, ++ {0x900e0, 0x0}, ++ {0x900e1, 0x0}, ++ {0x900e2, 0x0}, ++ {0x900e3, 0x0}, ++ {0x900e4, 0x0}, ++ {0x900e5, 0x0}, ++ {0x900e6, 0x0}, ++ {0x900e7, 0x0}, ++ {0x900e8, 0x0}, ++ {0x900e9, 0x0}, ++ {0x900ea, 0x0}, ++ {0x900eb, 0x0}, ++ {0x900ec, 0x0}, ++ {0x900ed, 0x0}, ++ {0x900ee, 0x0}, ++ {0x900ef, 0x0}, ++ {0x900f0, 0x0}, ++ {0x900f1, 0x0}, ++ {0x900f2, 0x0}, ++ {0x900f3, 0x0}, ++ {0x900f4, 0x0}, ++ {0x900f5, 0x0}, ++ {0x900f6, 0x0}, ++ {0x900f7, 0x0}, ++ {0x900f8, 0x0}, ++ {0x900f9, 0x0}, ++ {0x900fa, 0x0}, ++ {0x900fb, 0x0}, ++ {0x900fc, 0x0}, ++ {0x900fd, 0x0}, ++ {0x900fe, 0x0}, ++ {0x900ff, 0x0}, ++ {0x90100, 0x0}, ++ {0x90101, 0x0}, ++ {0x90102, 0x0}, ++ {0x90103, 0x0}, ++ {0x90104, 0x0}, ++ {0x90105, 0x0}, ++ {0x90106, 0x0}, ++ {0x90107, 0x0}, ++ {0x90108, 0x0}, ++ {0x90109, 0x0}, ++ {0x9010a, 0x0}, ++ {0x9010b, 0x0}, ++ {0x9010c, 0x0}, ++ {0x9010d, 0x0}, ++ {0x9010e, 0x0}, ++ {0x9010f, 0x0}, ++ {0x90110, 0x0}, ++ {0x90111, 0x0}, ++ {0x90112, 0x0}, ++ {0x90113, 0x0}, ++ {0x90114, 0x0}, ++ {0x90115, 0x0}, ++ {0x90116, 0x0}, ++ {0x90117, 0x0}, ++ {0x90118, 0x0}, ++ {0x90119, 0x0}, ++ {0x9011a, 0x0}, ++ {0x9011b, 0x0}, ++ {0x9011c, 0x0}, ++ {0x9011d, 0x0}, ++ {0x9011e, 0x0}, ++ {0x9011f, 0x0}, ++ {0x90120, 0x0}, ++ {0x90121, 0x0}, ++ {0x90122, 0x0}, ++ {0x90123, 0x0}, ++ {0x90124, 0x0}, ++ {0x90125, 0x0}, ++ {0x90126, 0x0}, ++ {0x90127, 0x0}, ++ {0x90128, 0x0}, ++ {0x90129, 0x0}, ++ {0x9012a, 0x0}, ++ {0x9012b, 0x0}, ++ {0x9012c, 0x0}, ++ {0x9012d, 0x0}, ++ {0x9012e, 0x0}, ++ {0x9012f, 0x0}, ++ {0x90130, 0x0}, ++ {0x90131, 0x0}, ++ {0x90132, 0x0}, ++ {0x90133, 0x0}, ++ {0x90134, 0x0}, ++ {0x90135, 0x0}, ++ {0x90136, 0x0}, ++ {0x90137, 0x0}, ++ {0x90138, 0x0}, ++ {0x90139, 0x0}, ++ {0x9013a, 0x0}, ++ {0x9013b, 0x0}, ++ {0x9013c, 0x0}, ++ {0x9013d, 0x0}, ++ {0x9013e, 0x0}, ++ {0x9013f, 0x0}, ++ {0x90140, 0x0}, ++ {0x90141, 0x0}, ++ {0x90142, 0x0}, ++ {0x90143, 0x0}, ++ {0x90144, 0x0}, ++ {0x90145, 0x0}, ++ {0x90146, 0x0}, ++ {0x90147, 0x0}, ++ {0x90148, 0x0}, ++ {0x90149, 0x0}, ++ {0x9014a, 0x0}, ++ {0x9014b, 0x0}, ++ {0x9014c, 0x0}, ++ {0x9014d, 0x0}, ++ {0x9014e, 0x0}, ++ {0x9014f, 0x0}, ++ {0x90150, 0x0}, ++ {0x90151, 0x0}, ++ {0x90152, 0x0}, ++ {0x90153, 0x0}, ++ {0x90154, 0x0}, ++ {0x90155, 0x0}, ++ {0x90156, 0x0}, ++ {0x90157, 0x0}, ++ {0x90158, 0x0}, ++ {0x90159, 0x0}, ++ {0x9015a, 0x0}, ++ {0x9015b, 0x0}, ++ {0x9015c, 0x0}, ++ {0x9015d, 0x0}, ++ {0x9015e, 0x0}, ++ {0x9015f, 0x0}, ++ {0x90160, 0x0}, ++ {0x90161, 0x0}, ++ {0x90162, 0x0}, ++ {0x90163, 0x0}, ++ {0x90164, 0x0}, ++ {0x90165, 0x0}, ++ {0x90166, 0x0}, ++ {0x90167, 0x0}, ++ {0x90168, 0x0}, ++ {0x90169, 0x0}, ++ {0x9016a, 0x0}, ++ {0x9016b, 0x0}, ++ {0x9016c, 0x0}, ++ {0x9016d, 0x0}, ++ {0x9016e, 0x0}, ++ {0x9016f, 0x0}, ++ {0x90170, 0x0}, ++ {0x90171, 0x0}, ++ {0x90172, 0x0}, ++ {0x90173, 0x0}, ++ {0x90174, 0x0}, ++ {0x90175, 0x0}, ++ {0x90176, 0x0}, ++ {0x90177, 0x0}, ++ {0x90178, 0x0}, ++ {0x90179, 0x0}, ++ {0x9017a, 0x0}, ++ {0x9017b, 0x0}, ++ {0x9017c, 0x0}, ++ {0x9017d, 0x0}, ++ {0x9017e, 0x0}, ++ {0x9017f, 0x0}, ++ {0x90180, 0x0}, ++ {0x90181, 0x0}, ++ {0x90182, 0x0}, ++ {0x90183, 0x0}, ++ {0x90184, 0x0}, ++ {0x90006, 0x0}, ++ {0x90007, 0x0}, ++ {0x90008, 0x0}, ++ {0x90009, 0x0}, ++ {0x9000a, 0x0}, ++ {0x9000b, 0x0}, ++ {0xd00e7, 0x0}, ++ {0x90017, 0x0}, ++ {0x9001f, 0x0}, ++ {0x90026, 0x0}, ++ {0x400d0, 0x0}, ++ {0x400d1, 0x0}, ++ {0x400d2, 0x0}, ++ {0x400d3, 0x0}, ++ {0x400d4, 0x0}, ++ {0x400d5, 0x0}, ++ {0x400d6, 0x0}, ++ {0x400d7, 0x0}, ++ {0x200be, 0x0}, ++ {0x2000b, 0x0}, ++ {0x2000c, 0x0}, ++ {0x2000d, 0x0}, ++ {0x2000e, 0x0}, ++ {0x12000b, 0x0}, ++ {0x12000c, 0x0}, ++ {0x12000d, 0x0}, ++ {0x12000e, 0x0}, ++ {0x22000b, 0x0}, ++ {0x22000c, 0x0}, ++ {0x22000d, 0x0}, ++ {0x22000e, 0x0}, ++ {0x9000c, 0x0}, ++ {0x9000d, 0x0}, ++ {0x9000e, 0x0}, ++ {0x9000f, 0x0}, ++ {0x90010, 0x0}, ++ {0x90011, 0x0}, ++ {0x90012, 0x0}, ++ {0x90013, 0x0}, ++ {0x20010, 0x0}, ++ {0x20011, 0x0}, ++ {0x120010, 0x0}, ++ {0x120011, 0x0}, ++ {0x40080, 0x0}, ++ {0x40081, 0x0}, ++ {0x40082, 0x0}, ++ {0x40083, 0x0}, ++ {0x40084, 0x0}, ++ {0x40085, 0x0}, ++ {0x140080, 0x0}, ++ {0x140081, 0x0}, ++ {0x140082, 0x0}, ++ {0x140083, 0x0}, ++ {0x140084, 0x0}, ++ {0x140085, 0x0}, ++ {0x240080, 0x0}, ++ {0x240081, 0x0}, ++ {0x240082, 0x0}, ++ {0x240083, 0x0}, ++ {0x240084, 0x0}, ++ {0x240085, 0x0}, ++ {0x400fd, 0x0}, ++ {0x400f1, 0x0}, ++ {0x10011, 0x0}, ++ {0x10012, 0x0}, ++ {0x10013, 0x0}, ++ {0x10018, 0x0}, ++ {0x10002, 0x0}, ++ {0x100b2, 0x0}, ++ {0x101b4, 0x0}, ++ {0x102b4, 0x0}, ++ {0x103b4, 0x0}, ++ {0x104b4, 0x0}, ++ {0x105b4, 0x0}, ++ {0x106b4, 0x0}, ++ {0x107b4, 0x0}, ++ {0x108b4, 0x0}, ++ {0x11011, 0x0}, ++ {0x11012, 0x0}, ++ {0x11013, 0x0}, ++ {0x11018, 0x0}, ++ {0x11002, 0x0}, ++ {0x110b2, 0x0}, ++ {0x111b4, 0x0}, ++ {0x112b4, 0x0}, ++ {0x113b4, 0x0}, ++ {0x114b4, 0x0}, ++ {0x115b4, 0x0}, ++ {0x116b4, 0x0}, ++ {0x117b4, 0x0}, ++ {0x118b4, 0x0}, ++ {0x20089, 0x0}, ++ {0xc0080, 0x0}, ++ {0x200cb, 0x0}, ++ {0x10068, 0x0}, ++ {0x10069, 0x0}, ++ {0x10168, 0x0}, ++ {0x10169, 0x0}, ++ {0x10268, 0x0}, ++ {0x10269, 0x0}, ++ {0x10368, 0x0}, ++ {0x10369, 0x0}, ++ {0x10468, 0x0}, ++ {0x10469, 0x0}, ++ {0x10568, 0x0}, ++ {0x10569, 0x0}, ++ {0x10668, 0x0}, ++ {0x10669, 0x0}, ++ {0x10768, 0x0}, ++ {0x10769, 0x0}, ++ {0x10868, 0x0}, ++ {0x10869, 0x0}, ++ {0x100aa, 0x0}, ++ {0x10062, 0x0}, ++ {0x10001, 0x0}, ++ {0x100a0, 0x0}, ++ {0x100a1, 0x0}, ++ {0x100a2, 0x0}, ++ {0x100a3, 0x0}, ++ {0x100a4, 0x0}, ++ {0x100a5, 0x0}, ++ {0x100a6, 0x0}, ++ {0x100a7, 0x0}, ++ {0x11068, 0x0}, ++ {0x11069, 0x0}, ++ {0x11168, 0x0}, ++ {0x11169, 0x0}, ++ {0x11268, 0x0}, ++ {0x11269, 0x0}, ++ {0x11368, 0x0}, ++ {0x11369, 0x0}, ++ {0x11468, 0x0}, ++ {0x11469, 0x0}, ++ {0x11568, 0x0}, ++ {0x11569, 0x0}, ++ {0x11668, 0x0}, ++ {0x11669, 0x0}, ++ {0x11768, 0x0}, ++ {0x11769, 0x0}, ++ {0x11868, 0x0}, ++ {0x11869, 0x0}, ++ {0x110aa, 0x0}, ++ {0x11062, 0x0}, ++ {0x11001, 0x0}, ++ {0x110a0, 0x0}, ++ {0x110a1, 0x0}, ++ {0x110a2, 0x0}, ++ {0x110a3, 0x0}, ++ {0x110a4, 0x0}, ++ {0x110a5, 0x0}, ++ {0x110a6, 0x0}, ++ {0x110a7, 0x0}, ++ {0x80, 0x0}, ++ {0x1080, 0x0}, ++ {0x2080, 0x0}, ++ {0x10020, 0x0}, ++ {0x10080, 0x0}, ++ {0x10081, 0x0}, ++ {0x100d0, 0x0}, ++ {0x100d1, 0x0}, ++ {0x1008c, 0x0}, ++ {0x1008d, 0x0}, ++ {0x10180, 0x0}, ++ {0x10181, 0x0}, ++ {0x101d0, 0x0}, ++ {0x101d1, 0x0}, ++ {0x1018c, 0x0}, ++ {0x1018d, 0x0}, ++ {0x100c0, 0x0}, ++ {0x100c1, 0x0}, ++ {0x101c0, 0x0}, ++ {0x101c1, 0x0}, ++ {0x102c0, 0x0}, ++ {0x102c1, 0x0}, ++ {0x103c0, 0x0}, ++ {0x103c1, 0x0}, ++ {0x104c0, 0x0}, ++ {0x104c1, 0x0}, ++ {0x105c0, 0x0}, ++ {0x105c1, 0x0}, ++ {0x106c0, 0x0}, ++ {0x106c1, 0x0}, ++ {0x107c0, 0x0}, ++ {0x107c1, 0x0}, ++ {0x108c0, 0x0}, ++ {0x108c1, 0x0}, ++ {0x100ae, 0x0}, ++ {0x100af, 0x0}, ++ {0x11020, 0x0}, ++ {0x11080, 0x0}, ++ {0x11081, 0x0}, ++ {0x110d0, 0x0}, ++ {0x110d1, 0x0}, ++ {0x1108c, 0x0}, ++ {0x1108d, 0x0}, ++ {0x11180, 0x0}, ++ {0x11181, 0x0}, ++ {0x111d0, 0x0}, ++ {0x111d1, 0x0}, ++ {0x1118c, 0x0}, ++ {0x1118d, 0x0}, ++ {0x110c0, 0x0}, ++ {0x110c1, 0x0}, ++ {0x111c0, 0x0}, ++ {0x111c1, 0x0}, ++ {0x112c0, 0x0}, ++ {0x112c1, 0x0}, ++ {0x113c0, 0x0}, ++ {0x113c1, 0x0}, ++ {0x114c0, 0x0}, ++ {0x114c1, 0x0}, ++ {0x115c0, 0x0}, ++ {0x115c1, 0x0}, ++ {0x116c0, 0x0}, ++ {0x116c1, 0x0}, ++ {0x117c0, 0x0}, ++ {0x117c1, 0x0}, ++ {0x118c0, 0x0}, ++ {0x118c1, 0x0}, ++ {0x110ae, 0x0}, ++ {0x110af, 0x0}, ++ {0x90201, 0x0}, ++ {0x90202, 0x0}, ++ {0x90203, 0x0}, ++ {0x90205, 0x0}, ++ {0x90206, 0x0}, ++ {0x90207, 0x0}, ++ {0x90208, 0x0}, ++ {0x20020, 0x0}, ++ {0x100080, 0x0}, ++ {0x101080, 0x0}, ++ {0x102080, 0x0}, ++ {0x110020, 0x0}, ++ {0x110080, 0x0}, ++ {0x110081, 0x0}, ++ {0x1100d0, 0x0}, ++ {0x1100d1, 0x0}, ++ {0x11008c, 0x0}, ++ {0x11008d, 0x0}, ++ {0x110180, 0x0}, ++ {0x110181, 0x0}, ++ {0x1101d0, 0x0}, ++ {0x1101d1, 0x0}, ++ {0x11018c, 0x0}, ++ {0x11018d, 0x0}, ++ {0x1100c0, 0x0}, ++ {0x1100c1, 0x0}, ++ {0x1101c0, 0x0}, ++ {0x1101c1, 0x0}, ++ {0x1102c0, 0x0}, ++ {0x1102c1, 0x0}, ++ {0x1103c0, 0x0}, ++ {0x1103c1, 0x0}, ++ {0x1104c0, 0x0}, ++ {0x1104c1, 0x0}, ++ {0x1105c0, 0x0}, ++ {0x1105c1, 0x0}, ++ {0x1106c0, 0x0}, ++ {0x1106c1, 0x0}, ++ {0x1107c0, 0x0}, ++ {0x1107c1, 0x0}, ++ {0x1108c0, 0x0}, ++ {0x1108c1, 0x0}, ++ {0x1100ae, 0x0}, ++ {0x1100af, 0x0}, ++ {0x111020, 0x0}, ++ {0x111080, 0x0}, ++ {0x111081, 0x0}, ++ {0x1110d0, 0x0}, ++ {0x1110d1, 0x0}, ++ {0x11108c, 0x0}, ++ {0x11108d, 0x0}, ++ {0x111180, 0x0}, ++ {0x111181, 0x0}, ++ {0x1111d0, 0x0}, ++ {0x1111d1, 0x0}, ++ {0x11118c, 0x0}, ++ {0x11118d, 0x0}, ++ {0x1110c0, 0x0}, ++ {0x1110c1, 0x0}, ++ {0x1111c0, 0x0}, ++ {0x1111c1, 0x0}, ++ {0x1112c0, 0x0}, ++ {0x1112c1, 0x0}, ++ {0x1113c0, 0x0}, ++ {0x1113c1, 0x0}, ++ {0x1114c0, 0x0}, ++ {0x1114c1, 0x0}, ++ {0x1115c0, 0x0}, ++ {0x1115c1, 0x0}, ++ {0x1116c0, 0x0}, ++ {0x1116c1, 0x0}, ++ {0x1117c0, 0x0}, ++ {0x1117c1, 0x0}, ++ {0x1118c0, 0x0}, ++ {0x1118c1, 0x0}, ++ {0x1110ae, 0x0}, ++ {0x1110af, 0x0}, ++ {0x190201, 0x0}, ++ {0x190202, 0x0}, ++ {0x190203, 0x0}, ++ {0x190205, 0x0}, ++ {0x190206, 0x0}, ++ {0x190207, 0x0}, ++ {0x190208, 0x0}, ++ {0x120020, 0x0}, ++ {0x200080, 0x0}, ++ {0x201080, 0x0}, ++ {0x202080, 0x0}, ++ {0x210020, 0x0}, ++ {0x210080, 0x0}, ++ {0x210081, 0x0}, ++ {0x2100d0, 0x0}, ++ {0x2100d1, 0x0}, ++ {0x21008c, 0x0}, ++ {0x21008d, 0x0}, ++ {0x210180, 0x0}, ++ {0x210181, 0x0}, ++ {0x2101d0, 0x0}, ++ {0x2101d1, 0x0}, ++ {0x21018c, 0x0}, ++ {0x21018d, 0x0}, ++ {0x2100c0, 0x0}, ++ {0x2100c1, 0x0}, ++ {0x2101c0, 0x0}, ++ {0x2101c1, 0x0}, ++ {0x2102c0, 0x0}, ++ {0x2102c1, 0x0}, ++ {0x2103c0, 0x0}, ++ {0x2103c1, 0x0}, ++ {0x2104c0, 0x0}, ++ {0x2104c1, 0x0}, ++ {0x2105c0, 0x0}, ++ {0x2105c1, 0x0}, ++ {0x2106c0, 0x0}, ++ {0x2106c1, 0x0}, ++ {0x2107c0, 0x0}, ++ {0x2107c1, 0x0}, ++ {0x2108c0, 0x0}, ++ {0x2108c1, 0x0}, ++ {0x2100ae, 0x0}, ++ {0x2100af, 0x0}, ++ {0x211020, 0x0}, ++ {0x211080, 0x0}, ++ {0x211081, 0x0}, ++ {0x2110d0, 0x0}, ++ {0x2110d1, 0x0}, ++ {0x21108c, 0x0}, ++ {0x21108d, 0x0}, ++ {0x211180, 0x0}, ++ {0x211181, 0x0}, ++ {0x2111d0, 0x0}, ++ {0x2111d1, 0x0}, ++ {0x21118c, 0x0}, ++ {0x21118d, 0x0}, ++ {0x2110c0, 0x0}, ++ {0x2110c1, 0x0}, ++ {0x2111c0, 0x0}, ++ {0x2111c1, 0x0}, ++ {0x2112c0, 0x0}, ++ {0x2112c1, 0x0}, ++ {0x2113c0, 0x0}, ++ {0x2113c1, 0x0}, ++ {0x2114c0, 0x0}, ++ {0x2114c1, 0x0}, ++ {0x2115c0, 0x0}, ++ {0x2115c1, 0x0}, ++ {0x2116c0, 0x0}, ++ {0x2116c1, 0x0}, ++ {0x2117c0, 0x0}, ++ {0x2117c1, 0x0}, ++ {0x2118c0, 0x0}, ++ {0x2118c1, 0x0}, ++ {0x2110ae, 0x0}, ++ {0x2110af, 0x0}, ++ {0x290201, 0x0}, ++ {0x290202, 0x0}, ++ {0x290203, 0x0}, ++ {0x290205, 0x0}, ++ {0x290206, 0x0}, ++ {0x290207, 0x0}, ++ {0x290208, 0x0}, ++ {0x220020, 0x0}, ++ {0x20077, 0x0}, ++ {0x20072, 0x0}, ++ {0x20073, 0x0}, ++ {0x400c0, 0x0}, ++ {0x10040, 0x0}, ++ {0x10140, 0x0}, ++ {0x10240, 0x0}, ++ {0x10340, 0x0}, ++ {0x10440, 0x0}, ++ {0x10540, 0x0}, ++ {0x10640, 0x0}, ++ {0x10740, 0x0}, ++ {0x10840, 0x0}, ++ {0x11040, 0x0}, ++ {0x11140, 0x0}, ++ {0x11240, 0x0}, ++ {0x11340, 0x0}, ++ {0x11440, 0x0}, ++ {0x11540, 0x0}, ++ {0x11640, 0x0}, ++ {0x11740, 0x0}, ++ {0x11840, 0x0}, ++}; ++ ++/* P0 message block parameter for training firmware */ ++static struct dram_cfg_param ddr_fsp0_cfg[] = { ++ {0xd0000, 0x0}, ++ {0x54003, 0xe94}, ++ {0x54004, 0x4}, ++ {0x54006, 0x15}, ++ {0x54008, 0x131f}, ++ {0x54009, 0xc8}, ++ {0x5400b, 0x4}, ++ {0x5400d, 0x100}, ++ {0x5400f, 0x100}, ++ {0x54012, 0x110}, ++ {0x54019, 0x36e4}, ++ {0x5401a, 0x32}, ++ {0x5401b, 0x1146}, ++ {0x5401c, 0x1108}, ++ {0x5401e, 0x4}, ++ {0x5401f, 0x36e4}, ++ {0x54020, 0x32}, ++ {0x54021, 0x1146}, ++ {0x54022, 0x1108}, ++ {0x54024, 0x4}, ++ {0x54032, 0xe400}, ++ {0x54033, 0x3236}, ++ {0x54034, 0x4600}, ++ {0x54035, 0x811}, ++ {0x54036, 0x11}, ++ {0x54037, 0x400}, ++ {0x54038, 0xe400}, ++ {0x54039, 0x3236}, ++ {0x5403a, 0x4600}, ++ {0x5403b, 0x811}, ++ {0x5403c, 0x11}, ++ {0x5403d, 0x400}, ++ {0xd0000, 0x1} ++}; ++ ++/* P1 message block parameter for training firmware */ ++static struct dram_cfg_param ddr_fsp1_cfg[] = { ++ {0xd0000, 0x0}, ++ {0x54002, 0x1}, ++ {0x54003, 0x74a}, ++ {0x54004, 0x4}, ++ {0x54006, 0x15}, ++ {0x54008, 0x121f}, ++ {0x54009, 0xc8}, ++ {0x5400b, 0x4}, ++ {0x5400d, 0x100}, ++ {0x5400f, 0x100}, ++ {0x54012, 0x110}, ++ {0x54019, 0x1bb4}, ++ {0x5401a, 0x32}, ++ {0x5401b, 0x1146}, ++ {0x5401c, 0x1108}, ++ {0x5401e, 0x4}, ++ {0x5401f, 0x1bb4}, ++ {0x54020, 0x32}, ++ {0x54021, 0x1146}, ++ {0x54022, 0x1108}, ++ {0x54024, 0x4}, ++ {0x54032, 0xb400}, ++ {0x54033, 0x321b}, ++ {0x54034, 0x4600}, ++ {0x54035, 0x811}, ++ {0x54036, 0x11}, ++ {0x54037, 0x400}, ++ {0x54038, 0xb400}, ++ {0x54039, 0x321b}, ++ {0x5403a, 0x4600}, ++ {0x5403b, 0x811}, ++ {0x5403c, 0x11}, ++ {0x5403d, 0x400}, ++ {0xd0000, 0x1} ++}; ++ ++/* P2 message block parameter for training firmware */ ++static struct dram_cfg_param ddr_fsp2_cfg[] = { ++ {0xd0000, 0x0}, ++ {0x54002, 0x102}, ++ {0x54003, 0x270}, ++ {0x54004, 0x4}, ++ {0x54006, 0x15}, ++ {0x54008, 0x121f}, ++ {0x54009, 0xc8}, ++ {0x5400b, 0x4}, ++ {0x5400d, 0x100}, ++ {0x5400f, 0x100}, ++ {0x54012, 0x110}, ++ {0x54019, 0x994}, ++ {0x5401a, 0x32}, ++ {0x5401b, 0x1146}, ++ {0x5401c, 0x1100}, ++ {0x5401e, 0x4}, ++ {0x5401f, 0x994}, ++ {0x54020, 0x32}, ++ {0x54021, 0x1146}, ++ {0x54022, 0x1100}, ++ {0x54024, 0x4}, ++ {0x54032, 0x9400}, ++ {0x54033, 0x3209}, ++ {0x54034, 0x4600}, ++ {0x54035, 0x11}, ++ {0x54036, 0x11}, ++ {0x54037, 0x400}, ++ {0x54038, 0x9400}, ++ {0x54039, 0x3209}, ++ {0x5403a, 0x4600}, ++ {0x5403b, 0x11}, ++ {0x5403c, 0x11}, ++ {0x5403d, 0x400}, ++ {0xd0000, 0x1} ++}; ++ ++/* P0 2D message block parameter for training firmware */ ++static struct dram_cfg_param ddr_fsp0_2d_cfg[] = { ++ {0xd0000, 0x0}, ++ {0x54003, 0xe94}, ++ {0x54004, 0x4}, ++ {0x54006, 0x15}, ++ {0x54008, 0x61}, ++ {0x54009, 0xc8}, ++ {0x5400b, 0x4}, ++ {0x5400d, 0x100}, ++ {0x5400f, 0x100}, ++ {0x54010, 0x2080}, ++ {0x54012, 0x110}, ++ {0x54019, 0x36e4}, ++ {0x5401a, 0x32}, ++ {0x5401b, 0x1146}, ++ {0x5401c, 0x1108}, ++ {0x5401e, 0x4}, ++ {0x5401f, 0x36e4}, ++ {0x54020, 0x32}, ++ {0x54021, 0x1146}, ++ {0x54022, 0x1108}, ++ {0x54024, 0x4}, ++ {0x54032, 0xe400}, ++ {0x54033, 0x3236}, ++ {0x54034, 0x4600}, ++ {0x54035, 0x811}, ++ {0x54036, 0x11}, ++ {0x54037, 0x400}, ++ {0x54038, 0xe400}, ++ {0x54039, 0x3236}, ++ {0x5403a, 0x4600}, ++ {0x5403b, 0x811}, ++ {0x5403c, 0x11}, ++ {0x5403d, 0x400}, ++ {0xd0000, 0x1} ++}; ++ ++/* DRAM PHY init engine image */ ++static struct dram_cfg_param ddr_phy_pie[] = { ++ {0xd0000, 0x0}, ++ {0x90000, 0x10}, ++ {0x90001, 0x400}, ++ {0x90002, 0x10e}, ++ {0x90003, 0x0}, ++ {0x90004, 0x0}, ++ {0x90005, 0x8}, ++ {0x90029, 0xb}, ++ {0x9002a, 0x480}, ++ {0x9002b, 0x109}, ++ {0x9002c, 0x8}, ++ {0x9002d, 0x448}, ++ {0x9002e, 0x139}, ++ {0x9002f, 0x8}, ++ {0x90030, 0x478}, ++ {0x90031, 0x109}, ++ {0x90032, 0x0}, ++ {0x90033, 0xe8}, ++ {0x90034, 0x109}, ++ {0x90035, 0x2}, ++ {0x90036, 0x10}, ++ {0x90037, 0x139}, ++ {0x90038, 0xb}, ++ {0x90039, 0x7c0}, ++ {0x9003a, 0x139}, ++ {0x9003b, 0x44}, ++ {0x9003c, 0x633}, ++ {0x9003d, 0x159}, ++ {0x9003e, 0x14f}, ++ {0x9003f, 0x630}, ++ {0x90040, 0x159}, ++ {0x90041, 0x47}, ++ {0x90042, 0x633}, ++ {0x90043, 0x149}, ++ {0x90044, 0x4f}, ++ {0x90045, 0x633}, ++ {0x90046, 0x179}, ++ {0x90047, 0x8}, ++ {0x90048, 0xe0}, ++ {0x90049, 0x109}, ++ {0x9004a, 0x0}, ++ {0x9004b, 0x7c8}, ++ {0x9004c, 0x109}, ++ {0x9004d, 0x0}, ++ {0x9004e, 0x1}, ++ {0x9004f, 0x8}, ++ {0x90050, 0x30}, ++ {0x90051, 0x65a}, ++ {0x90052, 0x9}, ++ {0x90053, 0x0}, ++ {0x90054, 0x45a}, ++ {0x90055, 0x9}, ++ {0x90056, 0x0}, ++ {0x90057, 0x448}, ++ {0x90058, 0x109}, ++ {0x90059, 0x40}, ++ {0x9005a, 0x633}, ++ {0x9005b, 0x179}, ++ {0x9005c, 0x1}, ++ {0x9005d, 0x618}, ++ {0x9005e, 0x109}, ++ {0x9005f, 0x40c0}, ++ {0x90060, 0x633}, ++ {0x90061, 0x149}, ++ {0x90062, 0x8}, ++ {0x90063, 0x4}, ++ {0x90064, 0x48}, ++ {0x90065, 0x4040}, ++ {0x90066, 0x633}, ++ {0x90067, 0x149}, ++ {0x90068, 0x0}, ++ {0x90069, 0x4}, ++ {0x9006a, 0x48}, ++ {0x9006b, 0x40}, ++ {0x9006c, 0x633}, ++ {0x9006d, 0x149}, ++ {0x9006e, 0x0}, ++ {0x9006f, 0x658}, ++ {0x90070, 0x109}, ++ {0x90071, 0x10}, ++ {0x90072, 0x4}, ++ {0x90073, 0x18}, ++ {0x90074, 0x0}, ++ {0x90075, 0x4}, ++ {0x90076, 0x78}, ++ {0x90077, 0x549}, ++ {0x90078, 0x633}, ++ {0x90079, 0x159}, ++ {0x9007a, 0xd49}, ++ {0x9007b, 0x633}, ++ {0x9007c, 0x159}, ++ {0x9007d, 0x94a}, ++ {0x9007e, 0x633}, ++ {0x9007f, 0x159}, ++ {0x90080, 0x441}, ++ {0x90081, 0x633}, ++ {0x90082, 0x149}, ++ {0x90083, 0x42}, ++ {0x90084, 0x633}, ++ {0x90085, 0x149}, ++ {0x90086, 0x1}, ++ {0x90087, 0x633}, ++ {0x90088, 0x149}, ++ {0x90089, 0x0}, ++ {0x9008a, 0xe0}, ++ {0x9008b, 0x109}, ++ {0x9008c, 0xa}, ++ {0x9008d, 0x10}, ++ {0x9008e, 0x109}, ++ {0x9008f, 0x9}, ++ {0x90090, 0x3c0}, ++ {0x90091, 0x149}, ++ {0x90092, 0x9}, ++ {0x90093, 0x3c0}, ++ {0x90094, 0x159}, ++ {0x90095, 0x18}, ++ {0x90096, 0x10}, ++ {0x90097, 0x109}, ++ {0x90098, 0x0}, ++ {0x90099, 0x3c0}, ++ {0x9009a, 0x109}, ++ {0x9009b, 0x18}, ++ {0x9009c, 0x4}, ++ {0x9009d, 0x48}, ++ {0x9009e, 0x18}, ++ {0x9009f, 0x4}, ++ {0x900a0, 0x58}, ++ {0x900a1, 0xb}, ++ {0x900a2, 0x10}, ++ {0x900a3, 0x109}, ++ {0x900a4, 0x1}, ++ {0x900a5, 0x10}, ++ {0x900a6, 0x109}, ++ {0x900a7, 0x5}, ++ {0x900a8, 0x7c0}, ++ {0x900a9, 0x109}, ++ {0x40000, 0x811}, ++ {0x40020, 0x880}, ++ {0x40040, 0x0}, ++ {0x40060, 0x0}, ++ {0x40001, 0x4008}, ++ {0x40021, 0x83}, ++ {0x40041, 0x4f}, ++ {0x40061, 0x0}, ++ {0x40002, 0x4040}, ++ {0x40022, 0x83}, ++ {0x40042, 0x51}, ++ {0x40062, 0x0}, ++ {0x40003, 0x811}, ++ {0x40023, 0x880}, ++ {0x40043, 0x0}, ++ {0x40063, 0x0}, ++ {0x40004, 0x720}, ++ {0x40024, 0xf}, ++ {0x40044, 0x1740}, ++ {0x40064, 0x0}, ++ {0x40005, 0x16}, ++ {0x40025, 0x83}, ++ {0x40045, 0x4b}, ++ {0x40065, 0x0}, ++ {0x40006, 0x716}, ++ {0x40026, 0xf}, ++ {0x40046, 0x2001}, ++ {0x40066, 0x0}, ++ {0x40007, 0x716}, ++ {0x40027, 0xf}, ++ {0x40047, 0x2800}, ++ {0x40067, 0x0}, ++ {0x40008, 0x716}, ++ {0x40028, 0xf}, ++ {0x40048, 0xf00}, ++ {0x40068, 0x0}, ++ {0x40009, 0x720}, ++ {0x40029, 0xf}, ++ {0x40049, 0x1400}, ++ {0x40069, 0x0}, ++ {0x4000a, 0xe08}, ++ {0x4002a, 0xc15}, ++ {0x4004a, 0x0}, ++ {0x4006a, 0x0}, ++ {0x4000b, 0x625}, ++ {0x4002b, 0x15}, ++ {0x4004b, 0x0}, ++ {0x4006b, 0x0}, ++ {0x4000c, 0x4028}, ++ {0x4002c, 0x80}, ++ {0x4004c, 0x0}, ++ {0x4006c, 0x0}, ++ {0x4000d, 0xe08}, ++ {0x4002d, 0xc1a}, ++ {0x4004d, 0x0}, ++ {0x4006d, 0x0}, ++ {0x4000e, 0x625}, ++ {0x4002e, 0x1a}, ++ {0x4004e, 0x0}, ++ {0x4006e, 0x0}, ++ {0x4000f, 0x4040}, ++ {0x4002f, 0x80}, ++ {0x4004f, 0x0}, ++ {0x4006f, 0x0}, ++ {0x40010, 0x2604}, ++ {0x40030, 0x15}, ++ {0x40050, 0x0}, ++ {0x40070, 0x0}, ++ {0x40011, 0x708}, ++ {0x40031, 0x5}, ++ {0x40051, 0x0}, ++ {0x40071, 0x2002}, ++ {0x40012, 0x8}, ++ {0x40032, 0x80}, ++ {0x40052, 0x0}, ++ {0x40072, 0x0}, ++ {0x40013, 0x2604}, ++ {0x40033, 0x1a}, ++ {0x40053, 0x0}, ++ {0x40073, 0x0}, ++ {0x40014, 0x708}, ++ {0x40034, 0xa}, ++ {0x40054, 0x0}, ++ {0x40074, 0x2002}, ++ {0x40015, 0x4040}, ++ {0x40035, 0x80}, ++ {0x40055, 0x0}, ++ {0x40075, 0x0}, ++ {0x40016, 0x60a}, ++ {0x40036, 0x15}, ++ {0x40056, 0x1200}, ++ {0x40076, 0x0}, ++ {0x40017, 0x61a}, ++ {0x40037, 0x15}, ++ {0x40057, 0x1300}, ++ {0x40077, 0x0}, ++ {0x40018, 0x60a}, ++ {0x40038, 0x1a}, ++ {0x40058, 0x1200}, ++ {0x40078, 0x0}, ++ {0x40019, 0x642}, ++ {0x40039, 0x1a}, ++ {0x40059, 0x1300}, ++ {0x40079, 0x0}, ++ {0x4001a, 0x4808}, ++ {0x4003a, 0x880}, ++ {0x4005a, 0x0}, ++ {0x4007a, 0x0}, ++ {0x900aa, 0x0}, ++ {0x900ab, 0x790}, ++ {0x900ac, 0x11a}, ++ {0x900ad, 0x8}, ++ {0x900ae, 0x7aa}, ++ {0x900af, 0x2a}, ++ {0x900b0, 0x10}, ++ {0x900b1, 0x7b2}, ++ {0x900b2, 0x2a}, ++ {0x900b3, 0x0}, ++ {0x900b4, 0x7c8}, ++ {0x900b5, 0x109}, ++ {0x900b6, 0x10}, ++ {0x900b7, 0x10}, ++ {0x900b8, 0x109}, ++ {0x900b9, 0x10}, ++ {0x900ba, 0x2a8}, ++ {0x900bb, 0x129}, ++ {0x900bc, 0x8}, ++ {0x900bd, 0x370}, ++ {0x900be, 0x129}, ++ {0x900bf, 0xa}, ++ {0x900c0, 0x3c8}, ++ {0x900c1, 0x1a9}, ++ {0x900c2, 0xc}, ++ {0x900c3, 0x408}, ++ {0x900c4, 0x199}, ++ {0x900c5, 0x14}, ++ {0x900c6, 0x790}, ++ {0x900c7, 0x11a}, ++ {0x900c8, 0x8}, ++ {0x900c9, 0x4}, ++ {0x900ca, 0x18}, ++ {0x900cb, 0xe}, ++ {0x900cc, 0x408}, ++ {0x900cd, 0x199}, ++ {0x900ce, 0x8}, ++ {0x900cf, 0x8568}, ++ {0x900d0, 0x108}, ++ {0x900d1, 0x18}, ++ {0x900d2, 0x790}, ++ {0x900d3, 0x16a}, ++ {0x900d4, 0x8}, ++ {0x900d5, 0x1d8}, ++ {0x900d6, 0x169}, ++ {0x900d7, 0x10}, ++ {0x900d8, 0x8558}, ++ {0x900d9, 0x168}, ++ {0x900da, 0x1ff8}, ++ {0x900db, 0x85a8}, ++ {0x900dc, 0x1e8}, ++ {0x900dd, 0x50}, ++ {0x900de, 0x798}, ++ {0x900df, 0x16a}, ++ {0x900e0, 0x60}, ++ {0x900e1, 0x7a0}, ++ {0x900e2, 0x16a}, ++ {0x900e3, 0x8}, ++ {0x900e4, 0x8310}, ++ {0x900e5, 0x168}, ++ {0x900e6, 0x8}, ++ {0x900e7, 0xa310}, ++ {0x900e8, 0x168}, ++ {0x900e9, 0xa}, ++ {0x900ea, 0x408}, ++ {0x900eb, 0x169}, ++ {0x900ec, 0x6e}, ++ {0x900ed, 0x0}, ++ {0x900ee, 0x68}, ++ {0x900ef, 0x0}, ++ {0x900f0, 0x408}, ++ {0x900f1, 0x169}, ++ {0x900f2, 0x0}, ++ {0x900f3, 0x8310}, ++ {0x900f4, 0x168}, ++ {0x900f5, 0x0}, ++ {0x900f6, 0xa310}, ++ {0x900f7, 0x168}, ++ {0x900f8, 0x1ff8}, ++ {0x900f9, 0x85a8}, ++ {0x900fa, 0x1e8}, ++ {0x900fb, 0x68}, ++ {0x900fc, 0x798}, ++ {0x900fd, 0x16a}, ++ {0x900fe, 0x78}, ++ {0x900ff, 0x7a0}, ++ {0x90100, 0x16a}, ++ {0x90101, 0x68}, ++ {0x90102, 0x790}, ++ {0x90103, 0x16a}, ++ {0x90104, 0x8}, ++ {0x90105, 0x8b10}, ++ {0x90106, 0x168}, ++ {0x90107, 0x8}, ++ {0x90108, 0xab10}, ++ {0x90109, 0x168}, ++ {0x9010a, 0xa}, ++ {0x9010b, 0x408}, ++ {0x9010c, 0x169}, ++ {0x9010d, 0x58}, ++ {0x9010e, 0x0}, ++ {0x9010f, 0x68}, ++ {0x90110, 0x0}, ++ {0x90111, 0x408}, ++ {0x90112, 0x169}, ++ {0x90113, 0x0}, ++ {0x90114, 0x8b10}, ++ {0x90115, 0x168}, ++ {0x90116, 0x1}, ++ {0x90117, 0xab10}, ++ {0x90118, 0x168}, ++ {0x90119, 0x0}, ++ {0x9011a, 0x1d8}, ++ {0x9011b, 0x169}, ++ {0x9011c, 0x80}, ++ {0x9011d, 0x790}, ++ {0x9011e, 0x16a}, ++ {0x9011f, 0x18}, ++ {0x90120, 0x7aa}, ++ {0x90121, 0x6a}, ++ {0x90122, 0xa}, ++ {0x90123, 0x0}, ++ {0x90124, 0x1e9}, ++ {0x90125, 0x8}, ++ {0x90126, 0x8080}, ++ {0x90127, 0x108}, ++ {0x90128, 0xf}, ++ {0x90129, 0x408}, ++ {0x9012a, 0x169}, ++ {0x9012b, 0xc}, ++ {0x9012c, 0x0}, ++ {0x9012d, 0x68}, ++ {0x9012e, 0x9}, ++ {0x9012f, 0x0}, ++ {0x90130, 0x1a9}, ++ {0x90131, 0x0}, ++ {0x90132, 0x408}, ++ {0x90133, 0x169}, ++ {0x90134, 0x0}, ++ {0x90135, 0x8080}, ++ {0x90136, 0x108}, ++ {0x90137, 0x8}, ++ {0x90138, 0x7aa}, ++ {0x90139, 0x6a}, ++ {0x9013a, 0x0}, ++ {0x9013b, 0x8568}, ++ {0x9013c, 0x108}, ++ {0x9013d, 0xb7}, ++ {0x9013e, 0x790}, ++ {0x9013f, 0x16a}, ++ {0x90140, 0x1f}, ++ {0x90141, 0x0}, ++ {0x90142, 0x68}, ++ {0x90143, 0x8}, ++ {0x90144, 0x8558}, ++ {0x90145, 0x168}, ++ {0x90146, 0xf}, ++ {0x90147, 0x408}, ++ {0x90148, 0x169}, ++ {0x90149, 0xd}, ++ {0x9014a, 0x0}, ++ {0x9014b, 0x68}, ++ {0x9014c, 0x0}, ++ {0x9014d, 0x408}, ++ {0x9014e, 0x169}, ++ {0x9014f, 0x0}, ++ {0x90150, 0x8558}, ++ {0x90151, 0x168}, ++ {0x90152, 0x8}, ++ {0x90153, 0x3c8}, ++ {0x90154, 0x1a9}, ++ {0x90155, 0x3}, ++ {0x90156, 0x370}, ++ {0x90157, 0x129}, ++ {0x90158, 0x20}, ++ {0x90159, 0x2aa}, ++ {0x9015a, 0x9}, ++ {0x9015b, 0x8}, ++ {0x9015c, 0xe8}, ++ {0x9015d, 0x109}, ++ {0x9015e, 0x0}, ++ {0x9015f, 0x8140}, ++ {0x90160, 0x10c}, ++ {0x90161, 0x10}, ++ {0x90162, 0x8138}, ++ {0x90163, 0x104}, ++ {0x90164, 0x8}, ++ {0x90165, 0x448}, ++ {0x90166, 0x109}, ++ {0x90167, 0xf}, ++ {0x90168, 0x7c0}, ++ {0x90169, 0x109}, ++ {0x9016a, 0x0}, ++ {0x9016b, 0xe8}, ++ {0x9016c, 0x109}, ++ {0x9016d, 0x47}, ++ {0x9016e, 0x630}, ++ {0x9016f, 0x109}, ++ {0x90170, 0x8}, ++ {0x90171, 0x618}, ++ {0x90172, 0x109}, ++ {0x90173, 0x8}, ++ {0x90174, 0xe0}, ++ {0x90175, 0x109}, ++ {0x90176, 0x0}, ++ {0x90177, 0x7c8}, ++ {0x90178, 0x109}, ++ {0x90179, 0x8}, ++ {0x9017a, 0x8140}, ++ {0x9017b, 0x10c}, ++ {0x9017c, 0x0}, ++ {0x9017d, 0x478}, ++ {0x9017e, 0x109}, ++ {0x9017f, 0x0}, ++ {0x90180, 0x1}, ++ {0x90181, 0x8}, ++ {0x90182, 0x8}, ++ {0x90183, 0x4}, ++ {0x90184, 0x0}, ++ {0x90006, 0x8}, ++ {0x90007, 0x7c8}, ++ {0x90008, 0x109}, ++ {0x90009, 0x0}, ++ {0x9000a, 0x400}, ++ {0x9000b, 0x106}, ++ {0xd00e7, 0x400}, ++ {0x90017, 0x0}, ++ {0x9001f, 0x2b}, ++ {0x90026, 0x69}, ++ {0x400d0, 0x0}, ++ {0x400d1, 0x101}, ++ {0x400d2, 0x105}, ++ {0x400d3, 0x107}, ++ {0x400d4, 0x10f}, ++ {0x400d5, 0x202}, ++ {0x400d6, 0x20a}, ++ {0x400d7, 0x20b}, ++ {0x2003a, 0x2}, ++ {0x200be, 0x3}, ++ {0x2000b, 0x41a}, ++ {0x2000c, 0xe9}, ++ {0x2000d, 0x91c}, ++ {0x2000e, 0x2c}, ++ {0x12000b, 0x20d}, ++ {0x12000c, 0x74}, ++ {0x12000d, 0x48e}, ++ {0x12000e, 0x2c}, ++ {0x22000b, 0xb0}, ++ {0x22000c, 0x27}, ++ {0x22000d, 0x186}, ++ {0x22000e, 0x10}, ++ {0x9000c, 0x0}, ++ {0x9000d, 0x173}, ++ {0x9000e, 0x60}, ++ {0x9000f, 0x6110}, ++ {0x90010, 0x2152}, ++ {0x90011, 0xdfbd}, ++ {0x90012, 0x2060}, ++ {0x90013, 0x6152}, ++ {0x20010, 0x5a}, ++ {0x20011, 0x3}, ++ {0x120010, 0x5a}, ++ {0x120011, 0x3}, ++ {0x40080, 0xe0}, ++ {0x40081, 0x12}, ++ {0x40082, 0xe0}, ++ {0x40083, 0x12}, ++ {0x40084, 0xe0}, ++ {0x40085, 0x12}, ++ {0x140080, 0xe0}, ++ {0x140081, 0x12}, ++ {0x140082, 0xe0}, ++ {0x140083, 0x12}, ++ {0x140084, 0xe0}, ++ {0x140085, 0x12}, ++ {0x240080, 0xe0}, ++ {0x240081, 0x12}, ++ {0x240082, 0xe0}, ++ {0x240083, 0x12}, ++ {0x240084, 0xe0}, ++ {0x240085, 0x12}, ++ {0x400fd, 0xf}, ++ {0x400f1, 0xe}, ++ {0x10011, 0x1}, ++ {0x10012, 0x1}, ++ {0x10013, 0x180}, ++ {0x10018, 0x1}, ++ {0x10002, 0x6209}, ++ {0x100b2, 0x1}, ++ {0x101b4, 0x1}, ++ {0x102b4, 0x1}, ++ {0x103b4, 0x1}, ++ {0x104b4, 0x1}, ++ {0x105b4, 0x1}, ++ {0x106b4, 0x1}, ++ {0x107b4, 0x1}, ++ {0x108b4, 0x1}, ++ {0x11011, 0x1}, ++ {0x11012, 0x1}, ++ {0x11013, 0x180}, ++ {0x11018, 0x1}, ++ {0x11002, 0x6209}, ++ {0x110b2, 0x1}, ++ {0x111b4, 0x1}, ++ {0x112b4, 0x1}, ++ {0x113b4, 0x1}, ++ {0x114b4, 0x1}, ++ {0x115b4, 0x1}, ++ {0x116b4, 0x1}, ++ {0x117b4, 0x1}, ++ {0x118b4, 0x1}, ++ {0x20089, 0x1}, ++ {0x20088, 0x19}, ++ {0xc0080, 0x0}, ++ {0xd0000, 0x1}, ++}; ++ ++static struct dram_fsp_msg ddr_dram_fsp_msg[] = { ++ { ++ /* P0 3733mts 1D */ ++ .drate = 3733, ++ .fw_type = FW_1D_IMAGE, ++ .fsp_cfg = ddr_fsp0_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_cfg), ++ }, ++ { ++ /* P1 1866mts 1D */ ++ .drate = 1866, ++ .fw_type = FW_1D_IMAGE, ++ .fsp_cfg = ddr_fsp1_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_fsp1_cfg), ++ }, ++ { ++ /* P2 625mts 1D */ ++ .drate = 625, ++ .fw_type = FW_1D_IMAGE, ++ .fsp_cfg = ddr_fsp2_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_fsp2_cfg), ++ }, ++ { ++ /* P0 3733mts 2D */ ++ .drate = 3733, ++ .fw_type = FW_2D_IMAGE, ++ .fsp_cfg = ddr_fsp0_2d_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_fsp0_2d_cfg), ++ }, ++}; ++ ++/* ddr timing config params */ ++struct dram_timing_info dram_timing_2GB = { ++ .ddrc_cfg = ddr_ddrc_cfg, ++ .ddrc_cfg_num = ARRAY_SIZE(ddr_ddrc_cfg), ++ .ddrphy_cfg = ddr_ddrphy_cfg, ++ .ddrphy_cfg_num = ARRAY_SIZE(ddr_ddrphy_cfg), ++ .fsp_msg = ddr_dram_fsp_msg, ++ .fsp_msg_num = ARRAY_SIZE(ddr_dram_fsp_msg), ++ .ddrphy_trained_csr = ddr_ddrphy_trained_csr, ++ .ddrphy_trained_csr_num = ARRAY_SIZE(ddr_ddrphy_trained_csr), ++ .ddrphy_pie = ddr_phy_pie, ++ .ddrphy_pie_num = ARRAY_SIZE(ddr_phy_pie), ++ .fsp_table = { 3733, 1866, 625, }, ++ .fsp_cfg = ddr_dram_fsp_cfg, ++ .fsp_cfg_num = ARRAY_SIZE(ddr_dram_fsp_cfg), ++}; +diff --git a/board/freescale/imx93_frdm/spl.c b/board/freescale/imx93_frdm/spl.c +new file mode 100644 +index 00000000000..5defdb05a5b +--- /dev/null ++++ b/board/freescale/imx93_frdm/spl.c +@@ -0,0 +1,201 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2024-2025 NXP ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++extern struct dram_timing_info dram_timing_2GB; ++ ++DECLARE_GLOBAL_DATA_PTR; ++ ++#define SRC_DDRC_SW_CTRL (0x44461020) ++#define SRC_DDRPHY_SINGLE_RESET_SW_CTRL (0x44461424) ++ ++int spl_board_boot_device(enum boot_device boot_dev_spl) ++{ ++#ifdef CONFIG_SPL_BOOTROM_SUPPORT ++ return BOOT_DEVICE_BOOTROM; ++#else ++ switch (boot_dev_spl) { ++ case SD1_BOOT: ++ case MMC1_BOOT: ++ return BOOT_DEVICE_MMC1; ++ case SD2_BOOT: ++ case MMC2_BOOT: ++ return BOOT_DEVICE_MMC2; ++ default: ++ return BOOT_DEVICE_NONE; ++ } ++#endif ++} ++ ++void spl_board_init(void) ++{ ++ int ret; ++ ++ ret = ele_start_rng(); ++ if (ret) ++ printf("Fail to start RNG: %d\n", ret); ++ ++ puts("Normal Boot\n"); ++} ++ ++void spl_dram_init(void) ++{ ++ int ret; ++ struct dram_timing_info *ptiming = &dram_timing_2GB; ++ ++ printf("DDR: %uMTS\n", ptiming->fsp_msg[0].drate); ++ ret = ddr_init(ptiming); ++ if (ret == 0) ++ printf("found DRAM %s matched\n", "2GB DRAM"); ++ else ++ printf("DRAM init failed\n"); ++} ++ ++#if CONFIG_IS_ENABLED(DM_PMIC_PCA9450) ++int power_init_board(void) ++{ ++ struct udevice *dev; ++ int ret; ++ unsigned int val = 0, buck_val; ++ ++ ret = pmic_get("pmic@25", &dev); ++ if (ret != 0) { ++ puts("ERROR: Get PMIC PCA9451A failed!\n"); ++ return ret; ++ } ++ puts("PMIC: PCA9451A\n"); ++ /* BUCKxOUT_DVS0/1 control BUCK123 output */ ++ pmic_reg_write(dev, PCA9450_BUCK123_DVS, 0x29); ++ ++ /* enable DVS control through PMIC_STBY_REQ */ ++ pmic_reg_write(dev, PCA9450_BUCK1CTRL, 0x59); ++ ++ ret = pmic_reg_read(dev, PCA9450_PWR_CTRL); ++ if (ret < 0) ++ return ret; ++ ++ val = ret; ++ ++ if (is_voltage_mode(VOLT_LOW_DRIVE)) { ++ buck_val = 0x0c; /* 0.8v for Low drive mode */ ++ printf("PMIC: Low Drive Voltage Mode\n"); ++ } else if (is_voltage_mode(VOLT_NOMINAL_DRIVE)) { ++ buck_val = 0x10; /* 0.85v for Nominal drive mode */ ++ printf("PMIC: Nominal Voltage Mode\n"); ++ } else { ++ buck_val = 0x14; /* 0.9v for Over drive mode */ ++ printf("PMIC: Over Drive Voltage Mode\n"); ++ } ++ ++ if (val & PCA9450_REG_PWRCTRL_TOFF_DEB) { ++ pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, buck_val); ++ pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, buck_val); ++ } else { ++ pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS0, buck_val + 0x4); ++ pmic_reg_write(dev, PCA9450_BUCK3OUT_DVS0, buck_val + 0x4); ++ } ++ ++ if (IS_ENABLED(CONFIG_IMX93_EVK_LPDDR4)) { ++ /* Set VDDQ to 1.1V from buck2 */ ++ pmic_reg_write(dev, PCA9450_BUCK2OUT_DVS0, 0x28); ++ } ++ ++ /* set standby voltage to 0.65v */ ++ if (val & PCA9450_REG_PWRCTRL_TOFF_DEB) ++ pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x0); ++ else ++ pmic_reg_write(dev, PCA9450_BUCK1OUT_DVS1, 0x4); ++ ++ /* I2C_LT_EN*/ ++ pmic_reg_write(dev, 0xa, 0x3); ++ return 0; ++} ++#endif ++ ++void board_init_f(ulong dummy) ++{ ++ int ret; ++ ++ /* Clear the BSS. */ ++ memset(__bss_start, 0, __bss_end - __bss_start); ++ ++ timer_init(); ++ ++ arch_cpu_init(); ++ ++ board_early_init_f(); ++ ++ spl_early_init(); ++ ++ preloader_console_init(); ++ ++ ret = imx9_probe_mu(); ++ if (ret) { ++ printf("Fail to init ELE API\n"); ++ } else { ++ printf("SOC: 0x%x\n", gd->arch.soc_rev); ++ printf("LC: 0x%x\n", gd->arch.lifecycle); ++ } ++ ++ clock_init_late(); ++ ++ power_init_board(); ++ ++ if (!is_voltage_mode(VOLT_LOW_DRIVE)) ++ set_arm_core_max_clk(); ++ ++ /* Init power of mix */ ++ soc_power_init(); ++ ++ /* Setup TRDC for DDR access */ ++ trdc_init(); ++ ++ /* DDR initialization */ ++ spl_dram_init(); ++ ++ /* Put M33 into CPUWAIT for following kick */ ++ ret = m33_prepare(); ++ if (!ret) ++ printf("M33 prepare ok\n"); ++ ++ board_init_r(NULL, 0); ++} ++ ++#ifdef CONFIG_ANDROID_SUPPORT ++int board_get_emmc_id(void) ++{ ++ return 0; ++} ++#endif +diff --git a/configs/imx93_11x11_frdm_defconfig b/configs/imx93_11x11_frdm_defconfig +new file mode 100644 +index 00000000000..22128b628d5 +--- /dev/null ++++ b/configs/imx93_11x11_frdm_defconfig +@@ -0,0 +1,158 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_IMX9=y ++CONFIG_TEXT_BASE=0x80200000 ++CONFIG_SYS_MALLOC_LEN=0x2000000 ++CONFIG_SYS_MALLOC_F_LEN=0x18000 ++CONFIG_SPL_LIBCOMMON_SUPPORT=y ++CONFIG_SPL_LIBGENERIC_SUPPORT=y ++CONFIG_NR_DRAM_BANKS=2 ++CONFIG_SF_DEFAULT_SPEED=40000000 ++CONFIG_ENV_SIZE=0x4000 ++CONFIG_ENV_OFFSET=0x700000 ++CONFIG_IMX_CONFIG="arch/arm/mach-imx/imx9/imximage.cfg" ++CONFIG_DM_GPIO=y ++CONFIG_DEFAULT_DEVICE_TREE="imx93-11x11-frdm" ++CONFIG_TARGET_IMX93_11X11_FRDM=y ++CONFIG_OF_LIBFDT_OVERLAY=y ++CONFIG_SYS_MONITOR_LEN=524288 ++CONFIG_SPL_SERIAL=y ++CONFIG_SPL_DRIVERS_MISC=y ++CONFIG_SPL_STACK=0x20519dd0 ++CONFIG_SPL_TEXT_BASE=0x2049A000 ++CONFIG_SPL_HAS_BSS_LINKER_SECTION=y ++CONFIG_SPL_BSS_START_ADDR=0x2051a000 ++CONFIG_SPL_BSS_MAX_SIZE=0x2000 ++CONFIG_SYS_LOAD_ADDR=0x80400000 ++CONFIG_SPL=y ++CONFIG_CMD_DEKBLOB=y ++CONFIG_SPL_IMX_ROMAPI_LOADADDR=0x88000000 ++CONFIG_EFI_VAR_BUF_SIZE=139264 ++CONFIG_ANDROID_BOOT_IMAGE=y ++CONFIG_FIT=y ++CONFIG_FIT_SIGNATURE=y ++CONFIG_LEGACY_IMAGE_FORMAT=y ++CONFIG_DISTRO_DEFAULTS=y ++CONFIG_OF_SYSTEM_SETUP=y ++CONFIG_BOOTCOMMAND="" ++CONFIG_DEFAULT_FDT_FILE="imx93-11x11-frdm.dtb" ++CONFIG_SYS_CBSIZE=2048 ++CONFIG_SYS_PBSIZE=2074 ++CONFIG_CONSOLE_MUX=y ++CONFIG_SYS_DEVICE_NULLDEV=y ++CONFIG_ARCH_MISC_INIT=y ++CONFIG_BOARD_EARLY_INIT_F=y ++CONFIG_BOARD_LATE_INIT=y ++CONFIG_SPL_MAX_SIZE=0x26000 ++CONFIG_SPL_BOARD_INIT=y ++CONFIG_SPL_BOOTROM_SUPPORT=y ++CONFIG_SPL_LOAD_IMX_CONTAINER=y ++CONFIG_IMX_CONTAINER_CFG="arch/arm/mach-imx/imx9/container.cfg" ++# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set ++CONFIG_SPL_HAVE_INIT_STACK=y ++CONFIG_SPL_SYS_MALLOC=y ++CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y ++CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x83200000 ++CONFIG_SPL_SYS_MALLOC_SIZE=0x80000 ++CONFIG_SPL_SYS_MMCSD_RAW_MODE=y ++CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x1040 ++CONFIG_SPL_I2C=y ++CONFIG_SPL_POWER=y ++CONFIG_SPL_WATCHDOG=y ++CONFIG_CMD_ERASEENV=y ++CONFIG_CMD_NVEDIT_EFI=y ++CONFIG_CRC32_VERIFY=y ++CONFIG_CMD_CLK=y ++CONFIG_CMD_DFU=y ++CONFIG_CMD_FUSE=y ++CONFIG_CMD_GPIO=y ++CONFIG_CMD_GPT=y ++CONFIG_CMD_I2C=y ++CONFIG_CMD_MMC=y ++CONFIG_CMD_POWEROFF=y ++CONFIG_CMD_USB=y ++CONFIG_CMD_USB_MASS_STORAGE=y ++CONFIG_CMD_SNTP=y ++CONFIG_CMD_CACHE=y ++CONFIG_CMD_EFIDEBUG=y ++CONFIG_CMD_RTC=y ++CONFIG_CMD_REGULATOR=y ++CONFIG_CMD_HASH=y ++CONFIG_CMD_EXT4_WRITE=y ++CONFIG_OF_CONTROL=y ++CONFIG_SPL_OF_CONTROL=y ++CONFIG_ENV_OVERWRITE=y ++CONFIG_ENV_IS_IN_MMC=y ++CONFIG_SYS_RELOC_GD_ENV_ADDR=y ++CONFIG_SYS_MMC_ENV_DEV=1 ++CONFIG_USE_ETHPRIME=y ++CONFIG_ETHPRIME="eth1" ++CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPL_DM=y ++CONFIG_REGMAP=y ++CONFIG_SYSCON=y ++CONFIG_ADC=y ++CONFIG_ADC_IMX93=y ++CONFIG_SPL_CLK_IMX93=y ++CONFIG_CLK_IMX93=y ++CONFIG_IMX_RGPIO2P=y ++CONFIG_DM_PCA953X=y ++CONFIG_ADP5585_GPIO=y ++CONFIG_DM_I2C=y ++CONFIG_SYS_I2C_IMX_LPI2C=y ++CONFIG_SUPPORT_EMMC_RPMB=y ++CONFIG_SUPPORT_EMMC_BOOT=y ++CONFIG_MMC_IO_VOLTAGE=y ++CONFIG_MMC_UHS_SUPPORT=y ++CONFIG_MMC_HS400_ES_SUPPORT=y ++CONFIG_MMC_HS400_SUPPORT=y ++CONFIG_FSL_USDHC=y ++CONFIG_MTD=y ++CONFIG_DM_SPI_FLASH=y ++CONFIG_SPI_FLASH_STMICRO=y ++CONFIG_PHY_MOTORCOMM=y ++CONFIG_PHY_REALTEK=y ++CONFIG_DM_ETH_PHY=y ++CONFIG_PHY_GIGE=y ++CONFIG_DWC_ETH_QOS=y ++CONFIG_DWC_ETH_QOS_IMX=y ++CONFIG_FEC_MXC=y ++CONFIG_MII=y ++CONFIG_MIPI_DPHY_HELPERS=y ++CONFIG_PINCTRL=y ++CONFIG_SPL_PINCTRL=y ++CONFIG_PINCTRL_IMX93=y ++CONFIG_POWER_DOMAIN=y ++CONFIG_DM_PMIC=y ++CONFIG_DM_PMIC_PCA9450=y ++CONFIG_SPL_DM_PMIC_PCA9450=y ++CONFIG_DM_REGULATOR=y ++CONFIG_DM_REGULATOR_PCA9450=y ++CONFIG_DM_REGULATOR_FIXED=y ++CONFIG_DM_REGULATOR_GPIO=y ++CONFIG_DM_RTC=y ++CONFIG_RTC_EMULATION=y ++CONFIG_DM_SERIAL=y ++CONFIG_FSL_LPUART=y ++CONFIG_SPI=y ++CONFIG_DM_SPI=y ++CONFIG_NXP_FSPI=y ++CONFIG_SYSRESET=y ++CONFIG_SPL_SYSRESET=y ++CONFIG_SYSRESET_CMD_POWEROFF=y ++CONFIG_SYSRESET_PSCI=y ++CONFIG_DM_THERMAL=y ++CONFIG_USB=y ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_HOST_ETHER=y ++CONFIG_USB_ETHER_ASIX=y ++CONFIG_USB_ETHER_RTL8152=y ++CONFIG_USB_GADGET=y ++CONFIG_USB_GADGET_MANUFACTURER="FSL" ++CONFIG_USB_GADGET_VENDOR_NUM=0x1fc9 ++CONFIG_USB_GADGET_PRODUCT_NUM=0x0152 ++CONFIG_CI_UDC=y ++CONFIG_USB_GADGET_DOWNLOAD=y ++CONFIG_ULP_WATCHDOG=y ++CONFIG_WDT=y ++CONFIG_SPL_RSA=y ++CONFIG_SHA384=y +diff --git a/include/configs/imx93_frdm.h b/include/configs/imx93_frdm.h +new file mode 100644 +index 00000000000..e1132c07c6b +--- /dev/null ++++ b/include/configs/imx93_frdm.h +@@ -0,0 +1,27 @@ ++/* SPDX-License-Identifier: GPL-2.0+ */ ++/* ++ * Copyright 2024-2025 NXP ++ */ ++ ++#ifndef __IMX93_FRDM_H ++#define __IMX93_FRDM_H ++ ++#include ++#include ++#include ++ ++#define CFG_SYS_UBOOT_BASE \ ++ (QSPI0_AMBA_BASE + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR * 512) ++ ++/* Link Definitions */ ++#define CFG_SYS_INIT_RAM_ADDR 0x80000000 ++#define CFG_SYS_INIT_RAM_SIZE 0x200000 ++ ++#define CFG_SYS_SDRAM_BASE 0x80000000 ++#define PHYS_SDRAM 0x80000000 ++#define PHYS_SDRAM_SIZE 0x80000000 /* 2GB DDR */ ++ ++/* Using ULP WDOG for reset */ ++#define WDOG_BASE_ADDR WDG3_BASE_ADDR ++ ++#endif +\ No newline at end of file +-- +2.43.0 + diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/mpd.conf b/lab-data/embedded-linux-imx93-frdm/buildroot/data/mpd.conf new file mode 100644 index 0000000000..063a083c45 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/buildroot/data/mpd.conf @@ -0,0 +1,36 @@ +# MPD configuration + +# For ALSA output: +audio_output { + type "alsa" + name "My ALSA Device" + mixer_type "software" +} + +# Directory where the music is stored +music_directory "/var/lib/mpd/music" + +# Directory where user-made playlists are stored (RW) +playlist_directory "/var/lib/mpd/playlists" + +# Database file (RW) +db_file "/var/lib/mpd/database" + +# Log file (RW) +log_file "/var/log/mpd.log" + +# Process ID file (RW) +pid_file "/var/run/mpd.pid" + +# State file (RW) +state_file "/var/lib/mpd/state" + +# User id to run the daemon as +#user "nobody" + +# TCP socket binding +#bind_to_address "any" +bind_to_address "localhost" + +# Unix socket to listen on +bind_to_address "/var/lib/mpd/socket" diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/1-sample.ogg b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/1-sample.ogg new file mode 100644 index 0000000000..bae2c390c0 Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/1-sample.ogg differ diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/2-arpent.ogg b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/2-arpent.ogg new file mode 100644 index 0000000000..9e60cc81a2 Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/2-arpent.ogg differ diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/3-chronos.ogg b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/3-chronos.ogg new file mode 100644 index 0000000000..fb02cff1de Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/3-chronos.ogg differ diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/4-land-of-pirates.ogg b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/4-land-of-pirates.ogg new file mode 100644 index 0000000000..321022477e Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/4-land-of-pirates.ogg differ diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/5-ukulele-song.ogg b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/5-ukulele-song.ogg new file mode 100644 index 0000000000..c536c4d41a Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/5-ukulele-song.ogg differ diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/6-le-baguette.ogg b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/6-le-baguette.ogg new file mode 100644 index 0000000000..64b171397e Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/6-le-baguette.ogg differ diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/7-fireworks.ogg b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/7-fireworks.ogg new file mode 100644 index 0000000000..9fc7849844 Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/7-fireworks.ogg differ diff --git a/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/README.txt b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/README.txt new file mode 100644 index 0000000000..0d194b0eba --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/buildroot/data/music/README.txt @@ -0,0 +1,3 @@ +With the exception of 1-sample.ogg file which is a short sample, +music files originate from https://freepd.com/ +(Free Public Domain music) diff --git a/lab-data/embedded-linux-imx93-frdm/hardware/data/nunchuk/Makefile b/lab-data/embedded-linux-imx93-frdm/hardware/data/nunchuk/Makefile new file mode 100644 index 0000000000..a857397e12 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/hardware/data/nunchuk/Makefile @@ -0,0 +1 @@ +obj-m := nunchuk.o diff --git a/lab-data/embedded-linux-imx93-frdm/hardware/data/nunchuk/nunchuk.c b/lab-data/embedded-linux-imx93-frdm/hardware/data/nunchuk/nunchuk.c new file mode 100644 index 0000000000..e20f2c7c25 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/hardware/data/nunchuk/nunchuk.c @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Available on SOLUTION_URL */ + +#include +#include +#include +#include +#include +#include + +/* Per device structure */ +struct nunchuk_dev { + struct i2c_client *i2c_client; +}; + +static int nunchuk_read_registers(struct i2c_client *client, u8 *recv) +{ + u8 buf[1]; + int ret; + + /* Ask the device to get ready for a read */ + usleep_range(10000, 20000); + + buf[0] = 0x00; + ret = i2c_master_send(client, buf, 1); + if (ret < 0) { + dev_err(&client->dev, "i2c send failed (%d)\n", ret); + return ret; + } + + usleep_range(10000, 20000); + + /* Now read registers */ + ret = i2c_master_recv(client, recv, 6); + if (ret < 0) { + dev_err(&client->dev, "i2c recv failed (%d)\n", ret); + return ret; + } + + return 0; +} + +static void nunchuk_poll(struct input_dev *input) +{ + u8 recv[6]; + int zpressed, cpressed, bx, by; + + /* Retrieve the physical i2c device */ + struct nunchuk_dev *nunchuk = input_get_drvdata(input); + struct i2c_client *client = nunchuk->i2c_client; + + /* Get the state of the device registers */ + if (nunchuk_read_registers(client, recv) < 0) + return; + + zpressed = (recv[5] & BIT(0)) ? 0 : 1; + cpressed = (recv[5] & BIT(1)) ? 0 : 1; + bx = recv[0]; + by = recv[1]; + + /* Send events to the INPUT subsystem */ + input_report_key(input, BTN_Z, zpressed); + input_report_key(input, BTN_C, cpressed); + + input_report_abs(input, ABS_X, bx); + input_report_abs(input, ABS_Y, by); + + input_sync(input); +} + +static int nunchuk_probe(struct i2c_client *client) +{ + struct nunchuk_dev *nunchuk; + struct input_dev *input; + u8 buf[2]; + int ret; + + /* Allocate per device structure */ + nunchuk = devm_kzalloc(&client->dev, sizeof(*nunchuk), GFP_KERNEL); + if (!nunchuk) + /* No message necessary here, already issued by allocation functions */ + return -ENOMEM; + + /* Initialize device */ + buf[0] = 0xf0; + buf[1] = 0x55; + + ret = i2c_master_send(client, buf, 2); + if (ret < 0) { + dev_err(&client->dev, "i2c send failed (%d)\n", ret); + return ret; + } + + udelay(1000); + + buf[0] = 0xfb; + buf[1] = 0x00; + + ret = i2c_master_send(client, buf, 2); + if (ret < 0) { + dev_err(&client->dev, "i2c send failed (%d)\n", ret); + return ret; + } + + /* Allocate input device */ + input = devm_input_allocate_device(&client->dev); + if (!input) + return -ENOMEM; + + /* + * Implement pointers from logical to physical. Here, no need for + * physical to logical pointers as unregistering and freeing the + * polled_input device will be automatic. + */ + nunchuk->i2c_client = client; + input_set_drvdata(input, nunchuk); + + /* Configure input device */ + input->name = "Wii Nunchuk"; + input->id.bustype = BUS_I2C; + + set_bit(EV_KEY, input->evbit); + set_bit(BTN_C, input->keybit); + set_bit(BTN_Z, input->keybit); + + set_bit(EV_ABS, input->evbit); + set_bit(ABS_X, input->absbit); + set_bit(ABS_Y, input->absbit); + input_set_abs_params(input, ABS_X, 30, 220, 4, 8); + input_set_abs_params(input, ABS_Y, 40, 200, 4, 8); + + /* Classic buttons */ + set_bit(BTN_TL, input->keybit); + set_bit(BTN_SELECT, input->keybit); + set_bit(BTN_MODE, input->keybit); + set_bit(BTN_START, input->keybit); + set_bit(BTN_TR, input->keybit); + set_bit(BTN_TL2, input->keybit); + set_bit(BTN_B, input->keybit); + set_bit(BTN_Y, input->keybit); + set_bit(BTN_A, input->keybit); + set_bit(BTN_X, input->keybit); + set_bit(BTN_TR2, input->keybit); + + /* Register and configure polling function */ + ret = input_setup_polling(input, nunchuk_poll); + if (ret) { + dev_err(&client->dev, "Failed to set polling function (%d)\n", + ret); + return ret; + } + + input_set_poll_interval(input, 50); + + /* Register the input device when everything is ready */ + ret = input_register_device(input); + if (ret) { + dev_err(&client->dev, "Cannot register input device (%d)\n", + ret); + return ret; + } + + + pr_info("Nunchuk device probed successfully\n"); + return 0; +} + +#if KERNEL_VERSION(5, 16, 0) <= LINUX_VERSION_CODE +static void nunchuk_remove(struct i2c_client *client) +#else +static int nunchuk_remove(struct i2c_client *client) +#endif +{ + /* + * Nothing to do here, as the polled_input device is automatically + * unregistered and freed thanks to the use of + * devm_input_allocate_device. + */ + + pr_info("Nunchuk device removed successfully\n"); + #if KERNEL_VERSION(5, 16, 0) > LINUX_VERSION_CODE + return 0; + #endif +} + +/* Specification of supported Device Tree devices */ +static const struct of_device_id nunchuk_dt_match[] = { + { .compatible = "nintendo,nunchuk" }, + { }, +}; +MODULE_DEVICE_TABLE(of, nunchuk_dt_match); + +/* Driver declaration */ +static struct i2c_driver nunchuk_driver = { + .driver = { + .name = "nunchuk", + .of_match_table = nunchuk_dt_match, + }, + .probe = nunchuk_probe, + .remove = nunchuk_remove, +}; +module_i2c_driver(nunchuk_driver); + +MODULE_LICENSE("GPL"); diff --git a/lab-data/embedded-linux-imx93-frdm/kernel/data/0001-linux-imx93-frdm.patch b/lab-data/embedded-linux-imx93-frdm/kernel/data/0001-linux-imx93-frdm.patch new file mode 100644 index 0000000000..50f19d20b9 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/kernel/data/0001-linux-imx93-frdm.patch @@ -0,0 +1,594 @@ +From 476863b5d172b9466e4158be055d6e352df170ae Mon Sep 17 00:00:00 2001 +From: Antoine Picard +Date: Thu, 24 Jul 2025 16:06:23 +0200 +Subject: [PATCH] linux-imx93-frdm + +Signed-off-by: Antoine Picard +--- + .../boot/dts/freescale/imx93-11x11-frdm.dts | 574 ++++++++++++++++++ + 1 file changed, 574 insertions(+) + create mode 100644 arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts + +diff --git a/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts +new file mode 100644 +index 000000000000..5236ce3b3f89 +--- /dev/null ++++ b/arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts +@@ -0,0 +1,574 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright 2024-2025 NXP ++ */ ++ ++/dts-v1/; ++ ++#include ++#include "imx93.dtsi" ++ ++/ { ++ model = "NXP i.MX93 11X11 FRDM board"; ++ compatible = "fsl,imx93-11x11-frdm", "fsl,imx93"; ++ ++ aliases { ++ rtc0 = &pcf2131; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyLP0,115200"; ++ stdout-path = &lpuart1; ++ }; ++ ++ reserved-memory { ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ ++ linux,cma { ++ compatible = "shared-dma-pool"; ++ reusable; ++ alloc-ranges = <0 0x80000000 0 0x40000000>; ++ size = <0 0x10000000>; ++ linux,cma-default; ++ }; ++ }; ++ ++ reg_can2_stby: regulator-can2-stby { ++ compatible = "regulator-fixed"; ++ regulator-name = "can2-stby"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&pcal6524 23 GPIO_ACTIVE_LOW>; ++ enable-active-high; ++ }; ++ ++ reg_vref_1v8: regulator-adc-vref { ++ compatible = "regulator-fixed"; ++ regulator-name = "vref_1v8"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ }; ++ ++ reg_usdhc2_vmmc: regulator-usdhc2 { ++ compatible = "regulator-fixed"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; ++ regulator-name = "VSD_3V3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; ++ off-on-delay-us = <12000>; ++ enable-active-high; ++ }; ++ ++ reg_vdd_12v: regulator-vdd-12v { ++ compatible = "regulator-fixed"; ++ regulator-name = "reg_vdd_12v"; ++ regulator-min-microvolt = <12000000>; ++ regulator-max-microvolt = <12000000>; ++ gpio = <&pcal6524 14 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led_red { ++ label = "led-red"; ++ gpios = <&gpio2 13 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_green { ++ label = "led-green"; ++ gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ ++ led_blue { ++ label = "led-blue"; ++ gpios = <&gpio2 12 GPIO_ACTIVE_HIGH>; ++ default-state = "on"; ++ }; ++ }; ++}; ++ ++ ++&adc1 { ++ vref-supply = <®_vref_1v8>; ++ status = "okay"; ++}; ++ ++&mu1 { ++ status = "okay"; ++}; ++ ++&mu2 { ++ status = "okay"; ++}; ++ ++&eqos { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_eqos>; ++ phy-mode = "rgmii-id"; ++ phy-handle = <ðphy1>; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <5000000>; ++ ++ ethphy1: ethernet-phy@1 { ++ reg = <1>; ++ eee-broken-1000t; ++ ++ reset-gpios = <&pcal6524 15 GPIO_ACTIVE_LOW>; ++ reset-assert-us = <15000>; ++ reset-deassert-us = <100000>; ++ }; ++ }; ++}; ++ ++&fec { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_fec>; ++ phy-mode = "rgmii-id"; ++ phy-handle = <ðphy2>; ++ fsl,magic-packet; ++ status = "okay"; ++ ++ mdio { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <5000000>; ++ ++ ethphy2: ethernet-phy@2 { ++ reg = <2>; ++ eee-broken-1000t; ++ }; ++ }; ++}; ++ ++&lpi2c1 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <400000>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&pinctrl_lpi2c1>; ++ pinctrl-1 = <&pinctrl_lpi2c1>; ++ status = "okay"; ++}; ++ ++&lpi2c2 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <400000>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&pinctrl_lpi2c2>; ++ pinctrl-1 = <&pinctrl_lpi2c2>; ++ status = "okay"; ++ ++ pmic@25 { ++ compatible = "nxp,pca9451a"; ++ reg = <0x25>; ++ interrupt-parent = <&pcal6524>; ++ interrupts = <11 IRQ_TYPE_EDGE_FALLING>; ++ ++ regulators { ++ buck1: BUCK1 { ++ regulator-name = "BUCK1"; ++ regulator-min-microvolt = <650000>; ++ regulator-max-microvolt = <2237500>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-ramp-delay = <3125>; ++ }; ++ ++ buck2: BUCK2 { ++ regulator-name = "BUCK2"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <2187500>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-ramp-delay = <3125>; ++ }; ++ ++ buck4: BUCK4{ ++ regulator-name = "BUCK4"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3400000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buck5: BUCK5{ ++ regulator-name = "BUCK5"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3400000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ buck6: BUCK6 { ++ regulator-name = "BUCK6"; ++ regulator-min-microvolt = <600000>; ++ regulator-max-microvolt = <3400000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo1: LDO1 { ++ regulator-name = "LDO1"; ++ regulator-min-microvolt = <1600000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo4: LDO4 { ++ regulator-name = "LDO4"; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo5: LDO5 { ++ regulator-name = "LDO5"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ }; ++ }; ++ ++ pcal6524: gpio@22 { ++ compatible = "nxp,pcal6524"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_pcal6524>; ++ reg = <0x22>; ++ gpio-controller; ++ #gpio-cells = <2>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ interrupt-parent = <&gpio3>; ++ interrupts = <27 IRQ_TYPE_EDGE_FALLING>; ++ }; ++ eeprom: eeprom@50 { ++ compatible = "atmel,24c256"; ++ reg = <0x50>; ++ pagesize = <64>; ++ }; ++ ++}; ++ ++&lpi2c3 { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ clock-frequency = <400000>; ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&pinctrl_lpi2c3>; ++ pinctrl-1 = <&pinctrl_lpi2c3>; ++ status = "okay"; ++ ++ pcf2131: rtc@53 { ++ compatible = "nxp,pcf2131"; ++ reg = <0x53>; ++ interrupt-parent = <&pcal6524>; ++ interrupts = <1 IRQ_TYPE_EDGE_FALLING>; ++ status = "okay"; ++ }; ++ ++ ptn5110: tcpc@50 { ++ compatible = "nxp,ptn5110", "tcpci"; ++ reg = <0x50>; ++ interrupt-parent = <&gpio3>; ++ interrupts = <27 IRQ_TYPE_EDGE_FALLING>; ++ status = "okay"; ++ ++ port { ++ typec1_dr_sw: endpoint { ++ remote-endpoint = <&usb1_drd_sw>; ++ }; ++ }; ++ ++ typec1_con: connector { ++ compatible = "usb-c-connector"; ++ label = "USB-C"; ++ power-role = "dual"; ++ data-role = "dual"; ++ try-power-role = "sink"; ++ source-pdos = ; ++ sink-pdos = ; ++ op-sink-microwatt = <15000000>; ++ self-powered; ++ }; ++ }; ++ ++}; ++ ++&lpuart1 { /* console */ ++ pinctrl-names = "default"; ++ pinctrl-0 = <&pinctrl_uart1>; ++ status = "okay"; ++}; ++ ++&media_blk_ctrl { ++ status = "okay"; ++}; ++ ++&usbotg1 { ++ dr_mode = "otg"; ++ hnp-disable; ++ srp-disable; ++ adp-disable; ++ usb-role-switch; ++ disable-over-current; ++ samsung,picophy-pre-emp-curr-control = <3>; ++ samsung,picophy-dc-vol-level-adjust = <7>; ++ status = "okay"; ++ ++ port { ++ usb1_drd_sw: endpoint { ++ remote-endpoint = <&typec1_dr_sw>; ++ }; ++ }; ++}; ++ ++&usbotg2 { ++ dr_mode = "host"; ++ disable-over-current; ++ samsung,picophy-pre-emp-curr-control = <3>; ++ samsung,picophy-dc-vol-level-adjust = <7>; ++ status = "okay"; ++}; ++ ++&usdhc1 { ++ pinctrl-names = "default", "state_100mhz", "state_200mhz"; ++ pinctrl-0 = <&pinctrl_usdhc1>; ++ pinctrl-1 = <&pinctrl_usdhc1_100mhz>; ++ pinctrl-2 = <&pinctrl_usdhc1_200mhz>; ++ bus-width = <8>; ++ non-removable; ++ status = "okay"; ++}; ++ ++&usdhc2 { ++ pinctrl-names = "default", "state_100mhz", "state_200mhz"; ++ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; ++ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; ++ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; ++ cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; ++ vmmc-supply = <®_usdhc2_vmmc>; ++ bus-width = <4>; ++ status = "okay"; ++ no-sdio; ++ no-mmc; ++}; ++ ++&usdhc3 { ++ status = "disabled"; ++}; ++ ++&wdog3 { ++ status = "okay"; ++}; ++ ++&iomuxc { ++ pinctrl_eqos: eqosgrp { ++ fsl,pins = < ++ MX93_PAD_ENET1_MDC__ENET_QOS_MDC 0x57e ++ MX93_PAD_ENET1_MDIO__ENET_QOS_MDIO 0x57e ++ MX93_PAD_ENET1_RD0__ENET_QOS_RGMII_RD0 0x57e ++ MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e ++ MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e ++ MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e ++ MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x5fe ++ MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e ++ MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e ++ MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e ++ MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e ++ MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e ++ MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x5fe ++ MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e ++ >; ++ }; ++ ++ pinctrl_flexspi: flexspigrp { ++ fsl,pins = < ++ MX93_PAD_SD3_CMD__FLEXSPI1_A_SS0_B 0x3fe ++ MX93_PAD_SD3_CLK__FLEXSPI1_A_SCLK 0x3fe ++ MX93_PAD_SD3_DATA0__FLEXSPI1_A_DATA00 0x3fe ++ MX93_PAD_SD3_DATA1__FLEXSPI1_A_DATA01 0x3fe ++ MX93_PAD_SD3_DATA2__FLEXSPI1_A_DATA02 0x3fe ++ MX93_PAD_SD3_DATA3__FLEXSPI1_A_DATA03 0x3fe ++ >; ++ }; ++ ++ pinctrl_fec: fecgrp { ++ fsl,pins = < ++ MX93_PAD_ENET2_MDC__ENET1_MDC 0x57e ++ MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x57e ++ MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e ++ MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e ++ MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e ++ MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e ++ MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x5fe ++ MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e ++ MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x57e ++ MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x57e ++ MX93_PAD_ENET2_TD2__ENET1_RGMII_TD2 0x57e ++ MX93_PAD_ENET2_TD3__ENET1_RGMII_TD3 0x57e ++ MX93_PAD_ENET2_TXC__ENET1_RGMII_TXC 0x5fe ++ MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x57e ++ >; ++ }; ++ ++ pinctrl_lpi2c1: lpi2c1grp { ++ fsl,pins = < ++ MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e ++ MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e ++ >; ++ }; ++ ++ pinctrl_lpi2c2: lpi2c2grp { ++ fsl,pins = < ++ MX93_PAD_I2C2_SCL__LPI2C2_SCL 0x40000b9e ++ MX93_PAD_I2C2_SDA__LPI2C2_SDA 0x40000b9e ++ >; ++ }; ++ ++ pinctrl_lpi2c3: lpi2c3grp { ++ fsl,pins = < ++ MX93_PAD_GPIO_IO28__LPI2C3_SDA 0x40000b9e ++ MX93_PAD_GPIO_IO29__LPI2C3_SCL 0x40000b9e ++ >; ++ }; ++ ++ pinctrl_pcal6524: pcal6524grp { ++ fsl,pins = < ++ MX93_PAD_CCM_CLKO2__GPIO3_IO27 0x31e ++ >; ++ }; ++ ++ pinctrl_uart1: uart1grp { ++ fsl,pins = < ++ MX93_PAD_UART1_RXD__LPUART1_RX 0x31e ++ MX93_PAD_UART1_TXD__LPUART1_TX 0x31e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc1: usdhc1grp { ++ fsl,pins = < ++ MX93_PAD_SD1_CLK__USDHC1_CLK 0x1582 ++ MX93_PAD_SD1_CMD__USDHC1_CMD 0x40001382 ++ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x40001382 ++ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x40001382 ++ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x40001382 ++ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x40001382 ++ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x40001382 ++ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x40001382 ++ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x40001382 ++ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x40001382 ++ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x1582 ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc1_100mhz: usdhc1-100mhzgrp { ++ fsl,pins = < ++ MX93_PAD_SD1_CLK__USDHC1_CLK 0x158e ++ MX93_PAD_SD1_CMD__USDHC1_CMD 0x4000138e ++ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x4000138e ++ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x4000138e ++ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x4000138e ++ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x4000138e ++ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x4000138e ++ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x4000138e ++ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x4000138e ++ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x4000138e ++ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x158e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc1_200mhz: usdhc1-200mhzgrp { ++ fsl,pins = < ++ MX93_PAD_SD1_CLK__USDHC1_CLK 0x15fe ++ MX93_PAD_SD1_CMD__USDHC1_CMD 0x400013fe ++ MX93_PAD_SD1_DATA0__USDHC1_DATA0 0x400013fe ++ MX93_PAD_SD1_DATA1__USDHC1_DATA1 0x400013fe ++ MX93_PAD_SD1_DATA2__USDHC1_DATA2 0x400013fe ++ MX93_PAD_SD1_DATA3__USDHC1_DATA3 0x400013fe ++ MX93_PAD_SD1_DATA4__USDHC1_DATA4 0x400013fe ++ MX93_PAD_SD1_DATA5__USDHC1_DATA5 0x400013fe ++ MX93_PAD_SD1_DATA6__USDHC1_DATA6 0x400013fe ++ MX93_PAD_SD1_DATA7__USDHC1_DATA7 0x400013fe ++ MX93_PAD_SD1_STROBE__USDHC1_STROBE 0x15fe ++ >; ++ }; ++ ++ pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { ++ fsl,pins = < ++ MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e ++ >; ++ }; ++ ++ pinctrl_usdhc2_gpio: usdhc2gpiogrp { ++ fsl,pins = < ++ MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e ++ >; ++ }; ++ ++ pinctrl_usdhc2_gpio_sleep: usdhc2-gpio-grp { ++ fsl,pins = < ++ MX93_PAD_SD2_CD_B__GPIO3_IO00 0x51e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc2: usdhc2grp { ++ fsl,pins = < ++ MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582 ++ MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382 ++ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382 ++ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382 ++ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382 ++ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382 ++ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { ++ fsl,pins = < ++ MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e ++ MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e ++ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e ++ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e ++ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e ++ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e ++ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e ++ >; ++ }; ++ ++ /* need to config the SION for data and cmd pad, refer to ERR052021 */ ++ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { ++ fsl,pins = < ++ MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe ++ MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe ++ MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe ++ MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe ++ MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe ++ MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe ++ MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e ++ >; ++ }; ++}; +-- +2.43.0 + diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/0001-menuconfig-GCC-failing-saying-ncurses-is-not-found.patch b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/0001-menuconfig-GCC-failing-saying-ncurses-is-not-found.patch new file mode 100644 index 0000000000..aaf4753387 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/0001-menuconfig-GCC-failing-saying-ncurses-is-not-found.patch @@ -0,0 +1,34 @@ +From 5b15eb054e3eb03c3e9214650490868d13966c90 Mon Sep 17 00:00:00 2001 +From: Nop +Date: Sun, 21 Jul 2024 14:10:52 +0200 +Subject: [PATCH] menuconfig: GCC failing saying ncurses is not found + +Newer GCC increased diagnostics levels resulting in considering the test +code to be invalid. The resulting message was misleading, saying that +ncurses is not found, while it is actually found because GCC output is +redirected to /dev/null. + +Signed-off-by: ctxnop +--- + scripts/kconfig/lxdialog/check-lxdialog.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh +index 5075ebf2d..c644d1d48 100755 +--- a/scripts/kconfig/lxdialog/check-lxdialog.sh ++++ b/scripts/kconfig/lxdialog/check-lxdialog.sh +@@ -45,9 +45,9 @@ trap "rm -f $tmp" 0 1 2 3 15 + + # Check if we can link to ncurses + check() { +- $cc -x c - -o $tmp 2>/dev/null <<'EOF' ++ $cc -x c - -o $tmp <<'EOF' + #include CURSES_LOC +-main() {} ++int main() { return 0; } + EOF + if [ $? != 0 ]; then + echo " *** Unable to find the ncurses libraries or the" 1>&2 +-- +2.47.0 + diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/busybox-1.37.config b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/busybox-1.37.config new file mode 100644 index 0000000000..eb3cfc76a0 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/busybox-1.37.config @@ -0,0 +1,1215 @@ +# +# Automatically generated make config: don't edit +# Busybox version: 1.37.0 +# Fri Jun 27 16:20:16 2025 +# +CONFIG_HAVE_DOT_CONFIG=y + +# +# Settings +# +# CONFIG_DESKTOP is not set +# CONFIG_EXTRA_COMPAT is not set +# CONFIG_FEDORA_COMPAT is not set +# CONFIG_INCLUDE_SUSv2 is not set +CONFIG_LONG_OPTS=y +CONFIG_SHOW_USAGE=y +CONFIG_FEATURE_VERBOSE_USAGE=y +# CONFIG_FEATURE_COMPRESS_USAGE is not set +CONFIG_LFS=y +CONFIG_TIME64=y +# CONFIG_PAM is not set +# CONFIG_FEATURE_DEVPTS is not set +# CONFIG_FEATURE_UTMP is not set +# CONFIG_FEATURE_WTMP is not set +# CONFIG_FEATURE_PIDFILE is not set +CONFIG_PID_FILE_PATH="" +CONFIG_BUSYBOX=y +CONFIG_FEATURE_SHOW_SCRIPT=y +# CONFIG_FEATURE_INSTALLER is not set +# CONFIG_INSTALL_NO_USR is not set +# CONFIG_FEATURE_SUID is not set +# CONFIG_FEATURE_SUID_CONFIG is not set +# CONFIG_FEATURE_SUID_CONFIG_QUIET is not set +# CONFIG_FEATURE_PREFER_APPLETS is not set +CONFIG_BUSYBOX_EXEC_PATH="/proc/self/exe" +# CONFIG_SELINUX is not set +# CONFIG_FEATURE_CLEAN_UP is not set +CONFIG_FEATURE_SYSLOG_INFO=y +CONFIG_FEATURE_SYSLOG=y + +# +# Build Options +# +CONFIG_STATIC=y +# CONFIG_PIE is not set +# CONFIG_NOMMU is not set +# CONFIG_BUILD_LIBBUSYBOX is not set +# CONFIG_FEATURE_LIBBUSYBOX_STATIC is not set +# CONFIG_FEATURE_INDIVIDUAL is not set +# CONFIG_FEATURE_SHARED_BUSYBOX is not set +CONFIG_CROSS_COMPILER_PREFIX="arm-linux-" +CONFIG_SYSROOT="" +CONFIG_EXTRA_CFLAGS="" +CONFIG_EXTRA_LDFLAGS="" +CONFIG_EXTRA_LDLIBS="" +# CONFIG_USE_PORTABLE_CODE is not set +# CONFIG_STACK_OPTIMIZATION_386 is not set +CONFIG_STATIC_LIBGCC=y + +# +# Installation Options ("make install" behavior) +# +CONFIG_INSTALL_APPLET_SYMLINKS=y +# CONFIG_INSTALL_APPLET_HARDLINKS is not set +# CONFIG_INSTALL_APPLET_SCRIPT_WRAPPERS is not set +# CONFIG_INSTALL_APPLET_DONT is not set +# CONFIG_INSTALL_SH_APPLET_SYMLINK is not set +# CONFIG_INSTALL_SH_APPLET_HARDLINK is not set +# CONFIG_INSTALL_SH_APPLET_SCRIPT_WRAPPER is not set +CONFIG_PREFIX="../nfsroot" + +# +# Debugging Options +# +# CONFIG_DEBUG is not set +# CONFIG_DEBUG_PESSIMIZE is not set +# CONFIG_DEBUG_SANITIZE is not set +# CONFIG_UNIT_TEST is not set +# CONFIG_WERROR is not set +# CONFIG_WARN_SIMPLE_MSG is not set +CONFIG_NO_DEBUG_LIB=y +# CONFIG_DMALLOC is not set +# CONFIG_EFENCE is not set + +# +# Library Tuning +# +# CONFIG_FEATURE_USE_BSS_TAIL is not set +CONFIG_FLOAT_DURATION=y +CONFIG_FEATURE_RTMINMAX=y +CONFIG_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS=y +CONFIG_FEATURE_BUFFERS_USE_MALLOC=y +# CONFIG_FEATURE_BUFFERS_GO_ON_STACK is not set +# CONFIG_FEATURE_BUFFERS_GO_IN_BSS is not set +CONFIG_PASSWORD_MINLEN=6 +CONFIG_MD5_SMALL=1 +CONFIG_SHA1_SMALL=3 +# CONFIG_SHA1_HWACCEL is not set +# CONFIG_SHA256_HWACCEL is not set +CONFIG_SHA3_SMALL=1 +CONFIG_FEATURE_NON_POSIX_CP=y +# CONFIG_FEATURE_VERBOSE_CP_MESSAGE is not set +CONFIG_FEATURE_USE_SENDFILE=y +CONFIG_FEATURE_COPYBUF_KB=4 +# CONFIG_MONOTONIC_SYSCALL is not set +CONFIG_IOCTL_HEX2STR_ERROR=y +CONFIG_FEATURE_EDITING=y +CONFIG_FEATURE_EDITING_MAX_LEN=1024 +# CONFIG_FEATURE_EDITING_VI is not set +CONFIG_FEATURE_EDITING_HISTORY=15 +# CONFIG_FEATURE_EDITING_SAVEHISTORY is not set +# CONFIG_FEATURE_EDITING_SAVE_ON_EXIT is not set +# CONFIG_FEATURE_REVERSE_SEARCH is not set +CONFIG_FEATURE_TAB_COMPLETION=y +# CONFIG_FEATURE_USERNAME_COMPLETION is not set +# CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set +CONFIG_FEATURE_EDITING_WINCH=y +# CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set +# CONFIG_LOCALE_SUPPORT is not set +CONFIG_UNICODE_SUPPORT=y +# CONFIG_UNICODE_USING_LOCALE is not set +# CONFIG_FEATURE_CHECK_UNICODE_IN_ENV is not set +CONFIG_SUBST_WCHAR=63 +CONFIG_LAST_SUPPORTED_WCHAR=767 +# CONFIG_UNICODE_COMBINING_WCHARS is not set +# CONFIG_UNICODE_WIDE_WCHARS is not set +# CONFIG_UNICODE_BIDI_SUPPORT is not set +# CONFIG_UNICODE_NEUTRAL_TABLE is not set +# CONFIG_UNICODE_PRESERVE_BROKEN is not set +# CONFIG_LOOP_CONFIGURE is not set +# CONFIG_NO_LOOP_CONFIGURE is not set +CONFIG_TRY_LOOP_CONFIGURE=y + +# +# Applets +# + +# +# Archival Utilities +# +# CONFIG_FEATURE_SEAMLESS_XZ is not set +# CONFIG_FEATURE_SEAMLESS_LZMA is not set +# CONFIG_FEATURE_SEAMLESS_BZ2 is not set +# CONFIG_FEATURE_SEAMLESS_GZ is not set +# CONFIG_FEATURE_SEAMLESS_Z is not set +# CONFIG_AR is not set +# CONFIG_FEATURE_AR_LONG_FILENAMES is not set +# CONFIG_FEATURE_AR_CREATE is not set +# CONFIG_UNCOMPRESS is not set +# CONFIG_GUNZIP is not set +# CONFIG_ZCAT is not set +# CONFIG_FEATURE_GUNZIP_LONG_OPTIONS is not set +# CONFIG_BUNZIP2 is not set +# CONFIG_BZCAT is not set +# CONFIG_UNLZMA is not set +# CONFIG_LZCAT is not set +# CONFIG_LZMA is not set +# CONFIG_UNXZ is not set +# CONFIG_XZCAT is not set +# CONFIG_XZ is not set +# CONFIG_BZIP2 is not set +CONFIG_BZIP2_SMALL=0 +# CONFIG_FEATURE_BZIP2_DECOMPRESS is not set +# CONFIG_CPIO is not set +# CONFIG_FEATURE_CPIO_O is not set +# CONFIG_FEATURE_CPIO_P is not set +# CONFIG_FEATURE_CPIO_IGNORE_DEVNO is not set +# CONFIG_FEATURE_CPIO_RENUMBER_INODES is not set +# CONFIG_DPKG is not set +# CONFIG_DPKG_DEB is not set +# CONFIG_GZIP is not set +# CONFIG_FEATURE_GZIP_LONG_OPTIONS is not set +CONFIG_GZIP_FAST=0 +# CONFIG_FEATURE_GZIP_LEVELS is not set +# CONFIG_FEATURE_GZIP_DECOMPRESS is not set +# CONFIG_LZOP is not set +# CONFIG_UNLZOP is not set +# CONFIG_LZOPCAT is not set +# CONFIG_LZOP_COMPR_HIGH is not set +# CONFIG_RPM is not set +# CONFIG_RPM2CPIO is not set +# CONFIG_TAR is not set +# CONFIG_FEATURE_TAR_LONG_OPTIONS is not set +# CONFIG_FEATURE_TAR_CREATE is not set +# CONFIG_FEATURE_TAR_AUTODETECT is not set +# CONFIG_FEATURE_TAR_FROM is not set +# CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_OLDSUN_COMPATIBILITY is not set +# CONFIG_FEATURE_TAR_GNU_EXTENSIONS is not set +# CONFIG_FEATURE_TAR_TO_COMMAND is not set +# CONFIG_FEATURE_TAR_UNAME_GNAME is not set +# CONFIG_FEATURE_TAR_NOPRESERVE_TIME is not set +# CONFIG_FEATURE_TAR_SELINUX is not set +# CONFIG_UNZIP is not set +# CONFIG_FEATURE_UNZIP_CDF is not set +# CONFIG_FEATURE_UNZIP_BZIP2 is not set +# CONFIG_FEATURE_UNZIP_LZMA is not set +# CONFIG_FEATURE_UNZIP_XZ is not set +# CONFIG_FEATURE_LZMA_FAST is not set + +# +# Coreutils +# +CONFIG_FEATURE_VERBOSE=y + +# +# Common options for date and touch +# +# CONFIG_FEATURE_TIMEZONE is not set + +# +# Common options for cp and mv +# +# CONFIG_FEATURE_PRESERVE_HARDLINKS is not set + +# +# Common options for df, du, ls +# +CONFIG_FEATURE_HUMAN_READABLE=y +# CONFIG_BASENAME is not set +CONFIG_CAT=y +# CONFIG_FEATURE_CATN is not set +CONFIG_FEATURE_CATV=y +# CONFIG_CHGRP is not set +CONFIG_CHMOD=y +# CONFIG_CHOWN is not set +# CONFIG_FEATURE_CHOWN_LONG_OPTIONS is not set +# CONFIG_CHROOT is not set +# CONFIG_CKSUM is not set +# CONFIG_CRC32 is not set +# CONFIG_COMM is not set +CONFIG_CP=y +# CONFIG_FEATURE_CP_LONG_OPTIONS is not set +# CONFIG_FEATURE_CP_REFLINK is not set +# CONFIG_CUT is not set +# CONFIG_FEATURE_CUT_REGEX is not set +# CONFIG_DATE is not set +# CONFIG_FEATURE_DATE_ISOFMT is not set +# CONFIG_FEATURE_DATE_NANO is not set +# CONFIG_FEATURE_DATE_COMPAT is not set +# CONFIG_DD is not set +# CONFIG_FEATURE_DD_SIGNAL_HANDLING is not set +# CONFIG_FEATURE_DD_THIRD_STATUS_LINE is not set +# CONFIG_FEATURE_DD_IBS_OBS is not set +# CONFIG_FEATURE_DD_STATUS is not set +CONFIG_DF=y +CONFIG_FEATURE_DF_FANCY=y +# CONFIG_FEATURE_SKIP_ROOTFS is not set +# CONFIG_DIRNAME is not set +# CONFIG_DOS2UNIX is not set +# CONFIG_UNIX2DOS is not set +# CONFIG_DU is not set +# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set +CONFIG_ECHO=y +# CONFIG_FEATURE_FANCY_ECHO is not set +# CONFIG_ENV is not set +# CONFIG_EXPAND is not set +# CONFIG_UNEXPAND is not set +# CONFIG_EXPR is not set +# CONFIG_EXPR_MATH_SUPPORT_64 is not set +# CONFIG_FACTOR is not set +# CONFIG_FALSE is not set +# CONFIG_FOLD is not set +# CONFIG_HEAD is not set +# CONFIG_FEATURE_FANCY_HEAD is not set +# CONFIG_HOSTID is not set +# CONFIG_ID is not set +# CONFIG_GROUPS is not set +# CONFIG_INSTALL is not set +# CONFIG_FEATURE_INSTALL_LONG_OPTIONS is not set +# CONFIG_LINK is not set +CONFIG_LN=y +# CONFIG_LOGNAME is not set +CONFIG_LS=y +# CONFIG_FEATURE_LS_FILETYPES is not set +# CONFIG_FEATURE_LS_FOLLOWLINKS is not set +# CONFIG_FEATURE_LS_RECURSIVE is not set +CONFIG_FEATURE_LS_WIDTH=y +CONFIG_FEATURE_LS_SORTFILES=y +CONFIG_FEATURE_LS_TIMESTAMPS=y +# CONFIG_FEATURE_LS_USERNAME is not set +# CONFIG_FEATURE_LS_COLOR is not set +# CONFIG_FEATURE_LS_COLOR_IS_DEFAULT is not set +# CONFIG_MD5SUM is not set +# CONFIG_SHA1SUM is not set +# CONFIG_SHA256SUM is not set +# CONFIG_SHA512SUM is not set +# CONFIG_SHA3SUM is not set +# CONFIG_FEATURE_MD5_SHA1_SUM_CHECK is not set +CONFIG_MKDIR=y +# CONFIG_MKFIFO is not set +CONFIG_MKNOD=y +# CONFIG_MKTEMP is not set +CONFIG_MV=y +# CONFIG_NICE is not set +# CONFIG_NL is not set +# CONFIG_NOHUP is not set +# CONFIG_NPROC is not set +CONFIG_OD=y +# CONFIG_PASTE is not set +# CONFIG_PRINTENV is not set +# CONFIG_PRINTF is not set +CONFIG_PWD=y +# CONFIG_READLINK is not set +# CONFIG_FEATURE_READLINK_FOLLOW is not set +# CONFIG_REALPATH is not set +CONFIG_RM=y +CONFIG_RMDIR=y +# CONFIG_SEQ is not set +# CONFIG_SHRED is not set +# CONFIG_SHUF is not set +CONFIG_SLEEP=y +# CONFIG_FEATURE_FANCY_SLEEP is not set +# CONFIG_SORT is not set +# CONFIG_FEATURE_SORT_BIG is not set +# CONFIG_FEATURE_SORT_OPTIMIZE_MEMORY is not set +# CONFIG_SPLIT is not set +# CONFIG_FEATURE_SPLIT_FANCY is not set +# CONFIG_STAT is not set +# CONFIG_FEATURE_STAT_FORMAT is not set +# CONFIG_FEATURE_STAT_FILESYSTEM is not set +# CONFIG_STTY is not set +# CONFIG_SUM is not set +CONFIG_SYNC=y +# CONFIG_FEATURE_SYNC_FANCY is not set +# CONFIG_FSYNC is not set +# CONFIG_TAC is not set +# CONFIG_TAIL is not set +# CONFIG_FEATURE_FANCY_TAIL is not set +# CONFIG_TEE is not set +# CONFIG_FEATURE_TEE_USE_BLOCK_IO is not set +# CONFIG_TEST is not set +# CONFIG_TEST1 is not set +# CONFIG_TEST2 is not set +# CONFIG_FEATURE_TEST_64 is not set +# CONFIG_TIMEOUT is not set +CONFIG_TOUCH=y +# CONFIG_FEATURE_TOUCH_SUSV3 is not set +# CONFIG_TR is not set +# CONFIG_FEATURE_TR_CLASSES is not set +# CONFIG_FEATURE_TR_EQUIV is not set +# CONFIG_TRUE is not set +# CONFIG_TRUNCATE is not set +CONFIG_TSORT=y +# CONFIG_TTY is not set +CONFIG_UNAME=y +CONFIG_UNAME_OSNAME="GNU/Linux" +# CONFIG_BB_ARCH is not set +# CONFIG_UNIQ is not set +# CONFIG_UNLINK is not set +# CONFIG_USLEEP is not set +# CONFIG_UUDECODE is not set +# CONFIG_BASE32 is not set +# CONFIG_BASE64 is not set +# CONFIG_UUENCODE is not set +# CONFIG_WC is not set +# CONFIG_FEATURE_WC_LARGE is not set +# CONFIG_WHO is not set +# CONFIG_W is not set +# CONFIG_USERS is not set +# CONFIG_WHOAMI is not set +# CONFIG_YES is not set + +# +# Console Utilities +# +# CONFIG_CHVT is not set +# CONFIG_CLEAR is not set +# CONFIG_DEALLOCVT is not set +# CONFIG_DUMPKMAP is not set +# CONFIG_FGCONSOLE is not set +# CONFIG_KBD_MODE is not set +# CONFIG_LOADFONT is not set +# CONFIG_SETFONT is not set +# CONFIG_FEATURE_SETFONT_TEXTUAL_MAP is not set +CONFIG_DEFAULT_SETFONT_DIR="" +# CONFIG_FEATURE_LOADFONT_PSF2 is not set +# CONFIG_FEATURE_LOADFONT_RAW is not set +# CONFIG_LOADKMAP is not set +# CONFIG_OPENVT is not set +# CONFIG_RESET is not set +# CONFIG_RESIZE is not set +# CONFIG_FEATURE_RESIZE_PRINT is not set +# CONFIG_SETCONSOLE is not set +# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set +# CONFIG_SETKEYCODES is not set +# CONFIG_SETLOGCONS is not set +# CONFIG_SHOWKEY is not set + +# +# Debian Utilities +# +# CONFIG_PIPE_PROGRESS is not set +# CONFIG_RUN_PARTS is not set +# CONFIG_FEATURE_RUN_PARTS_LONG_OPTIONS is not set +# CONFIG_FEATURE_RUN_PARTS_FANCY is not set +# CONFIG_START_STOP_DAEMON is not set +# CONFIG_FEATURE_START_STOP_DAEMON_LONG_OPTIONS is not set +# CONFIG_FEATURE_START_STOP_DAEMON_FANCY is not set +CONFIG_WHICH=y + +# +# klibc-utils +# +# CONFIG_MINIPS is not set +# CONFIG_NUKE is not set +# CONFIG_RESUME is not set +# CONFIG_RUN_INIT is not set + +# +# Editors +# +# CONFIG_AWK is not set +# CONFIG_FEATURE_AWK_LIBM is not set +# CONFIG_FEATURE_AWK_GNU_EXTENSIONS is not set +# CONFIG_CMP is not set +# CONFIG_DIFF is not set +# CONFIG_FEATURE_DIFF_LONG_OPTIONS is not set +# CONFIG_FEATURE_DIFF_DIR is not set +# CONFIG_ED is not set +# CONFIG_PATCH is not set +# CONFIG_SED is not set +CONFIG_VI=y +CONFIG_FEATURE_VI_MAX_LEN=4096 +# CONFIG_FEATURE_VI_8BIT is not set +CONFIG_FEATURE_VI_COLON=y +CONFIG_FEATURE_VI_COLON_EXPAND=y +CONFIG_FEATURE_VI_YANKMARK=y +CONFIG_FEATURE_VI_SEARCH=y +# CONFIG_FEATURE_VI_REGEX_SEARCH is not set +CONFIG_FEATURE_VI_USE_SIGNALS=y +CONFIG_FEATURE_VI_DOT_CMD=y +# CONFIG_FEATURE_VI_READONLY is not set +# CONFIG_FEATURE_VI_SETOPTS is not set +# CONFIG_FEATURE_VI_SET is not set +CONFIG_FEATURE_VI_WIN_RESIZE=y +CONFIG_FEATURE_VI_ASK_TERMINAL=y +CONFIG_FEATURE_VI_UNDO=y +CONFIG_FEATURE_VI_UNDO_QUEUE=y +CONFIG_FEATURE_VI_UNDO_QUEUE_MAX=256 +CONFIG_FEATURE_VI_VERBOSE_STATUS=y +# CONFIG_FEATURE_ALLOW_EXEC is not set + +# +# Finding Utilities +# +CONFIG_FIND=y +CONFIG_FEATURE_FIND_PRINT0=y +CONFIG_FEATURE_FIND_MTIME=y +# CONFIG_FEATURE_FIND_ATIME is not set +# CONFIG_FEATURE_FIND_CTIME is not set +CONFIG_FEATURE_FIND_MMIN=y +# CONFIG_FEATURE_FIND_AMIN is not set +# CONFIG_FEATURE_FIND_CMIN is not set +CONFIG_FEATURE_FIND_PERM=y +CONFIG_FEATURE_FIND_TYPE=y +CONFIG_FEATURE_FIND_EXECUTABLE=y +CONFIG_FEATURE_FIND_XDEV=y +CONFIG_FEATURE_FIND_MAXDEPTH=y +CONFIG_FEATURE_FIND_NEWER=y +CONFIG_FEATURE_FIND_INUM=y +# CONFIG_FEATURE_FIND_SAMEFILE is not set +CONFIG_FEATURE_FIND_EXEC=y +CONFIG_FEATURE_FIND_EXEC_PLUS=y +CONFIG_FEATURE_FIND_EXEC_OK=y +CONFIG_FEATURE_FIND_USER=y +CONFIG_FEATURE_FIND_GROUP=y +CONFIG_FEATURE_FIND_NOT=y +CONFIG_FEATURE_FIND_DEPTH=y +CONFIG_FEATURE_FIND_PAREN=y +CONFIG_FEATURE_FIND_SIZE=y +CONFIG_FEATURE_FIND_PRUNE=y +CONFIG_FEATURE_FIND_QUIT=y +CONFIG_FEATURE_FIND_DELETE=y +CONFIG_FEATURE_FIND_EMPTY=y +CONFIG_FEATURE_FIND_PATH=y +CONFIG_FEATURE_FIND_REGEX=y +# CONFIG_FEATURE_FIND_CONTEXT is not set +CONFIG_FEATURE_FIND_LINKS=y +CONFIG_GREP=y +# CONFIG_EGREP is not set +# CONFIG_FGREP is not set +# CONFIG_FEATURE_GREP_CONTEXT is not set +# CONFIG_XARGS is not set +# CONFIG_FEATURE_XARGS_SUPPORT_CONFIRMATION is not set +# CONFIG_FEATURE_XARGS_SUPPORT_QUOTES is not set +# CONFIG_FEATURE_XARGS_SUPPORT_TERMOPT is not set +# CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM is not set +# CONFIG_FEATURE_XARGS_SUPPORT_REPL_STR is not set +# CONFIG_FEATURE_XARGS_SUPPORT_PARALLEL is not set +# CONFIG_FEATURE_XARGS_SUPPORT_ARGS_FILE is not set + +# +# Init Utilities +# +# CONFIG_BOOTCHARTD is not set +# CONFIG_FEATURE_BOOTCHARTD_BLOATED_HEADER is not set +# CONFIG_FEATURE_BOOTCHARTD_CONFIG_FILE is not set +CONFIG_HALT=y +CONFIG_POWEROFF=y +CONFIG_REBOOT=y +CONFIG_FEATURE_WAIT_FOR_INIT=y +# CONFIG_FEATURE_CALL_TELINIT is not set +CONFIG_TELINIT_PATH="" +CONFIG_INIT=y +# CONFIG_LINUXRC is not set +CONFIG_FEATURE_USE_INITTAB=y +CONFIG_FEATURE_KILL_REMOVED=y +CONFIG_FEATURE_KILL_DELAY=0 +# CONFIG_FEATURE_INIT_SCTTY is not set +# CONFIG_FEATURE_INIT_SYSLOG is not set +CONFIG_FEATURE_INIT_QUIET=y +# CONFIG_FEATURE_INIT_COREDUMPS is not set +CONFIG_INIT_TERMINAL_TYPE="linux" +# CONFIG_FEATURE_INIT_MODIFY_CMDLINE is not set + +# +# Login/Password Management Utilities +# +# CONFIG_FEATURE_SHADOWPASSWDS is not set +# CONFIG_USE_BB_PWD_GRP is not set +# CONFIG_USE_BB_SHADOW is not set +CONFIG_USE_BB_CRYPT=y +CONFIG_USE_BB_CRYPT_SHA=y +# CONFIG_ADD_SHELL is not set +# CONFIG_REMOVE_SHELL is not set +# CONFIG_ADDGROUP is not set +# CONFIG_FEATURE_ADDUSER_TO_GROUP is not set +# CONFIG_ADDUSER is not set +# CONFIG_FEATURE_CHECK_NAMES is not set +CONFIG_LAST_ID=0 +CONFIG_FIRST_SYSTEM_ID=0 +CONFIG_LAST_SYSTEM_ID=0 +# CONFIG_CHPASSWD is not set +CONFIG_FEATURE_DEFAULT_PASSWD_ALGO="" +# CONFIG_CRYPTPW is not set +# CONFIG_MKPASSWD is not set +# CONFIG_DELUSER is not set +# CONFIG_DELGROUP is not set +# CONFIG_FEATURE_DEL_USER_FROM_GROUP is not set +CONFIG_GETTY=y +# CONFIG_LOGIN is not set +# CONFIG_LOGIN_SESSION_AS_CHILD is not set +# CONFIG_LOGIN_SCRIPTS is not set +# CONFIG_FEATURE_NOLOGIN is not set +# CONFIG_FEATURE_SECURETTY is not set +# CONFIG_PASSWD is not set +# CONFIG_FEATURE_PASSWD_WEAK_CHECK is not set +# CONFIG_SU is not set +# CONFIG_FEATURE_SU_SYSLOG is not set +# CONFIG_FEATURE_SU_CHECKS_SHELLS is not set +# CONFIG_FEATURE_SU_BLANK_PW_NEEDS_SECURE_TTY is not set +# CONFIG_SULOGIN is not set +# CONFIG_VLOCK is not set + +# +# Linux Ext2 FS Progs +# +# CONFIG_CHATTR is not set +# CONFIG_FSCK is not set +# CONFIG_LSATTR is not set +# CONFIG_TUNE2FS is not set + +# +# Linux Module Utilities +# +# CONFIG_MODPROBE_SMALL is not set +# CONFIG_DEPMOD is not set +CONFIG_INSMOD=y +CONFIG_LSMOD=y +CONFIG_FEATURE_LSMOD_PRETTY_2_6_OUTPUT=y +CONFIG_MODINFO=y +CONFIG_MODPROBE=y +# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set +CONFIG_RMMOD=y + +# +# Options common to multiple modutils +# +# CONFIG_FEATURE_CMDLINE_MODULE_OPTIONS is not set +# CONFIG_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED is not set +# CONFIG_FEATURE_2_4_MODULES is not set +# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set +# CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS is not set +# CONFIG_FEATURE_INSMOD_LOADINKMEM is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP is not set +# CONFIG_FEATURE_INSMOD_LOAD_MAP_FULL is not set +# CONFIG_FEATURE_CHECK_TAINTED_MODULE is not set +# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set +CONFIG_FEATURE_MODUTILS_ALIAS=y +CONFIG_FEATURE_MODUTILS_SYMBOLS=y +CONFIG_DEFAULT_MODULES_DIR="/lib/modules" +CONFIG_DEFAULT_DEPMOD_FILE="modules.dep" + +# +# Linux System Utilities +# +# CONFIG_ACPID is not set +# CONFIG_FEATURE_ACPID_COMPAT is not set +# CONFIG_BLKDISCARD is not set +# CONFIG_BLKID is not set +# CONFIG_FEATURE_BLKID_TYPE is not set +# CONFIG_BLOCKDEV is not set +# CONFIG_CAL is not set +# CONFIG_CHRT is not set +CONFIG_DMESG=y +CONFIG_FEATURE_DMESG_PRETTY=y +# CONFIG_EJECT is not set +# CONFIG_FEATURE_EJECT_SCSI is not set +# CONFIG_FALLOCATE is not set +# CONFIG_FATATTR is not set +# CONFIG_FBSET is not set +# CONFIG_FEATURE_FBSET_FANCY is not set +# CONFIG_FEATURE_FBSET_READMODE is not set +# CONFIG_FDFORMAT is not set +# CONFIG_FDISK is not set +# CONFIG_FDISK_SUPPORT_LARGE_DISKS is not set +# CONFIG_FEATURE_FDISK_WRITABLE is not set +# CONFIG_FEATURE_AIX_LABEL is not set +# CONFIG_FEATURE_SGI_LABEL is not set +# CONFIG_FEATURE_SUN_LABEL is not set +# CONFIG_FEATURE_OSF_LABEL is not set +# CONFIG_FEATURE_GPT_LABEL is not set +# CONFIG_FEATURE_FDISK_ADVANCED is not set +# CONFIG_FINDFS is not set +# CONFIG_FLOCK is not set +# CONFIG_FDFLUSH is not set +# CONFIG_FREERAMDISK is not set +# CONFIG_FSCK_MINIX is not set +# CONFIG_FSFREEZE is not set +# CONFIG_FSTRIM is not set +# CONFIG_GETOPT is not set +# CONFIG_FEATURE_GETOPT_LONG is not set +# CONFIG_HEXDUMP is not set +# CONFIG_HD is not set +# CONFIG_XXD is not set +# CONFIG_HWCLOCK is not set +# CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS is not set +# CONFIG_IONICE is not set +# CONFIG_IPCRM is not set +# CONFIG_IPCS is not set +# CONFIG_LAST is not set +# CONFIG_FEATURE_LAST_FANCY is not set +# CONFIG_LOSETUP is not set +# CONFIG_LSPCI is not set +CONFIG_LSUSB=y +# CONFIG_MDEV is not set +# CONFIG_FEATURE_MDEV_CONF is not set +# CONFIG_FEATURE_MDEV_RENAME is not set +# CONFIG_FEATURE_MDEV_RENAME_REGEXP is not set +# CONFIG_FEATURE_MDEV_EXEC is not set +# CONFIG_FEATURE_MDEV_LOAD_FIRMWARE is not set +# CONFIG_FEATURE_MDEV_DAEMON is not set +# CONFIG_MESG is not set +# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set +# CONFIG_MKE2FS is not set +# CONFIG_MKFS_EXT2 is not set +# CONFIG_MKFS_MINIX is not set +# CONFIG_FEATURE_MINIX2 is not set +# CONFIG_MKFS_REISER is not set +# CONFIG_MKDOSFS is not set +# CONFIG_MKFS_VFAT is not set +# CONFIG_MKSWAP is not set +# CONFIG_FEATURE_MKSWAP_UUID is not set +CONFIG_MORE=y +CONFIG_MOUNT=y +# CONFIG_FEATURE_MOUNT_FAKE is not set +# CONFIG_FEATURE_MOUNT_VERBOSE is not set +# CONFIG_FEATURE_MOUNT_HELPERS is not set +# CONFIG_FEATURE_MOUNT_LABEL is not set +# CONFIG_FEATURE_MOUNT_NFS is not set +# CONFIG_FEATURE_MOUNT_CIFS is not set +CONFIG_FEATURE_MOUNT_FLAGS=y +CONFIG_FEATURE_MOUNT_FSTAB=y +# CONFIG_FEATURE_MOUNT_OTHERTAB is not set +# CONFIG_MOUNTPOINT is not set +# CONFIG_NOLOGIN is not set +# CONFIG_NOLOGIN_DEPENDENCIES is not set +# CONFIG_NSENTER is not set +# CONFIG_PIVOT_ROOT is not set +# CONFIG_RDATE is not set +# CONFIG_RDEV is not set +# CONFIG_READPROFILE is not set +# CONFIG_RENICE is not set +# CONFIG_REV is not set +# CONFIG_RTCWAKE is not set +# CONFIG_SCRIPT is not set +# CONFIG_SCRIPTREPLAY is not set +# CONFIG_SETARCH is not set +# CONFIG_LINUX32 is not set +# CONFIG_LINUX64 is not set +# CONFIG_SETPRIV is not set +# CONFIG_FEATURE_SETPRIV_DUMP is not set +# CONFIG_FEATURE_SETPRIV_CAPABILITIES is not set +# CONFIG_FEATURE_SETPRIV_CAPABILITY_NAMES is not set +# CONFIG_SETSID is not set +# CONFIG_SWAPON is not set +# CONFIG_FEATURE_SWAPON_DISCARD is not set +# CONFIG_FEATURE_SWAPON_PRI is not set +CONFIG_SWAPOFF=y +# CONFIG_FEATURE_SWAPONOFF_LABEL is not set +# CONFIG_SWITCH_ROOT is not set +# CONFIG_TASKSET is not set +# CONFIG_FEATURE_TASKSET_FANCY is not set +# CONFIG_FEATURE_TASKSET_CPULIST is not set +# CONFIG_UEVENT is not set +CONFIG_UMOUNT=y +CONFIG_FEATURE_UMOUNT_ALL=y +# CONFIG_UNSHARE is not set +# CONFIG_WALL is not set + +# +# Common options for mount/umount +# +# CONFIG_FEATURE_MOUNT_LOOP is not set +# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set +# CONFIG_FEATURE_MTAB_SUPPORT is not set +# CONFIG_VOLUMEID is not set +# CONFIG_FEATURE_VOLUMEID_BCACHE is not set +# CONFIG_FEATURE_VOLUMEID_BTRFS is not set +# CONFIG_FEATURE_VOLUMEID_CRAMFS is not set +# CONFIG_FEATURE_VOLUMEID_EROFS is not set +# CONFIG_FEATURE_VOLUMEID_EXFAT is not set +# CONFIG_FEATURE_VOLUMEID_EXT is not set +# CONFIG_FEATURE_VOLUMEID_F2FS is not set +# CONFIG_FEATURE_VOLUMEID_FAT is not set +# CONFIG_FEATURE_VOLUMEID_HFS is not set +# CONFIG_FEATURE_VOLUMEID_ISO9660 is not set +# CONFIG_FEATURE_VOLUMEID_JFS is not set +# CONFIG_FEATURE_VOLUMEID_LFS is not set +# CONFIG_FEATURE_VOLUMEID_LINUXRAID is not set +# CONFIG_FEATURE_VOLUMEID_LINUXSWAP is not set +# CONFIG_FEATURE_VOLUMEID_LUKS is not set +# CONFIG_FEATURE_VOLUMEID_MINIX is not set +# CONFIG_FEATURE_VOLUMEID_NILFS is not set +# CONFIG_FEATURE_VOLUMEID_NTFS is not set +# CONFIG_FEATURE_VOLUMEID_OCFS2 is not set +# CONFIG_FEATURE_VOLUMEID_REISERFS is not set +# CONFIG_FEATURE_VOLUMEID_ROMFS is not set +# CONFIG_FEATURE_VOLUMEID_SQUASHFS is not set +# CONFIG_FEATURE_VOLUMEID_SYSV is not set +# CONFIG_FEATURE_VOLUMEID_UBIFS is not set +# CONFIG_FEATURE_VOLUMEID_UDF is not set +# CONFIG_FEATURE_VOLUMEID_XFS is not set + +# +# Miscellaneous Utilities +# +# CONFIG_ADJTIMEX is not set +# CONFIG_ASCII is not set +# CONFIG_BBCONFIG is not set +# CONFIG_FEATURE_COMPRESS_BBCONFIG is not set +# CONFIG_BC is not set +# CONFIG_DC is not set +# CONFIG_FEATURE_DC_BIG is not set +# CONFIG_FEATURE_DC_LIBM is not set +# CONFIG_FEATURE_BC_INTERACTIVE is not set +# CONFIG_FEATURE_BC_LONG_OPTIONS is not set +# CONFIG_BEEP is not set +CONFIG_FEATURE_BEEP_FREQ=0 +CONFIG_FEATURE_BEEP_LENGTH_MS=0 +# CONFIG_CHAT is not set +# CONFIG_FEATURE_CHAT_NOFAIL is not set +# CONFIG_FEATURE_CHAT_TTY_HIFI is not set +# CONFIG_FEATURE_CHAT_IMPLICIT_CR is not set +# CONFIG_FEATURE_CHAT_SWALLOW_OPTS is not set +# CONFIG_FEATURE_CHAT_SEND_ESCAPES is not set +# CONFIG_FEATURE_CHAT_VAR_ABORT_LEN is not set +# CONFIG_FEATURE_CHAT_CLR_ABORT is not set +# CONFIG_CONSPY is not set +# CONFIG_CROND is not set +# CONFIG_FEATURE_CROND_D is not set +# CONFIG_FEATURE_CROND_CALL_SENDMAIL is not set +# CONFIG_FEATURE_CROND_SPECIAL_TIMES is not set +CONFIG_FEATURE_CROND_DIR="" +# CONFIG_CRONTAB is not set +# CONFIG_DEVFSD is not set +# CONFIG_DEVFSD_MODLOAD is not set +# CONFIG_DEVFSD_FG_NP is not set +# CONFIG_DEVFSD_VERBOSE is not set +# CONFIG_FEATURE_DEVFS is not set +# CONFIG_DEVMEM is not set +# CONFIG_FBSPLASH is not set +# CONFIG_FLASH_ERASEALL is not set +# CONFIG_FLASH_LOCK is not set +# CONFIG_FLASH_UNLOCK is not set +# CONFIG_FLASHCP is not set +CONFIG_GETFATTR=y +# CONFIG_HDPARM is not set +# CONFIG_FEATURE_HDPARM_GET_IDENTITY is not set +# CONFIG_FEATURE_HDPARM_HDIO_SCAN_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_UNREGISTER_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_DRIVE_RESET is not set +# CONFIG_FEATURE_HDPARM_HDIO_TRISTATE_HWIF is not set +# CONFIG_FEATURE_HDPARM_HDIO_GETSET_DMA is not set +# CONFIG_HEXEDIT is not set +# CONFIG_I2CGET is not set +# CONFIG_I2CSET is not set +# CONFIG_I2CDUMP is not set +CONFIG_I2CDETECT=y +# CONFIG_I2CTRANSFER is not set +# CONFIG_INOTIFYD is not set +# CONFIG_LESS is not set +CONFIG_FEATURE_LESS_MAXLINES=0 +# CONFIG_FEATURE_LESS_BRACKETS is not set +# CONFIG_FEATURE_LESS_FLAGS is not set +# CONFIG_FEATURE_LESS_TRUNCATE is not set +# CONFIG_FEATURE_LESS_MARKS is not set +# CONFIG_FEATURE_LESS_REGEXP is not set +# CONFIG_FEATURE_LESS_WINCH is not set +# CONFIG_FEATURE_LESS_ASK_TERMINAL is not set +# CONFIG_FEATURE_LESS_DASHCMD is not set +# CONFIG_FEATURE_LESS_LINENUMS is not set +# CONFIG_FEATURE_LESS_RAW is not set +# CONFIG_FEATURE_LESS_ENV is not set +# CONFIG_LSSCSI is not set +# CONFIG_MAKEDEVS is not set +# CONFIG_FEATURE_MAKEDEVS_LEAF is not set +# CONFIG_FEATURE_MAKEDEVS_TABLE is not set +# CONFIG_MAN is not set +# CONFIG_MICROCOM is not set +# CONFIG_MIM is not set +# CONFIG_MT is not set +# CONFIG_NANDWRITE is not set +# CONFIG_NANDDUMP is not set +# CONFIG_PARTPROBE is not set +# CONFIG_RAIDAUTORUN is not set +# CONFIG_READAHEAD is not set +# CONFIG_RFKILL is not set +# CONFIG_RUNLEVEL is not set +# CONFIG_RX is not set +CONFIG_SEEDRNG=y +# CONFIG_SETFATTR is not set +# CONFIG_SETSERIAL is not set +# CONFIG_STRINGS is not set +# CONFIG_TIME is not set +CONFIG_TREE=y +# CONFIG_TS is not set +# CONFIG_TTYSIZE is not set +# CONFIG_UBIATTACH is not set +# CONFIG_UBIDETACH is not set +# CONFIG_UBIMKVOL is not set +# CONFIG_UBIRMVOL is not set +# CONFIG_UBIRSVOL is not set +# CONFIG_UBIUPDATEVOL is not set +# CONFIG_UBIRENAME is not set +# CONFIG_VOLNAME is not set +# CONFIG_WATCHDOG is not set +# CONFIG_FEATURE_WATCHDOG_OPEN_TWICE is not set + +# +# Networking Utilities +# +# CONFIG_FEATURE_IPV6 is not set +# CONFIG_FEATURE_UNIX_LOCAL is not set +# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set +# CONFIG_VERBOSE_RESOLUTION_ERRORS is not set +# CONFIG_FEATURE_ETC_NETWORKS is not set +# CONFIG_FEATURE_ETC_SERVICES is not set +# CONFIG_FEATURE_HWIB is not set +# CONFIG_FEATURE_TLS_SHA1 is not set +# CONFIG_ARP is not set +# CONFIG_ARPING is not set +# CONFIG_BRCTL is not set +# CONFIG_FEATURE_BRCTL_FANCY is not set +# CONFIG_FEATURE_BRCTL_SHOW is not set +# CONFIG_DNSD is not set +# CONFIG_ETHER_WAKE is not set +# CONFIG_FTPD is not set +# CONFIG_FEATURE_FTPD_WRITE is not set +# CONFIG_FEATURE_FTPD_ACCEPT_BROKEN_LIST is not set +# CONFIG_FEATURE_FTPD_AUTHENTICATION is not set +# CONFIG_FTPGET is not set +# CONFIG_FTPPUT is not set +# CONFIG_FEATURE_FTPGETPUT_LONG_OPTIONS is not set +# CONFIG_HOSTNAME is not set +# CONFIG_DNSDOMAINNAME is not set +CONFIG_HTTPD=y +CONFIG_FEATURE_HTTPD_PORT_DEFAULT=80 +# CONFIG_FEATURE_HTTPD_RANGES is not set +# CONFIG_FEATURE_HTTPD_SETUID is not set +# CONFIG_FEATURE_HTTPD_BASIC_AUTH is not set +# CONFIG_FEATURE_HTTPD_AUTH_MD5 is not set +CONFIG_FEATURE_HTTPD_CGI=y +# CONFIG_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR is not set +# CONFIG_FEATURE_HTTPD_SET_REMOTE_PORT_TO_ENV is not set +# CONFIG_FEATURE_HTTPD_ENCODE_URL_STR is not set +# CONFIG_FEATURE_HTTPD_ERROR_PAGES is not set +# CONFIG_FEATURE_HTTPD_PROXY is not set +# CONFIG_FEATURE_HTTPD_GZIP is not set +# CONFIG_FEATURE_HTTPD_ETAG is not set +# CONFIG_FEATURE_HTTPD_LAST_MODIFIED is not set +# CONFIG_FEATURE_HTTPD_DATE is not set +# CONFIG_FEATURE_HTTPD_ACL_IP is not set +CONFIG_IFCONFIG=y +CONFIG_FEATURE_IFCONFIG_STATUS=y +# CONFIG_FEATURE_IFCONFIG_SLIP is not set +# CONFIG_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ is not set +# CONFIG_FEATURE_IFCONFIG_HW is not set +CONFIG_FEATURE_IFCONFIG_BROADCAST_PLUS=y +# CONFIG_IFENSLAVE is not set +# CONFIG_IFPLUGD is not set +# CONFIG_IFUP is not set +# CONFIG_IFDOWN is not set +CONFIG_IFUPDOWN_IFSTATE_PATH="" +# CONFIG_FEATURE_IFUPDOWN_IP is not set +# CONFIG_FEATURE_IFUPDOWN_IPV4 is not set +# CONFIG_FEATURE_IFUPDOWN_IPV6 is not set +# CONFIG_FEATURE_IFUPDOWN_MAPPING is not set +# CONFIG_FEATURE_IFUPDOWN_EXTERNAL_DHCP is not set +# CONFIG_INETD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME is not set +# CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN is not set +# CONFIG_FEATURE_INETD_RPC is not set +# CONFIG_IP is not set +# CONFIG_IPADDR is not set +# CONFIG_IPLINK is not set +# CONFIG_IPROUTE is not set +# CONFIG_IPTUNNEL is not set +# CONFIG_IPRULE is not set +# CONFIG_IPNEIGH is not set +# CONFIG_FEATURE_IP_ADDRESS is not set +# CONFIG_FEATURE_IP_LINK is not set +CONFIG_FEATURE_IP_LINK_CAN=y +# CONFIG_FEATURE_IP_ROUTE is not set +CONFIG_FEATURE_IP_ROUTE_DIR="" +# CONFIG_FEATURE_IP_TUNNEL is not set +# CONFIG_FEATURE_IP_RULE is not set +# CONFIG_FEATURE_IP_NEIGH is not set +# CONFIG_FEATURE_IP_RARE_PROTOCOLS is not set +# CONFIG_IPCALC is not set +# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set +# CONFIG_FEATURE_IPCALC_FANCY is not set +# CONFIG_FAKEIDENTD is not set +# CONFIG_NAMEIF is not set +# CONFIG_FEATURE_NAMEIF_EXTENDED is not set +# CONFIG_NBDCLIENT is not set +# CONFIG_NC is not set +# CONFIG_NETCAT is not set +# CONFIG_NC_SERVER is not set +# CONFIG_NC_EXTRA is not set +# CONFIG_NC_110_COMPAT is not set +# CONFIG_NETSTAT is not set +# CONFIG_FEATURE_NETSTAT_WIDE is not set +# CONFIG_FEATURE_NETSTAT_PRG is not set +# CONFIG_NSLOOKUP is not set +# CONFIG_FEATURE_NSLOOKUP_BIG is not set +# CONFIG_FEATURE_NSLOOKUP_LONG_OPTIONS is not set +# CONFIG_NTPD is not set +# CONFIG_FEATURE_NTPD_SERVER is not set +# CONFIG_FEATURE_NTPD_CONF is not set +# CONFIG_FEATURE_NTP_AUTH is not set +CONFIG_PING=y +# CONFIG_PING6 is not set +CONFIG_FEATURE_FANCY_PING=y +# CONFIG_PSCAN is not set +# CONFIG_ROUTE is not set +# CONFIG_SLATTACH is not set +# CONFIG_SSL_CLIENT is not set +# CONFIG_TC is not set +# CONFIG_FEATURE_TC_INGRESS is not set +# CONFIG_TCPSVD is not set +# CONFIG_UDPSVD is not set +# CONFIG_TELNET is not set +# CONFIG_FEATURE_TELNET_TTYPE is not set +# CONFIG_FEATURE_TELNET_AUTOLOGIN is not set +# CONFIG_FEATURE_TELNET_WIDTH is not set +# CONFIG_TELNETD is not set +# CONFIG_FEATURE_TELNETD_STANDALONE is not set +CONFIG_FEATURE_TELNETD_PORT_DEFAULT=0 +# CONFIG_FEATURE_TELNETD_INETD_WAIT is not set +# CONFIG_TFTP is not set +# CONFIG_FEATURE_TFTP_PROGRESS_BAR is not set +# CONFIG_FEATURE_TFTP_HPA_COMPAT is not set +# CONFIG_TFTPD is not set +# CONFIG_FEATURE_TFTP_GET is not set +# CONFIG_FEATURE_TFTP_PUT is not set +# CONFIG_FEATURE_TFTP_BLOCKSIZE is not set +# CONFIG_TFTP_DEBUG is not set +# CONFIG_TLS is not set +# CONFIG_TRACEROUTE is not set +# CONFIG_TRACEROUTE6 is not set +# CONFIG_FEATURE_TRACEROUTE_VERBOSE is not set +# CONFIG_FEATURE_TRACEROUTE_USE_ICMP is not set +# CONFIG_TUNCTL is not set +# CONFIG_FEATURE_TUNCTL_UG is not set +# CONFIG_VCONFIG is not set +# CONFIG_WGET is not set +# CONFIG_FEATURE_WGET_LONG_OPTIONS is not set +# CONFIG_FEATURE_WGET_STATUSBAR is not set +# CONFIG_FEATURE_WGET_FTP is not set +# CONFIG_FEATURE_WGET_AUTHENTICATION is not set +# CONFIG_FEATURE_WGET_TIMEOUT is not set +# CONFIG_FEATURE_WGET_HTTPS is not set +# CONFIG_FEATURE_WGET_OPENSSL is not set +# CONFIG_WHOIS is not set +# CONFIG_ZCIP is not set +# CONFIG_UDHCPD is not set +# CONFIG_FEATURE_UDHCPD_BOOTP is not set +# CONFIG_FEATURE_UDHCPD_BASE_IP_ON_MAC is not set +# CONFIG_FEATURE_UDHCPD_WRITE_LEASES_EARLY is not set +CONFIG_DHCPD_LEASES_FILE="" +# CONFIG_DUMPLEASES is not set +# CONFIG_DHCPRELAY is not set +# CONFIG_UDHCPC is not set +# CONFIG_FEATURE_UDHCPC_ARPING is not set +# CONFIG_FEATURE_UDHCPC_SANITIZEOPT is not set +CONFIG_UDHCPC_DEFAULT_SCRIPT="" +CONFIG_UDHCPC6_DEFAULT_SCRIPT="" +# CONFIG_UDHCPC6 is not set +# CONFIG_FEATURE_UDHCPC6_RFC3646 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4704 is not set +# CONFIG_FEATURE_UDHCPC6_RFC4833 is not set +# CONFIG_FEATURE_UDHCPC6_RFC5970 is not set +CONFIG_UDHCPC_DEFAULT_INTERFACE="" +# CONFIG_FEATURE_UDHCP_PORT is not set +CONFIG_UDHCP_DEBUG=0 +CONFIG_UDHCPC_SLACK_FOR_BUGGY_SERVERS=0 +# CONFIG_FEATURE_UDHCP_RFC3397 is not set +# CONFIG_FEATURE_UDHCP_8021Q is not set +CONFIG_IFUPDOWN_UDHCPC_CMD_OPTIONS="" + +# +# Print Utilities +# +# CONFIG_LPD is not set +# CONFIG_LPR is not set +# CONFIG_LPQ is not set + +# +# Mail Utilities +# +CONFIG_FEATURE_MIME_CHARSET="" +# CONFIG_MAKEMIME is not set +# CONFIG_POPMAILDIR is not set +# CONFIG_FEATURE_POPMAILDIR_DELIVERY is not set +# CONFIG_REFORMIME is not set +# CONFIG_FEATURE_REFORMIME_COMPAT is not set +# CONFIG_SENDMAIL is not set + +# +# Process Utilities +# +# CONFIG_FEATURE_FAST_TOP is not set +CONFIG_FEATURE_SHOW_THREADS=y +# CONFIG_FREE is not set +# CONFIG_FUSER is not set +# CONFIG_IOSTAT is not set +CONFIG_KILL=y +# CONFIG_KILLALL is not set +# CONFIG_KILLALL5 is not set +# CONFIG_LSOF is not set +# CONFIG_MPSTAT is not set +# CONFIG_NMETER is not set +# CONFIG_PGREP is not set +# CONFIG_PKILL is not set +# CONFIG_PIDOF is not set +# CONFIG_FEATURE_PIDOF_SINGLE is not set +# CONFIG_FEATURE_PIDOF_OMIT is not set +# CONFIG_PMAP is not set +# CONFIG_POWERTOP is not set +# CONFIG_FEATURE_POWERTOP_INTERACTIVE is not set +CONFIG_PS=y +# CONFIG_FEATURE_PS_WIDE is not set +CONFIG_FEATURE_PS_LONG=y +# CONFIG_FEATURE_PS_TIME is not set +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set +# CONFIG_FEATURE_PS_ADDITIONAL_COLUMNS is not set +# CONFIG_PSTREE is not set +# CONFIG_PWDX is not set +# CONFIG_SMEMCAP is not set +# CONFIG_BB_SYSCTL is not set +CONFIG_TOP=y +# CONFIG_FEATURE_TOP_INTERACTIVE is not set +CONFIG_FEATURE_TOP_CPU_USAGE_PERCENTAGE=y +CONFIG_FEATURE_TOP_CPU_GLOBAL_PERCENTS=y +CONFIG_FEATURE_TOP_SMP_CPU=y +CONFIG_FEATURE_TOP_DECIMALS=y +CONFIG_FEATURE_TOP_SMP_PROCESS=y +CONFIG_FEATURE_TOPMEM=y +CONFIG_UPTIME=y +# CONFIG_FEATURE_UPTIME_UTMP_SUPPORT is not set +# CONFIG_WATCH is not set + +# +# Runit Utilities +# +# CONFIG_CHPST is not set +# CONFIG_SETUIDGID is not set +# CONFIG_ENVUIDGID is not set +# CONFIG_ENVDIR is not set +# CONFIG_SOFTLIMIT is not set +# CONFIG_RUNSV is not set +# CONFIG_RUNSVDIR is not set +# CONFIG_FEATURE_RUNSVDIR_LOG is not set +# CONFIG_SV is not set +CONFIG_SV_DEFAULT_SERVICE_DIR="" +# CONFIG_SVC is not set +# CONFIG_SVOK is not set +# CONFIG_SVLOGD is not set +# CONFIG_CHCON is not set +# CONFIG_GETENFORCE is not set +# CONFIG_GETSEBOOL is not set +# CONFIG_LOAD_POLICY is not set +# CONFIG_MATCHPATHCON is not set +# CONFIG_RUNCON is not set +# CONFIG_SELINUXENABLED is not set +# CONFIG_SESTATUS is not set +# CONFIG_SETENFORCE is not set +# CONFIG_SETFILES is not set +# CONFIG_FEATURE_SETFILES_CHECK_OPTION is not set +# CONFIG_RESTORECON is not set +# CONFIG_SETSEBOOL is not set + +# +# Shells +# +CONFIG_SH_IS_ASH=y +# CONFIG_SH_IS_HUSH is not set +# CONFIG_SH_IS_NONE is not set +# CONFIG_BASH_IS_ASH is not set +# CONFIG_BASH_IS_HUSH is not set +CONFIG_BASH_IS_NONE=y +CONFIG_SHELL_ASH=y +CONFIG_ASH=y +CONFIG_ASH_OPTIMIZE_FOR_SIZE=y +CONFIG_ASH_INTERNAL_GLOB=y +CONFIG_ASH_BASH_COMPAT=y +# CONFIG_ASH_BASH_SOURCE_CURDIR is not set +# CONFIG_ASH_BASH_NOT_FOUND_HOOK is not set +CONFIG_ASH_JOB_CONTROL=y +# CONFIG_ASH_ALIAS is not set +# CONFIG_ASH_RANDOM_SUPPORT is not set +# CONFIG_ASH_EXPAND_PRMT is not set +# CONFIG_ASH_IDLE_TIMEOUT is not set +# CONFIG_ASH_MAIL is not set +CONFIG_ASH_ECHO=y +# CONFIG_ASH_PRINTF is not set +CONFIG_ASH_TEST=y +CONFIG_ASH_HELP=y +# CONFIG_ASH_GETOPTS is not set +# CONFIG_ASH_CMDCMD is not set +# CONFIG_CTTYHACK is not set +# CONFIG_HUSH is not set +# CONFIG_SHELL_HUSH is not set +# CONFIG_HUSH_BASH_COMPAT is not set +# CONFIG_HUSH_BRACE_EXPANSION is not set +# CONFIG_HUSH_BASH_SOURCE_CURDIR is not set +# CONFIG_HUSH_LINENO_VAR is not set +# CONFIG_HUSH_INTERACTIVE is not set +# CONFIG_HUSH_SAVEHISTORY is not set +# CONFIG_HUSH_JOB is not set +# CONFIG_HUSH_TICK is not set +# CONFIG_HUSH_IF is not set +# CONFIG_HUSH_LOOPS is not set +# CONFIG_HUSH_CASE is not set +# CONFIG_HUSH_FUNCTIONS is not set +# CONFIG_HUSH_LOCAL is not set +# CONFIG_HUSH_RANDOM_SUPPORT is not set +# CONFIG_HUSH_MODE_X is not set +# CONFIG_HUSH_ECHO is not set +# CONFIG_HUSH_PRINTF is not set +# CONFIG_HUSH_TEST is not set +# CONFIG_HUSH_HELP is not set +# CONFIG_HUSH_EXPORT is not set +# CONFIG_HUSH_EXPORT_N is not set +# CONFIG_HUSH_READONLY is not set +# CONFIG_HUSH_KILL is not set +# CONFIG_HUSH_WAIT is not set +# CONFIG_HUSH_COMMAND is not set +# CONFIG_HUSH_TRAP is not set +# CONFIG_HUSH_TYPE is not set +# CONFIG_HUSH_TIMES is not set +# CONFIG_HUSH_READ is not set +# CONFIG_HUSH_SET is not set +# CONFIG_HUSH_UNSET is not set +# CONFIG_HUSH_ULIMIT is not set +# CONFIG_HUSH_UMASK is not set +# CONFIG_HUSH_GETOPTS is not set +# CONFIG_HUSH_MEMLEAK is not set + +# +# Options common to all shells +# +# CONFIG_FEATURE_SH_MATH is not set +# CONFIG_FEATURE_SH_MATH_64 is not set +# CONFIG_FEATURE_SH_MATH_BASE is not set +# CONFIG_FEATURE_SH_EXTRA_QUIET is not set +# CONFIG_FEATURE_SH_STANDALONE is not set +# CONFIG_FEATURE_SH_NOFORK is not set +# CONFIG_FEATURE_SH_READ_FRAC is not set +CONFIG_FEATURE_SH_HISTFILESIZE=y +CONFIG_FEATURE_SH_EMBEDDED_SCRIPTS=y + +# +# System Logging Utilities +# +# CONFIG_KLOGD is not set +# CONFIG_FEATURE_KLOGD_KLOGCTL is not set +# CONFIG_LOGGER is not set +# CONFIG_LOGREAD is not set +# CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING is not set +# CONFIG_SYSLOGD is not set +# CONFIG_FEATURE_ROTATE_LOGFILE is not set +# CONFIG_FEATURE_REMOTE_LOG is not set +# CONFIG_FEATURE_SYSLOGD_DUP is not set +# CONFIG_FEATURE_SYSLOGD_CFG is not set +# CONFIG_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS is not set +CONFIG_FEATURE_SYSLOGD_READ_BUFFER_SIZE=0 +# CONFIG_FEATURE_IPC_SYSLOG is not set +CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE=0 +# CONFIG_FEATURE_KMSG_SYSLOG is not set diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/hello.c b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/hello.c new file mode 100644 index 0000000000..22e78e7fe7 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/hello.c @@ -0,0 +1,8 @@ +#include +#include + +int main (void) +{ + printf( "Hello world!\n" ); + return EXIT_SUCCESS; +} diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/cpuinfo b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/cpuinfo new file mode 100755 index 0000000000..895422b465 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/cpuinfo @@ -0,0 +1,10 @@ +#!/bin/sh +echo "Content-type: text/html" +echo +echo "
" +echo "

CPU information

" +echo "Your embedded device uses the below processor:
"
+echo " "`cat /proc/cpuinfo | grep "model name" | while read cpu; do echo "$cpu 

"; done` +echo "

" +echo "

" +echo "" diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/list b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/list new file mode 100755 index 0000000000..0a1dd24c08 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/list @@ -0,0 +1,22 @@ +#!/bin/sh +echo "Content-type: text/html" +echo + +UPLOAD_DIR="/www/upload/files" +URL_PATH="/upload/files" + +echo "" +echo "

" +echo "

File collection

" +echo "

" + +cd $UPLOAD_DIR +for f in * +do +echo "\"$f\"" +done + +echo "

" + +echo "

" +echo "" diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/reboot b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/reboot new file mode 100755 index 0000000000..b98e29ee4d --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/reboot @@ -0,0 +1,11 @@ +#!/bin/sh +# Reboots the system +echo "Content-type: text/html" +echo +echo "
" +echo "

Rebooting the system

" +echo "" +echo "System reboot initiated" +echo "" +echo "" +reboot diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload new file mode 100755 index 0000000000..34584dedaa Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload differ diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload.c b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload.c new file mode 100644 index 0000000000..65d3f5603b --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload.c @@ -0,0 +1,963 @@ +/* + + upload.exe -- Upload a file to a server using forms. + + + DESCRIPTION + + This is a CGI program to upload one or more files to a WWW + server, using standard HTML forms instead of FTP. It works with + Netscape 3.0 and 4.0, and Internet Explorer 4.0. + + See the manpage for more information. + + AUTHOR + + Jeroen C. Kessels + Internet Engineer + mailto:jeroen@kessels.com http://www.kessels.com/ + Tel: +31(0)654 744 702 + + + COPYRIGHT + + Jeroen C. Kessels + 9 december 2000 + + + VERSION 2.6 + +*/ + + + + +#include +#include +#include +#include +#ifdef unix +#include +#else +#include +#ifdef _MSC_VER +#include +#else +#include +#endif +#endif +#include + + + + +#ifdef unix +#define stricmp strcasecmp +#define strnicmp strncasecmp +#endif + + + +#define COPYRIGHT "
Upload v2.6
© 2000 Jeroen C. Kessels
\n
" +#define NO 0 +#define YES 1 +#define MUST 2 + + + +/* Define DIRSEP, the character that will be used to separate directories. */ +#ifdef unix +#define DIRSEP "/\\" +#else +#define DIRSEP "\\/" +#endif + + + + +/* Configuration parameters from the configuration file. */ +char Root[BUFSIZ]; +char FileMask[BUFSIZ]; +int IgnoreSubdirs; +int OverWrite; +char LogFile[BUFSIZ]; +char OkPage[BUFSIZ]; +char OkUrl[BUFSIZ]; +char BadPage[BUFSIZ]; +char BadUrl[BUFSIZ]; + +char UpFileName[BUFSIZ]; +int Debug; + +long FileCount; +long ByteCount; +char LastFileName[BUFSIZ]; + + + + +/* Translate character to lowercase. */ +char clower(char c) { + if ((c >= 'A') && (c <= 'Z')) return((c - 'A') + 'a'); + return(c); + } + + + + +/* Compare a string with a mask, case-insensitive. If it matches then return + YES, otherwise NO. The mask may contain wildcard characters '?' (any + character) '*' (any characters). */ +int MatchMask(char *String, char *Mask) { + char *m; + char *s; + + if (String == NULL) return NO; /* Just to speed up things. */ + if (Mask == NULL) return NO; + if (strcmp(Mask,"*") == 0) return YES; + + m = Mask; + s = String; + + while ((*m != '\0') && (*s != '\0')) { + if ((clower(*m) != clower(*s)) && (*m != '?')) { + if (*m != '*') return NO; + m++; + if (*m == '\0') return YES; + while (*s != '\0') { + if (MatchMask(s,m) == YES) return YES; + s++; + } + return NO; + } + m++; + s++; + } + + while (*m == '*') m++; + if ((*s == '\0') && (*m == '\0')) return YES; + return NO; + } + + + + + +/* Translate the URL separator '/' into the directory separator ('/' for + UNIX, '\\' for DOS), making a proper pathname. */ +void Url2Dir(char *Dir, char *Url) { + char *p1; + char *p2; + + p1 = Url; + p2 = Dir; + while (*p1 != '\0') { + if (*p1 == '/') { + *p2++ = *DIRSEP; + p1++; + } else { + *p2++ = *p1++; + } + } + *p2 = '\0'; + } + + + + +/* Return the last position in a string of any character from + collection. The haystack string is scanned from end to begin until a + character is found from the needle string. The pointer to the found + character is returned, or NULL if not found. This subroutine is + designed to find a directory separator in a path, where the directory + separator can be '\\' (DOS) or '/' (UNIX). */ +char *strrchrs(char *haystack,char *needle) { + char *h_here; + char *n_here; + long h_length; + + if ((haystack == NULL) || (needle == NULL)) return(NULL); + + for (h_length = 0, h_here = haystack; *h_here != '\0'; h_here++, h_length++); + while (h_length > 0) { + h_here--; + h_length--; + n_here = needle; + while (*n_here != '\0') { + if (*n_here == *h_here) return(h_here); + n_here++; + } + } + + return(NULL); + } + + + + + +/* Create all directories in the path. The permissions of the directory at + From are used for the new directory, leave NULL for default permissions. + If IsAdir=NO then the path points to a filename, otherwise it is a + directoryname. */ +void CreatePath(char *To, char *From, int IsAdir) { +#ifdef unix + struct stat statbuf; +#endif + char s1[BUFSIZ]; + char s2[BUFSIZ]; + char *p1; + + if (To == NULL) return; + + /* If the Path contains subdirectories, then strip the last directory and + iterate. */ + strcpy(s1,To); + if (From != NULL) { + strcpy(s2,From); + } else { + *s2 ='\0'; + } + p1 = strrchrs(s1,DIRSEP); + if (p1 != NULL) { + *p1 = '\0'; + p1 = strrchrs(s2,DIRSEP); + if (p1 == NULL) p1 = s2; + *p1 = '\0'; + CreatePath(s1,s2,YES); + } + + /* Create the directory. */ + if (IsAdir == YES) { +#ifdef unix + if ((From != NULL) && (*From != '\0') && (stat(From,&statbuf) == 0)) { + mkdir(To,statbuf.st_mode & 0777); + } else { + mkdir(To,0755); + } +#else + if ((strlen(To) > 2) || (To[1] != ':')) mkdir(To); +#endif + } + } + + + + + +/* Show the BadPage, with macro MESSAGE. */ +void ShowBadPage(char *Message) { + FILE *Fin; + char Line[BUFSIZ]; + char s1[BUFSIZ]; + char *p1; + + if (*BadUrl != '\0') { + fprintf(stdout,"Location: %s\n\n",BadUrl); + return; + } + + if (Debug == 0) fprintf(stdout,"Content-type: text/html\n\n"); + + Fin = fopen(BadPage,"r"); + if (Fin == NULL) { + fprintf(stdout,"\n\n",Message); + if (*BadPage != '\0') { + fprintf(stdout,"Error: could not open the BadPage: %s

\n",BadPage); + fprintf(stdout,"The original error message was:
\n"); + } + fprintf(stdout,"%s\n",Message); + fprintf(stdout,"\n\n",Message); + exit(0); + } + + while (fgets(Line,BUFSIZ,Fin) != NULL) { + p1 = Line; + while (*p1 != '\0') { + if (strnicmp(p1,"",15) == 0) { + *p1 = '\0'; + sprintf(s1,"%s%s%s",Line,Message,p1 + 16); + strcpy(Line,s1); + } + p1++; + } + fprintf(stdout,"%s",Line); + } + + exit(0); + } + + + + +/* Write a line to the logging file. */ +void WriteLogLine(char *Line) { + FILE *Fout; + char s1[BUFSIZ]; + time_t Now; + + if (*LogFile == '\0') return; + + Fout = fopen(LogFile,"a"); + if (Fout == NULL) { + sprintf(s1,"I could not open the logfile: %s",LogFile); + ShowBadPage(s1); + } + Now = time(NULL); + strcpy(s1,ctime(&Now)); + s1[24] = '\0'; + fprintf(Fout,"%s %s\n",s1,Line); + fclose(Fout); + } + + + + +/* Show the OkPage, with statistics about the file. */ +void ShowOkPage(void) { + FILE *Fin; + char Line[BUFSIZ]; + char s1[BUFSIZ]; + char *p1; + + if (*OkUrl != '\0') { + fprintf(stdout,"Location: %s\n\n",OkUrl); + return; + } + + Fin = fopen(OkPage,"r"); + if (Fin == NULL) { + sprintf(s1,"I could not open the OkPage: %s",OkPage); + ShowBadPage(s1); + } + if (Debug == 0) fprintf(stdout,"Content-type: text/html\n\n"); + while (fgets(Line,BUFSIZ,Fin) != NULL) { + p1 = Line; + while (*p1 != '\0') { + if (strnicmp(p1,"",18) == 0) { + *p1 = '\0'; + sprintf(s1,"%s%lu%s",Line,FileCount,p1 + 18); + strcpy(Line,s1); + } + if (strnicmp(p1,"",18) == 0) { + *p1 = '\0'; + sprintf(s1,"%s%lu%s",Line,ByteCount,p1 + 18); + strcpy(Line,s1); + } + if (strnicmp(p1,"",21) == 0) { + *p1 = '\0'; + sprintf(s1,"%s%s%s",Line,LastFileName,p1 + 21); + strcpy(Line,s1); + } + p1++; + } + fprintf(stdout,"%s",Line); + } + + exit(0); + } + + + + +/* Load the proper segment from the configuration file. */ +void LoadConfig(char *ProgramPath, char *ConfigID) { + FILE *Fin; + char Path[BUFSIZ]; + char Line[BUFSIZ]; + char Name[BUFSIZ]; + char Value[BUFSIZ]; + int Accept; + int NewDebug; + char *p1; + char *p2; + + strcpy(Path,ProgramPath); + p1 = strrchrs(Path,"./\\"); + if (p1 != NULL) { + strcpy(p1,".cfg"); + } else { + strcat(Path,".cfg"); + } + Fin = fopen(Path,"rt"); + if (Fin == NULL) { + p1 = getenv("PATH"); + while ((p1 != NULL) && (*p1 != '\0')) { + p2 = Value; + while ((*p1 != '\0') && (*p1 != ';')) *p2++ = *p1++; + *p2 = '\0'; + if (*p1 == ';') p1++; + sprintf(Name,"%s%cupload.cfg",Value,*DIRSEP); + Fin = fopen(Name,"rt"); + if (Fin != NULL) break; + } + } + if (Fin == NULL) ShowBadPage("I could not open the configuration file."); + + if (Debug > 0) fprintf(stdout,"

\n"); + Accept = NO; + NewDebug = Debug; + while (fgets(Line,BUFSIZ,Fin) != NULL) { + *Name = *Value = '\0'; + if (sscanf(Line,"%[^ \t=]%*[ \t=]%[^\n\r]",Name,Value) != 2) { + sscanf(Line,"%*[ \t]%[^ \t=]%*[ \t=]%[^\n\r]",Name,Value); + } + if (stricmp(Name,"Config") == 0) { + if (Accept == YES) { + if (Debug > 0) fprintf(stdout,"\n
\n

\n"); + if ((Debug == 0) && (NewDebug > 0)) { + fprintf(stdout,"Content-type: text/html\n\n"); + fprintf(stdout,"\n\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"\n\n"); + fprintf(stdout,"%s\n",COPYRIGHT); + } + Debug = NewDebug; + return; + } + if ((ConfigID == NULL) || (*ConfigID == '\0')) { + Accept = YES; + } else { + if (stricmp(ConfigID,Value) == 0) Accept = YES; + } + if (Debug > 0) { + if (Accept == YES) { + fprintf(stdout,"

Loading configuration

\"%s\"\n",Value); + fprintf(stdout,"\n"); + } + } + continue; + } + if (Accept != NO) { + if (Debug > 0) { + fprintf(stdout,"\n",Name,Value); + } + if (stricmp(Name,"Debug") == 0) NewDebug = atoi(Value); + if (stricmp(Name,"Root") == 0) { + Url2Dir(Root,Value); + p1 = strchr(Root,'\0'); + if (p1 != Root) p1--; + if ((p1 != Root) && (strchr(DIRSEP,*p1) == NULL)) { + p1++; + *p1++ = *DIRSEP; + *p1 = '\0'; + } + } + if (stricmp(Name,"FileMask") == 0) strcpy(FileMask,Value); + if (stricmp(Name,"LogFile") == 0) Url2Dir(LogFile,Value); + if (stricmp(Name,"OkPage") == 0) Url2Dir(OkPage,Value); + if (stricmp(Name,"OkUrl") == 0) strcpy(OkUrl,Value); + if (stricmp(Name,"BadPage") == 0) Url2Dir(BadPage,Value); + if (stricmp(Name,"BadUrl") == 0) strcpy(BadUrl,Value); + if (stricmp(Name,"OverWrite") == 0) { + if (stricmp(Value,"no") == 0) OverWrite = NO; + if (stricmp(Value,"yes") == 0) OverWrite = YES; + if (stricmp(Value,"must") == 0) OverWrite = MUST; + } + if (stricmp(Name,"IgnoreSubdirs") == 0) { + if (stricmp(Value,"no") == 0) IgnoreSubdirs = NO; + if (stricmp(Value,"yes") == 0) IgnoreSubdirs = YES; + } + } + } + if (Debug > 0) { + if (Accept == YES) { + fprintf(stdout,"
%s%s
\n\n

\n"); + } else { + fprintf(stdout, + "\nConfiguration \"%s\" not found, using defaults instead.

\n", + ConfigID); + } + } + if ((Debug == 0) && (NewDebug > 0)) { + fprintf(stdout,"Content-type: text/html\n\n"); + fprintf(stdout,"\n\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"\n\n"); + fprintf(stdout,"%s\n",COPYRIGHT); + } + Debug = NewDebug; + } + + + + + +/* Skip a line in the input stream. */ +void SkipLine(char **Input, /* Pointer into the incoming stream. */ + long *InputLength) { /* Bytes left in the incoming stream. */ + + while ((**Input != '\0') && (**Input != '\r') && (**Input != '\n')) { + *Input = *Input + 1; + *InputLength = *InputLength - 1; + } + if (**Input == '\r') { + *Input = *Input + 1; + *InputLength = *InputLength - 1; + } + if (**Input == '\n') { + *Input = *Input + 1; + *InputLength = *InputLength - 1; + } + } + + + + + +/* Accept a single segment from the incoming mime stream. Each field in the + form will generate a mime segment. Return a pointer to the beginning of + the Boundary, or NULL if the stream is exhausted. */ +void AcceptSegment(char **Input, /* Pointer into the incoming stream. */ + long *InputLength, /* Bytes left in the incoming stream. */ + char *Boundary, /* Character string that delimits segments. */ + char *ProgramPath) { + char FieldName[BUFSIZ]; /* Name of the variable from the form. */ + char FileName[BUFSIZ]; /* The filename, as selected by the user. */ + char *ContentStart; /* Pointer to the file content. */ + char *ContentEnd; + char ContentAsString[BUFSIZ]; + long ContentLength; /* Bytecount of the content. */ + char Key1[BUFSIZ]; + char Key2[BUFSIZ]; + char Path[BUFSIZ]; + FILE *Fout; + long Result; + char s1[BUFSIZ]; + char *p1; + int i; + + /* The input stream should begin with a Boundary line. Error-exit if not + found. */ + if (strncmp(*Input,Boundary,strlen(Boundary)) != 0) { + sprintf(s1,"Missing boundary in input."); + WriteLogLine(s1); + ShowBadPage(s1); + } + + /* Skip the Boundary line. */ + *Input = *Input + strlen(Boundary); + *InputLength = *InputLength - strlen(Boundary); + SkipLine(Input,InputLength); + + /* Return NULL if the stream is exhausted (no more segments). */ + if ((**Input == '\0') || (strncmp(*Input,"--",2) == 0)) { + *InputLength = 0; + return; + } + + /* The first line of a segment must be a "Content-Disposition" line. It + contains the fieldname, and optionally the original filename. Error-exit + if the line is not recognised. */ + if (sscanf(*Input,"%[^:]: %[^;]; name=\"%[^\"]\"; filename=\"%[^\"]\"", + Key1,Key2,FieldName,FileName) != 4) { + *FileName = '\0'; + if (sscanf(*Input,"%[^:]: %[^;]; name=\"%[^\"]\"",Key1,Key2, + FieldName) != 3) { + *FieldName = '\0'; + if (sscanf(*Input,"%[^:]: %[^;]; filename=\"%[^\"]\"",Key1,Key2, + FileName) != 3) { + sscanf(*Input,"%[^\r\n]",Key1); + sprintf(s1,"Disposition line not recognised: %s",Key1); + WriteLogLine(s1); + ShowBadPage(s1); + } + } + } + if (stricmp(Key1,"content-disposition") != 0) { + sprintf(s1,"\"Content-Disposition\" expected, but I got \"%s\" instead.", + Key1); + WriteLogLine(s1); + ShowBadPage(s1); + } + if (stricmp(Key2,"form-data") != 0) { + sprintf(s1,"\"form-data\" expected, but I got \"%s\" instead.",Key2); + WriteLogLine(s1); + ShowBadPage(s1); + } + + /* Skip the Disposition line and one or more mime lines, until an empty + line is found. */ + SkipLine(Input,InputLength); + while ((**Input != '\r') && (**Input != '\n')) SkipLine(Input,InputLength); + SkipLine(Input,InputLength); + + /* The following data in the stream is binary. The Boundary string is the + end of the data. There may be a CRLF just before the Boundary, which + must be stripped. */ + ContentStart = *Input; + ContentLength = 0; + while ((*InputLength > 0) && (memcmp(*Input,Boundary,strlen(Boundary)) != 0)) { + *Input = *Input + 1; + *InputLength = *InputLength - 1; + ContentLength = ContentLength + 1; + } + ContentEnd = *Input - 1; + if ((ContentLength > 0) && (*ContentEnd == '\n')) { + ContentEnd--; + ContentLength = ContentLength - 1; + } + if ((ContentLength > 0) && (*ContentEnd == '\r')) { + ContentEnd--; + ContentLength = ContentLength - 1; + } + i = BUFSIZ - 1; + if (ContentLength < i) i = ContentLength; + strncpy(ContentAsString,ContentStart,i); + ContentAsString[i] = '\0'; + + if (ContentEnd) {}; /* Keep lint happy... */ + + /* Show debugging information. */ + if (Debug > 0) { + fprintf(stdout,"\n"); + fprintf(stdout," "); + if (*FieldName != '\0') fprintf(stdout,"%s",FieldName); + fprintf(stdout,"\n"); + fprintf(stdout," "); + if (*FileName != '\0') { + fprintf(stdout,"%s",FileName); + } else { + fprintf(stdout,"%s",ContentAsString); + } + fprintf(stdout,"\n"); + fprintf(stdout," %ld\n",ContentLength); + fprintf(stdout," \n"); + } + + /* If this field is the "Config" field, then load the configuration and + leave. */ + if ((stricmp(FieldName,"Config") == 0) && + (*FileName == '\0') && + (*ContentStart != '\0')) { + if (Debug > 0) fprintf(stdout,""); + LoadConfig(ProgramPath,ContentAsString); + if (Debug > 0) fprintf(stdout,"\n"); + return; + } + + /* If this field is the "FileName" field, then store it and leave. */ + if ((stricmp(FieldName,"FileName") == 0) && + (*FileName == '\0') && + (*ContentStart != '\0')) { + strcpy(UpFileName,ContentAsString); + if (Debug > 0) { + fprintf(stdout,"New filename stored.\n"); + } + return; + } + + /* If this field is the "OkPage" field, then store it and leave. */ + if ((stricmp(FieldName,"OkPage") == 0) && + (*FileName == '\0') && + (*ContentStart != '\0')) { + Url2Dir(OkPage,ContentAsString); + if (Debug > 0) { + fprintf(stdout,"New OkPage stored.\n"); + } + return; + } + + /* If this field is the "OkUrl" field, then store it and leave. */ + if ((stricmp(FieldName,"OkUrl") == 0) && + (*FileName == '\0') && + (*ContentStart != '\0')) { + strcpy(OkUrl,ContentAsString); + if (Debug > 0) { + fprintf(stdout,"New OkUrl stored.\n"); + } + return; + } + + /* If this field is the "BadPage" field, then store it and leave. */ + if ((stricmp(FieldName,"BadPage") == 0) && + (*FileName == '\0') && + (*ContentStart != '\0')) { + Url2Dir(BadPage,ContentAsString); + if (Debug > 0) { + fprintf(stdout,"New BadPage stored.\n"); + } + return; + } + + /* If this field is the "BadUrl" field, then store it and leave. */ + if ((stricmp(FieldName,"BadUrl") == 0) && + (*FileName == '\0') && + (*ContentStart != '\0')) { + strcpy(BadUrl,ContentAsString); + if (Debug > 0) { + fprintf(stdout,"New BadUrl stored.\n"); + } + return; + } + + /* Do nothing if this is not a file, but some other kind of field. */ + if ((FileName == NULL) || (*FileName == '\0')) { + if (Debug > 0) { + fprintf(stdout,"FieldName not recognised.\n"); + } + return; + } + + /* Determine the filename to store the file. If the UpFileName field was + defined then use it, otherwise use the name of the incoming file. The + ROOT is always prepended. */ + if (*UpFileName == '\0') strcpy(UpFileName,FileName); + if (IgnoreSubdirs == YES) { + p1 = strrchrs(UpFileName,DIRSEP); + if (p1 != NULL) { + p1++; + strcpy(UpFileName,p1); + } + } + sprintf(Path,"%s%s",Root,UpFileName); + + /* Test if the filename matches the mask. */ + if (MatchMask(Path,FileMask) == NO) { + sprintf(s1, + "The file is rejected because it does not match the mask.
Filename: %s
Mask: %s", + Path,FileMask); + WriteLogLine(s1); + ShowBadPage(s1); + } + + /* Test if the file already exists. */ + if (OverWrite != YES) { + Fout = fopen(Path,"r"); + if ((OverWrite == NO) && (Fout != NULL)) { + fclose(Fout); + sprintf(s1, + "The file could not be uploaded because it already exists.
Filename: %s", + Path); + WriteLogLine(s1); + ShowBadPage(s1); + } + if ((OverWrite == MUST) && (Fout == NULL)) { + sprintf(s1, + "The file could not be uploaded because it does not exist already.
Filename: %s", + Path); + WriteLogLine(s1); + ShowBadPage(s1); + } + if (Fout != NULL) fclose(Fout); + } + + /* If needed then create directories for the file. */ + CreatePath(Path,NULL,NO); + + /* Open the file for writing. */ +#ifndef unix + Fout = fopen(Path,"w"); +#else + Fout = fopen(Path,"wb"); +#endif + if (Fout == NULL) { + sprintf(s1, + "The file could not be uploaded because write permission is denied.
Filename: %s", + Path); + WriteLogLine(s1); + ShowBadPage(s1); + } +#ifndef unix + setmode(fileno(Fout),O_BINARY); +#endif + + /* Write the file to disk. */ + Result = fwrite(ContentStart,1,ContentLength,Fout); + fclose(Fout); + + /* If the wrong number of bytes were written to disk, then show an error + message. */ + if (Result != ContentLength) { + sprintf(s1, + "The wrong number of bytes were written.
Written: %ld
Bytes in input: %ld", + Result,ContentLength); + WriteLogLine(s1); + ShowBadPage(s1); + } + + /* Show debugging information. */ + if (Debug > 0) { + fprintf(stdout,"\n"); + fprintf(stdout," File written: %s\n",Path); + fprintf(stdout," \n"); + } + + FileCount = FileCount + 1; + ByteCount = ByteCount + ContentLength; + strcpy(LastFileName,UpFileName); + + sprintf(s1,"File uploaded succesfully: %s (%lu bytes)", + UpFileName,ContentLength); + WriteLogLine(s1); + + /* Clear the filename. */ + *UpFileName = '\0'; + + return; + } + + + + + +int main(int argc, char *argv[], char *environment[]) { + char *Method; /* Pointer to REQUEST_METHOD environment variable. */ + char *ContentLength; /* Pointer to CONTENT_LENGTH environment variable. */ + char *ContentType; /* Pointer to CONTENT_TYPE environment variable. */ + long InCount; /* The supposed number of incoming bytes. */ + long RealCount; /* Actual number of incoming bytes. */ + char *Content; /* Copy in memory of the Content. */ + char *Here; /* Position into the Content. */ + char Boundary[BUFSIZ]; /* The boundary string between segments. */ + + char Char; + long MoreCount; + char *p1; + char s1[BUFSIZ]; + + if (argc > 1) { + fprintf(stdout,"Error: %s is a cgi program, and should not be ",argv[0]); + fprintf(stdout,"started from the command line.\n"); + exit(1); + } + + *Root = '\0'; /* Setup defaults. */ + strcpy(FileMask,"*"); + IgnoreSubdirs = YES; + OverWrite = YES; + *LogFile = '\0'; + *OkPage = '\0'; + *OkUrl = '\0'; + *BadPage = '\0'; + *BadUrl = '\0'; + Debug = 0; + *UpFileName = '\0'; + FileCount = 0; + ByteCount = 0; + *LastFileName = '\0'; + + if (environment) {}; /* Keep lint() happy. */ + + if (Debug > 0) { + fprintf(stdout,"Content-type: text/html\n\n"); + fprintf(stdout,"\n\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"\n\n"); + fprintf(stdout,"%s\n",COPYRIGHT); + } + + LoadConfig(argv[0],""); /* Load default configuration. */ + + /* Test if the program was started by a METHOD=POST form. */ + Method = getenv("REQUEST_METHOD"); + if ((Method == NULL) || (*Method == '\0') || (stricmp(Method,"post") != 0)) { + ShowBadPage("Sorry, this program only supports METHOD=POST."); + } + if (Debug > 0) fprintf(stdout,"

Loading input

\n",Method); + if (Debug > 0) fprintf(stdout,"Method = %s
\n",Method); + + /* Test if the program was started with ENCTYPE="multipart/form-data". */ + ContentType = getenv("CONTENT_TYPE"); + if ((ContentType == NULL) || + (strnicmp(ContentType,"multipart/form-data; boundary=",30) != 0)) { + ShowBadPage("Sorry, this program only supports ENCTYPE=\"multipart/form-data\"."); + } + if (Debug > 0) fprintf(stdout,"Enctype = %s
\n",ContentType); + + /* Determine the Boundary, the string that separates the segments in the + stream. The boundary is available from the CONTENT_TYPE environment + variable. */ + Here = strchr(ContentType,'=') + 1; + sprintf(Boundary,"--%s",Here); + if (Debug > 0) fprintf(stdout,"Boundary = %s
\n",Boundary); + + /* Get the total number of bytes in the input stream from the + CONTENT_LENGTH environment variable. */ + ContentLength = getenv("CONTENT_LENGTH"); + if (ContentLength == NULL) { + WriteLogLine("Error: no CONTENT_LENGTH found."); + ShowBadPage("Error: no CONTENT_LENGTH found."); + } + InCount = atol(ContentLength); + if (InCount == 0) { + WriteLogLine("Error: CONTENT_LENGTH is zero."); + ShowBadPage("Error: CONTENT_LENGTH is zero."); + } + if (Debug > 0) fprintf(stdout,"Content_Length = %d
\n",InCount); + + /* Allocate sufficient memory for the incoming data. */ + Content = (char *)malloc(InCount + 1); + if (Content == NULL) { + WriteLogLine("Error: malloc() returned NULL."); + ShowBadPage("Error: malloc() returned NULL."); + } + + /* Load the data from standard input into memory. */ +#ifndef unix + setmode(fileno(stdin),O_BINARY); /* Make sure the input is binary... */ +#endif + p1 = Content; + RealCount = 0; + /* For some reason fread() of Borland C 4.52 barfs if the bytecount is + bigger than 2.5Mb, so I have to do it like this. */ + while (fread(p1++,1,1,stdin) == 1) { + RealCount++; + if (RealCount >= InCount) break; + } + *p1 = '\0'; + /* Ignore any extra caracters. We have to read them, or the server + will give an error message. */ + if (RealCount < InCount) { + MoreCount = InCount - RealCount; + while ((MoreCount > 0) && (fread(&Char,1,1,stdin) == 1)) MoreCount--; + } + if (RealCount != InCount) { + free(Content); + sprintf(s1, + "Error: The number of bytes received (%ld) is not what the CONTENT_LENGTH environment variable says it sould be (%ld).", + RealCount + MoreCount, InCount); + WriteLogLine(s1); + ShowBadPage(s1); + return(0); + } + if (Debug > 0) fprintf(stdout,"Input succesfully loaded into memory.
\n"); + + /* Handle all segments in the incoming data, that has been stored in + memory. */ + Here = Content; + if (Debug > 0) { + fprintf(stdout,"

\n

\n

Parsing input

\n"); + fprintf(stdout,"\n"); + fprintf(stdout,"\n"); + fprintf(stdout," \n"); + fprintf(stdout," \n"); + fprintf(stdout," \n"); + fprintf(stdout," \n"); + } + while (RealCount > 0) AcceptSegment(&Here,&RealCount,Boundary,argv[0]); + if (Debug > 0) fprintf(stdout,"
FieldnameContentsSize
\n
\n"); + + /* Cleanup. */ + free(Content); + + if (*LastFileName == '\0') ShowBadPage("You have not specified a file, so nothing was uploaded."); + + /* Display the OkPage. */ + if (Debug > 0) { + fprintf(stdout,"

Finished

\n"); + } + ShowOkPage(); + return(0); + } + + +/* +Ideeen: + +- Multiple filemasks. +- Maximum directory size. +- Maximum and Minimum file size. +- Result-macros as parameters to OkUrl. + +*/ diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload.cfg b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload.cfg new file mode 100644 index 0000000000..74683981a3 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/upload.cfg @@ -0,0 +1,9 @@ +Config = Default + Root = /www/upload/files + FileMask = * + IgnoreSubdirs = YES + Overwrite = YES + LogFile = /www/upload/files/upload.log + OkPage = /www/upload/OkPage.html + BadPage = /www/upload/BadPage.html + Debug = 0 diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/uptime b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/uptime new file mode 100755 index 0000000000..3ff6b372b8 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/cgi-bin/uptime @@ -0,0 +1,12 @@ +#!/bin/sh +echo "Content-type: text/html" +echo +echo "" +echo "" +echo "
" +echo "

Uptime information

" +echo "Your embedded device has been running for:
"
+echo `uptime`
+echo "
" +echo "

" +echo "" diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/gohome.png b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/gohome.png new file mode 100644 index 0000000000..ae0520383f Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/gohome.png differ diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/index.html b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/index.html new file mode 100644 index 0000000000..ae0c4ffe42 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/index.html @@ -0,0 +1,24 @@ + + +ACME ultra-tiny image server + + +

ACME ultra-tiny image server

+

Congratulations for your new device!

+

Device information

+ +

Upload image files

+ +
+ + +
+ +

List file collection

+ +

rebootReboot your system

+ + diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/kshutdown.png b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/kshutdown.png new file mode 100644 index 0000000000..a71ed470c3 Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/kshutdown.png differ diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/BadPage.html b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/BadPage.html new file mode 100644 index 0000000000..51c483bf98 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/BadPage.html @@ -0,0 +1,10 @@ + + +

Upload failure!

+
+ +

+ +

+ + diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/OkPage.html b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/OkPage.html new file mode 100644 index 0000000000..9e1348fa28 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/OkPage.html @@ -0,0 +1,12 @@ + + +

Successful upload!

+ +

File uploaded:
+Bytes uploaded: +

+ +

+ + + diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/adult-small.png b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/adult-small.png new file mode 100644 index 0000000000..d6ea415bd5 Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/adult-small.png differ diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/brick.png b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/brick.png new file mode 100644 index 0000000000..d5b771ef0f Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/brick.png differ diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/linux-blackfin.jpg b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/linux-blackfin.jpg new file mode 100644 index 0000000000..a1d314d191 Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/linux-blackfin.jpg differ diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/linux-kernel-dev-book.jpg b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/linux-kernel-dev-book.jpg new file mode 100644 index 0000000000..628f6df850 Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/linux-kernel-dev-book.jpg differ diff --git a/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/lkn-small.jpg b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/lkn-small.jpg new file mode 100644 index 0000000000..82c0559db6 Binary files /dev/null and b/lab-data/embedded-linux-imx93-frdm/tinysystem/data/www/upload/files/lkn-small.jpg differ diff --git a/lab-data/embedded-linux-imx93-frdm/toolchain/hello.c b/lab-data/embedded-linux-imx93-frdm/toolchain/hello.c new file mode 100644 index 0000000000..22e78e7fe7 --- /dev/null +++ b/lab-data/embedded-linux-imx93-frdm/toolchain/hello.c @@ -0,0 +1,8 @@ +#include +#include + +int main (void) +{ + printf( "Hello world!\n" ); + return EXIT_SUCCESS; +} diff --git a/labs/sysdev-accessing-hardware-imx93-frdm/imx93-frdm-connect-gpio.jpg b/labs/sysdev-accessing-hardware-imx93-frdm/imx93-frdm-connect-gpio.jpg new file mode 100644 index 0000000000..5139cc6ad7 Binary files /dev/null and b/labs/sysdev-accessing-hardware-imx93-frdm/imx93-frdm-connect-gpio.jpg differ diff --git a/labs/sysdev-accessing-hardware-imx93-frdm/sysdev-accessing-hardware-imx93-frdm.tex b/labs/sysdev-accessing-hardware-imx93-frdm/sysdev-accessing-hardware-imx93-frdm.tex new file mode 100644 index 0000000000..aefbb8581d --- /dev/null +++ b/labs/sysdev-accessing-hardware-imx93-frdm/sysdev-accessing-hardware-imx93-frdm.tex @@ -0,0 +1,701 @@ +\subchapter{Accessing Hardware Devices} +{Objective: learn how to access hardware devices and declare new ones.} + +\section{Goals} + +Now that we have access to a command line shell thanks to a working root +filesystem, we can now explore existing devices and make new ones +available. In particular, we will make changes to the Device Tree +and compile an out-of-tree Linux kernel module. + +\section{Setup} + +Go to the \code{$HOME/__SESSION_NAME__-labs/hardware} directory, +which provides useful files for this lab. + +However, we will go on booting the system through NFS, using the +root filesystem built by the previous lab. + +\section{Exploring /dev} + +Start by exploring \code{/dev} on your target system. Here are a few +noteworthy device files that you will see: + +\begin{itemize} + \item {\em Terminal devices}: devices starting with \code{tty}. + Terminals are user interfaces taking text as + input and producing text as output, and are typically used by + interactive shells. In particular, you will find + \code{console} which matches the device specified through + \code{console=} in the kernel command line. You will also find + the {\tt \ttyname} device file. + \item {\em Pseudo-terminal devices}: devices starting with \code{pty}, + used when you connect through SSH for example. Those are virtual + devices, but there are so many in \code{/dev} that we wanted + to give a description here. + \item {MMC device(s) and partitions}: devices starting with + \code{mmcblk}. You should here recognize the MMC device(s) + on your system and the associated partitions. + \item If you have a real board (not QEMU) and a USB stick, you could + plug it in and if your kernel was built with USB host and mass + storage support, you should see a new \code{sda} device appear, + together with the \code{sda} devices for its partitions. +\end{itemize} + +Don't hesitate to explore \code{/dev} on your workstation too +and ask any questions to your instructor. + +\section{Exploring /sys} + +The next thing you can explore is the {\em Sysfs} filesystem. + +A good place to start is \code{/sys/class}, which exposes devices +classified by the kernel frameworks which manage them. + +For example, go to \code{/sys/class/net}, and you will see all the +networking interfaces on your system, whether they are internal, +external or virtual ones. + +Find which subdirectory corresponds to the network connection +to your host system, and then check device properties such as: +\begin{itemize} + \item \code{speed}: will show you whether this is a gigabit + or hundred megabit interface. + \item \code{address}: will show the device MAC address. No + need to get it from a complex command! + \item \code{statistics/rx_bytes} will show you how many bytes + were received on this interface. +\end{itemize} + +Don't hesitate to look for further interesting properties by yourself! + +Next, you can now explore all the buses (virtual or physical) available +on your system, by checking the contents of \code{/sys/bus}. + +In particular, go to \code{/sys/bus/mmc/devices} to see all the +MMC devices on your system. Go inside the directory for the first device +and check several files (for example): + +\begin{itemize} +\item \code{serial}: the serial number for your device. +\item \code{preferred_erase_size}: the preferred erase block for your + device. It's recommended that partitions start at multiples of this + size. +\item \code{name}: the product name for your device. You could display + it in a user interface or log file, for example. +\item \code{date}: apparently the manufacturing date for the device. +\end{itemize} + +Don't hesitate to spend more time exploring \code{/sys} on your system +and asking questions to your instructor. + +\section{Driving GPIOs} + +At this stage, we can only explore GPIOs through the legacy interface +in \code{/sys/class/gpio}, because the {\em libgpiod} interface +commands are provided through a dedicated project which we have to +build separately, and {\em Busybox} does not provide a +re-implementation for the {\em libgpiod} tools. In a later lab, we +will build {\em libgpiod} tools which use the modern +\code{/dev/gpiochipX} interface. + +The first thing to do is to enable this legacy interface by enabling +\kconfig{CONFIG_GPIO_SYSFS} in the kernel configuration. +To do so, in recent Linux kernel versions the \kconfig{CONFIG_EXPERT} +needs to be enable to have access to some legacy options and in our +case to \kconfig{CONFIG_GPIO_SYSFS}. + +Also make sure {\em Debugfs} is enabled (\kconfig{CONFIG_DEBUG_FS} and +\kconfig{CONFIG_DEBUG_FS_ALLOW_ALL}). + +After rebooting the new kernel, the first thing to do is to mount +the {\em Debugfs} filesystem: + +\begin{bashinput} +# mount -t debugfs debugfs /sys/kernel/debug/ +\end{bashinput} + +Then, you can check information about available GPIOs banks and which +GPIOs are already in use: + +\begin{bashinput} +# cat /sys/kernel/debug/gpio +\end{bashinput} + +We are going to use one of the EXPI connector of the board, + +Take one of the F-F breadboard wires provided by your instructor and: +\begin{itemize} + \item Connect one end to the \code{Pin 40} of the \code{EXPI} connector + \item Connect the other end to the \code{GND} pin of the \code{EXPI} connector +\end{itemize} + +\includegraphics[width=0.3\textwidth]{labs/sysdev-accessing-hardware-imx93-frdm/imx93-frdm-connect-gpio.jpg} + +If you look at the board documentation, you will see that pin 40 is connected to GPIO\_IO21, which belongs to GPIO controller 2. However, GPIO controller 1 is not used, so this GPIO will be referenced under the label gpiochip0 in Linux. Furthermore, we are using GPIO 21 from gpiochip0, which corresponds to gpio-533. + +We now have everything we need to drive this GPIO using the legacy +interface. First, let's enable it: + +\begin{bashinput} +# cd /sys/class/gpio +# echo %\gpionum% > export +\end{bashinput} + +If indeed the pin is still available, this should create a new +{\tt gpio\gpionum} file in \code{/sys/class/gpio}. + +We can now configure this pin as input: + +\begin{bashinput} +# echo in > gpio%\gpionum%/direction +\end{bashinput} + +And check its value: + +\begin{bashinput} +# cat gpio%\gpionum%/value +0 +\end{bashinput} + +The value should be \code{0} as the pin is connected to a ground level. + +Now, let's connect our GPIO pin to the \code{+3.3V} pin. + +Let's check the value again: + +\begin{bashinput} +# cat gpio%\gpionum%/value +1 +\end{bashinput} + +The value is \code{1} because our pin is connected to a 3.3V level now. + +You could use this GPIO to add a button switch to your board, for +example. + +Note that you could also configure the pin as output and set its value +through the \code{value} file. This way, you could add an external LED +to your board, for example. + +Before moving on to the next section, you can also check +\code{/sys/kernel/debug/gpio} again, and see that {\tt gpio-\gpionum} is now +in use, through the sysfs interface, and is configured as an input pin. + +When you're done, you can see your GPIO free: + +\begin{bashinput} +# echo %\gpionum% > unexport +\end{bashinput} + +\section{Driving LEDs} + +First, make sure your kernel is compiled with +\kconfigval{CONFIG_LEDS_CLASS}{y}, \kconfigval{CONFIG_LEDS_GPIO}{y} +and \kconfigval{CONFIG_LEDS_TRIGGER_TIMER}{y}. + +Then, go to \code{/sys/class/leds} to see all the LEDs that you are allowed +to control. + +Let's control the LED which is called +\code{:heartbeat}. + +Go into the directory for this LED, and check its trigger (what +routine is used to drive its value): + +\begin{bashinput} +# cat trigger +\end{bashinput} + +As you can see, there are many triggers to choose from, the current +being \code{heartbeat}. + +You can disable all triggers by: + +\begin{bashinput} +# echo none > trigger +\end{bashinput} + +And then directly control the LED: + +\begin{bashinput} +# echo 1 > brightness +# echo 0 > brightness +\end{bashinput} + +You could also use the \code{timer} trigger to light the LED +with specified time on and time off: + +\begin{bashinput} +# echo timer > trigger +# echo 10 > delay_on +# echo 200 > delay_off +\end{bashinput} + +\section{Managing the I2C buses and devices} + +\subsection{Enabling an I2C bus} + +The next thing we want to do is connect an Nunchuk joystick +to an I2C bus on our board. The I2C bus is very frequently used +to connect all sorts of external devices. That's why we're covering +it here. + +First, let’s see which I2C buses are already enabled: +\begin{bashinput} +# i2cdetect -l +# i2cdetect -l +i2c-1 i2c 44350000.i2c I2C adapter +i2c-2 i2c 42530000.i2c I2C adapter +i2c-0 i2c 44340000.i2c I2C adapter +\end{bashinput} + +If we look at the SoC datasheet, we can see that \code{0x4434} is associated with the I2C1 controller, \code{0x4435} is associated with the I2C2 controller, and finally, \code{0x4253} is associated with the I2C3 controller. + +So, we are lucky that the first 3 Linux I2C names corresponds to the first 3 +datasheet names. + +In this lab we will be using the I2C1 bus to connect the Nunchuk +because it is located on the 10-pin 2x5 2.54 mm connector and is easily +accessible. + +However because this I2C controller is already enabled, we will +first play with I2C4 (WKUP\_I2C0 in datasheet) and demonstrate +how to enable it, even if we won't use I2C4 in the rest of the labs. + +\subsection{Customizing the Device Tree} + +Fortunately, I2C4 (LPI2C4 in datasheet of the soc) is already defined +in one of the DTS includes used by the Device Tree for our board. +In our case, that's in \kfile{arch/arm64/boot/dts/freescale/imx93.dtsi}. +Look by yourself in this file, and you will find its definition, but with +\code{status = "disabled";}. This means that this I2C controller is not +enabled yet, and it's up to boards using it to do so. + +We could modify the \kfile{arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts} file +for our board, but that's not a very good idea as this file is +maintained by the kernel developers. The changes that you make could +collide with future changes made by the maintainers for this file. + +A more futureproof idea is to create a new Device Tree file which +includes the standard one, and adds custom definitions. So, create a +new \code{arch/arm64/boot/dts/freescale/imx93-11x11-frdm-custom.dts} file containing: + +\begin{verbatim} +/dts-v1/; +#include "imx93-11x11-frdm.dts" + +&lpi2c4 { + status = "okay"; +}; +\end{verbatim} + +As you can see, it's also possible to include \code{dts} files, and not +only \code{dtsi} ones. + +Why the \code{/delete-property/} statement? That's because we want to see what happens when a +device doesn't have associated pin definitions yet. + +Modify the \kfile{arch/arm64/boot/dts/freescale/Makefile} file to add your custom +Device Tree, and then have it compiled (\code{make dtbs}). + +Reboot your board with the update. + +Back to the running system, we can now see that there is one more +I2C bus: + +\begin{bashinput} +# i2cdetect -l +i2c-3 i2c 42540000.i2c I2C adapter +i2c-1 i2c 44350000.i2c I2C adapter +i2c-2 i2c 42530000.i2c I2C adapter +i2c-0 i2c 44340000.i2c I2C adapter +\end{bashinput} + +Run the below command to confirm that the new bus has the same address +as in the datasheet (\code{0x4254}): + +\bashcmd{ls -l /sys/bus/i2c/devices/i2c-3} + +Now, let's use \code{i2cdetect}'s capability to probe a bus for devices. +Let's start by the bus associated to \code{i2c-1}: + +\begin{verbatim} +# i2cdetect -r 1 +i2cdetect: WARNING! This program can confuse your I2C bus +Continue? [y/N] y + 0 1 2 3 4 5 6 7 8 9 a b c d e f +00: -- -- -- -- -- -- -- -- -- -- -- -- -- +10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +20: -- -- UU -- -- UU -- -- -- -- -- -- -- -- -- -- +30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +70: -- -- -- -- -- -- -- -- +\end{verbatim} + +We can see three devices on this internal bus: +\begin{itemize} +\item Two at address \code{0x22} and \code{0x25}, indicated by \code{UU}, + which means that there is a kernel driver actively + driving this device. +\item One other devices at addresses \code{0x50}. + We just know that they are currently not bound to a kernel driver. +\end{itemize} + +Now we have demonstrated how to enable an I2C bus, it's time to +use the I2C1 bus, which will be connected to our Nunchuk device. + +\subsection{Adding and enabling an I2C device} + +Let's connect the Nunchuk provided by your instructor +to the \busname\ bus on the board, using breadboard wires: + +\includegraphics[width=0.3\textwidth]{common/nunchuk-pinout.pdf} +\includegraphics[width=0.7\textwidth]{common/imx93-frdm-connect-nunchuk.jpg} + +\begin{itemize} +\item Connect the Nunchuk PWR pin to \code{+3.3V} pin of 10-pin 2x5 2.54 mm connector +\item Connect the Nunchuk GND pin to \code{GND} pin of 10-pin 2x5 2.54 mm connector +\item Connect the Nunchuk SCL pin to \code{SCL} pin of 10-pin 2x5 2.54 mm connector +\item Connect the Nunchuk SDA pin to \code{SDA} pin of 10-pin 2x5 2.54 mm connector +\end{itemize} + +If you didn't do any mistake, your new device should be detected at +address \code{0x52}: + +\begin{verbatim} +# i2cdetect -r 0 +i2cdetect: WARNING! This program can confuse your I2C bus +Continue? [y/N] y + 0 1 2 3 4 5 6 7 8 9 a b c d e f +00: -- -- -- -- -- -- -- -- -- -- -- -- -- +10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +40: -- -- -- -- -- -- -- -- -- -- -- -- 4c -- -- -- +50: -- -- 52 -- -- -- -- -- -- -- -- -- -- -- -- -- +60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +70: -- -- -- -- -- -- -- -- +\end{verbatim} + +We will later compile an out-of-tree kernel module to support this device. + +\section{Plugging a USB audio headset} + +In the next labs, we are going to play audio using a USB audio headset. +Let's see whether our kernel supports such hardware by plugging the +headset provided by your instructor. + +Before plugging the device, look at the output of \code{lsusb}: + +\begin{bashinput} +# lsusb +Bus 001 Device 001: ID 1d6b:0002 +\end{bashinput} + +{\bf Known issue:} if you don't get any output from \code{lsusb}, +you may need to remove the power supply and power on the board +again. + +Now, when you plug the USB headset, a number of messages should appear +on the console, and running \code{lsusb} again should show an +additional device: + +\begin{bashinput} +# lsusb +Bus 001 Device 001: ID 1d6b:0002 +Bus 001 Device 002: ID 1b3f:2008 +\end{bashinput} + +The device of vendor ID \code{1b3f} and product ID \code{2008} has +appeared. Of course, this depends on the actual USB audio device +that you used. + +The device also appears in \code{/sys/bus/usb/devices/}, in a +directory whose name depends on the topology of the USB bus. When the +device is plugged in the kernel messages show: + +\begin{bashinput} +usb 1-1: new full-speed USB device number 2 using xhci-hcd +\end{bashinput} + +So if we go in \code{/sys/bus/usb/devices/1-1}, we get the {\em +sysfs} representation of this USB device: + +\begin{bashinput} +# cd /sys/bus/usb/devices/1-1 +# cat idVendor +1b3f +# cat idProduct +2008 +# cat manufacturer +GeneralPlus +# cat product +USB Audio Device +\end{bashinput} + +However, while the USB device is detected, we currently do not have +any driver for this device, so no actual sound card is detected. + +\section{Enabling, installing and using in-tree kernel modules} + +Go back to the kernel source directory. + +The Linux kernel has a generic driver supporting all USB audio devices +supporting the standard USB audio class. This driver can be enabled +using the \kconfig{CONFIG_SND_USB_AUDIO} configuration option. Look +for this parameter in the kernel configuration, and configure it +as a module. + +So, instead of compiling the corresponding driver as a built-in as +we did before, that's a good opportunity to practice with kernel modules. + +So, compile your modules: +\begin{bashinput} +make modules +\end{bashinput} + +Then, following details given in the lectures, install the modules in our NFS +root filesystem (\code{$HOME/__SESSION_NAME__-labs/tinysystem/nfsroot}). + +Also make sure to update the kernel image (\code{make Image.gz}), and reboot the +board. Indeed, due to the changes we have made to the kernel source code, +the kernel version is now \code{6.14.-dirty}, the {\em dirty} +keyword indicating that the Git working tree has uncommitted changes. +The modules are therefore installed in \code{/lib/modules/6.14.-dirty/}, +and the version of the running Linux kernel must match this. + +After rebooting, try to load the module that we need: + +\begin{bashinput} +modprobe snd-usb-audio +\end{bashinput} + +By running \code{lsmod}, see all the module dependencies that +were loaded too. + +You can also see that a new USB device driver in +\code{/sys/bus/usb/drivers/snd-usb-audio}. This directory shows which +USB devices are bound to this driver. + +You can check that \code{/proc/asound} now exists (thanks to loading +modules for ALSA, the Linux sound subsystem), and that one sound +card is available: + +\begin{bashinput} +# cat /proc/asound/cards + 0 [Device ]: USB-Audio - USB Audio Device + GeneralPlus USB Audio Device at usb-xhci-hcd.3.auto-1, full speed +\end{bashinput} + +Check also the \code{/dev/snd} directory, which should now contain +some character device files. These will be used by the user-space +libraries and applications to access the audio devices. + +Modify your startup scripts so that the \code{snd-usb-audio} module +is always loaded at startup. + +We cannot test the sound card yet, as we will need to build some +software first. Be patient, this is coming soon. + +\section{Compiling and installing an out-of-tree kernel module} + +The next device we want to support is the I2C Nunchuk. There is a driver +in the kernel to support it when connected to a Wiimote controller, but +there is no such driver to support it as an I2C device. + +Fortunately, one is provided in +\code{$HOME/__SESSION_NAME__-labs/hardware/data/nunchuk/nunchuk.c}. You can check +\href{https://bootlin.com/training/kernel/}{Bootlin's Linux kernel and +driver development course} to learn how to implement all sorts of device +drivers for Linux. + +Go to this directory, and compile the out-of-tree module as follows: + +\begin{bashinput} +make -C $HOME/__SESSION_NAME__-labs/kernel/linux M=$PWD +\end{bashinput} + +Here are a few explanations: +\begin{itemize} +\item The \code{-C} option lets \code{make} know which Makefile to + use, here the toplevel Makefile in the kernel sources. +\item \code{M=$PWD} tells the kernel Makefile to build external + module(s) from the file(s) in the current directory. +\end{itemize} + +Now, you can install the compiled module in the NFS root filesystem +by passing the \code{modules_install} target and specifying the +target directory through the \code{INSTALL_MOD_PATH} variable: + +\begin{bashinput} +make -C $HOME/__SESSION_NAME__-labs/kernel/linux \ + M=$PWD \ + INSTALL_MOD_PATH=$HOME/__SESSION_NAME__-labs/tinysystem/nfsroot \ + modules_install +\end{bashinput} + +You can see that this installs out-of-tree kernel modules under +\code{lib/modules//updates/}. + +Back on the target, you can now check that your custom module can +be loaded: + +\begin{bashinput} +# modprobe nunchuk +[ 4317.737978] nunchuk: loading out-of-tree module taints kernel. +\end{bashinput} + +See \kdochtml{kbuild/modules} in kernel documentation +for details about building out-of-tree kernel modules. + +However, run \code{i2cdetect -r 1} again. You will see that the +Nunchuk is still detected, but still not driven by the kernel. +Otherwise, it would be signaled by the \code{UU} character. You +may also look at the \code{nunchuk.c} file and notice a +\code{Nunchuk device probed successfully} message that you didn't +see when loading the module. + +That's because the Linux kernel doesn't know about the Nunchuk +device yet, even though the driver for this kind of devices is +already loaded. Our device also has to be described in the Device Tree. + +You can confirm this by having a look at the contents of the +\code{/sys/bus/i2c} directory. It contains two subdirectories: +\code{devices} and \code{drivers}. + +In \code{drivers}, there should be a \code{nunchuk} subdirectory, +but no symbolic link to a device yet. In \code{devices} you should +see some devices, but not the Nunchuk one yet. + +\section{Declaring an I2C device} + +To allow the kernel to manage our Nunchuk device, let's declare the +device in the custom Device Tree for our board. The declaration of the \busname\ +bus will then look as follows: + +\begin{verbatim} +&lpi2c1 { + status = "okay"; + clock-frequency = <100000>; + + nunchuk: joystick@52 { + compatible = "nintendo,nunchuk"; + reg = <0x52>; + }; +}; +\end{verbatim} + +Here are a few notes: +\begin{itemize} +\item The \code{clock-frequency} property is used to configure the bus + to operate at 100 KHz. This is supposed to be required for the + Nunchuk. +\item The Nunchuk device is added through a child node in the I2C + controller node. +\item For the kernel to {\em probe} and drive our device, it's required + that the \code{compatible} string matches one of the + \code{compatible} strings supported by the driver. +\item The \code{reg} property is the address of the device on the + I2C bus. If it doesn't match, the driver will probe the device + but won't be able to communicate with it. +\end{itemize} + +Recompile your Device Tree and reboot your kernel with the new binary. + +You can now load your module again, and this time, you should see that +the Nunchuk driver probed the Nunchuk device: + +\begin{bashinput} +# modprobe nunchuk +[ 7.638431] nunchuk: loading out-of-tree module taints kernel. +[ 7.669813] input: Wii Nunchuk as /devices/platform/bus@f0000/20030000.i2c/i2c-3/3-0052/input/input2 +[ 7.679188] Nunchuk device probed successfully +\end{bashinput} + +List the contents of \code{/sys/bus/i2c/drivers/nunchuk} once again. You +should now see a symbolic link corresponding to our new device. + +Also list \code{/sys/bus/i2c/devices/} again. You should now see the +Nunchuk device, which can be recognized through its \code{0052} address. +Follow the link and you should see a symbolic link back to the Nunchuk +driver! + +We are not ready to use this input device yet, but at least we can test +that we get bytes when buttons or the joypad are used. In the below +command, use the same number as in the message you got in the console +(\code{event2} for \code{input2} for example): + +\begin{bashinput} +# cat /dev/input/event2 | od -x +\end{bashinput} + +{\bf Caution}: using \code{od} directly on input event files should +work but is currently broken with the Musl library. We are investigating +this issue. + +We will use the Nunchuk to control audio playback in an upcoming lab. + +\section{Setting the board's model name} + +Modify the custom Device Tree file one last time to override the model +name for your system. Set the \code{model} property to +\code{BeaglePlay media player}. Don't hesitate to ask your +instructor if you're not sure how. + +Recompile the device tree, and reboot the board with it. You should see +the new model name in two different places: + +\begin{itemize} +\item In the first kernel messages on the serial console. +\item In \code{/sys/firmware/devicetree/base/model}. This can be + handy for a distribution to identify the device it's running on. + By the way, you can explore \code{/sys/firmware/devicetree} and + find that every subdirectory corresponds to a DT node, and every + file corresponds to a DT property. +\end{itemize} + +\section{Committing kernel tree changes} + +Now that our changes to the kernel sources are over, +create a branch for your changes and create a patch for them. +{\bf Please don't skip this step} as we need it for the next labs. + +First, if not done yet, you should set your identity +and e-mail address in git: + +\begin{bashinput} +git config --global user.email "linus@bootlin.com" +git config --global user.name "Linus Torvalds" +\end{bashinput} + +This is necessary to create a commit with the \code{git commit -s} +command, as required by the Linux kernel contribution guidelines. + +Let's create the branch and the patch now: + +\begin{bashinput} +git checkout -b bootlin-labs +git add arch/arm64/boot/dts/ti/k3-am625-beagleplay-custom.dts +git commit -as -m "Custom DTS for Bootlin lab" +\end{bashinput} + +We can now create the patch:\\ +\texttt{git format-patch stable/linux-\workingkernel.y} + +This should generate a \code{0001-Custom-DTS-for-Bootlin-lab.patch} +file. + +Creating the branch will impact the versions of the kernel and the modules. +Compile your kernel and install your modules again (not necessary for the +Nunchuk one for the moment) and see the version changes through the +new base directory for modules. + +To save space for the next lab, remove the old directory under +\code{lib/modules} containing the "dirty" modules. + +Don't forget to update the kernel your board boots. + +That's all for now! diff --git a/labs/sysdev-block-filesystems-imx93-frdm/sysdev-block-filesystems-imx93-frdm.tex b/labs/sysdev-block-filesystems-imx93-frdm/sysdev-block-filesystems-imx93-frdm.tex new file mode 100644 index 0000000000..f7180abd89 --- /dev/null +++ b/labs/sysdev-block-filesystems-imx93-frdm/sysdev-block-filesystems-imx93-frdm.tex @@ -0,0 +1,169 @@ +\subchapter{Filesystems - Block file systems}{Objective: configure and + boot an embedded Linux system relying on block storage} + +After this lab, you will be able to: +\begin{itemize} +\item Produce file system images. +\item Configure the kernel to use these file systems +\item Use the tmpfs file system to store temporary files +\item Load the kernel and DTB from a EXT4 partition +\end{itemize} + +\section{Goals} + +After doing the {\em A tiny embedded system} lab, we are going to copy +the filesystem contents to the SD card. The storage will be +split into several partitions, and your board will boot +on an root filesystem on this SD card, without using NFS anymore. + +\section{Setup} + +Throughout this lab, we will continue to use the root filesystem we +have created in the \code{$HOME/__SESSION_NAME__-labs/tinysystem/nfsroot} +directory, which we will progressively adapt to use block filesystems. + +\section{Filesystem support in the kernel} + +Recompile your kernel with support for SquashFS and ext4\footnote{Basic +configuration options for these filesystems will be sufficient. No need +for things like extended attributes.}. + +Update your kernel image in the boot partition. + +Boot your board with this new kernel and on the NFS filesystem you +used in this previous lab. + +Now, check the contents of \code{/proc/filesystems}. You should see + that ext4 and SquashFS are now supported. + +\section{Add partitions to the SD card} + +Plug the SD card in your workstation. + +Using \code{fdisk /dev/mmcblk0}, add two partitions, starting from the beginning +of the remaining space, with the following properties: + +\begin{itemize} +\item A third primary partition, 100 MB big, for the root filesystem +\item A fourth primary partition, that fills the rest of the SD card, that will be + used for the data filesystem +\end{itemize} + +Save and exit when you are done. + +\section{Data partition on the SD card} + +Using the \code{mkfs.ext4} create a journaled file system on the +third partition of the SD card: + +\bashcmd{$ sudo mkfs.ext4 -L data -E nodiscard /dev/mmcblk0p3} + +\begin{itemize} +\item \code{-L} assigns a volume name to the partition +\item \code{-E nodiscard} disables bad block discarding. While this + should be a useful option for cards with bad blocks, skipping + this step saves long minutes in SD cards. +\end{itemize} + +Now, mount this new partition and move the contents of the +\code{/www/upload/files} directory (in your target root filesystem) into +it. The goal is to use the data partition of the SD card as the storage +for the uploaded images. + +Insert the SD card in your board and boot. You should see the +partitions in \code{/proc/partitions}. + +Mount this data partition on \code{/www/upload/files}. + +Once this works, modify the startup scripts in your root filesystem +to do it automatically at boot time. + +Reboot your target system and with the \code{mount} command, check that +\code{/www/upload/files} is now a mount point for the last SD card +partition. Also make sure that you can still upload new images, and +that these images are listed in the web interface. + +\section{Adding a tmpfs partition for log files} + +For the moment, the upload script was storing its log file in +\code{/www/upload/files/upload.log}. To avoid seeing this log file in +the directory containing uploaded files, let's store it in +\code{/var/log} instead. + +Add the \code{/var/log/} directory to your root filesystem and modify +the startup scripts to mount a \code{tmpfs} filesystem on this +directory. You can test your \code{tmpfs} mount command line on the +system before adding it to the startup script, in order to be sure +that it works properly. + +Modify the \code{www/cgi-bin/upload.cfg} configuration file to store +the log file in \code{/var/log/upload.log}. You will lose your log +file each time you reboot your system, but that's OK in our +system. That's what \code{tmpfs} is for: temporary data that you don't need +to keep across system reboots. + +Reboot your system and check that it works as expected. + +\section{Making a SquashFS image} + +We are going to store the root filesystem in a SquashFS filesystem in +the second partition of the SD card. + +In order to create SquashFS images on your host, you need to install +the \code{squashfs-tools} package. Now create a SquashFS image of your +NFS root directory. + +Finally, using the \code{dd} command, copy the file system image to +the second partition of the SD card. + +\section{Booting on the SquashFS partition} + +In the U-boot shell, configure the kernel command line to use the +second partition of the SD card as the root file system. Also add the +\code{rootwait} boot argument, to wait for the SD card to be properly +initialized before trying to mount the root filesystem. Since the SD +cards are detected asynchronously by the kernel, the kernel might try +to mount the root filesystem too early without \code{rootwait}. + +Check that your system still works. + +\section{Loading the kernel and DTB from the SD card} + +In order to let the kernel boot on the board autonomously, we can +copy the kernel image and DTB in the boot partition we created +previously. + +Insert the SD card in your PC, it will get auto-mounted. Copy the +kernel and device tree to the \code{env} partition. + +Insert the SD card back in the board and reset it. You should now be +able to load the DTB and kernel image from the SD card and boot with: + +\begin{ubootinput} +=> load mmc 1:2 %\zimageboardaddr% Image.gz +=> load mmc 1:2 %\dtbboardaddr% %\dtname%-custom.dtb +=> booti %\zimageboardaddr% - %\dtbboardaddr% +\end{ubootinput} + +You are now ready to modify \code{bootcmd} to boot the board +from SD card. But first, save the settings for booting from +\code{tftp}: + +\begin{ubootinput} +=> setenv bootcmdtftp %\$%{bootcmd} +\end{ubootinput} + +This will be useful to switch back to \code{tftp} booting mode +later in the labs. + +Finally, using \code{editenv bootcmd}, adjust \code{bootcmd} so that +the board starts using the kernel from the SD card. + +Now, reset the board to check that it boots in the same way from the +SD card. + +Now, the whole system (bootloader, kernel and filesystems) is +stored on the SD card. That's very useful for product demos, for +example. You can switch demos by switching SD cards, and the +system depends on nothing else. In particular, no networking is +necessary. diff --git a/labs/sysdev-block-filesystems-stm32/sysdev-block-filesystems-stm32.tex b/labs/sysdev-block-filesystems-stm32/sysdev-block-filesystems-stm32.tex index 6e0c6ba388..b7be6660c8 100644 --- a/labs/sysdev-block-filesystems-stm32/sysdev-block-filesystems-stm32.tex +++ b/labs/sysdev-block-filesystems-stm32/sysdev-block-filesystems-stm32.tex @@ -77,9 +77,9 @@ \section{Data partition on the SD card} Using the \code{mkfs.ext4} create a journaled file system on the sixth partition of the SD card: \ifdefstring{\labboard}{stm32mp1}{ -\bashcmd{$ sudo mkfs.ext4 -L data -E nodiscard /dev/mmcblk0p6}} +\bashcmd{$ sudo mkfs.ext4 -L data -E nodiscard /dev/mmcblk0p6}}{} \ifdefstring{\labboard}{stm32mp2}{ -\bashcmd{$ sudo mkfs.ext4 -L data -E nodiscard /dev/mmcblk0p5}} +\bashcmd{$ sudo mkfs.ext4 -L data -E nodiscard /dev/mmcblk0p5}}{} \begin{itemize} \item \code{-L} assigns a volume name to the partition diff --git a/labs/sysdev-buildroot/sysdev-buildroot.tex b/labs/sysdev-buildroot/sysdev-buildroot.tex index 9b79cc444a..3ef8c011eb 100644 --- a/labs/sysdev-buildroot/sysdev-buildroot.tex +++ b/labs/sysdev-buildroot/sysdev-buildroot.tex @@ -112,9 +112,11 @@ \section{Configure Buildroot} }{ \item \code{Target Architecture}: \code{ARM (little endian)} } - + \if\defstring{\labboard}{stm32mp1} \item \code{Target Architecture Variant}: \code{cortex-A7} + +(Change buildroot lab to support imx93-frdm) \item \code{Target ABI}: \code{EABIhf} \item \code{Floating point strategy}: \code{VFPv4} \fi @@ -124,6 +126,11 @@ \section{Configure Buildroot} \item \code{Floating point strategy}: \code{FP-ARMv8} \fi + \if\defstring{\labboard}{imx93-frdm} + \item \code{Target Architecture Variant}: \code{cortex-A35} + \item \code{Floating point strategy}: \code{FP-ARMv8} + \fi + \if\defstring{\labboard}{qemu} \item \code{Target Architecture Variant}: \code{cortex-A9} \item \code{Enable NEON SIMD extension support}: Enabled @@ -155,7 +162,7 @@ \section{Configure Buildroot} } (replace \code{} by your actual user name) \item \code{External toolchain gcc version}: \code{14.x} - \item \code{External toolchain kernel headers series}: {\tt \workingkernel} + \item \code{External toolchain kernel headers series}: Set it to a version older than the one selected during the build of the toolchain, which itself was older than {\tt \workingkernel}. \item \code{External toolchain C library}: \code{musl (experimental)} \item We must tell Buildroot about our toolchain configuration, so select \code{Toolchain has SSP support?} and @@ -181,8 +188,9 @@ \section{Configure Buildroot} \ifdefstring{\labboard}{stm32mp1}{\code{st/stm32mp157a-dk1-custom}}{} \ifdefstring{\labboard}{stm32mp2}{\code{st/stm32mp257f-dk-custom}}{} \ifdefstring{\labboard}{beaglebone}{\code{ti/omap/am335x-boneblack-custom}}{} - \ifdefstring{\labboard}{beagleplay}{\code{ti/k3-am625-beagleplay-custom}}{} - \ifdefstring{\labboard}{beagleplay}{\item Set \code{Kernel Binary format} to \code{Image.gz}}{} + \ifdefstring{\labboard}{beagleplay}{\code{ti/k3-am625-beagleplay-custom}} + \ifdefstring{\labboard}{imx93-frdm}{imx93-11x11-frdm-custom}{} + \ifdefstring{\arch}{ARM64}{\item Set \code{Kernel Binary format} to \code{Image.gz}}{} \end{itemize} \item \code{Target packages} \begin{itemize} diff --git a/labs/sysdev-kernel-cross-compiling/sysdev-kernel-cross-compiling.tex b/labs/sysdev-kernel-cross-compiling/sysdev-kernel-cross-compiling.tex index bf297a2e07..7c88df49e2 100644 --- a/labs/sysdev-kernel-cross-compiling/sysdev-kernel-cross-compiling.tex +++ b/labs/sysdev-kernel-cross-compiling/sysdev-kernel-cross-compiling.tex @@ -51,6 +51,14 @@ \section{Choose a particular stable version of Linux} Check the version again using the \code{make kernelversion} command to make sure you now have a \workingkernel.x version. +\if\defstring{\labboard}{imx93-frdm} +{Before continuing, we still need to apply a patch in kernel/data to add the device tree for the imx93-frdm in `arch/arm64/boot/dts/freescale` because the board is not yet supported in the kernel. +\begin{bashinput} +git apply ../data/linux-imx93-frdm.patch +\end{bashinput} +After applying the patch edit the Makefile to build imx93-11x11-frdm.dts +} + \section{Cross-compiling environment setup} To cross-compile Linux, you need to have a cross-compiling @@ -58,7 +66,7 @@ \section{Cross-compiling environment setup} previously produced, so we just need to make it available in the PATH: \begin{bashinput} -$ export PATH=$HOME/x-tools/%\ifdefstring{\labboard}{beagleplay}{aarch64-training-linux-musl}{arm-training-linux-musleabihf}%/bin:$PATH +$ export PATH=$HOME/x-tools/%\ifdefstring{\arch}{ARM64}{aarch64-training-linux-musl}{arm-training-linux-musleabihf}%/bin:$PATH \end{bashinput} Also, don't forget to either: @@ -69,7 +77,7 @@ \section{Cross-compiling environment setup} \item {\bf Or} specify them on the command line at every invocation of \code{make}, i.e.: \code{make ARCH=... CROSS_COMPILE=... } \end{itemize} -\ifdefstring{\labboard}{beagleplay}{ +\ifdefstring{\arch}{ARM64}{ \textbf{Important:} The majority of tools use \code{aarch64} to define 64 bits ARM processors. However in specific cases, the tools may use \code{arm64} to define such architecture. In the case of the kernel Makefile we will use the @@ -89,7 +97,7 @@ \section{Linux kernel configuration} \ifdefstring{\labboard}{beaglebone} {In our case look for a configuration for boards in the OMAP2 and later family which the AM335x found in the BeagleBone belongs to.}{} -\ifdefstring{\labboard}{beagleplay} +\ifdefstring{\arch}{ARM64} {If you search for a configuration file that corresponds to the \code{arm64} architecture that the kernel will use, you might see that only one \code{defconfig} file is available. We will therefore load this basic @@ -140,6 +148,11 @@ \section{Linux kernel configuration} \item Disable \kconfig{CONFIG_DRM}, which will skip support for many display controller and GPU drivers. }{} + +\ifdefstring{\labboard}{imx93-frdm}{ + \item In the \code{System Type} menu, remove support for all the SoCs except + the \code{NXP SoC support} ones and in particular \code{NXP i.MX SoC family}. + \item To use ethetnet port enable as built in \code{CONFIG_STMMAC_ETH}, \code{CONFIG_STMMAC_PLATFORM},\code{CONFIG_NVMEM_IMX_OCOTP_ELE}, and \code{CONFIG_DWMAC_IMX8}}{} \end{itemize} \ifdefstring{\labboard}{stm32mp1}{ @@ -148,7 +161,7 @@ \section{Linux kernel configuration} enables plenty of features and drivers that will not be useful on our particular board.}{} -\ifdefstring{\labboard}{beagleplay}{ +\ifdefstring{\arch}{ARM64}{ Please note that this will definitely not build the smallest and most optimized kernel for the BeaglePlay: the ARM64 \code{defconfig} enables plenty of features and drivers that will not be useful on our @@ -189,13 +202,13 @@ \section{Load and boot the kernel using U-Boot} \begin{itemize} -\item On your workstation, copy the {\tt \ifdefstring{\labboard}{beagleplay}{Image.gz}{zImage}} and DTB +\item On your workstation, copy the {\tt \ifdefstring{\arch}{ARM64}{Image.gz}{zImage}} and DTB (\texttt{\dtname}\texttt{.dtb}) to the directory exposed by the TFTP server. -\item On the target (in the U-Boot prompt), load {\tt \ifdefstring{\labboard}{beagleplay}{Image.gz}{zImage}} from +\item On the target (in the U-Boot prompt), load {\tt \ifdefstring{\arch}{ARM64}{Image.gz}{zImage}} from TFTP into RAM: \begin{ubootinput} -=> tftp %\zimageboardaddr% %\ifdefstring{\labboard}{beagleplay}{Image.gz}{zImage}% +=> tftp %\zimageboardaddr% %\ifdefstring{\arch}{ARM64}{Image.gz}{zImage}% \end{ubootinput} \item Now, also load the DTB file into RAM: @@ -205,12 +218,12 @@ \section{Load and boot the kernel using U-Boot} \item Boot the kernel with its device tree: \begin{ubootinput} -=> %\ifdefstring{\labboard}{beagleplay}{booti}{bootz} \zimageboardaddr% - %\dtbboardaddr% +=> %\ifdefstring{\arch}{ARM64}{booti}{bootz} \zimageboardaddr% - %\dtbboardaddr% \end{ubootinput} \end{itemize} -\if\defstring{\labboard}{beagleplay} +\if\defstring{\arch}{ARM64} This last command should show you an error message of this type: \bashcmd{kernel_comp_addr_r or kernel_comp_size is not provided!} diff --git a/labs/sysdev-system-integration/sysdev-system-integration.tex b/labs/sysdev-system-integration/sysdev-system-integration.tex index addaf77e4a..c54d7e8487 100644 --- a/labs/sysdev-system-integration/sysdev-system-integration.tex +++ b/labs/sysdev-system-integration/sysdev-system-integration.tex @@ -80,8 +80,9 @@ \section{Buildroot configuration} \ifdefstring{\labboard}{stm32mp1}{\code{st/stm32mp157a-dk1-custom}}{} \ifdefstring{\labboard}{stm32mp2}{\code{st/stm32mp257f-dk-custom}}{} \ifdefstring{\labboard}{beaglebone}{\code{ti/omap/am335x-boneblack-custom}}{} - \ifdefstring{\labboard}{beagleplay}{\code{ti/k3-am625-beagleplay-custom}}{} - \ifdefstring{\labboard}{beagleplay}{\item Set \code{Kernel Binary format} to \code{Image.gz}}{} + \ifdefstring{\labboard}{beagleplay}{\code{ti/k3-am625-beagleplay-custom}} + \ifdefstring{\labboard}{imx93-frdm}{imx93-11x11-frdm-custom}{} + \ifdefstring{\arch}{ARM64}{\item Set \code{Kernel Binary format} to \code{Image.gz}}{} \end{itemize} \item \code{Target packages} \begin{itemize} @@ -250,7 +251,7 @@ \section{Understanding automatic module loading with Udev} address. \begin{bashinput} -# cd %\ifdefstring{\labboard}{beagleplay}{3}{1}%-0052 +# cd X-0052 # ls -la # cat modalias of:NjoystickT(null)Cnintendo,nunchuk diff --git a/labs/sysdev-thirdparty-imx93-frdm/dependencies.dia b/labs/sysdev-thirdparty-imx93-frdm/dependencies.dia new file mode 100644 index 0000000000..3530028822 --- /dev/null +++ b/labs/sysdev-thirdparty-imx93-frdm/dependencies.dia @@ -0,0 +1,483 @@ + + + + + + + + + + + + + #Letter# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #libgpiod# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #alsa-lib# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #alsa-utils# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #ipcalc# + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/labs/sysdev-thirdparty-imx93-frdm/sysdev-thirdparty-imx93-frdm.tex b/labs/sysdev-thirdparty-imx93-frdm/sysdev-thirdparty-imx93-frdm.tex new file mode 100644 index 0000000000..3f947a23ad --- /dev/null +++ b/labs/sysdev-thirdparty-imx93-frdm/sysdev-thirdparty-imx93-frdm.tex @@ -0,0 +1,843 @@ +\subchapter{Third party libraries and applications}{Objective: Learn + how to leverage existing libraries and applications: how to + configure, compile and install them} + +To illustrate how to use existing libraries and applications, we will +extend the small root filesystem built in the {\em A tiny embedded +system} lab to add the {\em ALSA} libraries and tools to run +basic sound support tests, and the {\em libgpiod} library and +executables to manage GPIOs. {\em ALSA} stands for {\em Advanced Linux +Sound Architecture}, and is the Linux audio subsystem. + +We'll see that manually re-using existing libraries is quite tedious, +so that more automated procedures are necessary to make it +easier. However, learning how to perform these operations manually +will significantly help you when you face issues with more +automated tools. + +\section{Figuring out library dependencies} + +We're going to integrate the {\em alsa-utils}, {\em libgpiod} +and {\em ipcalc} executables. In our case, the dependency chain +for {\em alsa-utils} is quite simple, it only depends on the +{\em alsa-lib} library. {\em libgpiod} and {\em ipcalc} are standalone +and don't have any dependency. + +\includegraphics[width=\textwidth]{labs/sysdev-thirdparty-imx93-frdm/dependencies.pdf} + +Of course, all these libraries rely on the C library, which is not +mentioned here, because it is already part of the root filesystem +built in the {\em A tiny embedded system} lab. You might wonder how to +figure out this dependency tree by yourself. Basically, there are +several ways, that can be combined: + +\begin{itemize} +\item Read the library documentation, which often mentions the + dependencies; +\item Read the help message of the \code{configure script} (by running + \code{./configure --help}). +\item By running the \code{configure} script, compiling and looking + at the errors. +\end{itemize} + +To configure, compile and install all the components of our system, +we're going to start from the bottom of the tree with {\em alsa-lib}, +then continue with {\em alsa-utils}. Then, we will also build +{\em libgpiod} and {\em ipcalc}. + +\section{Preparation} + +For our cross-compilation work, we will need two separate spaces: +\begin{itemize} +\item A \emph{staging} space in which we will directly install all the + packages: non-stripped versions of the libraries, headers, + documentation and other files needed for the compilation. This + \emph{staging} space can be quite big, but will not be used on our + target, only for compiling libraries or applications; +\item A \emph{target} space, in which we will only copy the required + files from the \emph{staging} space: binaries and libraries, after + stripping, configuration files needed at runtime, etc. This target + space will take a lot less space than the \emph{staging} space, and + it will contain only the files that are really needed to make the + system work on the target. +\end{itemize} + +To sum up, the {\em staging} space will contain everything that's +needed for compilation, while the {\em target} space will contain only +what's needed for execution. + +Create the \code{$HOME/__SESSION_NAME__-labs/thirdparty} directory, +and inside, create two directories: \code{staging} and \code{target}. + +For the target, we need a basic system with BusyBox and +initialization scripts. We will re-use the system built in the {\em A + tiny embedded system} lab, so copy this system in the target +directory: + +\bashcmd{$ cp -a $HOME/__SESSION_NAME__-labs/tinysystem/nfsroot/* target/} + +Note that for this lab, a lot of typing will be required. To save time +typing, we advise you to copy and paste commands from the electronic +version of these instructions. + +\section{Testing} + +Make sure the \code{target/} directory is exported by your NFS server +to your board by modifying \code{/etc/exports} and restarting your NFS +server. + +Make your board boot from this new directory through NFS. + +\section{alsa-lib} + +{\em alsa-lib} is a library supposed to handle the interaction with +the ALSA subsystem. It is available at \url{https://alsa-project.org}. +Download version 1.2.13, and extract it +in \code{$HOME/__SESSION_NAME__-labs/thirdparty/}. + +{\bf Tip}: if the website for any of the source packages that we +need to download in the next sections is down, a great mirror +that you can use is \url{http://sources.buildroot.net/}. + +Back to {\em alsa-lib} sources, look at the \code{configure} script +and see that it has been generated by \code{autoconf} (the header +contains a sentence like {\em Generated by GNU Autoconf 2.69}). Most of +the time, \code{autoconf} comes with \code{automake}, that generates +Makefiles from \code{Makefile.am} files. So {\em alsa-lib} uses a rather +common build system. Let's try to configure and build it: + +\begin{bashinput} +$ ./configure +$ make +\end{bashinput} + +If you look at the generated binaries, you'll see that they are +x86 ones because we compiled the sources with gcc, the default compiler. +This is obviously not what we want, so let's clean-up the generated objects +and tell the \code{configure} script to use the ARM cross-compiler: + +\begin{bashinput} +$ make clean +$ CC=aarch64-linux-gcc ./configure +\end{bashinput} + +Of course, the \code{aarch64-linux-gcc} cross-compiler must be in your +\code{PATH} prior to running the configure script. The \code{CC} environment +variable is the classical name for specifying the compiler to +use. + +Quickly, you should get an error saying: + +%\footnotesize +\begin{terminaloutput} +checking whether we are cross compiling... configure: error: in `/home/tux/__SESSION_NAME__-labs/thirdparty/alsa-lib-1.2.13': +configure: error: cannot run C compiled programs. +If you meant to cross compile, use `--host'. +See `config.log' for more details +\end{terminaloutput} +\normalsize + +If you look at the \code{config.log} file, you can see that the +\code{configure} script compiles a binary with the cross-compiler +and then tries to run it on the development workstation. This is a +rather usual thing to do for a \code{configure} script, and that's +why it tests so early that it's actually doable, and bails out if not. + +Obviously, it cannot work in our case, and the scripts exits. The job +of the \code{configure} script is to test the configuration of the system. To +do so, it tries to compile and run a few sample applications to test +if this library is available, if this compiler option is supported, +etc. But in our case, running the test examples is definitely not +possible. + +We need to tell the \code{configure} script that we are cross-compiling, and +this can be done using the \code{--build} and \code{--host} options, +as described in the help of the \code{configure} script: + +\begin{verbatim} +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +\end{verbatim} + +The \code{--build} option allows to specify on which system the +package is built, while the \code{--host} option allows to specify on +which system the package will run. By default, the value of the +\code{--build} option is guessed and the value of \code{--host} is the +same as the value of the \code{--build} option. The value is guessed +using the \code{./config.guess} script, which on your system should +return \code{x86_64-pc-linux-gnu}. See +\url{https://www.gnu.org/software/autoconf/manual/html_node/Specifying-Names.html} +for more details on these options. + +So, let's override the value of the \code{--host} option: + +\bashcmd{$ ./configure --host=aarch64-linux} + +Note that \code{CC} is not required anymore. It is implied +by \code{--host}. + +The \code{configure} script should end properly now, and create a +Makefile. + +However, there is one subtle issue to handle. +We need to tell {\em alsa-lib} to disable a feature called {\em alsa topology}. +{\em alsa-lib} will build fine but we will encounter some +problems afterwards, during {\em alsa-utils} building. +So you should configure {\em alsa-lib} as follows: + +\bashcmd{$ ./configure --host=aarch64-linux --disable-topology} + +Run the \code{make} command, which should run just fine. + +Look at the result of compiling in \code{src/.libs}: a set of object files +and a set of \code{libasound.so*} files. + +The \code{libasound.so*} files are a dynamic version of the +library. The shared library itself is \code{libasound.so.2.0.0}, it has +been generated by the following command line: + +\begin{bashinput} +$ aarch64-linux-gcc -shared conf.o confmisc.o input.o output.o async.o error.o dlmisc.o socket.o shmarea.o userfile.o names.o -lm -ldl -lpthread -lrt -Wl,-soname -Wl,libasound.so.2 -o libasound.so.2.0.0 +\end{bashinput} + +And creates the symbolic links \code{libasound.so} and +\code{libasound.so.2}. + +\begin{bashinput} +$ ln -s libasound.so.2.0.0 libasound.so.2 +$ ln -s libasound.so.2.0.0 libasound.so +\end{bashinput} + +These symlinks are needed for two different reasons: + +\begin{itemize} +\item \code{libasound.so} is used at compile time when you want to + compile an application that is dynamically linked against the + library. To do so, you pass the \code{-lLIBNAME} option to the + compiler, which will look for a file named + \code{lib.so}. In our case, the compilation option is + \code{-lasound} and the name of the library file is + \code{libasound.so}. So, the \code{libasound.so} symlink is needed + at compile time; +\item \code{libasound.so.2} is needed because it is the {\em SONAME} + of the library. {\em SONAME} stands for {\em Shared Object Name}. It + is the name of the library as it will be stored in applications + linked against this library. It means that at runtime, the dynamic + loader will look for exactly this name when looking for the shared + library. So this symbolic link is needed at runtime. +\end{itemize} + +To know what's the {\em SONAME} of a library, you can use: +\bashcmd{$ aarch64-linux-readelf -d libasound.so.2.0.0} + +and look at the \code{(SONAME)} line. You'll also see that this +library needs the C library, because of the \code{(NEEDED)} line on +\code{libc.so.0}. + +The mechanism of \code{SONAME} allows to change the library without +recompiling the applications linked with this library. Let's say that +a security problem is found in the {\em alsa-lib} release that provides +{\em libasound 2.0.0}, and fixed in the next {\em alsa-lib} release, which will +now provide {\em libasound 2.0.1}. + +You can just recompile the library, install it on your target system, +change the \code{libasound.so.2} link so that it points to +\code{libasound.so.2.0.1} and restart your applications. And it will +work, because your applications don't look specifically for +\code{libasound.so.2.0.0} but for the {\em SONAME} +\code{libasound.so.2}. + +However, it also means that as a library developer, if you break the +ABI of the library, you must change the {\em SONAME}: change from +\code{libasound.so.2} to \code{libasound.so.3}. + +Finally, the last step is to tell the \code{configure} script where the +library is going to be installed. Most \code{configure} scripts consider that +the installation prefix is \code{/usr/local/} (so that the library is +installed in \code{/usr/local/lib}, the headers in +\code{/usr/local/include}, etc.). But in our system, we simply want +the libraries to be installed in the \code{/usr} prefix, so let's tell +the \code{configure} script about this: + +\begin{bashinput} +$ ./configure --host=aarch64-linux --disable-topology --prefix=/usr +$ make +\end{bashinput} + +For this library, this option may not change anything to the resulting +binaries, but for safety, it is always recommended to make sure that +the prefix matches where your library will be running on the target +system. + +Do not confuse the {\em prefix} (where the application or library will +be running on the target system) from the location where the +application or library will be installed on your host while building +the root filesystem. + +For example, {\em libasound} will be installed in +\code{$HOME/__SESSION_NAME__-labs/thirdparty/target/usr/lib/} because this is +the directory where we are building the root filesystem, but once our +target system will be running, it will see {\em libasound} in +\code{/usr/lib}. + +The prefix corresponds to the path in the target system and {\bf + never} on the host. So, one should {\bf never} pass a prefix like +\code{$HOME/__SESSION_NAME__-labs/thirdparty/target/usr}, otherwise at +runtime, the application or library may look for files inside this +directory on the target system, which obviously doesn't exist! By +default, most build systems will install the application or library in +the given prefix (\code{/usr} or \code{/usr/local}), but with most +build systems (including {\em autotools}), the installation prefix can +be overridden, and be different from the configuration prefix. + +We now only have the installation process left to do. + +First, let's make the installation in the {\em staging} space: +\bashcmd{$ make DESTDIR=$HOME/__SESSION_NAME__-labs/thirdparty/staging install} + +Now look at what has been installed by {\em alsa-lib}: +\begin{itemize} +\item Some configuration files in \code{/usr/share/alsa} +\item The headers in \code{/usr/include} +\item The shared library and its libtool (\code{.la}) file in \code{/usr/lib} +\item A pkgconfig file in \code{/usr/lib/pkgconfig}. We'll come back + to these later +\end{itemize} + +Finally, let's install the library in the {\em target} space: + +\begin{enumerate} +\item Create the \code{target/usr/lib} directory, it will contain the + stripped version of the library +\item Copy the dynamic version of the library. Only + \code{libasound.so.2} and \code{libasound.so.2.0.0} are needed, + since \code{libasound.so.2} is the {\em SONAME} of the library and + \code{libasound.so.2.0.0} is the real binary: + \begin{itemize} + \item \bashcmd{$ cp -a staging/usr/lib/libasound.so.2* target/usr/lib} + \end{itemize} +\item Measure the size of the \code{target/usr/lib/libasound.so.2.0.0} + library before stripping. +\item Strip the library: + \begin{itemize} + \item \bashcmd{$ aarch64-linux-strip target/usr/lib/libasound.so.2.0.0} + \end{itemize} +\item Measure the size of the \code{target/usr/lib/libasound.so.2.0.0} + library library again after stripping. How many unnecessary bytes + were saved? +\end{enumerate} + +Then, we need to install the {\em alsa-lib} configuration files: + +\begin{bashinput} +$ mkdir -p target/usr/share +$ cp -a staging/usr/share/alsa target/usr/share +\end{bashinput} + +Now, we need to adjust one small detail in one of the configuration +files. Indeed, \code{/usr/share/alsa/alsa.conf} assumes a UNIX group +called \code{audio} exists, which is not the case on our very small +system. So edit this file, and replace \code{defaults.pcm.ipc_gid +audio} by \code{defaults.pcm.ipc_gid 0} instead. + +And we're done with {\em alsa-lib}! + +\section{Alsa-utils} + + +Download {\em alsa-utils} from the ALSA offical webpage. We tested the lab +with version 1.2.13. The \code{gettext} package is needed during the build +so we have to install it. + +\bashcmd{sudo apt install gettext} + +Once uncompressed, we quickly discover that the {\em alsa-utils} build +system is based on the {\em autotools}, so we will work once again +with a regular \code{configure} script. + +As we've seen previously, we will have to provide the prefix and host +options: + +\bashcmd{$ ./configure --host=aarch64-linux --prefix=/usr} + +Now, we should quiclky get an error in the execution of the +\code{configure} script: + +\begin{verbatim} +checking for libasound headers version >= 1.2.5 (1.2.5)... not present. +configure: error: Sufficiently new version of libasound not found. +\end{verbatim} + +Again, we can check in \code{config.log} what the \code{configure} +script is trying to do: + +%\footnotesize +\begin{terminaloutput} +configure:15855: checking for libasound headers version >= 1.2.5 (1.2.5) +configure:15902: aarch64-linux-gcc -c -g -O2 conftest.c >&5 +conftest.c:24:10: fatal error: alsa/asoundlib.h: No such file or directory +\end{terminaloutput} +\normalsize + +Of course, since {\em alsa-utils} uses {\em alsa-lib}, it includes +its header file! So we need to tell the C compiler where the headers +can be found: there are not in the default directory +\code{/usr/include/}, but in the \code{/usr/include} directory of our +{\em staging} space. The help text of the \code{configure} script says: + +\begin{verbatim} + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory +\end{verbatim} + +Let's use it: + +\begin{bashinput} +$ CPPFLAGS=-I$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/include \%\linebreak +./configure --host=aarch64-linux --prefix=/usr +\end{bashinput} + +Now, it should stop a bit later, this time with the error: +\begin{verbatim} +checking for snd_ctl_open in -lasound... no +configure: error: No linkable libasound was found. +\end{verbatim} + +The \code{configure} script tries to compile an application against {\em + libasound} (as can be seen from the \code{-lasound} option): {\em + alsa-utils} uses {\em alsa-lib}, so the \code{configure} script +wants to make sure this library is already installed. Unfortunately, +the \code{ld} linker doesn't find it. So, let's tell the +linker where to look for libraries using the \code{-L} option followed +by the directory where our libraries are (in +\code{staging/usr/lib}). This \code{-L} option can be passed to the +linker by using the \code{LDFLAGS} at configure time, as told by the +help text of the \code{configure} script: + +\begin{verbatim} + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory +\end{verbatim} + +Let's use this \code{LDFLAGS} variable: + +\begin{bashinput} +$ LDFLAGS=-L$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/lib \ + CPPFLAGS=-I$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/include \ + ./configure --host=aarch64-linux --prefix=/usr +\end{bashinput} + +Once again, it should fail a bit further down the tests, this time +complaining about a missing {\em curses helper header}. {\em curses} +or {\em ncurses} is a graphical framework to design UIs in the +terminal. This is only used by {\em alsamixer}, one of the tools +provided by {\em alsa-utils}, that we are not going to use. +Hence, we can just disable the build of {\em alsamixer}. + +Of course, if we wanted it, we would have had to build {\em ncurses} first, +just like we built {\em alsa-lib}. + +\begin{bashinput} +$ LDFLAGS=-L$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/lib \ + CPPFLAGS=-I$HOME/__SESSION_NAME__-labs/thirdparty/staging/usr/include \ + ./configure --host=aarch64-linux --prefix=/usr \ + --disable-alsamixer +\end{bashinput} + +Then, run the compilation with \code{make}. It should complete +successfully. + +Let's now begin the installation process. Before really installing in +the staging directory, let's install in a dummy directory, to see +what's going to be installed (this dummy directory will not be used +afterwards, it is only to verify what will be installed before +polluting the staging space): + +\bashcmd{$ make DESTDIR=/tmp/alsa-utils/ install} + +The \code{DESTDIR} variable can be used with all Makefiles based on +\code{automake}. It allows to override the installation directory: +instead of being installed in the configuration prefix directory, the +files will be installed in \code{DESTDIR/configuration-prefix}. + +Now, let's see what has been installed in \code{/tmp/alsa-utils/} (run +\code{tree /tmp/alsa-utils}): + +\begin{verbatim} +/tmp/alsa-utils/ +|-- lib +| `-- udev +| `-- rules.d +| `-- 90-alsa-restore.rules +|-- usr +| |-- bin +| | |-- aconnect +| | |-- alsabat +| | |-- alsaloop +| | |-- alsaucm +| | |-- amidi +| | |-- amixer +| | |-- aplay +| | |-- aplaymidi +| | |-- arecord -> aplay +| | |-- arecordmidi +| | |-- aseqdump +| | |-- aseqnet +| | |-- axfer +| | |-- iecset +| | |-- nhlt-dmic-info +| | `-- speaker-test +| |-- sbin +| | |-- alsabat-test.sh +| | |-- alsaconf +| | |-- alsactl +| | `-- alsa-info.sh +| `-- share +| |-- alsa +| | `-- init +| | |-- 00main +| | |-- ca0106 +| | |-- default +| | |-- hda +| | |-- help +| | |-- info +| | `-- test +| |-- locale +| | |-- de +| | | `-- LC_MESSAGES +| | | `-- alsa-utils.mo +| | |-- eu +| | | `-- LC_MESSAGES +| | | `-- alsa-utils.mo +| | |-- fr +| | | `-- LC_MESSAGES +| | | `-- alsa-utils.mo +| | |-- ja +| | | `-- LC_MESSAGES +| | | |-- alsaconf.mo +| | | `-- alsa-utils.mo +| | |-- ka +| | | `-- LC_MESSAGES +| | | |-- alsaconf.mo +| | | `-- alsa-utils.mo +| | |-- ko +| | | `-- LC_MESSAGES +| | | `-- alsa-utils.mo +| | |-- ru +| | | `-- LC_MESSAGES +| | | `-- alsaconf.mo +| | `-- sk +| | `-- LC_MESSAGES +| | `-- alsa-utils.mo +| |-- man +| | |-- fr +| | | `-- man8 +| | | `-- alsaconf.8 +| | |-- man1 +| | | |-- aconnect.1 +| | | |-- alsabat.1 +| | | |-- alsactl.1 +| | | |-- alsa-info.sh.1 +| | | |-- alsaloop.1 +| | | |-- amidi.1 +| | | |-- amixer.1 +| | | |-- aplay.1 +| | | |-- aplaymidi.1 +| | | |-- arecord.1 -> aplay.1 +| | | |-- arecordmidi.1 +| | | |-- aseqdump.1 +| | | |-- aseqnet.1 +| | | |-- axfer.1 +| | | |-- axfer-list.1 +| | | |-- axfer-transfer.1 +| | | |-- iecset.1 +| | | |-- nhlt-dmic-info.1 +| | | `-- speaker-test.1 +| | |-- man7 +| | `-- man8 +| | `-- alsaconf.8 +| `-- sounds +| `-- alsa +| |-- Front_Center.wav +| |-- Front_Left.wav +| |-- Front_Right.wav +| |-- Noise.wav +| |-- Rear_Center.wav +| |-- Rear_Left.wav +| |-- Rear_Right.wav +| |-- Side_Left.wav +| `-- Side_Right.wav +`-- var + `-- lib + `-- alsa + +37 directories, 68 files +\end{verbatim} + +So, we have: +\begin{itemize} +\item The {\em udev} rules in \code{lib/udev} +\item The {\em alsa-utils} binaries in \code{/usr/bin} and \code{/usr/sbin} +\item Some sound samples in \code{/usr/share/sounds} +\item The various translations in \code{/usr/share/locale} +\item The manual pages in \code{/usr/share/man/}, explaining how to + use the various tools +\item Some configuration samples in \code{/usr/share/alsa}. +\end{itemize} + +Now, let's make the installation in the {\em staging} space: + +\bashcmd{$ make DESTDIR=$HOME/__SESSION_NAME__-labs/thirdparty/staging/ install} + +Then, let's manually install only the necessary files in the {\em target} +space. We are only interested in \code{speaker-test}: + +\begin{bashinput} +$ cd .. +$ cp -a staging/usr/bin/speaker-test target/usr/bin/ +$ aarch64-linux-strip target/usr/bin/speaker-test +\end{bashinput} + +And we're finally done with {\em alsa-utils}! + +Now test that all is working fine by running the \code{speaker-test} util on +your board, with the headset provided by your instructor plugged +in. You may need to add the missing libraries from the toolchain +install directory. + +Now you can use: + +\begin{itemize} + +\item \code{speaker-test} with no arguments to generate {\em pink noise} + +\item \code{speaker-test -t sine} to generate a {\em sine wave}, +optionally with \code{-f } for a specific frequency + +\end{itemize} + +There you are: you built and ran your first program depending +on a library different from the C library. + +\section{libgpiod} + +\subsection{Compiling libgpiod} + +We are now going to use {\em libgpiod} (instead of the +deprecated interface in \code{/sys/class/gpio}, whose executables +(\code{gpiodetect}, \code{gpioset}, \code{gpioget}...) will +allow us to drive and manage GPIOs from shell scripts. + +Here, we will be using the 2.2 version of {\em libgpiod}. + +\begin{bashinput} +git clone https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git +cd libgpiod +git checkout v2.2 +\end{bashinput} + +As we are not starting from a release, we will need to install +further development tools to generate some files like the +\code{configure} script: + +\bashcmd{sudo apt install autoconf-archive pkg-config} + +Now let's generate the files which are present in a release: + +\bashcmd{./autogen.sh} + +Run \code{./configure --help} script, and see that this script provides +a \code{--enable-tools} option which allows to build the userspace +executables that we want. + +As this project doesn't have any external library dependency, let's +configure {\em libgpiod} in a similar way as {\em alsa-utils}: + +\begin{bashinput} +$ ./configure --host=aarch64-linux --prefix=/usr --enable-tools +\end{bashinput} + +Now, compile the software: + +\bashcmd{$ make} + +Installation to the {\em staging} space can be done using the +classical \code{DESTDIR} mechanism: + +\begin{bashinput} +$ make DESTDIR=$HOME/__SESSION_NAME__-labs/thirdparty/staging/ install +\end{bashinput} + +And finally, only manually install and strip the files +needed at runtime in the {\em target} space: + +\begin{bashinput} +$ cd .. +$ cp -a staging/usr/lib/libgpiod.so.3* target/usr/lib/ +$ aarch64-linux-strip target/usr/lib/libgpiod* +$ cp -a staging/usr/bin/gpio* target/usr/bin/ +$ aarch64-linux-strip target/usr/bin/gpio* +\end{bashinput} + +\subsection{Testing libgpiod} + +First, connect \code{GPIO PE1} (pin D2 of connector CN14) connected +to ground (pin 7 of connector CN16), as in the +{\em Accessing Hardware Devices} lab. + +Now, let's run the \code{gpiodetect} command on the target, and check that +you can list the various GPIO banks on your system. + +\begin{bashinput} +# gpiodetect +gpiochip0 [43810000.gpio] (32 lines) +gpiochip1 [43820000.gpio] (32 lines) +gpiochip2 [43830000.gpio] (32 lines) +gpiochip3 [47400000.gpio] (32 lines) +gpiochip4 [1-0022] (24 lines) +\end{bashinput} + +We can then get details on gpiochip0 by running +\code{gpioinfo -c gpiochip0} or on all GPIOs by simply running +\code{gpioinfo}. + +You can now read the state of your GPIO\_21: + +\begin{bashinput} +# gpioget -c gpiochip0 21 +"1"=inactive +\end{bashinput} + +Now, connect your wire to 3V3 . You should now +read: + +\begin{bashinput} +# gpioget -c gpiochip0 21 +"1"=active +\end{bashinput} + +You see that you didn't have to configure the GPIO as input. {\em +libgpiod} did that for you. + +If you have an LED and a small breadboard (or M-F breadboard wires), +you could also try to drive the GPIO in output mode. Connect the short +pin of the LED to GND, and the long one to the GPIO. Then then following +command should light up the diode: + +\begin{bashinput} +# gpioset -c gpiochip0 -t0 11=1 +\end{bashinput} + +The \code{-t0} option makes \code{gpioset} terminate by itself +immediately instead of waiting for the user to interrupt it. + +Here's how to turn the LED off: + +\begin{bashinput} +# gpioset -c gpiochip0 -t0 11=0 +\end{bashinput} + +\code{gpioset} offers many more options. Run \code{gpioset -h} to +check by yourself. + +\section{ipcalc} + +After practicing with autotools based packages, let's build {\em ipcalc}, which +is using {\em Meson} as build system. We won't really need this utility +in our system, but at least it has no dependencies and therefore +offers an easy way to build our first {\em Meson} based package. + +So, first install the \code{meson} package: + +\bashcmd{$ sudo apt install meson} + +In the main lab directory, then let's check out the sources through +\code{git}: + +\begin{bashinput} +$ git clone https://gitlab.com/ipcalc/ipcalc.git +$ cd ipcalc/ +$ git checkout 1.0.3 +\end{bashinput} + +To cross-compile with {\em Meson}, we need to create a {\em cross file}. +Let's create the \code{../cross-file.txt} file with the below contents: + +\begin{verbatim} +[binaries] +c = 'aarch64-linux-gcc' + +[host_machine] +system = 'linux' +cpu_family = 'arm64' +cpu = 'cortex-a8' +endian = 'little' +\end{verbatim} + +We also need to create a special directory for building: + +\begin{bashinput} +$ mkdir cross-build +$ cd cross-build +\end{bashinput} + +We can now have \code{meson} create the Ninja build files for us: + +\begin{bashinput} +$ meson --cross-file ../../cross-file.txt --prefix /usr .. +\end{bashinput} + +We are now ready to build {\em ipcalc}: + +\begin{bashinput} +$ ninja +\end{bashinput} + +And now install \code{ipcalc} to the build space: + +\begin{bashinput} +$ DESTDIR=$HOME/__SESSION_NAME__-labs/thirdparty/staging ninja install +\end{bashinput} + +Check that the \code{staging/usr/bin/ipcalc} file is indeed an ARM +executable. + +The last thing to do is to copy it to the target space and strip it: + +\begin{bashinput} +$ cd ../.. +$ cp staging/usr/bin/ipcalc target/usr/bin/ +$ aarch64-linux-strip target/usr/bin/ipcalc +\end{bashinput} + +Note that we could have asked \code{ninja install} to strip the +executable for us when installing it into the staging directory. +To do, this, we would have added a \code{strip} entry in the cross file, +and passed \code{--strip} to {\em Meson}. However, it's better to keep +files unstripped in the staging space, in case we need to debug them. + +You can now test that \code{ipcalc} works on the target: + +\begin{bashinput} +# ipcalc 192.168.0.100 +Address: 192.168.0.100 +Address space: Private Use +\end{bashinput} + +\section{Final touch} + +To finish this lab completely, and to be consistent with what we've done before, +let's strip the C library and its loader too. + +First, check the initial size of the binaries: +\bashcmd{$ ls -l target/lib} + +Then strip the binaries in \code{/lib}: +\begin{bashinput} +$ chmod +w target/lib/*.so.* +$ aarch64-linux-strip target/lib/*.so.* +\end{bashinput} + +And check the final size: +\bashcmd{$ ls -l target/lib/} diff --git a/labs/sysdev-tinysystem/sysdev-tinysystem.tex b/labs/sysdev-tinysystem/sysdev-tinysystem.tex index 80e081573f..0f01e12eb6 100644 --- a/labs/sysdev-tinysystem/sysdev-tinysystem.tex +++ b/labs/sysdev-tinysystem/sysdev-tinysystem.tex @@ -90,7 +90,7 @@ \section{Booting the system} nfsroot=192.168.0.1:/home//__SESSION_NAME__-labs/tinysystem/nfsroot,nfsvers=3,tcp rw \end{ubootinput} \else -\if\defstring{\labboard}{beagleplay} +\if\defstring{\arch}{ARM64} \begin{ubootinput} => setenv bootargs ${bootargs} root=/dev/nfs ip=192.168.0.100:::::eth0 nfsroot=192.168.0.1:/home//__SESSION_NAME__-labs/tinysystem/nfsroot,nfsvers=3,tcp rw diff --git a/labs/sysdev-u-boot-imx93-frdm/indent.log b/labs/sysdev-u-boot-imx93-frdm/indent.log new file mode 100644 index 0000000000..7b9b6e8573 --- /dev/null +++ b/labs/sysdev-u-boot-imx93-frdm/indent.log @@ -0,0 +1,22 @@ +INFO: latexindent version 3.23.6, 2024-01-17, a script to indent .tex files + latexindent lives here: /usr/share/texlive/texmf-dist/scripts/latexindent/ + Fri Jun 13 09:46:15 2025 + Filename: /home/antoine/training-materials/labs/sysdev-u-boot-imx93-frdm/sysdev-u-boot-imx93-frdm.tex +INFO: Processing switches: +INFO: Directory for backup files and indent.log: + /home/antoine/training-materials/labs/sysdev-u-boot-imx93-frdm +INFO: YAML settings read: defaultSettings.yaml + Reading defaultSettings.yaml from /usr/share/texlive/texmf-dist/scripts/latexindent/defaultSettings.yaml +INFO: YAML reading settings + Home directory is /home/antoine + latexindent.pl didn't find indentconfig.yaml or .indentconfig.yaml + see all possible locations: https://latexindentpl.readthedocs.io/en/latest/sec-appendices.html#indentconfig-options) +INFO: Phase 1: searching for objects +INFO: Phase 2: finding surrounding indentation +INFO: Phase 3: indenting objects +INFO: Phase 4: final indentation check +INFO: Output routine: + Not outputting to file; see -w and -o switches for more options. + -------------- +INFO: Please direct all communication/issues to: + https://github.com/cmhughes/latexindent.pl diff --git a/labs/sysdev-u-boot-imx93-frdm/sysdev-u-boot-imx93-frdm.tex b/labs/sysdev-u-boot-imx93-frdm/sysdev-u-boot-imx93-frdm.tex new file mode 100644 index 0000000000..5b41aeaa57 --- /dev/null +++ b/labs/sysdev-u-boot-imx93-frdm/sysdev-u-boot-imx93-frdm.tex @@ -0,0 +1,525 @@ +\subchapter{Bootloader - TF-A and U-Boot}{Objectives: Set up serial + communication, compile and install the U-Boot bootloader, use basic + U-Boot commands, set up TFTP communication with the development + workstation.} + +As the bootloader is the first piece of software executed by a +hardware platform, the installation procedure of the bootloader is +very specific to the hardware platform. There are usually two cases: + +\begin{itemize} + +\item The processor offers nothing to ease the installation of the + bootloader, in which case the JTAG has to be used to initialize + flash storage and write the bootloader code to flash. Detailed + knowledge of the hardware is of course required to perform these + operations. + +\item The processor offers a monitor, implemented in ROM, and through + which access to the memories is made easier. + +\end{itemize} + +The i.MX93 processor falls into the second category. At startup, the ROM code +initializes minimal hardware (clocks, RAM, etc.) and selects the boot source +based on BOOT MODE pins and fuse values. It then looks for a valid boot +container, typically stored on an SD card, eMMC, NOR flash, or received +USB. + +The boot image container must include at least one valid OEM container +(mandatory) and may include an optional NXP container. These containers hold +firmware images for the Cortex-A55 and Cortex-M33 cores. The images are +authenticated by the EdgeLock Secure Enclave. If authentication fails or no +valid image is found, the processor enters a fallback mode using the Serial +Download Protocol (SDP), allowing bootloader installation via USB with tools +like uuu. + +This mechanism allows an i.MX93-based board such as the FRDM-i.MX93 to boot +even without any pre-installed software, making initial setup easier. + +\section{Setup} + +Go to the \code{$HOME/__SESSION_NAME__-labs/bootloader} directory. + +\section{Setting up serial communication with the board} + +Plug the USB-C to USB-C cable into the Discovery board. The board has two USB-C ports: connect the power supply to the one labeled POWER, and use the one labeled DEBUG for data. The DEBUG port provides several debugging interfaces, including a serial console. Once connected to your computer, a new serial port should appear, {\tt \hosttty}. + +You can also see this device appear by looking at the output of +\code{sudo dmesg}. + +To communicate with the board through the serial port, install a +serial communication program, such as \code{picocom}: + +\bashcmd{$ sudo apt install picocom} + +If you run {\tt ls -l \hosttty}, you can also see that only +\code{root} and users belonging to the \code{dialout} group have +read and write access to the serial console. Therefore, you need +to add your user to the \code{dialout} group: + +\bashcmd{$ sudo adduser $USER dialout} + +{\bf Important}: for the group change to be effective, you have to +reboot your computer (at least on Ubuntu 24.04) and log in again. +A workaround is to run \code{newgrp dialout}, but it is not global. +You have to run it in each terminal. + +Run {\tt picocom -b 115200 \hosttty}, to start serial +communication on {\tt \hosttty}, with a baudrate of 115200. +If you wish to exit \code{picocom}, press \code{[Ctrl][a]} followed by +\code{[Ctrl][x]}. + +Don't be surprised if you don't get anything on the serial console yet, +even if you reset the board. That's because the SoC has nothing to boot +on yet. We will prepare a micro SD card to boot on in the next paragraphs. + +\section{TF-A and U-Boot relationship} + +The boot process on the i.MX93 platform consists of two main stages. Upon +power-up, the SoC’s internal ROM code executes and selects a boot image +container set from the configured boot device (e.g., SD card or QSPI flash). It +authenticates the container headers, then loads and verifies the contained +images with the help of the EdgeLock Secure Enclave. + +The ROM code loads the first-stage bootloader (FSBL) embedded in ROM, which +handles early hardware initialization, such as DRAM setup. Once complete, +control is passed to the second-stage bootloader (SSBL), which continues the +boot process and eventually launches the operating system. + +In our setup, the FSBL is provided by the ROM (no external BL2 is needed), and +the SSBL is U-Boot. Both are packaged into a boot container using NXP’s boot +image format. The container may also include components like the secure monitor +(BL31), but in this setup, no trusted execution environment (OP-TEE) is used. +These images are bundled into a Firmware Image Package (FIP) during the build +process. + +\section{TF-A setup} + +Get the mainline TF-A sources: + +\begin{bashinput} +$ cd .. +$ git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git +$ cd trusted-firmware-a/ +$ git checkout v2.12.0 +\end{bashinput} + +Two configuration parameters have to be passed to the Makefile: +\begin{itemize} +\item Specify the cross-compiler prefix (the part before gcc in the + cross-compiler executable name), either using the environment + variable:\inlinebash{$ export CROSS_COMPILE=aarch64-linux-}, or just by + adding it to the \code{make} command line. + +\item And we have to specify the platform \code{PLAT=imx93} +\end{itemize} + +We can now generate the \code{bl31} needed to build the container with u-boot. +\begin{bashinput} +$ make PLAT=imx93 +\end{bashinput} + +At the end of the build, the important output files generated are +located in \code{build/imx93/release/}. We will find \code{bl31.bin} the EL3 runtime firmware. + +\section{U-Boot setup} + +Download U-Boot: + +\begin{bashinput} +$ git clone https://github.com/u-boot/u-boot.git +$ cd u-boot +$ git checkout v2025.04 +\end{bashinput} + +Before continuing, we need to apply the patches located in bootloader/data/patches/u-boot/. These patches are necessary because the imx93-frdm board is not yet supported upstream. + +Get an understanding of U-Boot's configuration and compilation steps +by reading the \code{README} file, and specifically the {\em Building +the Software} section. + +Basically, you need to: + +\begin{enumerate} + +\item Retrieve the previously compiled bl31.bin file and place it in the U-Boot directory. +\bashcmd{$ cp ../trusted-firmware-a/build/imx93/release/bl31.bin ./} + +\item Retrieve the NXP firmware required for DDR memory support +\begin{bashinput} +$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.25-27879f8.bin +$ chmod +x firmware-imx-8.25-27879f8.bin +$ ./firmware-imx-8.25-27879f8.bin +\end{bashinput} +Once the conditions are accepted, copy the following files located in +\code{firmware-imx-8.25-27879f8/firmware/ddr/synopsys/} to the root of the U-Boot source tree: + +lpddr4\_dmem\_1d\_v202201.bin \\ +lpddr4\_dmem\_2d\_v202201.bin \\ +lpddr4\_imem\_1d\_v202201.bin \\ +lpddr4\_imem\_2d\_v202201.bin + +\item Specify the cross-compiler prefix +(the part before \code{gcc} in the cross-compiler executable name) and the +architecture: +\bashcmd{$ export CROSS_COMPILE=aarch64-linux-} + +\item Run \inlinebash{$ make _defconfig}, where the list of available + configurations can be found in the \code{configs/} directory. We will use the standard one (\code{imx93_11x11_frdm}). + +\item Now that you have a valid initial configuration, you can now + run \inlinebash{$ make menuconfig} to further edit your bootloader features. + + \begin{itemize} + + \item In the \code{Environment} submenu, we will configure U-Boot so + that it stores its environment inside a file called \code{uboot.env} + in an ext4 filesystem: + \begin{itemize} + \item Disable \code{Environment is not stored}. We want changes to variables to + be persistent across reboots + \item Enable \code{Environment is in a EXT4 filesystem}. Disable all other + options for environment storage (e.g.SPI, UBI) + \item The value for \code{Name of the block device for the environment} should be \code{mmc} + \item The value for \code{Device and partition for where to store + the environment in EXT4} should be \code{1:1} which indicates + we want to store the environment in the 1th partition of the + second MMC device (sd card). + \item The value for \code{Name of the EXT4 file to use for the + environment} should be \code{/uboot.env}, which indicates the + filename inside which the U-Boot environment will be stored + \item The value for \code{mmc device number} should be \code{-1}, to use our sdcard + \end{itemize} + \end{itemize} + +Install the following packages which should be needed to compile U-Boot for +your board: + +\begin{bashinput} +$ sudo apt install libssl-dev device-tree-compiler swig \ + python3-dev python3-setuptools uuid-dev libgnutls28-dev +\end{bashinput} + +\item Finally, run \bashcmd{make DEVICE_TREE=imx93-11x11-frdm} + which will build U-Boot + \footnote{You can speed up the + compiling by using the \code{-jX} option with \code{make}, where X + is the number of parallel jobs used for compiling. Twice the + number of CPU cores is a good value.}. + The \code{DEVICE_TREE} variable specifies the specific + Device Tree that describes our hardware board. If you wish to +run just make, specify our board’s device tree name on Device Tree Control → Default Device Tree +for DT Control option. + +This will generate a flash.bin file, which is our OEM container. + +{\bf Note}: u-boot build may fail on your machine if you have a recent +version of python. Such issue is +\href{https://source.denx.de/u-boot/u-boot/-/commit/a63456b9191fae2fe49f4b121e025792022e3950}{already +fixed upstream}, but not in the version targeted for the training. To get the +relevant fix, +you can cherry-pick the fix onto your local branch: + +\code{git cherry-pick a63456b9191fae2fe49f4b121e025792022e3950} +\end{enumerate} + +\section{Flashing the bootloaders} + +The ROM code on the i.MX93 platform is the first piece of software executed by +the Cortex-A55 core in secure mode. It selects the boot source based on the +configuration fuses and boot pins, and locates a valid boot container from the +selected device (e.g., SD card or QSPI flash). The ROM verifies the container +headers and authenticates the contained images with the help of the EdgeLock +Secure Enclave. + +Once a valid image is found—typically the BL31 firmware—it is loaded into SRAM +and executed. BL31 then initializes essential hardware components such as the +clock tree and DDR controller. It subsequently loads and transfers control to +the Second Stage Bootloader (SSBL), which is U-Boot in our case. U-Boot +continues system initialization and is responsible for loading and booting the +Linux kernel. + +So, as far as bootloaders are concerned, the SD card partitioning will +look like: + +\begin{verbatim} +Number Start End Size File system Name Flags + 1 2.00MiB 10.0MiB 8.00MiB ext4 bootfs + +\end{verbatim} +We intentionally leave the initial space on the device unallocated, so we can +later burn our flash.bin there. Then, we create a partition to store U-Boot +environment variables. + +On your workstation, plug in the SD card your instructor gave you. Type +the \code{sudo dmesg} command to see which device is used by your +workstation. In case the device is \code{/dev/mmcblk0}, you will see +something like + +\begin{verbatim} +[46939.425299] mmc0: new high speed SDHC card at address 0007 +[46939.427947] mmcblk0: mmc0:0007 SD16G 14.5 GiB +\end{verbatim} + +The device file name may be different (such as \code{/dev/sdb} +if the card reader is connected to a USB bus (either internally +or using a USB card reader). + +In the following instructions, we will assume that your SD card is +seen as \code{/dev/mmcblk0} by your PC workstation. + +Type the \code{mount} command to check your currently mounted +partitions. If SD partitions are mounted, unmount them: + +\bashcmd{$ sudo umount /dev/mmcblk0p*} + +We will erase the existing partition table and partition contents +by simply zero-ing the first 128 MiB of the SD card: + +\bashcmd{$ sudo dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=128} + +Now, let's use the \code{parted} command to create the partitions that +we are going to use: + +\bashcmd{$ sudo parted /dev/mmcblk0} + +The ROM monitor handles {\em GPT} partition tables, let's create one: + +\begin{verbatim} +(parted) mklabel gpt +\end{verbatim} + +Then, the 4 partitions are created with: +\begin{verbatim} +(parted) unit mib +(parted) mkpart bootfs ext4 2 10 +\end{verbatim} + +You can verify everything looks right with: + +\begin{verbatim} +(parted) print +Model: SD SA08G (sd/mmc) +Disk /dev/mmcblk0: 15278080s +Sector size (logical/physical): 512B/512B +Partition Table: +Disk Flags: + +Number Start End Size File system Name Flags + 1 2.00MiB 10.0MiB 8.00MiB ext4 bootfs + +\end{verbatim} + +Once done, quit: +\begin{verbatim} +(parted) quit +\end{verbatim} + +{\em Note: \code{parted} is definitely not very user friendly compared +to other tools to manipulate partitions (such as \code{cfdisk}), but +that's the only tool which supports assigning names to GPT partitions. +In your projects, you could use \code{gparted}, which is a more +friendly graphical front-end on top of \code{parted}.} + +Now, format the boot partition as an ext4 filesystem. This is where +U-Boot saves its environment: +\bashcmd{$ sudo mkfs.ext4 -L boot -O ^metadata_csum /dev/mmcblk0p1} + +The \code{-O ^metadata_csum} option allows to create the filesystem +without enabling metadata checksums, which U-Boot doesn't seem to +support yet. + +Now burn the flash.bin container to the SD card. +\begin{bashinput} +$ sudo dd if=./flash.bin of=/dev/mmcblk0 bs=1k seek=32 conv=fsync +\end{bashinput} + +\section{Testing the bootloaders} + +Insert the SD card in the board slot. You can now power-up the board +by connecting the USB-C cable to the board, \code{POWER} and +to your PC at the other end. Check that it boots your new bootloaders. +You can verify this by checking the build dates: + +\begin{verbatim} +U-Boot SPL 2025.07-rc2-00029-g354a2daf873f (Jun 13 2025 - 10:20:47 +0200) +SOC: 0xa1009300 +LC: 0x40010 +PMIC: PCA9451A +PMIC: Over Drive Voltage Mode +DDR: 3733MTS +DDR: 3733MTS +found DRAM 2GB DRAM matched +M33 prepare ok +Normal Boot +Trying to boot from BOOTROM +Boot Stage: Primary boot +image offset 0x8000, pagesize 0x200, ivt offset 0x0 +Load image from 0x3a000 by ROM_API +NOTICE: TRDC init done +NOTICE: BL31: v2.12.0(release):v2.13-rc1-2-gb68861c72 +NOTICE: BL31: Built : 10:37:35, May 20 2025 + + +U-Boot 2025.07-rc2-00029-g354a2daf873f (Jun 13 2025 - 10:20:47 +0200) + +Reset Status: POR + +CPU: NXP i.MX93(52) Rev1.1 A55 at 1700 MHz +CPU: Industrial temperature grade (-40C to 105C) at 49C +Model: NXP i.MX93 11X11 FRDM board +DRAM: 2 GiB +BOARD: V1.0(ADC2:690,ADC3:319) +Core: 217 devices, 28 uclasses, devicetree: separate +WDT: Started wdog@42490000 with servicing every 1000ms (40s timeout) +MMC: FSL_SDHC: 0, FSL_SDHC: 1 +Loading Environment from EXT4... ** File not found /uboot.env ** + +** Unable to read "/uboot.env" from mmc1:1 ** +In: serial +Out: serial +Err: serial + +BuildInfo: + - ELE firmware not included + +Net: +Warning: ethernet@42890000 (eth1) using random MAC address - 7e:ec:88:77:c0:54 + +Warning: ethernet@428a0000 (eth0) using random MAC address - 3a:eb:d6:c9:94:b6 +eth0: ethernet@428a0000, eth1: ethernet@42890000 [PRIME] +=> +\end{verbatim} + +In U-Boot, type the \code{help} command, and explore the few commands +available. + +\subsection{Adding a new command to the U-Boot shell} + +Check whether the \code{config} command is available. This command +allows to dump the configuration settings U-Boot was compiled from. + +If it's not, go back to U-Boot's configuration and enable it. + +Re-run the build of TF-A, copy bl31.bin, then rebuild U-Boot. Re-flash the SD +card with the new flash.bin and verify that the command is now available and +as expected. + +\subsection{Playing with the U-Boot environment} + +Display the U-Boot environment using \code{printenv}. + +Set a new U-Boot variable \code{foo} to a value of your choice, using +\code{setenv}, and verify it has been set. Reset the board, and check +if \code{foo} is still defined: it should not. + +Now repeat this process, but before resetting the board, use +\code{saveenv}. After the reset, check the \code{foo} variable is +still defined. + +Now reset the environment to its default settings using \code{env + default -a}, and save these changes using \code{saveenv}. + +\section{Setting up networking} + +The next step is to configure U-boot and your workstation to let your +board download files, such as the kernel image and Device Tree Binary +(DTB), using the TFTP protocol through a network connection. + +With a network cable, connect the Ethernet port of +your board to the one of your computer. If your computer already has a +wired connection to the network, your instructor will provide you with +a USB Ethernet adapter. A new network interface should appear on your +Linux system. + +\subsection{Network configuration on the target} + +Let's configure networking in U-Boot: + +\begin{itemize} + \item \code{ipaddr}: IP address of the board + \item \code{serverip}: IP address of the PC host +\end{itemize} + +\begin{ubootinput} +=> setenv ipaddr 192.168.0.100 +=> setenv serverip 192.168.0.1 +\end{ubootinput} + +Of course, make sure that this address belongs to a separate network +segment from the one of the main company network. + +To make these settings permanent, save the environment: + +\begin{ubootinput} +=> saveenv +\end{ubootinput} + +\subsection{Network configuration on the PC host} + +To configure your network interface on the workstation side, we need +to know the name of the network interface connected to your board. + +Find the name of this interface by typing: +\bashcmd{=> ip a} + +The network interface name is likely to be +\code{enxxx}\footnote{Following the {\em Predictable Network Interface +Names} convention: +\url{https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/}}. +If you have a pluggable Ethernet device, it's easy to identify as it's +the one that shows up after pluging in the device. + +Then, instead of configuring the host IP address from NetworkManager's +graphical interface, let's do it through its command line interface, +which is so much easier to use: + +\bashcmd{$ nmcli con add type ethernet ifname en... ip4 192.168.0.1/24} + +\section{Setting up the TFTP server} + +Let's install a TFTP server on your development workstation: + +\begin{verbatim} +sudo apt install tftpd-hpa +\end{verbatim} + +You can then test the TFTP connection. First, put a small text file in +the directory exported through TFTP on your development +workstation. Then, from U-Boot, do: + +\begin{ubootinput} +=> tftp %\zimageboardaddr% textfile.txt +\end{ubootinput} + +The \code{tftp} command should have downloaded the +\code{textfile.txt} file from your development workstation into +the board's memory at location {\tt \zimageboardaddr}\footnote{ +This location is part of the board DRAM. If you want +to check where this value comes from, you can check the SoC +datasheet at +\url{https://www.st.com/resource/en/reference_manual/dm00327659.pdf}. +It's a big document (more than 4,000 pages). In this document, look +for \code{Memory organization} and you will find the SoC memory map. +You will see that the address range for the memory controller +({\em DDRC}) +starts at the address we are looking for. +You can also try with other values in the RAM address range.}. + +You can verify that the download was successful by dumping the +contents of the memory: + +\begin{ubootinput} +=> md %\zimageboardaddr% +\end{ubootinput} + +We will see in the next labs how to use U-Boot to download, flash and +boot a kernel. + +\section{Rescue binaries} + +If you have trouble generating binaries that work properly, or later +make a mistake that causes you to lose your bootloader binaries, you +will find working versions under \code{data/} in the current lab +directory. diff --git a/mk/embedded-linux-bbb.mk b/mk/embedded-linux-bbb.mk index 1f2d67539b..1c1da76e5f 100644 --- a/mk/embedded-linux-bbb.mk +++ b/mk/embedded-linux-bbb.mk @@ -7,6 +7,7 @@ EMBEDDED_LINUX_BBB_SLIDES = \ discovery-board-also-supported \ beagleplay-board-also-supported \ stm32mp2-board-also-supported \ + imx93-frdm-board-also-supported \ course-information \ sysdev-intro \ sysdev-dev-environment \ diff --git a/mk/embedded-linux-beagleplay.mk b/mk/embedded-linux-beagleplay.mk index 754742f49f..9512b1a93e 100644 --- a/mk/embedded-linux-beagleplay.mk +++ b/mk/embedded-linux-beagleplay.mk @@ -7,6 +7,7 @@ EMBEDDED_LINUX_BEAGLEPLAY_SLIDES = \ discovery-board-also-supported \ beagleboneblack-board-also-supported \ stm32mp2-board-also-supported \ + imx93-frdm-board-also-supported \ course-information \ sysdev-intro \ sysdev-dev-environment \ diff --git a/mk/embedded-linux-imx93-frdm.mk b/mk/embedded-linux-imx93-frdm.mk new file mode 100644 index 0000000000..1cc07f3046 --- /dev/null +++ b/mk/embedded-linux-imx93-frdm.mk @@ -0,0 +1,65 @@ +EMBEDDED_LINUX_IMX93_FRDM_SLIDES = \ + first-slides \ + about-us \ + course-information-title \ + discovery-board-imx93-frdm \ + sysdev-shopping-list-imx93-frdm \ + discovery-board-also-supported \ + beagleboneblack-board-also-supported \ + beagleplay-board-also-supported \ + stm32mp2-board-also-supported \ + course-information \ + sysdev-intro \ + sysdev-dev-environment \ + setup-lab \ + sysdev-toolchains-title \ + sysdev-toolchains-definition \ + sysdev-toolchains-options \ + sysdev-toolchains-obtaining \ + sysdev-toolchains-lab \ + sysdev-bootloaders-title \ + sysdev-bootloaders-sequence \ + sysdev-bootloaders-u-boot \ + sysdev-bootloaders-tf-a \ + sysdev-bootloaders-lab \ + sysdev-linux-intro-title \ + sysdev-linux-intro-features \ + sysdev-linux-intro-versioning \ + sysdev-linux-intro-sources \ + sysdev-fetching-linux-kernel-sources-lab \ + sysdev-kernel-building \ + sysdev-customizing-dt \ + sysdev-kernel-booting \ + sysdev-linux-intro-lab-cross-compilation \ + sysdev-root-filesystem-title \ + sysdev-root-filesystem-principles \ + initramfs \ + sysdev-root-filesystem-contents \ + sysdev-root-filesystem-virtual-fs \ + sysdev-root-filesystem-minimal \ + boot-sequence-initramfs \ + sysdev-busybox \ + sysdev-hw-devices \ + sysdev-block-filesystems \ + sysdev-flash-filesystems \ + sysdev-cross-compiling-user-space \ + sysdev-build-systems \ + sysdev-licensing \ + sysdev-software-stacks \ + sysdev-application-development \ + sysdev-references \ + last-slides \ + sysdev-extra-slides + +EMBEDDED_LINUX_IMX93_FRDM_LABS = setup \ + sysdev-toolchain \ + sysdev-u-boot-imx93-frdm \ + sysdev-kernel-fetch-sources \ + sysdev-kernel-cross-compiling \ + sysdev-tinysystem \ + sysdev-accessing-hardware-imx93-frdm \ + sysdev-block-filesystems-imx93-frdm \ + sysdev-thirdparty-imx93-frdm \ + sysdev-buildroot \ + sysdev-system-integration \ + sysdev-application-development-and-debugging \ No newline at end of file diff --git a/mk/embedded-linux-qemu.mk b/mk/embedded-linux-qemu.mk index 4e98c7a4b6..9bba746e5f 100644 --- a/mk/embedded-linux-qemu.mk +++ b/mk/embedded-linux-qemu.mk @@ -7,6 +7,7 @@ EMBEDDED_LINUX_QEMU_SLIDES = \ beagleboneblack-board-also-supported \ beagleplay-board-also-supported \ stm32mp2-board-also-supported \ + imx93-frdm-board-also-supported \ course-information \ sysdev-intro \ sysdev-dev-environment \ diff --git a/mk/embedded-linux-stm32mp2.mk b/mk/embedded-linux-stm32mp2.mk index 7756b34b6c..c7c843a0e8 100644 --- a/mk/embedded-linux-stm32mp2.mk +++ b/mk/embedded-linux-stm32mp2.mk @@ -7,6 +7,7 @@ EMBEDDED_LINUX_STM32MP2_SLIDES = \ discovery-board-also-supported \ beagleboneblack-board-also-supported \ beagleplay-board-also-supported \ + imx93-frdm-board-also-supported \ course-information \ sysdev-intro \ sysdev-dev-environment \ diff --git a/mk/embedded-linux.mk b/mk/embedded-linux.mk index 9b9b4a4ec1..a08ce95533 100644 --- a/mk/embedded-linux.mk +++ b/mk/embedded-linux.mk @@ -7,6 +7,7 @@ EMBEDDED_LINUX_SLIDES = \ beagleboneblack-board-also-supported \ beagleplay-board-also-supported \ stm32mp2-board-also-supported \ + imx93-frdm-board-also-supported \ course-information \ sysdev-intro \ sysdev-dev-environment \ diff --git a/slides/discovery-board-imx93-frdm/discovery-board-imx93-frdm.tex b/slides/discovery-board-imx93-frdm/discovery-board-imx93-frdm.tex new file mode 100644 index 0000000000..7350fd1b36 --- /dev/null +++ b/slides/discovery-board-imx93-frdm/discovery-board-imx93-frdm.tex @@ -0,0 +1,28 @@ +\begin{frame} +\frametitle{Supported hardware} + NXP i.MX93 11x11 FRDM development board + \footnotesize + \begin{columns} + \column{0.6\textwidth} + \begin{itemize} + \item i.MX93 SoC (Dual Cortex-A55 + Cortex-M33) + \item 2 GB LPDDR4X, 32 GB eMMC + \item Dual Gigabit Ethernet + \item USB 2.0 Type-C + USB Type-A + \item CAN interface + \item MicroSD slot, EEPROM + \item Wi-Fi 6 + Bluetooth 5.4 + 802.15.4 (MAYA-W276) + \item HDMI output (via LVDS), MIPI DSI and CSI + \item Audio jack (MQS), buttons and LEDs + \item SWD and UART debug + \end{itemize} + \column{0.4\textwidth} + \begin{center} + \includegraphics[width=\textwidth]{slides/discovery-board-imx93-frdm/imx93-frdm.png}\\ + IMX93 FRDM Board + \end{center} + \end{columns} + \vspace{0.5em} + Documentation and resources: \\ + \href{https://www.nxp.com/design/design-center/development-boards-and-designs/frdm-i-mx-93-development-board:FRDM-IMX93}{nxp.com/imx93-frdm} +\end{frame} diff --git a/slides/discovery-board-imx93-frdm/imx93-frdm.png b/slides/discovery-board-imx93-frdm/imx93-frdm.png new file mode 100644 index 0000000000..2d5011e6d1 Binary files /dev/null and b/slides/discovery-board-imx93-frdm/imx93-frdm.png differ diff --git a/slides/imx93-frdm-board-also-supported/imx93-frdm-board-also-supported.tex b/slides/imx93-frdm-board-also-supported/imx93-frdm-board-also-supported.tex new file mode 100644 index 0000000000..ea88df00e7 --- /dev/null +++ b/slides/imx93-frdm-board-also-supported/imx93-frdm-board-also-supported.tex @@ -0,0 +1,14 @@ +\begin{frame} +\frametitle{Labs proposed on another platform} + \begin{columns} + \column{0.7\textwidth} + You can also run the labs of this course on the IMX93-FRDM board.\\ + \vspace{1em} + Lab instructions are available at\\ + {\small \url{https://bootlin.com/doc/training/__SESSION_NAME__-imx93-frdm}} + \column{0.3\textwidth} + \begin{center} + \includegraphics[width=\textwidth]{../slides/imx93-frdm-board-also-supported/imx93-frdm.png} + \end{center} + \end{columns} +\end{frame} \ No newline at end of file diff --git a/slides/imx93-frdm-board-also-supported/imx93-frdm.png b/slides/imx93-frdm-board-also-supported/imx93-frdm.png new file mode 100644 index 0000000000..2d5011e6d1 Binary files /dev/null and b/slides/imx93-frdm-board-also-supported/imx93-frdm.png differ diff --git a/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx6.dia b/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx6.dia new file mode 100644 index 0000000000..104eda4218 --- /dev/null +++ b/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx6.dia @@ -0,0 +1,888 @@ + + + + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # +#include <dt-bindings/clock/imx6ul-clock.h> +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> +#include <dt-bindings/interrupt-controller/arm-gic.h> +#include "imx6ul-pinfunc.h"# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # +#include "imx6ul.dtsi" +#include "imx6ull-pinfunc.h" +#include "imx6ull-pinfunc-snvs.h"# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # +#include <dt-bindings/gpio/gpio.h># + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # +#include <dt-bindings/gpio/gpio.h># + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # +#include "imx6ull.dtsi" +#include "imx6ull-seeed-npi.dtsi" +#include "imx6ull-seeed-npi-dev-board.dtsi"# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # +#include "imx6ull.dtsi" +#include "imx6ull-seeed-npi.dtsi" +#include "imx6ull-seeed-npi-dev-board.dtsi"# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx6ul.dtsi# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx6ull.dtsi# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx6ull-seeed-npi.dtsi# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx6ull-seeed-npi-dev-board.dtsi# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx6ull-seeed-npi-dev-board-emmc.dts# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx6ull-seeed-npi-dev-board-nand.dts# + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx93-frdm.dia b/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx93-frdm.dia new file mode 100644 index 0000000000..bcf2726009 --- /dev/null +++ b/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx93-frdm.dia @@ -0,0 +1,533 @@ + + + + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # + +#include <dt-bindings/usb/pd.h> +#include "imx93.dtsi"# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # + +#include <dt-bindings/usb/pd.h> +#include "imx93.dtsi"# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx93.dtsi# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #SOC# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #BOARD# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx93-11x11-evk.dts# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #imx93-11x11-frdm.dts# + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx93-frdm.pdf b/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx93-frdm.pdf new file mode 100644 index 0000000000..f53a6a28b9 Binary files /dev/null and b/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx93-frdm.pdf differ diff --git a/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance.dia b/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance.dia new file mode 100644 index 0000000000..a829f6cb82 --- /dev/null +++ b/slides/sysdev-hw-devices/imx93-frdm/dt-inheritance.dia @@ -0,0 +1,369 @@ + + + + + + + + + + + + + #A4# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # + / { + soc@0 { + lpi2c1: i2c@44340000 { + compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x44340000 0x10000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX93_CLK_LPI2C1_GATE>; + clock-names = "per", "ipg"; + status = "disabled"; + }; + }; + };# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # + / { + soc@0 { + lpi2c1 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_lpi2c1>; + pinctrl-1 = <&pinctrl_lpi2c1>; + status = "okay"; + }; + }; + };# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + # + / { + soc@0 { + lpi2c1: i2c@44340000 { + compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x44340000 0x10000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk IMX93_CLK_LPI2C1_GATE>; + clock-names = "per", "ipg"; + clock-frequency = <400000>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_lpi2c1>; + pinctrl-1 = <&pinctrl_lpi2c1>; + status = "okay"; + }; + }; + }; # + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/slides/sysdev-hw-devices/imx93-frdm/imx93-tab-gpio21.png b/slides/sysdev-hw-devices/imx93-frdm/imx93-tab-gpio21.png new file mode 100644 index 0000000000..dbb09ae3b5 Binary files /dev/null and b/slides/sysdev-hw-devices/imx93-frdm/imx93-tab-gpio21.png differ diff --git a/slides/sysdev-hw-devices/imx93-frdm/led-on.jpg b/slides/sysdev-hw-devices/imx93-frdm/led-on.jpg new file mode 100644 index 0000000000..a478d02795 Binary files /dev/null and b/slides/sysdev-hw-devices/imx93-frdm/led-on.jpg differ diff --git a/slides/sysdev-hw-devices/imx93-frdm/simple-hardware-imx93-frdm.dia b/slides/sysdev-hw-devices/imx93-frdm/simple-hardware-imx93-frdm.dia new file mode 100644 index 0000000000..2eee31f87e --- /dev/null +++ b/slides/sysdev-hw-devices/imx93-frdm/simple-hardware-imx93-frdm.dia @@ -0,0 +1,946 @@ + + + + + + + + + + + + + #Letter# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #System-on-chip# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #CPU cores# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #I2C controller# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Ethernet MAC# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #GIC +IRQ controller# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #MMC +controller# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #EEPROM# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ## + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #eMMC 5.1# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Cortex A55# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Cortex A55# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + #Ethernet +PHY# + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/slides/sysdev-hw-devices/imx93-frdm/sysdev-hw-devices-imx93-frdm.tex b/slides/sysdev-hw-devices/imx93-frdm/sysdev-hw-devices-imx93-frdm.tex new file mode 100644 index 0000000000..2ac9db9332 --- /dev/null +++ b/slides/sysdev-hw-devices/imx93-frdm/sysdev-hw-devices-imx93-frdm.tex @@ -0,0 +1,1072 @@ +\begin{frame}[fragile]{DT overall structure: simplified example} + \begin{columns} + \column{0.6\textwidth} + \begin{onlyenv}<1> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "NXP i.MX93 11X11 FRDM board"; + compatible = "fsl,imx93-11x11-frdm", "fsl,imx93"; + + cpus { ... }; + reserved-memory { ... }; + chosen { ... }; + gic: interrupt-controller@48000000 { ... }; + soc { + lpi2c1: i2c@44340000 { ... }; + eqos: ethernet@428a0000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<2> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + A55_0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0>; + enable-method = "psci"; + #cooling-cells = <2>; + }; + + A55_1: cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x100>; + enable-method = "psci"; + #cooling-cells = <2>; + }; + }; + + reserved-memory { ... }; + chosen { ... }; + intc: interrupt-controller@a0021000 { ... }; + soc { + i2c1: i2c@40012000 { ... }; + ethernet0: ethernet@5800a000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<3> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { ... }; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + alloc-ranges = <0 0x80000000 0 0x40000000>; + size = <0 0x10000000>; + linux,cma-default; + }; + }; + chosen { + bootargs = "console=ttyLP0,115200"; + stdout-path = &lpuart1; + }; + gic: interrupt-controller@48000000 { ... }; + soc { + lpi2c1: i2c@44340000 { ... }; + eqos: ethernet@428a0000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<4> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { ... }; + reserved-memory { ... }; + chosen { ... }; + + gic: interrupt-controller@48000000 { + compatible = "arm,gic-v3"; + reg = <0 0x48000000 0 0x10000>, + <0 0x48040000 0 0xc0000>; + #interrupt-cells = <3>; + interrupt-controller; + interrupts = ; + interrupt-parent = <&gic>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x0 0x0 0x80000000>, + <0x28000000 0x0 0x28000000 0x10000000>; + + lpi2c1: i2c@44340000 { ... }; + eqos: ethernet@428a0000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<5> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { ... }; + reserved-memory { ... }; + chosen { ... }; + gic: interrupt-controller@48000000 { ... }; + soc { + compatible = "simple-bus"; + ... + lpi2c1: i2c@44340000 { + compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c"; + reg = <0x44340000 0x10000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&clk IMX93_CLK_LPI2C1_GATE>, + <&clk IMX93_CLK_BUS_AON>; + clock-names = "per", "ipg"; + status = "disabled"; + }; + eqos: ethernet@428a0000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<6> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + soc { + compatible = "simple-bus"; + ... + lpi2c1: i2c@44340000 { ... }; + eqos: ethernet@428a0000 { + compatible = "nxp,imx93-dwmac-eqos", "snps,dwmac-5.10a"; + reg = <0x428a0000 0x10000>; + interrupts = , + ; + status = "okay"; + + mdio { + compatible = "snps,dwmac-mdio"; + ... + ethphy1: ethernet-phy@1 { + reg = <1>; + eee-broken-1000t; + reset-gpios = <&pcal6524 15 GPIO_ACTIVE_LOW>; + reset-assert-us = <15000>; + reset-deassert-us = <100000>; + }; + }; + }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \column{0.4\textwidth} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/imx93-frdm/simple-hardware-imx93-frdm.pdf} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Device Tree inheritance} + \begin{itemize} + \item Device Tree files are not monolithic, they can be split in + several files, including each other. + \item \code{.dtsi} files are included files, while \code{.dts} files + are {\em final} Device Trees + \begin{itemize} + \item Only \code{.dts} files are accepted as input to \code{dtc} + \end{itemize} + \item Typically, \code{.dtsi} will contain + \begin{itemize} + \item definitions of SoC-level information + \item definitions common to several boards + \end{itemize} + \item The \code{.dts} file contains the board-level information + \item The inclusion works by {\bf overlaying} the tree of the + including file over the tree of the included file, + according to the order of the \code{#include} directives. + \item Allows an including file to {\bf override} values specified by + an included file + \item Uses the C pre-processor \code{#include} directive + \end{itemize} +\end{frame} + +\begin{frame}{Device Tree inheritance example} + \begin{center} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/imx93-frdm/dt-inheritance.pdf} + \end{center} +\end{frame} + +\begin{frame}[fragile]{Inheritance and labels} + + \begin{columns}[t] + \column{0.5\textwidth} + Doing: + \begin{block}{soc.dtsi} + {\tiny +\begin{minted}{perl} +/ { + soc { + lpuart1: serial@44380000 { + compatible = "fsl,imx93-lpuart", "fsl,imx7ulp-lpuart"; + reg = <0x44380000 0x1000>; + interrupts = ; + clocks = <&clk IMX93_CLK_LPUART1_GATE>, ... ; + clock-names = "ipg", "per"; + status = "disabled"; + };};}; +\end{minted} + } + \end{block} + + \begin{block}{board.dts} + {\tiny +\begin{minted}{perl} +#include "soc.dtsi" + +/ { + soc { + serial@44380000 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; + };};}; + +\end{minted} + } + \end{block} + + \column{0.5\textwidth} + \begin{onlyenv}<2> + Is exactly equivalent to: + + \begin{block}{soc.dtsi} + {\tiny +\begin{minted}{perl} +/ { + soc { + lpuart1: serial@44380000 { + compatible = "fsl,imx93-lpuart", "fsl,imx7ulp-lpuart"; + reg = <0x44380000 0x1000>; + interrupts = ; + clocks = <&clk IMX93_CLK_LPUART1_GATE>, ... ; + clock-names = "ipg", "per"; + status = "disabled"; + };};}; +\end{minted} + } + \end{block} + + \begin{block}{board.dts} + {\tiny +\begin{minted}{perl} +#include "soc.dtsi" + +&lpuart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; +\end{minted} + } + \end{block} + + $\rightarrow$ this solution is now often preferred + \end{onlyenv} + \end{columns} + +\end{frame} + +\begin{frame}{DT inheritance in imx93-frdm support} + \begin{center} + \includegraphics[height=0.8\textheight]{slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx93-frdm.pdf} + \end{center} +\end{frame} + +\begin{frame}{DT inheritance in imx6ull-seed-npi-dev-board support} + \begin{center} + \includegraphics[height=0.8\textheight]{slides/sysdev-hw-devices/imx93-frdm/dt-inheritance-imx6.pdf} + \end{center} +\end{frame} + +\begin{frame}{Device Tree design principles} + \begin{itemize} + \item {\bf Describe hardware} (how the hardware is), not + configuration (how I choose to use the hardware) + \item {\bf OS-agnostic} + \begin{itemize} + \item For a given piece of HW, Device Tree should be the same for + U-Boot, FreeBSD or Linux + \item There should be no need to change the Device Tree when updating the OS + \end{itemize} + \item Describe {\bf integration of hardware components}, not the internals + of hardware components + \begin{itemize} + \item The details of how a specific device/IP block is working is + handled by code in device drivers + \item The Device Tree describes how the device/IP block is + connected/integrated with the rest of the system: IRQ lines, DMA + channels, clocks, reset lines, etc. + \end{itemize} + \item Like all beautiful design principles, these principles are + sometimes violated. + \end{itemize} +\end{frame} + +\begin{frame}{Device Tree specifications} + \begin{columns} + \column{0.7\textwidth} + \begin{itemize} + \item How to write the correct nodes/properties to describe a + given hardware platform~? + \item {\bf Device Tree Specifications} $\rightarrow$ base Device + Tree syntax + number of standard properties. + \begin{itemize} + \item \url{https://www.devicetree.org/specifications/} + \item Not sufficient to describe the wide variety of hardware. + \end{itemize} + \item {\bf Device Tree Bindings} $\rightarrow$ documents that each + specify how a piece of HW should be described + \begin{itemize} + \item \kdir{Documentation/devicetree/bindings} in Linux kernel sources + \item Reviewed by DT bindings maintainer team + \item Legacy: human readable documents + \item New norm: YAML-written specifications + \end{itemize} + \end{itemize} + \column{0.3\textwidth} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/dt-spec.png} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Device Tree binding: old style} + \begin{center} + \kfile{Documentation/devicetree/bindings/mtd/spear_smi.txt}\\ + This IP is {\em not} used on IMX93. + \end{center} + \begin{columns}[t] + \column{0.5\textwidth} + \begin{block}{} + {\fontsize{5}{6}\selectfont +\begin{verbatim} +* SPEAr SMI + +Required properties: +- compatible : "st,spear600-smi" +- reg : Address range of the mtd chip +- #address-cells, #size-cells : Must be present if the device has sub-nodes + representing partitions. +- interrupts: Should contain the STMMAC interrupts +- clock-rate : Functional clock rate of SMI in Hz + +Optional properties: +- st,smi-fast-mode : Flash supports read in fast mode + +\end{verbatim} + } + \end{block} + \column{0.5\textwidth} + \begin{block}{} + {\fontsize{4}{5}\selectfont +\begin{verbatim} +Example: + + smi: flash@fc000000 { + compatible = "st,spear600-smi"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xfc000000 0x1000>; + interrupt-parent = <&vic1>; + interrupts = <12>; + clock-rate = <50000000>; /* 50MHz */ + + flash@f8000000 { + st,smi-fast-mode; + ... + }; + }; +\end{verbatim} + } + \end{block} + \end{columns} + +\end{frame} + +\begin{frame}[fragile]{Device Tree binding: YAML style} + \kfile{Documentation/devicetree/bindings/i2c/i2c-imx-lpi2c.yaml} + \begin{columns}[t] + \column{0.5\textwidth} + \begin{block}{} + {\fontsize{5}{5}\selectfont +\begin{minted}{yaml} +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/i2c-imx-lpi2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale Low Power Inter IC (LPI2C) for i.MX + +maintainers: + - Shawn Guo + - Sascha Hauer + - Fabio Estevam + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: + oneOf: + - enum: + - fsl,imx7ulp-lpi2c + - items: + - enum: + - fsl,imx8qxp-lpi2c + - fsl,imx8dxl-lpi2c + - fsl,imx8qm-lpi2c + - fsl,imx8ulp-lpi2c + - fsl,imx93-lpi2c + - fsl,imx95-lpi2c + - const: fsl,imx7ulp-lpi2c + + reg: + maxItems: 1 + +\end{minted} + } + \end{block} + \column{0.5\textwidth} + \begin{block}{} + {\fontsize{5}{5}\selectfont +\begin{minted}{yaml} + assigned-clock-parents: true + assigned-clock-rates: true + assigned-clocks: true + clock-frequency: true + + clock-names: + items: + - const: per + - const: ipg + + clocks: + maxItems: 2 + + dmas: + items: + - description: DMA controller phandle and request line for TX + - description: DMA controller phandle and request line for RX + + dma-names: + items: + - const: tx + - const: rx + + power-domains: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false +\end{minted} + } + \end{block} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Device Tree binding: YAML style example} + \begin{block}{} + {\fontsize{5}{7}\selectfont +\begin{minted}{yaml} +examples: + - | + #include + #include + + i2c@40a50000 { + compatible = "fsl,imx7ulp-lpi2c"; + reg = <0x40A50000 0x10000>; + interrupt-parent = <&intc>; + interrupts = ; + clocks = <&clks IMX7ULP_CLK_LPI2C7>, + <&clks IMX7ULP_CLK_NIC1_BUS_DIV>; + }; + +\end{minted} + } + \end{block} +\end{frame} + +\begin{frame}{Validating Device Tree in Linux} + \begin{itemize} + \item \code{dtc} only does syntactic validation + \item YAML bindings allow to do semantic validation + \item Linux kernel \code{make} rules: + \begin{itemize} + \item \code{make dt_binding_check}\\ + verify that YAML bindings are valid + \item \code{make dtbs_check}\\ + validate DTs currently enabled against YAML bindings + \item \code{make DT_SCHEMA_FILES=Documentation/devicetree/bindings/trivial-devices.yaml dtbs_check}\\ + validate DTs against a specific YAML binding + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame}{The {\tt compatible} property} + \begin{itemize} + \item Is a list of strings + \begin{itemize} + \item From the most specific to the least specific + \end{itemize} + \item Describes the specific {\bf binding} to which the node complies. + \item It uniquely identifies the {\bf programming model} of the + device. + \item Practically speaking, it is used by the operating system to + find the {\bf appropriate driver} for this device. + \item When describing real hardware, the typical form is + \code{vendor,model} + \item Examples: + \begin{itemize} + \item \code{compatible = "arm,armv7-timer";} + \item \code{compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";} + \item \code{compatible = "regulator-fixed";} + \item \code{compatible = "gpio-keys";} + \end{itemize} + \item Special value: \code{simple-bus} $\rightarrow$ bus where all + sub-nodes are memory-mapped devices + \end{itemize} +\end{frame} + +\begin{frame}{{\tt compatible} property and Linux kernel drivers} + \begin{columns} + \column{0.6\textwidth} + \begin{itemize} + \item Linux identifies as {\bf platform devices}: + \begin{itemize} + \item Top-level DT nodes with a \code{compatible} string + \item Sub-nodes of \code{simple-bus} + \begin{itemize} + \item Instantiated automatically at boot time + \end{itemize} + \end{itemize} + \item Sub-nodes of I2C controllers $\rightarrow$ {\em I2C devices} + \item Sub-nodes of SPI controllers $\rightarrow$ {\em SPI devices} + \item Each Linux driver has a table of compatible strings it supports + \begin{itemize} + \item \kstruct{of_device_id}\code{[]} + \end{itemize} + \item When a DT node compatible string matches a given driver, the + device is {\em bound} to that driver. + \end{itemize} + \column{0.4\textwidth} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/dt-to-devices.pdf} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Matching with drivers in Linux: platform driver} + \begin{block}{\kfile{drivers/tty/serial/fsl_lpuart.c}} + {\tiny +\begin{minted}{c} +static const struct of_device_id lpuart_dt_ids[] = { + { .compatible = "fsl,vf610-lpuart", .data = &vf_data, }, + { .compatible = "fsl,ls1021a-lpuart", .data = &ls1021a_data, }, + { .compatible = "fsl,ls1028a-lpuart", .data = &ls1028a_data, }, + { .compatible = "fsl,imx7ulp-lpuart", .data = &imx7ulp_data, }, + { .compatible = "fsl,imx8ulp-lpuart", .data = &imx8ulp_data, }, + { .compatible = "fsl,imx8qxp-lpuart", .data = &imx8qxp_data, }, + { .compatible = "fsl,imxrt1050-lpuart", .data = &imxrt1050_data}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, lpuart_dt_ids); + +... + +static struct platform_driver lpuart_driver = { + .probe = lpuart_probe, + .remove_new = lpuart_remove, + .driver = { + .name = "fsl-lpuart", + .of_match_table = lpuart_dt_ids, + .pm = pm_ptr(&lpuart_pm_ops), + }, +}; +\end{minted} + } + \end{block} +\end{frame} + +\begin{frame}[fragile]{Matching with drivers in Linux: I2C driver} + \begin{block}{\kfile{sound/soc/codecs/cs42l51.c}} + {\tiny +\begin{minted}{c} +const struct of_device_id cs42l51_of_match[] = { + { .compatible = "cirrus,cs42l51", }, + { } +}; +MODULE_DEVICE_TABLE(of, cs42l51_of_match); +\end{minted} + } + \end{block} + \begin{block}{\kfile{sound/soc/codecs/cs42l51-i2c.c}} + {\tiny +\begin{minted}{c} +static struct i2c_driver cs42l51_i2c_driver = { + .driver = { + .name = "cs42l51", + .of_match_table = cs42l51_of_match, + .pm = &cs42l51_pm_ops, + }, + .probe = cs42l51_i2c_probe, + .remove = cs42l51_i2c_remove, + .id_table = cs42l51_i2c_id, +}; +\end{minted} + } + \end{block} +\end{frame} + +\begin{frame}[fragile]{{\tt reg} property} + \begin{itemize} + \item Most important property after \code{compatible} + \item {\bf Memory-mapped} devices: base physical address and size of + the memory-mapped registers. Can have several entries for multiple + register areas. +\begin{onlyenv}<1> +\begin{block}{} +\begin{verbatim} +sai4: sai@50027000 { + reg = <0x50027000 0x4>, <0x500273f0 0x10>; +}; +\end{verbatim} +\end{block} +\end{onlyenv} +\pause + \item {\bf I2C} devices: address of the device on the I2C bus. +\begin{onlyenv}<2> +\begin{block}{} +\begin{verbatim} +&i2c1 { + hdmi-transmitter@39 { + reg = <0x39>; + }; + cs42l51: cs42l51@4a { + reg = <0x4a>; + }; +}; +\end{verbatim} +\end{block} +\end{onlyenv} +\pause + \item {\bf SPI} devices: chip select number +\begin{onlyenv}<3> +\begin{block}{} +\begin{verbatim} +&qspi { + flash0: mx66l51235l@0 { + reg = <0>; + }; + flash1: mx66l51235l@1 { + reg = <1>; + }; +}; +\end{verbatim} +\end{block} +\end{onlyenv} +\pause +\item The unit address must be the address of the first \code{reg} + entry. +\begin{onlyenv}<4> +\begin{block}{} +\begin{verbatim} +sai4: sai@50027000 { + reg = <0x50027000 0x4>, <0x500273f0 0x10>; +}; +\end{verbatim} +\end{block} +\end{onlyenv} + \end{itemize} +\end{frame} + +\begin{frame}{Status property} + \begin{itemize} + \item The \code{status} property indicates if the device is really in + use or not + \begin{itemize} + \item \code{okay} or \code{ok} $\rightarrow$ the device is really + in use + \item any other value, by convention \code{disabled} $\rightarrow$ + the device is not in use + \end{itemize} + \item In Linux, controls if a device is instantiated + \item In \code{.dtsi} files describing SoCs: all devices that + interface to the outside world have \code{status = "disabled";} + \item Enabled on a per-device basis in the board \code{.dts} + \end{itemize} +\end{frame} + +\begin{frame}[fragile]{Resources: interrupts, clocks, DMA, reset lines, ...} + \begin{columns} + \column{0.5\textwidth} + \begin{itemize} + \item Common pattern for resources shared by multiple hardware + blocks + \begin{itemize} + \item Interrupt lines + \item Clock controllers + \item DMA controllers + \item Reset controllers + \item ... + \end{itemize} + \item A Device Tree node describing the {\em controller} as a device + \item References from other nodes that use resources provided by + this {\em controller} + \end{itemize} + \column{0.5\textwidth} +\begin{block}{} +{\fontsize{4}{5}\selectfont +\begin{minted}{perl} +gic: interrupt-controller@48000000 { + compatible = "arm,gic-v3"; + reg = <0 0x48000000 0 0x10000>, + <0 0x48040000 0 0xc0000>; + #interrupt-cells = <3>; + interrupt-controller; + interrupts = ; + interrupt-parent = <&gic>; +}; + +clk: clock-controller@44450000 { + compatible = "fsl,imx93-ccm"; + reg = <0x44450000 0x10000>; + #clock-cells = <1>; + clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>; + clock-names = "osc_32k", "osc_24m", "clk_ext1"; +}; + +edma1: dma-controller@44000000 { + compatible = "fsl,imx93-edma3"; + reg = <0x44000000 0x200000>; + #dma-cells = <3>; + dma-channels = <31>; + interrupts = , ; + clocks = <&clk IMX93_CLK_EDMA1_GATE>; + clock-names = "dma"; +}; + +lpuart1: serial@44380000 { + compatible = "fsl,imx93-lpuart", "fsl,imx8ulp-lpuart", "fsl,imx7ulp-lpuart"; + reg = <0x44380000 0x1000>; + interrupts = ; + clocks = <&clk IMX93_CLK_LPUART1_GATE>; + clock-names = "ipg"; + dmas = <&edma1 17 0 FSL_EDMA_RX>, <&edma1 16 0 0>; + dma-names = "rx", "tx"; +}; +\end{minted} +} +\end{block} +\end{columns} +\end{frame} + +\begin{frame}{Pin-muxing description} + \begin{columns} + \column{0.5\textwidth} + \begin{itemize} + \item Most modern SoCs, including the IMX93, have more features + than they have pins to expose those features to the outside world. + \item Pins are muxed: a given pin can be used for one function + {\bf or} another + \item A specific IP block in the SoC controls the muxing of pins: + the {\bf pinmux controller} + \item The Device Tree describes which pin configurations are + possible, and which configurations are used by the different + devices. + \end{itemize} + \column{0.5\textwidth} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/pin-muxing-principle.pdf} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Pin-muxing controllers on IMX93} + \begin{block}{\kfileversion{arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts}{6.1}} +{\tiny +\begin{minted}{perl} +iomuxc: pinctrl@443c0000 { + compatible = "fsl,imx93-iomuxc"; + reg = <0x443c0000 0x10000>; + pinctrl_uart1: uart1grp { + fsl,pins = < + MX93_PAD_UART1_RXD__LPUART1_RX 0x31e + MX93_PAD_UART1_TXD__LPUART1_TX 0x31e + >; + }; + pinctrl_lpi2c1: lpi2c1grp { + fsl,pins = < + MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e + MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e + >; + }; +}; + +lpuart1: serial@44380000 { + compatible = "fsl,imx93-lpuart", "fsl,imx8ulp-lpuart", "fsl,imx7ulp-lpuart"; + reg = <0x44380000 0x1000>; + interrupts = ; + clocks = <&clk IMX93_CLK_LPUART1_GATE>; + clock-names = "ipg"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; +\end{minted} +} + \end{block} +\end{frame} + +\begin{frame}[fragile]{Pin-muxing configuration} +\begin{onlyenv}<1> + \begin{block}{\kfile{arch/arm64/boot/dts/freescale/imx93-11x11-frdm.dts}} +{\tiny +\begin{minted}{perl} +&iomuxc { + pinctrl_lpi2c1: lpi2c1grp { + fsl,pins = < + MX93_PAD_I2C1_SCL__LPI2C1_SCL 0x40000b9e + MX93_PAD_I2C1_SDA__LPI2C1_SDA 0x40000b9e + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX93_PAD_UART1_RXD__LPUART1_RX 0x31e + MX93_PAD_UART1_TXD__LPUART1_TX 0x31e + >; + }; + + pinctrl_fec: fecgrp { + fsl,pins = < + MX93_PAD_ENET2_MDC__ENET1_MDC 0x57e + MX93_PAD_ENET2_MDIO__ENET1_MDIO 0x57e + MX93_PAD_ENET2_RD0__ENET1_RGMII_RD0 0x57e + ... + >; + }; +}; +\end{minted} +} +\end{block} +\end{onlyenv} +\end{frame} + +\begin{frame}[fragile]{Pin-muxing consumer} + \begin{block}{} +{\tiny +\begin{minted}{perl} +&i2c1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c1_pins_a>; + pinctrl-1 = <&i2c1_sleep_pins_a>; + ... +}; +\end{minted} +} +\end{block} +\begin{itemize} +\item Typically board-specific, in \code{.dts} +\item \code{pinctrl-0}, \code{pinctrl-1}, \code{pinctrl-X} provides + the pin mux configurations for the different {\bf states} +\item \code{pinctrl-names} gives a name to each state, mandatory even + if only one state +\item States are mutually exclusive +\item The driver is responsible for switching between states +\item \code{default} state is automatically set up when the device is + {\em probed} +\end{itemize} +\end{frame} + +\begin{frame}[fragile]{Example: LED and I2C device} + \begin{itemize} + \item Let's see how to describe an LED and an I2C device connected + to the DK1 platform. + \item Create \code{arch/arm64/boot/dts/freescale/imx93-11x11-frdm-custom.dts} + which includes \code{imx93-11x11-frdm.dts} + \begin{block}{} +{\tiny +\begin{verbatim} +#include "imx93-11x11-frdm.dts" +\end{verbatim} +} + \end{block} + \item Make sure \code{imx93-11x11-frdm.dts} gets compiled to a + DTB by changing \kfile{arch/arm64/boot/dts/freescale/Makefile} + \begin{block}{} + {\tiny +\begin{verbatim} +dtb-$(CONFIG_ARCH_MXC) += imx93-11x11-frdm-custom.dtb +\end{verbatim} + } + \end{block} + \item \code{make dtbs} + \begin{block}{} + {\tiny +\begin{verbatim} + DTC arch/arm64/boot/dts/freescale/imx93-11x11-frdm-custom.dtb +\end{verbatim} + } + \end{block} + \end{itemize} +\end{frame} + +\begin{frame}[fragile]{Example: describe an LED} + \begin{columns} + \column{0.5\textwidth} + \begin{block}{imx93-11x11-frdm-custom.dts} + {\tiny +\begin{minted}{perl} +#include "imx93-11x11-frdm.dts" + +/ { + leds { + compatible = "gpio-leds"; + webinar { + label = "webinar"; + gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>; + }; + }; +}; +\end{minted} + } + \end{block} + \begin{block}{shell} +{\tiny +\begin{verbatim} +# echo 255 > /sys/class/leds/webinar/brightness +\end{verbatim} +} +\end{block} + \column{0.5\textwidth} + \begin{center} + \includegraphics[height=0.3\textheight]{slides/sysdev-hw-devices/imx93-frdm/imx93-tab-gpio21.png}\\ + \vspace{0.5cm} + \includegraphics[height=0.3\textheight]{slides/sysdev-hw-devices/imx93-frdm/led-on.jpg} + \end{center} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Example: connect I2C temperature, humidity and pressure sensor} + \begin{columns} + \column{0.5\textwidth} + \begin{block}{imx93-11x11-frdm-custom.dts} + {\tiny +\begin{minted}{perl} + +&lpi2c4 { + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&pinctrl_lpi2c4>; + pinctrl-1 = <&pinctrl_lpi2c4>; + status = "okay"; + + pressure@76 { + compatible = "bosch,bme280"; + reg = <0x76>; + }; +}; + +\end{minted} +} + \end{block} + +\begin{block}{shell} +{\tiny +\begin{verbatim} +# cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_input +49147 +# cat /sys/bus/iio/devices/iio\:device2/in_pressure_input +101.567167968 +# cat /sys/bus/iio/devices/iio\:device2/in_temp_input +24380 +\end{verbatim} +} +\end{block} + \column{0.5\textwidth} + \begin{center} + \includegraphics[width=0.4\textwidth]{slides/sysdev-hw-devices/bme.jpg} + \end{center} +\end{columns} +\end{frame} + +\begin{frame}{Further details about the Device Tree} +\small +Check out our {\em Device Tree 101 webinar}, by Thomas Petazzoni (2021) +\begin{itemize} + \item Slides: \url{https://bootlin.com/blog/device-tree-101-webinar-slides-and-videos/}\\ + \item Video: \url{https://youtu.be/a9CZ1Uk3OYQ} +\end{itemize} +\vspace{0.5cm} +\includegraphics[height=0.5\textheight]{common/device-tree-video.jpg} +\end{frame} + +\subsection{Discoverable hardware: USB and PCI} + +\begin{frame}{Discoverable hardware} + \begin{itemize} + \item Some busses have built-in hardware discoverability mechanisms + \item Most common busses: USB and PCI + \item Hardware devices can be enumerated, and their characteristics + retrieved with just a driver or the bus controller + \item Useful Linux commands + \begin{itemize} + \item \code{lsusb}, lists all USB devices detected + \item \code{lspci}, lists all PCI devices detected + \item A detected device does not mean it has a kernel driver + associated to it! + \end{itemize} + \item Association with kernel drivers done based on product + ID/vendor ID, or some other characteristics of the device: device + class, device sub-class, etc. + \end{itemize} +\end{frame} + +\setuplabframe +{Accessing hardware devices} +{ + Time to start the practical lab! + \begin{itemize} + \item Exploring the contents of \code{/dev} and \code{/sys} and the + devices available on the embedded hardware platform. + \item Using GPIOs and LEDs. + \item Modifying the Device Tree to control pin multiplexing and + declare an I2C-connected joystick. + \item Adding support for a USB audio card using Linux kernel modules + \item Adding support for the I2C-connected joystick through + an out-of-tree module. + \end{itemize} +} diff --git a/slides/sysdev-hw-devices/cn13-pinout.png b/slides/sysdev-hw-devices/stm32mp1/cn13-pinout.png similarity index 100% rename from slides/sysdev-hw-devices/cn13-pinout.png rename to slides/sysdev-hw-devices/stm32mp1/cn13-pinout.png diff --git a/slides/sysdev-hw-devices/cn14-pinout.png b/slides/sysdev-hw-devices/stm32mp1/cn14-pinout.png similarity index 100% rename from slides/sysdev-hw-devices/cn14-pinout.png rename to slides/sysdev-hw-devices/stm32mp1/cn14-pinout.png diff --git a/slides/sysdev-hw-devices/dt-inheritance-stm32.dia b/slides/sysdev-hw-devices/stm32mp1/dt-inheritance-stm32.dia similarity index 100% rename from slides/sysdev-hw-devices/dt-inheritance-stm32.dia rename to slides/sysdev-hw-devices/stm32mp1/dt-inheritance-stm32.dia diff --git a/slides/sysdev-hw-devices/dt-inheritance.dia b/slides/sysdev-hw-devices/stm32mp1/dt-inheritance.dia similarity index 100% rename from slides/sysdev-hw-devices/dt-inheritance.dia rename to slides/sysdev-hw-devices/stm32mp1/dt-inheritance.dia diff --git a/slides/sysdev-hw-devices/led-on.jpg b/slides/sysdev-hw-devices/stm32mp1/led-on.jpg similarity index 100% rename from slides/sysdev-hw-devices/led-on.jpg rename to slides/sysdev-hw-devices/stm32mp1/led-on.jpg diff --git a/slides/sysdev-hw-devices/stm32mp157-i2c-pin-mux.png b/slides/sysdev-hw-devices/stm32mp1/stm32mp157-i2c-pin-mux.png similarity index 100% rename from slides/sysdev-hw-devices/stm32mp157-i2c-pin-mux.png rename to slides/sysdev-hw-devices/stm32mp1/stm32mp157-i2c-pin-mux.png diff --git a/slides/sysdev-hw-devices/stm32mp1/sysdev-hw-devices-stm32mp1.tex b/slides/sysdev-hw-devices/stm32mp1/sysdev-hw-devices-stm32mp1.tex new file mode 100644 index 0000000000..f16a2eb916 --- /dev/null +++ b/slides/sysdev-hw-devices/stm32mp1/sysdev-hw-devices-stm32mp1.tex @@ -0,0 +1,1041 @@ +\begin{frame}[fragile]{DT overall structure: simplified example} + \begin{columns} + \column{0.6\textwidth} + \begin{onlyenv}<1> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + + cpus { ... }; + memory@0 { ... }; + chosen { ... }; + intc: interrupt-controller@a0021000 { ... }; + soc { + i2c1: i2c@40012000 { ... }; + ethernet0: ethernet@5800a000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<2> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu0: cpu@0 { + compatible = "arm,cortex-a7"; + clock-frequency = <650000000>; + device_type = "cpu"; + reg = <0>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-a7"; + clock-frequency = <650000000>; + device_type = "cpu"; + reg = <1>; + }; + }; + + memory@0 { ... }; + chosen { ... }; + intc: interrupt-controller@a0021000 { ... }; + soc { + i2c1: i2c@40012000 { ... }; + ethernet0: ethernet@5800a000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<3> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { ... }; + memory@0 { + device_type = "memory"; + reg = <0x0 0x20000000>; + }; + + chosen { + bootargs = ""; + stdout-path = "serial0:115200n8"; + }; + intc: interrupt-controller@a0021000 { ... }; + soc { + i2c1: i2c@40012000 { ... }; + ethernet0: ethernet@5800a000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<4> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { ... }; + memory@0 { ... }; + chosen { ... }; + + intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, + <0xa0022000 0x2000>; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + + i2c1: i2c@40012000 { ... }; + ethernet0: ethernet@5800a000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<5> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { ... }; + memory@0 { ... }; + chosen { ... }; + intc: interrupt-controller@a0021000 { ... }; + soc { + i2c1: i2c@40012000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x40012000 0x400>; + interrupts = , + ; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + cs42l51: cs42l51@4a { + compatible = "cirrus,cs42l51"; + reg = <0x4a>; + reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + }; + ethernet0: ethernet@5800a000 { ... }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \begin{onlyenv}<6> + \begin{block}{} +\begin{minted}[fontsize=\tiny]{perl} +/ { + cpus { ... }; + memory@0 { ... }; + chosen { ... }; + intc: interrupt-controller@a0021000 { ... }; + soc { + compatible = "simple-bus"; + ... + interrupt-parent = <&intc>; + i2c1: i2c@40012000 { ... }; + + ethernet0: ethernet@5800a000 { + compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; + reg = <0x5800a000 0x2000>; + interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; + status = "okay"; + + mdio0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "snps,dwmac-mdio"; + phy0: ethernet-phy@0 { + reg = <0>; + }; + }; + }; + }; +}; +\end{minted} + \end{block} + \end{onlyenv} + \column{0.4\textwidth} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/simple-hardware.pdf} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Device Tree inheritance} + \begin{itemize} + \item Device Tree files are not monolithic, they can be split in + several files, including each other. + \item \code{.dtsi} files are included files, while \code{.dts} files + are {\em final} Device Trees + \begin{itemize} + \item Only \code{.dts} files are accepted as input to \code{dtc} + \end{itemize} + \item Typically, \code{.dtsi} will contain + \begin{itemize} + \item definitions of SoC-level information + \item definitions common to several boards + \end{itemize} + \item The \code{.dts} file contains the board-level information + \item The inclusion works by {\bf overlaying} the tree of the + including file over the tree of the included file, + according to the order of the \code{#include} directives. + \item Allows an including file to {\bf override} values specified by + an included file + \item Uses the C pre-processor \code{#include} directive + \end{itemize} +\end{frame} + +\begin{frame}{Device Tree inheritance example} + \begin{center} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/stm32mp1/dt-inheritance.pdf} + \end{center} +\end{frame} + +\begin{frame}[fragile]{Inheritance and labels} + + \begin{columns}[t] + \column{0.5\textwidth} + Doing: + \begin{block}{soc.dtsi} + {\tiny +\begin{minted}{perl} +/ { + soc { + usart1: serial@5c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x5c000000 0x400>; + status = "disabled"; + }; + }; +}; +\end{minted} + } + \end{block} + + \begin{block}{board.dts} + {\tiny +\begin{minted}{perl} +#include "soc.dtsi" + +/ { + soc { + serial@5c000000 { + status = "okay"; + }; + }; +}; +\end{minted} + } + \end{block} + + \column{0.5\textwidth} + \begin{onlyenv}<2> + Is exactly equivalent to: + + \begin{block}{soc.dtsi} + {\tiny +\begin{minted}{perl} +/ { + soc { + usart1: serial@5c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x5c000000 0x400>; + status = "disabled"; + }; + }; +}; +\end{minted} + } + \end{block} + + \begin{block}{board.dts} + {\tiny +\begin{minted}{perl} +#include "soc.dtsi" + +&usart1 { + status = "okay"; +}; +\end{minted} + } + \end{block} + + $\rightarrow$ this solution is now often preferred + \end{onlyenv} + \end{columns} + +\end{frame} + +\begin{frame}{DT inheritance in STM32MP1 support} + \begin{center} + \includegraphics[height=0.8\textheight]{slides/sysdev-hw-devices/stm32mp1/dt-inheritance-stm32.pdf} + \end{center} +\end{frame} + +\begin{frame}{Device Tree design principles} + \begin{itemize} + \item {\bf Describe hardware} (how the hardware is), not + configuration (how I choose to use the hardware) + \item {\bf OS-agnostic} + \begin{itemize} + \item For a given piece of HW, Device Tree should be the same for + U-Boot, FreeBSD or Linux + \item There should be no need to change the Device Tree when updating the OS + \end{itemize} + \item Describe {\bf integration of hardware components}, not the internals + of hardware components + \begin{itemize} + \item The details of how a specific device/IP block is working is + handled by code in device drivers + \item The Device Tree describes how the device/IP block is + connected/integrated with the rest of the system: IRQ lines, DMA + channels, clocks, reset lines, etc. + \end{itemize} + \item Like all beautiful design principles, these principles are + sometimes violated. + \end{itemize} +\end{frame} + +\begin{frame}{Device Tree specifications} + \begin{columns} + \column{0.7\textwidth} + \begin{itemize} + \item How to write the correct nodes/properties to describe a + given hardware platform~? + \item {\bf Device Tree Specifications} $\rightarrow$ base Device + Tree syntax + number of standard properties. + \begin{itemize} + \item \url{https://www.devicetree.org/specifications/} + \item Not sufficient to describe the wide variety of hardware. + \end{itemize} + \item {\bf Device Tree Bindings} $\rightarrow$ documents that each + specify how a piece of HW should be described + \begin{itemize} + \item \kdir{Documentation/devicetree/bindings} in Linux kernel sources + \item Reviewed by DT bindings maintainer team + \item Legacy: human readable documents + \item New norm: YAML-written specifications + \end{itemize} + \end{itemize} + \column{0.3\textwidth} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/dt-spec.png} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Device Tree binding: old style} + \begin{center} + \kfile{Documentation/devicetree/bindings/mtd/spear_smi.txt}\\ + This IP is {\em not} used on STM32MP1. + \end{center} + \begin{columns}[t] + \column{0.5\textwidth} + \begin{block}{} + {\fontsize{5}{6}\selectfont +\begin{verbatim} +* SPEAr SMI + +Required properties: +- compatible : "st,spear600-smi" +- reg : Address range of the mtd chip +- #address-cells, #size-cells : Must be present if the device has sub-nodes + representing partitions. +- interrupts: Should contain the STMMAC interrupts +- clock-rate : Functional clock rate of SMI in Hz + +Optional properties: +- st,smi-fast-mode : Flash supports read in fast mode + +\end{verbatim} + } + \end{block} + \column{0.5\textwidth} + \begin{block}{} + {\fontsize{4}{5}\selectfont +\begin{verbatim} +Example: + + smi: flash@fc000000 { + compatible = "st,spear600-smi"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0xfc000000 0x1000>; + interrupt-parent = <&vic1>; + interrupts = <12>; + clock-rate = <50000000>; /* 50MHz */ + + flash@f8000000 { + st,smi-fast-mode; + ... + }; + }; +\end{verbatim} + } + \end{block} + \end{columns} + +\end{frame} + +\begin{frame}[fragile]{Device Tree binding: YAML style} + \kfile{Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml} + \begin{columns}[t] + \column{0.5\textwidth} + \begin{block}{} + {\fontsize{5}{6}\selectfont +\begin{minted}{yaml} +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/st,stm32-i2c.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: I2C controller embedded in STMicroelectronics STM32 I2C platform + +maintainers: + - Pierre-Yves MORDRET + +properties: + compatible: + enum: + - st,stm32f4-i2c + - st,stm32f7-i2c + - st,stm32mp15-i2c + + reg: + maxItems: 1 + + interrupts: + items: + - description: interrupt ID for I2C event + - description: interrupt ID for I2C error + + resets: + maxItems: 1 + +\end{minted} + } + \end{block} + \column{0.5\textwidth} + \begin{block}{} + {\fontsize{5}{6}\selectfont +\begin{minted}{yaml} + clocks: + maxItems: 1 + + dmas: + items: + - description: RX DMA Channel phandle + - description: TX DMA Channel phandle + + ... + + clock-frequency: + description: Desired I2C bus clock frequency in Hz. If not specified, + the default 100 kHz frequency will be used. + For STM32F7, STM32H7 and STM32MP1 SoCs, if timing + parameters match, the bus clock frequency can be from + 1Hz to 1MHz. + default: 100000 + minimum: 1 + maximum: 1000000 + +required: + - compatible + - reg + - interrupts + - resets + - clocks +\end{minted} + } + \end{block} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Device Tree binding: YAML style example} + \begin{block}{} + {\fontsize{5}{6}\selectfont +\begin{minted}{yaml} +examples: + - | + //Example 3 (with st,stm32mp15-i2c compatible on stm32mp) + #include + #include + #include + i2c@40013000 { + compatible = "st,stm32mp15-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40013000 0x400>; + interrupts = , + ; + clocks = <&rcc I2C2_K>; + resets = <&rcc I2C2_R>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + st,syscfg-fmp = <&syscfg 0x4 0x2>; + }; +\end{minted} + } + \end{block} +\end{frame} + +\begin{frame}{Validating Device Tree in Linux} + \begin{itemize} + \item \code{dtc} only does syntactic validation + \item YAML bindings allow to do semantic validation + \item Linux kernel \code{make} rules: + \begin{itemize} + \item \code{make dt_binding_check}\\ + verify that YAML bindings are valid + \item \code{make dtbs_check}\\ + validate DTs currently enabled against YAML bindings + \item \code{make DT_SCHEMA_FILES=Documentation/devicetree/bindings/trivial-devices.yaml dtbs_check}\\ + validate DTs against a specific YAML binding + \end{itemize} + \end{itemize} +\end{frame} + +\begin{frame}{The {\tt compatible} property} + \begin{itemize} + \item Is a list of strings + \begin{itemize} + \item From the most specific to the least specific + \end{itemize} + \item Describes the specific {\bf binding} to which the node complies. + \item It uniquely identifies the {\bf programming model} of the + device. + \item Practically speaking, it is used by the operating system to + find the {\bf appropriate driver} for this device. + \item When describing real hardware, the typical form is + \code{vendor,model} + \item Examples: + \begin{itemize} + \item \code{compatible = "arm,armv7-timer";} + \item \code{compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";} + \item \code{compatible = "regulator-fixed";} + \item \code{compatible = "gpio-keys";} + \end{itemize} + \item Special value: \code{simple-bus} $\rightarrow$ bus where all + sub-nodes are memory-mapped devices + \end{itemize} +\end{frame} + +\begin{frame}{{\tt compatible} property and Linux kernel drivers} + \begin{columns} + \column{0.6\textwidth} + \begin{itemize} + \item Linux identifies as {\bf platform devices}: + \begin{itemize} + \item Top-level DT nodes with a \code{compatible} string + \item Sub-nodes of \code{simple-bus} + \begin{itemize} + \item Instantiated automatically at boot time + \end{itemize} + \end{itemize} + \item Sub-nodes of I2C controllers $\rightarrow$ {\em I2C devices} + \item Sub-nodes of SPI controllers $\rightarrow$ {\em SPI devices} + \item Each Linux driver has a table of compatible strings it supports + \begin{itemize} + \item \kstruct{of_device_id}\code{[]} + \end{itemize} + \item When a DT node compatible string matches a given driver, the + device is {\em bound} to that driver. + \end{itemize} + \column{0.4\textwidth} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/dt-to-devices.pdf} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Matching with drivers in Linux: platform driver} + \begin{block}{\kfile{drivers/tty/serial/stm32-usart.c}} + {\tiny +\begin{minted}{c} +static const struct of_device_id stm32_match[] = { + { .compatible = "st,stm32-uart", .data = &stm32f4_info}, + { .compatible = "st,stm32f7-uart", .data = &stm32f7_info}, + { .compatible = "st,stm32h7-uart", .data = &stm32h7_info}, + {}, +}; +MODULE_DEVICE_TABLE(of, stm32_match); + +... + +static struct platform_driver stm32_serial_driver = { + .probe = stm32_serial_probe, + .remove = stm32_serial_remove, + .driver = { + .name = DRIVER_NAME, + .pm = &stm32_serial_pm_ops, + .of_match_table = of_match_ptr(stm32_match), + }, +}; +\end{minted} + } + \end{block} +\end{frame} + +\begin{frame}[fragile]{Matching with drivers in Linux: I2C driver} + \begin{block}{\kfile{sound/soc/codecs/cs42l51.c}} + {\tiny +\begin{minted}{c} +const struct of_device_id cs42l51_of_match[] = { + { .compatible = "cirrus,cs42l51", }, + { } +}; +MODULE_DEVICE_TABLE(of, cs42l51_of_match); +\end{minted} + } + \end{block} + \begin{block}{\kfile{sound/soc/codecs/cs42l51-i2c.c}} + {\tiny +\begin{minted}{c} +static struct i2c_driver cs42l51_i2c_driver = { + .driver = { + .name = "cs42l51", + .of_match_table = cs42l51_of_match, + .pm = &cs42l51_pm_ops, + }, + .probe = cs42l51_i2c_probe, + .remove = cs42l51_i2c_remove, + .id_table = cs42l51_i2c_id, +}; +\end{minted} + } + \end{block} +\end{frame} + +\begin{frame}[fragile]{{\tt reg} property} + \begin{itemize} + \item Most important property after \code{compatible} + \item {\bf Memory-mapped} devices: base physical address and size of + the memory-mapped registers. Can have several entries for multiple + register areas. +\begin{onlyenv}<1> +\begin{block}{} +\begin{verbatim} +sai4: sai@50027000 { + reg = <0x50027000 0x4>, <0x500273f0 0x10>; +}; +\end{verbatim} +\end{block} +\end{onlyenv} +\pause + \item {\bf I2C} devices: address of the device on the I2C bus. +\begin{onlyenv}<2> +\begin{block}{} +\begin{verbatim} +&i2c1 { + hdmi-transmitter@39 { + reg = <0x39>; + }; + cs42l51: cs42l51@4a { + reg = <0x4a>; + }; +}; +\end{verbatim} +\end{block} +\end{onlyenv} +\pause + \item {\bf SPI} devices: chip select number +\begin{onlyenv}<3> +\begin{block}{} +\begin{verbatim} +&qspi { + flash0: mx66l51235l@0 { + reg = <0>; + }; + flash1: mx66l51235l@1 { + reg = <1>; + }; +}; +\end{verbatim} +\end{block} +\end{onlyenv} +\pause +\item The unit address must be the address of the first \code{reg} + entry. +\begin{onlyenv}<4> +\begin{block}{} +\begin{verbatim} +sai4: sai@50027000 { + reg = <0x50027000 0x4>, <0x500273f0 0x10>; +}; +\end{verbatim} +\end{block} +\end{onlyenv} + \end{itemize} +\end{frame} + +\begin{frame}{Status property} + \begin{itemize} + \item The \code{status} property indicates if the device is really in + use or not + \begin{itemize} + \item \code{okay} or \code{ok} $\rightarrow$ the device is really + in use + \item any other value, by convention \code{disabled} $\rightarrow$ + the device is not in use + \end{itemize} + \item In Linux, controls if a device is instantiated + \item In \code{.dtsi} files describing SoCs: all devices that + interface to the outside world have \code{status = "disabled";} + \item Enabled on a per-device basis in the board \code{.dts} + \end{itemize} +\end{frame} + +\begin{frame}[fragile]{Resources: interrupts, clocks, DMA, reset lines, ...} + \begin{columns} + \column{0.5\textwidth} + \begin{itemize} + \item Common pattern for resources shared by multiple hardware + blocks + \begin{itemize} + \item Interrupt lines + \item Clock controllers + \item DMA controllers + \item Reset controllers + \item ... + \end{itemize} + \item A Device Tree node describing the {\em controller} as a device + \item References from other nodes that use resources provided by + this {\em controller} + \end{itemize} + \column{0.5\textwidth} +\begin{block}{} +{\tiny +\begin{minted}{perl} +intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, <0xa0022000 0x2000>; +}; + +rcc: rcc@50000000 { + compatible = "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #clock-cells = <1>; + #reset-cells = <1>; +}; + +dmamux1: dma-router@48002000 { + compatible = "st,stm32h7-dmamux"; + reg = <0x48002000 0x1c>; + #dma-cells = <3>; + clocks = <&rcc DMAMUX>; + resets = <&rcc DMAMUX_R>; +}; + +spi3: spi@4000c000 { + interrupts = ; + clocks = <&rcc SPI3_K>; + resets = <&rcc SPI3_R>; + dmas = <&dmamux1 61 0x400 0x05>, <&dmamux1 62 0x400 0x05>; +}; +\end{minted} +} +\end{block} +\end{columns} +\end{frame} + +\begin{frame}{Pin-muxing description} + \begin{columns} + \column{0.5\textwidth} + \begin{itemize} + \item Most modern SoCs, including the STM32MP1, have more features + than they have pins to expose those features to the outside world. + \item Pins are muxed: a given pin can be used for one function + {\bf or} another + \item A specific IP block in the SoC controls the muxing of pins: + the {\bf pinmux controller} + \item The Device Tree describes which pin configurations are + possible, and which configurations are used by the different + devices. + \end{itemize} + \column{0.5\textwidth} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/pin-muxing-principle.pdf} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Pin-muxing controllers on STM32MP1} + \begin{block}{\kfileversion{arch/arm/boot/dts/stm32mp151.dtsi}{6.1}} +{\tiny +\begin{minted}{perl} +pinctrl: pin-controller@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-pinctrl"; + ... + gpioa: gpio@50002000 { ... }; + gpiob: gpio@50003000 { ... }; + gpioc: gpio@50004000 { ... }; + gpiod: gpio@50005000 { ... }; + gpioe: gpio@50006000 { ... }; + gpiof: gpio@50007000 { ... }; + ... +}; + +pinctrl_z: pin-controller-z@54004000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-z-pinctrl"; + ranges = <0 0x54004000 0x400>; + ... + gpioz: gpio@54004000 { .... }; + ... +}; +\end{minted} +} + \end{block} +\end{frame} + +\begin{frame}[fragile]{Pin-muxing configuration} +\begin{onlyenv}<1> + \begin{block}{\kfile{arch/arm/boot/dts/stm32mp15-pinctrl.dtsi}} +{\tiny +\begin{minted}{perl} +&pinctrl { + ... + i2c1_pins_a: i2c1-0 { + pins { + pinmux = , /* I2C1_SCL */ + ; /* I2C1_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + ... + m_can1_pins_a: m-can1-0 { + pins1 { + pinmux = ; /* CAN1_TX */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* CAN1_RX */ + bias-disable; + }; + }; + ... +}; +\end{minted} +} + \end{block} +\end{onlyenv} +\begin{onlyenv}<2> + \begin{center} + \includegraphics[height=0.78\textheight]{slides/sysdev-hw-devices/stm32mp1/stm32mp157-i2c-pin-mux.png} + \end{center} + \tiny + Source: \href{https://www.st.com/resource/en/datasheet/stm32mp157c.pdf}{STM32MP157C + datasheet}. Note that \code{I2C1_SDA} is also available on pin \code{PF15} (not shown here). +\end{onlyenv} +\end{frame} + +\begin{frame}[fragile]{Pin-muxing consumer} + \begin{block}{} +{\tiny +\begin{minted}{perl} +&i2c1 { + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c1_pins_a>; + pinctrl-1 = <&i2c1_sleep_pins_a>; + ... +}; +\end{minted} +} +\end{block} +\begin{itemize} +\item Typically board-specific, in \code{.dts} +\item \code{pinctrl-0}, \code{pinctrl-1}, \code{pinctrl-X} provides + the pin mux configurations for the different {\bf states} +\item \code{pinctrl-names} gives a name to each state, mandatory even + if only one state +\item States are mutually exclusive +\item The driver is responsible for switching between states +\item \code{default} state is automatically set up when the device is + {\em probed} +\end{itemize} +\end{frame} + +\begin{frame}[fragile]{Example: LED and I2C device} + \begin{itemize} + \item Let's see how to describe an LED and an I2C device connected + to the DK1 platform. + \item Create \code{arch/arm/boot/dts/stm32mp157a-dk1-custom.dts} + which includes \code{stm32mp157a-dk1.dts} + \begin{block}{} +{\tiny +\begin{verbatim} +#include "stm32mp157a-dk1.dts" +\end{verbatim} +} + \end{block} + \item Make sure \code{stm32mp157a-dk1-custom.dts} gets compiled to a + DTB by changing \kfile{arch/arm/boot/dts/Makefile} + \begin{block}{} + {\tiny +\begin{verbatim} +dtb-$(CONFIG_ARCH_STM32) += \ + ... + stm32mp157a-dk1.dtb \ + stm32mp157a-dk1-custom.dtb \ +\end{verbatim} + } + \end{block} + \item \code{make dtbs} + \begin{block}{} + {\tiny +\begin{verbatim} + DTC arch/arm/boot/dts/stm32mp157a-dk1-custom.dtb +\end{verbatim} + } + \end{block} + \end{itemize} +\end{frame} + +\begin{frame}[fragile]{Example: describe an LED} + \begin{columns} + \column{0.5\textwidth} + \begin{block}{stm32mp157a-dk1-custom.dts} + {\tiny +\begin{minted}{perl} +#include "stm32mp157a-dk1.dts" + +/ { + leds { + compatible = "gpio-leds"; + webinar { + label = "webinar"; + gpios = <&gpioe 1 GPIO_ACTIVE_HIGH>; + }; + }; +}; +\end{minted} + } + \end{block} + \begin{block}{shell} +{\tiny +\begin{verbatim} +# echo 255 > /sys/class/leds/webinar/brightness +\end{verbatim} +} +\end{block} + \column{0.5\textwidth} + \begin{center} + \includegraphics[height=0.3\textheight]{slides/sysdev-hw-devices/stm32mp1/cn14-pinout.png}\\ + \vspace{0.5cm} + \includegraphics[height=0.3\textheight]{slides/sysdev-hw-devices/stm32mp1/led-on.jpg} + \end{center} + \end{columns} +\end{frame} + +\begin{frame}[fragile]{Example: connect I2C temperature, humidity and pressure sensor} + \begin{columns} + \column{0.5\textwidth} + \begin{block}{stm32mp157a-dk1-custom.dts} + {\tiny +\begin{minted}{perl} +&i2c5 { + status = "okay"; + clock-frequency = <100000>; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&i2c5_pins_a>; + pinctrl-1 = <&i2c5_pins_sleep_a>; + + pressure@76 { + compatible = "bosch,bme280"; + reg = <0x76>; + }; +}; +\end{minted} +} + \end{block} + +\begin{block}{shell} +{\tiny +\begin{verbatim} +# cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_input +49147 +# cat /sys/bus/iio/devices/iio\:device2/in_pressure_input +101.567167968 +# cat /sys/bus/iio/devices/iio\:device2/in_temp_input +24380 +\end{verbatim} +} +\end{block} + \column{0.5\textwidth} + \begin{center} + \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/stm32mp1/cn13-pinout.png}\\ + \includegraphics[width=0.4\textwidth]{slides/sysdev-hw-devices/bme.jpg} + \end{center} +\end{columns} +\vspace{0.5cm} +Details at +\url{https://bootlin.com/blog/building-a-linux-system-for-the-stm32mp1-connecting-an-i2c-sensor/} +\end{frame} + +\begin{frame}{Further details about the Device Tree} +\small +Check out our {\em Device Tree 101 webinar}, by Thomas Petazzoni (2021) +\begin{itemize} + \item Slides: \url{https://bootlin.com/blog/device-tree-101-webinar-slides-and-videos/}\\ + \item Video: \url{https://youtu.be/a9CZ1Uk3OYQ} +\end{itemize} +\vspace{0.5cm} +\includegraphics[height=0.5\textheight]{common/device-tree-video.jpg} +\end{frame} + +\subsection{Discoverable hardware: USB and PCI} + +\begin{frame}{Discoverable hardware} + \begin{itemize} + \item Some busses have built-in hardware discoverability mechanisms + \item Most common busses: USB and PCI + \item Hardware devices can be enumerated, and their characteristics + retrieved with just a driver or the bus controller + \item Useful Linux commands + \begin{itemize} + \item \code{lsusb}, lists all USB devices detected + \item \code{lspci}, lists all PCI devices detected + \item A detected device does not mean it has a kernel driver + associated to it! + \end{itemize} + \item Association with kernel drivers done based on product + ID/vendor ID, or some other characteristics of the device: device + class, device sub-class, etc. + \end{itemize} +\end{frame} + +\setuplabframe +{Accessing hardware devices} +{ + Time to start the practical lab! + \begin{itemize} + \item Exploring the contents of \code{/dev} and \code{/sys} and the + devices available on the embedded hardware platform. + \item Using GPIOs and LEDs. + \item Modifying the Device Tree to control pin multiplexing and + declare an I2C-connected joystick. + \item Adding support for a USB audio card using Linux kernel modules + \item Adding support for the I2C-connected joystick through + an out-of-tree module. + \end{itemize} +} diff --git a/slides/sysdev-hw-devices/sysdev-hw-devices.tex b/slides/sysdev-hw-devices/sysdev-hw-devices.tex index 67197d246f..ccdad1a347 100644 --- a/slides/sysdev-hw-devices/sysdev-hw-devices.tex +++ b/slides/sysdev-hw-devices/sysdev-hw-devices.tex @@ -926,1044 +926,9 @@ \subsection{Describing non-discoverable hardware: Device Tree} \end{columns} \end{frame} -\begin{frame}[fragile]{DT overall structure: simplified example} - \begin{columns} - \column{0.6\textwidth} - \begin{onlyenv}<1> - \begin{block}{} -\begin{minted}[fontsize=\tiny]{perl} -/ { - #address-cells = <1>; - #size-cells = <1>; - model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; - compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; - - cpus { ... }; - memory@0 { ... }; - chosen { ... }; - intc: interrupt-controller@a0021000 { ... }; - soc { - i2c1: i2c@40012000 { ... }; - ethernet0: ethernet@5800a000 { ... }; - }; -}; -\end{minted} - \end{block} - \end{onlyenv} - \begin{onlyenv}<2> - \begin{block}{} -\begin{minted}[fontsize=\tiny]{perl} -/ { - cpus { - #address-cells = <1>; - #size-cells = <0>; - cpu0: cpu@0 { - compatible = "arm,cortex-a7"; - clock-frequency = <650000000>; - device_type = "cpu"; - reg = <0>; - }; - - cpu1: cpu@1 { - compatible = "arm,cortex-a7"; - clock-frequency = <650000000>; - device_type = "cpu"; - reg = <1>; - }; - }; - - memory@0 { ... }; - chosen { ... }; - intc: interrupt-controller@a0021000 { ... }; - soc { - i2c1: i2c@40012000 { ... }; - ethernet0: ethernet@5800a000 { ... }; - }; -}; -\end{minted} - \end{block} - \end{onlyenv} - \begin{onlyenv}<3> - \begin{block}{} -\begin{minted}[fontsize=\tiny]{perl} -/ { - cpus { ... }; - memory@0 { - device_type = "memory"; - reg = <0x0 0x20000000>; - }; - - chosen { - bootargs = ""; - stdout-path = "serial0:115200n8"; - }; - intc: interrupt-controller@a0021000 { ... }; - soc { - i2c1: i2c@40012000 { ... }; - ethernet0: ethernet@5800a000 { ... }; - }; -}; -\end{minted} - \end{block} - \end{onlyenv} - \begin{onlyenv}<4> - \begin{block}{} -\begin{minted}[fontsize=\tiny]{perl} -/ { - cpus { ... }; - memory@0 { ... }; - chosen { ... }; - - intc: interrupt-controller@a0021000 { - compatible = "arm,cortex-a7-gic"; - #interrupt-cells = <3>; - interrupt-controller; - reg = <0xa0021000 0x1000>, - <0xa0022000 0x2000>; - }; - - soc { - compatible = "simple-bus"; - #address-cells = <1>; - #size-cells = <1>; - interrupt-parent = <&intc>; - - i2c1: i2c@40012000 { ... }; - ethernet0: ethernet@5800a000 { ... }; - }; -}; -\end{minted} - \end{block} - \end{onlyenv} - \begin{onlyenv}<5> - \begin{block}{} -\begin{minted}[fontsize=\tiny]{perl} -/ { - cpus { ... }; - memory@0 { ... }; - chosen { ... }; - intc: interrupt-controller@a0021000 { ... }; - soc { - i2c1: i2c@40012000 { - compatible = "st,stm32mp15-i2c"; - reg = <0x40012000 0x400>; - interrupts = , - ; - #address-cells = <1>; - #size-cells = <0>; - status = "okay"; - - cs42l51: cs42l51@4a { - compatible = "cirrus,cs42l51"; - reg = <0x4a>; - reset-gpios = <&gpiog 9 GPIO_ACTIVE_LOW>; - status = "okay"; - }; - }; - ethernet0: ethernet@5800a000 { ... }; - }; -}; -\end{minted} - \end{block} - \end{onlyenv} - \begin{onlyenv}<6> - \begin{block}{} -\begin{minted}[fontsize=\tiny]{perl} -/ { - cpus { ... }; - memory@0 { ... }; - chosen { ... }; - intc: interrupt-controller@a0021000 { ... }; - soc { - compatible = "simple-bus"; - ... - interrupt-parent = <&intc>; - i2c1: i2c@40012000 { ... }; - - ethernet0: ethernet@5800a000 { - compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a"; - reg = <0x5800a000 0x2000>; - interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>; - status = "okay"; - - mdio0 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "snps,dwmac-mdio"; - phy0: ethernet-phy@0 { - reg = <0>; - }; - }; - }; - }; -}; -\end{minted} - \end{block} - \end{onlyenv} - \column{0.4\textwidth} - \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/simple-hardware.pdf} - \end{columns} -\end{frame} - -\begin{frame}[fragile]{Device Tree inheritance} - \begin{itemize} - \item Device Tree files are not monolithic, they can be split in - several files, including each other. - \item \code{.dtsi} files are included files, while \code{.dts} files - are {\em final} Device Trees - \begin{itemize} - \item Only \code{.dts} files are accepted as input to \code{dtc} - \end{itemize} - \item Typically, \code{.dtsi} will contain - \begin{itemize} - \item definitions of SoC-level information - \item definitions common to several boards - \end{itemize} - \item The \code{.dts} file contains the board-level information - \item The inclusion works by {\bf overlaying} the tree of the - including file over the tree of the included file, - according to the order of the \code{#include} directives. - \item Allows an including file to {\bf override} values specified by - an included file - \item Uses the C pre-processor \code{#include} directive - \end{itemize} -\end{frame} - -\begin{frame}{Device Tree inheritance example} - \begin{center} - \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/dt-inheritance.pdf} - \end{center} -\end{frame} - -\begin{frame}[fragile]{Inheritance and labels} - - \begin{columns}[t] - \column{0.5\textwidth} - Doing: - \begin{block}{soc.dtsi} - {\tiny -\begin{minted}{perl} -/ { - soc { - usart1: serial@5c000000 { - compatible = "st,stm32h7-uart"; - reg = <0x5c000000 0x400>; - status = "disabled"; - }; - }; -}; -\end{minted} - } - \end{block} - - \begin{block}{board.dts} - {\tiny -\begin{minted}{perl} -#include "soc.dtsi" - -/ { - soc { - serial@5c000000 { - status = "okay"; - }; - }; -}; -\end{minted} - } - \end{block} - - \column{0.5\textwidth} - \begin{onlyenv}<2> - Is exactly equivalent to: - - \begin{block}{soc.dtsi} - {\tiny -\begin{minted}{perl} -/ { - soc { - usart1: serial@5c000000 { - compatible = "st,stm32h7-uart"; - reg = <0x5c000000 0x400>; - status = "disabled"; - }; - }; -}; -\end{minted} - } - \end{block} - - \begin{block}{board.dts} - {\tiny -\begin{minted}{perl} -#include "soc.dtsi" - -&usart1 { - status = "okay"; -}; -\end{minted} - } - \end{block} - - $\rightarrow$ this solution is now often preferred - \end{onlyenv} - \end{columns} - -\end{frame} - -\begin{frame}{DT inheritance in STM32MP1 support} - \begin{center} - \includegraphics[height=0.8\textheight]{slides/sysdev-hw-devices/dt-inheritance-stm32.pdf} - \end{center} -\end{frame} - -\begin{frame}{Device Tree design principles} - \begin{itemize} - \item {\bf Describe hardware} (how the hardware is), not - configuration (how I choose to use the hardware) - \item {\bf OS-agnostic} - \begin{itemize} - \item For a given piece of HW, Device Tree should be the same for - U-Boot, FreeBSD or Linux - \item There should be no need to change the Device Tree when updating the OS - \end{itemize} - \item Describe {\bf integration of hardware components}, not the internals - of hardware components - \begin{itemize} - \item The details of how a specific device/IP block is working is - handled by code in device drivers - \item The Device Tree describes how the device/IP block is - connected/integrated with the rest of the system: IRQ lines, DMA - channels, clocks, reset lines, etc. - \end{itemize} - \item Like all beautiful design principles, these principles are - sometimes violated. - \end{itemize} -\end{frame} - -\begin{frame}{Device Tree specifications} - \begin{columns} - \column{0.7\textwidth} - \begin{itemize} - \item How to write the correct nodes/properties to describe a - given hardware platform~? - \item {\bf Device Tree Specifications} $\rightarrow$ base Device - Tree syntax + number of standard properties. - \begin{itemize} - \item \url{https://www.devicetree.org/specifications/} - \item Not sufficient to describe the wide variety of hardware. - \end{itemize} - \item {\bf Device Tree Bindings} $\rightarrow$ documents that each - specify how a piece of HW should be described - \begin{itemize} - \item \kdir{Documentation/devicetree/bindings} in Linux kernel sources - \item Reviewed by DT bindings maintainer team - \item Legacy: human readable documents - \item New norm: YAML-written specifications - \end{itemize} - \end{itemize} - \column{0.3\textwidth} - \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/dt-spec.png} - \end{columns} -\end{frame} - -\begin{frame}[fragile]{Device Tree binding: old style} - \begin{center} - \kfile{Documentation/devicetree/bindings/mtd/spear_smi.txt}\\ - This IP is {\em not} used on STM32MP1. - \end{center} - \begin{columns}[t] - \column{0.5\textwidth} - \begin{block}{} - {\fontsize{5}{6}\selectfont -\begin{verbatim} -* SPEAr SMI - -Required properties: -- compatible : "st,spear600-smi" -- reg : Address range of the mtd chip -- #address-cells, #size-cells : Must be present if the device has sub-nodes - representing partitions. -- interrupts: Should contain the STMMAC interrupts -- clock-rate : Functional clock rate of SMI in Hz - -Optional properties: -- st,smi-fast-mode : Flash supports read in fast mode - -\end{verbatim} - } - \end{block} - \column{0.5\textwidth} - \begin{block}{} - {\fontsize{4}{5}\selectfont -\begin{verbatim} -Example: - - smi: flash@fc000000 { - compatible = "st,spear600-smi"; - #address-cells = <1>; - #size-cells = <1>; - reg = <0xfc000000 0x1000>; - interrupt-parent = <&vic1>; - interrupts = <12>; - clock-rate = <50000000>; /* 50MHz */ - - flash@f8000000 { - st,smi-fast-mode; - ... - }; - }; -\end{verbatim} - } - \end{block} - \end{columns} - -\end{frame} - -\begin{frame}[fragile]{Device Tree binding: YAML style} - \kfile{Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml} - \begin{columns}[t] - \column{0.5\textwidth} - \begin{block}{} - {\fontsize{5}{6}\selectfont -\begin{minted}{yaml} -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/i2c/st,stm32-i2c.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: I2C controller embedded in STMicroelectronics STM32 I2C platform - -maintainers: - - Pierre-Yves MORDRET - -properties: - compatible: - enum: - - st,stm32f4-i2c - - st,stm32f7-i2c - - st,stm32mp15-i2c - - reg: - maxItems: 1 - - interrupts: - items: - - description: interrupt ID for I2C event - - description: interrupt ID for I2C error - - resets: - maxItems: 1 - -\end{minted} - } - \end{block} - \column{0.5\textwidth} - \begin{block}{} - {\fontsize{5}{6}\selectfont -\begin{minted}{yaml} - clocks: - maxItems: 1 - - dmas: - items: - - description: RX DMA Channel phandle - - description: TX DMA Channel phandle - - ... - - clock-frequency: - description: Desired I2C bus clock frequency in Hz. If not specified, - the default 100 kHz frequency will be used. - For STM32F7, STM32H7 and STM32MP1 SoCs, if timing - parameters match, the bus clock frequency can be from - 1Hz to 1MHz. - default: 100000 - minimum: 1 - maximum: 1000000 - -required: - - compatible - - reg - - interrupts - - resets - - clocks -\end{minted} - } - \end{block} - \end{columns} -\end{frame} - -\begin{frame}[fragile]{Device Tree binding: YAML style example} - \begin{block}{} - {\fontsize{5}{6}\selectfont -\begin{minted}{yaml} -examples: - - | - //Example 3 (with st,stm32mp15-i2c compatible on stm32mp) - #include - #include - #include - i2c@40013000 { - compatible = "st,stm32mp15-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40013000 0x400>; - interrupts = , - ; - clocks = <&rcc I2C2_K>; - resets = <&rcc I2C2_R>; - i2c-scl-rising-time-ns = <185>; - i2c-scl-falling-time-ns = <20>; - st,syscfg-fmp = <&syscfg 0x4 0x2>; - }; -\end{minted} - } - \end{block} -\end{frame} - -\begin{frame}{Validating Device Tree in Linux} - \begin{itemize} - \item \code{dtc} only does syntactic validation - \item YAML bindings allow to do semantic validation - \item Linux kernel \code{make} rules: - \begin{itemize} - \item \code{make dt_binding_check}\\ - verify that YAML bindings are valid - \item \code{make dtbs_check}\\ - validate DTs currently enabled against YAML bindings - \item \code{make DT_SCHEMA_FILES=Documentation/devicetree/bindings/trivial-devices.yaml dtbs_check}\\ - validate DTs against a specific YAML binding - \end{itemize} - \end{itemize} -\end{frame} - -\begin{frame}{The {\tt compatible} property} - \begin{itemize} - \item Is a list of strings - \begin{itemize} - \item From the most specific to the least specific - \end{itemize} - \item Describes the specific {\bf binding} to which the node complies. - \item It uniquely identifies the {\bf programming model} of the - device. - \item Practically speaking, it is used by the operating system to - find the {\bf appropriate driver} for this device. - \item When describing real hardware, the typical form is - \code{vendor,model} - \item Examples: - \begin{itemize} - \item \code{compatible = "arm,armv7-timer";} - \item \code{compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";} - \item \code{compatible = "regulator-fixed";} - \item \code{compatible = "gpio-keys";} - \end{itemize} - \item Special value: \code{simple-bus} $\rightarrow$ bus where all - sub-nodes are memory-mapped devices - \end{itemize} -\end{frame} - -\begin{frame}{{\tt compatible} property and Linux kernel drivers} - \begin{columns} - \column{0.6\textwidth} - \begin{itemize} - \item Linux identifies as {\bf platform devices}: - \begin{itemize} - \item Top-level DT nodes with a \code{compatible} string - \item Sub-nodes of \code{simple-bus} - \begin{itemize} - \item Instantiated automatically at boot time - \end{itemize} - \end{itemize} - \item Sub-nodes of I2C controllers $\rightarrow$ {\em I2C devices} - \item Sub-nodes of SPI controllers $\rightarrow$ {\em SPI devices} - \item Each Linux driver has a table of compatible strings it supports - \begin{itemize} - \item \kstruct{of_device_id}\code{[]} - \end{itemize} - \item When a DT node compatible string matches a given driver, the - device is {\em bound} to that driver. - \end{itemize} - \column{0.4\textwidth} - \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/dt-to-devices.pdf} - \end{columns} -\end{frame} - -\begin{frame}[fragile]{Matching with drivers in Linux: platform driver} - \begin{block}{\kfile{drivers/tty/serial/stm32-usart.c}} - {\tiny -\begin{minted}{c} -static const struct of_device_id stm32_match[] = { - { .compatible = "st,stm32-uart", .data = &stm32f4_info}, - { .compatible = "st,stm32f7-uart", .data = &stm32f7_info}, - { .compatible = "st,stm32h7-uart", .data = &stm32h7_info}, - {}, -}; -MODULE_DEVICE_TABLE(of, stm32_match); - -... - -static struct platform_driver stm32_serial_driver = { - .probe = stm32_serial_probe, - .remove = stm32_serial_remove, - .driver = { - .name = DRIVER_NAME, - .pm = &stm32_serial_pm_ops, - .of_match_table = of_match_ptr(stm32_match), - }, -}; -\end{minted} - } - \end{block} -\end{frame} - -\begin{frame}[fragile]{Matching with drivers in Linux: I2C driver} - \begin{block}{\kfile{sound/soc/codecs/cs42l51.c}} - {\tiny -\begin{minted}{c} -const struct of_device_id cs42l51_of_match[] = { - { .compatible = "cirrus,cs42l51", }, - { } -}; -MODULE_DEVICE_TABLE(of, cs42l51_of_match); -\end{minted} - } - \end{block} - \begin{block}{\kfile{sound/soc/codecs/cs42l51-i2c.c}} - {\tiny -\begin{minted}{c} -static struct i2c_driver cs42l51_i2c_driver = { - .driver = { - .name = "cs42l51", - .of_match_table = cs42l51_of_match, - .pm = &cs42l51_pm_ops, - }, - .probe = cs42l51_i2c_probe, - .remove = cs42l51_i2c_remove, - .id_table = cs42l51_i2c_id, -}; -\end{minted} - } - \end{block} -\end{frame} - -\begin{frame}[fragile]{{\tt reg} property} - \begin{itemize} - \item Most important property after \code{compatible} - \item {\bf Memory-mapped} devices: base physical address and size of - the memory-mapped registers. Can have several entries for multiple - register areas. -\begin{onlyenv}<1> -\begin{block}{} -\begin{verbatim} -sai4: sai@50027000 { - reg = <0x50027000 0x4>, <0x500273f0 0x10>; -}; -\end{verbatim} -\end{block} -\end{onlyenv} -\pause - \item {\bf I2C} devices: address of the device on the I2C bus. -\begin{onlyenv}<2> -\begin{block}{} -\begin{verbatim} -&i2c1 { - hdmi-transmitter@39 { - reg = <0x39>; - }; - cs42l51: cs42l51@4a { - reg = <0x4a>; - }; -}; -\end{verbatim} -\end{block} -\end{onlyenv} -\pause - \item {\bf SPI} devices: chip select number -\begin{onlyenv}<3> -\begin{block}{} -\begin{verbatim} -&qspi { - flash0: mx66l51235l@0 { - reg = <0>; - }; - flash1: mx66l51235l@1 { - reg = <1>; - }; -}; -\end{verbatim} -\end{block} -\end{onlyenv} -\pause -\item The unit address must be the address of the first \code{reg} - entry. -\begin{onlyenv}<4> -\begin{block}{} -\begin{verbatim} -sai4: sai@50027000 { - reg = <0x50027000 0x4>, <0x500273f0 0x10>; -}; -\end{verbatim} -\end{block} -\end{onlyenv} - \end{itemize} -\end{frame} - -\begin{frame}{Status property} - \begin{itemize} - \item The \code{status} property indicates if the device is really in - use or not - \begin{itemize} - \item \code{okay} or \code{ok} $\rightarrow$ the device is really - in use - \item any other value, by convention \code{disabled} $\rightarrow$ - the device is not in use - \end{itemize} - \item In Linux, controls if a device is instantiated - \item In \code{.dtsi} files describing SoCs: all devices that - interface to the outside world have \code{status = "disabled";} - \item Enabled on a per-device basis in the board \code{.dts} - \end{itemize} -\end{frame} - -\begin{frame}[fragile]{Resources: interrupts, clocks, DMA, reset lines, ...} - \begin{columns} - \column{0.5\textwidth} - \begin{itemize} - \item Common pattern for resources shared by multiple hardware - blocks - \begin{itemize} - \item Interrupt lines - \item Clock controllers - \item DMA controllers - \item Reset controllers - \item ... - \end{itemize} - \item A Device Tree node describing the {\em controller} as a device - \item References from other nodes that use resources provided by - this {\em controller} - \end{itemize} - \column{0.5\textwidth} -\begin{block}{} -{\tiny -\begin{minted}{perl} -intc: interrupt-controller@a0021000 { - compatible = "arm,cortex-a7-gic"; - #interrupt-cells = <3>; - interrupt-controller; - reg = <0xa0021000 0x1000>, <0xa0022000 0x2000>; -}; - -rcc: rcc@50000000 { - compatible = "st,stm32mp1-rcc", "syscon"; - reg = <0x50000000 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; -}; - -dmamux1: dma-router@48002000 { - compatible = "st,stm32h7-dmamux"; - reg = <0x48002000 0x1c>; - #dma-cells = <3>; - clocks = <&rcc DMAMUX>; - resets = <&rcc DMAMUX_R>; -}; - -spi3: spi@4000c000 { - interrupts = ; - clocks = <&rcc SPI3_K>; - resets = <&rcc SPI3_R>; - dmas = <&dmamux1 61 0x400 0x05>, <&dmamux1 62 0x400 0x05>; -}; -\end{minted} -} -\end{block} -\end{columns} -\end{frame} - -\begin{frame}{Pin-muxing description} - \begin{columns} - \column{0.5\textwidth} - \begin{itemize} - \item Most modern SoCs, including the STM32MP1, have more features - than they have pins to expose those features to the outside world. - \item Pins are muxed: a given pin can be used for one function - {\bf or} another - \item A specific IP block in the SoC controls the muxing of pins: - the {\bf pinmux controller} - \item The Device Tree describes which pin configurations are - possible, and which configurations are used by the different - devices. - \end{itemize} - \column{0.5\textwidth} - \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/pin-muxing-principle.pdf} - \end{columns} -\end{frame} - -\begin{frame}[fragile]{Pin-muxing controllers on STM32MP1} - \begin{block}{\kfileversion{arch/arm/boot/dts/stm32mp151.dtsi}{6.1}} -{\tiny -\begin{minted}{perl} -pinctrl: pin-controller@50002000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "st,stm32mp157-pinctrl"; - ... - gpioa: gpio@50002000 { ... }; - gpiob: gpio@50003000 { ... }; - gpioc: gpio@50004000 { ... }; - gpiod: gpio@50005000 { ... }; - gpioe: gpio@50006000 { ... }; - gpiof: gpio@50007000 { ... }; - ... -}; - -pinctrl_z: pin-controller-z@54004000 { - #address-cells = <1>; - #size-cells = <1>; - compatible = "st,stm32mp157-z-pinctrl"; - ranges = <0 0x54004000 0x400>; - ... - gpioz: gpio@54004000 { .... }; - ... -}; -\end{minted} -} - \end{block} -\end{frame} - -\begin{frame}[fragile]{Pin-muxing configuration} -\begin{onlyenv}<1> - \begin{block}{\kfile{arch/arm/boot/dts/stm32mp15-pinctrl.dtsi}} -{\tiny -\begin{minted}{perl} -&pinctrl { - ... - i2c1_pins_a: i2c1-0 { - pins { - pinmux = , /* I2C1_SCL */ - ; /* I2C1_SDA */ - bias-disable; - drive-open-drain; - slew-rate = <0>; - }; - }; - ... - m_can1_pins_a: m-can1-0 { - pins1 { - pinmux = ; /* CAN1_TX */ - slew-rate = <1>; - drive-push-pull; - bias-disable; - }; - pins2 { - pinmux = ; /* CAN1_RX */ - bias-disable; - }; - }; - ... -}; -\end{minted} -} - \end{block} -\end{onlyenv} -\begin{onlyenv}<2> - \begin{center} - \includegraphics[height=0.78\textheight]{slides/sysdev-hw-devices/stm32mp157-i2c-pin-mux.png} - \end{center} - \tiny - Source: \href{https://www.st.com/resource/en/datasheet/stm32mp157c.pdf}{STM32MP157C - datasheet}. Note that \code{I2C1_SDA} is also available on pin \code{PF15} (not shown here). -\end{onlyenv} -\end{frame} - -\begin{frame}[fragile]{Pin-muxing consumer} - \begin{block}{} -{\tiny -\begin{minted}{perl} -&i2c1 { - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&i2c1_pins_a>; - pinctrl-1 = <&i2c1_sleep_pins_a>; - ... -}; -\end{minted} -} -\end{block} -\begin{itemize} -\item Typically board-specific, in \code{.dts} -\item \code{pinctrl-0}, \code{pinctrl-1}, \code{pinctrl-X} provides - the pin mux configurations for the different {\bf states} -\item \code{pinctrl-names} gives a name to each state, mandatory even - if only one state -\item States are mutually exclusive -\item The driver is responsible for switching between states -\item \code{default} state is automatically set up when the device is - {\em probed} -\end{itemize} -\end{frame} - -\begin{frame}[fragile]{Example: LED and I2C device} - \begin{itemize} - \item Let's see how to describe an LED and an I2C device connected - to the DK1 platform. - \item Create \code{arch/arm/boot/dts/stm32mp157a-dk1-custom.dts} - which includes \code{stm32mp157a-dk1.dts} - \begin{block}{} -{\tiny -\begin{verbatim} -#include "stm32mp157a-dk1.dts" -\end{verbatim} -} - \end{block} - \item Make sure \code{stm32mp157a-dk1-custom.dts} gets compiled to a - DTB by changing \kfile{arch/arm/boot/dts/Makefile} - \begin{block}{} - {\tiny -\begin{verbatim} -dtb-$(CONFIG_ARCH_STM32) += \ - ... - stm32mp157a-dk1.dtb \ - stm32mp157a-dk1-custom.dtb \ -\end{verbatim} - } - \end{block} - \item \code{make dtbs} - \begin{block}{} - {\tiny -\begin{verbatim} - DTC arch/arm/boot/dts/stm32mp157a-dk1-custom.dtb -\end{verbatim} - } - \end{block} - \end{itemize} -\end{frame} - -\begin{frame}[fragile]{Example: describe an LED} - \begin{columns} - \column{0.5\textwidth} - \begin{block}{stm32mp157a-dk1-custom.dts} - {\tiny -\begin{minted}{perl} -#include "stm32mp157a-dk1.dts" - -/ { - leds { - compatible = "gpio-leds"; - webinar { - label = "webinar"; - gpios = <&gpioe 1 GPIO_ACTIVE_HIGH>; - }; - }; -}; -\end{minted} - } - \end{block} - \begin{block}{shell} -{\tiny -\begin{verbatim} -# echo 255 > /sys/class/leds/webinar/brightness -\end{verbatim} -} -\end{block} - \column{0.5\textwidth} - \begin{center} - \includegraphics[height=0.3\textheight]{slides/sysdev-hw-devices/cn14-pinout.png}\\ - \vspace{0.5cm} - \includegraphics[height=0.3\textheight]{slides/sysdev-hw-devices/led-on.jpg} - \end{center} - \end{columns} -\end{frame} - -\begin{frame}[fragile]{Example: connect I2C temperature, humidity and pressure sensor} - \begin{columns} - \column{0.5\textwidth} - \begin{block}{stm32mp157a-dk1-custom.dts} - {\tiny -\begin{minted}{perl} -&i2c5 { - status = "okay"; - clock-frequency = <100000>; - pinctrl-names = "default", "sleep"; - pinctrl-0 = <&i2c5_pins_a>; - pinctrl-1 = <&i2c5_pins_sleep_a>; - - pressure@76 { - compatible = "bosch,bme280"; - reg = <0x76>; - }; -}; -\end{minted} -} - \end{block} - -\begin{block}{shell} -{\tiny -\begin{verbatim} -# cat /sys/bus/iio/devices/iio\:device2/in_humidityrelative_input -49147 -# cat /sys/bus/iio/devices/iio\:device2/in_pressure_input -101.567167968 -# cat /sys/bus/iio/devices/iio\:device2/in_temp_input -24380 -\end{verbatim} -} -\end{block} - \column{0.5\textwidth} - \begin{center} - \includegraphics[width=\textwidth]{slides/sysdev-hw-devices/cn13-pinout.png}\\ - \includegraphics[width=0.4\textwidth]{slides/sysdev-hw-devices/bme.jpg} - \end{center} -\end{columns} -\vspace{0.5cm} -Details at -\url{https://bootlin.com/blog/building-a-linux-system-for-the-stm32mp1-connecting-an-i2c-sensor/} -\end{frame} - -\begin{frame}{Further details about the Device Tree} -\small -Check out our {\em Device Tree 101 webinar}, by Thomas Petazzoni (2021) -\begin{itemize} - \item Slides: \url{https://bootlin.com/blog/device-tree-101-webinar-slides-and-videos/}\\ - \item Video: \url{https://youtu.be/a9CZ1Uk3OYQ} -\end{itemize} -\vspace{0.5cm} -\includegraphics[height=0.5\textheight]{common/device-tree-video.jpg} -\end{frame} - -\subsection{Discoverable hardware: USB and PCI} - -\begin{frame}{Discoverable hardware} - \begin{itemize} - \item Some busses have built-in hardware discoverability mechanisms - \item Most common busses: USB and PCI - \item Hardware devices can be enumerated, and their characteristics - retrieved with just a driver or the bus controller - \item Useful Linux commands - \begin{itemize} - \item \code{lsusb}, lists all USB devices detected - \item \code{lspci}, lists all PCI devices detected - \item A detected device does not mean it has a kernel driver - associated to it! - \end{itemize} - \item Association with kernel drivers done based on product - ID/vendor ID, or some other characteristics of the device: device - class, device sub-class, etc. - \end{itemize} -\end{frame} - -\setuplabframe -{Accessing hardware devices} -{ - Time to start the practical lab! - \begin{itemize} - \item Exploring the contents of \code{/dev} and \code{/sys} and the - devices available on the embedded hardware platform. - \item Using GPIOs and LEDs. - \item Modifying the Device Tree to control pin multiplexing and - declare an I2C-connected joystick. - \item Adding support for a USB audio card using Linux kernel modules - \item Adding support for the I2C-connected joystick through - an out-of-tree module. - \end{itemize} -} +\ifdefstring{\labboard}{stm32mp1}{ + \input{slides/sysdev-hw-devices/stm32mp1/sysdev-hw-devices-stm32mp1.tex} +}{} +\ifdefstring{\labboard}{imx93-frdm}{ + \input{slides/sysdev-hw-devices/imx93-frdm/sysdev-hw-devices-imx93-frdm.tex} +}{\input{slides/sysdev-hw-devices/stm32mp1/sysdev-hw-devices-stm32mp1.tex}} diff --git a/slides/sysdev-shopping-list-imx93-frdm/sysdev-shopping-list-imx93-frdm.tex b/slides/sysdev-shopping-list-imx93-frdm/sysdev-shopping-list-imx93-frdm.tex new file mode 100644 index 0000000000..005eab2614 --- /dev/null +++ b/slides/sysdev-shopping-list-imx93-frdm/sysdev-shopping-list-imx93-frdm.tex @@ -0,0 +1,27 @@ +\begin{frame} +\frametitle{Shopping list: hardware for this course} + \begin{columns} + \column{0.75\textwidth} + \footnotesize + \begin{itemize} + \item NXP i.MX93 11x11 FRDM development board - + Available from Mouser (76 EUR + VAT) + \item 2 USB-C cable for the power supply and the serial console + \item RJ45 cable for networking + \item Nintendo Nunchuk with UEXT connector + \footnote{\tiny \url{https://www.olimex.com/Products/Modules/Sensors/MOD-WII/MOD-Wii-UEXT-NUNCHUCK/}} + \item Breadboard jumper wires - Male ends (to connect the Nunchuk) + \footnote{\tiny \url{https://www.olimex.com/Products/Breadboarding/JUMPER-WIRES/JW-110x10/}} + + \item A standard USB audio headset. + \item A micro SD card with at least 1 GB of capacity + \end{itemize} + \column{0.25\textwidth} + \includegraphics[height=0.25\textheight]{common/nunchuk.jpg} \\ + \includegraphics[height=0.15\textheight]{common/jumper-wires.jpg} \\ + %% Source: https://commons.wikimedia.org/wiki/Category:USB_Audio#/media/File:Andrea_Electronics_PureAudio_Speech_Development_Kit_(26603532598).png + \includegraphics[height=0.15\textheight]{common/usb-audio.png} \\ + %% Source: https://commons.wikimedia.org/wiki/File:SD_card_icon.svg + \includegraphics[height=0.15\textheight]{common/sd-card.pdf} + \end{columns} +\end{frame}