diff options
287 files changed, 7793 insertions, 3699 deletions
@@ -715,6 +715,20 @@ config SYS_CLK_FREQ A static value for the CPU frequency. Note that if not required for a given SoC, this can be left at 0. +config HAS_LDR + bool + help + Enables building .ldr targets for U-Boot and SPL. This does not + automatically build any additional targets with make or buildman. + +config LDR_CPU + string "CPU name to be passed to LDR utility." + depends on HAS_LDR + help + Set the CPU name for the -T parameter in the LDR utility. This is + generally used on processors from Analog Devices, but may be also + be useful for other vendors. + source "api/Kconfig" endmenu # General setup @@ -1360,7 +1360,7 @@ u-boot-nodtb.bin: u-boot FORCE u-boot.ldr: u-boot $(CREATE_LDR_ENV) - $(LDR) -T $(CONFIG_CPU) -c $@ $< $(LDR_FLAGS) + $(LDR) -T $(CONFIG_LDR_CPU) -c $@ $< $(LDR_FLAGS) $(BOARD_SIZE_CHECK) # binman diff --git a/arch/Kconfig b/arch/Kconfig index f9aaf372478..abd406d4884 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -254,7 +254,6 @@ config X86 imply CMD_PCI imply CMD_SF imply CMD_SF_TEST - imply CMD_ZBOOT imply DM_GPIO imply DM_KEYBOARD imply DM_MMC diff --git a/arch/arc/lib/Makefile b/arch/arc/lib/Makefile index 0eb44bcf33d..bde1c3d8af3 100644 --- a/arch/arc/lib/Makefile +++ b/arch/arc/lib/Makefile @@ -12,6 +12,6 @@ obj-y += reset.o obj-y += ints_low.o obj-y += init_helpers.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o lib-$(CONFIG_USE_PRIVATE_LIBGCC) += _millicodethunk.o libgcc2.o diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4cdf08dd695..23ee25269a2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1321,6 +1321,14 @@ config ARCH_ZYNQMP select SPL_DM_SPI_FLASH if SPL_DM_SPI select SPL_DM_MAILBOX if SPL imply SPL_FIRMWARE if SPL + imply SPL_FS_FAT if SPL + imply SPL_LIBCOMMON_SUPPORT if SPL + imply SPL_LIBDISK_SUPPORT if SPL + imply SPL_LIBGENERIC_SUPPORT if SPL + imply SPL_MMC if SPL && MMC_SDHCI_ZYNQ + imply SPL_SERIAL if SPL + imply SPL_SPI if SPL && ZYNQ_QSPI + imply SPL_SPI_FLASH_SUPPORT if SPL && ZYNQ_QSPI select SPL_SEPARATE_BSS if SPL select SUPPORT_SPL imply ZYNQMP_IPI if DM_MAILBOX diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c index 697334086fd..57d06f0575d 100644 --- a/arch/arm/cpu/armv8/cache_v8.c +++ b/arch/arm/cpu/armv8/cache_v8.c @@ -326,6 +326,8 @@ static void map_range(u64 virt, u64 phys, u64 size, int level, /* Going one level down */ if (pte_type(&table[i]) == PTE_TYPE_FAULT) set_pte_table(&table[i], create_table()); + else if (pte_type(&table[i]) != PTE_TYPE_TABLE) + split_block(&table[i], level); next_table = (u64 *)(table[i] & GENMASK_ULL(47, PAGE_SHIFT)); next_size = min(map_size - (virt & (map_size - 1)), size); diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 2634bb4c9ac..08dfbdd557b 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1353,7 +1353,6 @@ dtb-$(CONFIG_SOC_K3_AM625) += k3-am625-sk.dtb \ k3-am625-r5-sk.dtb \ k3-am625-beagleplay.dtb \ k3-am625-r5-beagleplay.dtb \ - k3-am625-verdin-wifi-dev.dtb \ k3-am625-verdin-r5.dtb \ k3-am625-phyboard-lyra-rdk.dtb \ k3-am625-r5-phycore-som-2gb.dtb diff --git a/arch/arm/dts/k3-am62-verdin-dev.dtsi b/arch/arm/dts/k3-am62-verdin-dev.dtsi deleted file mode 100644 index 6701cb8974b..00000000000 --- a/arch/arm/dts/k3-am62-verdin-dev.dtsi +++ /dev/null @@ -1,240 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright 2023 Toradex - * - * Common dtsi for Verdin AM62 SoM on Development carrier board - * - * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 - * https://www.toradex.com/products/carrier-board/verdin-development-board-kit - */ - -/ { - sound { - compatible = "simple-audio-card"; - simple-audio-card,bitclock-master = <&codec_dai>; - simple-audio-card,format = "i2s"; - simple-audio-card,frame-master = <&codec_dai>; - simple-audio-card,name = "verdin-nau8822"; - simple-audio-card,routing = - "Headphones", "LHP", - "Headphones", "RHP", - "Speaker", "LSPK", - "Speaker", "RSPK", - "Line Out", "AUXOUT1", - "Line Out", "AUXOUT2", - "LAUX", "Line In", - "RAUX", "Line In", - "LMICP", "Mic In", - "RMICP", "Mic In"; - simple-audio-card,widgets = - "Headphones", "Headphones", - "Line Out", "Line Out", - "Speaker", "Speaker", - "Microphone", "Mic In", - "Line", "Line In"; - - codec_dai: simple-audio-card,codec { - clocks = <&audio_refclk1>; - sound-dai = <&nau8822_1a>; - }; - - simple-audio-card,cpu { - sound-dai = <&mcasp0>; - }; - }; -}; - -/* Verdin ETHs */ -&cpsw3g { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_rgmii1>, <&pinctrl_rgmii2>; - status = "okay"; -}; - -/* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */ -&cpsw3g_mdio { - status = "okay"; - - cpsw3g_phy1: ethernet-phy@7 { - compatible = "ethernet-phy-ieee802.3-c22"; - reg = <7>; - interrupt-parent = <&main_gpio0>; - interrupts = <38 IRQ_TYPE_EDGE_FALLING>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_eth2_rgmii_int>; - micrel,led-mode = <0>; - }; -}; - -/* Verdin ETH_1 (On-module PHY) */ -&cpsw_port1 { - status = "okay"; -}; - -/* Verdin ETH_2_RGMII */ -&cpsw_port2 { - phy-handle = <&cpsw3g_phy1>; - phy-mode = "rgmii-rxid"; - status = "okay"; -}; - -/* Verdin PWM_1, PWM_2 */ -&epwm0 { - status = "okay"; -}; - -/* Verdin PWM_3_DSI */ -&epwm1 { - status = "okay"; -}; - -&main_gpio0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ctrl_sleep_moci>, - <&pinctrl_gpio_5>, - <&pinctrl_gpio_6>, - <&pinctrl_gpio_7>, - <&pinctrl_gpio_8>; -}; - -/* Verdin I2C_1 */ -&main_i2c1 { - status = "okay"; - - /* Audio Codec */ - nau8822_1a: audio-codec@1a { - compatible = "nuvoton,nau8822"; - reg = <0x1a>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2s1_mclk>; - #sound-dai-cells = <0>; - }; - - /* IO Expander */ - gpio_expander_21: gpio@21 { - compatible = "nxp,pcal6416"; - reg = <0x21>; - #gpio-cells = <2>; - gpio-controller; - }; - - /* Current measurement into module VCC */ - hwmon@40 { - compatible = "ti,ina219"; - reg = <0x40>; - shunt-resistor = <10000>; - }; - - /* Temperature sensor */ - sensor@4f { - compatible = "ti,tmp75c"; - reg = <0x4f>; - }; - - /* EEPROM */ - eeprom@57 { - compatible = "st,24c02", "atmel,24c02"; - reg = <0x57>; - pagesize = <16>; - }; -}; - -/* Verdin I2C_2_DSI */ -&main_i2c2 { - status = "okay"; -}; - -/* Verdin I2C_4_CSI */ -&main_i2c3 { - status = "okay"; -}; - -/* Verdin CAN_1 */ -&main_mcan0 { - status = "okay"; -}; - -/* Verdin SPI_1 */ -&main_spi1 { - status = "okay"; -}; - -/* Verdin UART_3 */ -&main_uart0 { - status = "okay"; -}; - -/* Verdin UART_1, connector X50 through RS485 transceiver. */ -&main_uart1 { - linux,rs485-enabled-at-boot-time; - rs485-rx-during-tx; - status = "okay"; -}; - -/* Verdin I2S_1 */ -&mcasp0 { - status = "okay"; -}; - -&mcu_gpio0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gpio_1>, - <&pinctrl_gpio_2>, - <&pinctrl_gpio_3>, - <&pinctrl_gpio_4>; -}; - -/* Verdin I2C_3_HDMI */ -&mcu_i2c0 { - status = "okay"; -}; - -/* Verdin CAN_2 */ -&mcu_mcan0 { - status = "okay"; -}; - -/* Verdin UART_4 */ -&mcu_uart0 { - status = "okay"; -}; - -/* Verdin QSPI_1 */ -&ospi0 { - status = "okay"; -}; - -/* Verdin SD_1 */ -&sdhci1 { - ti,driver-strength-ohm = <33>; - status = "okay"; -}; - -/* Verdin USB_1 */ -&usbss0 { - status = "okay"; -}; - -&usb0 { - status = "okay"; -}; - -/* Verdin USB_2 */ -&usbss1 { - status = "okay"; -}; - -&usb1 { - status = "okay"; -}; - -/* Verdin CTRL_WAKE1_MICO# */ -&verdin_gpio_keys { - status = "okay"; -}; - -/* Verdin UART_2 */ -&wkup_uart0 { - /* FIXME: WKUP UART0 is used by DM firmware */ - status = "reserved"; -}; diff --git a/arch/arm/dts/k3-am62-verdin-wifi.dtsi b/arch/arm/dts/k3-am62-verdin-wifi.dtsi deleted file mode 100644 index a6808b10c7b..00000000000 --- a/arch/arm/dts/k3-am62-verdin-wifi.dtsi +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright 2023 Toradex - * - * Common dtsi for Verdin AM62 SoM WB variant - * - * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 - */ - -/ { - wifi_pwrseq: wifi-pwrseq { - compatible = "mmc-pwrseq-simple"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_wifi_en>; - reset-gpios = <&main_gpio0 22 GPIO_ACTIVE_LOW>; - }; -}; - -/* On-module Wi-Fi */ -&sdhci2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sdhci2>; - bus-width = <4>; - cap-power-off-card; - keep-power-in-suspend; - mmc-pwrseq = <&wifi_pwrseq>; - non-removable; - ti,fails-without-test-cd; - ti,driver-strength-ohm = <50>; - vmmc-supply = <®_3v3>; - status = "okay"; -}; - -/* On-module Bluetooth */ -&main_uart5 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart5>; - uart-has-rtscts; - status = "okay"; - - bluetooth { - compatible = "nxp,88w8987-bt"; - fw-init-baudrate = <3000000>; - }; -}; diff --git a/arch/arm/dts/k3-am62-verdin.dtsi b/arch/arm/dts/k3-am62-verdin.dtsi deleted file mode 100644 index 5db52f23725..00000000000 --- a/arch/arm/dts/k3-am62-verdin.dtsi +++ /dev/null @@ -1,1443 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright 2023 Toradex - * - * Common dtsi for Verdin AM62 SoM - * - * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 - */ - -#include <dt-bindings/gpio/gpio.h> -#include <dt-bindings/input/input.h> -#include <dt-bindings/interrupt-controller/arm-gic.h> -#include <dt-bindings/interrupt-controller/irq.h> -#include <dt-bindings/net/ti-dp83867.h> - -/ { - chosen { - stdout-path = "serial2:115200n8"; - }; - - aliases { - can0 = &main_mcan0; - can1 = &mcu_mcan0; - ethernet0 = &cpsw_port1; - ethernet1 = &cpsw_port2; - i2c0 = &main_i2c0; - i2c1 = &main_i2c1; - i2c2 = &main_i2c2; - i2c3 = &mcu_i2c0; - i2c4 = &main_i2c3; - mmc0 = &sdhci0; - mmc1 = &sdhci1; - mmc2 = &sdhci2; - rtc0 = &rtc_i2c; - rtc1 = &wkup_rtc0; - serial0 = &main_uart1; - serial1 = &wkup_uart0; - serial2 = &main_uart0; - serial3 = &mcu_uart0; - serial4 = &main_uart5; - usb0 = &usb0; - usb1 = &usb1; - }; - - verdin_gpio_keys: gpio-keys { - compatible = "gpio-keys"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ctrl_wake1_mico>; - status = "disabled"; - - verdin_key_wakeup: key-wakeup { - debounce-interval = <10>; - /* Verdin CTRL_WAKE1_MICO# (SODIMM 252) */ - gpios = <&main_gpio0 32 GPIO_ACTIVE_LOW>; - label = "Wake-Up"; - linux,code = <KEY_WAKEUP>; - wakeup-source; - }; - }; - - memory@80000000 { - device_type = "memory"; - reg = <0x00000000 0x80000000 0x00000000 0x40000000>; /* 1G RAM */ - }; - - opp-table { - /* Add 1.4GHz OPP. Requires VDD_CORE to be at 0.85V */ - opp-1400000000 { - opp-hz = /bits/ 64 <1400000000>; - opp-supported-hw = <0x01 0x0004>; - clock-latency-ns = <6000000>; - }; - }; - - /* Module Power Supply */ - reg_vsodimm: regulator-vsodimm { - compatible = "regulator-fixed"; - regulator-name = "+V_SODIMM"; - }; - - /* Non PMIC On-module Supplies */ - reg_3v3: regulator-3v3 { - compatible = "regulator-fixed"; - regulator-max-microvolt = <3300000>; - regulator-min-microvolt = <3300000>; - regulator-name = "On-module +V3.3"; - vin-supply = <®_vsodimm>; - }; - - reg_1v2_dsi: regulator-1v2-dsi { - compatible = "regulator-fixed"; - regulator-max-microvolt = <1200000>; - regulator-min-microvolt = <1200000>; - regulator-name = "On-module +V1.2_DSI"; - vin-supply = <®_1v8>; - }; - - /* Enabled by +V1.2_DSI */ - reg_1v8_dsi: regulator-1v8-dsi { - compatible = "regulator-fixed"; - regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <1800000>; - regulator-name = "On-module +V1.8_DSI"; - vin-supply = <®_1v8>; - }; - - /* Enabled by +V2.5_ETH */ - reg_1v0_eth: regulator-1v0-eth { - compatible = "regulator-fixed"; - regulator-max-microvolt = <1000000>; - regulator-min-microvolt = <1000000>; - regulator-name = "On-module +V1.0_ETH"; - vin-supply = <®_1v8>; - }; - - /* Enabled by +V2.5_ETH */ - reg_1v8_eth: regulator-1v8-eth { - compatible = "regulator-fixed"; - regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <1800000>; - regulator-name = "On-module +V1.8_ETH"; - vin-supply = <®_1v8>; - }; - - /* Verdin SD_1 Power Supply */ - reg_sdhc1_vmmc: regulator-sdhci1 { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sd1_pwr_en>; - enable-active-high; - /* Verdin SD_1_PWR_EN (SODIMM 76) */ - gpio = <&main_gpio0 29 GPIO_ACTIVE_HIGH>; - off-on-delay-us = <100000>; - regulator-max-microvolt = <3300000>; - regulator-min-microvolt = <3300000>; - regulator-name = "+V3.3_SD"; - startup-delay-us = <2000>; - }; - - reg_sdhc1_vqmmc: regulator-sdhci1-vqmmc { - compatible = "regulator-gpio"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_vsel_sd>; - /* PMIC_VSEL_SD */ - gpios = <&main_gpio0 21 GPIO_ACTIVE_HIGH>; - regulator-name = "LDO1-VSEL-SD (PMIC)"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <3300000>; - states = <1800000 0x0>, - <3300000 0x1>; - vin-supply = <®_sd_3v3_1v8>; - }; - - reserved-memory { - #address-cells = <2>; - #size-cells = <2>; - ranges; - - secure_tfa_ddr: tfa@9e780000 { - reg = <0x00 0x9e780000 0x00 0x80000>; - alignment = <0x1000>; - no-map; - }; - - secure_ddr: optee@9e800000 { - reg = <0x00 0x9e800000 0x00 0x01800000>; /* for OP-TEE */ - alignment = <0x1000>; - no-map; - }; - - wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9db00000 { - compatible = "shared-dma-pool"; - reg = <0x00 0x9db00000 0x00 0xc00000>; - no-map; - }; - }; -}; - -&main_pmx0 { - /* Verdin PWM_1 */ - pinctrl_epwm0_a: main-epwm0a-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01b4, PIN_OUTPUT, 2) /* (A13) SPI0_CS0.EHRPWM0_A */ /* SODIMM 15 */ - >; - }; - - /* Verdin PWM_2 */ - pinctrl_epwm0_b: main-epwm0b-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01b8, PIN_OUTPUT, 2) /* (C13) SPI0_CS1.EHRPWM0_B */ /* SODIMM 16 */ - >; - }; - - /* Verdin PWM_3_DSI */ - pinctrl_epwm1_a: main-epwm1a-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01bc, PIN_OUTPUT, 2) /* (A14) SPI0_CLK.EHRPWM1_A */ /* SODIMM 19 */ - >; - }; - - /* Verdin QSPI_1_CLK as GPIO (conflict with Verdin QSPI_1 interface) */ - pinctrl_qspi1_clk_gpio: main-gpio0-0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0000, PIN_INPUT, 7) /* (H24) OSPI0_CLK.GPIO0_0 */ /* SODIMM 52 */ - >; - }; - - /* Verdin QSPI_1_IO0 as GPIO (conflict with Verdin QSPI_1 interface) */ - pinctrl_qspi1_io0_gpio: main-gpio0-3-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x000c, PIN_INPUT, 7) /* (E25) OSPI0_D0.GPIO0_3 */ /* SODIMM 56 */ - >; - }; - - /* Verdin QSPI_1_IO1 as GPIO (conflict with Verdin QSPI_1 interface) */ - pinctrl_qspi1_io1_gpio: main-gpio0-4-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0010, PIN_INPUT, 7) /* (G24) OSPI0_D1.GPIO0_4 */ /* SODIMM 58 */ - >; - }; - - /* Verdin QSPI_1_IO2 as GPIO (conflict with Verdin QSPI_1 interface) */ - pinctrl_qspi1_io2_gpio: main-gpio0-5-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0014, PIN_INPUT, 7) /* (F25) OSPI0_D2.GPIO0_5 */ /* SODIMM 60 */ - >; - }; - - /* Verdin QSPI_1_IO3 as GPIO (conflict with Verdin QSPI_1 interface) */ - pinctrl_qspi1_io3_gpio: main-gpio0-6-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0018, PIN_INPUT, 7) /* (F24) OSPI0_D3.GPIO0_6 */ /* SODIMM 62 */ - >; - }; - - /* Verdin QSPI_1_CS# as GPIO (conflict with Verdin QSPI_1 interface) */ - pinctrl_qspi1_cs_gpio: main-gpio0-11-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x002c, PIN_INPUT, 7) /* (F23) OSPI0_CSn0.GPIO0_11 */ /* SODIMM 54 */ - >; - }; - - /* Verdin QSPI_1_CS2# as GPIO (conflict with Verdin QSPI_1 interface) */ - pinctrl_qspi1_cs2_gpio: main-gpio0-12-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0030, PIN_INPUT, 7) /* (G21) OSPI0_CSn1.GPIO0_12 */ /* SODIMM 64 */ - >; - }; - - /* WiFi_W_WKUP_HOST# */ - pinctrl_wifi_w_wkup_host: main-gpio0-15-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x003c, PIN_INPUT, 7) /* (M25) GPMC0_AD0.GPIO0_15 */ /* SODIMM 174 */ - >; - }; - - /* WiFi_BT_WKUP_HOST# */ - pinctrl_bt_wkup_host: main-gpio0-16-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0040, PIN_INPUT, 7) /* (N23) GPMC0_AD1.GPIO0_16 */ /* SODIMM 172 */ - >; - }; - - /* PMIC_ETH_RESET# */ - pinctrl_eth_reset: main-gpio0-17-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0044, PIN_INPUT, 7) /* (N24) GPMC0_AD2.GPIO0_17 */ - >; - }; - - /* PMIC_BRIDGE_RESET# */ - pinctrl_bridge_reset: main-gpio0-20-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0050, PIN_INPUT, 7) /* (P22) GPMC0_AD5.GPIO0_20 */ - >; - }; - - /* PMIC_VSEL_SD */ - pinctrl_vsel_sd: main-gpio0-21-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0054, PIN_INPUT, 7) /* (P21) GPMC0_AD6.GPIO0_21 */ - >; - }; - - /* PMIC_EN_WIFI */ - pinctrl_wifi_en: main-gpio0-22-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0058, PIN_INPUT, 7) /* (R23) GPMC0_AD7.GPIO0_22 */ - >; - }; - - /* PMIC_ETH_INT# */ - pinctrl_eth_int: main-gpio0-25-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0064, PIN_INPUT_PULLUP, 7) /* (T25) GPMC0_AD10.GPIO0_25 */ - >; - }; - - /* WiFi_WKUP_BT# */ - pinctrl_wifi_wkup_bt: main-gpio0-26-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0068, PIN_INPUT, 7) /* (R21) GPMC0_AD11.GPIO0_26 */ - >; - }; - - /* WiFi_WKUP_WLAN# */ - pinctrl_wifi_wkup_wlan: main-gpio0-27-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x006c, PIN_INPUT, 7) /* (T22) GPMC0_AD12.GPIO0_27 */ - >; - }; - - /* Verdin SD_1_PWR_EN */ - pinctrl_sd1_pwr_en: main-gpio0-29-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0074, PIN_INPUT, 7) /* (U25) GPMC0_AD14.GPIO0_29 */ /* SODIMM 76 */ - >; - }; - - /* Verdin DSI_1_BKL_EN */ - pinctrl_dsi1_bkl_en: main-gpio0-30-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0078, PIN_INPUT, 7) /* (U24) GPMC0_AD15.GPIO0_30 */ /* SODIMM 21 */ - >; - }; - - /* Verdin CTRL_SLEEP_MOCI# */ - pinctrl_ctrl_sleep_moci: main-gpio0-31-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x007c, PIN_INPUT, 7) /* (P25) GPMC0_CLK.GPIO0_31 */ /* SODIMM 256 */ - >; - }; - - /* Verdin CTRL_WAKE1_MICO# */ - pinctrl_ctrl_wake1_mico: main-gpio0-32-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0084, PIN_INPUT_PULLUP, 7) /* (L23) GPMC0_ADVn_ALE.GPIO0_32 */ /* SODIMM 252 */ - >; - }; - - /* Verdin I2S_2_D_OUT as GPIO (conflict with Verdin I2S_2 interface) */ - pinctrl_i2s_2_d_out_gpio: main-gpio0-34-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x008c, PIN_INPUT, 7) /* (L25) GPMC0_WEn.GPIO0_34 */ /* SODIMM 46 */ - >; - }; - - /* Verdin I2S_2_BCLK as GPIO (conflict with Verdin I2S_2 interface) */ - pinctrl_i2s_2_bclk_gpio: main-gpio0-35-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0090, PIN_INPUT, 7) /* (M24) GPMC0_BE0n_CLE.GPIO0_35 */ /* SODIMM 42 */ - >; - }; - - /* Verdin GPIO_6 */ - pinctrl_gpio_6: main-gpio0-36-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0094, PIN_INPUT, 7) /* (N20) GPMC0_BE1n.GPIO0_36 */ /* SODIMM 218 */ - >; - }; - - /* Verdin ETH_2_RGMII_INT# */ - pinctrl_eth2_rgmii_int: main-gpio0-38-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x009c, PIN_INPUT, 7) /* (V25) GPMC0_WAIT1.GPIO0_38 */ /* SODIMM 189 */ - >; - }; - - /* Verdin GPIO_5 */ - pinctrl_gpio_5: main-gpio0-40-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x00a4, PIN_INPUT, 7) /* (M22) GPMC0_DIR.GPIO0_40 */ /* SODIMM 216 */ - >; - }; - - /* Verdin GPIO_7 */ - pinctrl_gpio_7: main-gpio0-41-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x00a8, PIN_INPUT, 7) /* (M21) GPMC0_CSn0.GPIO0_41 */ /* SODIMM 220 */ - >; - }; - - /* Verdin GPIO_8 */ - pinctrl_gpio_8: main-gpio0-42-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x00ac, PIN_INPUT, 7) /* (L21) GPMC0_CSn1.GPIO0_42 */ /* SODIMM 222 */ - >; - }; - - /* Verdin USB_1_OC# */ - pinctrl_usb1_oc: main-gpio0-71-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0124, PIN_INPUT, 7) /* (A23) MMC2_SDCD.GPIO0_71 */ /* SODIMM 157 */ - >; - }; - - /* Verdin USB_2_OC# */ - pinctrl_usb2_oc: main-gpio0-72-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0128, PIN_INPUT, 7) /* (B23) MMC2_SDWP.GPIO0_72 */ /* SODIMM 187 */ - >; - }; - - /* Verdin PWM_3_DSI as GPIO */ - pinctrl_pwm3_dsi_gpio: main-gpio1-17-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01bc, PIN_INPUT, 7) /* (A14) SPI0_CLK.GPIO1_17 */ /* SODIMM 19 */ - >; - }; - - /* Verdin QSPI_1_DQS as GPIO */ - pinctrl_qspi1_dqs_gpio: main-gpio1-18-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01c0, PIN_INPUT, 7) /* (B13) SPI0_D0.GPIO1_18 */ /* SODIMM 66 */ - >; - }; - - /* Verdin USB_1_ID */ - pinctrl_usb0_id: main-gpio1-19-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01c4, PIN_INPUT, 7) /* (B14) SPI0_D1.GPIO1_19 */ /* SODIMM 161 */ - >; - }; - - /* Verdin DSI_1_INT# (pulled-up as active-low) */ - pinctrl_dsi1_int: main-gpio1-49-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0244, PIN_INPUT_PULLUP, 7) /* (C17) MMC1_SDWP.GPIO1_49 */ /* SODIMM 17 */ - >; - }; - - /* On-module I2C - PMIC_I2C */ - pinctrl_i2c0: main-i2c0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01e0, PIN_INPUT, 0) /* (B16) I2C0_SCL */ /* PMIC_I2C_SCL */ - AM62X_IOPAD(0x01e4, PIN_INPUT, 0) /* (A16) I2C0_SDA */ /* PMIC_I2C_SDA */ - >; - }; - - /* Verdin I2C_1 */ - pinctrl_i2c1: main-i2c1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */ /* SODIMM 14 */ - AM62X_IOPAD(0x01ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */ /* SODIMM 12 */ - >; - }; - - /* Verdin I2C_2_DSI */ - pinctrl_i2c2: main-i2c2-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x00b0, PIN_INPUT, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */ /* SODIMM 55 */ - AM62X_IOPAD(0x00b4, PIN_INPUT, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */ /* SODIMM 53 */ - >; - }; - - /* Verdin I2C_4_CSI */ - pinctrl_i2c3: main-i2c3-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01d0, PIN_INPUT, 2) /* (A15) UART0_CTSn.I2C3_SCL */ /* SODIMM 95 */ - AM62X_IOPAD(0x01d4, PIN_INPUT, 2) /* (B15) UART0_RTSn.I2C3_SDA */ /* SODIMM 93 */ - >; - }; - - /* I2S_1_MCLK */ - pinctrl_i2s1_mclk: main-system-audio-ext-reflock1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x00a0, PIN_OUTPUT, 1) /* (K25) GPMC0_WPn.AUDIO_EXT_REFCLK1 */ /* SODIMM 38 */ - >; - }; - - /* Verdin I2S_1 */ - pinctrl_mcasp0: main-mcasp0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01a4, PIN_INPUT, 0) /* (B20) MCASP0_ACLKX */ /* SODIMM 30 */ - AM62X_IOPAD(0x01a8, PIN_INPUT, 0) /* (D20) MCASP0_AFSX */ /* SODIMM 32 */ - AM62X_IOPAD(0x01a0, PIN_OUTPUT, 0) /* (E18) MCASP0_AXR0 */ /* SODIMM 34 */ - AM62X_IOPAD(0x019c, PIN_INPUT, 0) /* (B18) MCASP0_AXR1 */ /* SODIMM 36 */ - >; - }; - - /* Verdin I2S_2 */ - pinctrl_mcasp1: main-mcasp1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0090, PIN_INPUT, 2) /* (M24) GPMC0_BE0n_CLE.MCASP1_ACLKX */ /* SODIMM 42 */ - AM62X_IOPAD(0x0098, PIN_INPUT, 2) /* (U23) GPMC0_WAIT0.MCASP1_AFSX */ /* SODIMM 44 */ - AM62X_IOPAD(0x008c, PIN_OUTPUT, 2) /* (L25) GPMC0_WEn.MCASP1_AXR0 */ /* SODIMM 46 */ - AM62X_IOPAD(0x0088, PIN_INPUT, 2) /* (L24) GPMC0_OEn_REn.MCASP1_AXR1 */ /* SODIMM 48 */ - >; - }; - - /* Verdin CAN_1 */ - pinctrl_mcan0: main-mcan0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01dc, PIN_INPUT, 0) /* (E15) MCAN0_RX */ /* SODIMM 22 */ - AM62X_IOPAD(0x01d8, PIN_OUTPUT, 0) /* (C15) MCAN0_TX */ /* SODIMM 20 */ - >; - }; - - /* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */ - pinctrl_mdio: main-mdio1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x160, PIN_OUTPUT, 0) /* (AD24) MDIO0_MDC */ /* ETH_1_MDC, SODIMM 193 */ - AM62X_IOPAD(0x15c, PIN_INPUT, 0) /* (AB22) MDIO0_MDIO */ /* ETH_1_MDIO, SODIMM 191 */ - >; - }; - - /* On-module eMMC */ - pinctrl_sdhci0: main-mmc0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */ - AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */ - AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (AA2) MMC0_DAT0 */ - AM62X_IOPAD(0x210, PIN_INPUT, 0) /* (AA1) MMC0_DAT1 */ - AM62X_IOPAD(0x20c, PIN_INPUT, 0) /* (AA3) MMC0_DAT2 */ - AM62X_IOPAD(0x208, PIN_INPUT, 0) /* (Y4) MMC0_DAT3 */ - AM62X_IOPAD(0x204, PIN_INPUT, 0) /* (AB2) MMC0_DAT4 */ - AM62X_IOPAD(0x200, PIN_INPUT, 0) /* (AC1) MMC0_DAT5 */ - AM62X_IOPAD(0x1fc, PIN_INPUT, 0) /* (AD2) MMC0_DAT6 */ - AM62X_IOPAD(0x1f8, PIN_INPUT, 0) /* (AC2) MMC0_DAT7 */ - >; - }; - - /* Verdin SD_1 */ - pinctrl_sdhci1: main-mmc1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x23c, PIN_INPUT, 0) /* (A21) MMC1_CMD */ /* SODIMM 74 */ - AM62X_IOPAD(0x234, PIN_INPUT, 0) /* (B22) MMC1_CLK */ /* SODIMM 78 */ - AM62X_IOPAD(0x230, PIN_INPUT, 0) /* (A22) MMC1_DAT0 */ /* SODIMM 80 */ - AM62X_IOPAD(0x22c, PIN_INPUT, 0) /* (B21) MMC1_DAT1 */ /* SODIMM 82 */ - AM62X_IOPAD(0x228, PIN_INPUT, 0) /* (C21) MMC1_DAT2 */ /* SODIMM 70 */ - AM62X_IOPAD(0x224, PIN_INPUT, 0) /* (D22) MMC1_DAT3 */ /* SODIMM 72 */ - AM62X_IOPAD(0x240, PIN_INPUT_PULLUP, 0) /* (D17) MMC1_SDCD */ /* SODIMM 84 */ - >; - }; - - /* On-module Wi-Fi on WB SKUs, module-specific SDIO otherwise */ - pinctrl_sdhci2: main-mmc2-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x120, PIN_INPUT, 0) /* (C24) MMC2_CMD */ /* WiFi_SDIO_CMD */ - AM62X_IOPAD(0x118, PIN_INPUT, 0) /* (D25) MMC2_CLK */ /* WiFi_SDIO_CLK */ - AM62X_IOPAD(0x114, PIN_INPUT, 0) /* (B24) MMC2_DAT0 */ /* WiFi_SDIO_DATA0 */ - AM62X_IOPAD(0x110, PIN_INPUT, 0) /* (C25) MMC2_DAT1 */ /* WiFi_SDIO_DATA1 */ - AM62X_IOPAD(0x10c, PIN_INPUT, 0) /* (E23) MMC2_DAT2 */ /* WiFi_SDIO_DATA2 */ - AM62X_IOPAD(0x108, PIN_INPUT, 0) /* (D24) MMC2_DAT3 */ /* WiFi_SDIO_DATA3 */ - AM62X_IOPAD(0x11c, PIN_INPUT, 0) /* (#N/A) MMC2_CLKB */ - >; - }; - - /* Verdin QSPI_1 */ - pinctrl_ospi0: main-ospi0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0000, PIN_OUTPUT, 0) /* (H24) OSPI0_CLK */ /* SODIMM 52 */ - AM62X_IOPAD(0x002c, PIN_OUTPUT, 0) /* (F23) OSPI0_CSn0 */ /* SODIMM 54 */ - AM62X_IOPAD(0x0030, PIN_OUTPUT, 0) /* (G21) OSPI0_CSn1 */ /* SODIMM 64 */ - AM62X_IOPAD(0x000c, PIN_INPUT, 0) /* (E25) OSPI0_D0 */ /* SODIMM 56 */ - AM62X_IOPAD(0x0010, PIN_INPUT, 0) /* (G24) OSPI0_D1 */ /* SODIMM 58 */ - AM62X_IOPAD(0x0014, PIN_INPUT, 0) /* (F25) OSPI0_D2 */ /* SODIMM 60 */ - AM62X_IOPAD(0x0018, PIN_INPUT, 0) /* (F24) OSPI0_D3 */ /* SODIMM 62 */ - >; - }; - - /* Verdin ETH_1 RGMII (On-module PHY) */ - pinctrl_rgmii1: main-rgmii1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x14c, PIN_INPUT, 0) /* (AB17) RGMII1_RD0 */ - AM62X_IOPAD(0x150, PIN_INPUT, 0) /* (AC17) RGMII1_RD1 */ - AM62X_IOPAD(0x154, PIN_INPUT, 0) /* (AB16) RGMII1_RD2 */ - AM62X_IOPAD(0x158, PIN_INPUT, 0) /* (AA15) RGMII1_RD3 */ - AM62X_IOPAD(0x148, PIN_INPUT, 0) /* (AD17) RGMII1_RXC */ - AM62X_IOPAD(0x144, PIN_INPUT, 0) /* (AE17) RGMII1_RX_CTL */ - AM62X_IOPAD(0x134, PIN_OUTPUT, 0) /* (AE20) RGMII1_TD0 */ - AM62X_IOPAD(0x138, PIN_OUTPUT, 0) /* (AD20) RGMII1_TD1 */ - AM62X_IOPAD(0x13c, PIN_OUTPUT, 0) /* (AE18) RGMII1_TD2 */ - AM62X_IOPAD(0x140, PIN_OUTPUT, 0) /* (AD18) RGMII1_TD3 */ - AM62X_IOPAD(0x130, PIN_OUTPUT, 0) /* (AE19) RGMII1_TXC */ - AM62X_IOPAD(0x12c, PIN_OUTPUT, 0) /* (AD19) RGMII1_TX_CTL */ - >; - }; - - /* Verdin ETH_2 RGMII */ - pinctrl_rgmii2: main-rgmii2-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */ /* SODIMM 201 */ - AM62X_IOPAD(0x188, PIN_INPUT, 0) /* (AB20) RGMII2_RD1 */ /* SODIMM 203 */ - AM62X_IOPAD(0x18c, PIN_INPUT, 0) /* (AC21) RGMII2_RD2 */ /* SODIMM 205 */ - AM62X_IOPAD(0x190, PIN_INPUT, 0) /* (AE22) RGMII2_RD3 */ /* SODIMM 207 */ - AM62X_IOPAD(0x180, PIN_INPUT, 0) /* (AD23) RGMII2_RXC */ /* SODIMM 197 */ - AM62X_IOPAD(0x17c, PIN_INPUT, 0) /* (AD22) RGMII2_RX_CTL */ /* SODIMM 199 */ - AM62X_IOPAD(0x16c, PIN_OUTPUT, 0) /* (Y18) RGMII2_TD0 */ /* SODIMM 221 */ - AM62X_IOPAD(0x170, PIN_OUTPUT, 0) /* (AA18) RGMII2_TD1 */ /* SODIMM 219 */ - AM62X_IOPAD(0x174, PIN_OUTPUT, 0) /* (AD21) RGMII2_TD2 */ /* SODIMM 217 */ - AM62X_IOPAD(0x178, PIN_OUTPUT, 0) /* (AC20) RGMII2_TD3 */ /* SODIMM 215 */ - AM62X_IOPAD(0x168, PIN_OUTPUT, 0) /* (AE21) RGMII2_TXC */ /* SODIMM 213 */ - AM62X_IOPAD(0x164, PIN_OUTPUT, 0) /* (AA19) RGMII2_TX_CTL */ /* SODIMM 211 */ - >; - }; - - /* Verdin SPI_1 */ - pinctrl_spi1: main-spi1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0020, PIN_INPUT, 1) /* (J25) OSPI0_D5.SPI1_CLK */ /* SODIMM 196 */ - AM62X_IOPAD(0x001c, PIN_INPUT, 1) /* (J23) OSPI0_D4.SPI1_CS0 */ /* SODIMM 202 */ - AM62X_IOPAD(0x0024, PIN_INPUT, 1) /* (H25) OSPI0_D6.SPI1_D0 */ /* SODIMM 200 */ - AM62X_IOPAD(0x0028, PIN_INPUT, 1) /* (J22) OSPI0_D7.SPI1_D1 */ /* SODIMM 198 */ - >; - }; - - /* ETH_25MHz_CLK */ - pinctrl_eth_clock: main-system-clkout0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01f0, PIN_OUTPUT_PULLUP, 5) /* (A18) EXT_REFCLK1.CLKOUT0 */ - >; - }; - - /* PMIC_EXTINT# */ - pinctrl_pmic_extint: main-system-extint-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x01f4, PIN_INPUT, 0) /* (D16) EXTINTn */ - >; - }; - - /* Verdin UART_3, used as the Linux console */ - pinctrl_uart0: main-uart0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x1c8, PIN_INPUT_PULLUP, 0) /* (D14) UART0_RXD */ /* SODIMM 147 */ - AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */ /* SODIMM 149 */ - >; - }; - - /* Verdin UART_1 */ - pinctrl_uart1: main-uart1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0194, PIN_INPUT_PULLUP, 2) /* (B19) MCASP0_AXR3.UART1_CTSn */ /* SODIMM 135 */ - AM62X_IOPAD(0x0198, PIN_OUTPUT, 2) /* (A19) MCASP0_AXR2.UART1_RTSn */ /* SODIMM 133 */ - AM62X_IOPAD(0x01ac, PIN_INPUT_PULLUP, 2) /* (E19) MCASP0_AFSR.UART1_RXD */ /* SODIMM 129 */ - AM62X_IOPAD(0x01b0, PIN_OUTPUT, 2) /* (A20) MCASP0_ACLKR.UART1_TXD */ /* SODIMM 131 */ - >; - }; - - /* Bluetooth on WB SKUs, module-specific UART otherwise */ - pinctrl_uart5: main-uart5-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0008, PIN_INPUT_PULLUP, 5) /* (J24) OSPI0_DQS.UART5_CTSn */ /* WiFi_UART_CTS */ - AM62X_IOPAD(0x0004, PIN_OUTPUT, 5) /* (G25) OSPI0_LBCLKO.UART5_RTSn */ /* WiFi_UART_RTS */ - AM62X_IOPAD(0x0034, PIN_INPUT_PULLUP, 5) /* (H21) OSPI0_CSn2.UART5_RXD */ /* WiFi_UART_RXD */ - AM62X_IOPAD(0x0038, PIN_OUTPUT, 5) /* (E24) OSPI0_CSn3.UART5_TXD */ /* WiFi_UART_TXD */ - >; - }; - - /* Verdin USB_1 */ - pinctrl_usb0: main-usb0-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0254, PIN_OUTPUT, 0) /* (C20) USB0_DRVVBUS */ /* SODIMM 155 */ - >; - }; - - /* Verdin USB_2 */ - pinctrl_usb1: main-usb1-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0258, PIN_OUTPUT, 0) /* (F18) USB1_DRVVBUS */ /* SODIMM 185 */ - >; - }; - - /* DSS VOUT0 RGB */ - pinctrl_parallel_rgb: main-vout-default-pins { - pinctrl-single,pins = < - AM62X_IOPAD(0x0100, PIN_OUTPUT, 0) /* (AC25) VOUT0_VSYNC */ - AM62X_IOPAD(0x00f8, PIN_OUTPUT, 0) /* (AB24) VOUT0_HSYNC */ - AM62X_IOPAD(0x0104, PIN_OUTPUT, 0) /* (AC24) VOUT0_PCLK */ - AM62X_IOPAD(0x00fc, PIN_OUTPUT, 0) /* (Y20) VOUT0_DE */ - AM62X_IOPAD(0x00b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */ - AM62X_IOPAD(0x00bc, PIN_OUTPUT, 0) /* (V24) VOUT0_DATA1 */ - AM62X_IOPAD(0x00c0, PIN_OUTPUT, 0) /* (W25) VOUT0_DATA2 */ - AM62X_IOPAD(0x00c4, PIN_OUTPUT, 0) /* (W24) VOUT0_DATA3 */ - AM62X_IOPAD(0x00c8, PIN_OUTPUT, 0) /* (Y25) VOUT0_DATA4 */ - AM62X_IOPAD(0x00cc, PIN_OUTPUT, 0) /* (Y24) VOUT0_DATA5 */ - AM62X_IOPAD(0x00d0, PIN_OUTPUT, 0) /* (Y23) VOUT0_DATA6 */ - AM62X_IOPAD(0x00d4, PIN_OUTPUT, 0) /* (AA25) VOUT0_DATA7 */ - AM62X_IOPAD(0x00d8, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA8 */ - AM62X_IOPAD(0x00dc, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA9 */ - AM62X_IOPAD(0x00e0, PIN_OUTPUT, 0) /* (V20) VOUT0_DATA10 */ - AM62X_IOPAD(0x00e4, PIN_OUTPUT, 0) /* (AA23) VOUT0_DATA11 */ - AM62X_IOPAD(0x00e8, PIN_OUTPUT, 0) /* (AB25) VOUT0_DATA12 */ - AM62X_IOPAD(0x00ec, PIN_OUTPUT, 0) /* (AA24) VOUT0_DATA13 */ - AM62X_IOPAD(0x00f0, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA14 */ - AM62X_IOPAD(0x00f4, PIN_OUTPUT, 0) /* (AA21) VOUT0_DATA15 */ - AM62X_IOPAD(0x005c, PIN_OUTPUT, 1) /* (R24) GPMC0_AD8.VOUT0_DATA16 */ - AM62X_IOPAD(0x0060, PIN_OUTPUT, 1) /* (R25) GPMC0_AD9.VOUT0_DATA17 */ - >; - }; -}; - -&mcu_pmx0 { - /* Verdin PCIE_1_RESET# */ - pinctrl_pcie_1_reset: mcu-gpio0-0-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0000, PIN_INPUT, 7) /* (E8) MCU_SPI0_CS0.MCU_GPIO0_0 */ /* SODIMM 244 */ - >; - }; - - /* Verdin GPIO_1 */ - pinctrl_gpio_1: mcu-gpio0-1-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0004, PIN_INPUT, 7) /* (B8) MCU_SPI0_CS1.MCU_GPIO0_1 */ /* SODIMM 206 */ - >; - }; - - /* Verdin GPIO_2 */ - pinctrl_gpio_2: mcu-gpio0-2-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0008, PIN_INPUT, 7) /* (A7) MCU_SPI0_CLK.MCU_GPIO0_2 */ /* SODIMM 208 */ - >; - }; - - /* Verdin GPIO_3 */ - pinctrl_gpio_3: mcu-gpio0-3-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x000c, PIN_INPUT, 7) /* (D9) MCU_SPI0_D0.MCU_GPIO0_3 */ /* SODIMM 210 */ - >; - }; - - /* Verdin GPIO_4 */ - pinctrl_gpio_4: mcu-gpio0-4-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0010, PIN_INPUT, 7) /* (C9) MCU_SPI0_D1.MCU_GPIO0_4 */ /* SODIMM 212 */ - >; - }; - - /* Verdin I2C_3_HDMI */ - pinctrl_mcu_i2c0: mcu-i2c0-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0044, PIN_INPUT, 0) /* (A8) MCU_I2C0_SCL */ /* SODIMM 59 */ - AM62X_MCU_IOPAD(0x0048, PIN_INPUT, 0) /* (D10) MCU_I2C0_SDA */ /* SODIMM 57 */ - >; - }; - - /* Verdin CAN_2 */ - pinctrl_mcu_mcan0: mcu-mcan0-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0038, PIN_INPUT, 0) /* (B3) MCU_MCAN0_RX */ /* SODIMM 26 */ - AM62X_MCU_IOPAD(0x0034, PIN_OUTPUT, 0) /* (D6) MCU_MCAN0_TX */ /* SODIMM 24 */ - >; - }; - - /* Verdin UART_4 - Reserved to Cortex-M4 */ - pinctrl_mcu_uart0: mcu-uart0-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0014, PIN_INPUT_PULLUP, 0) /* (B5) MCU_UART0_RXD */ /* SODIMM 151 */ - AM62X_MCU_IOPAD(0x0018, PIN_OUTPUT, 0) /* (A5) MCU_UART0_TXD */ /* SODIMM 153 */ - >; - }; - - /* Verdin CSI_1_MCLK */ - pinctrl_csi1_mclk: wkup-clkout0-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x0084, PIN_OUTPUT, 0) /* (A12) WKUP_CLKOUT0 */ /* SODIMM 91 */ - >; - }; - - /* Verdin UART_2 */ - pinctrl_wkup_uart0: wkup-uart0-default-pins { - pinctrl-single,pins = < - AM62X_MCU_IOPAD(0x002c, PIN_INPUT_PULLUP, 0) /* (C6) WKUP_UART0_CTSn */ /* SODIMM 143 */ - AM62X_MCU_IOPAD(0x0030, PIN_OUTPUT, 0) /* (A4) WKUP_UART0_RTSn */ /* SODIMM 141 */ - AM62X_MCU_IOPAD(0x0024, PIN_INPUT_PULLUP, 0) /* (B4) WKUP_UART0_RXD */ /* SODIMM 137 */ - AM62X_MCU_IOPAD(0x0028, PIN_OUTPUT, 0) /* (C5) WKUP_UART0_TXD */ /* SODIMM 139 */ - >; - }; -}; - -/* VERDIN I2S_1_MCLK */ -&audio_refclk1 { - assigned-clock-rates = <25000000>; -}; - -&cpsw3g { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_rgmii1>; - status = "disabled"; -}; - -/* Verdin ETH_1 (On-module PHY) */ -&cpsw_port1 { - phy-handle = <&cpsw3g_phy0>; - phy-mode = "rgmii-rxid"; - status = "disabled"; -}; - -/* Verdin ETH_2_RGMII */ -&cpsw_port2 { - status = "disabled"; -}; - -/* MDIO, shared by Verdin ETH_1 (On-module PHY) and Verdin ETH_2_RGMII */ -&cpsw3g_mdio { - assigned-clocks = <&k3_clks 157 20>; - assigned-clock-parents = <&k3_clks 157 22>; - assigned-clock-rates = <25000000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_eth_clock>, <&pinctrl_mdio>; - status = "disabled"; - - cpsw3g_phy0: ethernet-phy@0 { - compatible = "ethernet-phy-id2000.a231"; - reg = <0>; - interrupt-parent = <&main_gpio0>; - interrupts = <25 IRQ_TYPE_EDGE_FALLING>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_eth_int>, <&pinctrl_eth_reset>; - reset-gpios = <&main_gpio0 17 GPIO_ACTIVE_LOW>; - reset-assert-us = <10>; - reset-deassert-us = <1000>; - ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; - ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; - }; -}; - -&dss { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_parallel_rgb>; - status = "disabled"; -}; - -&dss_ports { - #address-cells = <1>; - #size-cells = <0>; - - /* VP2: DPI Output */ - port@1 { - reg = <1>; - - dpi_out: endpoint { - remote-endpoint = <&rgb_in>; - }; - }; -}; - -/* Verdin PWM_1, PWM_2 */ -&epwm0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_epwm0_a>, <&pinctrl_epwm0_b>; - status = "disabled"; -}; - -/* Verdin PWM_3_DSI */ -&epwm1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_epwm1_a>; - status = "disabled"; -}; - -&main_gpio0 { - gpio-line-names = - "SODIMM_52", /* 0 */ - "", - "", - "SODIMM_56", - "SODIMM_58", - "SODIMM_60", - "SODIMM_62", - "", - "", - "", - "", /* 10 */ - "SODIMM_54", - "SODIMM_64", - "", - "", - "SODIMM_174", - "SODIMM_172", - "", - "", - "", - "", /* 20 */ - "", - "", - "", - "", - "", - "", - "", - "", - "SODIMM_76", - "SODIMM_21", /* 30 */ - "SODIMM_256", - "SODIMM_252", - "", - "SODIMM_46", - "SODIMM_42", - "SODIMM_218", - "", - "SODIMM_189", - "", - "SODIMM_216", /* 40 */ - "SODIMM_220", - "SODIMM_222", - "", - "", - "", - "", - "", - "", - "", - "", /* 50 */ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", /* 60 */ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", /* 70 */ - "SODIMM_157", - "SODIMM_187", - "", - "", - "", - "", - "", - "", - "", - "", /* 80 */ - "", - "", - "", - "", - "", - ""; - - verdin_ctrl_sleep_moci: ctrl-sleep-moci-hog { - gpio-hog; - /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */ - gpios = <31 GPIO_ACTIVE_HIGH>; - line-name = "CTRL_SLEEP_MOCI#"; - output-high; - }; -}; - -&main_gpio1 { - gpio-line-names = - "", /* 0 */ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", /* 10 */ - "", - "", - "", - "", - "SODIMM_15", - "SODIMM_16", - "SODIMM_19", - "SODIMM_66", - "SODIMM_161", - "", /* 20 */ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", /* 30 */ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", /* 40 */ - "", - "", - "", - "", - "", - "", - "", - "", - "SODIMM_17", - "", /* 50 */ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", /* 60 */ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", /* 70 */ - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", /* 80 */ - "", - "", - "", - "", - "", - "", - ""; -}; - -/* On-module I2C - PMIC_I2C */ -&main_i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c0>; - clock-frequency = <400000>; - status = "okay"; - - dsi_bridge: dsi@e { - compatible = "toshiba,tc358778"; - reg = <0xe>; - assigned-clocks = <&k3_clks 157 20>; - assigned-clock-parents = <&k3_clks 157 22>; - assigned-clock-rates = <25000000>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_bridge_reset>; - clocks = <&k3_clks 157 20>; - clock-names = "refclk"; - reset-gpios = <&main_gpio0 20 GPIO_ACTIVE_LOW>; - vddc-supply = <®_1v2_dsi>; - vddmipi-supply = <®_1v2_dsi>; - vddio-supply = <®_1v8_dsi>; - status = "disabled"; - - dsi_bridge_ports: ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - rgb_in: endpoint { - data-lines = <18>; - remote-endpoint = <&dpi_out>; - }; - }; - - port@1 { - reg = <1>; - }; - }; - }; - - pmic@30 { - compatible = "ti,tps65219"; - reg = <0x30>; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_pmic_extint>; - interrupt-parent = <&gic500>; - interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>; - - buck1-supply = <®_vsodimm>; - buck2-supply = <®_vsodimm>; - buck3-supply = <®_vsodimm>; - ldo1-supply = <®_3v3>; - ldo2-supply = <®_1v8>; - ldo3-supply = <®_3v3>; - ldo4-supply = <®_3v3>; - system-power-controller; - ti,power-button; - - regulators { - reg_vdd_core: buck1 { - regulator-always-on; - regulator-boot-on; - regulator-max-microvolt = <850000>; - regulator-min-microvolt = <850000>; - regulator-name = "+VDD_CORE (PMIC BUCK1)"; - }; - - reg_1v8: buck2 { - regulator-always-on; - regulator-boot-on; - regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <1800000>; - regulator-name = "+V1.8 (PMIC BUCK2)"; /* On-module and SODIMM 214 */ - }; - - reg_vdd_ddr: buck3 { - regulator-always-on; - regulator-boot-on; - regulator-max-microvolt = <1100000>; - regulator-min-microvolt = <1100000>; - regulator-name = "+VDD_DDR (PMIC BUCK3)"; - }; - - reg_sd_3v3_1v8: ldo1 { - regulator-allow-bypass; - regulator-always-on; - regulator-boot-on; - regulator-max-microvolt = <3300000>; - regulator-min-microvolt = <3300000>; - regulator-name = "+V3.3_1.8_SD (PMIC LDO1)"; - }; - - reg_vddr_core: ldo2 { - regulator-always-on; - regulator-boot-on; - regulator-max-microvolt = <850000>; - regulator-min-microvolt = <850000>; - regulator-name = "+VDDR_CORE (PMIC LDO2)"; - }; - - reg_1v8a: ldo3 { - regulator-always-on; - regulator-boot-on; - regulator-max-microvolt = <1800000>; - regulator-min-microvolt = <1800000>; - regulator-name = "+V1.8A (PMIC LDO3)"; - }; - - reg_eth_2v5: ldo4 { - regulator-always-on; - regulator-boot-on; - regulator-max-microvolt = <2500000>; - regulator-min-microvolt = <2500000>; - regulator-name = "+V2.5_ETH (PMIC LDO4)"; - }; - }; - }; - - rtc_i2c: rtc@32 { - compatible = "epson,rx8130"; - reg = <0x32>; - }; - - sensor@48 { - compatible = "ti,tmp1075"; - reg = <0x48>; - }; - - adc@49 { - compatible = "ti,ads1015"; - reg = <0x49>; - #address-cells = <1>; - #size-cells = <0>; - - /* Verdin PMIC_I2C (ADC_4 - ADC_3) */ - channel@0 { - reg = <0>; - ti,datarate = <4>; - ti,gain = <2>; - }; - - /* Verdin PMIC_I2C (ADC_4 - ADC_1) */ - channel@1 { - reg = <1>; - ti,datarate = <4>; - ti,gain = <2>; - }; - - /* Verdin PMIC_I2C (ADC_3 - ADC_1) */ - channel@2 { - reg = <2>; - ti,datarate = <4>; - ti,gain = <2>; - }; - - /* Verdin PMIC_I2C (ADC_2 - ADC_1) */ - channel@3 { - reg = <3>; - ti,datarate = <4>; - ti,gain = <2>; - }; - - /* Verdin PMIC_I2C ADC_4 */ - channel@4 { - reg = <4>; - ti,datarate = <4>; - ti,gain = <2>; - }; - - /* Verdin PMIC_I2C ADC_3 */ - channel@5 { - reg = <5>; - ti,datarate = <4>; - ti,gain = <2>; - }; - - /* Verdin PMIC_I2C ADC_2 */ - channel@6 { - reg = <6>; - ti,datarate = <4>; - ti,gain = <2>; - }; - - /* Verdin PMIC_I2C ADC_1 */ - channel@7 { - reg = <7>; - ti,datarate = <4>; - ti,gain = <2>; - }; - }; - - eeprom@50 { - compatible = "st,24c02", "atmel,24c02"; - pagesize = <16>; - reg = <0x50>; - }; -}; - -/* Verdin I2C_1 */ -&main_i2c1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c1>; - status = "disabled"; -}; - -/* Verdin I2C_2_DSI */ -&main_i2c2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c2>; - status = "disabled"; -}; - -/* Verdin I2C_4_CSI */ -&main_i2c3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c3>; - status = "disabled"; -}; - -&mailbox0_cluster0 { - mbox_m4_0: mbox-m4-0 { - ti,mbox-rx = <0 0 0>; - ti,mbox-tx = <1 0 0>; - }; -}; - -/* Verdin CAN_1 */ -&main_mcan0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mcan0>; - status = "disabled"; -}; - -/* Verdin SPI_1 */ -&main_spi1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_spi1>; - ti,pindir-d0-out-d1-in; - status = "disabled"; -}; - -/* Verdin UART_3, used as the Linux console */ -&main_uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart0>; - status = "disabled"; -}; - -/* Verdin UART_1 */ -&main_uart1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart1>; - status = "disabled"; -}; - -/* Verdin I2S_1 */ -&mcasp0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mcasp0>; - op-mode = <0>; /* I2S mode */ - serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ - 1 2 0 0 - 0 0 0 0 - 0 0 0 0 - 0 0 0 0 - >; - tdm-slots = <2>; - rx-num-evt = <32>; - tx-num-evt = <32>; - #sound-dai-cells = <0>; - status = "disabled"; -}; - -/* Verdin I2S_2 */ -&mcasp1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mcasp1>; - op-mode = <0>; /* I2S mode */ - serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ - 1 2 0 0 - 0 0 0 0 - 0 0 0 0 - 0 0 0 0 - >; - tdm-slots = <2>; - rx-num-evt = <32>; - tx-num-evt = <32>; - #sound-dai-cells = <0>; - status = "disabled"; -}; - -/* Verdin I2C_3_HDMI */ -&mcu_i2c0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mcu_i2c0>; - status = "disabled"; -}; - -&mcu_gpio0 { - gpio-line-names = - "SODIMM_244", - "SODIMM_206", - "SODIMM_208", - "SODIMM_210", - "SODIMM_212", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - "", - ""; -}; - -/* Verdin CAN_2 */ -&mcu_mcan0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mcu_mcan0>; - status = "disabled"; -}; - -/* Verdin UART_4 - Cortex-M4 UART */ -&mcu_uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mcu_uart0>; - status = "disabled"; -}; - -/* Verdin QSPI_1 */ -&ospi0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ospi0>; - status = "disabled"; -}; - -/* On-module eMMC */ -&sdhci0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sdhci0>; - non-removable; - ti,driver-strength-ohm = <50>; - status = "okay"; -}; - -/* Verdin SD_1 */ -&sdhci1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sdhci1>; - disable-wp; - ti,driver-strength-ohm = <50>; - vmmc-supply = <®_sdhc1_vmmc>; - vqmmc-supply = <®_sdhc1_vqmmc>; - status = "disabled"; -}; - -/* Verdin USB_1 */ -&usbss0 { - ti,vbus-divider; - status = "disabled"; -}; - -/* TODO: role swich using ID pin */ -&usb0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usb0>, <&pinctrl_usb0_id>; - status = "disabled"; -}; - -/* Verdin USB_2 */ -&usbss1 { - ti,vbus-divider; - status = "disabled"; -}; - -&usb1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usb1>; - dr_mode = "host"; - status = "disabled"; -}; - -/* Verdin UART_2 */ -&wkup_uart0 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_wkup_uart0>; - status = "disabled"; -}; diff --git a/arch/arm/dts/k3-am625-beagleplay-u-boot.dtsi b/arch/arm/dts/k3-am625-beagleplay-u-boot.dtsi index cca0f44b7d8..fb2032068d1 100644 --- a/arch/arm/dts/k3-am625-beagleplay-u-boot.dtsi +++ b/arch/arm/dts/k3-am625-beagleplay-u-boot.dtsi @@ -41,13 +41,6 @@ clock-frequency = <25000000>; }; -&dmsc { - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; -}; - &sd_pins_default { /* Force to use SDCD card detect pin */ pinctrl-single,pins = < diff --git a/arch/arm/dts/k3-am625-phyboard-lyra-rdk-u-boot.dtsi b/arch/arm/dts/k3-am625-phyboard-lyra-rdk-u-boot.dtsi index f6138f3058f..94162282068 100644 --- a/arch/arm/dts/k3-am625-phyboard-lyra-rdk-u-boot.dtsi +++ b/arch/arm/dts/k3-am625-phyboard-lyra-rdk-u-boot.dtsi @@ -42,13 +42,6 @@ bootph-all; }; -&dmsc { - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; -}; - &fss { bootph-all; }; diff --git a/arch/arm/dts/k3-am625-sk-binman.dtsi b/arch/arm/dts/k3-am625-sk-binman.dtsi index 5b058bd03a0..dfd38d64f63 100644 --- a/arch/arm/dts/k3-am625-sk-binman.dtsi +++ b/arch/arm/dts/k3-am625-sk-binman.dtsi @@ -151,11 +151,107 @@ filename = "ti-dm/am62xx/ipc_echo_testb_mcu1_0_release_strip.xer5f"; }; }; + + tifsstub-hs { + filename = "tifsstub.bin_hs"; + ti-secure-rom { + content = <&tifsstub_hs_cert>; + core = "secure"; + load = <0x40000>; + sw-rev = <CONFIG_K3_X509_SWRV>; + keyfile = "custMpk.pem"; + countersign; + tifsstub; + }; + tifsstub_hs_cert: tifsstub-hs-cert.bin { + filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-cert.bin"; + type = "blob-ext"; + optional; + }; + tifsstub_hs_enc: tifsstub-hs-enc.bin { + filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-enc.bin"; + type = "blob-ext"; + optional; + }; + }; + + tifsstub-fs { + filename = "tifsstub.bin_fs"; + tifsstub_fs_cert: tifsstub-fs-cert.bin { + filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-cert.bin"; + type = "blob-ext"; + optional; + }; + tifsstub_fs_enc: tifsstub-fs-enc.bin { + filename = "ti-sysfw/ti-fs-stub-firmware-am62x-hs-enc.bin"; + type = "blob-ext"; + optional; + }; + + }; + + tifsstub-gp { + filename = "tifsstub.bin_gp"; + ti-secure-rom { + content = <&tifsstub_gp>; + core = "secure"; + load = <0x60000>; + sw-rev = <CONFIG_K3_X509_SWRV>; + keyfile = "ti-degenerate-key.pem"; + tifsstub; + }; + tifsstub_gp: tifsstub-gp.bin { + filename = "ti-sysfw/ti-fs-stub-firmware-am62x-gp.bin"; + type = "blob-ext"; + optional; + }; + }; + ti-spl { insert-template = <&ti_spl_template>; fit { images { + + tifsstub-hs { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-hs"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_hs"; + }; + }; + + tifsstub-fs { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-fs"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_fs"; + }; + }; + + tifsstub-gp { + description = "TIFSSTUB"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-gp"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_gp"; + }; + }; + dm { ti-secure { content = <&dm>; @@ -189,7 +285,8 @@ conf-0 { description = "k3-am625-sk"; firmware = "atf"; - loadables = "tee", "dm", "spl"; + loadables = "tee", "tifsstub-hs", "tifsstub-fs", + "tifsstub-gp", "dm", "spl"; fdt = "fdt-0"; }; }; @@ -247,6 +344,45 @@ fit { images { + tifsstub-hs { + description = "tifsstub"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-hs"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_hs"; + }; + }; + + tifsstub-fs { + description = "tifsstub"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-fs"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_fs"; + }; + }; + + tifsstub-gp { + description = "tifsstub"; + type = "firmware"; + arch = "arm32"; + compression = "none"; + os = "tifsstub-gp"; + load = <0x9dc00000>; + entry = <0x9dc00000>; + blob-ext { + filename = "tifsstub.bin_gp"; + }; + }; + dm { ti-dm { filename = "ti-dm.bin"; @@ -270,7 +406,8 @@ conf-0 { description = "k3-am625-sk"; firmware = "atf"; - loadables = "tee", "dm", "spl"; + loadables = "tee", "tifsstub-hs", "tifsstub-fs", + "tifsstub-gp", "dm", "spl"; fdt = "fdt-0"; }; }; diff --git a/arch/arm/dts/k3-am625-verdin-wifi-dev-binman.dtsi b/arch/arm/dts/k3-am625-verdin-wifi-dev-binman.dtsi index 4e3704809a6..6f5845024f2 100644 --- a/arch/arm/dts/k3-am625-verdin-wifi-dev-binman.dtsi +++ b/arch/arm/dts/k3-am625-verdin-wifi-dev-binman.dtsi @@ -140,7 +140,7 @@ #ifdef CONFIG_TARGET_VERDIN_AM62_A53 -#define SPL_VERDIN_AM62_DTB "spl/dts/k3-am625-verdin-wifi-dev.dtb" +#define SPL_VERDIN_AM62_DTB "spl/dts/ti/k3-am625-verdin-wifi-dev.dtb" #define VERDIN_AM62_DTB "u-boot.dtb" &binman { diff --git a/arch/arm/dts/k3-am625-verdin-wifi-dev-u-boot.dtsi b/arch/arm/dts/k3-am625-verdin-wifi-dev-u-boot.dtsi index 28b697b67ae..7fe7ae41543 100644 --- a/arch/arm/dts/k3-am625-verdin-wifi-dev-u-boot.dtsi +++ b/arch/arm/dts/k3-am625-verdin-wifi-dev-u-boot.dtsi @@ -85,13 +85,6 @@ bootph-all; }; -&dmsc { - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; -}; - &fss { bootph-all; }; diff --git a/arch/arm/dts/k3-am625-verdin-wifi-dev.dts b/arch/arm/dts/k3-am625-verdin-wifi-dev.dts deleted file mode 100644 index 4b657d6d3e0..00000000000 --- a/arch/arm/dts/k3-am625-verdin-wifi-dev.dts +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later OR MIT -/* - * Copyright 2023 Toradex - * - * https://www.toradex.com/computer-on-modules/verdin-arm-family/ti-am62 - * https://www.toradex.com/products/carrier-board/verdin-development-board-kit - */ - -/dts-v1/; - -#include "k3-am625.dtsi" -#include "k3-am62-verdin.dtsi" -#include "k3-am62-verdin-wifi.dtsi" -#include "k3-am62-verdin-dev.dtsi" - -/ { - model = "Toradex Verdin AM62 WB on Verdin Development Board"; - compatible = "toradex,verdin-am62-wifi-dev", - "toradex,verdin-am62-wifi", - "toradex,verdin-am62", - "ti,am625"; -}; diff --git a/arch/arm/dts/k3-am62a7-sk-u-boot.dtsi b/arch/arm/dts/k3-am62a7-sk-u-boot.dtsi index 31b89b41748..c42dec16194 100644 --- a/arch/arm/dts/k3-am62a7-sk-u-boot.dtsi +++ b/arch/arm/dts/k3-am62a7-sk-u-boot.dtsi @@ -119,10 +119,6 @@ &dmsc { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &vdd_mmc1 { diff --git a/arch/arm/dts/k3-am62p5-sk-u-boot.dtsi b/arch/arm/dts/k3-am62p5-sk-u-boot.dtsi index c166d655390..cf087c6e343 100644 --- a/arch/arm/dts/k3-am62p5-sk-u-boot.dtsi +++ b/arch/arm/dts/k3-am62p5-sk-u-boot.dtsi @@ -15,9 +15,4 @@ &dmsc { bootph-pre-ram; - - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-pre-ram; - }; }; diff --git a/arch/arm/dts/k3-am642-evm-u-boot.dtsi b/arch/arm/dts/k3-am642-evm-u-boot.dtsi index ee6656774d6..705b3baa81c 100644 --- a/arch/arm/dts/k3-am642-evm-u-boot.dtsi +++ b/arch/arm/dts/k3-am642-evm-u-boot.dtsi @@ -23,13 +23,6 @@ bootph-all; }; -&dmsc { - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; -}; - &sdhci0 { bootph-all; }; diff --git a/arch/arm/dts/k3-am642-phyboard-electra-rdk-u-boot.dtsi b/arch/arm/dts/k3-am642-phyboard-electra-rdk-u-boot.dtsi index 5dfc40a843b..4677c35e2d9 100644 --- a/arch/arm/dts/k3-am642-phyboard-electra-rdk-u-boot.dtsi +++ b/arch/arm/dts/k3-am642-phyboard-electra-rdk-u-boot.dtsi @@ -29,10 +29,6 @@ &dmsc { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &dmss { diff --git a/arch/arm/dts/k3-am642-sk-u-boot.dtsi b/arch/arm/dts/k3-am642-sk-u-boot.dtsi index 7e6b2981346..6fcb11bd04d 100644 --- a/arch/arm/dts/k3-am642-sk-u-boot.dtsi +++ b/arch/arm/dts/k3-am642-sk-u-boot.dtsi @@ -15,13 +15,6 @@ clock-frequency = <200000000>; }; -&dmsc { - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; -}; - &sdhci0 { status = "disabled"; }; diff --git a/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi b/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi index d53f133cd63..b6d2c816acc 100644 --- a/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-common-u-boot.dtsi @@ -99,10 +99,6 @@ &dmsc { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &k3_pds { diff --git a/arch/arm/dts/k3-am68-sk-base-board-u-boot.dtsi b/arch/arm/dts/k3-am68-sk-base-board-u-boot.dtsi index 4f34347586e..b8fc62f0dd1 100644 --- a/arch/arm/dts/k3-am68-sk-base-board-u-boot.dtsi +++ b/arch/arm/dts/k3-am68-sk-base-board-u-boot.dtsi @@ -51,10 +51,6 @@ &sms { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &main_pmx0 { diff --git a/arch/arm/dts/k3-am69-sk-u-boot.dtsi b/arch/arm/dts/k3-am69-sk-u-boot.dtsi index bed330e6d4e..4a82d2fd222 100644 --- a/arch/arm/dts/k3-am69-sk-u-boot.dtsi +++ b/arch/arm/dts/k3-am69-sk-u-boot.dtsi @@ -23,13 +23,6 @@ bootph-pre-ram; }; -&sms { - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-pre-ram; - }; -}; - #ifdef CONFIG_TARGET_J784S4_A72_EVM #define SPL_AM69_SK_DTB "spl/dts/ti/k3-am69-sk.dtb" diff --git a/arch/arm/dts/k3-j7200-common-proc-board-u-boot.dtsi b/arch/arm/dts/k3-j7200-common-proc-board-u-boot.dtsi index c9fee0ea99b..485f17c5f06 100644 --- a/arch/arm/dts/k3-j7200-common-proc-board-u-boot.dtsi +++ b/arch/arm/dts/k3-j7200-common-proc-board-u-boot.dtsi @@ -57,10 +57,6 @@ &dmsc { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &k3_pds { diff --git a/arch/arm/dts/k3-j721e-beagleboneai64-u-boot.dtsi b/arch/arm/dts/k3-j721e-beagleboneai64-u-boot.dtsi index 116ee373118..e202ae16644 100644 --- a/arch/arm/dts/k3-j721e-beagleboneai64-u-boot.dtsi +++ b/arch/arm/dts/k3-j721e-beagleboneai64-u-boot.dtsi @@ -92,10 +92,6 @@ &dmsc { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &k3_pds { diff --git a/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi b/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi index 9433f3bafae..aa919b40702 100644 --- a/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi +++ b/arch/arm/dts/k3-j721e-common-proc-board-u-boot.dtsi @@ -47,10 +47,6 @@ &dmsc { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &k3_pds { diff --git a/arch/arm/dts/k3-j721e-sk-u-boot.dtsi b/arch/arm/dts/k3-j721e-sk-u-boot.dtsi index 8b205553cdf..8f4f944263e 100644 --- a/arch/arm/dts/k3-j721e-sk-u-boot.dtsi +++ b/arch/arm/dts/k3-j721e-sk-u-boot.dtsi @@ -47,10 +47,6 @@ &dmsc { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &k3_pds { diff --git a/arch/arm/dts/k3-j721s2-common-proc-board-u-boot.dtsi b/arch/arm/dts/k3-j721s2-common-proc-board-u-boot.dtsi index a3ebf5996ea..19b2d48c7f8 100644 --- a/arch/arm/dts/k3-j721s2-common-proc-board-u-boot.dtsi +++ b/arch/arm/dts/k3-j721s2-common-proc-board-u-boot.dtsi @@ -51,10 +51,6 @@ &sms { bootph-all; - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-all; - }; }; &main_pmx0 { diff --git a/arch/arm/dts/k3-j784s4-evm-u-boot.dtsi b/arch/arm/dts/k3-j784s4-evm-u-boot.dtsi index ac749782bfc..8f0307321e8 100644 --- a/arch/arm/dts/k3-j784s4-evm-u-boot.dtsi +++ b/arch/arm/dts/k3-j784s4-evm-u-boot.dtsi @@ -22,10 +22,3 @@ "tchanrt", "rflow"; bootph-pre-ram; }; - -&sms { - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - bootph-pre-ram; - }; -}; diff --git a/arch/arm/dts/zynqmp-mini-nand.dts b/arch/arm/dts/zynqmp-mini-nand.dts index e0517cf4601..5889d436edb 100644 --- a/arch/arm/dts/zynqmp-mini-nand.dts +++ b/arch/arm/dts/zynqmp-mini-nand.dts @@ -50,6 +50,12 @@ #size-cells = <1>; arasan,has-mdma; num-cs = <2>; + nand@0 { + reg = <0>; + #address-cells = <2>; + #size-cells = <1>; + nand-ecc-mode = "hw"; + }; }; }; }; diff --git a/arch/arm/dts/zynqmp-sc-revB.dts b/arch/arm/dts/zynqmp-sc-revB.dts index 8517bdad6f4..c1d713b5d89 100644 --- a/arch/arm/dts/zynqmp-sc-revB.dts +++ b/arch/arm/dts/zynqmp-sc-revB.dts @@ -49,7 +49,7 @@ gpio-keys { compatible = "gpio-keys"; autorepeat; - fwuen { + key-fwuen { label = "sw16"; gpios = <&gpio 12 GPIO_ACTIVE_LOW>; linux,code = <BTN_MISC>; @@ -192,7 +192,7 @@ status = "okay"; /* QSPI should also have PINCTRL setup */ flash@0 { - compatible = "mt25qu512a", "m25p80", "jedec,spi-nor"; /* mt25qu512abb8e12 512Mib */ + compatible = "m25p80", "jedec,spi-nor"; /* mt25qu512abb8e12 512Mib */ #address-cells = <1>; #size-cells = <1>; reg = <0>; diff --git a/arch/arm/dts/zynqmp-sck-kd-g-revA.dtso b/arch/arm/dts/zynqmp-sck-kd-g-revA.dtso index 5202b7c4819..1727a1cc15c 100644 --- a/arch/arm/dts/zynqmp-sck-kd-g-revA.dtso +++ b/arch/arm/dts/zynqmp-sck-kd-g-revA.dtso @@ -356,6 +356,8 @@ &uart0 { status = "okay"; + rts-gpios = <&gpio 72 GPIO_ACTIVE_HIGH>; + linux,rs485-enabled-at-boot-time; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart0_default>; assigned-clock-rates = <100000000>; diff --git a/arch/arm/dts/zynqmp-sck-kr-g-revB.dtso b/arch/arm/dts/zynqmp-sck-kr-g-revB.dtso index 6c29f657413..0a0cbd2b69a 100644 --- a/arch/arm/dts/zynqmp-sck-kr-g-revB.dtso +++ b/arch/arm/dts/zynqmp-sck-kr-g-revB.dtso @@ -66,6 +66,18 @@ #clock-cells = <0>; clock-frequency = <74250000>; }; + + dpcon { + compatible = "dp-connector"; + label = "P11"; + type = "full-size"; + + port { + dpcon_in: endpoint { + remote-endpoint = <&dpsub_dp_out>; + }; + }; + }; }; &i2c1 { /* I2C_SCK C26/C27 - MIO from SOM */ @@ -130,6 +142,14 @@ phy-names = "dp-phy0"; phys = <&psgtr 1 PHY_TYPE_DP 0 1>; assigned-clock-rates = <27000000>, <25000000>, <300000000>; + + ports { + port@5 { + dpsub_dp_out: endpoint { + remote-endpoint = <&dpcon_in>; + }; + }; + }; }; &zynqmp_dpdma { diff --git a/arch/arm/dts/zynqmp-sck-kv-g-revA.dtso b/arch/arm/dts/zynqmp-sck-kv-g-revA.dtso index 6d0d5c487d2..561b546e37f 100644 --- a/arch/arm/dts/zynqmp-sck-kv-g-revA.dtso +++ b/arch/arm/dts/zynqmp-sck-kv-g-revA.dtso @@ -342,6 +342,7 @@ slew-rate = <SLEW_RATE_SLOW>; power-source = <IO_STANDARD_LVCMOS18>; bias-disable; + output-enable; }; conf-cd { diff --git a/arch/arm/dts/zynqmp-sck-kv-g-revB.dtso b/arch/arm/dts/zynqmp-sck-kv-g-revB.dtso index a4b4465d203..64683e0ccbb 100644 --- a/arch/arm/dts/zynqmp-sck-kv-g-revB.dtso +++ b/arch/arm/dts/zynqmp-sck-kv-g-revB.dtso @@ -63,6 +63,18 @@ #clock-cells = <0>; clock-frequency = <27000000>; }; + + dpcon { + compatible = "dp-connector"; + label = "P11"; + type = "full-size"; + + port { + dpcon_in: endpoint { + remote-endpoint = <&dpsub_dp_out>; + }; + }; + }; }; &i2c1 { /* I2C_SCK C23/C24 - MIO from SOM */ @@ -97,6 +109,14 @@ phy-names = "dp-phy0", "dp-phy1"; phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>; assigned-clock-rates = <27000000>, <25000000>, <300000000>; + + ports { + port@5 { + dpsub_dp_out: endpoint { + remote-endpoint = <&dpcon_in>; + }; + }; + }; }; &zynqmp_dpdma { @@ -329,6 +349,7 @@ slew-rate = <SLEW_RATE_SLOW>; power-source = <IO_STANDARD_LVCMOS18>; bias-disable; + output-enable; }; conf-cd { diff --git a/arch/arm/dts/zynqmp-vp-x-a2785-00-revA.dts b/arch/arm/dts/zynqmp-vp-x-a2785-00-revA.dts index 2a3bbe17047..b626d1aacf5 100644 --- a/arch/arm/dts/zynqmp-vp-x-a2785-00-revA.dts +++ b/arch/arm/dts/zynqmp-vp-x-a2785-00-revA.dts @@ -47,7 +47,7 @@ gpio-keys { compatible = "gpio-keys"; autorepeat; - j383 { + key-j383 { label = "j383"; gpios = <&gpio 10 GPIO_ACTIVE_HIGH>; linux,code = <BTN_MISC>; diff --git a/arch/arm/dts/zynqmp-vpk120-revA.dts b/arch/arm/dts/zynqmp-vpk120-revA.dts index e0e4f1b13ad..e0632883e4e 100644 --- a/arch/arm/dts/zynqmp-vpk120-revA.dts +++ b/arch/arm/dts/zynqmp-vpk120-revA.dts @@ -47,7 +47,7 @@ gpio-keys { compatible = "gpio-keys"; autorepeat; - sw16 { + button-16 { label = "sw16"; gpios = <&gpio 10 GPIO_ACTIVE_HIGH>; linux,code = <BTN_MISC>; diff --git a/arch/arm/dts/zynqmp-zc1751-xm017-dc3.dts b/arch/arm/dts/zynqmp-zc1751-xm017-dc3.dts index b97f7ee8d44..48ab619472e 100644 --- a/arch/arm/dts/zynqmp-zc1751-xm017-dc3.dts +++ b/arch/arm/dts/zynqmp-zc1751-xm017-dc3.dts @@ -136,8 +136,7 @@ reg = <0x0>; #address-cells = <0x2>; #size-cells = <0x1>; - nand-ecc-mode = "soft"; - nand-ecc-algo = "bch"; + nand-ecc-mode = "hw"; nand-rb = <0>; label = "main-storage-0"; nand-ecc-step-size = <1024>; @@ -173,8 +172,7 @@ reg = <0x1>; #address-cells = <0x2>; #size-cells = <0x1>; - nand-ecc-mode = "soft"; - nand-ecc-algo = "bch"; + nand-ecc-mode = "hw"; nand-rb = <0>; label = "main-storage-1"; nand-ecc-step-size = <1024>; diff --git a/arch/arm/dts/zynqmp-zcu208-revA.dts b/arch/arm/dts/zynqmp-zcu208-revA.dts index b4e24745a9a..a113e475082 100644 --- a/arch/arm/dts/zynqmp-zcu208-revA.dts +++ b/arch/arm/dts/zynqmp-zcu208-revA.dts @@ -46,7 +46,7 @@ gpio-keys { compatible = "gpio-keys"; autorepeat; - sw19 { + switch-19 { label = "sw19"; gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; linux,code = <KEY_DOWN>; diff --git a/arch/arm/dts/zynqmp-zcu216-revA.dts b/arch/arm/dts/zynqmp-zcu216-revA.dts index 6f593e80841..4d7d5d2e5ef 100644 --- a/arch/arm/dts/zynqmp-zcu216-revA.dts +++ b/arch/arm/dts/zynqmp-zcu216-revA.dts @@ -46,7 +46,7 @@ gpio-keys { compatible = "gpio-keys"; autorepeat; - sw19 { + switch-19 { label = "sw19"; gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; linux,code = <KEY_DOWN>; diff --git a/arch/arm/dts/zynqmp-zcu670-revA.dts b/arch/arm/dts/zynqmp-zcu670-revA.dts index 7f70904f44e..def3b53cef7 100644 --- a/arch/arm/dts/zynqmp-zcu670-revA.dts +++ b/arch/arm/dts/zynqmp-zcu670-revA.dts @@ -49,7 +49,7 @@ gpio-keys { compatible = "gpio-keys"; autorepeat; - sw1 { + switch-1 { label = "sw1"; gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; linux,code = <BTN_MISC>; diff --git a/arch/arm/dts/zynqmp-zcu670-revB.dts b/arch/arm/dts/zynqmp-zcu670-revB.dts index 0adb2062aef..41f9a23d06a 100644 --- a/arch/arm/dts/zynqmp-zcu670-revB.dts +++ b/arch/arm/dts/zynqmp-zcu670-revB.dts @@ -49,7 +49,7 @@ gpio-keys { compatible = "gpio-keys"; autorepeat; - sw1 { + switch-1 { label = "sw1"; gpios = <&gpio 22 GPIO_ACTIVE_HIGH>; linux,code = <BTN_MISC>; diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi index b50b83b7723..53a606c340a 100644 --- a/arch/arm/dts/zynqmp.dtsi +++ b/arch/arm/dts/zynqmp.dtsi @@ -168,7 +168,7 @@ bootph-all; }; - pmu { + pmu: pmu { compatible = "arm,armv8-pmuv3"; interrupt-parent = <&gic>; interrupts = <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, @@ -1001,14 +1001,14 @@ status = "disabled"; reg = <0x0 0xfe200000 0x0 0x40000>; interrupt-parent = <&gic>; - interrupt-names = "host", "peripheral", "otg"; + interrupt-names = "host", "peripheral", "otg", "wakeup"; interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>; + <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>; /* iommus = <&smmu 0x860>; */ snps,quirk-frame-length-adjustment = <0x20>; clock-names = "ref"; - snps,enable_guctl1_ipd_quirk; snps,resume-hs-terminations; /* dma-coherent; */ }; @@ -1033,14 +1033,14 @@ status = "disabled"; reg = <0x0 0xfe300000 0x0 0x40000>; interrupt-parent = <&gic>; - interrupt-names = "host", "peripheral", "otg"; + interrupt-names = "host", "peripheral", "otg", "wakeup"; interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; /* iommus = <&smmu 0x861>; */ snps,quirk-frame-length-adjustment = <0x20>; clock-names = "ref"; - snps,enable_guctl1_ipd_quirk; snps,resume-hs-terminations; /* dma-coherent; */ }; diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile index 67275fba616..b55167e9cc0 100644 --- a/arch/arm/lib/Makefile +++ b/arch/arm/lib/Makefile @@ -31,7 +31,7 @@ endif obj-$(CONFIG_CPU_V7M) += cmd_boot.o obj-$(CONFIG_OF_LIBFDT) += bootm-fdt.o obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-$(CONFIG_CMD_BOOTZ) += bootm.o zimage.o else obj-$(CONFIG_$(SPL_TPL_)FRAMEWORK) += spl.o diff --git a/arch/arm/mach-k3/Makefile b/arch/arm/mach-k3/Makefile index 6ee9864c72c..1bd523329a4 100644 --- a/arch/arm/mach-k3/Makefile +++ b/arch/arm/mach-k3/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_SOC_K3_J784S4) += j784s4_init.o obj-$(CONFIG_SOC_K3_AM62P5) += am62p5_init.o endif obj-y += common.o security.o +obj-$(CONFIG_SOC_K3_AM625) += am62x/ diff --git a/arch/arm/mach-k3/am625_init.c b/arch/arm/mach-k3/am625_init.c index 6c96e881146..668f9a51ef4 100644 --- a/arch/arm/mach-k3/am625_init.c +++ b/arch/arm/mach-k3/am625_init.c @@ -14,6 +14,7 @@ #include <dm.h> #include <dm/uclass-internal.h> #include <dm/pinctrl.h> +#include <dm/ofnode.h> #define RTC_BASE_ADDRESS 0x2b1f0000 #define REG_K3RTC_S_CNT_LSW (RTC_BASE_ADDRESS + 0x18) @@ -24,6 +25,9 @@ #define K3RTC_KICK0_UNLOCK_VALUE 0x83e70b13 #define K3RTC_KICK1_UNLOCK_VALUE 0x95a4f1e0 +/* TISCI DEV ID for A53 Clock */ +#define AM62X_DEV_A53SS0_CORE_0_DEV_ID 135 + /* * This uninitialized global variable would normal end up in the .bss section, * but the .bss is cleared between writing and reading this variable, so move @@ -112,6 +116,62 @@ static __maybe_unused void rtc_erratumi2327_init(void) writel(K3RTC_KICK1_UNLOCK_VALUE, REG_K3RTC_KICK1); } +#if CONFIG_IS_ENABLED(OF_CONTROL) +static int get_a53_cpu_clock_index(ofnode node) +{ + int count, i; + struct ofnode_phandle_args *args; + ofnode clknode; + + clknode = ofnode_path("/bus@f0000/system-controller@44043000/clock-controller"); + if (!ofnode_valid(clknode)) + return -1; + + count = ofnode_count_phandle_with_args(node, "assigned-clocks", "#clock-cells", 0); + + for (i = 0; i < count; i++) { + if (!ofnode_parse_phandle_with_args(node, "assigned-clocks", + "#clock-cells", 0, i, args)) { + if (ofnode_equal(clknode, args->node) && + args->args[0] == AM62X_DEV_A53SS0_CORE_0_DEV_ID) + return i; + } + } + + return -1; +} + +static void fixup_a53_cpu_freq_by_speed_grade(void) +{ + int index, size; + u32 *rates; + ofnode node; + + node = ofnode_path("/a53@0"); + if (!ofnode_valid(node)) + return; + + rates = fdt_getprop_w(ofnode_to_fdt(node), ofnode_to_offset(node), + "assigned-clock-rates", &size); + + index = get_a53_cpu_clock_index(node); + + if (!rates || index < 0 || index >= (size / sizeof(u32))) { + printf("Wrong A53 assigned-clocks configuration\n"); + return; + } + + rates[index] = cpu_to_fdt32(k3_get_a53_max_frequency()); + + printf("Changed A53 CPU frequency to %dHz (%c grade) in DT\n", + k3_get_a53_max_frequency(), k3_get_speed_grade()); +} +#else +static void fixup_a53_cpu_freq_by_speed_grade(void) +{ +} +#endif + void board_init_f(ulong dummy) { struct udevice *dev; @@ -176,6 +236,14 @@ void board_init_f(ulong dummy) } /* + * Relocate boot information to OCRAM (after TIFS has opend this + * region for us) so the next bootloader stages can keep access to + * primary vs backup bootmodes. + */ + if (IS_ENABLED(CONFIG_CPU_V7R)) + writel(bootindex, K3_BOOT_PARAM_TABLE_INDEX_OCRAM); + + /* * Force probe of clk_k3 driver here to ensure basic default clock * configuration is always done. */ @@ -210,6 +278,8 @@ void board_init_f(ulong dummy) panic("DRAM init failed: %d\n", ret); } spl_enable_cache(); + + fixup_a53_cpu_freq_by_speed_grade(); } u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) @@ -235,100 +305,7 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) } } -static u32 __get_backup_bootmedia(u32 devstat) -{ - u32 bkup_bootmode = (devstat & MAIN_DEVSTAT_BACKUP_BOOTMODE_MASK) >> - MAIN_DEVSTAT_BACKUP_BOOTMODE_SHIFT; - u32 bkup_bootmode_cfg = - (devstat & MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_MASK) >> - MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_SHIFT; - - switch (bkup_bootmode) { - case BACKUP_BOOT_DEVICE_UART: - return BOOT_DEVICE_UART; - - case BACKUP_BOOT_DEVICE_USB: - return BOOT_DEVICE_USB; - - case BACKUP_BOOT_DEVICE_ETHERNET: - return BOOT_DEVICE_ETHERNET; - - case BACKUP_BOOT_DEVICE_MMC: - if (bkup_bootmode_cfg) - return BOOT_DEVICE_MMC2; - return BOOT_DEVICE_MMC1; - - case BACKUP_BOOT_DEVICE_SPI: - return BOOT_DEVICE_SPI; - - case BACKUP_BOOT_DEVICE_I2C: - return BOOT_DEVICE_I2C; - - case BACKUP_BOOT_DEVICE_DFU: - if (bkup_bootmode_cfg & MAIN_DEVSTAT_BACKUP_USB_MODE_MASK) - return BOOT_DEVICE_USB; - return BOOT_DEVICE_DFU; - }; - - return BOOT_DEVICE_RAM; -} - -static u32 __get_primary_bootmedia(u32 devstat) -{ - u32 bootmode = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_MASK) >> - MAIN_DEVSTAT_PRIMARY_BOOTMODE_SHIFT; - u32 bootmode_cfg = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_MASK) >> - MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_SHIFT; - - switch (bootmode) { - case BOOT_DEVICE_OSPI: - fallthrough; - case BOOT_DEVICE_QSPI: - fallthrough; - case BOOT_DEVICE_XSPI: - fallthrough; - case BOOT_DEVICE_SPI: - return BOOT_DEVICE_SPI; - - case BOOT_DEVICE_ETHERNET_RGMII: - fallthrough; - case BOOT_DEVICE_ETHERNET_RMII: - return BOOT_DEVICE_ETHERNET; - - case BOOT_DEVICE_EMMC: - return BOOT_DEVICE_MMC1; - - case BOOT_DEVICE_MMC: - if ((bootmode_cfg & MAIN_DEVSTAT_PRIMARY_MMC_PORT_MASK) >> - MAIN_DEVSTAT_PRIMARY_MMC_PORT_SHIFT) - return BOOT_DEVICE_MMC2; - return BOOT_DEVICE_MMC1; - - case BOOT_DEVICE_DFU: - if ((bootmode_cfg & MAIN_DEVSTAT_PRIMARY_USB_MODE_MASK) >> - MAIN_DEVSTAT_PRIMARY_USB_MODE_SHIFT) - return BOOT_DEVICE_USB; - return BOOT_DEVICE_DFU; - - case BOOT_DEVICE_NOBOOT: - return BOOT_DEVICE_RAM; - } - - return bootmode; -} - u32 spl_boot_device(void) { - u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT); - u32 bootmedia; - - if (bootindex == K3_PRIMARY_BOOTMODE) - bootmedia = __get_primary_bootmedia(devstat); - else - bootmedia = __get_backup_bootmedia(devstat); - - debug("am625_init: %s: devstat = 0x%x bootmedia = 0x%x bootindex = %d\n", - __func__, devstat, bootmedia, bootindex); - - return bootmedia; + return get_boot_device(); } diff --git a/arch/arm/mach-k3/am62x/Kconfig b/arch/arm/mach-k3/am62x/Kconfig index 7c9bac2ece8..9786751874d 100644 --- a/arch/arm/mach-k3/am62x/Kconfig +++ b/arch/arm/mach-k3/am62x/Kconfig @@ -48,6 +48,7 @@ config TARGET_VERDIN_AM62_A53 select ARM64 select BINMAN select OF_SYSTEM_SETUP + imply OF_UPSTREAM config TARGET_VERDIN_AM62_R5 bool "Toradex Verdin AM62 running on R5" diff --git a/arch/arm/mach-k3/am62x/Makefile b/arch/arm/mach-k3/am62x/Makefile new file mode 100644 index 00000000000..acf09c3426c --- /dev/null +++ b/arch/arm/mach-k3/am62x/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0+ +obj-y += boot.o diff --git a/arch/arm/mach-k3/am62x/boot.c b/arch/arm/mach-k3/am62x/boot.c new file mode 100644 index 00000000000..132b42f7edb --- /dev/null +++ b/arch/arm/mach-k3/am62x/boot.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/am62_spl.h> + +static u32 __get_backup_bootmedia(u32 devstat) +{ + u32 bkup_bootmode = (devstat & MAIN_DEVSTAT_BACKUP_BOOTMODE_MASK) >> + MAIN_DEVSTAT_BACKUP_BOOTMODE_SHIFT; + u32 bkup_bootmode_cfg = + (devstat & MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_MASK) >> + MAIN_DEVSTAT_BACKUP_BOOTMODE_CFG_SHIFT; + + switch (bkup_bootmode) { + case BACKUP_BOOT_DEVICE_UART: + return BOOT_DEVICE_UART; + + case BACKUP_BOOT_DEVICE_USB: + return BOOT_DEVICE_USB; + + case BACKUP_BOOT_DEVICE_ETHERNET: + return BOOT_DEVICE_ETHERNET; + + case BACKUP_BOOT_DEVICE_MMC: + if (bkup_bootmode_cfg) + return BOOT_DEVICE_MMC2; + return BOOT_DEVICE_MMC1; + + case BACKUP_BOOT_DEVICE_SPI: + return BOOT_DEVICE_SPI; + + case BACKUP_BOOT_DEVICE_I2C: + return BOOT_DEVICE_I2C; + + case BACKUP_BOOT_DEVICE_DFU: + if (bkup_bootmode_cfg & MAIN_DEVSTAT_BACKUP_USB_MODE_MASK) + return BOOT_DEVICE_USB; + return BOOT_DEVICE_DFU; + }; + + return BOOT_DEVICE_RAM; +} + +static u32 __get_primary_bootmedia(u32 devstat) +{ + u32 bootmode = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_MASK) >> + MAIN_DEVSTAT_PRIMARY_BOOTMODE_SHIFT; + u32 bootmode_cfg = (devstat & MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_MASK) >> + MAIN_DEVSTAT_PRIMARY_BOOTMODE_CFG_SHIFT; + + switch (bootmode) { + case BOOT_DEVICE_OSPI: + fallthrough; + case BOOT_DEVICE_QSPI: + fallthrough; + case BOOT_DEVICE_XSPI: + fallthrough; + case BOOT_DEVICE_SPI: + return BOOT_DEVICE_SPI; + + case BOOT_DEVICE_ETHERNET_RGMII: + fallthrough; + case BOOT_DEVICE_ETHERNET_RMII: + return BOOT_DEVICE_ETHERNET; + + case BOOT_DEVICE_EMMC: + return BOOT_DEVICE_MMC1; + + case BOOT_DEVICE_MMC: + if ((bootmode_cfg & MAIN_DEVSTAT_PRIMARY_MMC_PORT_MASK) >> + MAIN_DEVSTAT_PRIMARY_MMC_PORT_SHIFT) + return BOOT_DEVICE_MMC2; + return BOOT_DEVICE_MMC1; + + case BOOT_DEVICE_DFU: + if ((bootmode_cfg & MAIN_DEVSTAT_PRIMARY_USB_MODE_MASK) >> + MAIN_DEVSTAT_PRIMARY_USB_MODE_SHIFT) + return BOOT_DEVICE_USB; + return BOOT_DEVICE_DFU; + + case BOOT_DEVICE_NOBOOT: + return BOOT_DEVICE_RAM; + } + + return bootmode; +} + +u32 get_boot_device(void) +{ + u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT); + u32 bootmode = *(u32 *)(K3_BOOT_PARAM_TABLE_INDEX_OCRAM); + u32 bootmedia; + + if (bootmode == K3_PRIMARY_BOOTMODE) + bootmedia = __get_primary_bootmedia(devstat); + else + bootmedia = __get_backup_bootmedia(devstat); + + debug("%s: devstat = 0x%x bootmedia = 0x%x bootmode = %d\n", + __func__, devstat, bootmedia, bootmode); + + return bootmedia; +} diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index b0fb87b97a2..1a269d6934a 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -24,6 +24,7 @@ #include <asm/io.h> #include <fs_loader.h> #include <fs.h> +#include <efi_loader.h> #include <env.h> #include <elf.h> #include <soc.h> @@ -270,6 +271,17 @@ int misc_init_r(void) printf("Failed to probe am65_cpsw_nuss driver\n"); } + if (IS_ENABLED(CONFIG_TI_ICSSG_PRUETH)) { + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MISC, + DM_DRIVER_GET(prueth), + &dev); + if (ret) + printf("Failed to probe prueth driver\n"); + } + /* Default FIT boot on HS-SE devices */ if (get_device_type() == K3_DEVICE_TYPE_HS_SE) env_set("boot_fit", "1"); @@ -296,3 +308,14 @@ void setup_qos(void) writel(qos_data[i].val, (uintptr_t)qos_data[i].reg); } #endif + +void efi_add_known_memory(void) +{ + if (IS_ENABLED(CONFIG_EFI_LOADER)) + /* + * Memory over ram_top can be used by various firmware + * Declare to EFI only memory area below ram_top + */ + efi_add_memory_map(gd->ram_base, gd->ram_top - gd->ram_base, + EFI_CONVENTIONAL_MEMORY); +} diff --git a/arch/arm/mach-k3/include/mach/am62_hardware.h b/arch/arm/mach-k3/include/mach/am62_hardware.h index 264f8a488b4..bcbc4821c82 100644 --- a/arch/arm/mach-k3/include/mach/am62_hardware.h +++ b/arch/arm/mach-k3/include/mach/am62_hardware.h @@ -83,6 +83,7 @@ #define CTRLMMR_DBOUNCE_CFG(index) (MCU_CTRL_MMR0_BASE + 0x4080 + (index * 4)) #define ROM_EXTENDED_BOOT_DATA_INFO 0x43c3f1e0 +#define K3_BOOT_PARAM_TABLE_INDEX_OCRAM 0x7000F290 #define TI_SRAM_SCRATCH_BOARD_EEPROM_START 0x43c30000 @@ -122,6 +123,21 @@ static inline int k3_get_max_temp(void) } } +static inline int k3_get_a53_max_frequency(void) +{ + switch (k3_get_speed_grade()) { + case 'K': + return 800000000; + case 'S': + return 1000000000; + case 'T': + return 1250000000; + case 'G': + default: + return 300000000; + } +} + static inline int k3_has_pru(void) { u32 full_devid = readl(CTRLMMR_WKUP_JTAG_DEVICE_ID); diff --git a/arch/arm/mach-k3/include/mach/hardware.h b/arch/arm/mach-k3/include/mach/hardware.h index af982e70d17..c724450638c 100644 --- a/arch/arm/mach-k3/include/mach/hardware.h +++ b/arch/arm/mach-k3/include/mach/hardware.h @@ -107,4 +107,5 @@ struct rom_extended_boot_data { u32 num_components; }; +u32 get_boot_device(void); #endif /* _ASM_ARCH_HARDWARE_H_ */ diff --git a/arch/arm/mach-k3/r5/common.c b/arch/arm/mach-k3/r5/common.c index c02f8d33099..0f6c294f1eb 100644 --- a/arch/arm/mach-k3/r5/common.c +++ b/arch/arm/mach-k3/r5/common.c @@ -24,6 +24,9 @@ enum { IMAGE_ID_OPTEE, IMAGE_ID_SPL, IMAGE_ID_DM_FW, + IMAGE_ID_TIFSSTUB_HS, + IMAGE_ID_TIFSSTUB_FS, + IMAGE_ID_T, IMAGE_AMT, }; @@ -33,6 +36,9 @@ static const char *image_os_match[IMAGE_AMT] = { "tee", "U-Boot", "DM", + "tifsstub-hs", + "tifsstub-fs", + "tifsstub-gp", }; #endif @@ -314,6 +320,24 @@ void board_fit_image_post_process(const void *fit, int node, void **p_image, break; } } + + if (i < IMAGE_AMT && i > IMAGE_ID_DM_FW) { + int device_type = get_device_type(); + + if ((device_type == K3_DEVICE_TYPE_HS_SE && + strcmp(os, "tifsstub-hs")) || + (device_type == K3_DEVICE_TYPE_HS_FS && + strcmp(os, "tifsstub-fs")) || + (device_type == K3_DEVICE_TYPE_GP && + strcmp(os, "tifsstub-gp"))) { + *p_size = 0; + } else { + debug("tifsstub-type: %s\n", os); + } + + return; + } + /* * Only DM and the DTBs are being authenticated here, * rest will be authenticated when A72 cluster is up diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 1008232cac8..6b6a162f568 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -90,6 +90,14 @@ config TARGET_SOCFPGA_ARRIA10 imply FPGA_SOCFPGA imply SPL_USE_TINY_PRINTF +config SOCFPGA_ARRIA10_ALWAYS_REPROGRAM + bool "Always reprogram Arria 10 FPGA" + depends on TARGET_SOCFPGA_ARRIA10 + help + Arria 10 FPGA is only programmed during the cold boot. + This option forces the FPGA to be reprogrammed every reboot, + allowing to change the bitstream and apply it with warm reboot. + config TARGET_SOCFPGA_CYCLONE5 bool select TARGET_SOCFPGA_GEN5 diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index 9edbbf4a29c..3981d2d4f14 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -122,7 +122,10 @@ void spl_board_init(void) arch_early_init_r(); /* If the full FPGA is already loaded, ie.from EPCQ, config fpga pins */ - if (is_fpgamgr_user_mode()) { + if ((IS_ENABLED(CONFIG_SOCFPGA_ARRIA10_ALWAYS_REPROGRAM) && + is_regular_boot_valid()) || + (!IS_ENABLED(CONFIG_SOCFPGA_ARRIA10_ALWAYS_REPROGRAM) && + is_fpgamgr_user_mode())) { ret = config_pins(gd->fdt_blob, "shared"); if (ret) return; @@ -130,7 +133,8 @@ void spl_board_init(void) ret = config_pins(gd->fdt_blob, "fpga"); if (ret) return; - } else if (!is_fpgamgr_early_user_mode()) { + } else if (IS_ENABLED(CONFIG_SOCFPGA_ARRIA10_ALWAYS_REPROGRAM) || + !is_fpgamgr_early_user_mode()) { /* Program IOSSM(early IO release) or full FPGA */ fpgamgr_program(buf, FPGA_BUFSIZ, 0); diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c index 7f2753190c2..e6f1286e71f 100644 --- a/arch/arm/mach-uniphier/dram_init.c +++ b/arch/arm/mach-uniphier/dram_init.c @@ -265,14 +265,15 @@ int dram_init(void) if (uniphier_get_soc_id() == UNIPHIER_LD20_ID) gd->ram_size -= 64; + /* map all the DRAM regions */ + uniphier_mem_map_init(gd->ram_base, prev_top - gd->ram_base); + return 0; } int dram_init_banksize(void) { struct uniphier_dram_map dram_map[3] = {}; - unsigned long base, top; - bool valid_bank_found = false; int ret, i; ret = uniphier_dram_map_get(dram_map); @@ -287,18 +288,7 @@ int dram_init_banksize(void) if (!dram_map[i].size) continue; - - if (!valid_bank_found) - base = dram_map[i].base; - top = dram_map[i].base + dram_map[i].size; - valid_bank_found = true; } - if (!valid_bank_found) - return -EINVAL; - - /* map all the DRAM regions */ - uniphier_mem_map_init(base, top - base); - return 0; } diff --git a/arch/arm/mach-zynqmp/Kconfig b/arch/arm/mach-zynqmp/Kconfig index 6a7be0b4271..0d2238ace1e 100644 --- a/arch/arm/mach-zynqmp/Kconfig +++ b/arch/arm/mach-zynqmp/Kconfig @@ -1,29 +1,5 @@ if ARCH_ZYNQMP -config SPL_FS_FAT - default y - -config SPL_LIBCOMMON_SUPPORT - default y - -config SPL_LIBDISK_SUPPORT - default y - -config SPL_LIBGENERIC_SUPPORT - default y - -config SPL_MMC - default y if MMC_SDHCI_ZYNQ - -config SPL_SERIAL - default y - -config SPL_SPI_FLASH_SUPPORT - default y if ZYNQ_QSPI - -config SPL_SPI - default y if ZYNQ_QSPI - config SYS_BOARD string "Board name" default "zynqmp" @@ -135,7 +111,8 @@ config ZYNQMP_PSU_INIT_ENABLED config SPL_ZYNQMP_PSU_INIT_ENABLED bool "Include psu_init in SPL" - default y if SPL + depends on SPL + default y select BOARD_EARLY_INIT_F help Include psu_init by default in SPL. diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c index a0f35f36faa..979ff3aef6c 100644 --- a/arch/arm/mach-zynqmp/spl.c +++ b/arch/arm/mach-zynqmp/spl.c @@ -9,6 +9,7 @@ #include <image.h> #include <init.h> #include <log.h> +#include <semihosting.h> #include <spl.h> #include <linux/delay.h> @@ -66,6 +67,11 @@ void spl_board_init(void) } #endif +static u32 jtag_boot_device(void) +{ + return semihosting_enabled() ? BOOT_DEVICE_SMH : BOOT_DEVICE_RAM; +} + void board_boot_order(u32 *spl_boot_list) { spl_boot_list[0] = spl_boot_device(); @@ -75,7 +81,7 @@ void board_boot_order(u32 *spl_boot_list) if (spl_boot_list[0] == BOOT_DEVICE_MMC2) spl_boot_list[1] = BOOT_DEVICE_MMC1; - spl_boot_list[2] = BOOT_DEVICE_RAM; + spl_boot_list[2] = jtag_boot_device(); } u32 spl_boot_device(void) @@ -85,19 +91,20 @@ u32 spl_boot_device(void) #if defined(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE_ENABLED) /* Change default boot mode at run-time */ + reg = CONFIG_SPL_ZYNQMP_ALT_BOOTMODE; writel(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE << BOOT_MODE_ALT_SHIFT, &crlapb_base->boot_mode); -#endif - +#else reg = readl(&crlapb_base->boot_mode); if (reg >> BOOT_MODE_ALT_SHIFT) reg >>= BOOT_MODE_ALT_SHIFT; +#endif bootmode = reg & BOOT_MODES_MASK; switch (bootmode) { case JTAG_MODE: - return BOOT_DEVICE_RAM; + return jtag_boot_device(); #ifdef CONFIG_SPL_MMC case SD_MODE1: case SD1_LSHFT_MODE: /* not working on silicon v1 */ diff --git a/arch/m68k/lib/Makefile b/arch/m68k/lib/Makefile index 6e1fd938f52..5ccd9545cb5 100644 --- a/arch/m68k/lib/Makefile +++ b/arch/m68k/lib/Makefile @@ -8,7 +8,7 @@ lib-$(CONFIG_USE_PRIVATE_LIBGCC) += lshrdi3.o muldi3.o ashldi3.o ashrdi3.o obj-y += bdinfo.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-y += cache.o obj-y += interrupts.o obj-y += time.o diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile index dfd8135f4f2..2f234825f80 100644 --- a/arch/microblaze/lib/Makefile +++ b/arch/microblaze/lib/Makefile @@ -3,6 +3,6 @@ # (C) Copyright 2003-2006 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-$(CONFIG_CMD_BDI) += bdinfo.o obj-y += muldi3.o diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 1621cc9a1ff..4386eb4d6d1 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -10,7 +10,7 @@ obj-y += reloc.o obj-y += stack.o obj-y += traps.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-$(CONFIG_CMD_GO) += boot.o obj-$(CONFIG_SPL_BUILD) += spl.o diff --git a/arch/nios2/lib/Makefile b/arch/nios2/lib/Makefile index a9f3c7100e7..68a5ca007d5 100644 --- a/arch/nios2/lib/Makefile +++ b/arch/nios2/lib/Makefile @@ -4,5 +4,5 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-y += cache.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-y += libgcc.o diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index bb819dcbb6c..dcce9834927 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile @@ -34,7 +34,7 @@ obj-y += ticks.o endif obj-y += reloc.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-y += cache.o obj-y += extable.o obj-y += interrupts.o diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 6c26f91f166..7e20ef63bba 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -22,6 +22,7 @@ config TARGET_OPENPITON_RISCV64 config TARGET_QEMU_VIRT bool "Support QEMU Virt Board" + select BOARD_LATE_INIT config TARGET_SIFIVE_UNLEASHED bool "Support SiFive Unleashed Board" @@ -93,6 +94,7 @@ source "board/xilinx/mbv/Kconfig" # platform-specific options below source "arch/riscv/cpu/andesv5/Kconfig" +source "arch/riscv/cpu/cv1800b/Kconfig" source "arch/riscv/cpu/fu540/Kconfig" source "arch/riscv/cpu/fu740/Kconfig" source "arch/riscv/cpu/generic/Kconfig" @@ -119,6 +121,26 @@ config ARCH_RV64I endchoice +config FRAMEPOINTER + bool "Build with frame pointer for stack unwinding" + help + Choose this option to use the frame pointer so the stack can be + unwound if needed. This is useful for tracing where faults came + from as the source may be several functions back + + If you say Y here, then the code size will be increased due to + having to store the fp. + +config SPL_FRAMEPOINTER + bool "Build SPL with frame pointer for stack unwinding" + help + Choose this option to use the frame pointer so the stack can be + unwound if needed. This is useful for tracing where faults came + from as the source may be several functions back + + If you say Y here, then the code size will be increased due to + having to store the fp. + choice prompt "Code Model" default CMODEL_MEDLOW diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index b3ef87078b5..c36a8533e0f 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -48,6 +48,10 @@ endif ARCH_FLAGS = -march=$(RISCV_MARCH) -mabi=$(ABI) \ -mcmodel=$(CMODEL) +ifeq ($(CONFIG_$(SPL_)FRAMEPOINTER),y) + ARCH_FLAGS += -fno-omit-frame-pointer +endif + PLATFORM_CPPFLAGS += $(ARCH_FLAGS) CFLAGS_EFI += $(ARCH_FLAGS) diff --git a/arch/riscv/cpu/cpu.c b/arch/riscv/cpu/cpu.c index ecfefa1a025..affe70081b5 100644 --- a/arch/riscv/cpu/cpu.c +++ b/arch/riscv/cpu/cpu.c @@ -38,35 +38,51 @@ static inline bool supports_extension(char ext) #if CONFIG_IS_ENABLED(RISCV_MMODE) return csr_read(CSR_MISA) & (1 << (ext - 'a')); #elif CONFIG_CPU + char sext[2] = {ext}; struct udevice *dev; - char desc[32]; - int i; + const char *isa; + int ret, i; uclass_find_first_device(UCLASS_CPU, &dev); if (!dev) { debug("unable to find the RISC-V cpu device\n"); return false; } - if (!cpu_get_desc(dev, desc, sizeof(desc))) { - /* - * skip the first 4 characters (rv32|rv64) - */ - for (i = 4; i < sizeof(desc); i++) { - switch (desc[i]) { - case 's': - case 'x': - case 'z': - case '_': - case '\0': - /* - * Any of these characters mean the single - * letter extensions have all been consumed. - */ - return false; - default: - if (desc[i] == ext) - return true; - } + + ret = dev_read_stringlist_search(dev, "riscv,isa-extensions", sext); + if (ret >= 0) + return true; + + /* + * Only if the property is not found (ENODATA) is the fallback to + * riscv,isa used, otherwise the extension is not present in this + * CPU. + */ + if (ret != -ENODATA) + return false; + + isa = dev_read_string(dev, "riscv,isa"); + if (!isa) + return false; + + /* + * Skip the first 4 characters (rv32|rv64). + */ + for (i = 4; i < sizeof(isa); i++) { + switch (isa[i]) { + case 's': + case 'x': + case 'z': + case '_': + case '\0': + /* + * Any of these characters mean the single + * letter extensions have all been consumed. + */ + return false; + default: + if (isa[i] == ext) + return true; } } diff --git a/arch/riscv/cpu/cv1800b/Kconfig b/arch/riscv/cpu/cv1800b/Kconfig new file mode 100644 index 00000000000..7225b1210c5 --- /dev/null +++ b/arch/riscv/cpu/cv1800b/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + +config SOPHGO_CV1800B + bool + select ARCH_EARLY_INIT_R + select SYS_CACHE_SHIFT_6 + imply CPU + imply CPU_RISCV + imply RISCV_TIMER + imply CMD_CPU diff --git a/arch/riscv/cpu/cv1800b/Makefile b/arch/riscv/cpu/cv1800b/Makefile new file mode 100644 index 00000000000..95beb34b51a --- /dev/null +++ b/arch/riscv/cpu/cv1800b/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + +obj-y += dram.o +obj-y += cpu.o +obj-y += cache.o diff --git a/arch/riscv/cpu/cv1800b/cache.c b/arch/riscv/cpu/cv1800b/cache.c new file mode 100644 index 00000000000..b8051e29e02 --- /dev/null +++ b/arch/riscv/cpu/cv1800b/cache.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + */ + +#include <cpu_func.h> + +/* + * dcache.ipa rs1 (invalidate) + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000001 01010 rs1 000 00000 0001011 + * + * dcache.cpa rs1 (clean) + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000001 01001 rs1 000 00000 0001011 + * + * dcache.cipa rs1 (clean then invalidate) + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000001 01011 rs1 000 00000 0001011 + * + * sync.s + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000000 11001 00000 000 00000 0001011 + */ +#define DCACHE_IPA_A0 ".long 0x02a5000b" +#define DCACHE_CPA_A0 ".long 0x0295000b" +#define DCACHE_CIPA_A0 ".long 0x02b5000b" + +#define SYNC_S ".long 0x0190000b" + +void invalidate_dcache_range(unsigned long start, unsigned long end) +{ + register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1); + for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE) + __asm__ __volatile__(DCACHE_IPA_A0); + __asm__ __volatile__(SYNC_S); +} + +void flush_dcache_range(unsigned long start, unsigned long end) +{ + register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1); + for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE) + __asm__ __volatile__(DCACHE_CPA_A0); + __asm__ __volatile__(SYNC_S); +} diff --git a/arch/riscv/cpu/cv1800b/cpu.c b/arch/riscv/cpu/cv1800b/cpu.c new file mode 100644 index 00000000000..233a6a3d64e --- /dev/null +++ b/arch/riscv/cpu/cv1800b/cpu.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + */ + +int cleanup_before_linux(void) +{ + return 0; +} diff --git a/arch/riscv/cpu/cv1800b/dram.c b/arch/riscv/cpu/cv1800b/dram.c new file mode 100644 index 00000000000..91007c0a3d3 --- /dev/null +++ b/arch/riscv/cpu/cv1800b/dram.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> + */ + +#include <fdtdec.h> +#include <init.h> +#include <asm/global_data.h> +#include <linux/sizes.h> + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + return fdtdec_setup_mem_size_base(); +} + +int dram_init_banksize(void) +{ + return fdtdec_setup_memory_banksize(); +} diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S index 6cecadfac56..a9e19356928 100644 --- a/arch/riscv/cpu/start.S +++ b/arch/riscv/cpu/start.S @@ -418,6 +418,7 @@ call_board_init_r: */ mv a0, s3 /* gd_t */ mv a1, s4 /* dest_addr */ + mv s0, zero /* fp == NULL */ /* * jump to it ... diff --git a/arch/riscv/dts/cv1800b-milkv-duo.dts b/arch/riscv/dts/cv1800b-milkv-duo.dts index 3af9e34b3bc..94e64ddce8f 100644 --- a/arch/riscv/dts/cv1800b-milkv-duo.dts +++ b/arch/riscv/dts/cv1800b-milkv-duo.dts @@ -33,6 +33,14 @@ clock-frequency = <25000000>; }; +&sdhci0 { + status = "okay"; + bus-width = <4>; + no-1-8-v; + no-mmc; + no-sdio; +}; + &uart0 { status = "okay"; }; diff --git a/arch/riscv/dts/cv1800b.dtsi b/arch/riscv/dts/cv1800b.dtsi index 165e9e320a8..baf641829e7 100644 --- a/arch/riscv/dts/cv1800b.dtsi +++ b/arch/riscv/dts/cv1800b.dtsi @@ -16,3 +16,7 @@ &clint { compatible = "sophgo,cv1800b-clint", "thead,c900-clint"; }; + +&clk { + compatible = "sophgo,cv1800-clk"; +}; diff --git a/arch/riscv/dts/cv18xx.dtsi b/arch/riscv/dts/cv18xx.dtsi index 2d6f4a4b1e5..ec99c4deeb6 100644 --- a/arch/riscv/dts/cv18xx.dtsi +++ b/arch/riscv/dts/cv18xx.dtsi @@ -45,6 +45,13 @@ #clock-cells = <0>; }; + sdhci_clk: sdhci-clock { + compatible = "fixed-clock"; + clock-frequency = <375000000>; + clock-output-names = "sdhci_clk"; + #clock-cells = <0>; + }; + soc { compatible = "simple-bus"; interrupt-parent = <&plic>; @@ -53,6 +60,12 @@ dma-noncoherent; ranges; + clk: clock-controller@3002000 { + reg = <0x03002000 0x1000>; + clocks = <&osc>; + #clock-cells = <1>; + }; + gpio0: gpio@3020000 { compatible = "snps,dw-apb-gpio"; reg = <0x3020000 0x1000>; @@ -175,6 +188,15 @@ status = "disabled"; }; + sdhci0: mmc@4310000 { + compatible = "sophgo,cv1800b-dwcmshc"; + reg = <0x4310000 0x1000>; + interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&sdhci_clk>; + clock-names = "core"; + status = "disabled"; + }; + plic: interrupt-controller@70000000 { reg = <0x70000000 0x4000000>; interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 9>; diff --git a/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi b/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi index f2c6bec9298..e11babc1cde 100644 --- a/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi +++ b/arch/riscv/dts/jh7110-starfive-visionfive-2.dtsi @@ -298,7 +298,7 @@ pinctrl-0 = <&mmc1_pins>; no-sdio; no-mmc; - broken-cd; + cd-gpios = <&sysgpio 41 GPIO_ACTIVE_LOW>; cap-sd-highspeed; post-power-on-delay-ms = <200>; status = "okay"; diff --git a/arch/riscv/dts/xilinx-mbv32.dts b/arch/riscv/dts/xilinx-mbv32.dts index 94e42c26811..48ee1154956 100644 --- a/arch/riscv/dts/xilinx-mbv32.dts +++ b/arch/riscv/dts/xilinx-mbv32.dts @@ -8,6 +8,9 @@ */ /dts-v1/; + +#include "binman.dtsi" + / { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/riscv/include/asm/arch-jh7110/eeprom.h b/arch/riscv/include/asm/arch-jh7110/eeprom.h index d2776d5b6cb..62d184aeb57 100644 --- a/arch/riscv/include/asm/arch-jh7110/eeprom.h +++ b/arch/riscv/include/asm/arch-jh7110/eeprom.h @@ -12,4 +12,13 @@ u8 get_pcb_revision_from_eeprom(void); u32 get_ddr_size_from_eeprom(void); +/** + * get_product_id_from_eeprom - get product ID string + * + * A string like "VF7110A1-2228-D008E000-00000001" is returned. + * + * Return: product ID string + */ +const char *get_product_id_from_eeprom(void); + #endif /* _ASM_RISCV_EEPROM_H */ diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index 9a05b662fd6..0b2c88db6ba 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -6,7 +6,7 @@ # Copyright (C) 2017 Andes Technology Corporation # Rick Chen, Andes Technology Corporation <rick@andestech.com> -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-$(CONFIG_CMD_BOOTI) += bootm.o image.o obj-$(CONFIG_CMD_GO) += boot.o obj-y += cache.o diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c index a26ccc721fd..7350e2ced85 100644 --- a/arch/riscv/lib/interrupts.c +++ b/arch/riscv/lib/interrupts.c @@ -60,6 +60,40 @@ static void show_regs(struct pt_regs *regs) #endif } +#if defined(CONFIG_FRAMEPOINTER) || defined(CONFIG_SPL_FRAMEPOINTER) +static void show_backtrace(struct pt_regs *regs) +{ + uintptr_t *fp = (uintptr_t *)regs->s0; + unsigned count = 0; + ulong ra; + + printf("backtrace:\n"); + + /* there are a few entry points where the s0 register is + * set to gd, so to avoid changing those, just abort if + * the value is the same */ + while (fp != NULL && fp != (uintptr_t *)gd) { + ra = fp[-1]; + printf("backtrace %2d: FP: " REG_FMT " RA: " REG_FMT, + count, (ulong)fp, ra); + + if (gd && gd->flags & GD_FLG_RELOC) + printf(" - RA: " REG_FMT " reloc adjusted\n", + ra - gd->reloc_off); + else + printf("\n"); + + fp = (uintptr_t *)fp[-2]; + count++; + } +} +#else +static void show_backtrace(struct pt_regs *regs) +{ + printf("No backtrace support enabled\n"); +} +#endif + /** * instr_len() - get instruction length * @@ -131,6 +165,7 @@ static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs) epc - gd->reloc_off, regs->ra - gd->reloc_off); show_regs(regs); + show_backtrace(regs); show_code(epc); show_efi_loaded_images(epc); panic("\n"); diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig index 0ce77de2fcb..1c8353d6156 100644 --- a/arch/sandbox/Kconfig +++ b/arch/sandbox/Kconfig @@ -58,10 +58,15 @@ config SANDBOX_CRASH_RESET bool "Reset on crash" help If an illegal instruction or an illegal memory access occurs, the - sandbox by default writes a crash dump and exits. If you set this - flag, the sandbox is reset instead. This may be useful when running - test suites like the UEFI self certification test which continue - with the next test after a crash. + sandbox exits with an error by default. + + If the u-boot binary is invoked with --signals (or -S), U-Boot will + handle the signal writing a crash dump before exiting. + + If you additionally set the CONFIG_SANDBOX_CRASH_RESET flag, the + sandbox is reset after writing the crash dump. This may be useful + when running test suites like the UEFI self certification test which + continue with the next test after a crash. config SANDBOX_BITS_PER_LONG int diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c index 92c35aed95d..39ea3b3f012 100644 --- a/arch/sandbox/cpu/eth-raw-os.c +++ b/arch/sandbox/cpu/eth-raw-os.c @@ -105,7 +105,12 @@ static int _raw_packet_start(struct eth_sandbox_raw_priv *priv, /* Make the socket non-blocking */ flags = fcntl(priv->sd, F_GETFL, 0); - fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK); + ret = fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK); + if (ret == -1) { + printf("Failed to make socket non-blocking: %d %s\n", errno, + strerror(errno)); + return -errno; + } /* Enable promiscuous mode to receive responses meant for us */ mr.mr_ifindex = device->sll_ifindex; @@ -172,7 +177,12 @@ static int _local_inet_start(struct eth_sandbox_raw_priv *priv) /* Make the socket non-blocking */ flags = fcntl(priv->sd, F_GETFL, 0); - fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK); + ret = fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK); + if (ret == -1) { + printf("Failed to make socket non-blocking: %d %s\n", errno, + strerror(errno)); + return -errno; + } /* Include the UDP/IP headers on send and receive */ ret = setsockopt(priv->sd, IPPROTO_IP, IP_HDRINCL, &one, diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile index a2bc5a7ee60..c4924b23c83 100644 --- a/arch/sandbox/lib/Makefile +++ b/arch/sandbox/lib/Makefile @@ -7,5 +7,5 @@ obj-y += fdt_fixup.o interrupts.o sections.o obj-$(CONFIG_PCI) += pci_io.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-$(CONFIG_CMD_BOOTZ) += bootm.o diff --git a/arch/sandbox/lib/bootm.c b/arch/sandbox/lib/bootm.c index 8dbcd9ff7dd..44ba8b52e13 100644 --- a/arch/sandbox/lib/bootm.c +++ b/arch/sandbox/lib/bootm.c @@ -85,5 +85,7 @@ int do_bootm_linux(int flag, struct bootm_info *bmi) int booti_setup(ulong image, ulong *relocated_addr, ulong *size, bool force_reloc) { - return 0; + log_err("Booting is not supported on the sandbox.\n"); + + return 1; } diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index e7520a328d5..8c3c30293a3 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -6,7 +6,7 @@ extra-y += start.o obj-y += board.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-y += time.o obj-$(CONFIG_CMD_SH_ZIMAGEBOOT) += zimageboot.o diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 99e59d94c60..23a1e21b29e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -723,6 +723,14 @@ config ROM_TABLE_SIZE hex default 0x10000 +config X86_HARDFP + bool "Support hardware floating point" + help + U-Boot generally does not make use of floating point. Where this is + needed, it can be enabled using this option. This adjusts the + start-up code for 64-bit mode and changes the compiler options for + 64-bit to enable SSE. + config HAVE_ITSS bool "Enable ITSS" help @@ -1053,4 +1061,12 @@ config SPL_COREBOOT_SYSINFO display, memory and build information. It is stored in struct sysinfo_t after parsing by get_coreboot_info(). +config ZBOOT + bool "Support the zImage format" + default y + help + Enable this to support booting the x86-specific zImage format. This + uses a special, binary format containing information about the Linux + format to boot. + endmenu diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 26ec1af2f0b..2e3a7119e79 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -27,9 +27,13 @@ ifeq ($(IS_32BIT),y) PLATFORM_CPPFLAGS += -march=i386 -m32 else PLATFORM_CPPFLAGS += $(if $(CONFIG_SPL_BUILD),,-fpic) -fno-common -march=core2 -m64 + +ifndef CONFIG_X86_HARDFP PLATFORM_CPPFLAGS += -mno-mmx -mno-sse endif +endif # IS_32BIT + PLATFORM_RELFLAGS += -fdata-sections -ffunction-sections -fvisibility=hidden KBUILD_LDFLAGS += -Bsymbolic -Bsymbolic-functions diff --git a/arch/x86/cpu/x86_64/cpu.c b/arch/x86/cpu/x86_64/cpu.c index 2647bff891f..5ea746ecce4 100644 --- a/arch/x86/cpu/x86_64/cpu.c +++ b/arch/x86/cpu/x86_64/cpu.c @@ -10,6 +10,7 @@ #include <init.h> #include <asm/cpu.h> #include <asm/global_data.h> +#include <asm/processor-flags.h> DECLARE_GLOBAL_DATA_PTR; @@ -39,11 +40,22 @@ int x86_mp_init(void) return 0; } +/* enable SSE features for hardware floating point */ +static void setup_sse_features(void) +{ + asm ("mov %%cr4, %%rax\n" \ + "or %0, %%rax\n" \ + "mov %%rax, %%cr4\n" \ + : : "i" (X86_CR4_OSFXSR | X86_CR4_OSXMMEXCPT) : "eax"); +} + int x86_cpu_reinit_f(void) { /* set the vendor to Intel so that native_calibrate_tsc() works */ gd->arch.x86_vendor = X86_VENDOR_INTEL; gd->arch.has_mtrr = true; + if (IS_ENABLED(CONFIG_X86_HARDFP)) + setup_sse_features(); return 0; } diff --git a/arch/x86/dts/coreboot.dts b/arch/x86/dts/coreboot.dts index dfce7c2d591..b867468e16c 100644 --- a/arch/x86/dts/coreboot.dts +++ b/arch/x86/dts/coreboot.dts @@ -46,6 +46,16 @@ compatible = "coreboot-fb"; }; + bootstd { + compatible = "u-boot,boot-std"; + + theme { + font-size = <30>; + menu-inset = <3>; + menuitem-gap-y = <1>; + }; + }; + sysinfo { compatible = "coreboot,sysinfo"; }; diff --git a/arch/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h index 655675b6661..8b542605170 100644 --- a/arch/x86/include/asm/zimage.h +++ b/arch/x86/include/asm/zimage.h @@ -30,6 +30,78 @@ #define BZIMAGE_LOAD_ADDR 0x100000 #define ZIMAGE_LOAD_ADDR 0x10000 +enum { + ZBOOT_STATE_START = BIT(0), + ZBOOT_STATE_LOAD = BIT(1), + ZBOOT_STATE_SETUP = BIT(2), + ZBOOT_STATE_INFO = BIT(3), + ZBOOT_STATE_GO = BIT(4), + + /* This one doesn't execute automatically, so stop the count before 5 */ + ZBOOT_STATE_DUMP = BIT(5), + ZBOOT_STATE_COUNT = 5, +}; + +/** + * struct zboot_state - Current state of the boot + * + * @bzimage_addr: Address of the bzImage to boot, or 0 if the image has already + * been loaded and does not exist (as a cohesive whole) in memory + * @bzimage_size: Size of the bzImage, or 0 to detect this + * @initrd_addr: Address of the initial ramdisk, or 0 if none + * @initrd_size: Size of the initial ramdisk, or 0 if none + * @load_address: Address where the bzImage is moved before booting, either + * BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR + * This is set up when loading the zimage + * @base_ptr: Pointer to the boot parameters, typically at address + * DEFAULT_SETUP_BASE + * This is set up when loading the zimage + * @cmdline: Environment variable containing the 'override' command line, or + * NULL to use the one in the setup block + */ +struct zboot_state { + ulong bzimage_addr; + ulong bzimage_size; + ulong initrd_addr; + ulong initrd_size; + ulong load_address; + struct boot_params *base_ptr; + const char *cmdline; +}; + +extern struct zboot_state state; + +/** + * zimage_dump() - Dump information about a zimage + * + * @base_ptr: Pointer to the boot parameters + * @show_cmdline: true to show the kernel command line + */ +void zimage_dump(struct boot_params *base_ptr, bool show_cmdline); + +/** + * zboot_load() - Load a zimage + * + * Load the zimage into the correct place + * + * Return: 0 if OK, -ve on error + */ +int zboot_load(void); + +/** + * zboot_setup() - Set up the zboot image reeady for booting + * + * Return: 0 if OK, -ve on error + */ +int zboot_setup(void); + +/** + * zboot_go() - Start the image + * + * Return: 0 if OK, -ve on error + */ +int zboot_go(void); + /** * load_zimage() - Load a zImage or bzImage * @@ -62,4 +134,29 @@ struct boot_params *load_zimage(char *image, unsigned long kernel_size, int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, ulong initrd_addr, ulong initrd_size, ulong cmdline_force); +/** + * zboot_start() - Prepare to boot a zimage + * + * Record information about a zimage so it can be booted + * + * @bzimage_addr: Address of the bzImage to boot + * @bzimage_size: Size of the bzImage, or 0 to detect this + * @initrd_addr: Address of the initial ramdisk, or 0 if none + * @initrd_size: Size of the initial ramdisk, or 0 if none + * @base_addr: If non-zero, this indicates that the boot parameters have already + * been loaded by the caller to this address, so the load_zimage() call + * in zboot_load() will be skipped when booting + * @cmdline: Environment variable containing the 'override' command line, or + * NULL to use the one in the setup block + */ +void zboot_start(ulong bzimage_addr, ulong bzimage_size, ulong initrd_addr, + ulong initrd_size, ulong base_addr, const char *cmdline); + +/** + * zboot_info() - Show simple info about a zimage + * + * Shows wherer the kernel was loaded and also the setup base + */ +void zboot_info(void); + #endif diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 90a7618ecfd..94aa335ede4 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_X86_32BIT_INIT) += string.o endif ifndef CONFIG_SPL_BUILD -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o endif obj-y += cmd_boot.o obj-$(CONFIG_$(SPL_)COREBOOT_SYSINFO) += coreboot/ @@ -48,7 +48,7 @@ obj-$(CONFIG_$(SPL_TPL_)GENERATE_ACPI_TABLE) += acpi_table.o endif obj-y += tables.o ifndef CONFIG_SPL_BUILD -obj-$(CONFIG_CMD_ZBOOT) += zimage.o +obj-$(CONFIG_ZBOOT) += zimage.o endif obj-$(CONFIG_USE_HOB) += hob.o ifndef CONFIG_TPL_BUILD diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index c15f11f8cdf..4e4cf18dec5 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -283,7 +283,7 @@ void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) { int ret; - printf("Jumping to 64-bit U-Boot: Note many features are missing\n"); + printf("Jumping to 64-bit U-Boot\n"); ret = cpu_jump_to_64bit_uboot(spl_image->entry_point); debug("ret=%d\n", ret); hang(); diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index a41e1ccf8a6..d7403876c13 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -56,41 +56,8 @@ DECLARE_GLOBAL_DATA_PTR; #define COMMAND_LINE_SIZE 2048 -/** - * struct zboot_state - Current state of the boot - * - * @bzimage_addr: Address of the bzImage to boot - * @bzimage_size: Size of the bzImage, or 0 to detect this - * @initrd_addr: Address of the initial ramdisk, or 0 if none - * @initrd_size: Size of the initial ramdisk, or 0 if none - * @load_address: Address where the bzImage is moved before booting, either - * BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR - * @base_ptr: Pointer to the boot parameters, typically at address - * DEFAULT_SETUP_BASE - * @cmdline: Environment variable containing the 'override' command line, or - * NULL to use the one in the setup block - */ -struct zboot_state { - ulong bzimage_addr; - ulong bzimage_size; - ulong initrd_addr; - ulong initrd_size; - ulong load_address; - struct boot_params *base_ptr; - char *cmdline; -} state; - -enum { - ZBOOT_STATE_START = BIT(0), - ZBOOT_STATE_LOAD = BIT(1), - ZBOOT_STATE_SETUP = BIT(2), - ZBOOT_STATE_INFO = BIT(3), - ZBOOT_STATE_GO = BIT(4), - - /* This one doesn't execute automatically, so stop the count before 5 */ - ZBOOT_STATE_DUMP = BIT(5), - ZBOOT_STATE_COUNT = 5, -}; +/* Current state of the boot */ +struct zboot_state state; static void build_command_line(char *command_line, int auto_boot) { @@ -400,56 +367,10 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, return 0; } -static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - const char *s; - - memset(&state, '\0', sizeof(state)); - if (argc >= 2) { - /* argv[1] holds the address of the bzImage */ - s = argv[1]; - } else { - s = env_get("fileaddr"); - } - - if (s) - state.bzimage_addr = hextoul(s, NULL); - - if (argc >= 3) { - /* argv[2] holds the size of the bzImage */ - state.bzimage_size = hextoul(argv[2], NULL); - } - - if (argc >= 4) - state.initrd_addr = hextoul(argv[3], NULL); - if (argc >= 5) - state.initrd_size = hextoul(argv[4], NULL); - if (argc >= 6) { - /* - * When the base_ptr is passed in, we assume that the image is - * already loaded at the address given by argv[1] and therefore - * the original bzImage is somewhere else, or not accessible. - * In any case, we don't need access to the bzImage since all - * the processing is assumed to be done. - * - * So set the base_ptr to the given address, use this arg as the - * load address and set bzimage_addr to 0 so we know that it - * cannot be proceesed (or processed again). - */ - state.base_ptr = (void *)hextoul(argv[5], NULL); - state.load_address = state.bzimage_addr; - state.bzimage_addr = 0; - } - if (argc >= 7) - state.cmdline = env_get(argv[6]); - - return 0; -} - -static int zboot_load(void) +int zboot_load(void) { struct boot_params *base_ptr; + int ret; if (state.base_ptr) { struct boot_params *from = (struct boot_params *)state.base_ptr; @@ -469,23 +390,16 @@ static int zboot_load(void) } state.base_ptr = base_ptr; - return 0; -} - -static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - if (zboot_load()) - return CMD_RET_FAILURE; - - if (env_set_hex("zbootbase", map_to_sysmem(state.base_ptr)) || - env_set_hex("zbootaddr", state.load_address)) - return CMD_RET_FAILURE; + ret = env_set_hex("zbootbase", map_to_sysmem(state.base_ptr)); + if (!ret) + ret = env_set_hex("zbootaddr", state.load_address); + if (ret) + return ret; return 0; } -static int zboot_setup(void) +int zboot_setup(void) { struct boot_params *base_ptr = state.base_ptr; int ret; @@ -499,33 +413,7 @@ static int zboot_setup(void) return 0; } -static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - struct boot_params *base_ptr = state.base_ptr; - - if (!base_ptr) { - printf("base is not set: use 'zboot load' first\n"); - return CMD_RET_FAILURE; - } - if (zboot_setup()) { - puts("Setting up boot parameters failed ...\n"); - return CMD_RET_FAILURE; - } - - return 0; -} - -static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - printf("Kernel loaded at %08lx, setup_base=%p\n", - state.load_address, state.base_ptr); - - return 0; -} - -static int zboot_go(void) +int zboot_go(void) { struct boot_params *params = state.base_ptr; struct setup_header *hdr = ¶ms->hdr; @@ -549,35 +437,12 @@ static int zboot_go(void) return ret; } -static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +int zboot_run(ulong addr, ulong size, ulong initrd, ulong initrd_size, + ulong base, char *cmdline) { int ret; - ret = zboot_go(); - printf("Kernel returned! (err=%d)\n", ret); - - return CMD_RET_FAILURE; -} - -int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size, - ulong base, char *cmdline) -{ - int ret; - - memset(&state, '\0', sizeof(state)); - - if (base) { - state.base_ptr = map_sysmem(base, 0); - state.load_address = addr; - } else { - state.bzimage_addr = addr; - } - state.bzimage_size = size; - state.initrd_addr = initrd; - state.initrd_size = initrd_size; - state.cmdline = cmdline; - + zboot_start(addr, size, initrd, initrd_size, base, cmdline); ret = zboot_load(); if (ret) return log_msg_ret("ld", ret); @@ -586,7 +451,7 @@ int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size, return log_msg_ret("set", ret); ret = zboot_go(); if (ret) - return log_msg_ret("set", ret); + return log_msg_ret("go", ret); return -EFAULT; } @@ -776,97 +641,25 @@ void zimage_dump(struct boot_params *base_ptr, bool show_cmdline) print_num("Kernel info offset", hdr->kernel_info_offset); } -static int do_zboot_dump(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +void zboot_start(ulong bzimage_addr, ulong bzimage_size, ulong initrd_addr, + ulong initrd_size, ulong base_addr, const char *cmdline) { - struct boot_params *base_ptr = state.base_ptr; - - if (argc > 1) - base_ptr = (void *)hextoul(argv[1], NULL); - if (!base_ptr) { - printf("No zboot setup_base\n"); - return CMD_RET_FAILURE; - } - zimage_dump(base_ptr, true); - - return 0; -} - -/* Note: This defines the complete_zboot() function */ -U_BOOT_SUBCMDS(zboot, - U_BOOT_CMD_MKENT(start, 8, 1, do_zboot_start, "", ""), - U_BOOT_CMD_MKENT(load, 1, 1, do_zboot_load, "", ""), - U_BOOT_CMD_MKENT(setup, 1, 1, do_zboot_setup, "", ""), - U_BOOT_CMD_MKENT(info, 1, 1, do_zboot_info, "", ""), - U_BOOT_CMD_MKENT(go, 1, 1, do_zboot_go, "", ""), - U_BOOT_CMD_MKENT(dump, 2, 1, do_zboot_dump, "", ""), -) - -int do_zboot_states(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], int state_mask) -{ - int i; - - for (i = 0; i < ZBOOT_STATE_COUNT; i++) { - struct cmd_tbl *cmd = &zboot_subcmds[i]; - int mask = 1 << i; - int ret; + memset(&state, '\0', sizeof(state)); - if (mask & state_mask) { - ret = cmd->cmd(cmd, flag, argc, argv); - if (ret) - return ret; - } + state.bzimage_size = bzimage_size; + state.initrd_addr = initrd_addr; + state.initrd_size = initrd_size; + if (base_addr) { + state.base_ptr = map_sysmem(base_addr, 0); + state.load_address = bzimage_addr; + } else { + state.bzimage_addr = bzimage_addr; } - - return 0; + state.cmdline = cmdline; } -int do_zboot_parent(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[], int *repeatable) +void zboot_info(void) { - /* determine if we have a sub command */ - if (argc > 1) { - char *endp; - - hextoul(argv[1], &endp); - /* - * endp pointing to nul means that argv[1] was just a valid - * number, so pass it along to the normal processing - */ - if (*endp) - return do_zboot(cmdtp, flag, argc, argv, repeatable); - } - - do_zboot_states(cmdtp, flag, argc, argv, ZBOOT_STATE_START | - ZBOOT_STATE_LOAD | ZBOOT_STATE_SETUP | - ZBOOT_STATE_INFO | ZBOOT_STATE_GO); - - return CMD_RET_FAILURE; + printf("Kernel loaded at %08lx, setup_base=%p\n", + state.load_address, state.base_ptr); } - -U_BOOT_CMDREP_COMPLETE( - zboot, 8, do_zboot_parent, "Boot bzImage", - "[addr] [size] [initrd addr] [initrd size] [setup] [cmdline]\n" - " addr - The optional starting address of the bzimage.\n" - " If not set it defaults to the environment\n" - " variable \"fileaddr\".\n" - " size - The optional size of the bzimage. Defaults to\n" - " zero.\n" - " initrd addr - The address of the initrd image to use, if any.\n" - " initrd size - The size of the initrd image to use, if any.\n" - " setup - The address of the kernel setup region, if this\n" - " is not at addr\n" - " cmdline - Environment variable containing the kernel\n" - " command line, to override U-Boot's normal\n" - " cmdline generation\n" - "\n" - "Sub-commands to do part of the zboot sequence:\n" - "\tstart [addr [arg ...]] - specify arguments\n" - "\tload - load OS image\n" - "\tsetup - set up table\n" - "\tinfo - show summary info\n" - "\tgo - start OS\n" - "\tdump [addr] - dump info (optional address of boot params)", - complete_zboot -); diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile index ad4fe32cb69..bb9157f30f0 100644 --- a/arch/xtensa/lib/Makefile +++ b/arch/xtensa/lib/Makefile @@ -3,6 +3,6 @@ # (C) Copyright 2007 - 2013 Tensilica Inc. # (C) Copyright 2014 - 2016 Cadence Design Systems Inc. -obj-$(CONFIG_CMD_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM) += bootm.o obj-y += cache.o misc.o relocate.o time.o diff --git a/board/emulation/qemu-riscv/qemu-riscv.c b/board/emulation/qemu-riscv/qemu-riscv.c index 181abbbf97d..173245b40e3 100644 --- a/board/emulation/qemu-riscv/qemu-riscv.c +++ b/board/emulation/qemu-riscv/qemu-riscv.c @@ -31,12 +31,6 @@ int is_flash_available(void) int board_init(void) { - /* - * Make sure virtio bus is enumerated so that peripherals - * on the virtio bus can be discovered by their drivers - */ - virtio_init(); - return 0; } @@ -46,6 +40,12 @@ int board_late_init(void) if (CONFIG_IS_ENABLED(USB_KEYBOARD)) usb_init(); + /* + * Make sure virtio bus is enumerated so that peripherals + * on the virtio bus can be discovered by their drivers + */ + virtio_init(); + return 0; } diff --git a/board/emulation/qemu-x86/Kconfig b/board/emulation/qemu-x86/Kconfig index 9a0611820ce..b2a4e0891a4 100644 --- a/board/emulation/qemu-x86/Kconfig +++ b/board/emulation/qemu-x86/Kconfig @@ -18,7 +18,8 @@ config BOARD_SPECIFIC_OPTIONS # dummy select X86_RESET_VECTOR select QEMU select QFW_PIO if CMD_QFW - select BOARD_ROMSIZE_KB_1024 + select BOARD_ROMSIZE_KB_1024 if TARGET_QEMU_X86 + select BOARD_ROMSIZE_KB_2048 if TARGET_QEMU_X86_64 imply VIRTIO_PCI imply VIRTIO_NET imply VIRTIO_BLK diff --git a/board/phytec/phycore_am62x/phycore-am62x.c b/board/phytec/phycore_am62x/phycore-am62x.c index 91a24018c40..618b4c370d1 100644 --- a/board/phytec/phycore_am62x/phycore-am62x.c +++ b/board/phytec/phycore_am62x/phycore-am62x.c @@ -57,3 +57,67 @@ void spl_board_init(void) MCU_CTRL_DEVICE_CLKOUT_32K_CTRL); } #endif + +#if IS_ENABLED(CONFIG_ENV_IS_IN_FAT) || IS_ENABLED(CONFIG_ENV_IS_IN_MMC) +int mmc_get_env_dev(void) +{ + u32 boot_device = get_boot_device(); + + switch (boot_device) { + case BOOT_DEVICE_MMC1: + return 0; + case BOOT_DEVICE_MMC2: + return 1; + }; + + return CONFIG_SYS_MMC_ENV_DEV; +} +#endif + +enum env_location env_get_location(enum env_operation op, int prio) +{ + u32 boot_device = get_boot_device(); + + if (prio) + return ENVL_UNKNOWN; + + switch (boot_device) { + case BOOT_DEVICE_MMC1: + case BOOT_DEVICE_MMC2: + if (CONFIG_IS_ENABLED(ENV_IS_IN_FAT)) + return ENVL_FAT; + if (CONFIG_IS_ENABLED(ENV_IS_IN_MMC)) + return ENVL_MMC; + case BOOT_DEVICE_SPI: + if (CONFIG_IS_ENABLED(ENV_IS_IN_SPI_FLASH)) + return ENVL_SPI_FLASH; + default: + return ENVL_NOWHERE; + }; +} + +#if IS_ENABLED(CONFIG_BOARD_LATE_INIT) +int board_late_init(void) +{ + u32 boot_device = get_boot_device(); + + switch (boot_device) { + case BOOT_DEVICE_MMC1: + env_set_ulong("mmcdev", 0); + env_set("boot", "mmc"); + break; + case BOOT_DEVICE_MMC2: + env_set_ulong("mmcdev", 1); + env_set("boot", "mmc"); + break; + case BOOT_DEVICE_SPI: + env_set("boot", "spi"); + break; + case BOOT_DEVICE_ETHERNET: + env_set("boot", "net"); + break; + }; + + return 0; +} +#endif diff --git a/board/sophgo/milkv_duo/Kconfig b/board/sophgo/milkv_duo/Kconfig index 2a458f291cc..040a7487f1b 100644 --- a/board/sophgo/milkv_duo/Kconfig +++ b/board/sophgo/milkv_duo/Kconfig @@ -7,7 +7,7 @@ config SYS_VENDOR default "sophgo" config SYS_CPU - default "generic" + default "cv1800b" config SYS_CONFIG_NAME default "milkv_duo" @@ -23,6 +23,6 @@ config ENV_SECT_SIZE config BOARD_SPECIFIC_OPTIONS def_bool y - select GENERIC_RISCV + select SOPHGO_CV1800B endif diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c index 1b49945d11b..45848db6d8b 100644 --- a/board/starfive/visionfive2/spl.c +++ b/board/starfive/visionfive2/spl.c @@ -4,7 +4,6 @@ * Author: Yanhong Wang<yanhong.wang@starfivetech.com> */ -#include <common.h> #include <asm/arch/eeprom.h> #include <asm/arch/gpio.h> #include <asm/arch/regs.h> @@ -27,6 +26,26 @@ struct starfive_vf2_pro { const char *value; }; +static const struct starfive_vf2_pro milk_v_mars[] = { + {"/soc/ethernet@16030000", "starfive,tx-use-rgmii-clk", NULL}, + {"/soc/ethernet@16040000", "starfive,tx-use-rgmii-clk", NULL}, + + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-adj-enabled", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-100-inverted", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,tx-clk-1000-inverted", NULL}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,rx-clk-drv-microamp", "3970"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "motorcomm,rx-data-drv-microamp", "2910"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "rx-internal-delay-ps", "1900"}, + {"/soc/ethernet@16030000/mdio/ethernet-phy@0", + "tx-internal-delay-ps", "1500"}, +}; + static const struct starfive_vf2_pro starfive_vera[] = { {"/soc/ethernet@16030000/mdio/ethernet-phy@0", "rx-internal-delay-ps", "1900"}, @@ -67,6 +86,49 @@ static const struct starfive_vf2_pro starfive_verb[] = { "tx-internal-delay-ps", "0"}, }; +void spl_fdt_fixup_mars(void *fdt) +{ + static const char compat[] = "milkv,mars\0starfive,jh7110"; + u32 phandle; + u8 i; + int offset; + int ret; + + fdt_setprop(fdt, fdt_path_offset(fdt, "/"), "compatible", compat, sizeof(compat)); + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/"), "model", + "Milk-V Mars"); + + /* gmac0 */ + offset = fdt_path_offset(fdt, "/soc/clock-controller@17000000"); + phandle = fdt_get_phandle(fdt, offset); + offset = fdt_path_offset(fdt, "/soc/ethernet@16030000"); + + fdt_setprop_u32(fdt, offset, "assigned-clocks", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clocks", JH7110_AONCLK_GMAC0_TX); + fdt_setprop_u32(fdt, offset, "assigned-clock-parents", phandle); + fdt_appendprop_u32(fdt, offset, "assigned-clock-parents", + JH7110_AONCLK_GMAC0_RMII_RTX); + + /* gmac1 */ + fdt_setprop_string(fdt, fdt_path_offset(fdt, "/soc/ethernet@16040000"), + "status", "disabled"); + + for (i = 0; i < ARRAY_SIZE(milk_v_mars); i++) { + offset = fdt_path_offset(fdt, milk_v_mars[i].path); + + if (milk_v_mars[i].value) + ret = fdt_setprop_u32(fdt, offset, milk_v_mars[i].name, + dectoul(milk_v_mars[i].value, NULL)); + else + ret = fdt_setprop_empty(fdt, offset, milk_v_mars[i].name); + + if (ret) { + pr_err("%s set prop %s fail.\n", __func__, milk_v_mars[i].name); + break; + } + } +} + void spl_fdt_fixup_version_a(void *fdt) { static const char compat[] = "starfive,visionfive-2-v1.2a\0starfive,jh7110"; @@ -167,22 +229,34 @@ void spl_fdt_fixup_version_b(void *fdt) void spl_perform_fixups(struct spl_image_info *spl_image) { u8 version; + const char *product_id; - version = get_pcb_revision_from_eeprom(); - switch (version) { - case 'a': - case 'A': - spl_fdt_fixup_version_a(spl_image->fdt_addr); - break; - - case 'b': - case 'B': - default: - spl_fdt_fixup_version_b(spl_image->fdt_addr); + product_id = get_product_id_from_eeprom(); + if (!product_id) { + pr_err("Can't read EEPROM\n"); + return; + } + if (!strncmp(product_id, "MARS", 4)) { + spl_fdt_fixup_mars(spl_image->fdt_addr); + } else if (!strncmp(product_id, "VF7110", 6)) { + version = get_pcb_revision_from_eeprom(); + switch (version) { + case 'a': + case 'A': + spl_fdt_fixup_version_a(spl_image->fdt_addr); + break; + + case 'b': + case 'B': + default: + spl_fdt_fixup_version_b(spl_image->fdt_addr); break; + }; + } else { + pr_err("Unknown product %s\n", product_id); }; - /* Update the memory size which read form eeprom or DT */ + /* Update the memory size which read from eeprom or DT */ fdt_fixup_memory(spl_image->fdt_addr, 0x40000000, gd->ram_size); } diff --git a/board/starfive/visionfive2/starfive_visionfive2.c b/board/starfive/visionfive2/starfive_visionfive2.c index 78e118d5a05..a86bca533b2 100644 --- a/board/starfive/visionfive2/starfive_visionfive2.c +++ b/board/starfive/visionfive2/starfive_visionfive2.c @@ -4,11 +4,11 @@ * Author: Yanhong Wang<yanhong.wang@starfivetech.com> */ -#include <common.h> #include <cpu_func.h> #include <dm.h> #include <fdt_support.h> #include <env.h> +#include <log.h> #include <asm/arch/eeprom.h> #include <asm/io.h> #include <asm/sections.h> @@ -17,6 +17,8 @@ DECLARE_GLOBAL_DATA_PTR; #define JH7110_L2_PREFETCHER_BASE_ADDR 0x2030000 #define JH7110_L2_PREFETCHER_HART_OFFSET 0x2000 +#define FDTFILE_MILK_V_MARS \ + "starfive/jh7110-milkv-mars.dtb" #define FDTFILE_VISIONFIVE2_1_2A \ "starfive/jh7110-starfive-visionfive-2-v1.2a.dtb" #define FDTFILE_VISIONFIVE2_1_3B \ @@ -48,20 +50,38 @@ static void set_fdtfile(void) { u8 version; const char *fdtfile; + const char *product_id; - version = get_pcb_revision_from_eeprom(); - switch (version) { - case 'a': - case 'A': - fdtfile = FDTFILE_VISIONFIVE2_1_2A; - break; - - case 'b': - case 'B': - default: - fdtfile = FDTFILE_VISIONFIVE2_1_3B; - break; - }; + fdtfile = env_get("fdtfile"); + if (fdtfile) + return; + + product_id = get_product_id_from_eeprom(); + if (!product_id) { + log_err("Can't read EEPROM\n"); + return; + } + if (!strncmp(product_id, "MARS", 4)) { + fdtfile = FDTFILE_MILK_V_MARS; + } else if (!strncmp(product_id, "VF7110", 6)) { + version = get_pcb_revision_from_eeprom(); + + switch (version) { + case 'a': + case 'A': + fdtfile = FDTFILE_VISIONFIVE2_1_2A; + break; + + case 'b': + case 'B': + default: + fdtfile = FDTFILE_VISIONFIVE2_1_3B; + break; + } + } else { + log_err("Unknown product\n"); + return; + } env_set("fdtfile", fdtfile); } diff --git a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c index c36de1a5125..ddef7d61235 100644 --- a/board/starfive/visionfive2/visionfive2-i2c-eeprom.c +++ b/board/starfive/visionfive2/visionfive2-i2c-eeprom.c @@ -4,7 +4,6 @@ * Author: Yanhong Wang<yanhong.wang@starfivetech.com> */ -#include <common.h> #include <command.h> #include <env.h> #include <i2c.h> @@ -405,6 +404,14 @@ static void set_product_id(char *string) update_crc(); } +const char *get_product_id_from_eeprom(void) +{ + if (read_eeprom()) + return NULL; + + return pbuf.eeprom.atom1.data.pstr; +} + int do_mac(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { char *cmd; diff --git a/board/toradex/verdin-am62/MAINTAINERS b/board/toradex/verdin-am62/MAINTAINERS index 4e75980dbd7..3e30d1d5112 100644 --- a/board/toradex/verdin-am62/MAINTAINERS +++ b/board/toradex/verdin-am62/MAINTAINERS @@ -1,12 +1,8 @@ Verdin AM62 F: arch/arm/dts/k3-am625-verdin-lpddr4-1600MTs.dtsi F: arch/arm/dts/k3-am625-verdin-r5.dts -F: arch/arm/dts/k3-am625-verdin-wifi-dev.dts F: arch/arm/dts/k3-am625-verdin-wifi-dev-binman.dtsi F: arch/arm/dts/k3-am625-verdin-wifi-dev-u-boot.dtsi -F: arch/arm/dts/k3-am62-verdin-dev.dtsi -F: arch/arm/dts/k3-am62-verdin.dtsi -F: arch/arm/dts/k3-am62-verdin-wifi.dtsi F: board/toradex/verdin-am62/ F: configs/verdin-am62_a53_defconfig F: configs/verdin-am62_r5_defconfig diff --git a/board/xilinx/Kconfig b/board/xilinx/Kconfig index 843198fa0da..5c4ad8f1df9 100644 --- a/board/xilinx/Kconfig +++ b/board/xilinx/Kconfig @@ -45,6 +45,7 @@ config XILINX_OF_BOARD_DTB_ADDR default 0x1000 if ARCH_VERSAL || ARCH_VERSAL_NET default 0x8000 if MICROBLAZE default 0x100000 if ARCH_ZYNQ || ARCH_ZYNQMP + default 0x23000000 if TARGET_XILINX_MBV depends on OF_BOARD || OF_SEPARATE help Offset in the memory where the board configuration DTB is placed. diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c index 9641ed307b7..b47d2d23f91 100644 --- a/board/xilinx/common/board.c +++ b/board/xilinx/common/board.c @@ -12,6 +12,7 @@ #include <env.h> #include <image.h> #include <init.h> +#include <jffs2/load_kernel.h> #include <lmb.h> #include <log.h> #include <asm/global_data.h> @@ -20,6 +21,7 @@ #include <i2c.h> #include <linux/sizes.h> #include <malloc.h> +#include <mtd_node.h> #include "board.h" #include <dm.h> #include <i2c_eeprom.h> @@ -43,7 +45,7 @@ struct efi_fw_image fw_images[] = { .image_index = 1, }, #endif -#if defined(XILINX_UBOOT_IMAGE_GUID) +#if defined(XILINX_UBOOT_IMAGE_GUID) && defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) { .image_type_id = XILINX_UBOOT_IMAGE_GUID, .fw_name = u"XILINX-UBOOT", @@ -103,10 +105,14 @@ static void xilinx_eeprom_legacy_cleanup(char *eeprom, int size) for (i = 0; i < size; i++) { byte = eeprom[i]; - /* Remove all non printable chars but ignore MAC address */ - if ((i < offsetof(struct xilinx_legacy_format, eth_mac) || - i >= offsetof(struct xilinx_legacy_format, unused1)) && - (byte < '!' || byte > '~')) { + /* Ignore MAC address */ + if (i >= offsetof(struct xilinx_legacy_format, eth_mac) && + i < offsetof(struct xilinx_legacy_format, unused1)) { + continue; + } + + /* Remove all non printable chars */ + if (byte < '!' || byte > '~') { eeprom[i] = 0; continue; } @@ -358,6 +364,14 @@ void *board_fdt_blob_setup(int *err) void *fdt_blob; *err = 0; + + if (IS_ENABLED(CONFIG_TARGET_XILINX_MBV)) { + fdt_blob = (void *)CONFIG_XILINX_OF_BOARD_DTB_ADDR; + + if (fdt_magic(fdt_blob) == FDT_MAGIC) + return fdt_blob; + } + if (!IS_ENABLED(CONFIG_SPL_BUILD) && !IS_ENABLED(CONFIG_VERSAL_NO_DDR) && !IS_ENABLED(CONFIG_ZYNQMP_NO_DDR)) { @@ -693,6 +707,13 @@ int ft_board_setup(void *blob, struct bd_info *bd) u8 buf[MAX_RAND_SIZE]; int nodeoffset, ret; + static const struct node_info nodes[] = { + { "arm,pl353-nand-r2p1", MTD_DEV_TYPE_NAND, }, + }; + + if (IS_ENABLED(CONFIG_FDT_FIXUP_PARTITIONS) && IS_ENABLED(CONFIG_NAND_ZYNQ)) + fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes)); + if (uclass_get_device(UCLASS_RNG, 0, &dev) || !dev) { debug("No RNG device\n"); return 0; diff --git a/board/xilinx/mbv/Kconfig b/board/xilinx/mbv/Kconfig index d2dec397ed6..a3a6f212577 100644 --- a/board/xilinx/mbv/Kconfig +++ b/board/xilinx/mbv/Kconfig @@ -10,15 +10,25 @@ config SYS_CPU default "generic" config TEXT_BASE - default 0x80000000 if !RISCV_SMODE - default 0x80400000 if RISCV_SMODE && ARCH_RV32I + default 0x21200000 + +config SPL_TEXT_BASE + default 0x20000000 + +config SPL_OPENSBI_LOAD_ADDR + hex + default 0x20200000 config BOARD_SPECIFIC_OPTIONS def_bool y select GENERIC_RISCV + select SUPPORT_SPL imply BOARD_LATE_INIT + imply SPL_RAM_SUPPORT + imply SPL_RAM_DEVICE imply CMD_SBI imply CMD_PING + imply OF_HAS_PRIOR_STAGE source "board/xilinx/Kconfig" diff --git a/board/xilinx/mbv/board.c b/board/xilinx/mbv/board.c index ccf4395d6ac..c478f7e04a0 100644 --- a/board/xilinx/mbv/board.c +++ b/board/xilinx/mbv/board.c @@ -5,7 +5,17 @@ * Michal Simek <michal.simek@amd.com> */ +#include <spl.h> + int board_init(void) { return 0; } + +#ifdef CONFIG_SPL +u32 spl_boot_device(void) +{ + /* RISC-V QEMU only supports RAM as SPL boot device */ + return BOOT_DEVICE_RAM; +} +#endif diff --git a/board/xilinx/versal-net/board.c b/board/xilinx/versal-net/board.c index 990ca1650aa..da03024e162 100644 --- a/board/xilinx/versal-net/board.c +++ b/board/xilinx/versal-net/board.c @@ -371,3 +371,35 @@ int dram_init(void) void reset_cpu(void) { } + +#if defined(CONFIG_ENV_IS_NOWHERE) +enum env_location env_get_location(enum env_operation op, int prio) +{ + u8 bootmode = versal_net_get_bootmode(); + + if (prio) + return ENVL_UNKNOWN; + + switch (bootmode) { + case EMMC_MODE: + case SD_MODE: + case SD1_LSHFT_MODE: + case SD_MODE1: + if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT)) + return ENVL_FAT; + if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4)) + return ENVL_EXT4; + return ENVL_NOWHERE; + case OSPI_MODE: + case QSPI_MODE_24BIT: + case QSPI_MODE_32BIT: + if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH)) + return ENVL_SPI_FLASH; + return ENVL_NOWHERE; + case JTAG_MODE: + case SELECTMAP_MODE: + default: + return ENVL_NOWHERE; + } +} +#endif diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c index 8c2e614ad8a..4f6d56119db 100644 --- a/board/xilinx/versal/board.c +++ b/board/xilinx/versal/board.c @@ -291,6 +291,7 @@ void reset_cpu(void) { } +#if defined(CONFIG_ENV_IS_NOWHERE) enum env_location env_get_location(enum env_operation op, int prio) { u32 bootmode = versal_get_bootmode(); @@ -320,3 +321,4 @@ enum env_location env_get_location(enum env_operation op, int prio) return ENVL_NOWHERE; } } +#endif diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index ba49eb7be22..f370fb7347a 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -588,6 +588,7 @@ int mmc_get_env_dev(void) return bootseq; } +#if defined(CONFIG_ENV_IS_NOWHERE) enum env_location env_get_location(enum env_operation op, int prio) { u32 bootmode = zynqmp_get_bootmode(); @@ -621,11 +622,37 @@ enum env_location env_get_location(enum env_operation op, int prio) return ENVL_NOWHERE; } } +#endif #if defined(CONFIG_SET_DFU_ALT_INFO) #define DFU_ALT_BUF_LEN SZ_1K +static void mtd_found_part(u32 *base, u32 *size) +{ + struct mtd_info *part, *mtd; + + mtd_probe_devices(); + + mtd = get_mtd_device_nm("nor0"); + if (!IS_ERR_OR_NULL(mtd)) { + list_for_each_entry(part, &mtd->partitions, node) { + debug("0x%012llx-0x%012llx : \"%s\"\n", + part->offset, part->offset + part->size, + part->name); + + if (*base >= part->offset && + *base < part->offset + part->size) { + debug("Found my partition: %d/%s\n", + part->index, part->name); + *base = part->offset; + *size = part->size; + break; + } + } + } +} + void set_dfu_alt_info(char *interface, char *devstr) { int multiboot, bootseq = 0, len = 0; @@ -661,21 +688,38 @@ void set_dfu_alt_info(char *interface, char *devstr) len += snprintf(buf + len, DFU_ALT_BUF_LEN, ".bin fat %d 1", bootseq); #if defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) - len += snprintf(buf + len, DFU_ALT_BUF_LEN, ";%s fat %d 1", - CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, bootseq); + if (strlen(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME)) + len += snprintf(buf + len, DFU_ALT_BUF_LEN, + ";%s fat %d 1", + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, + bootseq); #endif break; case QSPI_MODE_24BIT: case QSPI_MODE_32BIT: - len += snprintf(buf + len, DFU_ALT_BUF_LEN, - "sf 0:0=boot.bin raw %x 0x1500000", - multiboot * SZ_32K); + { + u32 base = multiboot * SZ_32K; + u32 size = 0x1500000; + u32 limit = size; + + mtd_found_part(&base, &limit); + +#if defined(CONFIG_SYS_SPI_U_BOOT_OFFS) + size = limit; + limit = CONFIG_SYS_SPI_U_BOOT_OFFS; +#endif + + len += snprintf(buf + len, DFU_ALT_BUF_LEN, + "sf 0:0=boot.bin raw 0x%x 0x%x", + base, limit); #if defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) && defined(CONFIG_SYS_SPI_U_BOOT_OFFS) - len += snprintf(buf + len, DFU_ALT_BUF_LEN, - ";%s raw 0x%x 0x500000", - CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, - multiboot * SZ_32K + CONFIG_SYS_SPI_U_BOOT_OFFS); + if (strlen(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME)) + len += snprintf(buf + len, DFU_ALT_BUF_LEN, + ";%s raw 0x%x 0x%x", + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, + base + limit, size - limit); #endif + } break; default: return; diff --git a/board/xilinx/zynqmp/zynqmp_kria.env b/board/xilinx/zynqmp/zynqmp_kria.env index 0f940bd68f8..846eceb0118 100644 --- a/board/xilinx/zynqmp/zynqmp_kria.env +++ b/board/xilinx/zynqmp/zynqmp_kria.env @@ -17,6 +17,7 @@ bootcmd_usb0=devnum=0; run usb_boot bootcmd_usb1=devnum=1; run usb_boot bootcmd_usb2=devnum=2; run usb_boot bootcmd_usb3=devnum=3; run usb_boot +bootcmd_usb4=devnum=4; run usb_boot bootdelay=2 bootfstype=fat bootm_low=0 @@ -44,7 +45,8 @@ usb_boot=usb start; if usb dev ${devnum}; then devtype=usb; run scan_dev_for_boo preboot=setenv boot_targets; setenv modeboot; run board_setup # SOM specific boot methods -som_cc_boot=if test ${card1_name} = SCK-KV-G; then setenv boot_targets mmc1 usb0 usb1 usb2 usb3 pxe dhcp && run distro_bootcmd; elif test ${card1_name} = SCK-KR-G; then setenv boot_targets usb0 usb1 usb2 usb3 pxe dhcp && run distro_bootcmd; else test ${card1_name} = SCK-KD-G; setenv boot_targets usb0 usb1 usb2 usb3 pxe dhcp && run distro_bootcmd; fi;" +usb_boot_devices='usb0 usb1 usb2 usb3 usb4' +som_cc_boot=if test ${card1_name} = SCK-KV-G; then setenv boot_targets mmc1 ${usb_boot_devices} pxe dhcp jtag && run distro_bootcmd; elif test ${card1_name} = SCK-KR-G; then setenv boot_targets ${usb_boot_devices} pxe dhcp jtag && run distro_bootcmd; else test ${card1_name} = SCK-KD-G; setenv boot_targets ${usb_boot_devices} pxe dhcp jtag && run distro_bootcmd; fi;" som_mmc_boot=setenv boot_targets mmc0 && run distro_bootcmd k26_starter=SMK-K26-XCL2G diff --git a/boot/Kconfig b/boot/Kconfig index d9a6c270059..777e408e243 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -2,39 +2,6 @@ menu "Boot options" menu "Boot images" -config ANDROID_BOOT_IMAGE - bool "Android Boot Images" - default y if FASTBOOT - help - This enables support for booting images which use the Android - image format header. - -config TIMESTAMP - bool "Show image date and time when displaying image information" - default y if CMD_DATE - help - When CONFIG_TIMESTAMP is selected, the timestamp (date and time) of - an image is printed by image commands like bootm or iminfo. This - is shown as 'Timestamp: xxx' and 'Created: xxx'. If this option is - enabled, then U-Boot requires FITs to have a timestamp. If a FIT is - loaded that does not, the message 'Wrong FIT format: no timestamp' - is shown. - -config BUTTON_CMD - bool "Support for running a command if a button is held during boot" - depends on CMDLINE - depends on BUTTON - help - For many embedded devices it's useful to enter a special flashing mode - such as fastboot mode when a button is held during boot. This option - allows arbitrary commands to be assigned to specific buttons. These will - be run after "preboot" if the button is held. Configuration is done via - the environment variables "button_cmd_N_name" and "button_cmd_N" where n is - the button number (starting from 0). e.g: - - "button_cmd_0_name=vol_down" - "button_cmd_0=fastboot usb 0" - menuconfig FIT bool "Flattened Image Tree (FIT)" select HASH @@ -721,6 +688,100 @@ config BOOTMETH_SCRIPT endif # BOOTSTD +config BOOTM + bool "Support booting an application image from memory" + default y + help + This is the main boot implementation in U-Boot, supporting a wide + variety of features including FIT and legacy-image boot, kernel and + FDT selection, setting up of the command line for the OS and many + other features. + + This option should normally be enabled. It is used to implement the + 'bootm' command. + +config BOOTM_LINUX + bool "Support booting Linux OS images" + depends on BOOTM || CMD_BOOTZ || CMD_BOOTI + default y + help + Support booting the Linux kernel directly via a command such as bootm + or booti or bootz. + +config BOOTM_NETBSD + bool "Support booting NetBSD (non-EFI) loader images" + depends on BOOTM + default y + help + Support booting NetBSD via the bootm command. + +config BOOTM_OPENRTOS + bool "Support booting OPENRTOS / FreeRTOS images" + depends on BOOTM + help + Support booting OPENRTOS / FreeRTOS via the bootm command. + +config BOOTM_OSE + bool "Support booting Enea OSE images" + depends on (ARM && (ARM64 || CPU_V7A || CPU_V7R) || SANDBOX || PPC || X86) + depends on BOOTM + help + Support booting Enea OSE images via the bootm command. + +config BOOTM_PLAN9 + bool "Support booting Plan9 OS images" + depends on BOOTM + default y + help + Support booting Plan9 images via the bootm command. + +config BOOTM_RTEMS + bool "Support booting RTEMS OS images" + depends on BOOTM + default y + help + Support booting RTEMS images via the bootm command. + +config BOOTM_VXWORKS + bool "Support booting VxWorks OS images" + depends on BOOTM + default y + help + Support booting VxWorks images via the bootm command. + +config ANDROID_BOOT_IMAGE + bool "Android Boot Images" + default y if FASTBOOT + help + This enables support for booting images which use the Android + image format header. + +config TIMESTAMP + bool "Show image date and time when displaying image information" + default y if CMD_DATE + help + When CONFIG_TIMESTAMP is selected, the timestamp (date and time) of + an image is printed by image commands like bootm or iminfo. This + is shown as 'Timestamp: xxx' and 'Created: xxx'. If this option is + enabled, then U-Boot requires FITs to have a timestamp. If a FIT is + loaded that does not, the message 'Wrong FIT format: no timestamp' + is shown. + +config BUTTON_CMD + bool "Support for running a command if a button is held during boot" + depends on CMDLINE + depends on BUTTON + help + For many embedded devices it's useful to enter a special flashing mode + such as fastboot mode when a button is held during boot. This option + allows arbitrary commands to be assigned to specific buttons. These will + be run after "preboot" if the button is held. Configuration is done via + the environment variables "button_cmd_N_name" and "button_cmd_N" where n is + the button number (starting from 0). e.g: + + "button_cmd_0_name=vol_down" + "button_cmd_0=fastboot usb 0" + config LEGACY_IMAGE_FORMAT bool "Enable support for the legacy image format" default y if !FIT_SIGNATURE && !TI_SECURE_DEVICE @@ -765,7 +826,7 @@ endif # MEASURED_BOOT config SYS_BOOTM_LEN hex "Maximum size of a decompresed OS image" - depends on CMD_BOOTM || CMD_BOOTI || CMD_BOOTZ || \ + depends on BOOTM || CMD_BOOTI || CMD_BOOTZ || \ LEGACY_IMAGE_FORMAT || SPL_LEGACY_IMAGE_FORMAT default 0x4000000 if PPC || ARM64 default 0x1000000 if X86 || ARCH_MX6 || ARCH_MX7 diff --git a/boot/Makefile b/boot/Makefile index 84ccfeaecec..bf767fd5356 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -6,7 +6,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_BOOT_RETRY) += bootretry.o -obj-$(CONFIG_CMD_BOOTM) += bootm.o bootm_os.o +obj-$(CONFIG_BOOTM) += bootm.o bootm_os.o obj-$(CONFIG_CMD_BOOTZ) += bootm.o bootm_os.o obj-$(CONFIG_CMD_BOOTI) += bootm.o bootm_os.o diff --git a/boot/bootm.c b/boot/bootm.c index d071537d692..032f5a4a160 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -242,13 +242,13 @@ static int boot_get_kernel(const char *addr_fit, struct bootm_headers *images, #ifdef CONFIG_LMB static void boot_start_lmb(struct bootm_headers *images) { - ulong mem_start; + phys_addr_t mem_start; phys_size_t mem_size; mem_start = env_get_bootm_low(); mem_size = env_get_bootm_size(); - lmb_init_and_reserve_range(&images->lmb, (phys_addr_t)mem_start, + lmb_init_and_reserve_range(&images->lmb, mem_start, mem_size, NULL); } #else diff --git a/boot/bootmeth_cros.c b/boot/bootmeth_cros.c index cd72db8250c..f015f2e1c75 100644 --- a/boot/bootmeth_cros.c +++ b/boot/bootmeth_cros.c @@ -432,9 +432,9 @@ static int cros_boot(struct udevice *dev, struct bootflow *bflow) } if (IS_ENABLED(CONFIG_X86)) { - ret = zboot_start(map_to_sysmem(bflow->buf), bflow->size, 0, 0, - map_to_sysmem(bflow->x86_setup), - bflow->cmdline); + ret = zboot_run(map_to_sysmem(bflow->buf), bflow->size, 0, 0, + map_to_sysmem(bflow->x86_setup), + bflow->cmdline); } else { ret = bootm_boot_start(map_to_sysmem(bflow->buf), bflow->cmdline); diff --git a/boot/fdt_support.c b/boot/fdt_support.c index 090d82ee80a..9844c70be80 100644 --- a/boot/fdt_support.c +++ b/boot/fdt_support.c @@ -17,6 +17,7 @@ #include <linux/ctype.h> #include <linux/types.h> #include <asm/global_data.h> +#include <asm/unaligned.h> #include <linux/libfdt.h> #include <fdt_support.h> #include <exports.h> @@ -421,13 +422,13 @@ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size, for (i = 0; i < n; i++) { if (address_cells == 2) - *(fdt64_t *)p = cpu_to_fdt64(address[i]); + put_unaligned_be64(address[i], p); else *(fdt32_t *)p = cpu_to_fdt32(address[i]); p += 4 * address_cells; if (size_cells == 2) - *(fdt64_t *)p = cpu_to_fdt64(size[i]); + put_unaligned_be64(size[i], p); else *(fdt32_t *)p = cpu_to_fdt32(size[i]); p += 4 * size_cells; diff --git a/boot/image-board.c b/boot/image-board.c index 75f6906cd56..09b6e4e0bdc 100644 --- a/boot/image-board.c +++ b/boot/image-board.c @@ -107,14 +107,12 @@ static int on_loadaddr(const char *name, const char *value, enum env_op op, } U_BOOT_ENV_CALLBACK(loadaddr, on_loadaddr); -ulong env_get_bootm_low(void) +phys_addr_t env_get_bootm_low(void) { char *s = env_get("bootm_low"); - if (s) { - ulong tmp = hextoul(s, NULL); - return tmp; - } + if (s) + return simple_strtoull(s, NULL, 16); #if defined(CFG_SYS_SDRAM_BASE) return CFG_SYS_SDRAM_BASE; @@ -127,14 +125,12 @@ ulong env_get_bootm_low(void) phys_size_t env_get_bootm_size(void) { - phys_size_t tmp, size; - phys_addr_t start; + phys_addr_t start, low; + phys_size_t size; char *s = env_get("bootm_size"); - if (s) { - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); - return tmp; - } + if (s) + return simple_strtoull(s, NULL, 16); start = gd->ram_base; size = gd->ram_size; @@ -144,22 +140,19 @@ phys_size_t env_get_bootm_size(void) s = env_get("bootm_low"); if (s) - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); + low = simple_strtoull(s, NULL, 16); else - tmp = start; + low = start; - return size - (tmp - start); + return size - (low - start); } phys_size_t env_get_bootm_mapsize(void) { - phys_size_t tmp; char *s = env_get("bootm_mapsize"); - if (s) { - tmp = (phys_size_t)simple_strtoull(s, NULL, 16); - return tmp; - } + if (s) + return simple_strtoull(s, NULL, 16); #if defined(CFG_SYS_BOOTMAPSZ) return CFG_SYS_BOOTMAPSZ; @@ -538,7 +531,7 @@ int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, ulong *initrd_start, ulong *initrd_end) { char *s; - ulong initrd_high; + phys_addr_t initrd_high; int initrd_copy_to_ram = 1; s = env_get("initrd_high"); @@ -553,8 +546,8 @@ int boot_ramdisk_high(struct lmb *lmb, ulong rd_data, ulong rd_len, initrd_high = env_get_bootm_mapsize() + env_get_bootm_low(); } - debug("## initrd_high = 0x%08lx, copy_to_ram = %d\n", - initrd_high, initrd_copy_to_ram); + debug("## initrd_high = 0x%llx, copy_to_ram = %d\n", + (u64)initrd_high, initrd_copy_to_ram); if (rd_data) { if (!initrd_copy_to_ram) { /* zero-copy ramdisk support */ diff --git a/boot/image-fdt.c b/boot/image-fdt.c index 5e4aa9de0d2..2b92bdaff16 100644 --- a/boot/image-fdt.c +++ b/boot/image-fdt.c @@ -160,9 +160,11 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) { void *fdt_blob = *of_flat_tree; void *of_start = NULL; - u64 start, size, usable; + phys_addr_t start, size, usable; char *fdt_high; - ulong mapsize, low; + phys_addr_t addr; + phys_addr_t low; + phys_size_t mapsize; ulong of_len = 0; int bank; int err; @@ -185,7 +187,6 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) fdt_high = env_get("fdt_high"); if (fdt_high) { ulong desired_addr = hextoul(fdt_high, NULL); - ulong addr; if (desired_addr == ~0UL) { /* All ones means use fdt in place */ @@ -217,14 +218,14 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) if (start + size < low) continue; - usable = min(start + size, (u64)(low + mapsize)); - /* * At least part of this DRAM bank is usable, try - * using it for LMB allocation. + * using the DRAM bank up to 'usable' address limit + * for LMB allocation. */ - of_start = map_sysmem((ulong)lmb_alloc_base(lmb, - of_len, 0x1000, usable), of_len); + usable = min(start + size, low + mapsize); + addr = lmb_alloc_base(lmb, of_len, 0x1000, usable); + of_start = map_sysmem(addr, of_len); /* Allocation succeeded, use this block. */ if (of_start != NULL) break; @@ -233,7 +234,7 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) * Reduce the mapping size in the next bank * by the size of attempt in current bank. */ - mapsize -= usable - max(start, (u64)low); + mapsize -= usable - max(start, low); if (!mapsize) break; } diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index 96205626750..d5e1bead125 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <bootm.h> #include <command.h> #include <dm.h> #include <env.h> @@ -470,6 +471,220 @@ skip_overlay: #endif /** + * calc_fdt_fname() - Figure out the filename to use for the FDT + * + * Determine the path to the FDT filename, based on the "fdtfile" environment + * variable. Use <soc>-<board>.dtb as a fallback + * + * @fdtdir: Directory to use for the FDT file + * Return: allocated filename (including directory), or NULL if out of memory + */ +static char *calc_fdt_fname(const char *fdtdir) +{ + char *fdtfile; + char *f1, *f2, *f3, *f4, *slash; + int len; + + f1 = env_get("fdtfile"); + if (f1) { + f2 = ""; + f3 = ""; + f4 = ""; + } else { + /* + * For complex cases where this code doesn't generate the + * correct filename, the board code should set $fdtfile during + * early boot, or the boot scripts should set $fdtfile before + * invoking "pxe" or "sysboot". + */ + f1 = env_get("soc"); + f2 = "-"; + f3 = env_get("board"); + f4 = ".dtb"; + if (!f1) { + f1 = ""; + f2 = ""; + } + if (!f3) { + f2 = ""; + f3 = ""; + } + } + + len = strlen(fdtdir); + if (!len) + slash = "./"; + else if (fdtdir[len - 1] != '/') + slash = "/"; + else + slash = ""; + + len = strlen(fdtdir) + strlen(slash) + strlen(f1) + strlen(f2) + + strlen(f3) + strlen(f4) + 1; + fdtfile = malloc(len); + if (!fdtfile) { + printf("malloc fail (FDT filename)\n"); + return NULL; + } + + snprintf(fdtfile, len, "%s%s%s%s%s%s", fdtdir, slash, f1, f2, f3, f4); + + return fdtfile; +} + +/** + * label_run_boot() - Run the correct boot procedure + * + * fdt usage is optional: + * It handles the following scenarios. + * + * Scenario 1: If fdt_addr_r specified and "fdt" or "fdtdir" label is + * defined in pxe file, retrieve fdt blob from server. Pass fdt_addr_r to + * bootm, and adjust argc appropriately. + * + * If retrieve fails and no exact fdt blob is specified in pxe file with + * "fdt" label, try Scenario 2. + * + * Scenario 2: If there is an fdt_addr specified, pass it along to + * bootm, and adjust argc appropriately. + * + * Scenario 3: If there is an fdtcontroladdr specified, pass it along to + * bootm, and adjust argc appropriately, unless the image type is fitImage. + * + * Scenario 4: fdt blob is not available. + * + * @ctx: PXE context + * @label: Label to process + * @kernel_addr: string containing the kernel address / config + * @initrd_str: string containing the initrd address / size + * @initrd_addr_str: initrd address, or NULL if none + * @initrd_filesize: initrd size in bytes; only valid if initrd_addr_str is not + * NULL + * Returns does not return on success, otherwise returns 0 if a localboot + * label was processed, or 1 on error + */ +static int label_run_boot(struct pxe_context *ctx, struct pxe_label *label, + char *kernel_addr, char *initrd_str, + char *initrd_addr_str, char *initrd_filesize) +{ + struct bootm_info bmi; + const char *fdt_addr; + ulong kernel_addr_r; + void *buf; + int ret; + + if (IS_ENABLED(CONFIG_BOOTM)) + bootm_init(&bmi); + + fdt_addr = env_get("fdt_addr_r"); + + /* For FIT, the label can be identical to kernel one */ + if (label->fdt && !strcmp(label->kernel_label, label->fdt)) { + fdt_addr = kernel_addr; + /* if fdt label is defined then get fdt from server */ + } else if (fdt_addr) { + char *fdtfile = NULL; + char *fdtfilefree = NULL; + + if (label->fdt) { + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + fdtfile = label->fdt; + } else { + fdtfile = label->fdt; + } + } else if (label->fdtdir) { + fdtfilefree = calc_fdt_fname(label->fdtdir); + if (!fdtfilefree) + return -ENOMEM; + fdtfile = fdtfilefree; + } + + if (fdtfile) { + int err = get_relfile_envaddr(ctx, fdtfile, + "fdt_addr_r", NULL); + + free(fdtfilefree); + if (err < 0) { + fdt_addr = NULL; + + if (label->fdt) { + printf("Skipping %s for failure retrieving FDT\n", + label->name); + return -ENOENT; + } + + if (label->fdtdir) { + printf("Skipping fdtdir %s for failure retrieving dts\n", + label->fdtdir); + } + } + + if (label->kaslrseed) + label_boot_kaslrseed(); + +#ifdef CONFIG_OF_LIBFDT_OVERLAY + if (label->fdtoverlays) + label_boot_fdtoverlay(ctx, label); +#endif + } else { + fdt_addr = NULL; + } + } + + bmi.addr_img = kernel_addr; + + if (initrd_addr_str) + bmi.conf_ramdisk = initrd_str; + + if (!fdt_addr) { + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + fdt_addr = env_get("fdt_addr"); + } else { + fdt_addr = env_get("fdt_addr"); + } + } + + kernel_addr_r = genimg_get_kernel_addr(kernel_addr); + buf = map_sysmem(kernel_addr_r, 0); + + if (!fdt_addr && genimg_get_format(buf) != IMAGE_FORMAT_FIT) { + if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { + if (strcmp("-", label->fdt)) + fdt_addr = env_get("fdtcontroladdr"); + } else { + fdt_addr = env_get("fdtcontroladdr"); + } + } + + bmi.conf_fdt = fdt_addr; + + /* Try bootm for legacy and FIT format image */ + if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID && + IS_ENABLED(CONFIG_BOOTM)) + ret = bootm_run(&bmi); + /* Try booting an AArch64 Linux kernel image */ + else if (IS_ENABLED(CONFIG_BOOTM)) + ret = booti_run(&bmi); + /* Try booting a Image */ + else if (IS_ENABLED(CONFIG_BOOTM)) + ret = bootz_run(&bmi); + /* Try booting an x86_64 Linux kernel image */ + else if (IS_ENABLED(CONFIG_ZBOOT)) + ret = zboot_run(hextoul(kernel_addr, NULL), 0, + initrd_addr_str ? + hextoul(initrd_addr_str, NULL) : 0, + initrd_addr_str ? + hextoul(initrd_filesize, NULL) : 0, + 0, NULL); + + unmap_sysmem(buf); + + return 0; +} + +/** * label_boot() - Boot according to the contents of a pxe_label * * If we can't boot for any reason, we return. A successful boot never @@ -491,8 +706,6 @@ skip_overlay: */ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) { - char *bootm_argv[] = { "bootm", NULL, NULL, NULL, NULL }; - char *zboot_argv[] = { "zboot", NULL, "0", NULL, NULL }; char *kernel_addr = NULL; char *initrd_addr_str = NULL; char initrd_filesize[10]; @@ -500,11 +713,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) char mac_str[29] = ""; char ip_str[68] = ""; char *fit_addr = NULL; - int bootm_argc = 2; - int zboot_argc = 3; - int len = 0; - ulong kernel_addr_r; - void *buf; + int ret; label_print(label); @@ -545,9 +754,10 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) /* For FIT, the label can be identical to kernel one */ if (label->initrd && !strcmp(label->kernel_label, label->initrd)) { - initrd_addr_str = kernel_addr; + initrd_addr_str = kernel_addr; } else if (label->initrd) { ulong size; + if (get_relfile_envaddr(ctx, label->initrd, "ramdisk_addr_r", &size) < 0) { printf("Skipping %s for failure retrieving initrd\n", @@ -593,7 +803,7 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) } if (label->append) - strncpy(bootargs, label->append, sizeof(bootargs)); + strlcpy(bootargs, label->append, sizeof(bootargs)); strcat(bootargs, ip_str); strcat(bootargs, mac_str); @@ -604,180 +814,8 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) printf("append: %s\n", finalbootargs); } - /* - * fdt usage is optional: - * It handles the following scenarios. - * - * Scenario 1: If fdt_addr_r specified and "fdt" or "fdtdir" label is - * defined in pxe file, retrieve fdt blob from server. Pass fdt_addr_r to - * bootm, and adjust argc appropriately. - * - * If retrieve fails and no exact fdt blob is specified in pxe file with - * "fdt" label, try Scenario 2. - * - * Scenario 2: If there is an fdt_addr specified, pass it along to - * bootm, and adjust argc appropriately. - * - * Scenario 3: If there is an fdtcontroladdr specified, pass it along to - * bootm, and adjust argc appropriately, unless the image type is fitImage. - * - * Scenario 4: fdt blob is not available. - */ - bootm_argv[3] = env_get("fdt_addr_r"); - - /* For FIT, the label can be identical to kernel one */ - if (label->fdt && !strcmp(label->kernel_label, label->fdt)) { - bootm_argv[3] = kernel_addr; - /* if fdt label is defined then get fdt from server */ - } else if (bootm_argv[3]) { - char *fdtfile = NULL; - char *fdtfilefree = NULL; - - if (label->fdt) { - if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { - if (strcmp("-", label->fdt)) - fdtfile = label->fdt; - } else { - fdtfile = label->fdt; - } - } else if (label->fdtdir) { - char *f1, *f2, *f3, *f4, *slash; - - f1 = env_get("fdtfile"); - if (f1) { - f2 = ""; - f3 = ""; - f4 = ""; - } else { - /* - * For complex cases where this code doesn't - * generate the correct filename, the board - * code should set $fdtfile during early boot, - * or the boot scripts should set $fdtfile - * before invoking "pxe" or "sysboot". - */ - f1 = env_get("soc"); - f2 = "-"; - f3 = env_get("board"); - f4 = ".dtb"; - if (!f1) { - f1 = ""; - f2 = ""; - } - if (!f3) { - f2 = ""; - f3 = ""; - } - } - - len = strlen(label->fdtdir); - if (!len) - slash = "./"; - else if (label->fdtdir[len - 1] != '/') - slash = "/"; - else - slash = ""; - - len = strlen(label->fdtdir) + strlen(slash) + - strlen(f1) + strlen(f2) + strlen(f3) + - strlen(f4) + 1; - fdtfilefree = malloc(len); - if (!fdtfilefree) { - printf("malloc fail (FDT filename)\n"); - goto cleanup; - } - - snprintf(fdtfilefree, len, "%s%s%s%s%s%s", - label->fdtdir, slash, f1, f2, f3, f4); - fdtfile = fdtfilefree; - } - - if (fdtfile) { - int err = get_relfile_envaddr(ctx, fdtfile, - "fdt_addr_r", NULL); - - free(fdtfilefree); - if (err < 0) { - bootm_argv[3] = NULL; - - if (label->fdt) { - printf("Skipping %s for failure retrieving FDT\n", - label->name); - goto cleanup; - } - - if (label->fdtdir) { - printf("Skipping fdtdir %s for failure retrieving dts\n", - label->fdtdir); - } - } - - if (label->kaslrseed) - label_boot_kaslrseed(); - -#ifdef CONFIG_OF_LIBFDT_OVERLAY - if (label->fdtoverlays) - label_boot_fdtoverlay(ctx, label); -#endif - } else { - bootm_argv[3] = NULL; - } - } - - bootm_argv[1] = kernel_addr; - zboot_argv[1] = kernel_addr; - - if (initrd_addr_str) { - bootm_argv[2] = initrd_str; - bootm_argc = 3; - - zboot_argv[3] = initrd_addr_str; - zboot_argv[4] = initrd_filesize; - zboot_argc = 5; - } - - if (!bootm_argv[3]) { - if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { - if (strcmp("-", label->fdt)) - bootm_argv[3] = env_get("fdt_addr"); - } else { - bootm_argv[3] = env_get("fdt_addr"); - } - } - - kernel_addr_r = genimg_get_kernel_addr(kernel_addr); - buf = map_sysmem(kernel_addr_r, 0); - - if (!bootm_argv[3] && genimg_get_format(buf) != IMAGE_FORMAT_FIT) { - if (IS_ENABLED(CONFIG_SUPPORT_PASSING_ATAGS)) { - if (strcmp("-", label->fdt)) - bootm_argv[3] = env_get("fdtcontroladdr"); - } else { - bootm_argv[3] = env_get("fdtcontroladdr"); - } - } - - if (bootm_argv[3]) { - if (!bootm_argv[2]) - bootm_argv[2] = "-"; - bootm_argc = 4; - } - - /* Try bootm for legacy and FIT format image */ - if (genimg_get_format(buf) != IMAGE_FORMAT_INVALID && - IS_ENABLED(CONFIG_CMD_BOOTM)) - do_bootm(ctx->cmdtp, 0, bootm_argc, bootm_argv); - /* Try booting an AArch64 Linux kernel image */ - else if (IS_ENABLED(CONFIG_CMD_BOOTI)) - do_booti(ctx->cmdtp, 0, bootm_argc, bootm_argv); - /* Try booting a Image */ - else if (IS_ENABLED(CONFIG_CMD_BOOTZ)) - do_bootz(ctx->cmdtp, 0, bootm_argc, bootm_argv); - /* Try booting an x86_64 Linux kernel image */ - else if (IS_ENABLED(CONFIG_CMD_ZBOOT)) - do_zboot_parent(ctx->cmdtp, 0, zboot_argc, zboot_argv, NULL); - - unmap_sysmem(buf); + ret = label_run_boot(ctx, label, kernel_addr, initrd_str, + initrd_addr_str, initrd_filesize); cleanup: free(fit_addr); diff --git a/cmd/Kconfig b/cmd/Kconfig index 61e280fb1a4..8eeb99eea5e 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -262,6 +262,7 @@ config CMD_BOOTD config CMD_BOOTM bool "bootm" + depends on BOOTM default y help Boot an application image from the memory. @@ -333,48 +334,6 @@ config CMD_BOOTI help Boot an AArch64 Linux Kernel image from memory. -config BOOTM_LINUX - bool "Support booting Linux OS images" - depends on CMD_BOOTM || CMD_BOOTZ || CMD_BOOTI - default y - help - Support booting the Linux kernel directly via a command such as bootm - or booti or bootz. - -config BOOTM_NETBSD - bool "Support booting NetBSD (non-EFI) loader images" - depends on CMD_BOOTM - default y - help - Support booting NetBSD via the bootm command. - -config BOOTM_OPENRTOS - bool "Support booting OPENRTOS / FreeRTOS images" - depends on CMD_BOOTM - help - Support booting OPENRTOS / FreeRTOS via the bootm command. - -config BOOTM_OSE - bool "Support booting Enea OSE images" - depends on (ARM && (ARM64 || CPU_V7A || CPU_V7R) || SANDBOX || PPC || X86) - depends on CMD_BOOTM - help - Support booting Enea OSE images via the bootm command. - -config BOOTM_PLAN9 - bool "Support booting Plan9 OS images" - depends on CMD_BOOTM - default y - help - Support booting Plan9 images via the bootm command. - -config BOOTM_RTEMS - bool "Support booting RTEMS OS images" - depends on CMD_BOOTM - default y - help - Support booting RTEMS images via the bootm command. - config CMD_SEAMA bool "Support read SEAMA NAND images" depends on MTD_RAW_NAND @@ -391,13 +350,6 @@ config CMD_VBE is used to boot. Updating the parameters is not currently supported. -config BOOTM_VXWORKS - bool "Support booting VxWorks OS images" - depends on CMD_BOOTM - default y - help - Support booting VxWorks images via the bootm command. - config CMD_BOOTEFI bool "bootefi" depends on EFI_LOADER @@ -612,6 +564,8 @@ config THOR_RESET_OFF config CMD_ZBOOT bool "zboot - x86 boot command" + depends on ZBOOT + default y help With x86 machines it is common to boot a bzImage file which contains both a kernel and a setup.bin file. The latter includes @@ -1407,6 +1361,13 @@ config CMD_MTD help MTD commands support. +config CMD_MTD_OTP + bool "mtd otp" + depends on CMD_MTD + select HEXDUMP + help + MTD commands for OTP access. + config CMD_MUX bool "mux" depends on MULTIPLEXER @@ -2878,8 +2839,8 @@ config CMD_TRACE Enables a command to control using of function tracing within U-Boot. This allows recording of call traces including timing information. The command can write data to memory for exporting - for analysis (e.g. using bootchart). See doc/README.trace for full - details. + for analysis (e.g. using bootchart). See doc/develop/trace.rst + for full details. config CMD_AVB bool "avb - Android Verified Boot 2.0 operations" diff --git a/cmd/booti.c b/cmd/booti.c index 898df0f8896..b9637b3ec3d 100644 --- a/cmd/booti.c +++ b/cmd/booti.c @@ -74,7 +74,7 @@ static int booti_start(struct bootm_info *bmi) unmap_sysmem((void *)ld); ret = booti_setup(ld, &relocated_addr, &image_size, false); - if (ret || IS_ENABLED(CONFIG_SANDBOX)) + if (ret) return 1; /* Handle BOOTM_STATE_LOADOS */ diff --git a/cmd/fastboot.c b/cmd/fastboot.c index c3c19231c98..792e83d372c 100644 --- a/cmd/fastboot.c +++ b/cmd/fastboot.c @@ -159,7 +159,7 @@ NXTARG: return CMD_RET_USAGE; } - fastboot_init((void *)buf_addr, buf_size); + fastboot_init(buf_addr, buf_size); if (!strcmp(argv[1], "udp")) return do_fastboot_udp(argc, argv, buf_addr, buf_size); diff --git a/cmd/mtd.c b/cmd/mtd.c index 9083a6840ac..9189f45cabd 100644 --- a/cmd/mtd.c +++ b/cmd/mtd.c @@ -11,6 +11,9 @@ #include <command.h> #include <common.h> #include <console.h> +#if CONFIG_IS_ENABLED(CMD_MTD_OTP) +#include <hexdump.h> +#endif #include <malloc.h> #include <mapmem.h> #include <mtd.h> @@ -202,6 +205,221 @@ static bool mtd_oob_write_is_empty(struct mtd_oob_ops *op) return true; } +#if CONFIG_IS_ENABLED(CMD_MTD_OTP) +static int do_mtd_otp_read(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct mtd_info *mtd; + size_t retlen; + off_t from; + size_t len; + bool user; + int ret; + u8 *buf; + + if (argc != 5) + return CMD_RET_USAGE; + + if (!strcmp(argv[2], "u")) + user = true; + else if (!strcmp(argv[2], "f")) + user = false; + else + return CMD_RET_USAGE; + + mtd = get_mtd_by_name(argv[1]); + if (IS_ERR_OR_NULL(mtd)) + return CMD_RET_FAILURE; + + from = simple_strtoul(argv[3], NULL, 0); + len = simple_strtoul(argv[4], NULL, 0); + + ret = CMD_RET_FAILURE; + + buf = malloc(len); + if (!buf) + goto put_mtd; + + printf("Reading %s OTP from 0x%lx, %zu bytes\n", + user ? "user" : "factory", from, len); + + if (user) + ret = mtd_read_user_prot_reg(mtd, from, len, &retlen, buf); + else + ret = mtd_read_fact_prot_reg(mtd, from, len, &retlen, buf); + if (ret) { + free(buf); + pr_err("OTP read failed: %d\n", ret); + ret = CMD_RET_FAILURE; + goto put_mtd; + } + + if (retlen != len) + pr_err("OTP read returns %zu, but %zu expected\n", + retlen, len); + + print_hex_dump("", 0, 16, 1, buf, retlen, true); + + free(buf); + + ret = CMD_RET_SUCCESS; + +put_mtd: + put_mtd_device(mtd); + + return ret; +} + +static int do_mtd_otp_lock(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct mtd_info *mtd; + off_t from; + size_t len; + int ret; + + if (argc != 4) + return CMD_RET_USAGE; + + mtd = get_mtd_by_name(argv[1]); + if (IS_ERR_OR_NULL(mtd)) + return CMD_RET_FAILURE; + + from = simple_strtoul(argv[2], NULL, 0); + len = simple_strtoul(argv[3], NULL, 0); + + ret = mtd_lock_user_prot_reg(mtd, from, len); + if (ret) { + pr_err("OTP lock failed: %d\n", ret); + ret = CMD_RET_FAILURE; + goto put_mtd; + } + + ret = CMD_RET_SUCCESS; + +put_mtd: + put_mtd_device(mtd); + + return ret; +} + +static int do_mtd_otp_write(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct mtd_info *mtd; + size_t retlen; + size_t binlen; + u8 *binbuf; + off_t from; + int ret; + + if (argc != 4) + return CMD_RET_USAGE; + + mtd = get_mtd_by_name(argv[1]); + if (IS_ERR_OR_NULL(mtd)) + return CMD_RET_FAILURE; + + from = simple_strtoul(argv[2], NULL, 0); + binlen = strlen(argv[3]) / 2; + + ret = CMD_RET_FAILURE; + binbuf = malloc(binlen); + if (!binbuf) + goto put_mtd; + + hex2bin(binbuf, argv[3], binlen); + + printf("Will write:\n"); + + print_hex_dump("", 0, 16, 1, binbuf, binlen, true); + + printf("to 0x%lx\n", from); + + printf("Continue (y/n)?\n"); + + if (confirm_yesno() != 1) { + pr_err("OTP write canceled\n"); + ret = CMD_RET_SUCCESS; + goto put_mtd; + } + + ret = mtd_write_user_prot_reg(mtd, from, binlen, &retlen, binbuf); + if (ret) { + pr_err("OTP write failed: %d\n", ret); + ret = CMD_RET_FAILURE; + goto put_mtd; + } + + if (retlen != binlen) + pr_err("OTP write returns %zu, but %zu expected\n", + retlen, binlen); + + ret = CMD_RET_SUCCESS; + +put_mtd: + free(binbuf); + put_mtd_device(mtd); + + return ret; +} + +static int do_mtd_otp_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct otp_info otp_info; + struct mtd_info *mtd; + size_t retlen; + bool user; + int ret; + + if (argc != 3) + return CMD_RET_USAGE; + + if (!strcmp(argv[2], "u")) + user = true; + else if (!strcmp(argv[2], "f")) + user = false; + else + return CMD_RET_USAGE; + + mtd = get_mtd_by_name(argv[1]); + if (IS_ERR_OR_NULL(mtd)) + return CMD_RET_FAILURE; + + if (user) + ret = mtd_get_user_prot_info(mtd, sizeof(otp_info), &retlen, + &otp_info); + else + ret = mtd_get_fact_prot_info(mtd, sizeof(otp_info), &retlen, + &otp_info); + if (ret) { + pr_err("OTP info failed: %d\n", ret); + ret = CMD_RET_FAILURE; + goto put_mtd; + } + + if (retlen != sizeof(otp_info)) { + pr_err("OTP info returns %zu, but %zu expected\n", + retlen, sizeof(otp_info)); + ret = CMD_RET_FAILURE; + goto put_mtd; + } + + printf("%s OTP region info:\n", user ? "User" : "Factory"); + printf("\tstart: %u\n", otp_info.start); + printf("\tlength: %u\n", otp_info.length); + printf("\tlocked: %u\n", otp_info.locked); + + ret = CMD_RET_SUCCESS; + +put_mtd: + put_mtd_device(mtd); + + return ret; +} +#endif + static int do_mtd_list(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -551,6 +769,12 @@ U_BOOT_LONGHELP(mtd, "\n" "Specific functions:\n" "mtd bad <name>\n" +#if CONFIG_IS_ENABLED(CMD_MTD_OTP) + "mtd otpread <name> [u|f] <off> <size>\n" + "mtd otpwrite <name> <off> <hex string>\n" + "mtd otplock <name> <off> <size>\n" + "mtd otpinfo <name> [u|f]\n" +#endif "\n" "With:\n" "\t<name>: NAND partition/chip name (or corresponding DM device name or OF path)\n" @@ -561,10 +785,20 @@ U_BOOT_LONGHELP(mtd, "\t<size>: length of the operation in bytes (default: the entire device)\n" "\t\t* must be a multiple of a block for erase\n" "\t\t* must be a multiple of a page otherwise (special case: default is a page with dump)\n" +#if CONFIG_IS_ENABLED(CMD_MTD_OTP) + "\t<hex string>: hex string without '0x' and spaces. Example: ABCD1234\n" + "\t[u|f]: user or factory OTP region\n" +#endif "\n" "The .dontskipff option forces writing empty pages, don't use it if unsure.\n"); U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text, +#if CONFIG_IS_ENABLED(CMD_MTD_OTP) + U_BOOT_SUBCMD_MKENT(otpread, 5, 1, do_mtd_otp_read), + U_BOOT_SUBCMD_MKENT(otpwrite, 4, 1, do_mtd_otp_write), + U_BOOT_SUBCMD_MKENT(otplock, 4, 1, do_mtd_otp_lock), + U_BOOT_SUBCMD_MKENT(otpinfo, 3, 1, do_mtd_otp_info), +#endif U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list), U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io, mtd_name_complete), @@ -135,8 +135,9 @@ static int do_spi_flash_probe(int argc, char *const argv[]) } flash = NULL; if (use_dt) { - spi_flash_probe_bus_cs(bus, cs, &new); - flash = dev_get_uclass_priv(new); + ret = spi_flash_probe_bus_cs(bus, cs, &new); + if (!ret) + flash = dev_get_uclass_priv(new); } else { flash = spi_flash_probe(bus, cs, speed, mode); } diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 63a7806debe..d14c570d96a 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -77,6 +77,10 @@ static int do_sysboot(struct cmd_tbl *cmdtp, int flag, int argc, if (argc < 6) { filename = env_get("bootfile"); + if (!filename) { + printf("Specify a filename or set the ${bootfile} environment variable\n"); + return 1; + } } else { filename = argv[5]; env_set("bootfile", filename); diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile index 5f82204c87e..b1f39d3bfde 100644 --- a/cmd/x86/Makefile +++ b/cmd/x86/Makefile @@ -5,3 +5,4 @@ obj-y += mtrr.o obj-$(CONFIG_CMD_EXCEPTION) += exception.o obj-$(CONFIG_USE_HOB) += hob.o obj-$(CONFIG_HAVE_FSP) += fsp.o +obj-$(CONFIG_CMD_ZBOOT) += zboot.o diff --git a/cmd/x86/zboot.c b/cmd/x86/zboot.c new file mode 100644 index 00000000000..addf28cb4aa --- /dev/null +++ b/cmd/x86/zboot.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se> + */ + +#include <command.h> +#include <mapmem.h> +#include <vsprintf.h> +#include <asm/zimage.h> + +static int do_zboot_start(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + ulong bzimage_addr = 0, bzimage_size, initrd_addr, initrd_size; + ulong base_addr; + const char *s, *cmdline; + + /* argv[1] holds the address of the bzImage */ + s = cmd_arg1(argc, argv) ? : env_get("fileaddr"); + if (s) + bzimage_addr = hextoul(s, NULL); + bzimage_size = argc > 2 ? hextoul(argv[2], NULL) : 0; + initrd_addr = argc > 3 ? hextoul(argv[3], NULL) : 0; + initrd_size = argc > 4 ? hextoul(argv[4], NULL) : 0; + base_addr = argc > 5 ? hextoul(argv[5], NULL) : 0; + cmdline = argc > 6 ? env_get(argv[6]) : NULL; + + zboot_start(bzimage_addr, bzimage_size, initrd_addr, initrd_size, + base_addr, cmdline); + + return 0; +} + +static int do_zboot_load(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = zboot_load(); + if (ret) + return ret; + + return 0; +} + +static int do_zboot_setup(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (!state.base_ptr) { + printf("base is not set: use 'zboot load' first\n"); + return CMD_RET_FAILURE; + } + if (zboot_setup()) { + puts("Setting up boot parameters failed ...\n"); + return CMD_RET_FAILURE; + } + + if (zboot_setup()) + return CMD_RET_FAILURE; + + return 0; +} + +static int do_zboot_info(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + zboot_info(); + + return 0; +} + +static int do_zboot_go(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + int ret; + + ret = zboot_go(); + if (ret) { + printf("Kernel returned! (err=%d)\n", ret); + return CMD_RET_FAILURE; + } + + return 0; +} + +static int do_zboot_dump(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct boot_params *base_ptr = state.base_ptr; + + if (argc > 1) + base_ptr = (void *)hextoul(argv[1], NULL); + if (!base_ptr) { + printf("No zboot setup_base\n"); + return CMD_RET_FAILURE; + } + zimage_dump(base_ptr, true); + + return 0; +} + +/* Note: This defines the complete_zboot() function */ +U_BOOT_SUBCMDS(zboot, + U_BOOT_CMD_MKENT(start, 8, 1, do_zboot_start, "", ""), + U_BOOT_CMD_MKENT(load, 1, 1, do_zboot_load, "", ""), + U_BOOT_CMD_MKENT(setup, 1, 1, do_zboot_setup, "", ""), + U_BOOT_CMD_MKENT(info, 1, 1, do_zboot_info, "", ""), + U_BOOT_CMD_MKENT(go, 1, 1, do_zboot_go, "", ""), + U_BOOT_CMD_MKENT(dump, 2, 1, do_zboot_dump, "", ""), +) + +int do_zboot_states(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[], int state_mask) +{ + int ret; + + if (flag & ZBOOT_STATE_START) + ret = do_zboot_start(cmdtp, flag, argc, argv); + if (!ret && (flag & ZBOOT_STATE_LOAD)) + ret = do_zboot_load(cmdtp, flag, argc, argv); + if (!ret && (flag & ZBOOT_STATE_SETUP)) + ret = do_zboot_setup(cmdtp, flag, argc, argv); + if (!ret && (flag & ZBOOT_STATE_INFO)) + ret = do_zboot_info(cmdtp, flag, argc, argv); + if (!ret && (flag & ZBOOT_STATE_GO)) + ret = do_zboot_go(cmdtp, flag, argc, argv); + if (ret) + return ret; + + return 0; +} + +int do_zboot_parent(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[], int *repeatable) +{ + /* determine if we have a sub command */ + if (argc > 1) { + char *endp; + + hextoul(argv[1], &endp); + /* + * endp pointing to nul means that argv[1] was just a valid + * number, so pass it along to the normal processing + */ + if (*endp) + return do_zboot(cmdtp, flag, argc, argv, repeatable); + } + + do_zboot_states(cmdtp, flag, argc, argv, ZBOOT_STATE_START | + ZBOOT_STATE_LOAD | ZBOOT_STATE_SETUP | + ZBOOT_STATE_INFO | ZBOOT_STATE_GO); + + return CMD_RET_FAILURE; +} + +U_BOOT_CMDREP_COMPLETE( + zboot, 8, do_zboot_parent, "Boot bzImage", + "[addr] [size] [initrd addr] [initrd size] [setup] [cmdline]\n" + " addr - The optional starting address of the bzimage.\n" + " If not set it defaults to the environment\n" + " variable \"fileaddr\".\n" + " size - The optional size of the bzimage. Defaults to\n" + " zero.\n" + " initrd addr - The address of the initrd image to use, if any.\n" + " initrd size - The size of the initrd image to use, if any.\n" + " setup - The address of the kernel setup region, if this\n" + " is not at addr\n" + " cmdline - Environment variable containing the kernel\n" + " command line, to override U-Boot's normal\n" + " cmdline generation\n" + "\n" + "Sub-commands to do part of the zboot sequence:\n" + "\tstart [addr [arg ...]] - specify arguments\n" + "\tload - load OS image\n" + "\tsetup - set up table\n" + "\tinfo - show summary info\n" + "\tgo - start OS\n" + "\tdump [addr] - dump info (optional address of boot params)", + complete_zboot +); diff --git a/common/board_f.c b/common/board_f.c index 8bada6ff2ee..039d6d712d0 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -718,6 +718,7 @@ static int reloc_bloblist(void) return 0; } +void mcheck_on_ramrelocation(size_t offset); static int setup_reloc(void) { if (!(gd->flags & GD_FLG_SKIP_RELOC)) { @@ -743,6 +744,9 @@ static int setup_reloc(void) if (gd->flags & GD_FLG_SKIP_RELOC) { debug("Skipping relocation due to flag\n"); } else { +#ifdef MCHECK_HEAP_PROTECTION + mcheck_on_ramrelocation(gd->reloc_off); +#endif debug("Relocation Offset is: %08lx\n", gd->reloc_off); debug("Relocating to %08lx, new gd at %08lx, sp at %08lx\n", gd->relocaddr, (ulong)map_to_sysmem(gd->new_gd), diff --git a/common/cli.c b/common/cli.c index a34938294ec..1c33daf1149 100644 --- a/common/cli.c +++ b/common/cli.c @@ -11,6 +11,7 @@ #define pr_fmt(fmt) "cli: %s: " fmt, __func__ #include <common.h> +#include <ansi.h> #include <bootstage.h> #include <cli.h> #include <cli_hush.h> @@ -336,4 +337,7 @@ void cli_init(void) #if defined(CONFIG_HUSH_INIT_VAR) hush_init_var(); #endif + + if (CONFIG_IS_ENABLED(VIDEO_ANSI)) + printf(ANSI_CURSOR_SHOW "\n"); } diff --git a/common/dlmalloc.c b/common/dlmalloc.c index de3f04225f4..a0616217d49 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -32,6 +32,21 @@ void malloc_stats(); DECLARE_GLOBAL_DATA_PTR; +#ifdef MCHECK_HEAP_PROTECTION + #define STATIC_IF_MCHECK static + #undef MALLOC_COPY + #undef MALLOC_ZERO +static inline void MALLOC_ZERO(void *p, size_t sz) { memset(p, 0, sz); } +static inline void MALLOC_COPY(void *dest, const void *src, size_t sz) { memcpy(dest, src, sz); } +#else + #define STATIC_IF_MCHECK + #define mALLOc_impl mALLOc + #define fREe_impl fREe + #define rEALLOc_impl rEALLOc + #define mEMALIGn_impl mEMALIGn + #define cALLOc_impl cALLOc +#endif + /* Emulation of sbrk for WIN32 All code within the ifdef WIN32 is untested by me. @@ -1270,10 +1285,11 @@ static void malloc_extend_top(nb) INTERNAL_SIZE_T nb; */ +STATIC_IF_MCHECK #if __STD_C -Void_t* mALLOc(size_t bytes) +Void_t* mALLOc_impl(size_t bytes) #else -Void_t* mALLOc(bytes) size_t bytes; +Void_t* mALLOc_impl(bytes) size_t bytes; #endif { mchunkptr victim; /* inspected/selected chunk */ @@ -1555,10 +1571,11 @@ Void_t* mALLOc(bytes) size_t bytes; */ +STATIC_IF_MCHECK #if __STD_C -void fREe(Void_t* mem) +void fREe_impl(Void_t* mem) #else -void fREe(mem) Void_t* mem; +void fREe_impl(mem) Void_t* mem; #endif { mchunkptr p; /* chunk corresponding to mem */ @@ -1696,10 +1713,11 @@ void fREe(mem) Void_t* mem; */ +STATIC_IF_MCHECK #if __STD_C -Void_t* rEALLOc(Void_t* oldmem, size_t bytes) +Void_t* rEALLOc_impl(Void_t* oldmem, size_t bytes) #else -Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; +Void_t* rEALLOc_impl(oldmem, bytes) Void_t* oldmem; size_t bytes; #endif { INTERNAL_SIZE_T nb; /* padded request size */ @@ -1725,7 +1743,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; #ifdef REALLOC_ZERO_BYTES_FREES if (!bytes) { - fREe(oldmem); + fREe_impl(oldmem); return NULL; } #endif @@ -1733,7 +1751,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; if ((long)bytes < 0) return NULL; /* realloc of null is supposed to be same as malloc */ - if (oldmem == NULL) return mALLOc(bytes); + if (oldmem == NULL) return mALLOc_impl(bytes); #if CONFIG_IS_ENABLED(SYS_MALLOC_F) if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) { @@ -1758,7 +1776,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; /* Note the extra SIZE_SZ overhead. */ if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */ /* Must alloc, copy, free. */ - newmem = mALLOc(bytes); + newmem = mALLOc_impl(bytes); if (!newmem) return NULL; /* propagate failure */ MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ); @@ -1869,7 +1887,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; /* Must allocate */ - newmem = mALLOc (bytes); + newmem = mALLOc_impl (bytes); if (newmem == NULL) /* propagate failure */ return NULL; @@ -1886,7 +1904,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; /* Otherwise copy, free, and exit */ MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); - fREe(oldmem); + fREe_impl(oldmem); return newmem; } else { VALGRIND_RESIZEINPLACE_BLOCK(oldmem, 0, bytes, SIZE_SZ); @@ -1905,7 +1923,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; set_inuse_bit_at_offset(remainder, remainder_size); VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(remainder), remainder_size, SIZE_SZ, false); - fREe(chunk2mem(remainder)); /* let free() deal with it */ + fREe_impl(chunk2mem(remainder)); /* let free() deal with it */ } else { @@ -1939,10 +1957,11 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; */ +STATIC_IF_MCHECK #if __STD_C -Void_t* mEMALIGn(size_t alignment, size_t bytes) +Void_t* mEMALIGn_impl(size_t alignment, size_t bytes) #else -Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; +Void_t* mEMALIGn_impl(alignment, bytes) size_t alignment; size_t bytes; #endif { INTERNAL_SIZE_T nb; /* padded request size */ @@ -1965,7 +1984,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; /* If need less alignment than we give anyway, just relay to malloc */ - if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes); + if (alignment <= MALLOC_ALIGNMENT) return mALLOc_impl(bytes); /* Otherwise, ensure that it is at least a minimum chunk size */ @@ -1974,7 +1993,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; /* Call malloc with worst case padding to hit alignment. */ nb = request2size(bytes); - m = (char*)(mALLOc(nb + alignment + MINSIZE)); + m = (char*)(mALLOc_impl(nb + alignment + MINSIZE)); /* * The attempt to over-allocate (with a size large enough to guarantee the @@ -1990,7 +2009,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; * Use bytes not nb, since mALLOc internally calls request2size too, and * each call increases the size to allocate, to account for the header. */ - m = (char*)(mALLOc(bytes)); + m = (char*)(mALLOc_impl(bytes)); /* Aligned -> return it */ if ((((unsigned long)(m)) % alignment) == 0) return m; @@ -1998,10 +2017,10 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; * Otherwise, try again, requesting enough extra space to be able to * acquire alignment. */ - fREe(m); + fREe_impl(m); /* Add in extra bytes to match misalignment of unexpanded allocation */ extra = alignment - (((unsigned long)(m)) % alignment); - m = (char*)(mALLOc(bytes + extra)); + m = (char*)(mALLOc_impl(bytes + extra)); /* * m might not be the same as before. Validate that the previous value of * extra still works for the current value of m. @@ -2010,7 +2029,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; if (m) { extra2 = alignment - (((unsigned long)(m)) % alignment); if (extra2 > extra) { - fREe(m); + fREe_impl(m); m = NULL; } } @@ -2060,7 +2079,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; set_head(newp, newsize | PREV_INUSE); set_inuse_bit_at_offset(newp, newsize); set_head_size(p, leadsize); - fREe(chunk2mem(p)); + fREe_impl(chunk2mem(p)); p = newp; VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(p), bytes, SIZE_SZ, false); @@ -2078,7 +2097,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; set_head_size(p, nb); VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(remainder), remainder_size, SIZE_SZ, false); - fREe(chunk2mem(remainder)); + fREe_impl(chunk2mem(remainder)); } check_inuse_chunk(p); @@ -2126,10 +2145,11 @@ Void_t* pvALLOc(bytes) size_t bytes; */ +STATIC_IF_MCHECK #if __STD_C -Void_t* cALLOc(size_t n, size_t elem_size) +Void_t* cALLOc_impl(size_t n, size_t elem_size) #else -Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; +Void_t* cALLOc_impl(n, elem_size) size_t n; size_t elem_size; #endif { mchunkptr p; @@ -2145,7 +2165,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; INTERNAL_SIZE_T oldtopsize = chunksize(top); #endif #endif - Void_t* mem = mALLOc (sz); + Void_t* mem = mALLOc_impl (sz); if ((long)n < 0) return NULL; @@ -2205,6 +2225,90 @@ void cfree(mem) Void_t *mem; #endif +#ifdef MCHECK_HEAP_PROTECTION + #include "mcheck_core.inc.h" + #if !__STD_C + #error "must have __STD_C" + #endif + +Void_t *mALLOc(size_t bytes) +{ + mcheck_pedantic_prehook(); + size_t fullsz = mcheck_alloc_prehook(bytes); + void *p = mALLOc_impl(fullsz); + + if (!p) + return p; + return mcheck_alloc_posthook(p, bytes); +} + +void fREe(Void_t *mem) { fREe_impl(mcheck_free_prehook(mem)); } + +Void_t *rEALLOc(Void_t *oldmem, size_t bytes) +{ + mcheck_pedantic_prehook(); + if (bytes == 0) { + if (oldmem) + fREe(oldmem); + return NULL; + } + + if (oldmem == NULL) + return mALLOc(bytes); + + void *p = mcheck_reallocfree_prehook(oldmem); + size_t newsz = mcheck_alloc_prehook(bytes); + + p = rEALLOc_impl(p, newsz); + if (!p) + return p; + return mcheck_alloc_noclean_posthook(p, bytes); +} + +Void_t *mEMALIGn(size_t alignment, size_t bytes) +{ + mcheck_pedantic_prehook(); + size_t fullsz = mcheck_memalign_prehook(alignment, bytes); + void *p = mEMALIGn_impl(alignment, fullsz); + + if (!p) + return p; + return mcheck_memalign_posthook(alignment, p, bytes); +} + +// pvALLOc, vALLOc - redirect to mEMALIGn, defined here, so they need no wrapping. + +Void_t *cALLOc(size_t n, size_t elem_size) +{ + mcheck_pedantic_prehook(); + // NB: here is no overflow check. + size_t fullsz = mcheck_alloc_prehook(n * elem_size); + void *p = cALLOc_impl(1, fullsz); + + if (!p) + return p; + return mcheck_alloc_noclean_posthook(p, n * elem_size); +} + +// mcheck API { +int mcheck_pedantic(mcheck_abortfunc_t f) +{ + mcheck_initialize(f, 1); + return 0; +} + +int mcheck(mcheck_abortfunc_t f) +{ + mcheck_initialize(f, 0); + return 0; +} + +void mcheck_check_all(void) { mcheck_pedantic_check(); } + +enum mcheck_status mprobe(void *__ptr) { return mcheck_mprobe(__ptr); } +// mcheck API } +#endif + /* diff --git a/common/mcheck_core.inc.h b/common/mcheck_core.inc.h new file mode 100644 index 00000000000..69021409922 --- /dev/null +++ b/common/mcheck_core.inc.h @@ -0,0 +1,304 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2024 Free Software Foundation, Inc. + * Written by Eugene Uriev, based on glibc 2.0 prototype of Mike Haertel. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * <https://www.gnu.org/licenses/> + */ + +/* + * TL;DR: this is a porting of glibc mcheck into U-Boot + * + * This file contains no entities for external linkage. + * So mcheck protection may be used in parallel, e.g. for "malloc_simple(..)" and "malloc(..)". + * To do so, the file should be shared/include twice, - without linkage conflicts. + * I.e. "core"-part is shared as a source, but not as a binary. + * Maybe some optimization here make sense, to engage more binary sharing too. + * But, currently I strive to keep it as simple, as possible. + * And this, programmers'-only, mode don't pretend to be main. + * + * This library is aware of U-Boot specific. It's also aware of ARM alignment concerns. + * Unlike glibc-clients, U-Boot has limited malloc-usage, and only one thread. + * So it's better to make the protection heavier. + * Thus overflow canary here is greater, than glibc's one. Underflow canary is bigger too. + * U-Boot also allows to use fixed-size heap-registry, instead of double-linked list in glibc. + * + * Heavy canary allows to catch not only memset(..)-errors, + * but overflow/underflow of struct-array access: + * { + * struct mystruct* p = malloc(sizeof(struct mystruct) * N); + * p[-1].field1 = 0; + * p[N].field2 = 13; + * } + * TODO: In order to guarantee full coverage of that kind of errors, a user can add variable-size + * canaries here. So pre- and post-canary with size >= reqested_size, could be provided + * (with the price of 3x heap-usage). Therefore, it would catch 100% of changes beyond + * an array, for index(+1/-1) errors. + * + * U-Boot is a BL, not an OS with a lib. Activity of the library is set not in runtime, + * rather in compile-time, by MCHECK_HEAP_PROTECTION macro. That guarantees that + * we haven't missed first malloc. + */ + +/* + * Testing + * This library had been successfully tested for U-Boot @ ARM SoC chip / 64bits. + * Proven for both default and pedantic mode: confirms U-Boot to be clean, and catches + * intentional/testing corruptions. Working with malloc_trim is not tested. + */ +#ifndef _MCHECKCORE_INC_H +#define _MCHECKCORE_INC_H 1 +#include "mcheck.h" + +#if defined(MCHECK_HEAP_PROTECTION) +#define mcheck_flood memset + +// these are from /dev/random: +#define MAGICWORD 0x99ccf430fa562a05ULL +#define MAGICFREE 0x4875e63c0c6fc08eULL +#define MAGICTAIL 0x918dbcd7df78dcd6ULL +#define MALLOCFLOOD ((char)0xb6) +#define FREEFLOOD ((char)0xf5) +#define PADDINGFLOOD ((char)0x58) + +// my normal run demands 4427-6449 chunks: +#define REGISTRY_SZ 6608 +#define CANARY_DEPTH 2 + +// avoid problems with BSS at early stage: +static char mcheck_pedantic_flag __section(".data") = 0; +static void *mcheck_registry[REGISTRY_SZ] __section(".data") = {0}; +static size_t mcheck_chunk_count __section(".data") = 0; +static size_t mcheck_chunk_count_max __section(".data") = 0; + +typedef unsigned long long mcheck_elem; +typedef struct { + mcheck_elem elems[CANARY_DEPTH]; +} mcheck_canary; +struct mcheck_hdr { + size_t size; /* Exact size requested by user. */ + size_t aln_skip; /* Ignored bytes, before the mcheck_hdr, to fulfill alignment */ + mcheck_canary canary; /* Magic number to check header integrity. */ +}; + +static void mcheck_default_abort(enum mcheck_status status, const void *p) +{ + const char *msg; + + switch (status) { + case MCHECK_OK: + msg = "memory is consistent, library is buggy\n"; + break; + case MCHECK_HEAD: + msg = "memory clobbered before allocated block\n"; + break; + case MCHECK_TAIL: + msg = "memory clobbered past end of allocated block\n"; + break; + case MCHECK_FREE: + msg = "block freed twice\n"; + break; + default: + msg = "bogus mcheck_status, library is buggy\n"; + break; + } + printf("\n\nmcheck: %p:%s!!! [%zu]\n\n", p, msg, mcheck_chunk_count_max); +} + +static mcheck_abortfunc_t mcheck_abortfunc = &mcheck_default_abort; + +static inline size_t allign_size_up(size_t sz, size_t grain) +{ + return (sz + grain - 1) & ~(grain - 1); +} + +#define mcheck_allign_customer_size(SZ) allign_size_up(SZ, sizeof(mcheck_elem)) +#define mcheck_evaluate_memalign_prefix_size(ALIGN) allign_size_up(sizeof(struct mcheck_hdr), ALIGN) + +static enum mcheck_status mcheck_OnNok(enum mcheck_status status, const void *p) +{ + (*mcheck_abortfunc)(status, p); + return status; +} + +static enum mcheck_status mcheck_checkhdr(const struct mcheck_hdr *hdr) +{ + int i; + + for (i = 0; i < CANARY_DEPTH; ++i) + if (hdr->canary.elems[i] == MAGICFREE) + return mcheck_OnNok(MCHECK_FREE, hdr + 1); + + for (i = 0; i < CANARY_DEPTH; ++i) + if (hdr->canary.elems[i] != MAGICWORD) + return mcheck_OnNok(MCHECK_HEAD, hdr + 1); + + const size_t payload_size = hdr->size; + const size_t payload_size_aligned = mcheck_allign_customer_size(payload_size); + const size_t padd_size = payload_size_aligned - hdr->size; + + const char *payload = (const char *)&hdr[1]; + + for (i = 0; i < padd_size; ++i) + if (payload[payload_size + i] != PADDINGFLOOD) + return mcheck_OnNok(MCHECK_TAIL, hdr + 1); + + const mcheck_canary *tail = (const mcheck_canary *)&payload[payload_size_aligned]; + + for (i = 0; i < CANARY_DEPTH; ++i) + if (tail->elems[i] != MAGICTAIL) + return mcheck_OnNok(MCHECK_TAIL, hdr + 1); + return MCHECK_OK; +} + +enum { KEEP_CONTENT = 0, CLEAN_CONTENT, ANY_ALIGNMENT = 1 }; +static void *mcheck_free_helper(void *ptr, int clean_content) +{ + if (!ptr) + return ptr; + + struct mcheck_hdr *hdr = &((struct mcheck_hdr *)ptr)[-1]; + int i; + + mcheck_checkhdr(hdr); + for (i = 0; i < CANARY_DEPTH; ++i) + hdr->canary.elems[i] = MAGICFREE; + + if (clean_content) + mcheck_flood(ptr, FREEFLOOD, mcheck_allign_customer_size(hdr->size)); + + for (i = 0; i < REGISTRY_SZ; ++i) + if (mcheck_registry[i] == hdr) { + mcheck_registry[i] = 0; + break; + } + + --mcheck_chunk_count; + return (char *)hdr - hdr->aln_skip; +} + +static void *mcheck_free_prehook(void *ptr) { return mcheck_free_helper(ptr, CLEAN_CONTENT); } +static void *mcheck_reallocfree_prehook(void *ptr) { return mcheck_free_helper(ptr, KEEP_CONTENT); } + +static size_t mcheck_alloc_prehook(size_t sz) +{ + sz = mcheck_allign_customer_size(sz); + return sizeof(struct mcheck_hdr) + sz + sizeof(mcheck_canary); +} + +static void *mcheck_allocated_helper(void *altoghether_ptr, size_t customer_sz, + size_t alignment, int clean_content) +{ + const size_t slop = alignment ? + mcheck_evaluate_memalign_prefix_size(alignment) - sizeof(struct mcheck_hdr) : 0; + struct mcheck_hdr *hdr = (struct mcheck_hdr *)((char *)altoghether_ptr + slop); + int i; + + hdr->size = customer_sz; + hdr->aln_skip = slop; + for (i = 0; i < CANARY_DEPTH; ++i) + hdr->canary.elems[i] = MAGICWORD; + + char *payload = (char *)&hdr[1]; + + if (clean_content) + mcheck_flood(payload, MALLOCFLOOD, customer_sz); + + const size_t customer_size_aligned = mcheck_allign_customer_size(customer_sz); + + mcheck_flood(payload + customer_sz, PADDINGFLOOD, customer_size_aligned - customer_sz); + + mcheck_canary *tail = (mcheck_canary *)&payload[customer_size_aligned]; + + for (i = 0; i < CANARY_DEPTH; ++i) + tail->elems[i] = MAGICTAIL; + + ++mcheck_chunk_count; + if (mcheck_chunk_count > mcheck_chunk_count_max) + mcheck_chunk_count_max = mcheck_chunk_count; + + for (i = 0; i < REGISTRY_SZ; ++i) + if (!mcheck_registry[i]) { + mcheck_registry[i] = hdr; + return payload; // normal end + } + + static char *overflow_msg = "\n\n\nERROR: mcheck registry overflow, pedantic check would be incomplete!!\n\n\n\n"; + + printf("%s", overflow_msg); + overflow_msg = "(mcheck registry full)"; + return payload; +} + +static void *mcheck_alloc_posthook(void *altoghether_ptr, size_t customer_sz) +{ + return mcheck_allocated_helper(altoghether_ptr, customer_sz, ANY_ALIGNMENT, CLEAN_CONTENT); +} + +static void *mcheck_alloc_noclean_posthook(void *altoghether_ptr, size_t customer_sz) +{ + return mcheck_allocated_helper(altoghether_ptr, customer_sz, ANY_ALIGNMENT, KEEP_CONTENT); +} + +static size_t mcheck_memalign_prehook(size_t alig, size_t sz) +{ + return mcheck_evaluate_memalign_prefix_size(alig) + sz + sizeof(mcheck_canary); +} + +static void *mcheck_memalign_posthook(size_t alignment, void *altoghether_ptr, size_t customer_sz) +{ + return mcheck_allocated_helper(altoghether_ptr, customer_sz, alignment, CLEAN_CONTENT); +} + +static enum mcheck_status mcheck_mprobe(void *ptr) +{ + struct mcheck_hdr *hdr = &((struct mcheck_hdr *)ptr)[-1]; + + return mcheck_checkhdr(hdr); +} + +static void mcheck_pedantic_check(void) +{ + int i; + + for (i = 0; i < REGISTRY_SZ; ++i) + if (mcheck_registry[i]) + mcheck_checkhdr(mcheck_registry[i]); +} + +static void mcheck_pedantic_prehook(void) +{ + if (mcheck_pedantic_flag) + mcheck_pedantic_check(); +} + +static void mcheck_initialize(mcheck_abortfunc_t new_func, char pedantic_flag) +{ + mcheck_abortfunc = (new_func) ? new_func : &mcheck_default_abort; + mcheck_pedantic_flag = pedantic_flag; +} + +void mcheck_on_ramrelocation(size_t offset) +{ + char *p; + int i; + // Simple, but inaccurate strategy: drop the pre-reloc heap + for (i = 0; i < REGISTRY_SZ; ++i) + if ((p = mcheck_registry[i]) != NULL ) { + printf("mcheck, WRN: forgetting %p chunk\n", p); + mcheck_registry[i] = 0; + } + + mcheck_chunk_count = 0; +} +#endif +#endif diff --git a/common/usb.c b/common/usb.c index 836506dcd9e..99e6b857c74 100644 --- a/common/usb.c +++ b/common/usb.c @@ -28,6 +28,7 @@ #include <common.h> #include <command.h> #include <dm.h> +#include <dm/device_compat.h> #include <log.h> #include <malloc.h> #include <memalign.h> @@ -1084,6 +1085,54 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, return 0; } +static int usb_device_is_ignored(u16 id_vendor, u16 id_product) +{ + ulong vid, pid; + char *end; + const char *cur = NULL; + + /* ignore list depends on env support */ + if (!CONFIG_IS_ENABLED(ENV_SUPPORT)) + return 0; + + cur = env_get("usb_ignorelist"); + + /* parse "usb_ignorelist" strictly */ + while (cur && cur[0] != '\0') { + vid = simple_strtoul(cur, &end, 0); + /* + * If strtoul did not parse a single digit or the next char is + * not ':' the ignore list is malformed. + */ + if (cur == end || end[0] != ':') + return -EINVAL; + + cur = end + 1; + pid = simple_strtoul(cur, &end, 0); + /* Consider '*' as wildcard for the product ID */ + if (cur == end && end[0] == '*') { + pid = U16_MAX + 1; + end++; + } + /* + * The ignore list is malformed if no product ID / wildcard was + * parsed or entries are not separated by ',' or terminated with + * '\0'. + */ + if (cur == end || (end[0] != ',' && end[0] != '\0')) + return -EINVAL; + + if (id_vendor == vid && (pid > U16_MAX || id_product == pid)) + return -ENODEV; + + if (end[0] == '\0') + break; + cur = end + 1; + } + + return 0; +} + int usb_select_config(struct usb_device *dev) { unsigned char *tmpbuf = NULL; @@ -1099,6 +1148,27 @@ int usb_select_config(struct usb_device *dev) le16_to_cpus(&dev->descriptor.idProduct); le16_to_cpus(&dev->descriptor.bcdDevice); + /* ignore devices from usb_ignorelist */ + err = usb_device_is_ignored(dev->descriptor.idVendor, + dev->descriptor.idProduct); + if (err == -ENODEV) { + debug("Ignoring USB device 0x%x:0x%x\n", + dev->descriptor.idVendor, dev->descriptor.idProduct); + return err; + } else if (err == -EINVAL) { + /* + * Continue on "usb_ignorelist" parsing errors. The list is + * parsed for each device returning the error would result in + * ignoring all USB devices. + * Since the parsing error is independent of the probed device + * report errors with printf instead of dev_err. + */ + printf("usb_ignorelist parse error in \"%s\"\n", + env_get("usb_ignorelist")); + } else if (err < 0) { + return err; + } + /* * Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive * about this first Get Descriptor request. If there are any other diff --git a/common/usb_kbd.c b/common/usb_kbd.c index 4cbc9acb738..820f591fc5b 100644 --- a/common/usb_kbd.c +++ b/common/usb_kbd.c @@ -24,6 +24,18 @@ #include <usb.h> /* + * USB vendor and product IDs used for quirks. + */ +#define USB_VENDOR_ID_APPLE 0x05ac +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a +#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f + +#define USB_VENDOR_ID_KEYCHRON 0x3434 + +#define USB_HID_QUIRK_POLL_NO_REPORT_IDLE BIT(0) + +/* * If overwrite_console returns 1, the stdin, stderr and stdout * are switched to the serial port, else the settings in the * environment are used @@ -106,6 +118,8 @@ struct usb_kbd_pdata { unsigned long last_report; struct int_queue *intq; + uint32_t ifnum; + uint32_t repeat_delay; uint32_t usb_in_pointer; @@ -150,8 +164,8 @@ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c) */ static void usb_kbd_setled(struct usb_device *dev) { - struct usb_interface *iface = &dev->config.if_desc[0]; struct usb_kbd_pdata *data = dev->privptr; + struct usb_interface *iface = &dev->config.if_desc[data->ifnum]; ALLOC_ALIGN_BUFFER(uint32_t, leds, 1, USB_DMA_MINALIGN); *leds = data->flags & USB_KBD_LEDMASK; @@ -365,7 +379,7 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev) #if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP) struct usb_interface *iface; struct usb_kbd_pdata *data = dev->privptr; - iface = &dev->config.if_desc[0]; + iface = &dev->config.if_desc[data->ifnum]; usb_get_report(dev, iface->desc.bInterfaceNumber, 1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE); if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) { @@ -464,6 +478,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) struct usb_interface *iface; struct usb_endpoint_descriptor *ep; struct usb_kbd_pdata *data; + unsigned int quirks = 0; int epNum; if (dev->descriptor.bNumConfigurations != 1) @@ -496,6 +511,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress); + switch (dev->descriptor.idVendor) { + case USB_VENDOR_ID_APPLE: + case USB_VENDOR_ID_KEYCHRON: + quirks |= USB_HID_QUIRK_POLL_NO_REPORT_IDLE; + break; + default: + break; + } + data = malloc(sizeof(struct usb_kbd_pdata)); if (!data) { printf("USB KBD: Error allocating private data\n"); @@ -509,6 +533,8 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) data->new = memalign(USB_DMA_MINALIGN, roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN)); + data->ifnum = ifnum; + /* Insert private data into USB device structure */ dev->privptr = data; @@ -534,6 +560,14 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum) usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0); #endif + /* + * Apple and Keychron keyboards do not report the device state. Reports + * are only returned during key presses. + */ + if (quirks & USB_HID_QUIRK_POLL_NO_REPORT_IDLE) { + debug("USB KBD: quirk: skip testing device state\n"); + return 1; + } debug("USB KBD: enable interrupt pipe...\n"); #ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE data->intq = create_int_queue(dev, data->intpipe, 1, @@ -561,10 +595,17 @@ static int probe_usb_keyboard(struct usb_device *dev) { char *stdinname; struct stdio_dev usb_kbd_dev; + unsigned int ifnum; + unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES, + (unsigned int)dev->config.no_of_if); int error; /* Try probing the keyboard */ - if (usb_kbd_probe_dev(dev, 0) != 1) + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + if (usb_kbd_probe_dev(dev, ifnum) == 1) + break; + } + if (ifnum >= max_ifnum) return -ENOENT; /* Register the keyboard */ @@ -731,6 +772,18 @@ static const struct usb_device_id kbd_id_table[] = { .bInterfaceSubClass = USB_SUB_HID_BOOT, .bInterfaceProtocol = USB_PROT_HID_KEYBOARD, }, + { + USB_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021), + }, + { + USB_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021), + }, + { + USB_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021), + }, { } /* Terminating entry */ }; diff --git a/configs/am62px_evm_a53_defconfig b/configs/am62px_evm_a53_defconfig index 65dfda19f18..638d2e90a6b 100644 --- a/configs/am62px_evm_a53_defconfig +++ b/configs/am62px_evm_a53_defconfig @@ -70,6 +70,7 @@ CONFIG_CMD_TIME=y CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_MTDPARTS=y CONFIG_CMD_UBI=y +CONFIG_MMC_SPEED_MODE_SET=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_OF_UPSTREAM=y diff --git a/configs/am62x_evm_a53_defconfig b/configs/am62x_evm_a53_defconfig index d650b8575b6..6b37f8b4791 100644 --- a/configs/am62x_evm_a53_defconfig +++ b/configs/am62x_evm_a53_defconfig @@ -33,7 +33,7 @@ CONFIG_SPL_LOAD_FIT=y CONFIG_SPL_LOAD_FIT_ADDRESS=0x81000000 CONFIG_BOOTSTD_FULL=y CONFIG_SYS_BOOTM_LEN=0x800000 -CONFIG_BOOTCOMMAND="run envboot; bootflow scan -lb" +CONFIG_BOOTCOMMAND="run findfdt; run envboot; bootflow scan -lb" CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_MAX_SIZE=0x58000 CONFIG_SPL_SYS_REPORT_STACK_F_USAGE=y @@ -52,6 +52,7 @@ CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_CMD_BOOTEFI_SELFTEST=y CONFIG_CMD_NVEDIT_EFI=y CONFIG_CMD_MMC=y +CONFIG_MMC_SPEED_MODE_SET=y CONFIG_CMD_EFIDEBUG=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y diff --git a/configs/am64x_evm_a53_defconfig b/configs/am64x_evm_a53_defconfig index 61b498b49a6..8b0ccbabbef 100644 --- a/configs/am64x_evm_a53_defconfig +++ b/configs/am64x_evm_a53_defconfig @@ -75,6 +75,7 @@ CONFIG_CMD_EFIDEBUG=y CONFIG_CMD_TIME=y CONFIG_CMD_PMIC=y CONFIG_CMD_REGULATOR=y +CONFIG_MMC_SPEED_MODE_SET=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_OF_UPSTREAM=y diff --git a/configs/am65x_evm_a53_defconfig b/configs/am65x_evm_a53_defconfig index 500335f7e6e..3afa80f45a8 100644 --- a/configs/am65x_evm_a53_defconfig +++ b/configs/am65x_evm_a53_defconfig @@ -73,6 +73,7 @@ CONFIG_CMD_TIME=y CONFIG_MTDIDS_DEFAULT="nor0=47040000.spi.0" CONFIG_MTDPARTS_DEFAULT="mtdparts=47040000.spi.0:512k(ospi.tiboot3),2m(ospi.tispl),4m(ospi.u-boot),128k(ospi.env),128k(ospi.env.backup),1m(ospi.sysfw),-@8m(ospi.rootfs)" CONFIG_CMD_UBI=y +CONFIG_MMC_SPEED_MODE_SET=y # CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y diff --git a/configs/colibri_vf_defconfig b/configs/colibri_vf_defconfig index a5e6bcb64c0..0249dc3128b 100644 --- a/configs/colibri_vf_defconfig +++ b/configs/colibri_vf_defconfig @@ -17,6 +17,7 @@ CONFIG_SYS_MEMTEST_END=0x87c00000 CONFIG_ENV_VARS_UBOOT_CONFIG=y CONFIG_HAS_BOARD_SIZE_LIMIT=y CONFIG_BOARD_SIZE_LIMIT=520192 +# CONFIG_BOOTM is not set CONFIG_BOOTDELAY=1 CONFIG_FDT_FIXUP_PARTITIONS=y CONFIG_USE_BOOTCOMMAND=y @@ -33,7 +34,6 @@ CONFIG_HUSH_PARSER=y # CONFIG_SYS_LONGHELP is not set CONFIG_SYS_PROMPT="Colibri VFxx # " # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set CONFIG_CMD_BOOTZ=y # CONFIG_CMD_ELF is not set # CONFIG_CMD_IMI is not set diff --git a/configs/coreboot64_defconfig b/configs/coreboot64_defconfig index dab5eafe160..da42ad0a20a 100644 --- a/configs/coreboot64_defconfig +++ b/configs/coreboot64_defconfig @@ -16,6 +16,7 @@ CONFIG_BOOTSTD_FULL=y CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" +CONFIG_BOOTCOMMAND="bootflow scan -l; if bootflow menu; then cls; bootflow boot; fi" CONFIG_SYS_PBSIZE=532 CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_SYS_CONSOLE_INFO_QUIET=y @@ -59,6 +60,7 @@ CONFIG_SYS_NS16550_MEM32=y CONFIG_SOUND=y CONFIG_SOUND_I8254=y CONFIG_VIDEO_COPY=y +CONFIG_CONSOLE_TRUETYPE=y CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_SPL_ACPI=y CONFIG_CMD_DHRYSTONE=y diff --git a/configs/coreboot_defconfig b/configs/coreboot_defconfig index c846dfc2b91..0b103efe16d 100644 --- a/configs/coreboot_defconfig +++ b/configs/coreboot_defconfig @@ -14,6 +14,7 @@ CONFIG_BOOTSTD_FULL=y CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" +CONFIG_BOOTCOMMAND="bootflow scan -l; if bootflow menu; then cls; bootflow boot; fi" CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_SYS_CONSOLE_INFO_QUIET=y CONFIG_LOG=y @@ -53,6 +54,7 @@ CONFIG_SYS_NS16550_MEM32=y CONFIG_SOUND=y CONFIG_SOUND_I8254=y CONFIG_VIDEO_COPY=y +CONFIG_CONSOLE_TRUETYPE=y CONFIG_CONSOLE_SCROLL_LINES=5 CONFIG_CMD_DHRYSTONE=y # CONFIG_GZIP is not set diff --git a/configs/iot_devkit_defconfig b/configs/iot_devkit_defconfig index c4920052f82..d02a28abfab 100644 --- a/configs/iot_devkit_defconfig +++ b/configs/iot_devkit_defconfig @@ -14,12 +14,12 @@ CONFIG_DEFAULT_DEVICE_TREE="iot_devkit" CONFIG_SYS_CLK_FREQ=16000000 CONFIG_SYS_LOAD_ADDR=0x30000000 CONFIG_LOCALVERSION="-iotdk-1.0" +# CONFIG_BOOTM is not set # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set CONFIG_SYS_CBSIZE=256 CONFIG_SYS_PBSIZE=280 CONFIG_SYS_PROMPT="IoTDK# " # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_XIMG is not set # CONFIG_CMD_LOADB is not set diff --git a/configs/milkv_duo_defconfig b/configs/milkv_duo_defconfig index 548adf174c6..e8413d7aa94 100644 --- a/configs/milkv_duo_defconfig +++ b/configs/milkv_duo_defconfig @@ -17,6 +17,16 @@ CONFIG_SYS_CBSIZE=512 CONFIG_SYS_PBSIZE=544 CONFIG_HUSH_PARSER=y CONFIG_SYS_PROMPT="milkv_duo# " +CONFIG_CMD_MMC=y +CONFIG_CMD_PART=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y CONFIG_ENV_OVERWRITE=y +CONFIG_MMC=y +CONFIG_MMC_IO_VOLTAGE=y +CONFIG_MMC_UHS_SUPPORT=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_ADMA=y +CONFIG_MMC_SDHCI_CV1800B=y CONFIG_SYS_NS16550=y CONFIG_SYS_NS16550_MEM32=y diff --git a/configs/mx6memcal_defconfig b/configs/mx6memcal_defconfig index 7f11e6f5d45..6c5481cd6ed 100644 --- a/configs/mx6memcal_defconfig +++ b/configs/mx6memcal_defconfig @@ -14,6 +14,7 @@ CONFIG_SPL_SERIAL=y CONFIG_SPL=y CONFIG_SYS_MEMTEST_START=0x10000000 CONFIG_SYS_MEMTEST_END=0x20000000 +# CONFIG_BOOTM is not set CONFIG_SUPPORT_RAW_INITRD=y CONFIG_SYS_PBSIZE=528 CONFIG_SPL_SYS_MALLOC=y @@ -21,7 +22,6 @@ CONFIG_SPL_WATCHDOG=y CONFIG_HUSH_PARSER=y CONFIG_SYS_MAXARGS=32 # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_IMI is not set # CONFIG_CMD_XIMG is not set diff --git a/configs/phycore_am62x_a53_defconfig b/configs/phycore_am62x_a53_defconfig index 552b7e91396..08a2532d398 100644 --- a/configs/phycore_am62x_a53_defconfig +++ b/configs/phycore_am62x_a53_defconfig @@ -33,6 +33,7 @@ CONFIG_BOOTSTD_FULL=y CONFIG_SYS_BOOTM_LEN=0x800000 CONFIG_BOOTCOMMAND="run mmcboot; bootflow scan -lb" CONFIG_DEFAULT_FDT_FILE="oftree" +CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_MAX_SIZE=0x58000 CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x80c80000 diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 451af0bda68..008eb46a01c 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -6,7 +6,7 @@ CONFIG_ENV_SIZE=0x40000 CONFIG_MAX_CPUS=2 CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="qemu-x86_i440fx" -CONFIG_SPL_TEXT_BASE=0xfffd8000 +CONFIG_SPL_TEXT_BASE=0xfffd4000 CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000 CONFIG_DEBUG_UART_BASE=0x3f8 CONFIG_DEBUG_UART_CLOCK=1843200 @@ -17,7 +17,7 @@ CONFIG_DEBUG_UART=y CONFIG_SMP=y CONFIG_GENERATE_PIRQ_TABLE=y CONFIG_GENERATE_MP_TABLE=y -CONFIG_X86_OFFSET_U_BOOT=0xfff00000 +CONFIG_X86_OFFSET_U_BOOT=0xffe00000 CONFIG_SYS_MONITOR_BASE=0x01110000 CONFIG_FIT=y CONFIG_SPL_LOAD_FIT=y @@ -80,6 +80,7 @@ CONFIG_SPL_DM_RTC=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y +CONFIG_CONSOLE_TRUETYPE=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_USER=y CONFIG_FRAMEBUFFER_VESA_MODE=0x144 diff --git a/configs/qemu-x86_defconfig b/configs/qemu-x86_defconfig index b2a221b12a3..947d15cd727 100644 --- a/configs/qemu-x86_defconfig +++ b/configs/qemu-x86_defconfig @@ -57,6 +57,7 @@ CONFIG_NVME_PCI=y CONFIG_SYS_NS16550_PORT_MAPPED=y CONFIG_SPI=y CONFIG_USB_KEYBOARD=y +CONFIG_CONSOLE_TRUETYPE=y CONFIG_FRAMEBUFFER_SET_VESA_MODE=y CONFIG_FRAMEBUFFER_VESA_MODE_USER=y CONFIG_FRAMEBUFFER_VESA_MODE=0x144 diff --git a/configs/socfpga_chameleonv3_defconfig b/configs/socfpga_chameleonv3_defconfig index 6ea61ca6ea9..7506aa8d329 100644 --- a/configs/socfpga_chameleonv3_defconfig +++ b/configs/socfpga_chameleonv3_defconfig @@ -7,6 +7,7 @@ CONFIG_DEFAULT_DEVICE_TREE="socfpga_arria10_chameleonv3_480_2" CONFIG_SPL_TEXT_BASE=0xFFE00000 CONFIG_SPL_DRIVERS_MISC=y CONFIG_TARGET_SOCFPGA_CHAMELEONV3=y +CONFIG_SOCFPGA_ARRIA10_ALWAYS_REPROGRAM=y CONFIG_SPL_FS_FAT=y CONFIG_FIT=y CONFIG_SPL_FIT=y diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig index 7a3f1d4dbdf..fa80d489f5e 100644 --- a/configs/starfive_visionfive2_defconfig +++ b/configs/starfive_visionfive2_defconfig @@ -40,7 +40,6 @@ CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="console=ttyS0,115200 debug rootwait earlycon=sbi" CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="nvme scan; usb start; setenv fdt_addr ${fdtcontroladdr}; fdt addr ${fdtcontroladdr};" -CONFIG_DEFAULT_FDT_FILE="starfive/jh7110-starfive-visionfive-2.dtb" CONFIG_SYS_CBSIZE=256 CONFIG_SYS_PBSIZE=276 CONFIG_DISPLAY_CPUINFO=y diff --git a/configs/tools-only_defconfig b/configs/tools-only_defconfig index b54d2cefa10..5de482a0d84 100644 --- a/configs/tools-only_defconfig +++ b/configs/tools-only_defconfig @@ -12,10 +12,10 @@ CONFIG_FIT_SIGNATURE=y # CONFIG_BOOTSTD_FULL is not set # CONFIG_BOOTMETH_CROS is not set # CONFIG_BOOTMETH_VBE is not set +# CONFIG_BOOTM is not set CONFIG_USE_BOOTCOMMAND=y CONFIG_BOOTCOMMAND="run distro_bootcmd" # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_EXTENSION is not set diff --git a/configs/verdin-am62_a53_defconfig b/configs/verdin-am62_a53_defconfig index 15424fedb90..633e9c7398e 100644 --- a/configs/verdin-am62_a53_defconfig +++ b/configs/verdin-am62_a53_defconfig @@ -14,7 +14,7 @@ CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80b80000 CONFIG_ENV_SIZE=0x2000 CONFIG_ENV_OFFSET=0xFFFFDE00 CONFIG_DM_GPIO=y -CONFIG_DEFAULT_DEVICE_TREE="k3-am625-verdin-wifi-dev" +CONFIG_DEFAULT_DEVICE_TREE="ti/k3-am625-verdin-wifi-dev" CONFIG_SPL_TEXT_BASE=0x80080000 CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_DM_RESET=y diff --git a/configs/xilinx_mbv32_defconfig b/configs/xilinx_mbv32_defconfig index 2689495057b..4113409efbb 100644 --- a/configs/xilinx_mbv32_defconfig +++ b/configs/xilinx_mbv32_defconfig @@ -1,30 +1,43 @@ CONFIG_RISCV=y -CONFIG_TEXT_BASE=0x21200000 -CONFIG_SYS_MALLOC_LEN=0x800000 +CONFIG_SYS_MALLOC_LEN=0xe00000 CONFIG_NR_DRAM_BANKS=1 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x20200000 +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x21200000 CONFIG_ENV_SIZE=0x20000 CONFIG_DEFAULT_DEVICE_TREE="xilinx-mbv32" +CONFIG_SPL_STACK=0x20200000 +CONFIG_SPL_SIZE_LIMIT=0x40000 +CONFIG_SPL=y CONFIG_DEBUG_UART_BASE=0x40600000 CONFIG_DEBUG_UART_CLOCK=1000000 CONFIG_SYS_CLK_FREQ=100000000 CONFIG_BOOT_SCRIPT_OFFSET=0x0 -CONFIG_SYS_LOAD_ADDR=0x80200000 +CONFIG_SYS_LOAD_ADDR=0x20200000 CONFIG_DEBUG_UART=y CONFIG_TARGET_XILINX_MBV=y +# CONFIG_SPL_SMP is not set +CONFIG_REMAKE_ELF=y CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x20200000 CONFIG_DISTRO_DEFAULTS=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y # CONFIG_BOARD_LATE_INIT is not set +CONFIG_SPL_MAX_SIZE=0x40000 +CONFIG_SPL_BSS_START_ADDR=0x24000000 +CONFIG_SPL_BSS_MAX_SIZE=0x80000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_SYS_MALLOC_SIZE=0x800000 # CONFIG_CMD_MII is not set CONFIG_CMD_TIMER=y -CONFIG_OF_EMBED=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DM_MTD=y CONFIG_DEBUG_UART_ANNOUNCE=y CONFIG_DEBUG_UART_SKIP_INIT=y CONFIG_XILINX_UARTLITE=y CONFIG_XILINX_TIMER=y +# CONFIG_BINMAN_FDT is not set CONFIG_PANIC_HANG=y +CONFIG_SPL_GZIP=y diff --git a/configs/xilinx_mbv32_smode_defconfig b/configs/xilinx_mbv32_smode_defconfig index c724d1bad74..99381478ac5 100644 --- a/configs/xilinx_mbv32_smode_defconfig +++ b/configs/xilinx_mbv32_smode_defconfig @@ -1,27 +1,40 @@ CONFIG_RISCV=y -CONFIG_TEXT_BASE=0x21200000 -CONFIG_SYS_MALLOC_LEN=0x800000 +CONFIG_SYS_MALLOC_LEN=0xe00000 CONFIG_NR_DRAM_BANKS=1 CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y -CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x20200000 +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x21200000 CONFIG_ENV_SIZE=0x20000 CONFIG_DEFAULT_DEVICE_TREE="xilinx-mbv32" +CONFIG_SPL_STACK=0x20200000 +CONFIG_SPL_SIZE_LIMIT=0x40000 +CONFIG_SPL=y CONFIG_DEBUG_UART_BASE=0x40600000 CONFIG_DEBUG_UART_CLOCK=1000000 CONFIG_SYS_CLK_FREQ=100000000 CONFIG_BOOT_SCRIPT_OFFSET=0x0 -CONFIG_SYS_LOAD_ADDR=0x80200000 +CONFIG_SYS_LOAD_ADDR=0x20200000 CONFIG_TARGET_XILINX_MBV=y +CONFIG_SPL_OPENSBI_LOAD_ADDR=0x20100000 CONFIG_RISCV_SMODE=y +# CONFIG_SPL_SMP is not set +CONFIG_REMAKE_ELF=y CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x20200000 CONFIG_DISTRO_DEFAULTS=y CONFIG_DISPLAY_CPUINFO=y CONFIG_DISPLAY_BOARDINFO=y # CONFIG_BOARD_LATE_INIT is not set +CONFIG_SPL_MAX_SIZE=0x40000 +CONFIG_SPL_BSS_START_ADDR=0x24000000 +CONFIG_SPL_BSS_MAX_SIZE=0x80000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_SYS_MALLOC_SIZE=0x800000 +CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x2 # CONFIG_CMD_MII is not set CONFIG_CMD_TIMER=y -CONFIG_OF_EMBED=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_DM_MTD=y CONFIG_DEBUG_UART_UARTLITE=y CONFIG_DEBUG_UART_ANNOUNCE=y @@ -29,4 +42,6 @@ CONFIG_DEBUG_UART_SKIP_INIT=y CONFIG_XILINX_UARTLITE=y # CONFIG_RISCV_TIMER is not set CONFIG_XILINX_TIMER=y +# CONFIG_BINMAN_FDT is not set CONFIG_PANIC_HANG=y +CONFIG_SPL_GZIP=y diff --git a/configs/xilinx_versal_mini_defconfig b/configs/xilinx_versal_mini_defconfig index 9d3924cc9cb..143d2622748 100644 --- a/configs/xilinx_versal_mini_defconfig +++ b/configs/xilinx_versal_mini_defconfig @@ -18,6 +18,7 @@ CONFIG_SYS_MEMTEST_START=0x00000000 CONFIG_SYS_MEMTEST_END=0x00001000 # CONFIG_EXPERT is not set CONFIG_REMAKE_ELF=y +# CONFIG_BOOTM is not set # CONFIG_LEGACY_IMAGE_FORMAT is not set # CONFIG_AUTOBOOT is not set CONFIG_SYS_CBSIZE=1024 @@ -33,7 +34,6 @@ CONFIG_CLOCKS=y CONFIG_SYS_PROMPT="Versal> " # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_mini_emmc0_defconfig b/configs/xilinx_versal_mini_emmc0_defconfig index 5c949e34442..b0e346208e0 100644 --- a/configs/xilinx_versal_mini_emmc0_defconfig +++ b/configs/xilinx_versal_mini_emmc0_defconfig @@ -15,6 +15,7 @@ CONFIG_DEFAULT_DEVICE_TREE="versal-mini-emmc0" CONFIG_SYS_LOAD_ADDR=0x8000000 # CONFIG_EXPERT is not set CONFIG_REMAKE_ELF=y +# CONFIG_BOOTM is not set # CONFIG_AUTOBOOT is not set CONFIG_SYS_CBSIZE=1024 CONFIG_SYS_PBSIZE=1049 @@ -30,7 +31,6 @@ CONFIG_SYS_PROMPT="Versal> " # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_mini_emmc1_defconfig b/configs/xilinx_versal_mini_emmc1_defconfig index 04cba5bc72d..559b32c2a19 100644 --- a/configs/xilinx_versal_mini_emmc1_defconfig +++ b/configs/xilinx_versal_mini_emmc1_defconfig @@ -15,6 +15,7 @@ CONFIG_DEFAULT_DEVICE_TREE="versal-mini-emmc1" CONFIG_SYS_LOAD_ADDR=0x8000000 # CONFIG_EXPERT is not set CONFIG_REMAKE_ELF=y +# CONFIG_BOOTM is not set # CONFIG_AUTOBOOT is not set CONFIG_SYS_CBSIZE=1024 CONFIG_SYS_PBSIZE=1049 @@ -30,7 +31,6 @@ CONFIG_SYS_PROMPT="Versal> " # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_mini_ospi_defconfig b/configs/xilinx_versal_mini_ospi_defconfig index 7a110350c2c..c02c6ba40db 100644 --- a/configs/xilinx_versal_mini_ospi_defconfig +++ b/configs/xilinx_versal_mini_ospi_defconfig @@ -19,6 +19,7 @@ CONFIG_SYS_LOAD_ADDR=0x8000000 CONFIG_LTO=y # CONFIG_EXPERT is not set CONFIG_REMAKE_ELF=y +# CONFIG_BOOTM is not set # CONFIG_AUTOBOOT is not set CONFIG_SYS_CONSOLE_INFO_QUIET=y # CONFIG_DISPLAY_CPUINFO is not set @@ -31,7 +32,6 @@ CONFIG_SYS_PROMPT="Versal> " # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_mini_qspi_defconfig b/configs/xilinx_versal_mini_qspi_defconfig index 58945a1cac9..4d4b59a22ff 100644 --- a/configs/xilinx_versal_mini_qspi_defconfig +++ b/configs/xilinx_versal_mini_qspi_defconfig @@ -17,6 +17,7 @@ CONFIG_SYS_LOAD_ADDR=0x8000000 CONFIG_LTO=y # CONFIG_EXPERT is not set CONFIG_REMAKE_ELF=y +# CONFIG_BOOTM is not set # CONFIG_AUTOBOOT is not set # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set CONFIG_LOGLEVEL=0 @@ -32,7 +33,6 @@ CONFIG_SYS_PROMPT="Versal> " # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_net_mini_defconfig b/configs/xilinx_versal_net_mini_defconfig index 7dac1ec54eb..317fc8e2e15 100644 --- a/configs/xilinx_versal_net_mini_defconfig +++ b/configs/xilinx_versal_net_mini_defconfig @@ -20,6 +20,7 @@ CONFIG_SYS_MEMTEST_START=0x00000000 CONFIG_SYS_MEMTEST_END=0x00001000 # CONFIG_EXPERT is not set CONFIG_REMAKE_ELF=y +# CONFIG_BOOTM is not set # CONFIG_LEGACY_IMAGE_FORMAT is not set # CONFIG_AUTOBOOT is not set # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set @@ -33,7 +34,6 @@ CONFIG_BOARD_EARLY_INIT_R=y CONFIG_SYS_PROMPT="Versal NET> " # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_net_mini_emmc_defconfig b/configs/xilinx_versal_net_mini_emmc_defconfig index fc88eee10af..31c44323666 100644 --- a/configs/xilinx_versal_net_mini_emmc_defconfig +++ b/configs/xilinx_versal_net_mini_emmc_defconfig @@ -25,7 +25,7 @@ CONFIG_SYS_PROMPT="Versal NET> " # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set +# CONFIG_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_net_mini_ospi_defconfig b/configs/xilinx_versal_net_mini_ospi_defconfig index d78c9f80599..d0d91f98230 100644 --- a/configs/xilinx_versal_net_mini_ospi_defconfig +++ b/configs/xilinx_versal_net_mini_ospi_defconfig @@ -30,7 +30,7 @@ CONFIG_SYS_PROMPT="Versal NET> " # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set +# CONFIG_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_net_mini_qspi_defconfig b/configs/xilinx_versal_net_mini_qspi_defconfig index b0567f857a3..48b6d86f9b3 100644 --- a/configs/xilinx_versal_net_mini_qspi_defconfig +++ b/configs/xilinx_versal_net_mini_qspi_defconfig @@ -31,7 +31,7 @@ CONFIG_SYS_PROMPT="Versal NET> " # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set +# CONFIG_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_versal_net_virt_defconfig b/configs/xilinx_versal_net_virt_defconfig index 29cebe27136..40c6a29a16e 100644 --- a/configs/xilinx_versal_net_virt_defconfig +++ b/configs/xilinx_versal_net_virt_defconfig @@ -60,6 +60,9 @@ CONFIG_PARTITION_TYPE_GUID=y CONFIG_OF_BOARD=y CONFIG_DTB_RESELECT=y CONFIG_MULTI_DTB_FIT=y +CONFIG_ENV_IS_NOWHERE=y +CONFIG_ENV_IS_IN_FAT=y +CONFIG_ENV_IS_IN_SPI_FLASH=y CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y diff --git a/configs/xilinx_zynqmp_kria_defconfig b/configs/xilinx_zynqmp_kria_defconfig index 7cb8b62d325..7af8b27be93 100644 --- a/configs/xilinx_zynqmp_kria_defconfig +++ b/configs/xilinx_zynqmp_kria_defconfig @@ -155,7 +155,6 @@ CONFIG_MMC_HS200_SUPPORT=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_ZYNQ=y CONFIG_DM_MTD=y -CONFIG_SPI_FLASH_BAR=y CONFIG_SPI_FLASH_STMICRO=y # CONFIG_SPI_FLASH_USE_4K_SECTORS is not set CONFIG_SPI_FLASH_MTD=y diff --git a/configs/xilinx_zynqmp_mini_defconfig b/configs/xilinx_zynqmp_mini_defconfig index 7fdd2eee555..40d4a4a5859 100644 --- a/configs/xilinx_zynqmp_mini_defconfig +++ b/configs/xilinx_zynqmp_mini_defconfig @@ -13,6 +13,7 @@ CONFIG_SYS_LOAD_ADDR=0x8000000 CONFIG_SYS_MEMTEST_START=0x00000000 CONFIG_SYS_MEMTEST_END=0x00001000 CONFIG_REMAKE_ELF=y +# CONFIG_BOOTM is not set # CONFIG_LEGACY_IMAGE_FORMAT is not set # CONFIG_AUTOBOOT is not set CONFIG_SYS_CBSIZE=1024 @@ -26,7 +27,6 @@ CONFIG_CLOCKS=y # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_zynqmp_mini_emmc0_defconfig b/configs/xilinx_zynqmp_mini_emmc0_defconfig index bf34832d22c..9cccf5d486f 100644 --- a/configs/xilinx_zynqmp_mini_emmc0_defconfig +++ b/configs/xilinx_zynqmp_mini_emmc0_defconfig @@ -17,6 +17,7 @@ CONFIG_SYS_LOAD_ADDR=0x8000000 CONFIG_REMAKE_ELF=y # CONFIG_MP is not set CONFIG_FIT=y +# CONFIG_BOOTM is not set CONFIG_SUPPORT_RAW_INITRD=y # CONFIG_AUTOBOOT is not set CONFIG_SYS_CBSIZE=1024 @@ -37,7 +38,6 @@ CONFIG_SPL_SYS_MALLOC_SIZE=0x1000000 # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_zynqmp_mini_emmc1_defconfig b/configs/xilinx_zynqmp_mini_emmc1_defconfig index af70ccfae12..3919e23539a 100644 --- a/configs/xilinx_zynqmp_mini_emmc1_defconfig +++ b/configs/xilinx_zynqmp_mini_emmc1_defconfig @@ -17,6 +17,7 @@ CONFIG_SYS_LOAD_ADDR=0x8000000 CONFIG_REMAKE_ELF=y # CONFIG_MP is not set CONFIG_FIT=y +# CONFIG_BOOTM is not set CONFIG_SUPPORT_RAW_INITRD=y # CONFIG_AUTOBOOT is not set CONFIG_SYS_CBSIZE=1024 @@ -37,7 +38,6 @@ CONFIG_SPL_SYS_MALLOC_SIZE=0x1000000 # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/xilinx_zynqmp_mini_nand_defconfig b/configs/xilinx_zynqmp_mini_nand_defconfig index d2e920fc573..ae0c3ae7186 100644 --- a/configs/xilinx_zynqmp_mini_nand_defconfig +++ b/configs/xilinx_zynqmp_mini_nand_defconfig @@ -13,6 +13,7 @@ CONFIG_SYS_LOAD_ADDR=0x8000000 CONFIG_REMAKE_ELF=y # CONFIG_MP is not set CONFIG_FIT=y +# CONFIG_BOOTM is not set CONFIG_SUPPORT_RAW_INITRD=y # CONFIG_AUTOBOOT is not set CONFIG_SYS_CBSIZE=1024 @@ -27,7 +28,6 @@ CONFIG_CLOCKS=y # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_GO is not set # CONFIG_CMD_RUN is not set diff --git a/configs/xilinx_zynqmp_mini_nand_single_defconfig b/configs/xilinx_zynqmp_mini_nand_single_defconfig index 31f647357f7..15d471caf70 100644 --- a/configs/xilinx_zynqmp_mini_nand_single_defconfig +++ b/configs/xilinx_zynqmp_mini_nand_single_defconfig @@ -13,6 +13,7 @@ CONFIG_SYS_LOAD_ADDR=0x8000000 CONFIG_REMAKE_ELF=y # CONFIG_MP is not set CONFIG_FIT=y +# CONFIG_BOOTM is not set CONFIG_SUPPORT_RAW_INITRD=y # CONFIG_AUTOBOOT is not set CONFIG_SYS_CBSIZE=1024 @@ -27,7 +28,6 @@ CONFIG_CLOCKS=y # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_GO is not set # CONFIG_CMD_RUN is not set diff --git a/configs/xilinx_zynqmp_mini_qspi_defconfig b/configs/xilinx_zynqmp_mini_qspi_defconfig index 096feeb83cd..071784c493b 100644 --- a/configs/xilinx_zynqmp_mini_qspi_defconfig +++ b/configs/xilinx_zynqmp_mini_qspi_defconfig @@ -19,6 +19,7 @@ CONFIG_ZYNQMP_NO_DDR=y CONFIG_SYS_LOAD_ADDR=0x8000000 # CONFIG_EXPERT is not set CONFIG_REMAKE_ELF=y +# CONFIG_BOOTM is not set # CONFIG_LEGACY_IMAGE_FORMAT is not set # CONFIG_AUTOBOOT is not set # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set @@ -41,7 +42,6 @@ CONFIG_SPL_SYS_MALLOC_SIZE=0x1000000 # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_BOOTI is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set diff --git a/configs/zynq_cse_nand_defconfig b/configs/zynq_cse_nand_defconfig index 0dbc80442bb..982777b910c 100644 --- a/configs/zynq_cse_nand_defconfig +++ b/configs/zynq_cse_nand_defconfig @@ -19,6 +19,7 @@ CONFIG_SYS_LOAD_ADDR=0x0 CONFIG_REMAKE_ELF=y CONFIG_SYS_CUSTOM_LDSCRIPT=y CONFIG_SYS_LDSCRIPT="arch/arm/mach-zynq/u-boot.lds" +# CONFIG_BOOTM is not set # CONFIG_AUTOBOOT is not set CONFIG_USE_PREBOOT=y CONFIG_SYS_CBSIZE=1024 @@ -43,7 +44,6 @@ CONFIG_SYS_MAXARGS=32 # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set # CONFIG_CMD_GO is not set diff --git a/configs/zynq_cse_nor_defconfig b/configs/zynq_cse_nor_defconfig index d95f7602d68..7d70dae5e9d 100644 --- a/configs/zynq_cse_nor_defconfig +++ b/configs/zynq_cse_nor_defconfig @@ -19,6 +19,7 @@ CONFIG_SYS_LOAD_ADDR=0x0 CONFIG_REMAKE_ELF=y CONFIG_SYS_CUSTOM_LDSCRIPT=y CONFIG_SYS_LDSCRIPT="arch/arm/mach-zynq/u-boot.lds" +# CONFIG_BOOTM is not set # CONFIG_AUTOBOOT is not set CONFIG_USE_PREBOOT=y CONFIG_SYS_CBSIZE=1024 @@ -43,7 +44,6 @@ CONFIG_SYS_MAXARGS=32 # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set # CONFIG_CMD_GO is not set diff --git a/configs/zynq_cse_qspi_defconfig b/configs/zynq_cse_qspi_defconfig index dd7f978c494..c7477aa9c61 100644 --- a/configs/zynq_cse_qspi_defconfig +++ b/configs/zynq_cse_qspi_defconfig @@ -25,6 +25,7 @@ CONFIG_DEBUG_UART=y CONFIG_REMAKE_ELF=y CONFIG_SYS_CUSTOM_LDSCRIPT=y CONFIG_SYS_LDSCRIPT="arch/arm/mach-zynq/u-boot.lds" +# CONFIG_BOOTM is not set # CONFIG_AUTOBOOT is not set # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set CONFIG_USE_PREBOOT=y @@ -52,7 +53,6 @@ CONFIG_SYS_MAXARGS=32 # CONFIG_CMD_BDI is not set # CONFIG_CMD_CONSOLE is not set # CONFIG_CMD_BOOTD is not set -# CONFIG_CMD_BOOTM is not set # CONFIG_CMD_ELF is not set # CONFIG_CMD_FDT is not set # CONFIG_CMD_GO is not set diff --git a/disk/part.c b/disk/part.c index 36b88205eca..2bee6695828 100644 --- a/disk/part.c +++ b/disk/part.c @@ -14,6 +14,7 @@ #include <malloc.h> #include <part.h> #include <ubifs_uboot.h> +#include <dm/uclass.h> #undef PART_DEBUG @@ -305,50 +306,8 @@ static void print_part_header(const char *type, struct blk_desc *desc) CONFIG_IS_ENABLED(ISO_PARTITION) || \ CONFIG_IS_ENABLED(AMIGA_PARTITION) || \ CONFIG_IS_ENABLED(EFI_PARTITION) - puts ("\nPartition Map for "); - switch (desc->uclass_id) { - case UCLASS_IDE: - puts ("IDE"); - break; - case UCLASS_AHCI: - puts ("SATA"); - break; - case UCLASS_SCSI: - puts ("SCSI"); - break; - case UCLASS_USB: - puts ("USB"); - break; - case UCLASS_MMC: - puts ("MMC"); - break; - case UCLASS_HOST: - puts ("HOST"); - break; - case UCLASS_NVME: - puts ("NVMe"); - break; - case UCLASS_PVBLOCK: - puts("PV BLOCK"); - break; - case UCLASS_RKMTD: - puts("RKMTD"); - break; - case UCLASS_VIRTIO: - puts("VirtIO"); - break; - case UCLASS_EFI_MEDIA: - puts("EFI"); - break; - case UCLASS_BLKMAP: - puts("BLKMAP"); - break; - default: - printf("UNKNOWN(%d)", desc->uclass_id); - break; - } - printf (" device %d -- Partition Type: %s\n\n", - desc->devnum, type); + printf("\nPartition Map for %s device %d -- Partition Type: %s\n\n", + uclass_get_name(desc->uclass_id), desc->devnum, type); #endif /* any CONFIG_..._PARTITION */ } @@ -717,8 +676,11 @@ int part_get_info_by_name(struct blk_desc *desc, const char *name, for (i = 1; i < part_drv->max_entries; i++) { ret = part_drv->get_info(desc, i, info); if (ret != 0) { - /* no more entries in table */ - break; + /* + * Partition with this index can't be obtained, but + * further partitions might be, so keep checking. + */ + continue; } if (strcmp(name, (const char *)info->name) == 0) { /* matched */ diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst index 05d8f777595..9e337cae2cb 100644 --- a/doc/android/fastboot.rst +++ b/doc/android/fastboot.rst @@ -128,6 +128,7 @@ Boot command When executing the fastboot ``boot`` command, if ``fastboot_bootcmd`` is set then that will be executed in place of ``bootm <CONFIG_FASTBOOT_BUF_ADDR>``. +This is supported if CONFIG_CMDLINE is enabled, which it normally is. Partition Names --------------- diff --git a/doc/board/emulation/qemu-x86.rst b/doc/board/emulation/qemu-x86.rst index c604e42990e..4eeba46ba7a 100644 --- a/doc/board/emulation/qemu-x86.rst +++ b/doc/board/emulation/qemu-x86.rst @@ -134,7 +134,7 @@ The output will be something like this:: U-Boot SPL 2023.07 (Jul 23 2023 - 08:00:12 -0600) Trying to boot from SPI - Jumping to 64-bit U-Boot: Note many features are missing + Jumping to 64-bit U-Boot U-Boot 2023.07 (Jul 23 2023 - 08:00:12 -0600) diff --git a/doc/board/starfive/index.rst b/doc/board/starfive/index.rst index 0c52dc7b095..2762bf74c11 100644 --- a/doc/board/starfive/index.rst +++ b/doc/board/starfive/index.rst @@ -6,4 +6,5 @@ StarFive .. toctree:: :maxdepth: 1 + milk-v_mars.rst visionfive2 diff --git a/doc/board/starfive/milk-v_mars.rst b/doc/board/starfive/milk-v_mars.rst new file mode 100644 index 00000000000..554932ecfd4 --- /dev/null +++ b/doc/board/starfive/milk-v_mars.rst @@ -0,0 +1,111 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Milk-V Mars +=========== + +U-Boot for the Milk-V Mars uses the same U-Boot binaries as the VisionFive 2 +board. In U-Boot SPL the actual board is detected and the device-tree patched +accordingly. + +Building +~~~~~~~~ + +1. Add the RISC-V toolchain to your PATH. +2. Setup ARCH & cross compilation environment variable: + +.. code-block:: none + + export CROSS_COMPILE=<riscv64 toolchain prefix> + +The M-mode software OpenSBI provides the supervisor binary interface (SBI) and +is responsible for the switch to S-Mode. It is a prerequisite to build U-Boot. +Support for the JH7110 was introduced in OpenSBI 1.2. It is recommended to use +a current release. + +.. code-block:: console + + git clone https://github.com/riscv/opensbi.git + cd opensbi + make PLATFORM=generic FW_TEXT_START=0x40000000 FW_OPTIONS=0 + +Now build the U-Boot SPL and U-Boot proper. + +.. code-block:: console + + cd <U-Boot-dir> + make starfive_visionfive2_defconfig + make OPENSBI=$(opensbi_dir)/build/platform/generic/firmware/fw_dynamic.bin + +This will generate the U-Boot SPL image (spl/u-boot-spl.bin.normal.out) as well +as the FIT image (u-boot.itb) with OpenSBI and U-Boot. + +Device-tree selection +~~~~~~~~~~~~~~~~~~~~~ + +Depending on the board version U-Boot set variable $fdtfile to either +starfive/jh7110-starfive-visionfive-2-v1.2a.dtb or +starfive/jh7110-starfive-visionfive-2-v1.3b.dtb. + +To overrule this selection the variable can be set manually and saved in the +environment + +:: + + setenv fdtfile my_device-tree.dtb + env save + +or the configuration variable CONFIG_DEFAULT_FDT_FILE can be used to set to +provide a default value. + +Boot source selection +~~~~~~~~~~~~~~~~~~~~~ + +The board provides the DIP switches MSEL[1:0] to select the boot device out of +SPI flash, eMMC, SD-card, UART. To select booting from SD-card set the DIP +switches MSEL[1:0] to 10. + +Preparing the SD-Card +~~~~~~~~~~~~~~~~~~~~~ + +The device firmware loads U-Boot SPL (u-boot-spl.bin.normal.out) from the +partition with type GUID 2E54B353-1271-4842-806F-E436D6AF6985. You are free +to choose any partition number. + +With the default configuration U-Boot SPL loads the U-Boot FIT image +(u-boot.itb) from partition 2 (CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION=0x2). +When formatting it is recommended to use GUID +BC13C2FF-59E6-4262-A352-B275FD6F7172 for this partition. + +The FIT image (u-boot.itb) is a combination of OpenSBI's fw_dynamic.bin, +u-boot-nodtb.bin and the device tree blob. + +Format the SD card (make sure the disk has GPT, otherwise use gdisk to switch) + +.. code-block:: bash + + sudo sgdisk --clear \ + --set-alignment=2 \ + --new=1:4096:8191 --change-name=1:spl --typecode=1:2E54B353-1271-4842-806F-E436D6AF6985\ + --new=2:8192:16383 --change-name=2:uboot --typecode=2:BC13C2FF-59E6-4262-A352-B275FD6F7172 \ + --new=3:16384:1654784 --change-name=3:system --typecode=3:EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 \ + /dev/sdb + +Copy U-Boot to the SD card + +.. code-block:: bash + + sudo dd if=u-boot-spl.bin.normal.out of=/dev/sdb1 + sudo dd if=u-boot.itb of=/dev/sdb2 + + sudo mount /dev/sdb3 /mnt/ + sudo cp u-boot-spl.bin.normal.out /mnt/ + sudo cp u-boot.itb /mnt/ + sudo cp Image.gz /mnt/ + sudo cp initramfs.cpio.gz /mnt/ + sudo cp jh7110-starfive-visionfive-2.dtb /mnt/ + sudo umount /mnt + +Booting +~~~~~~~ + +Once you plugin the sdcard and power up, you should see the U-Boot prompt. diff --git a/doc/board/starfive/visionfive2.rst b/doc/board/starfive/visionfive2.rst index abda8ac21bc..2c68df3ce4d 100644 --- a/doc/board/starfive/visionfive2.rst +++ b/doc/board/starfive/visionfive2.rst @@ -71,6 +71,24 @@ Now build the U-Boot SPL and U-Boot proper This will generate the U-Boot SPL image (spl/u-boot-spl.bin.normal.out) as well as the FIT image (u-boot.itb) with OpenSBI and U-Boot. +Device-tree selection +~~~~~~~~~~~~~~~~~~~~~ + +Depending on the board version U-Boot set variable $fdtfile to either +starfive/jh7110-starfive-visionfive-2-v1.2a.dtb or +starfive/jh7110-starfive-visionfive-2-v1.3b.dtb. + +To overrule this selection the variable can be set manually and saved in the +environment + +:: + + setenv fdtfile my_device-tree.dtb + env save + +or the configuration variable CONFIG_DEFAULT_FDT_FILE can be used to provide +a default value. + Flashing ~~~~~~~~ diff --git a/doc/build/docker.rst b/doc/build/docker.rst index 953d1b28a06..45659b3b89d 100644 --- a/doc/build/docker.rst +++ b/doc/build/docker.rst @@ -11,4 +11,4 @@ Or to use an existing container .. code-block:: bash - sudo docker pull trini/u-boot-gitlab-ci-runner:bionic-20200807-02Sep2020 + sudo docker pull trini/u-boot-gitlab-ci-runner:jammy-20240227-14Mar2024 diff --git a/doc/build/gen_compile_commands.rst b/doc/build/gen_compile_commands.rst index 50305cec4a8..d503764f9e3 100644 --- a/doc/build/gen_compile_commands.rst +++ b/doc/build/gen_compile_commands.rst @@ -42,7 +42,7 @@ needed for it to be usable by the LSP, unless you set a name for the database other than it's default one (compile_commands.json). Compatible IDEs -=============== +--------------- Several popular integrated development environments (IDEs) support the use of JSON compilation databases for C/C++ development, making it easier to @@ -73,7 +73,7 @@ compile_commands.json in the root of the repository should suffice to enable code navigation. Usage -===== +----- For further details on the script's options, please refer to its help message, as in the example below. diff --git a/doc/develop/tests_sandbox.rst b/doc/develop/tests_sandbox.rst index bfd3bdb9270..72923070150 100644 --- a/doc/develop/tests_sandbox.rst +++ b/doc/develop/tests_sandbox.rst @@ -28,8 +28,8 @@ Some of the available tests are: - test/image/test-imagetools.sh - multi-file images - test/py/tests/test-fit.py - FIT images - - tracing: test/trace/test-trace.sh tests the tracing system (see - README.trace) + - tracing: test/trace/test-trace.sh tests the tracing system + (see :doc:`trace`). - verified boot: test/py/tests/test_vboot.py If you change or enhance any U-Boot subsystem, you should write or expand a diff --git a/doc/device-tree-bindings/sysreset/ti,sci-sysreset.txt b/doc/device-tree-bindings/sysreset/ti,sci-sysreset.txt deleted file mode 100644 index 02704c6487e..00000000000 --- a/doc/device-tree-bindings/sysreset/ti,sci-sysreset.txt +++ /dev/null @@ -1,29 +0,0 @@ -Texas Instruments TI SCI System Reset Controller -================================================ - -Some TI SoCs contain a system controller (like the SYSFW, etc...) that is -responsible for controlling the state of the IPs that are present. -Communication between the host processor running an OS and the system -controller happens through a protocol known as TI SCI [1]. - -[1] http://processors.wiki.ti.com/index.php/TISCI - -System Reset Controller Node -============================ -The sysreset controller node represents the reset for the overall SoC -which is managed by the SYSFW. Because this relies on the TI SCI protocol -to communicate with the SYSFW it must be a child of the sysfw node. - -Required Properties: --------------------- - - compatible: Must be "ti,sci-sysreset" - -Example (AM65x): ----------------- - sysfw: sysfw { - compatible = "ti,am654-system-controller"; - ... - k3_sysreset: sysreset-controller { - compatible = "ti,sci-sysreset"; - }; - }; diff --git a/doc/sphinx/requirements.txt b/doc/sphinx/requirements.txt index 840c6cedfde..5b4df36804b 100644 --- a/doc/sphinx/requirements.txt +++ b/doc/sphinx/requirements.txt @@ -3,7 +3,7 @@ Babel==2.14.0 certifi==2023.11.17 charset-normalizer==3.3.2 docutils==0.20.1 -idna==3.6 +idna==3.7 imagesize==1.4.1 Jinja2==3.1.3 MarkupSafe==2.1.3 diff --git a/doc/usage/environment.rst b/doc/usage/environment.rst index ebf75fa948a..7d4b448cb30 100644 --- a/doc/usage/environment.rst +++ b/doc/usage/environment.rst @@ -366,6 +366,19 @@ tftpwindowsize This means the count of blocks we can receive before sending ack to server. +usb_ignorelist + Ignore USB devices to prevent binding them to an USB device driver. This can + be used to ignore devices are for some reason undesirable or causes crashes + u-boot's USB stack. + An example for undesired behavior is the keyboard emulation of security keys + like Yubikeys. U-boot currently supports only a single USB keyboard device + so try to probe an useful keyboard device. The default environment blocks + Yubico devices as common devices emulating keyboards. + Devices are matched by idVendor and idProduct. The variable contains a comma + separated list of idVendor:idProduct pairs as hexadecimal numbers joined + by a colon. '*' functions as a wildcard for idProduct to block all devices + with the specified idVendor. + vlan When set to a value < 4095 the traffic over Ethernet is encapsulated/received over 802.1q diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c index ce10d795316..f0cb797d975 100644 --- a/drivers/clk/imx/clk-imx93.c +++ b/drivers/clk/imx/clk-imx93.c @@ -289,7 +289,7 @@ static int imx93_clk_probe(struct udevice *dev) clk_dm(IMX93_CLK_SYS_PLL_PFD2_DIV2, imx_clk_fixed_factor("sys_pll_pfd2_div2", "sys_pll_pfd2", 1, 2)); - base = (void *)ANATOP_BASE_ADDR; + anatop_base = (void *)ANATOP_BASE_ADDR; clk_dm(IMX93_CLK_ARM_PLL, imx_clk_fracn_gppll_integer("arm_pll", "clock-osc-24m", diff --git a/drivers/cpu/imx9_cpu.c b/drivers/cpu/imx9_cpu.c deleted file mode 100644 index 66534fe6d17..00000000000 --- a/drivers/cpu/imx9_cpu.c +++ /dev/null @@ -1,224 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright 2019 NXP - */ - -#include <common.h> -#include <cpu.h> -#include <dm.h> -#include <thermal.h> -#include <asm/global_data.h> -#include <asm/system.h> -#include <firmware/linux/imx/sci/sci.h> -#include <asm/arch/sys_proto.h> -#include <asm/arch-imx/cpu.h> -#include <asm/armv8/cpu.h> -#include <linux/bitops.h> - -DECLARE_GLOBAL_DATA_PTR; - -struct cpu_imx_plat { - const char *name; - const char *rev; - const char *type; - u32 cpu_rsrc; - u32 cpurev; - u32 freq_mhz; - u32 mpidr; -}; - -const char *get_imx9_type(u32 imxtype) -{ - switch (imxtype) { - case MXC_CPU_IMX93: - return "93"; - default: - return "??"; - } -} - -const char *get_imx9_rev(u32 rev) -{ - switch (rev) { - case CHIP_REV_1_0: - return "1."; - case CHIP_REV_B: - return "B"; - case CHIP_REV_C: - return "C"; - default: - return "?"; - } -} - -static void set_core_data(struct udevice *dev) -{ - struct cpu_imx_plat *plat = dev_get_plat(dev); - - if (device_is_compatible(dev, "arm,cortex-a35")) - plat->name = "A35"; - else - plat->name = "?"; -} - -#if IS_ENABLED(CONFIG_IMX_SCU_THERMAL) -static int cpu_imx_get_temp(struct cpu_imx_plat *plat) -{ - struct udevice *thermal_dev; - int cpu_tmp, ret; - int idx = 1; /* use "cpu-thermal0" device */ - - if (plat->cpu_rsrc == SC_R_A72) - idx = 2; /* use "cpu-thermal1" device */ - - ret = uclass_get_device(UCLASS_THERMAL, idx, &thermal_dev); - if (!ret) { - ret = thermal_get_temp(thermal_dev, &cpu_tmp); - if (ret) - return 0xdeadbeef; - } else { - return 0xdeadbeef; - } - - return cpu_tmp; -} -#else -static int cpu_imx_get_temp(struct cpu_imx_plat *plat) -{ - return 0; -} -#endif - -int cpu_imx_get_desc(const struct udevice *dev, char *buf, int size) -{ - struct cpu_imx_plat *plat = dev_get_plat(dev); - int ret, temp; - - if (size < 100) - return -ENOSPC; - - ret = snprintf(buf, size, "NXP i.MX8%s Rev%s %s at %u MHz", - plat->type, plat->rev, plat->name, plat->freq_mhz); - - if (IS_ENABLED(CONFIG_IMX_SCU_THERMAL)) { - temp = cpu_imx_get_temp(plat); - buf = buf + ret; - size = size - ret; - if (temp != 0xdeadbeef) - ret = snprintf(buf, size, " at %dC", temp); - else - ret = snprintf(buf, size, " - invalid sensor data"); - } - - snprintf(buf + ret, size - ret, "\n"); - - return 0; -} - -static int cpu_imx_get_info(const struct udevice *dev, struct cpu_info *info) -{ - struct cpu_imx_plat *plat = dev_get_plat(dev); - - info->cpu_freq = plat->freq_mhz * 1000; - info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU); - return 0; -} - -static int cpu_imx_get_count(const struct udevice *dev) -{ - ofnode node; - int num = 0; - - ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { - const char *device_type; - - if (!ofnode_is_enabled(node)) - continue; - - device_type = ofnode_read_string(node, "device_type"); - if (!device_type) - continue; - - if (!strcmp(device_type, "cpu")) - num++; - } - - return num; -} - -static int cpu_imx_get_vendor(const struct udevice *dev, char *buf, int size) -{ - snprintf(buf, size, "NXP"); - return 0; -} - -static int cpu_imx_is_current(struct udevice *dev) -{ - struct cpu_imx_plat *plat = dev_get_plat(dev); - - if (plat->mpidr == (read_mpidr() & 0xffff)) - return 1; - - return 0; -} - -static const struct cpu_ops cpu_imx9_ops = { - .get_desc = cpu_imx_get_desc, - .get_info = cpu_imx_get_info, - .get_count = cpu_imx_get_count, - .get_vendor = cpu_imx_get_vendor, - .is_current = cpu_imx_is_current, -}; - -static const struct udevice_id cpu_imx9_ids[] = { - { .compatible = "arm,cortex-a35" }, - { .compatible = "arm,cortex-a53" }, - { .compatible = "arm,cortex-a72" }, - { } -}; - -static ulong imx9_get_cpu_rate(struct udevice *dev) -{ - struct cpu_imx_plat *plat = dev_get_plat(dev); - ulong rate; - int ret; - - ret = sc_pm_get_clock_rate(-1, plat->cpu_rsrc, SC_PM_CLK_CPU, - (sc_pm_clock_rate_t *)&rate); - if (ret) { - printf("Could not read CPU frequency: %d\n", ret); - return 0; - } - - return rate; -} - -static int imx9_cpu_probe(struct udevice *dev) -{ - struct cpu_imx_plat *plat = dev_get_plat(dev); - u32 cpurev; - - set_core_data(dev); - cpurev = get_cpu_rev(); - plat->cpurev = cpurev; - plat->rev = get_imx9_rev(cpurev & 0xFFF); - plat->type = get_imx9_type((cpurev & 0xFF000) >> 12); - plat->freq_mhz = imx9_get_cpu_rate(dev) / 1000000; - plat->mpidr = dev_read_addr(dev); - if (plat->mpidr == FDT_ADDR_T_NONE) { - printf("%s: Failed to get CPU reg property\n", __func__); - return -EINVAL; - } - - return 0; -} - -U_BOOT_DRIVER(cpu_imx9_drv) = { - .name = "imx9x_cpu", - .id = UCLASS_CPU, - .of_match = cpu_imx9_ids, - .ops = &cpu_imx9_ops, - .probe = imx9_cpu_probe, - .plat_auto = sizeof(struct cpu_imx_plat), - .flags = DM_FLAG_PRE_RELOC, -}; diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c index 5d1026b37da..9b1950efe05 100644 --- a/drivers/cpu/riscv_cpu.c +++ b/drivers/cpu/riscv_cpu.c @@ -21,13 +21,13 @@ DECLARE_GLOBAL_DATA_PTR; static int riscv_cpu_get_desc(const struct udevice *dev, char *buf, int size) { - const char *isa; + const char *cpu; - isa = dev_read_string(dev, "riscv,isa"); - if (size < (strlen(isa) + 1)) + cpu = dev_read_string(dev, "compatible"); + if (size < (strlen(cpu) + 1)) return -ENOSPC; - strcpy(buf, isa); + strcpy(buf, cpu); return 0; } diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 5e5855a76c2..d6e2be09cf7 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -1,5 +1,4 @@ menu "Fastboot support" - depends on CMDLINE config FASTBOOT bool @@ -13,6 +12,10 @@ config FASTBOOT More information about the protocol and usecases: https://android.googlesource.com/platform/system/core/+/refs/heads/master/fastboot/ + Note that enabling CMDLINE is recommended since fastboot allows U-Boot + commands to be executed on request. The CMDLINE option is required + for anything other than simply booting the OS. + config USB_FUNCTION_FASTBOOT bool "Enable USB fastboot gadget" depends on USB_GADGET diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c index f95f4e4ae15..b8782bfa7fa 100644 --- a/drivers/fastboot/fb_command.c +++ b/drivers/fastboot/fb_command.c @@ -11,6 +11,7 @@ #include <fastboot-internal.h> #include <fb_mmc.h> #include <fb_nand.h> +#include <mapmem.h> #include <part.h> #include <stdlib.h> #include <linux/printk.h> @@ -278,6 +279,7 @@ void fastboot_data_download(const void *fastboot_data, { #define BYTES_PER_DOT 0x20000 u32 pre_dot_num, now_dot_num; + void *buf; if (fastboot_data_len == 0 || (fastboot_bytes_received + fastboot_data_len) > @@ -287,8 +289,10 @@ void fastboot_data_download(const void *fastboot_data, return; } /* Download data to fastboot_buf_addr */ - memcpy(fastboot_buf_addr + fastboot_bytes_received, + buf = map_sysmem(fastboot_buf_addr, 0); + memcpy(buf + fastboot_bytes_received, fastboot_data, fastboot_data_len); + unmap_sysmem(buf); pre_dot_num = fastboot_bytes_received / BYTES_PER_DOT; fastboot_bytes_received += fastboot_data_len; @@ -331,13 +335,16 @@ void fastboot_data_complete(char *response) */ static void __maybe_unused flash(char *cmd_parameter, char *response) { + void *buf = map_sysmem(fastboot_buf_addr, 0); + if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_MMC)) - fastboot_mmc_flash_write(cmd_parameter, fastboot_buf_addr, - image_size, response); + fastboot_mmc_flash_write(cmd_parameter, buf, image_size, + response); if (IS_ENABLED(CONFIG_FASTBOOT_FLASH_NAND)) - fastboot_nand_flash_write(cmd_parameter, fastboot_buf_addr, - image_size, response); + fastboot_nand_flash_write(cmd_parameter, buf, image_size, + response); + unmap_sysmem(buf); } /** diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c index 3576b067729..595954542a6 100644 --- a/drivers/fastboot/fb_common.c +++ b/drivers/fastboot/fb_common.c @@ -11,6 +11,7 @@ */ #include <bcb.h> +#include <bootm.h> #include <common.h> #include <command.h> #include <env.h> @@ -20,7 +21,7 @@ /** * fastboot_buf_addr - base address of the fastboot download buffer */ -void *fastboot_buf_addr; +ulong fastboot_buf_addr; /** * fastboot_buf_size - size of the fastboot download buffer @@ -142,22 +143,19 @@ void (*fastboot_get_progress_callback(void))(const char *) */ void fastboot_boot(void) { - char *s; + char *s = NULL; - s = env_get("fastboot_bootcmd"); - if (s) { - run_command(s, CMD_FLAG_ENV); - } else if (IS_ENABLED(CONFIG_CMD_BOOTM)) { - static char boot_addr_start[20]; - static char *const bootm_args[] = { - "bootm", boot_addr_start, NULL - }; + if (IS_ENABLED(CONFIG_CMDLINE)) { + s = env_get("fastboot_bootcmd"); + if (s) + run_command(s, CMD_FLAG_ENV); + } - snprintf(boot_addr_start, sizeof(boot_addr_start) - 1, - "0x%p", fastboot_buf_addr); - printf("Booting kernel at %s...\n\n\n", boot_addr_start); + if (!s && IS_ENABLED(CONFIG_BOOTM)) { + int ret; - do_bootm(NULL, 0, 2, bootm_args); + printf("Booting kernel at %lx...\n\n\n", fastboot_buf_addr); + ret = bootm_boot_start(fastboot_buf_addr, NULL); /* * This only happens if image is somehow faulty so we start @@ -214,16 +212,9 @@ void fastboot_set_progress_callback(void (*progress)(const char *msg)) fastboot_progress_callback = progress; } -/* - * fastboot_init() - initialise new fastboot protocol session - * - * @buf_addr: Pointer to download buffer, or NULL for default - * @buf_size: Size of download buffer, or zero for default - */ -void fastboot_init(void *buf_addr, u32 buf_size) +void fastboot_init(ulong buf_addr, u32 buf_size) { - fastboot_buf_addr = buf_addr ? buf_addr : - (void *)CONFIG_FASTBOOT_BUF_ADDR; + fastboot_buf_addr = buf_addr ? buf_addr : CONFIG_FASTBOOT_BUF_ADDR; fastboot_buf_size = buf_size ? buf_size : CONFIG_FASTBOOT_BUF_SIZE; fastboot_set_progress_callback(NULL); } diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index ee092185588..6c581b9df9c 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -16,6 +16,7 @@ #include <dm/device.h> #include <dm/device_compat.h> #include <dm/devres.h> +#include <dm/lists.h> #include <linux/bitops.h> #include <linux/compat.h> #include <linux/err.h> @@ -2840,6 +2841,12 @@ static int ti_sci_probe(struct udevice *dev) INIT_LIST_HEAD(&info->dev_list); + if (IS_ENABLED(CONFIG_SYSRESET_TI_SCI)) { + ret = device_bind_driver(dev, "ti-sci-sysreset", "sysreset", NULL); + if (ret) + dev_warn(dev, "cannot bind SYSRESET (ret = %d)\n", ret); + } + return 0; } diff --git a/drivers/gpio/imx_rgpio2p.c b/drivers/gpio/imx_rgpio2p.c index 175e460aff5..3227a8d5b57 100644 --- a/drivers/gpio/imx_rgpio2p.c +++ b/drivers/gpio/imx_rgpio2p.c @@ -21,6 +21,12 @@ enum imx_rgpio2p_direction { #define GPIO_PER_BANK 32 +struct imx_rgpio2p_soc_data { + bool have_dual_base; +}; + +#define IMX8ULP_GPIO_BASE_OFF 0x40 + struct imx_rgpio2p_data { struct gpio_regs *regs; }; @@ -165,6 +171,9 @@ static int imx_rgpio2p_probe(struct udevice *dev) static int imx_rgpio2p_bind(struct udevice *dev) { struct imx_rgpio2p_plat *plat = dev_get_plat(dev); + struct imx_rgpio2p_soc_data *data = + (struct imx_rgpio2p_soc_data *)dev_get_driver_data(dev); + bool dual_base = data->have_dual_base; fdt_addr_t addr; /* @@ -176,9 +185,26 @@ static int imx_rgpio2p_bind(struct udevice *dev) if (plat) return 0; - addr = devfdt_get_addr_index(dev, 1); - if (addr == FDT_ADDR_T_NONE) - return -EINVAL; + /* + * Handle legacy compatible combinations which used two reg values + * for the i.MX8ULP and i.MX93. + */ + if (device_is_compatible(dev, "fsl,imx7ulp-gpio") && + (device_is_compatible(dev, "fsl,imx93-gpio") || + (device_is_compatible(dev, "fsl,imx8ulp-gpio")))) + dual_base = true; + + if (dual_base) { + addr = devfdt_get_addr_index(dev, 1); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + } else { + addr = devfdt_get_addr_index(dev, 0); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + addr += IMX8ULP_GPIO_BASE_OFF; + } /* * TODO: @@ -202,9 +228,17 @@ static int imx_rgpio2p_bind(struct udevice *dev) return 0; } +static struct imx_rgpio2p_soc_data imx7ulp_data = { + .have_dual_base = true, +}; + +static struct imx_rgpio2p_soc_data imx8ulp_data = { + .have_dual_base = false, +}; static const struct udevice_id imx_rgpio2p_ids[] = { - { .compatible = "fsl,imx7ulp-gpio" }, + { .compatible = "fsl,imx7ulp-gpio", .data = (ulong)&imx7ulp_data }, + { .compatible = "fsl,imx8ulp-gpio", .data = (ulong)&imx8ulp_data }, { } }; diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 9e829905f12..e53d52c47b3 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -91,4 +91,4 @@ obj-$(CONFIG_K3_AVS0) += k3_avs.o obj-$(CONFIG_ESM_K3) += k3_esm.o obj-$(CONFIG_ESM_PMIC) += esm_pmic.o obj-$(CONFIG_SL28CPLD) += sl28cpld.o -obj-$(CONFIG_SPL_SOCFPGA_SEC_REG) += socfpga_dtreg.o +obj-$(CONFIG_SPL_SOCFPGA_DT_REG) += socfpga_dtreg.o diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index cef05790dd9..06e32e75696 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -20,11 +20,19 @@ config MMC_WRITE config MMC_PWRSEQ bool "HW reset support for eMMC" - depends on PWRSEQ + depends on PWRSEQ && DM_GPIO help - Ths select Hardware reset support aka pwrseq-emmc for eMMC + This select Hardware reset support aka pwrseq-emmc for eMMC devices. +config SPL_MMC_PWRSEQ + bool "HW reset support for eMMC in SPL" + depends on SPL_PWRSEQ && SPL_DM_GPIO + default y if MMC_PWRSEQ + help + This select Hardware reset support aka pwrseq-emmc for eMMC + devices in SPL. + config MMC_BROKEN_CD bool "Poll for broken card detection case" help @@ -79,11 +87,12 @@ config MMC_SPI_CRC_ON config ARM_PL180_MMCI bool "ARM AMBA Multimedia Card Interface and compatible support" + depends on DM_MMC help This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card Interface (PL180, PL181 and compatible) support. If you have an ARM(R) platform with a Multimedia Card slot, - say Y or M here. + say Y here. config MMC_QUIRKS bool "Enable quirks" @@ -568,6 +577,19 @@ config MMC_SDHCI_CADENCE If unsure, say N. +config MMC_SDHCI_CV1800B + bool "SDHCI support for the CV1800B SD/SDIO/eMMC controller" + depends on BLK && DM_MMC + depends on MMC_SDHCI + depends on OF_CONTROL + help + This selects the CV1800B SD/SDIO/eMMC driver. + + If you have a controller with this interface, + say Y here. + + If unsure, say N. + config MMC_SDHCI_AM654 bool "SDHCI Controller on TI's Am654 devices" depends on ARCH_K3 @@ -586,7 +608,7 @@ config MMC_SDHCI_IPROC This selects the iProc SD/MMC controller. If you have a Broadcom IPROC platform with SD or MMC devices, - say Y or M here. + say Y here. If unsure, say N. @@ -597,7 +619,7 @@ config MMC_SDHCI_F_SDH30 help This selects the Secure Digital Host Controller Interface (SDHCI) Needed by some Fujitsu/Socionext SoC for MMC / SD / SDIO support. - If you have a controller with this interface, say Y or M here. + If you have a controller with this interface, say Y here. If unsure, say N. config MMC_SDHCI_KONA @@ -791,7 +813,7 @@ config STM32_SDMMC2 help This selects support for the SD/MMC controller on STM32H7 SoCs. If you have a board based on such a SoC and with a SD/MMC slot, - say Y or M here. + say Y here. config FTSDC010 bool "Ftsdc010 SD/MMC controller Support" @@ -811,7 +833,7 @@ config MMC_MTK depends on OF_CONTROL help This selects the MediaTek(R) Secure digital and Multimedia card Interface. - If you have a machine with a integrated SD/MMC card reader, say Y or M here. + If you have a machine with a integrated SD/MMC card reader, say Y here. This is needed if support for any SD/SDIO/MMC devices is required. If unsure, say N. diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index e9cf1fcc640..72c3fb66ce0 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += mmc_bootdev.o endif obj-$(CONFIG_$(SPL_TPL_)MMC_WRITE) += mmc_write.o -obj-$(CONFIG_MMC_PWRSEQ) += mmc-pwrseq.o +obj-$(CONFIG_$(SPL_)MMC_PWRSEQ) += mmc-pwrseq.o obj-$(CONFIG_MMC_SDHCI_ADMA_HELPERS) += sdhci-adma.o ifndef CONFIG_$(SPL_)BLK @@ -60,6 +60,7 @@ obj-$(CONFIG_MMC_SDHCI_ATMEL) += atmel_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCM2835) += bcm2835_sdhci.o obj-$(CONFIG_MMC_SDHCI_BCMSTB) += bcmstb_sdhci.o obj-$(CONFIG_MMC_SDHCI_CADENCE) += sdhci-cadence.o +obj-$(CONFIG_MMC_SDHCI_CV1800B) += cv1800b_sdhci.o obj-$(CONFIG_MMC_SDHCI_AM654) += am654_sdhci.o obj-$(CONFIG_MMC_SDHCI_IPROC) += iproc_sdhci.o obj-$(CONFIG_MMC_SDHCI_KONA) += kona_sdhci.o diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index 05595bdac39..2139fea04d5 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -390,7 +390,7 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) for (itap = 0; itap < ITAP_MAX; itap++) { am654_sdhci_write_itapdly(plat, itap); - cur_val = !mmc_send_tuning(mmc, opcode, NULL); + cur_val = !mmc_send_tuning(mmc, opcode); if (cur_val && !prev_val) pass_window = itap; diff --git a/drivers/mmc/arm_pl180_mmci.c b/drivers/mmc/arm_pl180_mmci.c index 5cf5502ed54..2666b65362b 100644 --- a/drivers/mmc/arm_pl180_mmci.c +++ b/drivers/mmc/arm_pl180_mmci.c @@ -18,6 +18,7 @@ #include <malloc.h> #include <mmc.h> #include <dm/device_compat.h> +#include <dm.h> #include <asm/io.h> #include <asm-generic/gpio.h> @@ -25,8 +26,6 @@ #include "arm_pl180_mmci.h" #include <linux/delay.h> -#ifdef CONFIG_DM_MMC -#include <dm.h> #define MMC_CLOCK_MAX 48000000 #define MMC_CLOCK_MIN 400000 @@ -34,7 +33,6 @@ struct arm_pl180_mmc_plat { struct mmc_config cfg; struct mmc mmc; }; -#endif static int wait_for_command_end(struct mmc *dev, struct mmc_cmd *cmd) { @@ -358,65 +356,6 @@ static int host_set_ios(struct mmc *dev) return 0; } -#ifndef CONFIG_DM_MMC -/* MMC uses open drain drivers in the enumeration phase */ -static int mmc_host_reset(struct mmc *dev) -{ - struct pl180_mmc_host *host = dev->priv; - - writel(host->pwr_init, &host->base->power); - - return 0; -} - -static const struct mmc_ops arm_pl180_mmci_ops = { - .send_cmd = host_request, - .set_ios = host_set_ios, - .init = mmc_host_reset, -}; - -/* - * mmc_host_init - initialize the mmc controller. - * Set initial clock and power for mmc slot. - * Initialize mmc struct and register with mmc framework. - */ - -int arm_pl180_mmci_init(struct pl180_mmc_host *host, struct mmc **mmc) -{ - u32 sdi_u32; - - writel(host->pwr_init, &host->base->power); - writel(host->clkdiv_init, &host->base->clock); - udelay(CLK_CHANGE_DELAY); - - /* Disable mmc interrupts */ - sdi_u32 = readl(&host->base->mask0) & ~SDI_MASK0_MASK; - writel(sdi_u32, &host->base->mask0); - - host->cfg.name = host->name; - host->cfg.ops = &arm_pl180_mmci_ops; - - /* TODO remove the duplicates */ - host->cfg.host_caps = host->caps; - host->cfg.voltages = host->voltages; - host->cfg.f_min = host->clock_min; - host->cfg.f_max = host->clock_max; - if (host->b_max != 0) - host->cfg.b_max = host->b_max; - else - host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; - - *mmc = mmc_create(&host->cfg, host); - if (!*mmc) - return -1; - debug("registered mmc interface number is:%d\n", - (*mmc)->block_dev.devnum); - - return 0; -} -#endif - -#ifdef CONFIG_DM_MMC static void arm_pl180_mmc_init(struct pl180_mmc_host *host) { u32 sdi_u32; @@ -477,7 +416,7 @@ static int arm_pl180_mmc_probe(struct udevice *dev) host->version2 = true; break; default: - host->version2 = true; + host->version2 = false; /* ARM variant */ } gpio_request_by_name(dev, "cd-gpios", 0, &host->cd_gpio, GPIOD_IS_IN); @@ -561,4 +500,3 @@ U_BOOT_DRIVER(arm_pl180_mmc) = { .priv_auto = sizeof(struct pl180_mmc_host), .plat_auto = sizeof(struct arm_pl180_mmc_plat), }; -#endif diff --git a/drivers/mmc/cv1800b_sdhci.c b/drivers/mmc/cv1800b_sdhci.c new file mode 100644 index 00000000000..9af6b971984 --- /dev/null +++ b/drivers/mmc/cv1800b_sdhci.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + */ + +#include <dm.h> +#include <mmc.h> +#include <sdhci.h> +#include <linux/delay.h> + +#define SDHCI_PHY_TX_RX_DLY 0x240 +#define MMC_MAX_CLOCK 375000000 +#define TUNE_MAX_PHCODE 128 + +struct cv1800b_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +static void cv1800b_set_tap_delay(struct sdhci_host *host, u16 tap) +{ + sdhci_writel(host, tap << 16, SDHCI_PHY_TX_RX_DLY); +} + +static void cv1800b_sdhci_reset(struct sdhci_host *host, u8 mask) +{ + sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); + while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) + udelay(10); +} + +static int cv1800b_execute_tuning(struct mmc *mmc, u8 opcode) +{ + struct sdhci_host *host = dev_get_priv(mmc->dev); + + u16 tap; + + int current_size = 0; + int max_size = 0; + int max_window = 0; + + for (tap = 0; tap < TUNE_MAX_PHCODE; tap++) { + cv1800b_set_tap_delay(host, tap); + + if (mmc_send_tuning(host->mmc, opcode)) { + current_size = 0; + } else { + current_size++; + if (current_size > max_size) { + max_size = current_size; + max_window = tap; + } + } + } + + cv1800b_sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); + + cv1800b_set_tap_delay(host, max_window - max_size / 2); + + return 0; +} + +const struct sdhci_ops cv1800b_sdhci_sd_ops = { + .platform_execute_tuning = cv1800b_execute_tuning, +}; + +static int cv1800b_sdhci_bind(struct udevice *dev) +{ + struct cv1800b_sdhci_plat *plat = dev_get_plat(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static int cv1800b_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct cv1800b_sdhci_plat *plat = dev_get_plat(dev); + struct sdhci_host *host = dev_get_priv(dev); + int ret; + + host->name = dev->name; + host->ioaddr = devfdt_get_addr_ptr(dev); + + upriv->mmc = &plat->mmc; + host->mmc = &plat->mmc; + host->mmc->priv = host; + host->mmc->dev = dev; + host->ops = &cv1800b_sdhci_sd_ops; + host->max_clk = MMC_MAX_CLOCK; + + ret = mmc_of_parse(dev, &plat->cfg); + if (ret) + return ret; + + ret = sdhci_setup_cfg(&plat->cfg, host, 0, 200000); + if (ret) + return ret; + + return sdhci_probe(dev); +} + +static const struct udevice_id cv1800b_sdhci_match[] = { + { .compatible = "sophgo,cv1800b-dwcmshc" }, + { } +}; + +U_BOOT_DRIVER(cv1800b_sdhci) = { + .name = "sdhci-cv1800b", + .id = UCLASS_MMC, + .of_match = cv1800b_sdhci_match, + .bind = cv1800b_sdhci_bind, + .probe = cv1800b_sdhci_probe, + .priv_auto = sizeof(struct sdhci_host), + .plat_auto = sizeof(struct cv1800b_sdhci_plat), + .ops = &sdhci_ops, +}; diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 400066fa99a..e1036641452 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -262,8 +262,8 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) { if (get_timer(start) > timeout) { - debug("%s: Timeout on data busy\n", __func__); - return -ETIMEDOUT; + debug("%s: Timeout on data busy, continue anyway\n", __func__); + break; } } diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index d5066666698..d44dfa5d06f 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -1123,7 +1123,7 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) esdhc_write32(®s->irqstaten, IRQSTATEN_BRR); for (i = 0; i < MAX_TUNING_LOOP; i++) { - mmc_send_tuning(mmc, opcode, NULL); + mmc_send_tuning(mmc, opcode); mdelay(1); val = esdhc_read32(®s->autoc12err); diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index 7c39c86c5e9..b74c0140020 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -882,7 +882,7 @@ static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) esdhc_write32(®s->mixctrl, val); /* We are using STD tuning, no need to check return value */ - mmc_send_tuning(mmc, opcode, NULL); + mmc_send_tuning(mmc, opcode); ctrl = esdhc_read32(®s->autoc12err); if ((!(ctrl & MIX_CTRL_EXE_TUNE)) && diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c index 71962cd47e0..dc0210402bd 100644 --- a/drivers/mmc/hi6220_dw_mmc.c +++ b/drivers/mmc/hi6220_dw_mmc.c @@ -5,15 +5,24 @@ */ #include <common.h> +#include <clk.h> #include <dm.h> #include <dwmmc.h> #include <errno.h> #include <fdtdec.h> #include <malloc.h> +#include <reset.h> #include <asm/global_data.h> +#include <dm/device_compat.h> DECLARE_GLOBAL_DATA_PTR; +enum hi6220_dwmmc_clk_type { + HI6220_DWMMC_CLK_BIU, + HI6220_DWMMC_CLK_CIU, + HI6220_DWMMC_CLK_CNT, +}; + struct hi6220_dwmmc_plat { struct mmc_config cfg; struct mmc mmc; @@ -21,18 +30,43 @@ struct hi6220_dwmmc_plat { struct hi6220_dwmmc_priv_data { struct dwmci_host host; + struct clk *clks[HI6220_DWMMC_CLK_CNT]; + struct reset_ctl_bulk rsts; }; struct hisi_mmc_data { unsigned int clock; bool use_fifo; + u32 fifoth_val; }; static int hi6220_dwmmc_of_to_plat(struct udevice *dev) { struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; + int ret; + if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) { + priv->clks[HI6220_DWMMC_CLK_BIU] = devm_clk_get(dev, "biu"); + if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_BIU])) { + ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_BIU]); + dev_err(dev, "Failed to get BIU clock(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + + priv->clks[HI6220_DWMMC_CLK_CIU] = devm_clk_get(dev, "ciu"); + if (IS_ERR(priv->clks[HI6220_DWMMC_CLK_CIU])) { + ret = PTR_ERR(priv->clks[HI6220_DWMMC_CLK_CIU]); + dev_err(dev, "Failed to get CIU clock(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + + ret = reset_get_bulk(dev, &priv->rsts); + if (ret) { + dev_err(dev, "Failed to get resets(ret = %d)", ret); + return log_msg_ret("rst", ret); + } + } host->name = dev->name; host->ioaddr = dev_read_addr_ptr(dev); host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), @@ -56,16 +90,43 @@ static int hi6220_dwmmc_probe(struct udevice *dev) struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; struct hisi_mmc_data *mmc_data; + int ret; mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev); - /* Use default bus speed due to absence of clk driver */ host->bus_hz = mmc_data->clock; + if (CONFIG_IS_ENABLED(CLK) && CONFIG_IS_ENABLED(DM_RESET)) { + ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_BIU]); + if (ret) { + dev_err(dev, "Failed to enable biu clock(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + + ret = clk_prepare_enable(priv->clks[HI6220_DWMMC_CLK_CIU]); + if (ret) { + dev_err(dev, "Failed to enable ciu clock(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + + ret = reset_deassert_bulk(&priv->rsts); + if (ret) { + dev_err(dev, "Failed to deassert resets(ret = %d).\n", ret); + return log_msg_ret("rst", ret); + } + + host->bus_hz = clk_get_rate(priv->clks[HI6220_DWMMC_CLK_CIU]); + if (host->bus_hz <= 0) { + dev_err(dev, "Failed to get ciu clock rate(ret = %d).\n", ret); + return log_msg_ret("clk", ret); + } + } + dev_dbg(dev, "bus clock rate: %d.\n", host->bus_hz); dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000); host->mmc = &plat->mmc; host->fifo_mode = mmc_data->use_fifo; + host->fifoth_val = mmc_data->fifoth_val; host->mmc->priv = &priv->host; upriv->mmc = host->mmc; host->mmc->dev = dev; @@ -95,13 +156,20 @@ static const struct hisi_mmc_data hi6220_mmc_data = { .use_fifo = false, }; +static const struct hisi_mmc_data hi3798mv2x_mmc_data = { + .clock = 50000000, + .use_fifo = false, + // FIFO depth is 256 + .fifoth_val = MSIZE(4) | RX_WMARK(0x7f) | TX_WMARK(0x80), +}; + static const struct udevice_id hi6220_dwmmc_ids[] = { { .compatible = "hisilicon,hi6220-dw-mshc", .data = (ulong)&hi6220_mmc_data }, { .compatible = "hisilicon,hi3798cv200-dw-mshc", .data = (ulong)&hi6220_mmc_data }, { .compatible = "hisilicon,hi3798mv200-dw-mshc", - .data = (ulong)&hi6220_mmc_data }, + .data = (ulong)&hi3798mv2x_mmc_data }, { .compatible = "hisilicon,hi3660-dw-mshc", .data = (ulong)&hi3660_mmc_data }, { } diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c index fcf4f03d1e2..0825c0a2a83 100644 --- a/drivers/mmc/meson_gx_mmc.c +++ b/drivers/mmc/meson_gx_mmc.c @@ -288,7 +288,7 @@ static int meson_mmc_probe(struct udevice *dev) mmc_set_clock(mmc, cfg->f_min, MMC_CLK_ENABLE); -#ifdef CONFIG_MMC_PWRSEQ +#if CONFIG_IS_ENABLED(MMC_PWRSEQ) /* Enable power if needed */ ret = mmc_pwrseq_get_power(dev, cfg); if (!ret) { diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 328456831dd..1e03901e9dc 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -124,7 +124,13 @@ static int dm_mmc_execute_tuning(struct udevice *dev, uint opcode) int mmc_execute_tuning(struct mmc *mmc, uint opcode) { - return dm_mmc_execute_tuning(mmc->dev, opcode); + int ret; + + mmc->tuning = true; + ret = dm_mmc_execute_tuning(mmc->dev, opcode); + mmc->tuning = false; + + return ret; } #endif @@ -494,10 +500,7 @@ static int mmc_blk_probe(struct udevice *dev) if (ret) { debug("Probing %s failed (err=%d)\n", dev->name, ret); - if (CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || - CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || - CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)) - mmc_deinit(mmc); + mmc_deinit(mmc); return ret; } @@ -505,9 +508,6 @@ static int mmc_blk_probe(struct udevice *dev) return 0; } -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) static int mmc_blk_remove(struct udevice *dev) { struct udevice *mmc_dev = dev_get_parent(dev); @@ -516,7 +516,6 @@ static int mmc_blk_remove(struct udevice *dev) return mmc_deinit(mmc); } -#endif static const struct blk_ops mmc_blk_ops = { .read = mmc_bread, @@ -532,12 +531,8 @@ U_BOOT_DRIVER(mmc_blk) = { .id = UCLASS_BLK, .ops = &mmc_blk_ops, .probe = mmc_blk_probe, -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) .remove = mmc_blk_remove, .flags = DM_FLAG_OS_PREPARE, -#endif }; #endif /* CONFIG_BLK */ diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index d96db7a0f83..7b068c71ff3 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -360,7 +360,7 @@ static const u8 tuning_blk_pattern_8bit[] = { 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, }; -int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error) +int mmc_send_tuning(struct mmc *mmc, u32 opcode) { struct mmc_cmd cmd; struct mmc_data data; @@ -1570,13 +1570,20 @@ static int sd_read_ssr(struct mmc *mmc) return 0; } #endif -/* frequency bases */ -/* divided by 10 to be nice to platforms without floating point */ +/* + * TRAN_SPEED bits 0:2 encode the frequency unit: + * 0 = 100KHz, 1 = 1MHz, 2 = 10MHz, 3 = 100MHz, values 4 - 7 are reserved. + * The values in fbase[] are divided by 10 to avoid floats in multiplier[]. + */ static const int fbase[] = { 10000, 100000, 1000000, 10000000, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ }; /* Multiplier values for TRAN_SPEED. Multiplied by 10 to be nice @@ -2027,9 +2034,9 @@ static int mmc_select_hs400(struct mmc *mmc) mmc_set_clock(mmc, mmc->tran_speed, false); /* execute tuning if needed */ - mmc->hs400_tuning = 1; + mmc->hs400_tuning = true; err = mmc_execute_tuning(mmc, MMC_CMD_SEND_TUNING_BLOCK_HS200); - mmc->hs400_tuning = 0; + mmc->hs400_tuning = false; if (err) { debug("tuning failed\n"); return err; @@ -2250,6 +2257,16 @@ error: return -ENOTSUPP; } +#else +static int sd_select_mode_and_width(struct mmc *mmc, uint card_caps) +{ + return 0; +}; + +static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) +{ + return 0; +}; #endif #if CONFIG_IS_ENABLED(MMC_TINY) @@ -2560,6 +2577,8 @@ static int mmc_startup(struct mmc *mmc) mult = multipliers[((cmd.response[0] >> 3) & 0xf)]; mmc->legacy_speed = freq * mult; + if (!mmc->legacy_speed) + log_debug("TRAN_SPEED: reserved value"); mmc_select_mode(mmc, MMC_LEGACY); mmc->dsr_imp = ((cmd.response[1] >> 12) & 0x1); @@ -3010,13 +3029,15 @@ int mmc_init(struct mmc *mmc) return err; } -#if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ - CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) int mmc_deinit(struct mmc *mmc) { u32 caps_filtered; + if (!CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) && + !CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) && + !CONFIG_IS_ENABLED(MMC_HS400_SUPPORT)) + return 0; + if (!mmc->has_init) return 0; @@ -3034,7 +3055,6 @@ int mmc_deinit(struct mmc *mmc) return mmc_select_mode_and_width(mmc, caps_filtered); } } -#endif int mmc_set_dsr(struct mmc *mmc, u16 val) { diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index 5a0c61daed5..296aaee7331 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -1131,7 +1131,7 @@ static int hs400_tune_response(struct udevice *dev, u32 opcode) i << PAD_CMD_TUNE_RX_DLY3_S); for (j = 0; j < 3; j++) { - mmc_send_tuning(mmc, opcode, &cmd_err); + cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) { cmd_delay |= (1 << i); } else { @@ -1181,7 +1181,7 @@ static int msdc_tune_response(struct udevice *dev, u32 opcode) i << MSDC_PAD_TUNE_CMDRDLY_S); for (j = 0; j < 3; j++) { - mmc_send_tuning(mmc, opcode, &cmd_err); + cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) { rise_delay |= (1 << i); } else { @@ -1203,7 +1203,7 @@ static int msdc_tune_response(struct udevice *dev, u32 opcode) i << MSDC_PAD_TUNE_CMDRDLY_S); for (j = 0; j < 3; j++) { - mmc_send_tuning(mmc, opcode, &cmd_err); + cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) { fall_delay |= (1 << i); } else { @@ -1238,7 +1238,7 @@ skip_fall: clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M, i << MSDC_PAD_TUNE_CMDRRDLY_S); - mmc_send_tuning(mmc, opcode, &cmd_err); + cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) internal_delay |= (1 << i); } @@ -1264,7 +1264,6 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode) struct msdc_delay_phase final_rise_delay, final_fall_delay = { 0, }; u8 final_delay, final_maxlen; void __iomem *tune_reg = &host->base->pad_tune; - int cmd_err; int i, ret; if (host->dev_comp->pad_tune0) @@ -1277,10 +1276,10 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode) clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, i << MSDC_PAD_TUNE_DATRRDLY_S); - ret = mmc_send_tuning(mmc, opcode, &cmd_err); + ret = mmc_send_tuning(mmc, opcode); if (!ret) { rise_delay |= (1 << i); - } else if (cmd_err) { + } else { /* in this case, retune response is needed */ ret = msdc_tune_response(dev, opcode); if (ret) @@ -1300,10 +1299,10 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode) clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, i << MSDC_PAD_TUNE_DATRRDLY_S); - ret = mmc_send_tuning(mmc, opcode, &cmd_err); + ret = mmc_send_tuning(mmc, opcode); if (!ret) { fall_delay |= (1 << i); - } else if (cmd_err) { + } else { /* in this case, retune response is needed */ ret = msdc_tune_response(dev, opcode); if (ret) @@ -1362,7 +1361,7 @@ static int msdc_tune_together(struct udevice *dev, u32 opcode) for (i = 0; i < PAD_DELAY_MAX; i++) { msdc_set_cmd_delay(host, i); msdc_set_data_delay(host, i); - ret = mmc_send_tuning(mmc, opcode, NULL); + ret = mmc_send_tuning(mmc, opcode); if (!ret) rise_delay |= (1 << i); } @@ -1378,7 +1377,7 @@ static int msdc_tune_together(struct udevice *dev, u32 opcode) for (i = 0; i < PAD_DELAY_MAX; i++) { msdc_set_cmd_delay(host, i); msdc_set_data_delay(host, i); - ret = mmc_send_tuning(mmc, opcode, NULL); + ret = mmc_send_tuning(mmc, opcode); if (!ret) fall_delay |= (1 << i); } diff --git a/drivers/mmc/octeontx_hsmmc.c b/drivers/mmc/octeontx_hsmmc.c index 4ee62df9d40..7f9c4f4d36d 100644 --- a/drivers/mmc/octeontx_hsmmc.c +++ b/drivers/mmc/octeontx_hsmmc.c @@ -1653,6 +1653,12 @@ static int octeontx_mmc_test_cmd(struct mmc *mmc, u32 opcode, int *statp) return err; } +static int octeontx_mmc_send_tuning(struct mmc *mmc, u32 opcode, int *error) +{ + *error = 0; + return mmc_send_tuning(mmc, opcode); +} + static int octeontx_mmc_test_get_ext_csd(struct mmc *mmc, u32 opcode, int *statp) { @@ -2006,7 +2012,7 @@ struct adj adj[] = { { "CMD_IN", 48, octeontx_mmc_test_cmd, MMC_CMD_SEND_STATUS, false, false, false, 2, }, /* { "CMD_OUT", 32, octeontx_mmc_test_cmd, MMC_CMD_SEND_STATUS, },*/ - { "DATA_IN(HS200)", 16, mmc_send_tuning, + { "DATA_IN(HS200)", 16, octeontx_mmc_send_tuning, MMC_CMD_SEND_TUNING_BLOCK_HS200, false, true, false, 2, }, { "DATA_IN", 16, octeontx_mmc_test_get_ext_csd, 0, false, false, true, 2, }, diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index a2595d19e7f..99f21b2c546 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -666,7 +666,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) while (phase_delay <= MAX_PHASE_DELAY) { omap_hsmmc_set_dll(mmc, phase_delay); - cur_match = !mmc_send_tuning(mmc, opcode, NULL); + cur_match = !mmc_send_tuning(mmc, opcode); if (cur_match) { if (prev_match) { @@ -731,7 +731,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) */ for (i = 3; i <= 10; i++) { omap_hsmmc_set_dll(mmc, phase_delay + i); - if (mmc_send_tuning(mmc, opcode, NULL)) { + if (mmc_send_tuning(mmc, opcode)) { if (temperature < 10000) phase_delay += i + 6; else if (temperature < 20000) @@ -749,7 +749,7 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) for (i = 2; i >= -10; i--) { omap_hsmmc_set_dll(mmc, phase_delay + i); - if (mmc_send_tuning(mmc, opcode, NULL)) { + if (mmc_send_tuning(mmc, opcode)) { if (temperature < 10000) phase_delay += i + 12; else if (temperature < 20000) diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 20b1e9277eb..23db2a75c44 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -568,8 +568,8 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode) struct mmc *mmc = upriv->mmc; unsigned int tap_num; unsigned int taps = 0; - int i, ret = 0; - u32 caps; + int i, ret = 0, sret; + u32 caps, reg; /* Only supported on Renesas RCar */ if (!(priv->caps & TMIO_SD_CAP_RCAR_UHS)) @@ -605,15 +605,15 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode) caps = priv->caps; priv->caps &= ~TMIO_SD_CAP_DMA_INTERNAL; - ret = mmc_send_tuning(mmc, opcode, NULL); + ret = mmc_send_tuning(mmc, opcode); priv->caps = caps; if (ret == 0) taps |= BIT(i); - ret = renesas_sdhi_compare_scc_data(priv); - if (ret == 0) + reg = renesas_sdhi_compare_scc_data(priv); + if (reg == 0) priv->smpcmp |= BIT(i); mdelay(1); @@ -624,9 +624,9 @@ int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode) * eMMC. */ if (ret && (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200)) { - ret = mmc_send_stop_transmission(mmc, false); - if (ret < 0) - dev_dbg(dev, "Tuning abort fail (%d)\n", ret); + sret = mmc_send_stop_transmission(mmc, false); + if (sret < 0) + dev_dbg(dev, "Tuning abort fail (%d)\n", sret); } } @@ -798,9 +798,12 @@ static int renesas_sdhi_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct tmio_sd_priv *priv = dev_get_priv(dev); + struct mmc *mmc = upriv->mmc; - renesas_sdhi_check_scc_error(dev); + if (!mmc->tuning) + renesas_sdhi_check_scc_error(dev); if (cmd->cmdidx == MMC_CMD_SEND_STATUS) renesas_sdhi_adjust_hs400_mode_enable(priv); diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index 72c820ee633..ad4529d6afa 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -145,7 +145,7 @@ static int rockchip_dwmmc_probe(struct udevice *dev) host->fifo_mode = priv->fifo_mode; -#ifdef CONFIG_MMC_PWRSEQ +#if CONFIG_IS_ENABLED(MMC_PWRSEQ) /* Enable power if needed */ ret = mmc_pwrseq_get_power(dev, &plat->cfg); if (!ret) { diff --git a/drivers/mmc/sdhci-cadence.c b/drivers/mmc/sdhci-cadence.c index 327a05ad11d..c0a9f60b149 100644 --- a/drivers/mmc/sdhci-cadence.c +++ b/drivers/mmc/sdhci-cadence.c @@ -224,7 +224,7 @@ static int __maybe_unused sdhci_cdns_execute_tuning(struct udevice *dev, for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) { if (sdhci_cdns_set_tune_val(plat, i) || - mmc_send_tuning(mmc, opcode, NULL)) { /* bad */ + mmc_send_tuning(mmc, opcode)) { /* bad */ cur_streak = 0; } else { /* good */ cur_streak++; diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 890c496b535..719c4830bc3 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -299,7 +299,13 @@ static int tmio_sd_dma_wait_for_irq(struct udevice *dev, u32 flag, struct tmio_sd_priv *priv = dev_get_priv(dev); long wait = 1000000 + 10 * blocks; - while (!(tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag)) { + for (;;) { + if (tmio_sd_readl(priv, TMIO_SD_DMA_INFO1) & flag) + break; + + if (tmio_sd_readl(priv, TMIO_SD_INFO1) & TMIO_SD_INFO1_CMP) + break; + if (wait-- < 0) { dev_err(dev, "timeout during DMA\n"); return -ETIMEDOUT; diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index bb9994b8626..9f3f1267cbd 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -1,6 +1,6 @@ - menuconfig MTD_RAW_NAND bool "Raw NAND Device Support" + if MTD_RAW_NAND config SYS_NAND_SELF_INIT @@ -49,12 +49,12 @@ config SYS_NAND_NO_SUBPAGE_WRITE depends on NAND_ARASAN || NAND_DAVINCI || NAND_KIRKWOOD config DM_NAND_ATMEL - bool "Support Atmel NAND controller with DM support" - select SYS_NAND_SELF_INIT - imply SYS_NAND_USE_FLASH_BBT - help - Enable this driver for NAND flash platforms using an Atmel NAND - controller. + bool "Support Atmel NAND controller with DM support" + select SYS_NAND_SELF_INIT + imply SYS_NAND_USE_FLASH_BBT + help + Enable this driver for NAND flash platforms using an Atmel NAND + controller. config NAND_ATMEL bool "Support Atmel NAND controller" @@ -133,35 +133,35 @@ config NAND_BRCMNAND_6753 Enable support for broadcom nand driver on bcm6753. config NAND_BRCMNAND_68360 - bool "Support Broadcom NAND controller on bcm68360" - depends on NAND_BRCMNAND && BCM6856 - help - Enable support for broadcom nand driver on bcm68360. + bool "Support Broadcom NAND controller on bcm68360" + depends on NAND_BRCMNAND && BCM6856 + help + Enable support for broadcom nand driver on bcm68360. config NAND_BRCMNAND_6838 - bool "Support Broadcom NAND controller on bcm6838" - depends on NAND_BRCMNAND && ARCH_BMIPS && SOC_BMIPS_BCM6838 - help - Enable support for broadcom nand driver on bcm6838. + bool "Support Broadcom NAND controller on bcm6838" + depends on NAND_BRCMNAND && ARCH_BMIPS && SOC_BMIPS_BCM6838 + help + Enable support for broadcom nand driver on bcm6838. config NAND_BRCMNAND_6858 - bool "Support Broadcom NAND controller on bcm6858" - depends on NAND_BRCMNAND && BCM6858 - help - Enable support for broadcom nand driver on bcm6858. + bool "Support Broadcom NAND controller on bcm6858" + depends on NAND_BRCMNAND && BCM6858 + help + Enable support for broadcom nand driver on bcm6858. config NAND_BRCMNAND_63158 - bool "Support Broadcom NAND controller on bcm63158" - depends on NAND_BRCMNAND && BCM63158 - help - Enable support for broadcom nand driver on bcm63158. + bool "Support Broadcom NAND controller on bcm63158" + depends on NAND_BRCMNAND && BCM63158 + help + Enable support for broadcom nand driver on bcm63158. config NAND_BRCMNAND_IPROC - bool "Support Broadcom NAND controller on the iproc family" - depends on NAND_BRCMNAND - help - Enable support for broadcom nand driver on the Broadcom - iproc family such as Northstar (BCM5301x, BCM4708...) + bool "Support Broadcom NAND controller on the iproc family" + depends on NAND_BRCMNAND + help + Enable support for broadcom nand driver on the Broadcom + iproc family such as Northstar (BCM5301x, BCM4708...) config NAND_DAVINCI bool "Support TI Davinci NAND controller" @@ -413,10 +413,10 @@ config NAND_VF610_NFC if NAND_VF610_NFC config NAND_VF610_NFC_DT - bool "Support Vybrid's vf610 NAND controller as a DT device" - depends on OF_CONTROL && DM_MTD - help - Enable the driver for Vybrid's vf610 NAND flash on platforms + bool "Support Vybrid's vf610 NAND controller as a DT device" + depends on OF_CONTROL && DM_MTD + help + Enable the driver for Vybrid's vf610 NAND flash on platforms using device tree. choice @@ -472,11 +472,11 @@ config NAND_SUNXI select SPL_NAND_SUPPORT select SPL_SYS_NAND_SELF_INIT imply CMD_NAND - ---help--- - Enable support for NAND. This option enables the standard and - SPL drivers. - The SPL driver only supports reading from the NAND using DMA - transfers. + help + Enable support for NAND. This option enables the standard and + SPL drivers. + The SPL driver only supports reading from the NAND using DMA + transfers. if NAND_SUNXI @@ -504,6 +504,15 @@ config NAND_ARASAN controller. This uses the hardware ECC for read and write operations. +config NAND_MESON + bool "Meson NAND support" + select SYS_NAND_SELF_INIT + depends on DM_MTD && ARCH_MESON + imply CMD_NAND + help + This enables Nand driver support for Meson raw NAND flash + controller. + config NAND_MXC bool "MXC NAND support" depends on CPU_ARM926EJS || CPU_ARM1136 || MX5 @@ -577,16 +586,16 @@ config NAND_OCTEONTX select SYS_NAND_SELF_INIT imply CMD_NAND help - This enables Nand flash controller hardware found on the OcteonTX - processors. + This enables Nand flash controller hardware found on the OcteonTX + processors. config NAND_OCTEONTX_HW_ECC bool "Support Hardware ECC for OcteonTX NAND controller" depends on NAND_OCTEONTX default y help - This enables Hardware BCH engine found on the OcteonTX processors to - support ECC for NAND flash controller. + This enables Hardware BCH engine found on the OcteonTX processors to + support ECC for NAND flash controller. config NAND_STM32_FMC2 bool "Support for NAND controller on STM32MP SoCs" @@ -751,37 +760,37 @@ config SYS_NAND_BAD_BLOCK_POS config SYS_NAND_U_BOOT_LOCATIONS bool "Define U-Boot binaries locations in NAND" help - Enable CONFIG_SYS_NAND_U_BOOT_OFFS though Kconfig. - This option should not be enabled when compiling U-Boot for boards - defining CONFIG_SYS_NAND_U_BOOT_OFFS in their include/configs/<board>.h - file. + Enable CONFIG_SYS_NAND_U_BOOT_OFFS though Kconfig. + This option should not be enabled when compiling U-Boot for boards + defining CONFIG_SYS_NAND_U_BOOT_OFFS in their include/configs/<board>.h + file. config SYS_NAND_U_BOOT_OFFS hex "Location in NAND to read U-Boot from" default 0x800000 if NAND_SUNXI depends on SYS_NAND_U_BOOT_LOCATIONS help - Set the offset from the start of the nand where u-boot should be - loaded from. + Set the offset from the start of the nand where u-boot should be + loaded from. config SYS_NAND_U_BOOT_OFFS_REDUND hex "Location in NAND to read U-Boot from" default SYS_NAND_U_BOOT_OFFS depends on SYS_NAND_U_BOOT_LOCATIONS help - Set the offset from the start of the nand where the redundant u-boot - should be loaded from. + Set the offset from the start of the nand where the redundant u-boot + should be loaded from. config SPL_NAND_AM33XX_BCH bool "Enables SPL-NAND driver which supports ELM based" depends on SPL_NAND_SUPPORT && NAND_OMAP_GPMC && !OMAP34XX default y - help + help Hardware ECC correction. This is useful for platforms which have ELM hardware engine and use NAND boot mode. Some legacy platforms like OMAP3xx do not have in-built ELM h/w engine, so those platforms should use CONFIG_SPL_NAND_SIMPLE for enabling - SPL-NAND driver with software ECC correction support. + SPL-NAND driver with software ECC correction support. config SPL_NAND_DENALI bool "Support Denali NAND controller for SPL" @@ -810,6 +819,6 @@ config SYS_NAND_HW_ECC_OOBFIRST bool "In SPL, read the OOB first and then the data from NAND" depends on SPL_NAND_SIMPLE -endif +endif # if SPL -endif # if NAND +endif # if MTD_RAW_NAND diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index ddbba899e58..46fead6fa48 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o obj-$(CONFIG_NAND_LPC32XX_MLC) += lpc32xx_nand_mlc.o obj-$(CONFIG_NAND_LPC32XX_SLC) += lpc32xx_nand_slc.o obj-$(CONFIG_NAND_VF610_NFC) += vf610_nfc.o +obj-$(CONFIG_NAND_MESON) += meson_nand.o obj-$(CONFIG_NAND_MXC) += mxc_nand.o obj-$(CONFIG_NAND_MXS) += mxs_nand.o obj-$(CONFIG_NAND_MXS_DT) += mxs_nand_dt.o diff --git a/drivers/mtd/nand/raw/arasan_nfc.c b/drivers/mtd/nand/raw/arasan_nfc.c index 14766401bf6..ffcd963b3da 100644 --- a/drivers/mtd/nand/raw/arasan_nfc.c +++ b/drivers/mtd/nand/raw/arasan_nfc.c @@ -1232,7 +1232,8 @@ static int arasan_probe(struct udevice *dev) struct nand_config *nand = &info->config; struct mtd_info *mtd; ofnode child; - int err = -1; + int ret; + const char *str; info->reg = dev_read_addr_ptr(dev); mtd = nand_to_mtd(nand_chip); @@ -1258,9 +1259,16 @@ static int arasan_probe(struct udevice *dev) writel(0x0, &info->reg->pgm_reg); /* first scan to find the device and get the page size */ - if (nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL)) { + ret = nand_scan_ident(mtd, CONFIG_SYS_NAND_MAX_CHIPS, NULL); + if (ret) { printf("%s: nand_scan_ident failed\n", __func__); - goto fail; + return ret; + } + + str = ofnode_read_string(nand_chip->flash_node, "nand-ecc-mode"); + if (!str || strcmp(str, "hw") != 0) { + printf("%s ecc mode is not supported\n", str); + return -EINVAL; } nand_chip->ecc.mode = NAND_ECC_HW; @@ -1282,26 +1290,26 @@ static int arasan_probe(struct udevice *dev) nand_chip->ecc.bytes = 0; nand_chip->ecc.layout = &ondie_nand_oob_64; } else { - if (arasan_nand_ecc_init(mtd)) { + ret = arasan_nand_ecc_init(mtd); + if (ret) { printf("%s: nand_ecc_init failed\n", __func__); - goto fail; + return ret; } } - if (nand_scan_tail(mtd)) { + ret = nand_scan_tail(mtd); + if (ret) { printf("%s: nand_scan_tail failed\n", __func__); - goto fail; + return ret; } - if (nand_register(0, mtd)) { + ret = nand_register(0, mtd); + if (ret) { printf("Nand Register Fail\n"); - goto fail; + return ret; } - return 0; -fail: - free(nand); - return err; + return ret; } static const struct udevice_id arasan_nand_dt_ids[] = { diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index 0e0441472b8..ee4ec6da587 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -1267,7 +1267,7 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand, return ret; /* - * The write cycle timing is directly matching tWC, but is also + * The read cycle timing is directly matching tRC, but is also * dependent on the setup and hold timings we calculated earlier, * which gives: * @@ -1429,8 +1429,6 @@ static int atmel_nand_setup_data_interface(struct mtd_info *mtd, int csline, return nc->caps->ops->setup_data_interface(nand, csline, conf); } -#define NAND_KEEP_TIMINGS 0x00800000 - static void atmel_nand_init(struct atmel_nand_controller *nc, struct atmel_nand *nand) { diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c new file mode 100644 index 00000000000..12499a79478 --- /dev/null +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -0,0 +1,1247 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Amlogic Meson Nand Flash Controller Driver + * + * Copyright (c) 2018 Amlogic, inc. + * Author: Liang Yang <liang.yang@amlogic.com> + * + * Copyright (c) 2023 SaluteDevices, Inc. + * Author: Arseniy Krasnov <avkrasnov@salutedevices.com> + */ + +#include <nand.h> +#include <asm/io.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/ofnode.h> +#include <dm/uclass.h> +#include <linux/bug.h> +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/iopoll.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/rawnand.h> +#include <linux/sizes.h> + +#define NFC_CMD_IDLE (0xc << 14) +#define NFC_CMD_CLE (0x5 << 14) +#define NFC_CMD_ALE (0x6 << 14) +#define NFC_CMD_DWR (0x4 << 14) +#define NFC_CMD_DRD (0x8 << 14) +#define NFC_CMD_ADL ((0 << 16) | (3 << 20)) +#define NFC_CMD_ADH ((1 << 16) | (3 << 20)) +#define NFC_CMD_AIL ((2 << 16) | (3 << 20)) +#define NFC_CMD_AIH ((3 << 16) | (3 << 20)) +#define NFC_CMD_SEED ((8 << 16) | (3 << 20)) +#define NFC_CMD_M2N ((0 << 17) | (2 << 20)) +#define NFC_CMD_N2M ((1 << 17) | (2 << 20)) +#define NFC_CMD_RB BIT(20) +#define NFC_CMD_SCRAMBLER_ENABLE BIT(19) +#define NFC_CMD_SCRAMBLER_DISABLE 0 +#define NFC_CMD_SHORTMODE_DISABLE 0 +#define NFC_CMD_RB_INT BIT(14) +#define NFC_CMD_RB_INT_NO_PIN ((0xb << 10) | BIT(18) | BIT(16)) + +#define NFC_CMD_GET_SIZE(x) (((x) >> 22) & GENMASK(4, 0)) + +#define NFC_REG_CMD 0x00 +#define NFC_REG_CFG 0x04 +#define NFC_REG_DADR 0x08 +#define NFC_REG_IADR 0x0c +#define NFC_REG_BUF 0x10 +#define NFC_REG_INFO 0x14 +#define NFC_REG_DC 0x18 +#define NFC_REG_ADR 0x1c +#define NFC_REG_DL 0x20 +#define NFC_REG_DH 0x24 +#define NFC_REG_CADR 0x28 +#define NFC_REG_SADR 0x2c +#define NFC_REG_PINS 0x30 +#define NFC_REG_VER 0x38 + +#define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \ + ( \ + (cmd_dir) | \ + (ran) | \ + ((bch) << 14) | \ + ((short_mode) << 13) | \ + (((page_size) & 0x7f) << 6) | \ + ((pages) & 0x3f) \ + ) + +#define GENCMDDADDRL(adl, addr) ((adl) | ((addr) & 0xffff)) +#define GENCMDDADDRH(adh, addr) ((adh) | (((addr) >> 16) & 0xffff)) +#define GENCMDIADDRL(ail, addr) ((ail) | ((addr) & 0xffff)) +#define GENCMDIADDRH(aih, addr) ((aih) | (((addr) >> 16) & 0xffff)) + +#define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N) + +#define ECC_CHECK_RETURN_FF -1 + +#define NAND_CE0 (0xe << 10) +#define NAND_CE1 (0xd << 10) + +#define DMA_BUSY_TIMEOUT_US 1000000 +#define CMD_DRAIN_TIMEOUT_US 1000 +#define ECC_POLL_TIMEOUT_US 15 + +#define MAX_CE_NUM 2 + +/* eMMC clock register, misc control */ +#define CLK_SELECT_NAND BIT(31) +#define CLK_ALWAYS_ON_NAND BIT(24) +#define CLK_ENABLE_VALUE 0x245 + +#define DIRREAD 1 +#define DIRWRITE 0 + +#define ECC_PARITY_BCH8_512B 14 +#define ECC_COMPLETE BIT(31) +#define ECC_ERR_CNT(x) (((x) >> 24) & GENMASK(5, 0)) +#define ECC_ZERO_CNT(x) (((x) >> 16) & GENMASK(5, 0)) +#define ECC_UNCORRECTABLE 0x3f + +#define PER_INFO_BYTE 8 + +#define NFC_SEND_CMD(host, cmd) \ + (writel((cmd), (host)->reg_base + NFC_REG_CMD)) + +#define NFC_GET_CMD(host) \ + (readl((host)->reg_base + NFC_REG_CMD)) + +#define NFC_CMDFIFO_SIZE(host) ((NFC_GET_CMD((host)) >> 22) & GENMASK(4, 0)) + +#define NFC_CMD_MAKE_IDLE(ce, delay) ((ce) | NFC_CMD_IDLE | ((delay) & 0x3ff)) +#define NFC_CMD_MAKE_DRD(ce, size) ((ce) | NFC_CMD_DRD | (size)) +#define NFC_CMD_MAKE_DWR(ce, data) ((ce) | NFC_CMD_DWR | ((data) & 0xff)) +#define NFC_CMD_MAKE_CLE(ce, cmd_val) ((ce) | NFC_CMD_CLE | ((cmd_val) & 0xff)) +#define NFC_CMD_MAKE_ALE(ce, addr) ((ce) | NFC_CMD_ALE | ((addr) & 0xff)) + +#define NAND_TWB_TIME_CYCLE 10 + +#define NFC_DEV_READY_TICK_MAX 5000 + +/* Both values are recommended by vendor, as the most + * tested with almost all SLC NAND flash. Second value + * could be calculated dynamically from timing parameters, + * but we need both values for initial start of the NAND + * controller (e.g. before NAND subsystem processes timings), + * so use hardcoded constants. + */ +#define NFC_DEFAULT_BUS_CYCLE 6 +#define NFC_DEFAULT_BUS_TIMING 7 + +#define NFC_SEED_OFFSET 0xc2 +#define NFC_SEED_MASK 0x7fff + +#define DMA_ADDR_ALIGN 8 + +struct meson_nfc_nand_chip { + struct list_head node; + struct nand_chip nand; + + u32 bch_mode; + u8 *data_buf; + __le64 *info_buf; + u32 nsels; + u8 sels[]; +}; + +struct meson_nfc_param { + u32 chip_select; + u32 rb_select; +}; + +struct meson_nfc { + void __iomem *reg_base; + void __iomem *reg_clk; + struct list_head chips; + struct meson_nfc_param param; + struct udevice *dev; + dma_addr_t daddr; + dma_addr_t iaddr; + u32 data_bytes; + u32 info_bytes; + u64 assigned_cs; +}; + +struct meson_nand_ecc { + u32 bch; + u32 strength; + u32 size; +}; + +enum { + NFC_ECC_BCH8_512 = 1, + NFC_ECC_BCH8_1K, + NFC_ECC_BCH24_1K, + NFC_ECC_BCH30_1K, + NFC_ECC_BCH40_1K, + NFC_ECC_BCH50_1K, + NFC_ECC_BCH60_1K, +}; + +#define MESON_ECC_DATA(b, s, sz) { .bch = (b), .strength = (s), .size = (sz) } + +static struct meson_nand_ecc meson_ecc[] = { + MESON_ECC_DATA(NFC_ECC_BCH8_512, 8, 512), + MESON_ECC_DATA(NFC_ECC_BCH8_1K, 8, 1024), +}; + +static int meson_nand_calc_ecc_bytes(int step_size, int strength) +{ + int ecc_bytes; + + if (step_size == 512 && strength == 8) + return ECC_PARITY_BCH8_512B; + + ecc_bytes = DIV_ROUND_UP(strength * fls(step_size * 8), 8); + ecc_bytes = ALIGN(ecc_bytes, 2); + + return ecc_bytes; +} + +static struct meson_nfc_nand_chip *to_meson_nand(struct nand_chip *nand) +{ + return container_of(nand, struct meson_nfc_nand_chip, nand); +} + +static void meson_nfc_nand_select_chip(struct mtd_info *mtd, int chip) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + struct meson_nfc *nfc = nand_get_controller_data(nand); + + nfc->param.chip_select = meson_chip->sels[chip] ? NAND_CE1 : NAND_CE0; +} + +static void meson_nfc_cmd_idle(struct meson_nfc *nfc, u32 time) +{ + writel(NFC_CMD_MAKE_IDLE(nfc->param.chip_select, time), + nfc->reg_base + NFC_REG_CMD); +} + +static void meson_nfc_cmd_seed(const struct meson_nfc *nfc, u32 seed) +{ + writel(NFC_CMD_SEED | (NFC_SEED_OFFSET + (seed & NFC_SEED_MASK)), + nfc->reg_base + NFC_REG_CMD); +} + +static void meson_nfc_cmd_access(struct nand_chip *nand, bool raw, bool dir, + int scrambler) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + const struct meson_nfc *nfc = nand_get_controller_data(mtd_to_nand(mtd)); + const struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + u32 bch = meson_chip->bch_mode, cmd; + int len = mtd->writesize, pagesize, pages; + + pagesize = nand->ecc.size; + + if (raw) { + len = mtd->writesize + mtd->oobsize; + cmd = len | scrambler | DMA_DIR(dir); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + return; + } + + pages = len / nand->ecc.size; + + cmd = CMDRWGEN(DMA_DIR(dir), scrambler, bch, + NFC_CMD_SHORTMODE_DISABLE, pagesize, pages); + + writel(cmd, nfc->reg_base + NFC_REG_CMD); +} + +static void meson_nfc_drain_cmd(struct meson_nfc *nfc) +{ + /* + * Insert two commands to make sure all valid commands are finished. + * + * The Nand flash controller is designed as two stages pipleline - + * a) fetch and b) execute. + * There might be cases when the driver see command queue is empty, + * but the Nand flash controller still has two commands buffered, + * one is fetched into NFC request queue (ready to run), and another + * is actively executing. So pushing 2 "IDLE" commands guarantees that + * the pipeline is emptied. + */ + meson_nfc_cmd_idle(nfc, 0); + meson_nfc_cmd_idle(nfc, 0); +} + +static int meson_nfc_wait_cmd_finish(const struct meson_nfc *nfc, + unsigned int timeout_us) +{ + u32 cmd_size = 0; + + /* wait cmd fifo is empty */ + return readl_relaxed_poll_timeout(nfc->reg_base + NFC_REG_CMD, cmd_size, + !NFC_CMD_GET_SIZE(cmd_size), + timeout_us); +} + +static int meson_nfc_wait_dma_finish(struct meson_nfc *nfc) +{ + meson_nfc_drain_cmd(nfc); + + return meson_nfc_wait_cmd_finish(nfc, DMA_BUSY_TIMEOUT_US); +} + +static u8 *meson_nfc_oob_ptr(struct nand_chip *nand, int i) +{ + const struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + int len; + + len = nand->ecc.size * (i + 1) + (nand->ecc.bytes + 2) * i; + + return meson_chip->data_buf + len; +} + +static u8 *meson_nfc_data_ptr(struct nand_chip *nand, int i) +{ + const struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + int len, temp; + + temp = nand->ecc.size + nand->ecc.bytes; + len = (temp + 2) * i; + + return meson_chip->data_buf + len; +} + +static void meson_nfc_get_data_oob(struct nand_chip *nand, + u8 *buf, u8 *oobbuf) +{ + u8 *dsrc, *osrc; + int i, oob_len; + + oob_len = nand->ecc.bytes + 2; + for (i = 0; i < nand->ecc.steps; i++) { + if (buf) { + dsrc = meson_nfc_data_ptr(nand, i); + memcpy(buf, dsrc, nand->ecc.size); + buf += nand->ecc.size; + } + + if (oobbuf) { + osrc = meson_nfc_oob_ptr(nand, i); + memcpy(oobbuf, osrc, oob_len); + oobbuf += oob_len; + } + } +} + +static void meson_nfc_set_data_oob(struct nand_chip *nand, + const u8 *buf, u8 *oobbuf) +{ + int i, oob_len; + + oob_len = nand->ecc.bytes + 2; + for (i = 0; i < nand->ecc.steps; i++) { + u8 *osrc; + + if (buf) { + u8 *dsrc; + + dsrc = meson_nfc_data_ptr(nand, i); + memcpy(dsrc, buf, nand->ecc.size); + buf += nand->ecc.size; + } + + osrc = meson_nfc_oob_ptr(nand, i); + memcpy(osrc, oobbuf, oob_len); + oobbuf += oob_len; + } +} + +static void meson_nfc_set_user_byte(struct nand_chip *nand, const u8 *oob_buf) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + int i, count; + + for (i = 0, count = 0; i < nand->ecc.steps; i++, count += (2 + nand->ecc.bytes)) { + __le64 *info = &meson_chip->info_buf[i]; + + *info |= oob_buf[count]; + *info |= oob_buf[count + 1] << 8; + } +} + +static void meson_nfc_get_user_byte(struct nand_chip *nand, u8 *oob_buf) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + int i, count; + + for (i = 0, count = 0; i < nand->ecc.steps; i++, count += (2 + nand->ecc.bytes)) { + const __le64 *info = &meson_chip->info_buf[i]; + + oob_buf[count] = *info; + oob_buf[count + 1] = *info >> 8; + } +} + +static int meson_nfc_ecc_correct(struct nand_chip *nand, u32 *bitflips, + u64 *correct_bitmap) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + int ret = 0, i; + + for (i = 0; i < nand->ecc.steps; i++) { + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + const __le64 *info = &meson_chip->info_buf[i]; + + if (ECC_ERR_CNT(*info) != ECC_UNCORRECTABLE) { + mtd->ecc_stats.corrected += ECC_ERR_CNT(*info); + *bitflips = max_t(u32, *bitflips, ECC_ERR_CNT(*info)); + *correct_bitmap |= BIT_ULL(i); + continue; + } + + if ((nand->options & NAND_NEED_SCRAMBLING) && + ECC_ZERO_CNT(*info) < nand->ecc.strength) { + mtd->ecc_stats.corrected += ECC_ZERO_CNT(*info); + *bitflips = max_t(u32, *bitflips, + ECC_ZERO_CNT(*info)); + ret = ECC_CHECK_RETURN_FF; + } else { + ret = -EBADMSG; + } + } + + return ret; +} + +static int meson_nfc_dma_buffer_setup(struct nand_chip *nand, void *databuf, + int datalen, void *infobuf, int infolen, + enum dma_data_direction dir) +{ + struct meson_nfc *nfc = nand_get_controller_data(nand); + int ret; + u32 cmd; + + nfc->daddr = dma_map_single(databuf, datalen, DMA_BIDIRECTIONAL); + ret = dma_mapping_error(nfc->dev, nfc->daddr); + if (ret) + return ret; + + cmd = GENCMDDADDRL(NFC_CMD_ADL, nfc->daddr); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + cmd = GENCMDDADDRH(NFC_CMD_ADH, nfc->daddr); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + if (infobuf) { + nfc->iaddr = dma_map_single(infobuf, infolen, + DMA_BIDIRECTIONAL); + ret = dma_mapping_error(nfc->dev, nfc->iaddr); + if (ret) { + dma_unmap_single(nfc->daddr, datalen, dir); + return ret; + } + + nfc->info_bytes = infolen; + cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + cmd = GENCMDIADDRH(NFC_CMD_AIH, nfc->iaddr); + writel(cmd, nfc->reg_base + NFC_REG_CMD); + } + + return 0; +} + +static void meson_nfc_dma_buffer_release(struct nand_chip *nand, + int datalen, int infolen, + enum dma_data_direction dir) +{ + struct meson_nfc *nfc = nand_get_controller_data(nand); + + dma_unmap_single(nfc->daddr, datalen, dir); + + if (infolen) { + dma_unmap_single(nfc->iaddr, infolen, dir); + nfc->info_bytes = 0; + } +} + +static void meson_nfc_read_buf(struct mtd_info *mtd, u8 *buf, int size) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct meson_nfc *nfc = nand_get_controller_data(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + u8 *dma_buf; + int ret; + u32 cmd; + + if ((uintptr_t)buf % DMA_ADDR_ALIGN) { + unsigned long tmp_addr; + + dma_buf = dma_alloc_coherent(size, &tmp_addr); + if (!dma_buf) + return; + } else { + dma_buf = buf; + } + + ret = meson_nfc_dma_buffer_setup(nand, dma_buf, size, meson_chip->info_buf, + PER_INFO_BYTE, DMA_FROM_DEVICE); + if (ret) { + pr_err("Failed to setup DMA buffer %p/%p\n", dma_buf, + meson_chip->info_buf); + return; + } + + cmd = NFC_CMD_N2M | size; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, CMD_DRAIN_TIMEOUT_US); + meson_nfc_dma_buffer_release(nand, size, PER_INFO_BYTE, DMA_FROM_DEVICE); + + if (buf != dma_buf) { + memcpy(buf, dma_buf, size); + dma_free_coherent(dma_buf); + } +} + +static void meson_nfc_write_buf(struct mtd_info *mtd, const u8 *buf, int size) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct meson_nfc *nfc = nand_get_controller_data(nand); + u8 *dma_buf; + int ret; + u32 cmd; + + if ((uintptr_t)buf % DMA_ADDR_ALIGN) { + unsigned long tmp_addr; + + dma_buf = dma_alloc_coherent(size, &tmp_addr); + if (!dma_buf) + return; + + memcpy(dma_buf, buf, size); + } else { + dma_buf = (u8 *)buf; + } + + ret = meson_nfc_dma_buffer_setup(nand, (void *)dma_buf, size, NULL, + 0, DMA_TO_DEVICE); + if (ret) { + pr_err("Failed to setup DMA buffer %p\n", dma_buf); + return; + } + + cmd = NFC_CMD_M2N | size; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + meson_nfc_drain_cmd(nfc); + meson_nfc_wait_cmd_finish(nfc, CMD_DRAIN_TIMEOUT_US); + meson_nfc_dma_buffer_release(nand, size, 0, DMA_TO_DEVICE); + + if (buf != dma_buf) + dma_free_coherent(dma_buf); +} + +static int meson_nfc_write_page_sub(struct nand_chip *nand, + int page, bool raw) +{ + const struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + struct meson_nfc *nfc = nand_get_controller_data(nand); + int data_len, info_len; + int ret; + u32 cmd; + + data_len = mtd->writesize + mtd->oobsize; + info_len = nand->ecc.steps * PER_INFO_BYTE; + + ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf, + data_len, meson_chip->info_buf, + info_len, DMA_TO_DEVICE); + if (ret) { + pr_err("Failed to setup DMA buffer %p/%p\n", + meson_chip->data_buf, meson_chip->info_buf); + return ret; + } + + if (nand->options & NAND_NEED_SCRAMBLING) { + meson_nfc_cmd_seed(nfc, page); + meson_nfc_cmd_access(nand, raw, DIRWRITE, + NFC_CMD_SCRAMBLER_ENABLE); + } else { + meson_nfc_cmd_access(nand, raw, DIRWRITE, + NFC_CMD_SCRAMBLER_DISABLE); + } + + cmd = nfc->param.chip_select | NFC_CMD_CLE | NAND_CMD_PAGEPROG; + writel(cmd, nfc->reg_base + NFC_REG_CMD); + + meson_nfc_dma_buffer_release(nand, data_len, info_len, DMA_TO_DEVICE); + + return 0; +} + +static int meson_nfc_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, + const u8 *buf, int oob_required, int page) +{ + meson_nfc_set_data_oob(chip, buf, oob_required ? chip->oob_poi : NULL); + + return meson_nfc_write_page_sub(chip, page, true); +} + +static int meson_nfc_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, + const u8 *buf, int oob_required, int page) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(chip); + + if (buf) + memcpy(meson_chip->data_buf, buf, mtd->writesize); + + memset(meson_chip->info_buf, 0, chip->ecc.steps * PER_INFO_BYTE); + + if (oob_required) + meson_nfc_set_user_byte(chip, chip->oob_poi); + + return meson_nfc_write_page_sub(chip, page, false); +} + +static void meson_nfc_check_ecc_pages_valid(struct meson_nfc *nfc, + struct nand_chip *nand, bool raw) +{ + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + __le64 *info; + u32 neccpages; + int ret; + + neccpages = raw ? 1 : nand->ecc.steps; + info = &meson_chip->info_buf[neccpages - 1]; + do { + udelay(ECC_POLL_TIMEOUT_US); + /* info is updated by nfc dma engine*/ + rmb(); + invalidate_dcache_range(nfc->iaddr, nfc->iaddr + nfc->info_bytes); + ret = *info & ECC_COMPLETE; + } while (!ret); +} + +static int meson_nfc_read_page_sub(struct nand_chip *nand, + int page, bool raw) +{ + struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc *nfc = nand_get_controller_data(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + u32 data_len, info_len; + int ret; + + data_len = mtd->writesize + mtd->oobsize; + info_len = nand->ecc.steps * PER_INFO_BYTE; + + ret = meson_nfc_dma_buffer_setup(nand, meson_chip->data_buf, data_len, + meson_chip->info_buf, info_len, + DMA_FROM_DEVICE); + if (ret) + return ret; + + if (nand->options & NAND_NEED_SCRAMBLING) { + meson_nfc_cmd_seed(nfc, page); + meson_nfc_cmd_access(nand, raw, DIRREAD, + NFC_CMD_SCRAMBLER_ENABLE); + } else { + meson_nfc_cmd_access(nand, raw, DIRREAD, + NFC_CMD_SCRAMBLER_DISABLE); + } + + meson_nfc_wait_dma_finish(nfc); + meson_nfc_check_ecc_pages_valid(nfc, nand, raw); + + meson_nfc_dma_buffer_release(nand, data_len, info_len, + DMA_FROM_DEVICE); + + return 0; +} + +static int meson_nfc_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, + u8 *buf, int oob_required, int page) +{ + int ret; + + ret = meson_nfc_read_page_sub(chip, page, true); + if (ret) + return ret; + + meson_nfc_get_data_oob(chip, buf, oob_required ? chip->oob_poi : NULL); + + return 0; +} + +static int meson_nfc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, + u8 *buf, int oob_required, int page) +{ + const struct meson_nfc_nand_chip *meson_chip = to_meson_nand(chip); + u64 correct_bitmap = 0; + u32 bitflips = 0; + int ret; + + ret = meson_nfc_read_page_sub(chip, page, false); + if (ret) + return ret; + + if (oob_required) + meson_nfc_get_user_byte(chip, chip->oob_poi); + + ret = meson_nfc_ecc_correct(chip, &bitflips, &correct_bitmap); + + if (ret == ECC_CHECK_RETURN_FF) { + if (buf) + memset(buf, 0xff, mtd->writesize); + + if (oob_required) + memset(chip->oob_poi, 0xff, mtd->oobsize); + } else if (ret < 0) { + struct nand_ecc_ctrl *ecc; + int i; + + if ((chip->options & NAND_NEED_SCRAMBLING) || !buf) { + mtd->ecc_stats.failed++; + return bitflips; + } + + chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page); + + ret = meson_nfc_read_page_raw(mtd, chip, buf, 1, page); + if (ret) + return ret; + + ecc = &chip->ecc; + + for (i = 0; i < chip->ecc.steps ; i++) { + u8 *data = buf + i * ecc->size; + u8 *oob = chip->oob_poi + i * (ecc->bytes + 2); + + if (correct_bitmap & BIT_ULL(i)) + continue; + + ret = nand_check_erased_ecc_chunk(data, ecc->size, + oob, ecc->bytes + 2, + NULL, 0, + ecc->strength); + if (ret < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += ret; + bitflips = max_t(u32, bitflips, ret); + } + } + } else if (buf && buf != meson_chip->data_buf) { + memcpy(buf, meson_chip->data_buf, mtd->writesize); + } + + return bitflips; +} + +static int meson_nfc_read_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + int ret; + + ret = nand_read_page_op(chip, page, 0, NULL, 0); + if (ret) + return ret; + + return meson_nfc_read_page_raw(mtd, chip, NULL, 1, page); +} + +static int meson_nfc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + int ret; + + ret = nand_read_page_op(chip, page, 0, NULL, 0); + if (ret) + return ret; + + return meson_nfc_read_page_hwecc(mtd, chip, NULL, 1, page); +} + +static int meson_nfc_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + int ret; + + ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0); + if (ret) + return ret; + + ret = meson_nfc_write_page_raw(mtd, chip, NULL, 1, page); + if (ret) + return ret; + + return nand_prog_page_end_op(chip); +} + +static int meson_nfc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page) +{ + int ret; + + ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0); + if (ret) + return ret; + + ret = meson_nfc_write_page_hwecc(mtd, chip, NULL, 1, page); + if (ret) + return ret; + + return nand_prog_page_end_op(chip); +} + +static void meson_nfc_nand_cmd_function(struct mtd_info *mtd, unsigned int command, + int column, int page_addr) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + + chip->cmd_ctrl(mtd, command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + + if (column != -1 || page_addr != -1) { + int ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; + + /* Serially input address */ + if (column != -1) { + /* Adjust columns for 16 bit buswidth */ + if (chip->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) + column >>= 1; + + chip->cmd_ctrl(mtd, column, ctrl); + ctrl &= ~NAND_CTRL_CHANGE; + /* Only output a single addr cycle for 8bits + * opcodes. + */ + if (!nand_opcode_8bits(command)) + chip->cmd_ctrl(mtd, column >> 8, ctrl); + } + + if (page_addr != -1) { + chip->cmd_ctrl(mtd, page_addr, ctrl); + chip->cmd_ctrl(mtd, page_addr >> 8, NAND_NCE | + NAND_ALE); + /* One more address cycle for devices > 128MiB */ + if (chip->chipsize > SZ_128M) + chip->cmd_ctrl(mtd, page_addr >> 16, + NAND_NCE | NAND_ALE); + } + + switch (command) { + case NAND_CMD_READ0: + chip->cmd_ctrl(mtd, NAND_CMD_READSTART, + NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); + fallthrough; + case NAND_CMD_PARAM: + nand_wait_ready(mtd); + nand_exit_status_op(chip); + } + } +} + +static void meson_nfc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct meson_nfc *nfc = nand_get_controller_data(nand); + + if (cmd == NAND_CMD_NONE) + return; + + if (ctrl & NAND_CLE) + cmd = NFC_CMD_MAKE_CLE(nfc->param.chip_select, cmd); + else + cmd = NFC_CMD_MAKE_ALE(nfc->param.chip_select, cmd); + + writel(cmd, nfc->reg_base + NFC_REG_CMD); +} + +static void meson_nfc_wait_cmd_fifo(struct meson_nfc *nfc) +{ + while ((NFC_GET_CMD(nfc) >> 22) & GENMASK(4, 0)) + ; +} + +static u8 meson_nfc_nand_read_byte(struct mtd_info *mtd) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct meson_nfc *nfc = nand_get_controller_data(nand); + + writel(NFC_CMD_MAKE_DRD(nfc->param.chip_select, 0), nfc->reg_base + NFC_REG_CMD); + + meson_nfc_cmd_idle(nfc, NAND_TWB_TIME_CYCLE); + meson_nfc_cmd_idle(nfc, 0); + meson_nfc_cmd_idle(nfc, 0); + + meson_nfc_wait_cmd_fifo(nfc); + + return readl(nfc->reg_base + NFC_REG_BUF); +} + +static void meson_nfc_nand_write_byte(struct mtd_info *mtd, u8 val) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct meson_nfc *nfc = nand_get_controller_data(nand); + + meson_nfc_cmd_idle(nfc, NAND_TWB_TIME_CYCLE); + + writel(NFC_CMD_MAKE_DWR(nfc->param.chip_select, val), nfc->reg_base + NFC_REG_CMD); + + meson_nfc_cmd_idle(nfc, NAND_TWB_TIME_CYCLE); + meson_nfc_cmd_idle(nfc, 0); + meson_nfc_cmd_idle(nfc, 0); + + meson_nfc_wait_cmd_fifo(nfc); +} + +static int meson_nfc_dev_ready(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + unsigned int time_out_cnt = 0; + + chip->select_chip(mtd, 0); + + chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); + + do { + int status; + + status = (int)chip->read_byte(mtd); + if (status & NAND_STATUS_READY) + break; + } while (time_out_cnt++ < NFC_DEV_READY_TICK_MAX); + + return time_out_cnt != NFC_DEV_READY_TICK_MAX; +} + +static int meson_chip_buffer_init(struct nand_chip *nand) +{ + const struct mtd_info *mtd = nand_to_mtd(nand); + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + u32 page_bytes, info_bytes, nsectors; + unsigned long tmp_addr; + + nsectors = mtd->writesize / nand->ecc.size; + + page_bytes = mtd->writesize + mtd->oobsize; + info_bytes = nsectors * PER_INFO_BYTE; + + meson_chip->data_buf = dma_alloc_coherent(page_bytes, &tmp_addr); + if (!meson_chip->data_buf) + return -ENOMEM; + + meson_chip->info_buf = dma_alloc_coherent(info_bytes, &tmp_addr); + if (!meson_chip->info_buf) { + dma_free_coherent(meson_chip->data_buf); + return -ENOMEM; + } + + return 0; +} + +static const int axg_stepinfo_strengths[] = { 8 }; +static const struct nand_ecc_step_info axg_stepinfo_1024 = { + .stepsize = 1024, + .strengths = axg_stepinfo_strengths, + .nstrengths = ARRAY_SIZE(axg_stepinfo_strengths) +}; + +static const struct nand_ecc_step_info axg_stepinfo_512 = { + .stepsize = 512, + .strengths = axg_stepinfo_strengths, + .nstrengths = ARRAY_SIZE(axg_stepinfo_strengths) +}; + +static const struct nand_ecc_step_info axg_stepinfo[] = { axg_stepinfo_1024, axg_stepinfo_512 }; + +static const struct nand_ecc_caps meson_axg_ecc_caps = { + .stepinfos = axg_stepinfo, + .nstepinfos = ARRAY_SIZE(axg_stepinfo), + .calc_ecc_bytes = meson_nand_calc_ecc_bytes, +}; + +/* + * OOB layout: + * + * For ECC with 512 bytes step size: + * 0x00: AA AA BB BB BB BB BB BB BB BB BB BB BB BB BB BB + * 0x10: AA AA CC CC CC CC CC CC CC CC CC CC CC CC CC CC + * 0x20: + * 0x30: + * + * For ECC with 1024 bytes step size: + * 0x00: AA AA BB BB BB BB BB BB BB BB BB BB BB BB BB BB + * 0x10: AA AA CC CC CC CC CC CC CC CC CC CC CC CC CC CC + * 0x20: AA AA DD DD DD DD DD DD DD DD DD DD DD DD DD DD + * 0x30: AA AA EE EE EE EE EE EE EE EE EE EE EE EE EE EE + * + * AA - user bytes. + * BB, CC, DD, EE - ECC code bytes for each step. + */ +static struct nand_ecclayout nand_oob; + +static void meson_nfc_init_nand_oob(struct nand_chip *nand) +{ + int section_size = 2 + nand->ecc.bytes; + int i; + int k; + + nand_oob.eccbytes = nand->ecc.steps * nand->ecc.bytes; + k = 0; + + for (i = 0; i < nand->ecc.steps; i++) { + int j; + + for (j = 0; j < nand->ecc.bytes; j++) + nand_oob.eccpos[k++] = (i * section_size) + 2 + j; + + nand_oob.oobfree[i].offset = (i * section_size); + nand_oob.oobfree[i].length = 2; + } + + nand_oob.oobavail = 2 * nand->ecc.steps; + nand->ecc.layout = &nand_oob; +} + +static int meson_nfc_init_ecc(struct nand_chip *nand, ofnode node) +{ + const struct mtd_info *mtd = nand_to_mtd(nand); + int ret; + int i; + + ret = nand_check_ecc_caps(nand, &meson_axg_ecc_caps, mtd->oobsize - 2); + if (ret) + return ret; + + for (i = 0; i < ARRAY_SIZE(meson_ecc); i++) { + if (meson_ecc[i].strength == nand->ecc.strength && + meson_ecc[i].size == nand->ecc.size) { + struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); + + nand->ecc.steps = mtd->writesize / nand->ecc.size; + meson_chip->bch_mode = meson_ecc[i].bch; + + meson_nfc_init_nand_oob(nand); + + return 0; + } + } + + return -EINVAL; +} + +static int meson_nfc_nand_chip_init(struct udevice *dev, struct meson_nfc *nfc, + ofnode node) +{ + struct meson_nfc_nand_chip *meson_chip; + struct nand_chip *nand; + struct mtd_info *mtd; + u32 cs[MAX_CE_NUM]; + u32 nsels; + int ret; + int i; + + if (!ofnode_get_property(node, "reg", &nsels)) { + dev_err(dev, "\"reg\" property is not found\n"); + return -ENODEV; + } + + nsels /= sizeof(u32); + if (nsels >= MAX_CE_NUM) { + dev_err(dev, "invalid size of CS array, max is %d\n", + MAX_CE_NUM); + return -EINVAL; + } + + ret = ofnode_read_u32_array(node, "reg", cs, nsels); + if (ret < 0) { + dev_err(dev, "failed to read \"reg\" property\n"); + return ret; + } + + for (i = 0; i < nsels; i++) { + if (test_and_set_bit(cs[i], &nfc->assigned_cs)) { + dev_err(dev, "CS %d already assigned\n", cs[i]); + return -EINVAL; + } + } + + meson_chip = malloc(sizeof(*meson_chip) + nsels * sizeof(meson_chip->sels[0])); + if (!meson_chip) { + dev_err(dev, "failed to allocate memory for chip\n"); + return -ENOMEM; + } + + meson_chip->nsels = nsels; + nand = &meson_chip->nand; + + nand->flash_node = node; + nand_set_controller_data(nand, nfc); + /* Set the driver entry points for MTD */ + nand->cmdfunc = meson_nfc_nand_cmd_function; + nand->cmd_ctrl = meson_nfc_cmd_ctrl; + nand->select_chip = meson_nfc_nand_select_chip; + nand->read_byte = meson_nfc_nand_read_byte; + nand->write_byte = meson_nfc_nand_write_byte; + nand->dev_ready = meson_nfc_dev_ready; + + /* Buffer read/write routines */ + nand->read_buf = meson_nfc_read_buf; + nand->write_buf = meson_nfc_write_buf; + nand->options |= NAND_NO_SUBPAGE_WRITE; + + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.hwctl = NULL; + nand->ecc.read_page = meson_nfc_read_page_hwecc; + nand->ecc.write_page = meson_nfc_write_page_hwecc; + nand->ecc.read_page_raw = meson_nfc_read_page_raw; + nand->ecc.write_page_raw = meson_nfc_write_page_raw; + + nand->ecc.read_oob = meson_nfc_read_oob; + nand->ecc.write_oob = meson_nfc_write_oob; + nand->ecc.read_oob_raw = meson_nfc_read_oob_raw; + nand->ecc.write_oob_raw = meson_nfc_write_oob_raw; + + nand->ecc.algo = NAND_ECC_BCH; + + mtd = nand_to_mtd(nand); + + ret = nand_scan_ident(mtd, 1, NULL); + if (ret) { + dev_err(dev, "'nand_scan_ident()' failed: %d\n", ret); + goto err_chip_free; + } + + ret = meson_nfc_init_ecc(nand, node); + if (ret) { + dev_err(dev, "failed to init ECC settings: %d\n", ret); + goto err_chip_free; + } + + ret = meson_chip_buffer_init(nand); + if (ret) { + dev_err(dev, "failed to init DMA buffers: %d\n", ret); + goto err_chip_free; + } + + /* 'nand_scan_tail()' needs ECC parameters to be already + * set and correct. + */ + ret = nand_scan_tail(mtd); + if (ret) { + dev_err(dev, "'nand_scan_tail()' failed: %d\n", ret); + goto err_chip_buf_free; + } + + ret = nand_register(0, mtd); + if (ret) { + dev_err(dev, "'nand_register()' failed: %d\n", ret); + goto err_chip_buf_free; + } + + list_add_tail(&meson_chip->node, &nfc->chips); + + return 0; + +err_chip_buf_free: + dma_free_coherent(meson_chip->info_buf); + dma_free_coherent(meson_chip->data_buf); + +err_chip_free: + free(meson_chip); + + return ret; +} + +static int meson_nfc_nand_chips_init(struct udevice *dev, + struct meson_nfc *nfc) +{ + ofnode parent = dev_ofnode(dev); + ofnode node; + + ofnode_for_each_subnode(node, parent) { + int ret = meson_nfc_nand_chip_init(dev, nfc, node); + + if (ret) + return ret; + } + + return 0; +} + +static void meson_nfc_clk_init(struct meson_nfc *nfc) +{ + u32 bus_cycle = NFC_DEFAULT_BUS_CYCLE; + u32 bus_timing = NFC_DEFAULT_BUS_TIMING; + u32 bus_cfg_val; + + writel(CLK_ALWAYS_ON_NAND | CLK_SELECT_NAND | CLK_ENABLE_VALUE, nfc->reg_clk); + writel(0, nfc->reg_base + NFC_REG_CFG); + + bus_cfg_val = (((bus_cycle - 1) & 31) | ((bus_timing & 31) << 5)); + writel(bus_cfg_val, nfc->reg_base + NFC_REG_CFG); + writel(BIT(31), nfc->reg_base + NFC_REG_CMD); +} + +static int meson_probe(struct udevice *dev) +{ + struct meson_nfc *nfc = dev_get_priv(dev); + void *addr; + int ret; + + addr = dev_read_addr_ptr(dev); + if (!addr) { + dev_err(dev, "base register address not found\n"); + return -EINVAL; + } + + nfc->reg_base = addr; + + addr = dev_read_addr_index_ptr(dev, 1); + if (!addr) { + dev_err(dev, "clk register address not found\n"); + return -EINVAL; + } + + nfc->reg_clk = addr; + nfc->dev = dev; + + meson_nfc_clk_init(nfc); + + ret = meson_nfc_nand_chips_init(dev, nfc); + if (ret) { + dev_err(nfc->dev, "failed to init chips\n"); + return ret; + } + + return 0; +} + +static const struct udevice_id meson_nand_dt_ids[] = { + {.compatible = "amlogic,meson-axg-nfc",}, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(meson_nand) = { + .name = "meson_nand", + .id = UCLASS_MTD, + .of_match = meson_nand_dt_ids, + .probe = meson_probe, + .priv_auto = sizeof(struct meson_nfc), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_MTD, + DM_DRIVER_GET(meson_nand), &dev); + + if (ret && ret != -ENODEV) + pr_err("Failed to initialize: %d\n", ret); +} diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index c40a0f23d7b..688d17ba3c2 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4118,7 +4118,7 @@ static int nand_get_bits_per_cell(u8 cellinfo) */ void nand_decode_ext_id(struct nand_chip *chip) { - struct mtd_info *mtd = &chip->mtd; + struct mtd_info *mtd = nand_to_mtd(chip); int extid; /* The 3rd id byte holds MLC / multichip data */ chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]); @@ -4185,7 +4185,7 @@ static int nand_manufacturer_init(struct nand_chip *chip) */ static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type) { - struct mtd_info *mtd = &chip->mtd; + struct mtd_info *mtd = nand_to_mtd(chip); mtd->erasesize = type->erasesize; mtd->writesize = type->pagesize; @@ -4265,7 +4265,7 @@ static const struct nand_manufacturer *nand_get_manufacturer_desc(u8 id) int nand_detect(struct nand_chip *chip, int *maf_id, int *dev_id, struct nand_flash_dev *type) { - struct mtd_info *mtd = &chip->mtd; + struct mtd_info *mtd = nand_to_mtd(chip); const struct nand_manufacturer *manufacturer_desc; int busw, ret; u8 *id_data = chip->id.data; diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile index f172f4787f8..65b836b34ca 100644 --- a/drivers/mtd/nand/spi/Makefile +++ b/drivers/mtd/nand/spi/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o -spinand-objs += toshiba.o winbond.o +spinand-objs += toshiba.o winbond.o xtx.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 8ca33459f96..62c28aa422d 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -829,6 +829,7 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = { &toshiba_spinand_manufacturer, &winbond_spinand_manufacturer, &esmt_c8_spinand_manufacturer, + &xtx_spinand_manufacturer, }; static int spinand_manufacturer_match(struct spinand_device *spinand, diff --git a/drivers/mtd/nand/spi/xtx.c b/drivers/mtd/nand/spi/xtx.c new file mode 100644 index 00000000000..aee1849a71f --- /dev/null +++ b/drivers/mtd/nand/spi/xtx.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Author: + * Felix Matouschek <felix@matouschek.org> + */ + +#include <linux/bitfield.h> +#ifndef __UBOOT__ +#include <linux/device.h> +#include <linux/kernel.h> +#endif +#include <linux/mtd/spinand.h> + +#define SPINAND_MFR_XTX 0x0B + +#define XT26G0XA_STATUS_ECC_MASK GENMASK(5, 2) +#define XT26G0XA_STATUS_ECC_NO_DETECTED (0 << 2) +#define XT26G0XA_STATUS_ECC_8_CORRECTED (3 << 4) +#define XT26G0XA_STATUS_ECC_UNCOR_ERROR (2 << 4) + +#define XT26XXXD_STATUS_ECC3_ECC2_MASK GENMASK(7, 6) +#define XT26XXXD_STATUS_ECC_NO_DETECTED (0) +#define XT26XXXD_STATUS_ECC_1_7_CORRECTED (1) +#define XT26XXXD_STATUS_ECC_8_CORRECTED (3) +#define XT26XXXD_STATUS_ECC_UNCOR_ERROR (2) + +static SPINAND_OP_VARIANTS(read_cache_variants, + SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + +static SPINAND_OP_VARIANTS(write_cache_variants, + SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), + SPINAND_PROG_LOAD(true, 0, NULL, 0)); + +static SPINAND_OP_VARIANTS(update_cache_variants, + SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), + SPINAND_PROG_LOAD(false, 0, NULL, 0)); + +static int xt26g0xa_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + region->offset = 48; + region->length = 16; + + return 0; +} + +static int xt26g0xa_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + region->offset = 1; + region->length = 47; + + return 0; +} + +static const struct mtd_ooblayout_ops xt26g0xa_ooblayout = { + .ecc = xt26g0xa_ooblayout_ecc, + .rfree = xt26g0xa_ooblayout_free, +}; + +static int xt26g0xa_ecc_get_status(struct spinand_device *spinand, + u8 status) +{ + status = status & XT26G0XA_STATUS_ECC_MASK; + + switch (status) { + case XT26G0XA_STATUS_ECC_NO_DETECTED: + return 0; + case XT26G0XA_STATUS_ECC_8_CORRECTED: + return 8; + case XT26G0XA_STATUS_ECC_UNCOR_ERROR: + return -EBADMSG; + default: + break; + } + + /* At this point values greater than (2 << 4) are invalid */ + if (status > XT26G0XA_STATUS_ECC_UNCOR_ERROR) + return -EINVAL; + + /* (1 << 2) through (7 << 2) are 1-7 corrected errors */ + return status >> 2; +} + +static int xt26xxxd_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + region->offset = mtd->oobsize / 2; + region->length = mtd->oobsize / 2; + + return 0; +} + +static int xt26xxxd_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + if (section) + return -ERANGE; + + region->offset = 2; + region->length = mtd->oobsize / 2 - 2; + + return 0; +} + +static const struct mtd_ooblayout_ops xt26xxxd_ooblayout = { + .ecc = xt26xxxd_ooblayout_ecc, + .rfree = xt26xxxd_ooblayout_free, +}; + +static int xt26xxxd_ecc_get_status(struct spinand_device *spinand, + u8 status) +{ + switch (FIELD_GET(STATUS_ECC_MASK, status)) { + case XT26XXXD_STATUS_ECC_NO_DETECTED: + return 0; + case XT26XXXD_STATUS_ECC_UNCOR_ERROR: + return -EBADMSG; + case XT26XXXD_STATUS_ECC_1_7_CORRECTED: + return 4 + FIELD_GET(XT26XXXD_STATUS_ECC3_ECC2_MASK, status); + case XT26XXXD_STATUS_ECC_8_CORRECTED: + return 8; + default: + break; + } + + return -EINVAL; +} + +static const struct spinand_info xtx_spinand_table[] = { + SPINAND_INFO("XT26G01A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE1), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g0xa_ooblayout, + xt26g0xa_ecc_get_status)), + SPINAND_INFO("XT26G02A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE2), + NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g0xa_ooblayout, + xt26g0xa_ecc_get_status)), + SPINAND_INFO("XT26G04A", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0xE3), + NAND_MEMORG(1, 2048, 64, 128, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + SPINAND_HAS_QE_BIT, + SPINAND_ECCINFO(&xt26g0xa_ooblayout, + xt26g0xa_ecc_get_status)), + SPINAND_INFO("XT26G01D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x31), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&xt26xxxd_ooblayout, + xt26xxxd_ecc_get_status)), + SPINAND_INFO("XT26G11D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x34), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&xt26xxxd_ooblayout, + xt26xxxd_ecc_get_status)), + SPINAND_INFO("XT26Q01D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51), + NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&xt26xxxd_ooblayout, + xt26xxxd_ecc_get_status)), + SPINAND_INFO("XT26G02D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x32), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&xt26xxxd_ooblayout, + xt26xxxd_ecc_get_status)), + SPINAND_INFO("XT26G12D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x35), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&xt26xxxd_ooblayout, + xt26xxxd_ecc_get_status)), + SPINAND_INFO("XT26Q02D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x52), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&xt26xxxd_ooblayout, + xt26xxxd_ecc_get_status)), + SPINAND_INFO("XT26G04D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x33), + NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&xt26xxxd_ooblayout, + xt26xxxd_ecc_get_status)), + SPINAND_INFO("XT26Q04D", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x53), + NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&xt26xxxd_ooblayout, + xt26xxxd_ecc_get_status)), +}; + +static const struct spinand_manufacturer_ops xtx_spinand_manuf_ops = { +}; + +const struct spinand_manufacturer xtx_spinand_manufacturer = { + .id = SPINAND_MFR_XTX, + .name = "XTX", + .chips = xtx_spinand_table, + .nchips = ARRAY_SIZE(xtx_spinand_table), + .ops = &xtx_spinand_manuf_ops, +}; diff --git a/drivers/net/designware.c b/drivers/net/designware.c index c222197b114..4c1642b29a8 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -352,6 +352,11 @@ static int dw_adjust_link(struct dw_eth_dev *priv, struct eth_mac_regs *mac_p, (phydev->duplex) ? "full" : "half", (phydev->port == PORT_FIBRE) ? ", fiber mode" : ""); +#ifdef CONFIG_ARCH_NPCM8XX + /* Pass all Multicast Frames */ + setbits_le32(&mac_p->framefilt, BIT(4)); + +#endif return 0; } @@ -554,6 +559,11 @@ static int _dw_free_pkt(struct dw_eth_dev *priv) ulong desc_start = (ulong)desc_p; ulong desc_end = desc_start + roundup(sizeof(*desc_p), ARCH_DMA_MINALIGN); + ulong data_start = desc_p->dmamac_addr; + ulong data_end = data_start + roundup(CFG_ETH_BUFSIZE, ARCH_DMA_MINALIGN); + + /* Invalidate the descriptor buffer data */ + invalidate_dcache_range(data_start, data_end); /* * Make the current descriptor valid again and go to diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 9b3bce1dc87..67d80d987ff 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -159,7 +159,7 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, ret = eqos_mdio_wait_idle(eqos); if (ret) { - pr_err("MDIO not idle at entry"); + pr_err("MDIO not idle at entry\n"); return ret; } @@ -179,7 +179,7 @@ static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, ret = eqos_mdio_wait_idle(eqos); if (ret) { - pr_err("MDIO read didn't complete"); + pr_err("MDIO read didn't complete\n"); return ret; } @@ -203,7 +203,7 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, ret = eqos_mdio_wait_idle(eqos); if (ret) { - pr_err("MDIO not idle at entry"); + pr_err("MDIO not idle at entry\n"); return ret; } @@ -225,7 +225,7 @@ static int eqos_mdio_write(struct mii_dev *bus, int mdio_addr, int mdio_devad, ret = eqos_mdio_wait_idle(eqos); if (ret) { - pr_err("MDIO read didn't complete"); + pr_err("MDIO read didn't complete\n"); return ret; } @@ -242,37 +242,37 @@ static int eqos_start_clks_tegra186(struct udevice *dev) ret = clk_enable(&eqos->clk_slave_bus); if (ret < 0) { - pr_err("clk_enable(clk_slave_bus) failed: %d", ret); + pr_err("clk_enable(clk_slave_bus) failed: %d\n", ret); goto err; } ret = clk_enable(&eqos->clk_master_bus); if (ret < 0) { - pr_err("clk_enable(clk_master_bus) failed: %d", ret); + pr_err("clk_enable(clk_master_bus) failed: %d\n", ret); goto err_disable_clk_slave_bus; } ret = clk_enable(&eqos->clk_rx); if (ret < 0) { - pr_err("clk_enable(clk_rx) failed: %d", ret); + pr_err("clk_enable(clk_rx) failed: %d\n", ret); goto err_disable_clk_master_bus; } ret = clk_enable(&eqos->clk_ptp_ref); if (ret < 0) { - pr_err("clk_enable(clk_ptp_ref) failed: %d", ret); + pr_err("clk_enable(clk_ptp_ref) failed: %d\n", ret); goto err_disable_clk_rx; } ret = clk_set_rate(&eqos->clk_ptp_ref, 125 * 1000 * 1000); if (ret < 0) { - pr_err("clk_set_rate(clk_ptp_ref) failed: %d", ret); + pr_err("clk_set_rate(clk_ptp_ref) failed: %d\n", ret); goto err_disable_clk_ptp_ref; } ret = clk_enable(&eqos->clk_tx); if (ret < 0) { - pr_err("clk_enable(clk_tx) failed: %d", ret); + pr_err("clk_enable(clk_tx) failed: %d\n", ret); goto err_disable_clk_ptp_ref; } #endif @@ -305,26 +305,26 @@ static int eqos_start_clks_stm32(struct udevice *dev) ret = clk_enable(&eqos->clk_master_bus); if (ret < 0) { - pr_err("clk_enable(clk_master_bus) failed: %d", ret); + pr_err("clk_enable(clk_master_bus) failed: %d\n", ret); goto err; } ret = clk_enable(&eqos->clk_rx); if (ret < 0) { - pr_err("clk_enable(clk_rx) failed: %d", ret); + pr_err("clk_enable(clk_rx) failed: %d\n", ret); goto err_disable_clk_master_bus; } ret = clk_enable(&eqos->clk_tx); if (ret < 0) { - pr_err("clk_enable(clk_tx) failed: %d", ret); + pr_err("clk_enable(clk_tx) failed: %d\n", ret); goto err_disable_clk_rx; } if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) { ret = clk_enable(&eqos->clk_ck); if (ret < 0) { - pr_err("clk_enable(clk_ck) failed: %d", ret); + pr_err("clk_enable(clk_ck) failed: %d\n", ret); goto err_disable_clk_tx; } eqos->clk_ck_enabled = true; @@ -390,7 +390,7 @@ static int eqos_start_resets_tegra186(struct udevice *dev) ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); if (ret < 0) { - pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", ret); + pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d\n", ret); return ret; } @@ -398,13 +398,13 @@ static int eqos_start_resets_tegra186(struct udevice *dev) ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); if (ret < 0) { - pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", ret); + pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d\n", ret); return ret; } ret = reset_assert(&eqos->reset_ctl); if (ret < 0) { - pr_err("reset_assert() failed: %d", ret); + pr_err("reset_assert() failed: %d\n", ret); return ret; } @@ -412,7 +412,7 @@ static int eqos_start_resets_tegra186(struct udevice *dev) ret = reset_deassert(&eqos->reset_ctl); if (ret < 0) { - pr_err("reset_deassert() failed: %d", ret); + pr_err("reset_deassert() failed: %d\n", ret); return ret; } @@ -448,14 +448,14 @@ static int eqos_calibrate_pads_tegra186(struct udevice *dev) ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false); if (ret) { - pr_err("calibrate didn't start"); + pr_err("calibrate didn't start\n"); goto failed; } ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false); if (ret) { - pr_err("calibrate didn't finish"); + pr_err("calibrate didn't finish\n"); goto failed; } @@ -586,13 +586,13 @@ static int eqos_set_tx_clk_speed_tegra186(struct udevice *dev) rate = 2.5 * 1000 * 1000; break; default: - pr_err("invalid speed %d", eqos->phy->speed); + pr_err("invalid speed %d\n", eqos->phy->speed); return -EINVAL; } ret = clk_set_rate(&eqos->clk_tx, rate); if (ret < 0) { - pr_err("clk_set_rate(tx_clk, %lu) failed: %d", rate, ret); + pr_err("clk_set_rate(tx_clk, %lu) failed: %d\n", rate, ret); return ret; } #endif @@ -613,7 +613,7 @@ static int eqos_adjust_link(struct udevice *dev) else ret = eqos_set_half_duplex(dev); if (ret < 0) { - pr_err("eqos_set_*_duplex() failed: %d", ret); + pr_err("eqos_set_*_duplex() failed: %d\n", ret); return ret; } @@ -631,32 +631,32 @@ static int eqos_adjust_link(struct udevice *dev) ret = eqos_set_mii_speed_10(dev); break; default: - pr_err("invalid speed %d", eqos->phy->speed); + pr_err("invalid speed %d\n", eqos->phy->speed); return -EINVAL; } if (ret < 0) { - pr_err("eqos_set_*mii_speed*() failed: %d", ret); + pr_err("eqos_set_*mii_speed*() failed: %d\n", ret); return ret; } if (en_calibration) { ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) { - pr_err("eqos_calibrate_pads() failed: %d", + pr_err("eqos_calibrate_pads() failed: %d\n", ret); return ret; } } else { ret = eqos->config->ops->eqos_disable_calibration(dev); if (ret < 0) { - pr_err("eqos_disable_calibration() failed: %d", + pr_err("eqos_disable_calibration() failed: %d\n", ret); return ret; } } ret = eqos->config->ops->eqos_set_tx_clk_speed(dev); if (ret < 0) { - pr_err("eqos_set_tx_clk_speed() failed: %d", ret); + pr_err("eqos_set_tx_clk_speed() failed: %d\n", ret); return ret; } @@ -755,7 +755,7 @@ static int eqos_start(struct udevice *dev) ret = eqos->config->ops->eqos_start_resets(dev); if (ret < 0) { - pr_err("eqos_start_resets() failed: %d", ret); + pr_err("eqos_start_resets() failed: %d\n", ret); goto err; } @@ -773,13 +773,13 @@ static int eqos_start(struct udevice *dev) EQOS_DMA_MODE_SWR, false, eqos->config->swr_wait, false); if (ret) { - pr_err("EQOS_DMA_MODE_SWR stuck"); + pr_err("EQOS_DMA_MODE_SWR stuck\n"); goto err_stop_resets; } ret = eqos->config->ops->eqos_calibrate_pads(dev); if (ret < 0) { - pr_err("eqos_calibrate_pads() failed: %d", ret); + pr_err("eqos_calibrate_pads() failed: %d\n", ret); goto err_stop_resets; } @@ -812,7 +812,7 @@ static int eqos_start(struct udevice *dev) } if (!eqos->phy) { - pr_err("phy_connect() failed"); + pr_err("phy_connect() failed\n"); ret = -ENODEV; goto err_stop_resets; } @@ -820,7 +820,7 @@ static int eqos_start(struct udevice *dev) if (eqos->max_speed) { ret = phy_set_supported(eqos->phy, eqos->max_speed); if (ret) { - pr_err("phy_set_supported() failed: %d", ret); + pr_err("phy_set_supported() failed: %d\n", ret); goto err_shutdown_phy; } } @@ -828,26 +828,26 @@ static int eqos_start(struct udevice *dev) eqos->phy->node = eqos->phy_of_node; ret = phy_config(eqos->phy); if (ret < 0) { - pr_err("phy_config() failed: %d", ret); + pr_err("phy_config() failed: %d\n", ret); goto err_shutdown_phy; } } ret = phy_startup(eqos->phy); if (ret < 0) { - pr_err("phy_startup() failed: %d", ret); + pr_err("phy_startup() failed: %d\n", ret); goto err_shutdown_phy; } if (!eqos->phy->link) { - pr_err("No link"); + pr_err("No link\n"); ret = -EAGAIN; goto err_shutdown_phy; } ret = eqos_adjust_link(dev); if (ret < 0) { - pr_err("eqos_adjust_link() failed: %d", ret); + pr_err("eqos_adjust_link() failed: %d\n", ret); goto err_shutdown_phy; } @@ -1090,7 +1090,7 @@ err_shutdown_phy: err_stop_resets: eqos->config->ops->eqos_stop_resets(dev); err: - pr_err("FAILED: %d", ret); + pr_err("FAILED: %d\n", ret); return ret; } @@ -1217,7 +1217,7 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) struct eqos_priv *eqos = dev_get_priv(dev); u32 idx, idx_mask = eqos->desc_per_cacheline - 1; uchar *packet_expected; - struct eqos_desc *rx_desc; + struct eqos_desc *rx_desc = NULL; debug("%s(packet=%p, length=%d)\n", __func__, packet, length); @@ -1361,7 +1361,7 @@ static int eqos_probe_resources_tegra186(struct udevice *dev) ret = reset_get_by_name(dev, "eqos", &eqos->reset_ctl); if (ret) { - pr_err("reset_get_by_name(rst) failed: %d", ret); + pr_err("reset_get_by_name(rst) failed: %d\n", ret); return ret; } @@ -1369,37 +1369,37 @@ static int eqos_probe_resources_tegra186(struct udevice *dev) &eqos->phy_reset_gpio, GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); if (ret) { - pr_err("gpio_request_by_name(phy reset) failed: %d", ret); + pr_err("gpio_request_by_name(phy reset) failed: %d\n", ret); goto err_free_reset_eqos; } ret = clk_get_by_name(dev, "slave_bus", &eqos->clk_slave_bus); if (ret) { - pr_err("clk_get_by_name(slave_bus) failed: %d", ret); + pr_err("clk_get_by_name(slave_bus) failed: %d\n", ret); goto err_free_gpio_phy_reset; } ret = clk_get_by_name(dev, "master_bus", &eqos->clk_master_bus); if (ret) { - pr_err("clk_get_by_name(master_bus) failed: %d", ret); + pr_err("clk_get_by_name(master_bus) failed: %d\n", ret); goto err_free_gpio_phy_reset; } ret = clk_get_by_name(dev, "rx", &eqos->clk_rx); if (ret) { - pr_err("clk_get_by_name(rx) failed: %d", ret); + pr_err("clk_get_by_name(rx) failed: %d\n", ret); goto err_free_gpio_phy_reset; } ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref); if (ret) { - pr_err("clk_get_by_name(ptp_ref) failed: %d", ret); + pr_err("clk_get_by_name(ptp_ref) failed: %d\n", ret); goto err_free_gpio_phy_reset; } ret = clk_get_by_name(dev, "tx", &eqos->clk_tx); if (ret) { - pr_err("clk_get_by_name(tx) failed: %d", ret); + pr_err("clk_get_by_name(tx) failed: %d\n", ret); goto err_free_gpio_phy_reset; } @@ -1436,19 +1436,19 @@ static int eqos_probe_resources_stm32(struct udevice *dev) ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); if (ret) { - pr_err("clk_get_by_name(master_bus) failed: %d", ret); + pr_err("clk_get_by_name(master_bus) failed: %d\n", ret); goto err_probe; } ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx); if (ret) { - pr_err("clk_get_by_name(rx) failed: %d", ret); + pr_err("clk_get_by_name(rx) failed: %d\n", ret); goto err_probe; } ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx); if (ret) { - pr_err("clk_get_by_name(tx) failed: %d", ret); + pr_err("clk_get_by_name(tx) failed: %d\n", ret); goto err_probe; } @@ -1502,7 +1502,7 @@ static int eqos_probe(struct udevice *dev) eqos->regs = dev_read_addr(dev); if (eqos->regs == FDT_ADDR_T_NONE) { - pr_err("dev_read_addr() failed"); + pr_err("dev_read_addr() failed\n"); return -ENODEV; } eqos->mac_regs = (void *)(eqos->regs + EQOS_MAC_REGS_BASE); @@ -1514,19 +1514,19 @@ static int eqos_probe(struct udevice *dev) ret = eqos_probe_resources_core(dev); if (ret < 0) { - pr_err("eqos_probe_resources_core() failed: %d", ret); + pr_err("eqos_probe_resources_core() failed: %d\n", ret); return ret; } ret = eqos->config->ops->eqos_probe_resources(dev); if (ret < 0) { - pr_err("eqos_probe_resources() failed: %d", ret); + pr_err("eqos_probe_resources() failed: %d\n", ret); goto err_remove_resources_core; } ret = eqos->config->ops->eqos_start_clks(dev); if (ret < 0) { - pr_err("eqos_start_clks() failed: %d", ret); + pr_err("eqos_start_clks() failed: %d\n", ret); goto err_remove_resources_tegra; } @@ -1536,7 +1536,7 @@ static int eqos_probe(struct udevice *dev) if (!eqos->mii) { eqos->mii = mdio_alloc(); if (!eqos->mii) { - pr_err("mdio_alloc() failed"); + pr_err("mdio_alloc() failed\n"); ret = -ENOMEM; goto err_stop_clks; } @@ -1547,7 +1547,7 @@ static int eqos_probe(struct udevice *dev) ret = mdio_register(eqos->mii); if (ret < 0) { - pr_err("mdio_register() failed: %d", ret); + pr_err("mdio_register() failed: %d\n", ret); goto err_free_mdio; } } diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig index 72eccc99e5f..ddfa95a0b7e 100644 --- a/drivers/net/ti/Kconfig +++ b/drivers/net/ti/Kconfig @@ -57,3 +57,16 @@ config MDIO_TI_CPSW help This driver supports the TI CPSW MDIO interface found in various TI SoCs. + +config TI_ICSSG_PRUETH + bool "TI Gigabit PRU Ethernet driver" + depends on ARCH_K3 + imply DM_MDIO + imply MISC_INIT_R + imply MISC + imply MDIO_TI_CPSW + select PHYLIB + select FS_LOADER + help + Support Gigabit Ethernet ports over the ICSSG PRU Subsystem + This subsystem is available starting with the AM65 platform. diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile index 30c4c4b6d5a..b2b3aa3b180 100644 --- a/drivers/net/ti/Makefile +++ b/drivers/net/ti/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o cpsw_mdio.o obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o obj-$(CONFIG_MDIO_TI_CPSW) += cpsw_mdio.o +obj-$(CONFIG_TI_ICSSG_PRUETH) += icssg_prueth.o icssg_classifier.o icssg_config.o icssg_queues.o diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c index d68ed671836..b151e25d6a4 100644 --- a/drivers/net/ti/am65-cpsw-nuss.c +++ b/drivers/net/ti/am65-cpsw-nuss.c @@ -664,7 +664,7 @@ static int am65_cpsw_port_probe(struct udevice *dev) struct am65_cpsw_priv *priv = dev_get_priv(dev); struct eth_pdata *pdata = dev_get_plat(dev); struct am65_cpsw_common *cpsw_common; - char portname[15]; + char portname[32]; int ret; priv->dev = dev; @@ -672,7 +672,7 @@ static int am65_cpsw_port_probe(struct udevice *dev) cpsw_common = dev_get_priv(dev->parent); priv->cpsw_common = cpsw_common; - sprintf(portname, "%s%s", dev->parent->name, dev->name); + snprintf(portname, sizeof(portname), "%s%s", dev->parent->name, dev->name); device_set_name(dev, portname); ret = am65_cpsw_ofdata_parse_phy(dev); diff --git a/drivers/net/ti/icss_mii_rt.h b/drivers/net/ti/icss_mii_rt.h new file mode 100644 index 00000000000..fd95d4d7c1f --- /dev/null +++ b/drivers/net/ti/icss_mii_rt.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* PRU-ICSS MII_RT register definitions + * + * Copyright (C) 2015-2024 Texas Instruments Incorporated - https://www.ti.com + */ + +#ifndef __NET_PRUSS_MII_RT_H__ +#define __NET_PRUSS_MII_RT_H__ + +#include <regmap.h> + +/* PRUSS_MII_RT Registers */ +#define PRUSS_MII_RT_RXCFG0 0x0 +#define PRUSS_MII_RT_RXCFG1 0x4 +#define PRUSS_MII_RT_TXCFG0 0x10 +#define PRUSS_MII_RT_TXCFG1 0x14 +#define PRUSS_MII_RT_TX_CRC0 0x20 +#define PRUSS_MII_RT_TX_CRC1 0x24 +#define PRUSS_MII_RT_TX_IPG0 0x30 +#define PRUSS_MII_RT_TX_IPG1 0x34 +#define PRUSS_MII_RT_PRS0 0x38 +#define PRUSS_MII_RT_PRS1 0x3c +#define PRUSS_MII_RT_RX_FRMS0 0x40 +#define PRUSS_MII_RT_RX_FRMS1 0x44 +#define PRUSS_MII_RT_RX_PCNT0 0x48 +#define PRUSS_MII_RT_RX_PCNT1 0x4c +#define PRUSS_MII_RT_RX_ERR0 0x50 +#define PRUSS_MII_RT_RX_ERR1 0x54 + +/* PRUSS_MII_RT_RXCFG0/1 bits */ +#define PRUSS_MII_RT_RXCFG_RX_ENABLE BIT(0) +#define PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS BIT(1) +#define PRUSS_MII_RT_RXCFG_RX_CUT_PREAMBLE BIT(2) +#define PRUSS_MII_RT_RXCFG_RX_MUX_SEL BIT(3) +#define PRUSS_MII_RT_RXCFG_RX_L2_EN BIT(4) +#define PRUSS_MII_RT_RXCFG_RX_BYTE_SWAP BIT(5) +#define PRUSS_MII_RT_RXCFG_RX_AUTO_FWD_PRE BIT(6) +#define PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS BIT(9) + +/* PRUSS_MII_RT_TXCFG0/1 bits */ +#define PRUSS_MII_RT_TXCFG_TX_ENABLE BIT(0) +#define PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE BIT(1) +#define PRUSS_MII_RT_TXCFG_TX_EN_MODE BIT(2) +#define PRUSS_MII_RT_TXCFG_TX_BYTE_SWAP BIT(3) +#define PRUSS_MII_RT_TXCFG_TX_MUX_SEL BIT(8) +#define PRUSS_MII_RT_TXCFG_PRE_TX_AUTO_SEQUENCE BIT(9) +#define PRUSS_MII_RT_TXCFG_PRE_TX_AUTO_ESC_ERR BIT(10) +#define PRUSS_MII_RT_TXCFG_TX_32_MODE_EN BIT(11) +#define PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN BIT(12) /* SR2.0 onwards */ + +#define PRUSS_MII_RT_TXCFG_TX_START_DELAY_SHIFT 16 +#define PRUSS_MII_RT_TXCFG_TX_START_DELAY_MASK GENMASK(25, 16) + +#define PRUSS_MII_RT_TXCFG_TX_CLK_DELAY_SHIFT 28 +#define PRUSS_MII_RT_TXCFG_TX_CLK_DELAY_MASK GENMASK(30, 28) + +/* PRUSS_MII_RT_TX_IPG0/1 bits */ +#define PRUSS_MII_RT_TX_IPG_IPG_SHIFT 0 +#define PRUSS_MII_RT_TX_IPG_IPG_MASK GENMASK(9, 0) + +/* PRUSS_MII_RT_PRS0/1 bits */ +#define PRUSS_MII_RT_PRS_COL BIT(0) +#define PRUSS_MII_RT_PRS_CRS BIT(1) + +/* PRUSS_MII_RT_RX_FRMS0/1 bits */ +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM_SHIFT 0 +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM_MASK GENMASK(15, 0) + +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_SHIFT 16 +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_MASK GENMASK(31, 16) + +/* Min/Max in MII_RT_RX_FRMS */ +/* For EMAC and Switch */ +#define PRUSS_MII_RT_RX_FRMS_MAX (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN) +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM (64) + +/* for HSR and PRP */ +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_LRE (PRUSS_MII_RT_RX_FRMS_MAX + \ + ICSS_LRE_TAG_RCT_SIZE) +/* PRUSS_MII_RT_RX_PCNT0/1 bits */ +#define PRUSS_MII_RT_RX_PCNT_MIN_PCNT_SHIFT 0 +#define PRUSS_MII_RT_RX_PCNT_MIN_PCNT_MASK GENMASK(3, 0) + +#define PRUSS_MII_RT_RX_PCNT_MAX_PCNT_SHIFT 4 +#define PRUSS_MII_RT_RX_PCNT_MAX_PCNT_MASK GENMASK(7, 4) + +/* PRUSS_MII_RT_RX_ERR0/1 bits */ +#define PRUSS_MII_RT_RX_ERR_MIN_PCNT_ERR BIT(0) +#define PRUSS_MII_RT_RX_ERR_MAX_PCNT_ERR BIT(1) +#define PRUSS_MII_RT_RX_ERR_MIN_FRM_ERR BIT(2) +#define PRUSS_MII_RT_RX_ERR_MAX_FRM_ERR BIT(3) + +#define ICSSG_CFG_OFFSET 0 +#define RGMII_CFG_OFFSET 4 + +/* Constant to choose between MII0 and MII1 */ +#define ICSS_MII0 0 +#define ICSS_MII1 1 + +/* ICSSG_CFG Register bits */ +#define ICSSG_CFG_SGMII_MODE BIT(16) +#define ICSSG_CFG_TX_PRU_EN BIT(11) +#define ICSSG_CFG_RX_SFD_TX_SOF_EN BIT(10) +#define ICSSG_CFG_RTU_PRU_PSI_SHARE_EN BIT(9) +#define ICSSG_CFG_IEP1_TX_EN BIT(8) +#define ICSSG_CFG_MII1_MODE GENMASK(6, 5) +#define ICSSG_CFG_MII1_MODE_SHIFT 5 +#define ICSSG_CFG_MII0_MODE GENMASK(4, 3) +#define ICSSG_CFG_MII0_MODE_SHIFT 3 +#define ICSSG_CFG_RX_L2_G_EN BIT(2) +#define ICSSG_CFG_TX_L2_EN BIT(1) +#define ICSSG_CFG_TX_L1_EN BIT(0) + +enum mii_mode { MII_MODE_MII = 0, MII_MODE_RGMII, MII_MODE_SGMII }; + +/* RGMII CFG Register bits */ +#define RGMII_CFG_INBAND_EN_MII0 BIT(16) +#define RGMII_CFG_GIG_EN_MII0 BIT(17) +#define RGMII_CFG_INBAND_EN_MII1 BIT(20) +#define RGMII_CFG_GIG_EN_MII1 BIT(21) +#define RGMII_CFG_FULL_DUPLEX_MII0 BIT(18) +#define RGMII_CFG_FULL_DUPLEX_MII1 BIT(22) +#define RGMII_CFG_SPEED_MII0 GENMASK(2, 1) +#define RGMII_CFG_SPEED_MII1 GENMASK(6, 5) +#define RGMII_CFG_SPEED_MII0_SHIFT 1 +#define RGMII_CFG_SPEED_MII1_SHIFT 5 +#define RGMII_CFG_FULLDUPLEX_MII0 BIT(3) +#define RGMII_CFG_FULLDUPLEX_MII1 BIT(7) +#define RGMII_CFG_FULLDUPLEX_MII0_SHIFT 3 +#define RGMII_CFG_FULLDUPLEX_MII1_SHIFT 7 +#define RGMII_CFG_SPEED_10M 0 +#define RGMII_CFG_SPEED_100M 1 +#define RGMII_CFG_SPEED_1G 2 + +static inline void icssg_mii_update_ipg(struct regmap *mii_rt, int mii, u32 ipg) +{ + u32 val; + + if (mii == ICSS_MII0) { + regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG0, ipg); + } else { + /* Errata workaround: IEP1 is not read by h/w unless IEP0 is written */ + regmap_read(mii_rt, PRUSS_MII_RT_TX_IPG0, &val); + regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG1, ipg); + regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG0, val); + } +} + +static inline void icssg_update_rgmii_cfg(struct regmap *miig_rt, int speed, + bool full_duplex, int slice, struct prueth_priv *priv) +{ + u32 gig_en_mask, gig_val = 0, full_duplex_mask, full_duplex_val = 0; + u32 inband_en_mask, inband_val = 0; + + gig_en_mask = (slice == ICSS_MII0) ? RGMII_CFG_GIG_EN_MII0 : + RGMII_CFG_GIG_EN_MII1; + if (speed == SPEED_1000) + gig_val = gig_en_mask; + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, gig_val); + + inband_en_mask = (slice == ICSS_MII0) ? RGMII_CFG_INBAND_EN_MII0 : + RGMII_CFG_INBAND_EN_MII1; + if (speed == SPEED_10 && phy_interface_is_rgmii(priv->phydev)) + inband_val = inband_en_mask; + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, inband_en_mask, inband_val); + + full_duplex_mask = (slice == ICSS_MII0) ? RGMII_CFG_FULL_DUPLEX_MII0 : + RGMII_CFG_FULL_DUPLEX_MII1; + if (full_duplex) + full_duplex_val = full_duplex_mask; + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask, + full_duplex_val); +} + +static inline void icssg_miig_set_interface_mode(struct regmap *miig_rt, int mii, int phy_if) +{ + u32 val, mask, shift; + + mask = mii == ICSS_MII0 ? ICSSG_CFG_MII0_MODE : ICSSG_CFG_MII1_MODE; + shift = mii == ICSS_MII0 ? ICSSG_CFG_MII0_MODE_SHIFT : ICSSG_CFG_MII1_MODE_SHIFT; + + val = MII_MODE_RGMII; + if (phy_if == PHY_INTERFACE_MODE_MII) + val = MII_MODE_MII; + + val <<= shift; + regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, mask, val); + regmap_read(miig_rt, ICSSG_CFG_OFFSET, &val); +} + +#endif /* __NET_PRUSS_MII_RT_H__ */ diff --git a/drivers/net/ti/icssg_classifier.c b/drivers/net/ti/icssg_classifier.c new file mode 100644 index 00000000000..e510a1cd3e5 --- /dev/null +++ b/drivers/net/ti/icssg_classifier.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Texas Instruments ICSSG Ethernet Driver + * + * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#include <dm/ofnode.h> +#include <regmap.h> + +#define ICSSG_NUM_CLASSIFIERS 16 +#define ICSSG_NUM_FT1_SLOTS 8 +#define ICSSG_NUM_FT3_SLOTS 16 + +#define ICSSG_NUM_CLASSIFIERS_IN_USE 1 + +/* Filter 1 - FT1 */ +#define FT1_NUM_SLOTS 8 +#define FT1_SLOT_SIZE 0x10 /* bytes */ + +/* offsets from FT1 slot base i.e. slot 1 start */ +#define FT1_DA0 0x0 +#define FT1_DA1 0x4 +#define FT1_DA0_MASK 0x8 +#define FT1_DA1_MASK 0xc + +#define FT1_N_REG(slize, n, reg) (offs[slice].ft1_slot_base + FT1_SLOT_SIZE * (n) + (reg)) + +#define FT1_LEN_MASK GENMASK(19, 16) +#define FT1_LEN_SHIFT 16 +#define FT1_LEN(len) (((len) << FT1_LEN_SHIFT) & FT1_LEN_MASK) + +#define FT1_START_MASK GENMASK(14, 0) +#define FT1_START(start) ((start) & FT1_START_MASK) + +#define FT1_MATCH_SLOT(n) (GENMASK(23, 16) & (BIT(n) << 16)) + +enum ft1_cfg_type { + FT1_CFG_TYPE_DISABLED = 0, + FT1_CFG_TYPE_EQ, + FT1_CFG_TYPE_GT, + FT1_CFG_TYPE_LT, +}; + +#define FT1_CFG_SHIFT(n) (2 * (n)) +#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n))) + +/* Filter 3 - FT3 */ +#define FT3_NUM_SLOTS 16 +#define FT3_SLOT_SIZE 0x20 /* bytes */ + +/* offsets from FT3 slot n's base */ +#define FT3_START 0 +#define FT3_START_AUTO 0x4 +#define FT3_START_OFFSET 0x8 +#define FT3_JUMP_OFFSET 0xc +#define FT3_LEN 0x10 +#define FT3_CFG 0x14 +#define FT3_T 0x18 +#define FT3_T_MASK 0x1c + +#define FT3_N_REG(slize, n, reg) \ + (offs[slice].ft3_slot_base + FT3_SLOT_SIZE * (n) + (reg)) + +/* offsets from rx_class n's base */ +#define RX_CLASS_AND_EN 0 +#define RX_CLASS_OR_EN 0x4 + +#define RX_CLASS_NUM_SLOTS 16 +#define RX_CLASS_EN_SIZE 0x8 /* bytes */ + +#define RX_CLASS_N_REG(slice, n, reg) \ + (offs[slice].rx_class_base + RX_CLASS_EN_SIZE * (n) + (reg)) + +/* RX Class Gates */ +#define RX_CLASS_GATES_SIZE 0x4 /* bytes */ + +#define RX_CLASS_GATES_N_REG(slice, n) \ + (offs[slice].rx_class_gates_base + RX_CLASS_GATES_SIZE * (n)) + +#define RX_CLASS_GATES_ALLOW_MASK BIT(6) +#define RX_CLASS_GATES_RAW_MASK BIT(5) +#define RX_CLASS_GATES_PHASE_MASK BIT(4) + +/* RX Class traffic data matching bits */ +#define RX_CLASS_FT_UC BIT(31) +#define RX_CLASS_FT_MC BIT(30) +#define RX_CLASS_FT_BC BIT(29) +#define RX_CLASS_FT_FW BIT(28) +#define RX_CLASS_FT_RCV BIT(27) +#define RX_CLASS_FT_VLAN BIT(26) +#define RX_CLASS_FT_DA_P BIT(25) +#define RX_CLASS_FT_DA_I BIT(24) +#define RX_CLASS_FT_FT1_MATCH_MASK GENMASK(23, 16) +#define RX_CLASS_FT_FT1_MATCH_SHIFT 16 +#define RX_CLASS_FT_FT3_MATCH_MASK GENMASK(15, 0) +#define RX_CLASS_FT_FT3_MATCH_SHIFT 0 + +#define RX_CLASS_FT_FT1_MATCH(slot) \ + ((BIT(slot) << RX_CLASS_FT_FT1_MATCH_SHIFT) & \ + RX_CLASS_FT_FT1_MATCH_MASK) + +enum rx_class_sel_type { + RX_CLASS_SEL_TYPE_OR = 0, + RX_CLASS_SEL_TYPE_AND = 1, + RX_CLASS_SEL_TYPE_OR_AND_AND = 2, + RX_CLASS_SEL_TYPE_OR_OR_AND = 3, +}; + +#define FT1_CFG_SHIFT(n) (2 * (n)) +#define FT1_CFG_MASK(n) (0x3 << FT1_CFG_SHIFT((n))) + +#define RX_CLASS_SEL_SHIFT(n) (2 * (n)) +#define RX_CLASS_SEL_MASK(n) (0x3 << RX_CLASS_SEL_SHIFT((n))) + +#define ICSSG_CFG_OFFSET 0 +#define MAC_INTERFACE_0 0x18 +#define MAC_INTERFACE_1 0x1c + +#define ICSSG_CFG_RX_L2_G_EN BIT(2) + +/* these are register offsets per PRU */ +struct miig_rt_offsets { + u32 mac0; + u32 mac1; + u32 ft1_start_len; + u32 ft1_cfg; + u32 ft1_slot_base; + u32 ft3_slot_base; + u32 ft3_p_base; + u32 ft_rx_ptr; + u32 rx_class_base; + u32 rx_class_cfg1; + u32 rx_class_cfg2; + u32 rx_class_gates_base; + u32 rx_green; + u32 rx_rate_cfg_base; + u32 rx_rate_src_sel0; + u32 rx_rate_src_sel1; + u32 tx_rate_cfg_base; + u32 stat_base; + u32 tx_hsr_tag; + u32 tx_hsr_seq; + u32 tx_vlan_type; + u32 tx_vlan_ins; +}; + +static struct miig_rt_offsets offs[] = { + /* PRU0 */ + { + 0x8, + 0xc, + 0x80, + 0x84, + 0x88, + 0x108, + 0x308, + 0x408, + 0x40c, + 0x48c, + 0x490, + 0x494, + 0x4d4, + 0x4e4, + 0x504, + 0x508, + 0x50c, + 0x54c, + 0x63c, + 0x640, + 0x644, + 0x648, + }, + /* PRU1 */ + { + 0x10, + 0x14, + 0x64c, + 0x650, + 0x654, + 0x6d4, + 0x8d4, + 0x9d4, + 0x9d8, + 0xa58, + 0xa5c, + 0xa60, + 0xaa0, + 0xab0, + 0xad0, + 0xad4, + 0xad8, + 0xb18, + 0xc08, + 0xc0c, + 0xc10, + 0xc14, + }, +}; + +static inline u32 addr_to_da0(const u8 *addr) +{ + return (u32)(addr[0] | addr[1] << 8 | + addr[2] << 16 | addr[3] << 24); +}; + +static inline u32 addr_to_da1(const u8 *addr) +{ + return (u32)(addr[4] | addr[5] << 8); +}; + +static void rx_class_ft1_set_start_len(struct regmap *miig_rt, int slice, + u16 start, u8 len) +{ + u32 offset, val; + + offset = offs[slice].ft1_start_len; + val = FT1_LEN(len) | FT1_START(start); + regmap_write(miig_rt, offset, val); +} + +static void rx_class_ft1_set_da(struct regmap *miig_rt, int slice, + int n, const u8 *addr) +{ + u32 offset; + + offset = FT1_N_REG(slice, n, FT1_DA0); + regmap_write(miig_rt, offset, addr_to_da0(addr)); + offset = FT1_N_REG(slice, n, FT1_DA1); + regmap_write(miig_rt, offset, addr_to_da1(addr)); +} + +static void rx_class_ft1_set_da_mask(struct regmap *miig_rt, int slice, + int n, const u8 *addr) +{ + u32 offset; + + offset = FT1_N_REG(slice, n, FT1_DA0_MASK); + regmap_write(miig_rt, offset, addr_to_da0(addr)); + offset = FT1_N_REG(slice, n, FT1_DA1_MASK); + regmap_write(miig_rt, offset, addr_to_da1(addr)); +} + +static void rx_class_ft1_cfg_set_type(struct regmap *miig_rt, int slice, int n, + enum ft1_cfg_type type) +{ + u32 offset; + + offset = offs[slice].ft1_cfg; + regmap_update_bits(miig_rt, offset, FT1_CFG_MASK(n), + type << FT1_CFG_SHIFT(n)); +} + +static void rx_class_sel_set_type(struct regmap *miig_rt, int slice, int n, + enum rx_class_sel_type type) +{ + u32 offset; + + offset = offs[slice].rx_class_cfg1; + regmap_update_bits(miig_rt, offset, RX_CLASS_SEL_MASK(n), + type << RX_CLASS_SEL_SHIFT(n)); +} + +static void rx_class_set_and(struct regmap *miig_rt, int slice, int n, + u32 data) +{ + u32 offset; + + offset = RX_CLASS_N_REG(slice, n, RX_CLASS_AND_EN); + regmap_write(miig_rt, offset, data); +} + +static void rx_class_set_or(struct regmap *miig_rt, int slice, int n, + u32 data) +{ + u32 offset; + + offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN); + regmap_write(miig_rt, offset, data); +} + +void icssg_class_set_host_mac_addr(struct regmap *miig_rt, u8 *mac) +{ + regmap_write(miig_rt, MAC_INTERFACE_0, addr_to_da0(mac)); + regmap_write(miig_rt, MAC_INTERFACE_1, addr_to_da1(mac)); +} + +void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac) +{ + regmap_write(miig_rt, offs[slice].mac0, addr_to_da0(mac)); + regmap_write(miig_rt, offs[slice].mac1, addr_to_da1(mac)); +} + +void icssg_class_disable_n(struct regmap *miig_rt, int slice, int n) +{ + u32 data, offset; + + /* AND_EN = 0 */ + rx_class_set_and(miig_rt, slice, n, 0); + /* OR_EN = 0 */ + rx_class_set_or(miig_rt, slice, n, 0); + + /* set CFG1 to OR */ + rx_class_sel_set_type(miig_rt, slice, n, RX_CLASS_SEL_TYPE_OR); + + /* configure gate */ + offset = RX_CLASS_GATES_N_REG(slice, n); + regmap_read(miig_rt, offset, &data); + /* clear class_raw so we go through filters */ + data &= ~RX_CLASS_GATES_RAW_MASK; + /* set allow and phase mask */ + data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK; + regmap_write(miig_rt, offset, data); +} + +/* disable all RX traffic */ +void icssg_class_disable(struct regmap *miig_rt, int slice) +{ + int n; + + /* Enable RX_L2_G */ + regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_RX_L2_G_EN, + ICSSG_CFG_RX_L2_G_EN); + + for (n = 0; n < ICSSG_NUM_CLASSIFIERS; n++) + icssg_class_disable_n(miig_rt, slice, n); + + /* FT1 Disabled */ + for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) { + u8 addr[] = { 0, 0, 0, 0, 0, 0, }; + + rx_class_ft1_cfg_set_type(miig_rt, slice, n, + FT1_CFG_TYPE_DISABLED); + rx_class_ft1_set_da(miig_rt, slice, n, addr); + rx_class_ft1_set_da_mask(miig_rt, slice, n, addr); + } + + /* clear CFG2 */ + regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0); +} + +void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti) +{ + u32 data; + + /* defaults */ + icssg_class_disable(miig_rt, slice); + + /* Setup Classifier */ + /* match on Broadcast or MAC_PRU address */ + data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P; + + /* multicast? */ + if (allmulti) + data |= RX_CLASS_FT_MC; + + rx_class_set_or(miig_rt, slice, 0, data); + + /* set CFG1 for OR_OR_AND for classifier */ + rx_class_sel_set_type(miig_rt, slice, 0, + RX_CLASS_SEL_TYPE_OR_OR_AND); + + /* clear CFG2 */ + regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0); +} + +/* required for SR2 for SAV check */ +void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr) +{ + u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, }; + + rx_class_ft1_set_start_len(miig_rt, slice, 6, 6); + rx_class_ft1_set_da(miig_rt, slice, 0, mac_addr); + rx_class_ft1_set_da_mask(miig_rt, slice, 0, mask_addr); + rx_class_ft1_cfg_set_type(miig_rt, slice, 0, FT1_CFG_TYPE_EQ); +} diff --git a/drivers/net/ti/icssg_config.c b/drivers/net/ti/icssg_config.c new file mode 100644 index 00000000000..5f132d0525c --- /dev/null +++ b/drivers/net/ti/icssg_config.c @@ -0,0 +1,474 @@ +// SPDX-License-Identifier: GPL-2.0 +/* ICSSG Ethernet driver + * + * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com + */ + +#include <phy.h> +#include "icssg_prueth.h" +#include "icssg_switch_map.h" +#include "icss_mii_rt.h" +#include <dm/device_compat.h> +#include <linux/iopoll.h> + +/* TX IPG Values to be set for 100M and 1G link speeds. These values are + * in ocp_clk cycles. So need change if ocp_clk is changed for a specific + * h/w design. + */ + +/* SR2.0 IPG is in rgmii_clk (125MHz) clock cycles + 1 */ +#define MII_RT_TX_IPG_100M 0x17 +#define MII_RT_TX_IPG_1G 0xb + +#define ICSSG_QUEUES_MAX 64 +#define ICSSG_QUEUE_OFFSET 0xd00 +#define ICSSG_QUEUE_PEEK_OFFSET 0xe00 +#define ICSSG_QUEUE_CNT_OFFSET 0xe40 +#define ICSSG_QUEUE_RESET_OFFSET 0xf40 + +#define ICSSG_NUM_TX_QUEUES 8 + +#define RECYCLE_Q_SLICE0 16 +#define RECYCLE_Q_SLICE1 17 + +#define ICSSG_NUM_OTHER_QUEUES 5 /* port, host and special queues */ + +#define PORT_HI_Q_SLICE0 32 +#define PORT_LO_Q_SLICE0 33 +#define HOST_HI_Q_SLICE0 34 +#define HOST_LO_Q_SLICE0 35 +#define HOST_SPL_Q_SLICE0 40 /* Special Queue */ + +#define PORT_HI_Q_SLICE1 36 +#define PORT_LO_Q_SLICE1 37 +#define HOST_HI_Q_SLICE1 38 +#define HOST_LO_Q_SLICE1 39 +#define HOST_SPL_Q_SLICE1 41 /* Special Queue */ + +#define MII_RXCFG_DEFAULT (PRUSS_MII_RT_RXCFG_RX_ENABLE | \ + PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS | \ + PRUSS_MII_RT_RXCFG_RX_L2_EN | \ + PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS) + +#define MII_TXCFG_DEFAULT (PRUSS_MII_RT_TXCFG_TX_ENABLE | \ + PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE | \ + PRUSS_MII_RT_TXCFG_TX_32_MODE_EN | \ + PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN) + +#define ICSSG_CFG_DEFAULT (ICSSG_CFG_TX_L1_EN | \ + ICSSG_CFG_TX_L2_EN | ICSSG_CFG_RX_L2_G_EN | \ + ICSSG_CFG_TX_PRU_EN | /* SR2.0 only */ \ + ICSSG_CFG_SGMII_MODE) + +#define FDB_GEN_CFG1 0x60 +#define SMEM_VLAN_OFFSET 8 +#define SMEM_VLAN_OFFSET_MASK GENMASK(25, 8) + +#define FDB_GEN_CFG2 0x64 +#define FDB_VLAN_EN BIT(6) +#define FDB_HOST_EN BIT(2) +#define FDB_PRU1_EN BIT(1) +#define FDB_PRU0_EN BIT(0) +#define FDB_EN_ALL (FDB_PRU0_EN | FDB_PRU1_EN | \ + FDB_HOST_EN | FDB_VLAN_EN) + +struct map { + int queue; + u32 pd_addr_start; + u32 flags; + bool special; +}; + +struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = { + { + { PORT_HI_Q_SLICE0, PORT_DESC0_HI, 0x200000, 0 }, + { PORT_LO_Q_SLICE0, PORT_DESC0_LO, 0, 0 }, + { HOST_HI_Q_SLICE0, HOST_DESC0_HI, 0x200000, 0 }, + { HOST_LO_Q_SLICE0, HOST_DESC0_LO, 0, 0 }, + { HOST_SPL_Q_SLICE0, HOST_SPPD0, 0x400000, 1 }, + }, + { + { PORT_HI_Q_SLICE1, PORT_DESC1_HI, 0xa00000, 0 }, + { PORT_LO_Q_SLICE1, PORT_DESC1_LO, 0x800000, 0 }, + { HOST_HI_Q_SLICE1, HOST_DESC1_HI, 0xa00000, 0 }, + { HOST_LO_Q_SLICE1, HOST_DESC1_LO, 0x800000, 0 }, + { HOST_SPL_Q_SLICE1, HOST_SPPD1, 0xc00000, 1 }, + }, +}; + +static void icssg_config_mii_init(struct prueth_priv *priv, int slice) +{ + struct prueth *prueth = priv->prueth; + struct regmap *mii_rt = prueth->mii_rt; + u32 txcfg_reg, pcnt_reg; + u32 txcfg; + + txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 : + PRUSS_MII_RT_TXCFG1; + pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 : + PRUSS_MII_RT_RX_PCNT1; + + txcfg = MII_TXCFG_DEFAULT; + + if (prueth->phy_interface == PHY_INTERFACE_MODE_MII && slice == ICSS_MII0) + txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; + else if (prueth->phy_interface != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1) + txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL; + + regmap_write(mii_rt, txcfg_reg, txcfg); + regmap_write(mii_rt, pcnt_reg, 0x1); +} + +static void icssg_miig_queues_init(struct prueth_priv *priv, int slice) +{ + struct prueth *prueth = priv->prueth; + void __iomem *smem = (void __iomem *)prueth->shram.pa; + struct regmap *miig_rt = prueth->miig_rt; + int queue = 0, i, j; + u8 pd[ICSSG_SPECIAL_PD_SIZE]; + u32 *pdword; + + /* reset hwqueues */ + if (slice) + queue = ICSSG_NUM_TX_QUEUES; + + for (i = 0; i < ICSSG_NUM_TX_QUEUES; i++) { + regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); + queue++; + } + + queue = slice ? RECYCLE_Q_SLICE1 : RECYCLE_Q_SLICE0; + regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue); + + for (i = 0; i < ICSSG_NUM_OTHER_QUEUES; i++) { + regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, + hwq_map[slice][i].queue); + } + + /* initialize packet descriptors in SMEM */ + /* push pakcet descriptors to hwqueues */ + + pdword = (u32 *)pd; + for (j = 0; j < ICSSG_NUM_OTHER_QUEUES; j++) { + struct map *mp; + int pd_size, num_pds; + u32 pdaddr; + + mp = &hwq_map[slice][j]; + if (mp->special) { + pd_size = ICSSG_SPECIAL_PD_SIZE; + num_pds = ICSSG_NUM_SPECIAL_PDS; + } else { + pd_size = ICSSG_NORMAL_PD_SIZE; + num_pds = ICSSG_NUM_NORMAL_PDS; + } + + for (i = 0; i < num_pds; i++) { + memset(pd, 0, pd_size); + + pdword[0] &= cpu_to_le32(ICSSG_FLAG_MASK); + pdword[0] |= cpu_to_le32(mp->flags); + pdaddr = mp->pd_addr_start + i * pd_size; + + memcpy_toio(smem + pdaddr, pd, pd_size); + queue = mp->queue; + regmap_write(miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, + pdaddr); + } + } +} + +void icssg_config_ipg(struct prueth_priv *priv, int speed, int mii) +{ + struct prueth *prueth = priv->prueth; + + switch (speed) { + case SPEED_1000: + icssg_mii_update_ipg(prueth->mii_rt, mii, MII_RT_TX_IPG_1G); + break; + case SPEED_100: + icssg_mii_update_ipg(prueth->mii_rt, mii, MII_RT_TX_IPG_100M); + break; + default: + /* Other links speeds not supported */ + pr_err("Unsupported link speed\n"); + return; + } +} + +static void emac_r30_cmd_init(struct prueth_priv *priv) +{ + struct prueth *prueth = priv->prueth; + struct icssg_r30_cmd *p; + int i; + + p = (struct icssg_r30_cmd *)(prueth->dram[priv->port_id].pa + MGR_R30_CMD_OFFSET); + + for (i = 0; i < 4; i++) + writel(EMAC_NONE, &p->cmd[i]); +} + +static int emac_r30_is_done(struct prueth_priv *priv) +{ + struct prueth *prueth = priv->prueth; + const struct icssg_r30_cmd *p; + int i; + u32 cmd; + + p = (const struct icssg_r30_cmd *)(prueth->dram[priv->port_id].pa + MGR_R30_CMD_OFFSET); + + for (i = 0; i < 4; i++) { + cmd = readl(&p->cmd[i]); + if (cmd != EMAC_NONE) + return 0; + } + + return 1; +} + +static int prueth_emac_buffer_setup(struct prueth_priv *priv) +{ + struct prueth *prueth = priv->prueth; + struct icssg_buffer_pool_cfg *bpool_cfg; + struct icssg_rxq_ctx *rxq_ctx; + int slice = priv->port_id; + u32 addr; + int i; + + /* Layout to have 64KB aligned buffer pool + * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1| + */ + + addr = lower_32_bits(prueth->sram_pa); + if (slice) + addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; + + if (addr % SZ_64K) { + dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); + return -EINVAL; + } + + bpool_cfg = (struct icssg_buffer_pool_cfg *)(prueth->dram[priv->port_id].pa + BUFFER_POOL_0_ADDR_OFFSET); + /* workaround for f/w bug. bpool 0 needs to be initilalized */ + bpool_cfg[0].addr = cpu_to_le32(addr); + bpool_cfg[0].len = 0; + + for (i = PRUETH_EMAC_BUF_POOL_START; + i < (PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS); + i++) { + bpool_cfg[i].addr = cpu_to_le32(addr); + bpool_cfg[i].len = cpu_to_le32(PRUETH_EMAC_BUF_POOL_SIZE); + addr += PRUETH_EMAC_BUF_POOL_SIZE; + } + + if (!slice) + addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; + else + addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2; + + rxq_ctx = (struct icssg_rxq_ctx *)(prueth->dram[priv->port_id].pa + HOST_RX_Q_PRE_CONTEXT_OFFSET); + + for (i = 0; i < 3; i++) + rxq_ctx->start[i] = cpu_to_le32(addr); + + addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; + rxq_ctx->end = cpu_to_le32(addr); + + /* Express RX buffer queue */ + rxq_ctx = (struct icssg_rxq_ctx *)(prueth->dram[priv->port_id].pa + HOST_RX_Q_EXP_CONTEXT_OFFSET); + for (i = 0; i < 3; i++) + rxq_ctx->start[i] = cpu_to_le32(addr); + + addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; + rxq_ctx->end = cpu_to_le32(addr); + + return 0; +} + +static void icssg_init_emac_mode(struct prueth *prueth) +{ + u8 mac[6] = { 0 }; + + regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK, 0); + regmap_write(prueth->miig_rt, FDB_GEN_CFG2, 0); + /* Clear host MAC address */ + icssg_class_set_host_mac_addr(prueth->miig_rt, mac); +} + +int icssg_config(struct prueth_priv *priv) +{ + struct prueth *prueth = priv->prueth; + void *config = (void *)(prueth->dram[priv->port_id].pa + ICSSG_CONFIG_OFFSET); + u8 *cfg_byte_ptr = config; + struct icssg_flow_cfg *flow_cfg; + u32 mask; + int ret; + + int slice = priv->port_id; + + icssg_init_emac_mode(prueth); + + memset_io(config, 0, TAS_GATE_MASK_LIST0); + icssg_miig_queues_init(priv, slice); + + prueth->speed = SPEED_1000; + prueth->duplex = DUPLEX_FULL; + if (!phy_interface_is_rgmii(priv->phydev)) { + prueth->speed = SPEED_100; + prueth->duplex = DUPLEX_FULL; + } + + regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET, + ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT); + icssg_miig_set_interface_mode(prueth->miig_rt, ICSS_MII0, prueth->phy_interface); + icssg_miig_set_interface_mode(prueth->miig_rt, ICSS_MII1, prueth->phy_interface); + icssg_config_mii_init(priv, slice); + + icssg_config_ipg(priv, SPEED_1000, slice); + icssg_update_rgmii_cfg(prueth->miig_rt, SPEED_1000, true, slice, priv); + + /* set GPI mode */ + pruss_cfg_gpimode(prueth->pruss, slice, PRUSS_GPI_MODE_MII); + + /* enable XFR shift for PRU and RTU */ + mask = PRUSS_SPP_XFER_SHIFT_EN | PRUSS_SPP_RTU_XFR_SHIFT_EN; + pruss_cfg_update(prueth->pruss, PRUSS_CFG_SPP, mask, mask); + + flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; + flow_cfg->rx_base_flow = prueth->dma_rx.id; + flow_cfg->mgm_base_flow = 0; + *(cfg_byte_ptr + SPL_PKT_DEFAULT_PRIORITY) = 0; + *(cfg_byte_ptr + QUEUE_NUM_UNTAGGED) = 0x0; + + ret = prueth_emac_buffer_setup(priv); + + if (ret) + return ret; + + emac_r30_cmd_init(priv); + return 0; +} + +/* commands to program ICSSG R30 registers */ +static struct icssg_r30_cmd emac_r32_bitmask[] = { + {{0xffff0004, 0xffff0100, 0xffff0004, EMAC_NONE}}, /* EMAC_PORT_DISABLE */ + {{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}}, /* EMAC_PORT_BLOCK */ + {{0xffbb0000, 0xfcff0000, 0xdcfb0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */ + {{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}}, /* EMAC_PORT_FORWARD_WO_LEARNING */ + {{0xffff0001, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT ALL */ + {{0xfffe0002, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT TAGGED */ + {{0xfffc0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT UNTAGGED and PRIO */ + {{EMAC_NONE, 0xffff0020, EMAC_NONE, EMAC_NONE}}, /* TAS Trigger List change */ + {{EMAC_NONE, 0xdfff1000, EMAC_NONE, EMAC_NONE}}, /* TAS set state ENABLE*/ + {{EMAC_NONE, 0xefff2000, EMAC_NONE, EMAC_NONE}}, /* TAS set state RESET*/ + {{EMAC_NONE, 0xcfff0000, EMAC_NONE, EMAC_NONE}}, /* TAS set state DISABLE*/ + {{EMAC_NONE, EMAC_NONE, 0xffff0400, EMAC_NONE}}, /* UC flooding ENABLE*/ + {{EMAC_NONE, EMAC_NONE, 0xfbff0000, EMAC_NONE}}, /* UC flooding DISABLE*/ + {{EMAC_NONE, EMAC_NONE, 0xffff0800, EMAC_NONE}}, /* MC flooding ENABLE*/ + {{EMAC_NONE, EMAC_NONE, 0xf7ff0000, EMAC_NONE}}, /* MC flooding DISABLE*/ + {{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/ + {{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}} /* Preemption on Tx DISABLE*/ +}; + +int emac_set_port_state(struct prueth_priv *priv, + enum icssg_port_state_cmd cmd) +{ + struct prueth *prueth = priv->prueth; + struct icssg_r30_cmd *p; + int ret = -ETIMEDOUT; + int timeout = 10; + int i; + + p = (struct icssg_r30_cmd *)(prueth->dram[priv->port_id].pa + MGR_R30_CMD_OFFSET); + + if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) { + dev_err(prueth->dev, "invalid port command\n"); + return -EINVAL; + } + + for (i = 0; i < 4; i++) + writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]); + + /* wait for done */ + while (timeout) { + if (emac_r30_is_done(priv)) { + ret = 0; + break; + } + + udelay(2000); + timeout--; + } + + if (ret == -ETIMEDOUT) + dev_err(prueth->dev, "timeout waiting for command done\n"); + + return ret; +} + +int icssg_send_fdb_msg(struct prueth_priv *priv, struct mgmt_cmd *cmd, + struct mgmt_cmd_rsp *rsp) +{ + struct prueth *prueth = priv->prueth; + int slice = priv->port_id; + int ret, addr; + + addr = icssg_queue_pop(prueth, slice == 0 ? + ICSSG_CMD_POP_SLICE0 : ICSSG_CMD_POP_SLICE1); + if (addr < 0) + return addr; + + /* First 4 bytes have FW owned buffer linking info which should + * not be touched + */ + memcpy_toio((void __iomem *)prueth->shram.pa + addr + 4, cmd, sizeof(*cmd)); + icssg_queue_push(prueth, slice == 0 ? + ICSSG_CMD_PUSH_SLICE0 : ICSSG_CMD_PUSH_SLICE1, addr); + ret = read_poll_timeout(icssg_queue_pop, addr, addr >= 0, + 2000, 20000000, prueth, slice == 0 ? + ICSSG_RSP_POP_SLICE0 : ICSSG_RSP_POP_SLICE1); + + if (ret) { + dev_err(prueth->dev, "Timedout sending HWQ message\n"); + return ret; + } + + memcpy_fromio(rsp, (void __iomem *)prueth->shram.pa + addr, sizeof(*rsp)); + /* Return buffer back for to pool */ + icssg_queue_push(prueth, slice == 0 ? + ICSSG_RSP_PUSH_SLICE0 : ICSSG_RSP_PUSH_SLICE1, addr); + + return 0; +} + +int emac_fdb_flow_id_updated(struct prueth_priv *priv) +{ + struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 }; + struct prueth *prueth = priv->prueth; + struct mgmt_cmd fdb_cmd = { 0 }; + int slice = priv->port_id; + int ret = 0; + + fdb_cmd.header = ICSSG_FW_MGMT_CMD_HEADER; + fdb_cmd.type = ICSSG_FW_MGMT_FDB_CMD_TYPE_RX_FLOW; + fdb_cmd.seqnum = ++(prueth->icssg_hwcmdseq); + fdb_cmd.param = 0; + + fdb_cmd.param |= (slice << 4); + fdb_cmd.cmd_args[0] = 0; + + ret = icssg_send_fdb_msg(priv, &fdb_cmd, &fdb_cmd_rsp); + if (ret) + return ret; + + if (fdb_cmd.seqnum != fdb_cmd_rsp.seqnum) { + dev_err(prueth->dev, "seqnum doesn't match, cmd.seqnum %d != rsp.seqnum %d\n", + fdb_cmd.seqnum, fdb_cmd_rsp.seqnum); + return -EINVAL; + } + + if (fdb_cmd_rsp.status == 1) + return 0; + + return -EINVAL; +} diff --git a/drivers/net/ti/icssg_config.h b/drivers/net/ti/icssg_config.h new file mode 100644 index 00000000000..d388484c035 --- /dev/null +++ b/drivers/net/ti/icssg_config.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSSG_CONFIG_H +#define __NET_TI_ICSSG_CONFIG_H + +struct icssg_buffer_pool_cfg { + __le32 addr; + __le32 len; +} __packed; + +struct icssg_flow_cfg { + __le16 rx_base_flow; + __le16 mgm_base_flow; +} __packed; + +/* Config area lies in shared RAM */ +#define ICSSG_CONFIG_OFFSET_SLICE0 0 +#define ICSSG_CONFIG_OFFSET_SLICE1 0x8000 + +/* pstate speed/duplex command to set speed and duplex settings + * in firmware. + * Command format : 0x8102ssPN. ss - sequence number: currently not + * used by driver, P - port number: For switch, N - Speed/Duplex state + * - Possible values of N: + * 0x0 - 10Mbps/Half duplex ; + * 0x8 - 10Mbps/Full duplex ; + * 0x2 - 100Mbps/Half duplex; + * 0xa - 100Mbps/Full duplex; + * 0xc - 1Gbps/Full duplex; + * NOTE: The above are same as bits [3..1](slice 0) or bits [8..6](slice 1) of + * RGMII CFG register. So suggested to read the register to populate the command + * bits. + */ +#define ICSSG_PSTATE_SPEED_DUPLEX_CMD 0x81020000 +#define ICSSG_PSTATE_FULL_DUPLEX BIT(3) +#define ICSSG_PSTATE_SPEED_100 BIT(1) +#define ICSSG_PSTATE_SPEED_1000 BIT(2) + +/* Flow IDs used in config structure to firmware. Should match with + * flow_id in struct dma for rx channels. + */ +#define ICSSG_RX_CHAN_FLOW_ID 0 /* flow id for host port */ +#define ICSSG_RX_MGM_CHAN_FLOW_ID 1 /* flow id for command response */ + +/* Used to notify the FW of the current link speed */ +#define PORT_LINK_SPEED_OFFSET 0x00A8 + +#define FW_LINK_SPEED_1G (0x00) +#define FW_LINK_SPEED_100M (0x01) +#define FW_LINK_SPEED_10M (0x02) +#define FW_LINK_SPEED_HD (0x80) + +#define PRUETH_PKT_TYPE_CMD 0x10 +#define PRUETH_NAV_PS_DATA_SIZE 16 /* Protocol specific data size */ +#define PRUETH_NAV_SW_DATA_SIZE 16 /* SW related data size */ +#define PRUETH_MAX_RX_FLOWS 1 /* excluding default flow */ +#define PRUETH_RX_FLOW_DATA 0 /* FIXME: f/w bug to change to highest priority flow */ + +#define PRUETH_EMAC_BUF_POOL_SIZE SZ_8K +#define PRUETH_EMAC_POOLS_PER_SLICE 24 +#define PRUETH_EMAC_BUF_POOL_START 8 +#define PRUETH_NUM_BUF_POOLS 8 +#define PRUETH_EMAC_RX_CTX_BUF_SIZE SZ_16K /* per slice */ +#define MSMC_RAM_SIZE (2 * (PRUETH_EMAC_BUF_POOL_SIZE * PRUETH_NUM_BUF_POOLS + \ + PRUETH_EMAC_RX_CTX_BUF_SIZE)) + +struct icssg_rxq_ctx { + __le32 start[3]; + __le32 end; +} __packed; + +/* Load time Fiwmware Configuration */ + +#define ICSSG_FW_MGMT_CMD_HEADER 0x81 +#define ICSSG_FW_MGMT_FDB_CMD_TYPE 0x03 +#define ICSSG_FW_MGMT_CMD_TYPE 0x04 +#define ICSSG_FW_MGMT_PKT 0x80000000 +#define ICSSG_FW_MGMT_FDB_CMD_TYPE_RX_FLOW 0x05 + +struct icssg_r30_cmd { + u32 cmd[4]; +} __packed; + +enum icssg_port_state_cmd { + ICSSG_EMAC_PORT_DISABLE = 0, + ICSSG_EMAC_PORT_BLOCK, + ICSSG_EMAC_PORT_FORWARD, + ICSSG_EMAC_PORT_FORWARD_WO_LEARNING, + ICSSG_EMAC_PORT_ACCEPT_ALL, + ICSSG_EMAC_PORT_ACCEPT_TAGGED, + ICSSG_EMAC_PORT_ACCEPT_UNTAGGED_N_PRIO, + ICSSG_EMAC_PORT_TAS_TRIGGER, + ICSSG_EMAC_PORT_TAS_ENABLE, + ICSSG_EMAC_PORT_TAS_RESET, + ICSSG_EMAC_PORT_TAS_DISABLE, + ICSSG_EMAC_PORT_UC_FLOODING_ENABLE, + ICSSG_EMAC_PORT_UC_FLOODING_DISABLE, + ICSSG_EMAC_PORT_MC_FLOODING_ENABLE, + ICSSG_EMAC_PORT_MC_FLOODING_DISABLE, + ICSSG_EMAC_PORT_PREMPT_TX_ENABLE, + ICSSG_EMAC_PORT_PREMPT_TX_DISABLE, + ICSSG_EMAC_PORT_MAX_COMMANDS +}; + +#define EMAC_NONE 0xffff0000 +#define EMAC_PRU0_P_DI 0xffff0004 +#define EMAC_PRU1_P_DI 0xffff0040 +#define EMAC_TX_P_DI 0xffff0100 + +#define EMAC_PRU0_P_EN 0xfffb0000 +#define EMAC_PRU1_P_EN 0xffbf0000 +#define EMAC_TX_P_EN 0xfeff0000 + +#define EMAC_P_BLOCK 0xffff0040 +#define EMAC_TX_P_BLOCK 0xffff0200 +#define EMAC_P_UNBLOCK 0xffbf0000 +#define EMAC_TX_P_UNBLOCK 0xfdff0000 +#define EMAC_LEAN_EN 0xfff70000 +#define EMAC_LEAN_DI 0xffff0008 + +#define EMAC_ACCEPT_ALL 0xffff0001 +#define EMAC_ACCEPT_TAG 0xfffe0002 +#define EMAC_ACCEPT_PRIOR 0xfffc0000 + +/* Config area lies in DRAM */ +#define ICSSG_CONFIG_OFFSET 0x0 + +#define ICSSG_NUM_NORMAL_PDS 64 +#define ICSSG_NUM_SPECIAL_PDS 16 + +#define ICSSG_NORMAL_PD_SIZE 8 +#define ICSSG_SPECIAL_PD_SIZE 20 + +#define ICSSG_FLAG_MASK 0xff00ffff + +struct icssg_setclock_desc { + u8 request; + u8 restore; + u8 acknowledgment; + u8 cmp_status; + u32 margin; + u32 cyclecounter0_set; + u32 cyclecounter1_set; + u32 iepcount_set; + u32 rsvd1; + u32 rsvd2; + u32 CMP0_current; + u32 iepcount_current; + u32 difference; + u32 cyclecounter0_new; + u32 cyclecounter1_new; + u32 CMP0_new; +} __packed; + +struct mgmt_cmd { + u8 param; + u8 seqnum; + u8 type; + u8 header; + u32 cmd_args[3]; +} __packed; + +struct mgmt_cmd_rsp { + u32 reserved; + u8 status; + u8 seqnum; + u8 type; + u8 header; + u32 cmd_args[3]; +} __packed; + +#define ICSSG_CMD_POP_SLICE0 56 +#define ICSSG_CMD_POP_SLICE1 60 + +#define ICSSG_CMD_PUSH_SLICE0 57 +#define ICSSG_CMD_PUSH_SLICE1 61 + +#define ICSSG_RSP_POP_SLICE0 58 +#define ICSSG_RSP_POP_SLICE1 62 + +#define ICSSG_RSP_PUSH_SLICE0 56 +#define ICSSG_RSP_PUSH_SLICE1 60 + +#define ICSSG_TS_POP_SLICE0 59 +#define ICSSG_TS_POP_SLICE1 63 + +#define ICSSG_TS_PUSH_SLICE0 40 +#define ICSSG_TS_PUSH_SLICE1 41 + +#endif /* __NET_TI_ICSSG_CONFIG_H */ diff --git a/drivers/net/ti/icssg_prueth.c b/drivers/net/ti/icssg_prueth.c new file mode 100644 index 00000000000..2639f960631 --- /dev/null +++ b/drivers/net/ti/icssg_prueth.c @@ -0,0 +1,691 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Texas Instruments K3 AM65 PRU Ethernet Driver + * + * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#include <asm/io.h> +#include <asm/processor.h> +#include <clk.h> +#include <dm/lists.h> +#include <dm/device.h> +#include <dma-uclass.h> +#include <dm/of_access.h> +#include <dm/pinctrl.h> +#include <fs_loader.h> +#include <miiphy.h> +#include <net.h> +#include <phy.h> +#include <power-domain.h> +#include <linux/soc/ti/ti-udma.h> +#include <regmap.h> +#include <remoteproc.h> +#include <syscon.h> +#include <soc.h> +#include <linux/pruss_driver.h> +#include <dm/device_compat.h> + +#include "icssg_prueth.h" +#include "icss_mii_rt.h" + +#define ICSS_SLICE0 0 +#define ICSS_SLICE1 1 + +#ifdef PKTSIZE_ALIGN +#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN +#else +#define UDMA_RX_BUF_SIZE ALIGN(PKTSIZE, ARCH_DMA_MINALIGN) +#endif + +#ifdef PKTBUFSRX +#define UDMA_RX_DESC_NUM PKTBUFSRX +#else +#define UDMA_RX_DESC_NUM 4 +#endif + +/* Config region lies in shared RAM */ +#define ICSS_CONFIG_OFFSET_SLICE0 0 +#define ICSS_CONFIG_OFFSET_SLICE1 0x8000 + +/* Firmware flags */ +#define ICSS_SET_RUN_FLAG_VLAN_ENABLE BIT(0) /* switch only */ +#define ICSS_SET_RUN_FLAG_FLOOD_UNICAST BIT(1) /* switch only */ +#define ICSS_SET_RUN_FLAG_PROMISC BIT(2) /* MAC only */ +#define ICSS_SET_RUN_FLAG_MULTICAST_PROMISC BIT(3) /* MAC only */ + +/* CTRLMMR_ICSSG_RGMII_CTRL register bits */ +#define ICSSG_CTRL_RGMII_ID_MODE BIT(24) + +/* Management packet type */ +#define PRUETH_PKT_TYPE_CMD 0x10 + +/* Number of PRU Cores per Slice */ +#define ICSSG_NUM_PRU_CORES 3 + +static int icssg_gmii_select(struct prueth_priv *priv) +{ + struct phy_device *phydev = priv->phydev; + + if (phydev->interface != PHY_INTERFACE_MODE_MII && + phydev->interface < PHY_INTERFACE_MODE_RGMII && + phydev->interface > PHY_INTERFACE_MODE_RGMII_TXID) { + dev_err(priv->dev, "PHY mode unsupported %s\n", + phy_string_for_interface(phydev->interface)); + return -EINVAL; + } + + /* AM65 SR2.0 has TX Internal delay always enabled by hardware + * and it is not possible to disable TX Internal delay. The below + * switch case block describes how we handle different phy modes + * based on hardware restriction. + */ + switch (phydev->interface) { + case PHY_INTERFACE_MODE_RGMII_ID: + phydev->interface = PHY_INTERFACE_MODE_RGMII_RXID; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + phydev->interface = PHY_INTERFACE_MODE_RGMII; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_RXID: + dev_err(priv->dev, "RGMII mode without TX delay is not supported"); + return -EINVAL; + default: + break; + } + + return 0; +} + +static int icssg_phy_init(struct udevice *dev) +{ + struct prueth_priv *priv = dev_get_priv(dev); + struct phy_device *phydev; + u32 supported = PHY_GBIT_FEATURES; + int ret; + + phydev = dm_eth_phy_connect(dev); + if (!phydev) { + dev_err(dev, "phy_connect() failed\n"); + return -ENODEV; + } + + /* disable unsupported features */ + supported &= ~(PHY_10BT_FEATURES | + SUPPORTED_100baseT_Half | + SUPPORTED_1000baseT_Half | + SUPPORTED_Pause | + SUPPORTED_Asym_Pause); + + phydev->supported &= supported; + phydev->advertising = phydev->supported; + priv->phydev = phydev; + + ret = icssg_gmii_select(priv); + if (ret) + goto out; + + ret = phy_config(phydev); + if (ret < 0) + dev_err(dev, "phy_config() failed: %d", ret); +out: + return ret; +} + +static void icssg_config_set_speed(struct prueth_priv *priv, int speed) +{ + struct prueth *prueth = priv->prueth; + u8 fw_speed; + + switch (speed) { + case SPEED_1000: + fw_speed = FW_LINK_SPEED_1G; + break; + case SPEED_100: + fw_speed = FW_LINK_SPEED_100M; + break; + case SPEED_10: + fw_speed = FW_LINK_SPEED_10M; + break; + default: + /* Other links speeds not supported */ + dev_err(priv->dev, "Unsupported link speed\n"); + return; + } + + writeb(fw_speed, prueth->dram[priv->port_id].pa + PORT_LINK_SPEED_OFFSET); +} + +static int icssg_update_link(struct prueth_priv *priv) +{ + struct phy_device *phy = priv->phydev; + struct prueth *prueth = priv->prueth; + bool gig_en = false, full_duplex = false; + + if (phy->link) { /* link up */ + if (phy->speed == SPEED_1000) + gig_en = true; + if (phy->duplex == DUPLEX_FULL) + full_duplex = true; + /* Set the RGMII cfg for gig en and full duplex */ + icssg_update_rgmii_cfg(prueth->miig_rt, phy->speed, full_duplex, + priv->port_id, priv); + /* update the Tx IPG based on 100M/1G speed */ + icssg_config_ipg(priv, phy->speed, priv->port_id); + + /* Send command to firmware to update Speed setting */ + icssg_config_set_speed(priv, phy->speed); + + /* Enable PORT FORWARDING */ + emac_set_port_state(priv, ICSSG_EMAC_PORT_FORWARD); + + printf("link up on port %d, speed %d, %s duplex\n", + priv->port_id, phy->speed, + (phy->duplex == DUPLEX_FULL) ? "full" : "half"); + } else { + emac_set_port_state(priv, ICSSG_EMAC_PORT_DISABLE); + printf("link down on port %d\n", priv->port_id); + } + + return phy->link; +} + +struct icssg_firmwares { + char *pru; + char *rtu; + char *txpru; +}; + +static struct icssg_firmwares icssg_emac_firmwares[] = { + { + .pru = "/lib/firmware/ti-pruss/am65x-sr2-pru0-prueth-fw.elf", + .rtu = "/lib/firmware/ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", + .txpru = "/lib/firmware/ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", + }, + { + .pru = "/lib/firmware/ti-pruss/am65x-sr2-pru1-prueth-fw.elf", + .rtu = "/lib/firmware/ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", + .txpru = "/lib/firmware/ti-pruss/am65x-sr2-txpru1-prueth-fw.elf", + } +}; + +static int icssg_start_pru_cores(struct udevice *dev) +{ + struct prueth_priv *priv = dev_get_priv(dev); + struct prueth *prueth = priv->prueth; + struct icssg_firmwares *firmwares; + struct udevice *rproc_dev = NULL; + int ret, slice; + u32 phandle; + u8 index; + + slice = priv->port_id; + index = slice * ICSSG_NUM_PRU_CORES; + firmwares = icssg_emac_firmwares; + + ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index, &phandle); + ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev); + if (ret) { + dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n", + phandle, ret); + return ret; + } + + prueth->pru_core_id = dev_seq(rproc_dev); + ret = rproc_set_firmware(rproc_dev, firmwares[slice].pru); + if (ret) + return ret; + + ret = rproc_boot(rproc_dev); + if (ret) { + dev_err(dev, "failed to boot PRU%d: %d\n", slice, ret); + return -EINVAL; + } + + ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index + 1, &phandle); + ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev); + if (ret) { + dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n", + phandle, ret); + goto halt_pru; + } + + prueth->rtu_core_id = dev_seq(rproc_dev); + ret = rproc_set_firmware(rproc_dev, firmwares[slice].rtu); + if (ret) + goto halt_pru; + + ret = rproc_boot(rproc_dev); + if (ret) { + dev_err(dev, "failed to boot RTU%d: %d\n", slice, ret); + goto halt_pru; + } + + ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index + 2, &phandle); + ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev); + if (ret) { + dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n", + phandle, ret); + goto halt_rtu; + } + + prueth->txpru_core_id = dev_seq(rproc_dev); + ret = rproc_set_firmware(rproc_dev, firmwares[slice].txpru); + if (ret) + goto halt_rtu; + + ret = rproc_boot(rproc_dev); + if (ret) { + dev_err(dev, "failed to boot TXPRU%d: %d\n", slice, ret); + goto halt_rtu; + } + + return 0; + +halt_rtu: + rproc_stop(prueth->rtu_core_id); + +halt_pru: + rproc_stop(prueth->pru_core_id); + return ret; +} + +static int icssg_stop_pru_cores(struct udevice *dev) +{ + struct prueth_priv *priv = dev_get_priv(dev); + struct prueth *prueth = priv->prueth; + + rproc_stop(prueth->pru_core_id); + rproc_stop(prueth->rtu_core_id); + rproc_stop(prueth->txpru_core_id); + + return 0; +} + +static int prueth_start(struct udevice *dev) +{ + struct ti_udma_drv_chan_cfg_data *dma_rx_cfg_data; + struct eth_pdata *pdata = dev_get_plat(dev); + struct prueth_priv *priv = dev_get_priv(dev); + struct prueth *prueth = priv->prueth; + struct icssg_flow_cfg *flow_cfg; + u8 *hwaddr = pdata->enetaddr; + char chn_name[16]; + void *config; + int ret, i; + + icssg_class_set_mac_addr(prueth->miig_rt, priv->port_id, hwaddr); + icssg_ft1_set_mac_addr(prueth->miig_rt, priv->port_id, hwaddr); + icssg_class_default(prueth->miig_rt, priv->port_id, 0); + + /* Set Load time configuration */ + icssg_config(priv); + + ret = icssg_start_pru_cores(dev); + if (ret) + return ret; + + /* To differentiate channels for SLICE0 vs SLICE1 */ + snprintf(chn_name, sizeof(chn_name), "tx%d-0", priv->port_id); + + ret = dma_get_by_name(prueth->dev, chn_name, &prueth->dma_tx); + if (ret) + dev_err(dev, "TX dma get failed %d\n", ret); + + snprintf(chn_name, sizeof(chn_name), "rx%d", priv->port_id); + ret = dma_get_by_name(prueth->dev, chn_name, &prueth->dma_rx); + if (ret) + dev_err(dev, "RX dma get failed %d\n", ret); + + for (i = 0; i < UDMA_RX_DESC_NUM; i++) { + ret = dma_prepare_rcv_buf(&prueth->dma_rx, + net_rx_packets[i], + UDMA_RX_BUF_SIZE); + if (ret) + dev_err(dev, "RX dma add buf failed %d\n", ret); + } + + ret = dma_enable(&prueth->dma_tx); + if (ret) { + dev_err(dev, "TX dma_enable failed %d\n", ret); + goto tx_fail; + } + + ret = dma_enable(&prueth->dma_rx); + if (ret) { + dev_err(dev, "RX dma_enable failed %d\n", ret); + goto rx_fail; + } + + /* check if the rx_flow_id of dma_rx is as expected since + * driver hardcode that value in config struct to firmware + * in probe. Just add this sanity check to catch any change + * to rx channel assignment in the future. + */ + dma_get_cfg(&prueth->dma_rx, 0, (void **)&dma_rx_cfg_data); + config = (void *)(prueth->dram[priv->port_id].pa + ICSSG_CONFIG_OFFSET); + + flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET; + writew(dma_rx_cfg_data->flow_id_base, &flow_cfg->rx_base_flow); + writew(0, &flow_cfg->mgm_base_flow); + + dev_info(dev, "K3 ICSSG: rflow_id_base: %u, chn_name = %s\n", + dma_rx_cfg_data->flow_id_base, chn_name); + + ret = emac_fdb_flow_id_updated(priv); + if (ret) { + dev_err(dev, "Failed to update Rx Flow ID %d", ret); + goto phy_fail; + } + + ret = phy_startup(priv->phydev); + if (ret) { + dev_err(dev, "phy_startup failed\n"); + goto phy_fail; + } + + ret = icssg_update_link(priv); + if (!ret) { + ret = -ENODEV; + goto phy_shut; + } + + return 0; + +phy_shut: + phy_shutdown(priv->phydev); +phy_fail: + dma_disable(&prueth->dma_rx); + dma_free(&prueth->dma_rx); +rx_fail: + dma_disable(&prueth->dma_tx); + dma_free(&prueth->dma_tx); + +tx_fail: + icssg_class_disable(prueth->miig_rt, priv->port_id); + + return ret; +} + +static int prueth_send(struct udevice *dev, void *packet, int length) +{ + struct prueth_priv *priv = dev_get_priv(dev); + struct prueth *prueth = priv->prueth; + int ret; + + ret = dma_send(&prueth->dma_tx, packet, length, NULL); + + return ret; +} + +static int prueth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct prueth_priv *priv = dev_get_priv(dev); + struct prueth *prueth = priv->prueth; + int ret; + + /* try to receive a new packet */ + ret = dma_receive(&prueth->dma_rx, (void **)packetp, NULL); + + return ret; +} + +static int prueth_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct prueth_priv *priv = dev_get_priv(dev); + struct prueth *prueth = priv->prueth; + int ret = 0; + + if (length > 0) { + u32 pkt = prueth->rx_next % UDMA_RX_DESC_NUM; + + dev_dbg(dev, "%s length:%d pkt:%u\n", __func__, length, pkt); + + ret = dma_prepare_rcv_buf(&prueth->dma_rx, + net_rx_packets[pkt], + UDMA_RX_BUF_SIZE); + prueth->rx_next++; + } + + return ret; +} + +static void prueth_stop(struct udevice *dev) +{ + struct prueth_priv *priv = dev_get_priv(dev); + struct prueth *prueth = priv->prueth; + + phy_shutdown(priv->phydev); + + dma_disable(&prueth->dma_tx); + dma_disable(&prueth->dma_rx); + + icssg_stop_pru_cores(dev); + + dma_free(&prueth->dma_tx); + dma_free(&prueth->dma_rx); +} + +static const struct eth_ops prueth_ops = { + .start = prueth_start, + .send = prueth_send, + .recv = prueth_recv, + .free_pkt = prueth_free_pkt, + .stop = prueth_stop, +}; + +static int icssg_ofdata_parse_phy(struct udevice *dev) +{ + struct prueth_priv *priv = dev_get_priv(dev); + + dev_read_u32(dev, "reg", &priv->port_id); + priv->phy_interface = dev_read_phy_mode(dev); + if (priv->phy_interface == PHY_INTERFACE_MODE_NA) { + dev_err(dev, "Invalid PHY mode '%s', port %u\n", + phy_string_for_interface(priv->phy_interface), + priv->port_id); + return -EINVAL; + } + + return 0; +} + +static int prueth_port_probe(struct udevice *dev) +{ + struct prueth_priv *priv = dev_get_priv(dev); + struct prueth *prueth; + char portname[15]; + int ret; + + priv->dev = dev; + prueth = dev_get_priv(dev->parent); + priv->prueth = prueth; + + sprintf(portname, "%s-%s", dev->parent->name, dev->name); + + device_set_name(dev, portname); + + ret = icssg_ofdata_parse_phy(dev); + if (ret) + goto out; + + ret = icssg_phy_init(dev); + if (ret) + goto out; + + ret = pruss_request_mem_region(prueth->pruss, + priv->port_id ? PRUSS_MEM_DRAM1 : PRUSS_MEM_DRAM0, + &prueth->dram[priv->port_id]); + if (ret) { + dev_err(dev, "could not request DRAM%d region\n", priv->port_id); + return ret; + } +out: + return ret; +} + +static int prueth_probe(struct udevice *dev) +{ + ofnode node, pruss_node, mdio_node, sram_node, curr_sram_node; + struct prueth *prueth = dev_get_priv(dev); + u32 phandle, err, sp, prev_end_addr; + struct udevice **prussdev = NULL; + ofnode eth_ports_node, eth_node; + struct udevice *port_dev; + int ret = 0; + + prueth->dev = dev; + + err = ofnode_read_u32(dev_ofnode(dev), "ti,prus", &phandle); + if (err) + return err; + + node = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(node)) + return -EINVAL; + + pruss_node = ofnode_get_parent(node); + ret = device_get_global_by_ofnode(pruss_node, prussdev); + if (ret) + dev_err(dev, "error getting the pruss dev\n"); + prueth->pruss = *prussdev; + + ret = pruss_request_mem_region(*prussdev, PRUSS_MEM_SHRD_RAM2, + &prueth->shram); + if (ret) + return ret; + + ret = pruss_request_tm_region(*prussdev, &prueth->tmaddr); + if (ret) + return ret; + + prueth->miig_rt = syscon_regmap_lookup_by_phandle(dev, "ti,mii-g-rt"); + if (!prueth->miig_rt) { + dev_err(dev, "couldn't get mii-g-rt syscon regmap\n"); + return -ENODEV; + } + + prueth->mii_rt = syscon_regmap_lookup_by_phandle(dev, "ti,mii-rt"); + if (!prueth->mii_rt) { + dev_err(dev, "couldn't get mii-rt syscon regmap\n"); + return -ENODEV; + } + + ret = ofnode_read_u32(dev_ofnode(dev), "sram", &sp); + if (ret) { + dev_err(dev, "sram node fetch failed %d\n", ret); + return ret; + } + + sram_node = ofnode_get_by_phandle(sp); + if (!ofnode_valid(sram_node)) + return -EINVAL; + + prev_end_addr = ofnode_get_addr(sram_node); + + ofnode_for_each_subnode(curr_sram_node, sram_node) { + u32 start_addr, size, end_addr, avail; + const char *name; + + name = ofnode_get_name(curr_sram_node); + start_addr = ofnode_get_addr(curr_sram_node); + size = ofnode_get_size(curr_sram_node); + end_addr = start_addr + size; + avail = start_addr - prev_end_addr; + + if (avail > MSMC_RAM_SIZE) + break; + + prev_end_addr = end_addr; + } + + prueth->sram_pa = prev_end_addr; + if (prueth->sram_pa % SZ_64K != 0) { + /* This is constraint for SR2.0 firmware */ + dev_err(dev, "sram address needs to be 64KB aligned\n"); + return -EINVAL; + } + dev_dbg(dev, "sram: addr %x size %x\n", prueth->sram_pa, MSMC_RAM_SIZE); + + mdio_node = ofnode_find_subnode(pruss_node, "mdio"); + prueth->mdio_base = ofnode_get_addr(mdio_node); + ofnode_read_u32(mdio_node, "bus_freq", &prueth->mdio_freq); + + ret = clk_get_by_name_nodev(mdio_node, "fck", &prueth->mdiofck); + if (ret) { + dev_err(dev, "failed to get clock %d\n", ret); + return ret; + } + + ret = clk_enable(&prueth->mdiofck); + if (ret) { + dev_err(dev, "clk_enable failed %d\n", ret); + return ret; + } + + eth_ports_node = dev_read_subnode(dev, "ethernet-ports"); + if (!ofnode_valid(eth_ports_node)) + return -ENOENT; + + ofnode_for_each_subnode(eth_node, eth_ports_node) { + const char *node_name; + u32 port_id; + bool disabled; + + node_name = ofnode_get_name(eth_node); + disabled = !ofnode_is_enabled(eth_node); + ret = ofnode_read_u32(eth_node, "reg", &port_id); + if (ret) + dev_err(dev, "%s: error reading port_id (%d)\n", node_name, ret); + + if (port_id >= PRUETH_NUM_MACS) { + dev_err(dev, "%s: invalid port_id (%d)\n", node_name, port_id); + return -EINVAL; + } + + if (port_id < 0) + continue; + if (disabled) + continue; + + ret = device_bind_driver_to_node(dev, "prueth_port", + ofnode_get_name(eth_node), + eth_node, &port_dev); + if (ret) { + dev_err(dev, "Failed to bind to %s node\n", ofnode_get_name(eth_node)); + goto out; + } + } + + return 0; +out: + clk_disable(&prueth->mdiofck); + + return ret; +} + +static const struct udevice_id prueth_ids[] = { + { .compatible = "ti,am654-icssg-prueth" }, + { .compatible = "ti,am642-icssg-prueth" }, + { } +}; + +U_BOOT_DRIVER(prueth) = { + .name = "prueth", + .id = UCLASS_MISC, + .of_match = prueth_ids, + .probe = prueth_probe, + .priv_auto = sizeof(struct prueth), +}; + +U_BOOT_DRIVER(prueth_port) = { + .name = "prueth_port", + .id = UCLASS_ETH, + .probe = prueth_port_probe, + .ops = &prueth_ops, + .priv_auto = sizeof(struct prueth_priv), + .plat_auto = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/net/ti/icssg_prueth.h b/drivers/net/ti/icssg_prueth.h new file mode 100644 index 00000000000..c69cfd4f162 --- /dev/null +++ b/drivers/net/ti/icssg_prueth.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver + * + * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSSG_PRUETH_H +#define __NET_TI_ICSSG_PRUETH_H + +#include <asm/io.h> +#include <clk.h> +#include <dm/lists.h> +#include <dm/ofnode.h> +#include <dm/device.h> +#include <dma-uclass.h> +#include <regmap.h> +#include <linux/sizes.h> +#include <linux/pruss_driver.h> +#include "icssg_config.h" +#include "icssg_switch_map.h" + +void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac); +void icssg_class_set_host_mac_addr(struct regmap *miig_rt, u8 *mac); +void icssg_class_disable(struct regmap *miig_rt, int slice); +void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti); +void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr); + +enum prueth_mac { + PRUETH_MAC0 = 0, + PRUETH_MAC1, + PRUETH_NUM_MACS, +}; + +enum prueth_port { + PRUETH_PORT_HOST = 0, /* host side port */ + PRUETH_PORT_MII0, /* physical port MII 0 */ + PRUETH_PORT_MII1, /* physical port MII 1 */ +}; + +struct prueth { + struct udevice *dev; + struct udevice *pruss; + struct regmap *miig_rt; + struct regmap *mii_rt; + fdt_addr_t mdio_base; + struct pruss_mem_region shram; + struct pruss_mem_region dram[PRUETH_NUM_MACS]; + phys_addr_t tmaddr; + struct mii_dev *bus; + u32 sram_pa; + ofnode eth_node[PRUETH_NUM_MACS]; + u32 mdio_freq; + int phy_interface; + struct clk mdiofck; + struct dma dma_tx; + struct dma dma_rx; + struct dma dma_rx_mgm; + u32 rx_next; + u32 rx_pend; + int slice; + bool mdio_manual_mode; + int speed; + int duplex; + u8 pru_core_id; + u8 rtu_core_id; + u8 txpru_core_id; + u8 icssg_hwcmdseq; +}; + +struct prueth_priv { + struct udevice *dev; + struct prueth *prueth; + u32 port_id; + struct phy_device *phydev; + bool has_phy; + ofnode phy_node; + u32 phy_addr; + int phy_interface; +}; + +/* config helpers */ +void icssg_config_ipg(struct prueth_priv *priv, int speed, int mii); +int icssg_config(struct prueth_priv *priv); +int emac_set_port_state(struct prueth_priv *priv, enum icssg_port_state_cmd cmd); + +/* Buffer queue helpers */ +int icssg_queue_pop(struct prueth *prueth, u8 queue); +void icssg_queue_push(struct prueth *prueth, int queue, u16 addr); +u32 icssg_queue_level(struct prueth *prueth, int queue); + +/* FDB helpers */ +int icssg_send_fdb_msg(struct prueth_priv *priv, struct mgmt_cmd *cmd, + struct mgmt_cmd_rsp *rsp); +int emac_fdb_flow_id_updated(struct prueth_priv *priv); + +#endif /* __NET_TI_ICSSG_PRUETH_H */ diff --git a/drivers/net/ti/icssg_queues.c b/drivers/net/ti/icssg_queues.c new file mode 100644 index 00000000000..fc4d33dbb25 --- /dev/null +++ b/drivers/net/ti/icssg_queues.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* ICSSG Buffer queue helpers + * + * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com + */ + +#include <dm/ofnode.h> +#include <regmap.h> +#include "icssg_prueth.h" + +#define ICSSG_QUEUES_MAX 64 +#define ICSSG_QUEUE_OFFSET 0xd00 +#define ICSSG_QUEUE_PEEK_OFFSET 0xe00 +#define ICSSG_QUEUE_CNT_OFFSET 0xe40 +#define ICSSG_QUEUE_RESET_OFFSET 0xf40 + +int icssg_queue_pop(struct prueth *prueth, u8 queue) +{ + u32 val, cnt; + + if (queue >= ICSSG_QUEUES_MAX) + return -EINVAL; + + regmap_read(prueth->miig_rt, ICSSG_QUEUE_CNT_OFFSET + 4 * queue, &cnt); + if (!cnt) + return -EINVAL; + + regmap_read(prueth->miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, &val); + + return val; +} + +void icssg_queue_push(struct prueth *prueth, int queue, u16 addr) +{ + if (queue >= ICSSG_QUEUES_MAX) + return; + + regmap_write(prueth->miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, addr); +} + +u32 icssg_queue_level(struct prueth *prueth, int queue) +{ + u32 reg; + + if (queue >= ICSSG_QUEUES_MAX) + return 0; + + regmap_read(prueth->miig_rt, ICSSG_QUEUE_CNT_OFFSET + 4 * queue, ®); + + return reg; +} diff --git a/drivers/net/ti/icssg_switch_map.h b/drivers/net/ti/icssg_switch_map.h new file mode 100644 index 00000000000..b62c51407b8 --- /dev/null +++ b/drivers/net/ti/icssg_switch_map.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Texas Instruments ICSSG Ethernet driver + * + * Copyright (C) 2020-2024 Texas Instruments Incorporated - https://www.ti.com/ + * + */ + +#ifndef __NET_TI_ICSSG_SWITCH_MAP_H +#define __NET_TI_ICSSG_SWITCH_MAP_H + +/*Time after which FDB entries are checked for aged out values. Value in nanoseconds*/ +#define FDB_AGEING_TIMEOUT_OFFSET 0x0014 + +/*default VLAN tag for Host Port*/ +#define HOST_PORT_DF_VLAN_OFFSET 0x001C + +/*Same as HOST_PORT_DF_VLAN_OFFSET*/ +#define EMAC_ICSSG_SWITCH_PORT0_DEFAULT_VLAN_OFFSET HOST_PORT_DF_VLAN_OFFSET + +/*default VLAN tag for P1 Port*/ +#define P1_PORT_DF_VLAN_OFFSET 0x0020 + +/*Same as P1_PORT_DF_VLAN_OFFSET*/ +#define EMAC_ICSSG_SWITCH_PORT1_DEFAULT_VLAN_OFFSET P1_PORT_DF_VLAN_OFFSET + +/*default VLAN tag for P2 Port*/ +#define P2_PORT_DF_VLAN_OFFSET 0x0024 + +/*Same as P2_PORT_DF_VLAN_OFFSET*/ +#define EMAC_ICSSG_SWITCH_PORT2_DEFAULT_VLAN_OFFSET P2_PORT_DF_VLAN_OFFSET + +/*VLAN-FID Table offset. 4096 VIDs. 2B per VID = 8KB = 0x2000*/ +#define VLAN_STATIC_REG_TABLE_OFFSET 0x0100 + +/*VLAN-FID Table offset for EMAC*/ +#define EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET VLAN_STATIC_REG_TABLE_OFFSET + +/*packet descriptor Q reserved memory*/ +#define PORT_DESC0_HI 0x2104 + +/*packet descriptor Q reserved memory*/ +#define PORT_DESC0_LO 0x2F6C + +/*packet descriptor Q reserved memory*/ +#define PORT_DESC1_HI 0x3DD4 + +/*packet descriptor Q reserved memory*/ +#define PORT_DESC1_LO 0x4C3C + +/*packet descriptor Q reserved memory*/ +#define HOST_DESC0_HI 0x5AA4 + +/*packet descriptor Q reserved memory*/ +#define HOST_DESC0_LO 0x5F0C + +/*packet descriptor Q reserved memory*/ +#define HOST_DESC1_HI 0x6374 + +/*packet descriptor Q reserved memory*/ +#define HOST_DESC1_LO 0x67DC + +/*special packet descriptor Q reserved memory*/ +#define HOST_SPPD0 0x7AAC + +/*special packet descriptor Q reserved memory*/ +#define HOST_SPPD1 0x7EAC + +/*_Small_Description_*/ +#define TIMESYNC_FW_WC_CYCLECOUNT_OFFSET 0x83EC + +/*IEP count hi roll over count*/ +#define TIMESYNC_FW_WC_HI_ROLLOVER_COUNT_OFFSET 0x83F4 + +/*_Small_Description_*/ +#define TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET 0x83F8 + +/*Set clock descriptor*/ +#define TIMESYNC_FW_WC_SETCLOCK_DESC_OFFSET 0x83FC + +/*_Small_Description_*/ +#define TIMESYNC_FW_WC_SYNCOUT_REDUCTION_FACTOR_OFFSET 0x843C + +/*_Small_Description_*/ +#define TIMESYNC_FW_WC_SYNCOUT_REDUCTION_COUNT_OFFSET 0x8440 + +/*_Small_Description_*/ +#define TIMESYNC_FW_WC_SYNCOUT_START_TIME_CYCLECOUNT_OFFSET 0x8444 + +/*Control variable to generate SYNC1*/ +#define TIMESYNC_FW_WC_ISOM_PIN_SIGNAL_EN_OFFSET 0x844C + +/*SystemTime Sync0 periodicity*/ +#define TIMESYNC_FW_ST_SYNCOUT_PERIOD_OFFSET 0x8450 + +/*pktTxDelay for P1 = link speed dependent p1 mac delay + p1 phy delay*/ +#define TIMESYNC_FW_WC_PKTTXDELAY_P1_OFFSET 0x8454 + +/*pktTxDelay for P2 = link speed dependent p2 mac delay + p2 phy delay*/ +#define TIMESYNC_FW_WC_PKTTXDELAY_P2_OFFSET 0x8458 + +/*Set clock operation done signal for next task*/ +#define TIMESYNC_FW_SIG_PNFW_OFFSET 0x845C + +/*Set clock operation done signal for next task*/ +#define TIMESYNC_FW_SIG_TIMESYNCFW_OFFSET 0x8460 + +/*New list is copied at this time*/ +#define TAS_CONFIG_CHANGE_TIME 0x000C + +/*config change error counter*/ +#define TAS_CONFIG_CHANGE_ERROR_COUNTER 0x0014 + +/*TAS List update pending flag*/ +#define TAS_CONFIG_PENDING 0x0018 + +/*TAS list update trigger flag*/ +#define TAS_CONFIG_CHANGE 0x0019 + +/*List length for new TAS schedule*/ +#define TAS_ADMIN_LIST_LENGTH 0x001A + +/*Currently active TAS list index*/ +#define TAS_ACTIVE_LIST_INDEX 0x001B + +/*Cycle time for the new TAS schedule*/ +#define TAS_ADMIN_CYCLE_TIME 0x001C + +/*Cycle counts remaining till the TAS list update*/ +#define TAS_CONFIG_CHANGE_CYCLE_COUNT 0x0020 + +/*Base Flow ID for sending packets to Host for Slice0*/ +#define PSI_L_REGULAR_FLOW_ID_BASE_OFFSET 0x0024 + +/*Same as PSI_L_REGULAR_FLOW_ID_BASE_OFFSET*/ +#define EMAC_ICSSG_SWITCH_PSI_L_REGULAR_FLOW_ID_BASE_OFFSET PSI_L_REGULAR_FLOW_ID_BASE_OFFSET + +/*Base Flow ID for sending mgmt and Tx TS to Host for Slice0*/ +#define PSI_L_MGMT_FLOW_ID_OFFSET 0x0026 + +/*Same as PSI_L_MGMT_FLOW_ID_OFFSET*/ +#define EMAC_ICSSG_SWITCH_PSI_L_MGMT_FLOW_ID_BASE_OFFSET PSI_L_MGMT_FLOW_ID_OFFSET + +/*Queue number for Special packets written here*/ +#define SPL_PKT_DEFAULT_PRIORITY 0x0028 + +/*Express Preemptible Queue Mask*/ +#define EXPRESS_PRE_EMPTIVE_Q_MASK 0x0029 + +/*Port1/Port2 Default Queue number for untagged packets, only 1B is used*/ +#define QUEUE_NUM_UNTAGGED 0x002A + +/*Stores the table used for priority regeneration. 1B per PCP/Queue*/ +#define PORT_Q_PRIORITY_REGEN_OFFSET 0x002C + +/* For marking Packet as priority/express (this feature is disabled) or + * cut-through/S&F. + */ +#define EXPRESS_PRE_EMPTIVE_Q_MAP 0x0034 + +/*Stores the table used for priority mapping. 1B per PCP/Queue*/ +#define PORT_Q_PRIORITY_MAPPING_OFFSET 0x003C + +/*TAS gate mask for windows list0*/ +#define TAS_GATE_MASK_LIST0 0x0100 + +/*TAS gate mask for windows list1*/ +#define TAS_GATE_MASK_LIST1 0x0350 + +/*Memory to Enable/Disable Preemption on TX side*/ +#define PRE_EMPTION_ENABLE_TX 0x05A0 + +/*Active State of Preemption on TX side*/ +#define PRE_EMPTION_ACTIVE_TX 0x05A1 + +/*Memory to Enable/Disable Verify State Machine Preemption*/ +#define PRE_EMPTION_ENABLE_VERIFY 0x05A2 + +/*Verify Status of State Machine*/ +#define PRE_EMPTION_VERIFY_STATUS 0x05A3 + +/*Non Final Fragment Size supported by Link Partner*/ +#define PRE_EMPTION_ADD_FRAG_SIZE_REMOTE 0x05A4 + +/*Non Final Fragment Size supported by Firmware*/ +#define PRE_EMPTION_ADD_FRAG_SIZE_LOCAL 0x05A6 + +/*Time in ms the State machine waits for respond packet*/ +#define PRE_EMPTION_VERIFY_TIME 0x05A8 + +/*Memory used for R30 related management commands*/ +#define MGR_R30_CMD_OFFSET 0x05AC + +/*HW Buffer Pool0 base address*/ +#define BUFFER_POOL_0_ADDR_OFFSET 0x05BC + +/*16B for Host Egress MSMC Q (Pre-emptible) context*/ +#define HOST_RX_Q_PRE_CONTEXT_OFFSET 0x0684 + +/*Buffer for 8 FDB entries to be added by 'Add Multiple FDB entries IOCTL*/ +#define FDB_CMD_BUFFER 0x0894 + +/*16B for Host Egress MSMC Q (Express) context*/ +#define HOST_RX_Q_EXP_CONTEXT_OFFSET 0x0940 + +/*Start of 32 bits PA_STAT counters*/ +#define PA_STAT_32b_START_OFFSET 0x0080 + +#endif +/* __NET_TI_ICSSG_SWITCH_MAP_H */ diff --git a/drivers/rtc/goldfish_rtc.c b/drivers/rtc/goldfish_rtc.c index 1ace9903858..3231eb0daf8 100644 --- a/drivers/rtc/goldfish_rtc.c +++ b/drivers/rtc/goldfish_rtc.c @@ -72,7 +72,7 @@ static int goldfish_rtc_set(struct udevice *dev, const struct rtc_time *time) return 0; } -int goldfish_rtc_probe(struct udevice *dev) +static int goldfish_rtc_probe(struct udevice *dev) { struct goldfish_rtc *priv = dev_get_priv(dev); fdt_addr_t addr; diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c index ce08a6b4486..3f2be72b830 100644 --- a/drivers/serial/serial_lpuart.c +++ b/drivers/serial/serial_lpuart.c @@ -109,28 +109,35 @@ u32 __weak get_lpuart_clk(void) } #if CONFIG_IS_ENABLED(CLK) -static int get_lpuart_clk_rate(struct udevice *dev, u32 *clk) +static int get_lpuart_clk_rate(struct udevice *dev, u32 *clk_rate) { - struct clk per_clk; + struct lpuart_serial_plat *plat = dev_get_plat(dev); + struct clk clk; ulong rate; int ret; + char *name; - ret = clk_get_by_name(dev, "per", &per_clk); + if (plat->devtype == DEV_MX7ULP) + name = "ipg"; + else + name = "per"; + + ret = clk_get_by_name(dev, name, &clk); if (ret) { - dev_err(dev, "Failed to get per clk: %d\n", ret); + dev_err(dev, "Failed to get clk: %d\n", ret); return ret; } - rate = clk_get_rate(&per_clk); + rate = clk_get_rate(&clk); if ((long)rate <= 0) { - dev_err(dev, "Failed to get per clk rate: %ld\n", (long)rate); + dev_err(dev, "Failed to get clk rate: %ld\n", (long)rate); return ret; } - *clk = rate; + *clk_rate = rate; return 0; } #else -static inline int get_lpuart_clk_rate(struct udevice *dev, u32 *clk) +static inline int get_lpuart_clk_rate(struct udevice *dev, u32 *clk_rate) { return -ENOSYS; } #endif @@ -479,19 +486,22 @@ static int lpuart_serial_pending(struct udevice *dev, bool input) static int lpuart_serial_probe(struct udevice *dev) { #if CONFIG_IS_ENABLED(CLK) + struct lpuart_serial_plat *plat = dev_get_plat(dev); struct clk per_clk; struct clk ipg_clk; int ret; - ret = clk_get_by_name(dev, "per", &per_clk); - if (!ret) { - ret = clk_enable(&per_clk); - if (ret) { - dev_err(dev, "Failed to enable per clk: %d\n", ret); - return ret; + if (plat->devtype != DEV_MX7ULP) { + ret = clk_get_by_name(dev, "per", &per_clk); + if (!ret) { + ret = clk_enable(&per_clk); + if (ret) { + dev_err(dev, "Failed to enable per clk: %d\n", ret); + return ret; + } + } else { + debug("%s: Failed to get per clk: %d\n", __func__, ret); } - } else { - debug("%s: Failed to get per clk: %d\n", __func__, ret); } ret = clk_get_by_name(dev, "ipg", &ipg_clk); diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c index b6197da97cc..35df413321f 100644 --- a/drivers/serial/serial_xuartlite.c +++ b/drivers/serial/serial_xuartlite.c @@ -23,7 +23,7 @@ #define ULITE_CONTROL_RST_TX 0x01 #define ULITE_CONTROL_RST_RX 0x02 -static bool little_endian; +static bool little_endian __section(".data"); struct uartlite { unsigned int rx_fifo; diff --git a/drivers/soc/soc_xilinx_zynqmp.c b/drivers/soc/soc_xilinx_zynqmp.c index 786825d920c..d8b4f172a39 100644 --- a/drivers/soc/soc_xilinx_zynqmp.c +++ b/drivers/soc/soc_xilinx_zynqmp.c @@ -44,6 +44,7 @@ enum { ZYNQMP_VARIANT_DR = BIT(3), ZYNQMP_VARIANT_DR_SE = BIT(4), ZYNQMP_VARIANT_EG_SE = BIT(5), + ZYNQMP_VARIANT_TEG = BIT(6), }; struct zynqmp_device { @@ -75,6 +76,11 @@ static const struct zynqmp_device zynqmp_devices[] = { .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG, }, { + .id = 0x04718093, + .device = 3, + .variants = ZYNQMP_VARIANT_TEG, + }, + { .id = 0x04721093, .device = 4, .variants = ZYNQMP_VARIANT_EG | ZYNQMP_VARIANT_CG | @@ -299,6 +305,8 @@ static int soc_xilinx_zynqmp_detect_machine(struct udevice *dev, u32 idcode, strlcat(priv->machine, "dr", sizeof(priv->machine)); } else if (device->variants & ZYNQMP_VARIANT_DR_SE) { strlcat(priv->machine, "dr_SE", sizeof(priv->machine)); + } else if (device->variants & ZYNQMP_VARIANT_TEG) { + strlcat(priv->machine, "teg", sizeof(priv->machine)); } return 0; diff --git a/drivers/sysreset/sysreset-ti-sci.c b/drivers/sysreset/sysreset-ti-sci.c index 5fc05c46cb0..0de132633a8 100644 --- a/drivers/sysreset/sysreset-ti-sci.c +++ b/drivers/sysreset/sysreset-ti-sci.c @@ -60,15 +60,9 @@ static struct sysreset_ops ti_sci_sysreset_ops = { .request = ti_sci_sysreset_request, }; -static const struct udevice_id ti_sci_sysreset_of_match[] = { - { .compatible = "ti,sci-sysreset", }, - { /* sentinel */ }, -}; - U_BOOT_DRIVER(ti_sci_sysreset) = { .name = "ti-sci-sysreset", .id = UCLASS_SYSRESET, - .of_match = ti_sci_sysreset_of_match, .probe = ti_sci_sysreset_probe, .priv_auto = sizeof(struct ti_sci_sysreset_data), .ops = &ti_sci_sysreset_ops, diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b60661fe05e..910c5f3352b 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -685,6 +685,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, reset_ep(udev, ep_index); ring = virt_dev->eps[ep_index].ring; + if (!ring) + return -EINVAL; + /* * How much data is (potentially) left before the 64KB boundary? * XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec) @@ -871,6 +874,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, ep_index = usb_pipe_ep_index(pipe); ep_ring = virt_dev->eps[ep_index].ring; + if (!ep_ring) + return -EINVAL; /* * Check to see if the max packet size for the default control diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d13cbff9b37..741e186ee05 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -475,67 +475,34 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) } /** - * Configure the endpoint, programming the device contexts. + * Fill endpoint contexts for interface descriptor ifdesc. * - * @param udev pointer to the USB device structure - * Return: returns the status of the xhci_configure_endpoints + * @param udev pointer to the USB device structure + * @param ctrl pointer to the xhci pravte device structure + * @param virt_dev pointer to the xhci virtual device structure + * @param ifdesc pointer to the USB interface config descriptor + * Return: returns the status of xhci_init_ep_contexts_if */ -static int xhci_set_configuration(struct usb_device *udev) +static int xhci_init_ep_contexts_if(struct usb_device *udev, + struct xhci_ctrl *ctrl, + struct xhci_virt_device *virt_dev, + struct usb_interface *ifdesc + ) { - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM]; int cur_ep; - int max_ep_flag = 0; int ep_index; unsigned int dir; unsigned int ep_type; - struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); - int num_of_ep; - int ep_flag = 0; u64 trb_64 = 0; - int slot_id = udev->slot_id; - struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; - struct usb_interface *ifdesc; u32 max_esit_payload; unsigned int interval; unsigned int mult; unsigned int max_burst; unsigned int avg_trb_len; unsigned int err_count = 0; + int num_of_ep = ifdesc->no_of_ep; - out_ctx = virt_dev->out_ctx; - in_ctx = virt_dev->in_ctx; - - num_of_ep = udev->config.if_desc[0].no_of_ep; - ifdesc = &udev->config.if_desc[0]; - - ctrl_ctx = xhci_get_input_control_ctx(in_ctx); - /* Initialize the input context control */ - ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); - ctrl_ctx->drop_flags = 0; - - /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ - for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { - ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]); - ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); - if (max_ep_flag < ep_flag) - max_ep_flag = ep_flag; - } - - xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); - - /* slot context */ - xhci_slot_copy(ctrl, in_ctx, out_ctx); - slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); - slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK)); - slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); - - xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); - - /* filling up ep contexts */ for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { struct usb_endpoint_descriptor *endpt_desc = NULL; struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL; @@ -561,7 +528,8 @@ static int xhci_set_configuration(struct usb_device *udev) avg_trb_len = max_esit_payload; ep_index = xhci_get_ep_index(endpt_desc); - ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index); + ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx, + ep_index); /* Allocate the ep rings */ virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true); @@ -614,6 +582,72 @@ static int xhci_set_configuration(struct usb_device *udev) } } + return 0; +} + +/** + * Configure the endpoint, programming the device contexts. + * + * @param udev pointer to the USB device structure + * Return: returns the status of the xhci_configure_endpoints + */ +static int xhci_set_configuration(struct usb_device *udev) +{ + struct xhci_container_ctx *out_ctx; + struct xhci_container_ctx *in_ctx; + struct xhci_input_control_ctx *ctrl_ctx; + struct xhci_slot_ctx *slot_ctx; + int err; + int cur_ep; + int max_ep_flag = 0; + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + int num_of_ep; + int ep_flag = 0; + int slot_id = udev->slot_id; + struct xhci_virt_device *virt_dev = ctrl->devs[slot_id]; + struct usb_interface *ifdesc; + unsigned int ifnum; + unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES, + (unsigned int)udev->config.no_of_if); + + out_ctx = virt_dev->out_ctx; + in_ctx = virt_dev->in_ctx; + + ctrl_ctx = xhci_get_input_control_ctx(in_ctx); + /* Initialize the input context control */ + ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG); + ctrl_ctx->drop_flags = 0; + + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = &udev->config.if_desc[ifnum]; + num_of_ep = ifdesc->no_of_ep; + /* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */ + for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) { + ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]); + ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1)); + if (max_ep_flag < ep_flag) + max_ep_flag = ep_flag; + } + } + + xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size); + + /* slot context */ + xhci_slot_copy(ctrl, in_ctx, out_ctx); + slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx); + slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK)); + slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0); + + xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0); + + /* filling up ep contexts */ + for (ifnum = 0; ifnum < max_ifnum; ifnum++) { + ifdesc = &udev->config.if_desc[ifnum]; + err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc); + if (err < 0) + return err; + } + return xhci_configure_endpoints(udev, false); } diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6f319ba0d54..39c82521be1 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -180,6 +180,7 @@ config CONSOLE_ROTATION config CONSOLE_TRUETYPE bool "Support a console that uses TrueType fonts" + select X86_HARDFP if X86 help TrueTrype fonts can provide outline-drawing capability rather than needing to provide a bitmap for each font and size that is needed. diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 362458aecd4..28665a32757 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -8,6 +8,7 @@ #include <dm.h> #include <log.h> #include <malloc.h> +#include <spl.h> #include <video.h> #include <video_console.h> @@ -802,6 +803,9 @@ static int truetype_entry_save(struct udevice *dev, struct abuf *buf) struct console_tt_store store; const uint size = sizeof(store); + if (spl_phase() <= PHASE_SPL) + return -ENOSYS; + /* * store the whole priv structure as it is simpler that picking out * what we need @@ -823,6 +827,9 @@ static int truetype_entry_restore(struct udevice *dev, struct abuf *buf) struct console_tt_priv *priv = dev_get_priv(dev); struct console_tt_store store; + if (spl_phase() <= PHASE_SPL) + return -ENOSYS; + memcpy(&store, abuf_data(buf), sizeof(store)); vc_priv->xcur_frac = store.cur.xpos_frac; @@ -847,6 +854,9 @@ static int truetype_set_cursor_visible(struct udevice *dev, bool visible, uint out, val; int ret; + if (spl_phase() <= PHASE_SPL) + return -ENOSYS; + if (!visible) return 0; diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 5f89f6a5219..5d06e51ff23 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -126,6 +126,7 @@ void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y) priv->xcur_frac = VID_TO_POS(x); priv->xstart_frac = priv->xcur_frac; priv->ycur = y; + vidconsole_entry_start(dev); } /** @@ -135,8 +136,10 @@ void vidconsole_set_cursor_pos(struct udevice *dev, int x, int y) * @row: new row * @col: new column */ -static void set_cursor_position(struct vidconsole_priv *priv, int row, int col) +static void set_cursor_position(struct udevice *dev, int row, int col) { + struct vidconsole_priv *priv = dev_get_uclass_priv(dev); + /* * Ensure we stay in the bounds of the screen. */ @@ -145,9 +148,7 @@ static void set_cursor_position(struct vidconsole_priv *priv, int row, int col) if (col >= priv->cols) col = priv->cols - 1; - priv->ycur = row * priv->y_charsize; - priv->xcur_frac = priv->xstart_frac + - VID_TO_POS(col * priv->x_charsize); + vidconsole_position_cursor(dev, col, row); } /** @@ -194,7 +195,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) int row = priv->row_saved; int col = priv->col_saved; - set_cursor_position(priv, row, col); + set_cursor_position(dev, row, col); priv->escape = 0; return; } @@ -256,7 +257,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) if (row < 0) row = 0; /* Right and bottom overflows are handled in the callee. */ - set_cursor_position(priv, row, col); + set_cursor_position(dev, row, col); break; } case 'H': @@ -280,7 +281,7 @@ static void vidconsole_escape_char(struct udevice *dev, char ch) if (col) --col; - set_cursor_position(priv, row, col); + set_cursor_position(dev, row, col); break; } diff --git a/env/Kconfig b/env/Kconfig index 7885c8bf831..1f8e90af55e 100644 --- a/env/Kconfig +++ b/env/Kconfig @@ -472,7 +472,7 @@ config ENV_FAT_DEVICE_AND_PART string "Device and partition for where to store the environemt in FAT" depends on ENV_IS_IN_FAT default "0:1" if TI_COMMON_CMD_OPTIONS - default "0:auto" if ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL + default "0:auto" if ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL || ARCH_VERSAL_NET default ":auto" if ARCH_SUNXI default "0" if ARCH_AT91 help diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 365c5147c4b..2ff0dca2495 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -765,11 +765,6 @@ int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags) struct ext2_inode *first_inode = NULL; struct ext2_inode temp_inode; - if (*dirname != '/') { - printf("Please supply Absolute path\n"); - return -1; - } - /* TODO: input validation make equivalent to linux */ depth_dirname = zalloc(strlen(dirname) + 1); if (!depth_dirname) diff --git a/fs/ext4/ext4_journal.c b/fs/ext4/ext4_journal.c index 1a340b4764c..e80f797c8dc 100644 --- a/fs/ext4/ext4_journal.c +++ b/fs/ext4/ext4_journal.c @@ -430,7 +430,7 @@ int ext4fs_check_journal_state(int recovery_flag) printf("Recovery required\n"); } else { if (recovery_flag == RECOVER) - printf("File System is consistent\n"); + log_debug("File System is consistent\n"); goto end; } diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c index ea4c5d4157c..d057f6b5a79 100644 --- a/fs/ext4/ext4_write.c +++ b/fs/ext4/ext4_write.c @@ -847,6 +847,7 @@ int ext4fs_write(const char *fname, const char *buffer, { int ret = 0; struct ext2_inode *file_inode = NULL; + struct ext2_inode *existing_file_inode = NULL; unsigned char *inode_buffer = NULL; int parent_inodeno; int inodeno; @@ -900,6 +901,15 @@ int ext4fs_write(const char *fname, const char *buffer, /* check if the filename is already present in root */ existing_file_inodeno = ext4fs_filename_unlink(filename); if (existing_file_inodeno != -1) { + existing_file_inode = (struct ext2_inode *)zalloc(fs->inodesz); + if (!existing_file_inode) + goto fail; + ret = ext4fs_iget(existing_file_inodeno, existing_file_inode); + if (ret) { + free(existing_file_inode); + goto fail; + } + ret = ext4fs_delete_file(existing_file_inodeno); fs->first_pass_bbmap = 0; fs->curr_blkno = 0; @@ -948,9 +958,15 @@ int ext4fs_write(const char *fname, const char *buffer, sizebytes = 0; } } else { - file_inode->mode = cpu_to_le16(S_IFREG | S_IRWXU | S_IRGRP | - S_IROTH | S_IXGRP | S_IXOTH); + if (existing_file_inode) { + file_inode->mode = existing_file_inode->mode; + } else { + file_inode->mode = cpu_to_le16(S_IFREG | S_IRWXU | S_IRGRP | + S_IROTH | S_IXGRP | S_IXOTH); + } } + if (existing_file_inode) + free(existing_file_inode); /* ToDo: Update correct time */ file_inode->mtime = cpu_to_le32(timestamp); file_inode->atime = cpu_to_le32(timestamp); diff --git a/fs/zfs/dev.c b/fs/zfs/dev.c index 251e7d1f74f..fcd9893b3ac 100644 --- a/fs/zfs/dev.c +++ b/fs/zfs/dev.c @@ -26,5 +26,5 @@ void zfs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info) int zfs_devread(int sector, int byte_offset, int byte_len, char *buf) { return fs_devread(zfs_blk_desc, part_info, sector, byte_offset, - byte_len, buf); + byte_len, buf) ? 0 : 1; } diff --git a/fs/zfs/zfs.c b/fs/zfs/zfs.c index 1fec96cd5ce..bfc11fa6676 100644 --- a/fs/zfs/zfs.c +++ b/fs/zfs/zfs.c @@ -655,7 +655,7 @@ dmu_read(dnode_end_t *dn, uint64_t blkid, void **buf, dn->endian) << SPA_MINBLOCKSHIFT; *buf = malloc(size); - if (*buf) { + if (!*buf) { err = ZFS_ERR_OUT_OF_MEMORY; break; } @@ -1559,6 +1559,10 @@ nvlist_find_value(char *nvlist, char *name, int valtype, char **val, return 0; } +int is_word_aligned_ptr(void *ptr) { + return ((uintptr_t)ptr & (sizeof(void *) - 1)) == 0; +} + int zfs_nvlist_lookup_uint64(char *nvlist, char *name, uint64_t *out) { @@ -1574,6 +1578,20 @@ zfs_nvlist_lookup_uint64(char *nvlist, char *name, uint64_t *out) return ZFS_ERR_BAD_FS; } + /* On arm64, calling be64_to_cpu() on a value stored at a memory address + * that's not 8-byte aligned causes the CPU to reset. Avoid that by copying the + * value somewhere else if needed. + */ + if (!is_word_aligned_ptr((void *)nvpair)) { + uint64_t *alignedptr = malloc(sizeof(uint64_t)); + if (!alignedptr) + return 0; + memcpy(alignedptr, nvpair, sizeof(uint64_t)); + *out = be64_to_cpu(*alignedptr); + free(alignedptr); + return 1; + } + *out = be64_to_cpu(*(uint64_t *) nvpair); return 1; } @@ -1617,6 +1635,11 @@ zfs_nvlist_lookup_nvlist(char *nvlist, char *name) &size, 0); if (!found) return 0; + + /* Allocate 12 bytes in addition to the nvlist size: One uint32 before the + * nvlist to hold the encoding method, and two zero uint32's after the + * nvlist as the NULL terminator. + */ ret = calloc(1, size + 3 * sizeof(uint32_t)); if (!ret) return 0; @@ -2112,7 +2135,7 @@ zfs_read(zfs_file_t file, char *buf, uint64_t len) * Find requested blkid and the offset within that block. */ uint64_t blkid = file->offset + red; - blkid = do_div(blkid, blksz); + uint64_t blkoff = do_div(blkid, blksz); free(data->file_buf); data->file_buf = 0; @@ -2127,8 +2150,7 @@ zfs_read(zfs_file_t file, char *buf, uint64_t len) movesize = min(length, data->file_end - (int)file->offset - red); - memmove(buf, data->file_buf + file->offset + red - - data->file_start, movesize); + memmove(buf, data->file_buf + blkoff, movesize); buf += movesize; length -= movesize; red += movesize; diff --git a/include/bootm.h b/include/bootm.h index 9e0f8d60de0..6983375ff8b 100644 --- a/include/bootm.h +++ b/include/bootm.h @@ -273,21 +273,24 @@ int bootm_process_cmdline(char *buf, int maxlen, int flags); int bootm_process_cmdline_env(int flags); /** - * zboot_start() - Boot a zimage + * zboot_run() - Run through the various steps to boot a zimage * * Boot a zimage, given the component parts * * @addr: Address where the bzImage is moved before booting, either * BZIMAGE_LOAD_ADDR or ZIMAGE_LOAD_ADDR - * @base: Pointer to the boot parameters, typically at address - * DEFAULT_SETUP_BASE + * @size: Size of bzImage, or 0 to detect this * @initrd: Address of the initial ramdisk, or 0 if none * @initrd_size: Size of the initial ramdisk, or 0 if none - * @cmdline: Command line to use for booting + * @base_addr: If non-zero, this indicates that the boot parameters have already + * been loaded by the caller to this address, so the load_zimage() call + * in zboot_load() will be skipped when booting + * @cmdline: If non-NULL, the environment variable containing the command line + * to use for booting * Return: -EFAULT on error (normally it does not return) */ -int zboot_start(ulong addr, ulong size, ulong initrd, ulong initrd_size, - ulong base, char *cmdline); +int zboot_run(ulong addr, ulong size, ulong initrd, ulong initrd_size, + ulong base, char *cmdline); /* * zimage_get_kernel_version() - Get the version string from a kernel @@ -314,7 +317,7 @@ void zimage_dump(struct boot_params *base_ptr, bool show_cmdline); * bootm_boot_start() - Boot an image at the given address * * @addr: Image address - * @cmdline: Command line to set + * @cmdline: Command line to set, NULL for default */ int bootm_boot_start(ulong addr, const char *cmdline); diff --git a/include/efi_loader.h b/include/efi_loader.h index 7daca0afba2..bb51c028177 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -345,9 +345,6 @@ extern const efi_guid_t smbios3_guid; extern const efi_guid_t efi_guid_text_input_protocol; extern const efi_guid_t efi_guid_text_output_protocol; -extern char __efi_runtime_start[], __efi_runtime_stop[]; -extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[]; - /** * struct efi_open_protocol_info_item - open protocol info item * diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h index b21c5cb3dd6..a75b5a35b6e 100644 --- a/include/efi_tcg2.h +++ b/include/efi_tcg2.h @@ -150,16 +150,14 @@ struct efi_tcg2_final_events_table { * the variable. * @variable_data_length: The size of the variable data. * @unicode_name: The CHAR16 unicode name of the variable - * without NULL-terminator. - * @variable_data: The data parameter of the efi variable - * in the GetVariable() API. + * without NULL-terminator followed by data. */ struct efi_tcg2_uefi_variable_data { efi_guid_t variable_name; u64 unicode_name_length; u64 variable_data_length; - u16 unicode_name[1]; - u8 variable_data[1]; + u16 unicode_name[]; + // u8 variable_data[]; }; /** diff --git a/include/env_default.h b/include/env_default.h index 2ca4a087d3b..8ee500d1709 100644 --- a/include/env_default.h +++ b/include/env_default.h @@ -99,6 +99,17 @@ const char default_environment[] = { #ifdef CONFIG_SYS_SOC "soc=" CONFIG_SYS_SOC "\0" #endif +#ifdef CONFIG_USB_HOST + "usb_ignorelist=" +#ifdef CONFIG_USB_KEYBOARD + /* Ignore Yubico devices. Currently only a single USB keyboard device is + * supported and the emulated HID keyboard Yubikeys present is useless + * as keyboard. + */ + "0x1050:*," +#endif + "\0" +#endif #ifdef CONFIG_ENV_IMPORT_FDT "env_fdt_path=" CONFIG_ENV_FDT_PATH "\0" #endif diff --git a/include/fastboot-internal.h b/include/fastboot-internal.h index 610d4f91414..e59c187c05c 100644 --- a/include/fastboot-internal.h +++ b/include/fastboot-internal.h @@ -6,7 +6,7 @@ /** * fastboot_buf_addr - base address of the fastboot download buffer */ -extern void *fastboot_buf_addr; +extern ulong fastboot_buf_addr; /** * fastboot_buf_size - size of the fastboot download buffer diff --git a/include/fastboot.h b/include/fastboot.h index 1e7920eb913..c75184cc912 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -114,13 +114,13 @@ int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason); */ void fastboot_set_progress_callback(void (*progress)(const char *msg)); -/* +/** * fastboot_init() - initialise new fastboot protocol session * - * @buf_addr: Pointer to download buffer, or NULL for default + * @buf_addr: Address of download buffer, or 0 for default * @buf_size: Size of download buffer, or zero for default */ -void fastboot_init(void *buf_addr, u32 buf_size); +void fastboot_init(ulong buf_addr, u32 buf_size); /** * fastboot_boot() - Execute fastboot boot command diff --git a/include/image.h b/include/image.h index 21de70f0c9e..acffd17e0df 100644 --- a/include/image.h +++ b/include/image.h @@ -946,7 +946,7 @@ static inline void image_set_name(struct legacy_img_hdr *hdr, const char *name) int image_check_hcrc(const struct legacy_img_hdr *hdr); int image_check_dcrc(const struct legacy_img_hdr *hdr); #ifndef USE_HOSTCC -ulong env_get_bootm_low(void); +phys_addr_t env_get_bootm_low(void); phys_size_t env_get_bootm_size(void); phys_size_t env_get_bootm_mapsize(void); #endif diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index fb002ae6411..4abaf4734cf 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -249,6 +249,13 @@ enum nand_ecc_algo { */ #define NAND_USE_BOUNCE_BUFFER 0x00100000 +/* + * Do not try to tweak the timings at runtime. This is needed when the + * controller initializes the timings on itself or when it relies on + * configuration done by the bootloader. + */ +#define NAND_KEEP_TIMINGS 0x00800000 + /* Options set by nand scan */ /* bbt has already been read */ #define NAND_BBT_SCANNED 0x40000000 diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index 6f479fa5adc..13b5a52f8b9 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -251,6 +251,7 @@ extern const struct spinand_manufacturer paragon_spinand_manufacturer; extern const struct spinand_manufacturer toshiba_spinand_manufacturer; extern const struct spinand_manufacturer winbond_spinand_manufacturer; extern const struct spinand_manufacturer esmt_c8_spinand_manufacturer; +extern const struct spinand_manufacturer xtx_spinand_manufacturer; /** * struct spinand_op_variants - SPI NAND operation variants diff --git a/include/mcheck.h b/include/mcheck.h new file mode 100644 index 00000000000..bd506ae6291 --- /dev/null +++ b/include/mcheck.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.1+ */ +/* + * Copyright (C) 1996-2024 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * <https://www.gnu.org/licenses/>. + */ +#ifndef _MCHECK_H +#define _MCHECK_H 1 + +/* + * Return values for `mprobe': these are the kinds of inconsistencies that + * `mcheck' enables detection of. + */ +enum mcheck_status { + MCHECK_DISABLED = -1, /* Consistency checking is not turned on. */ + MCHECK_OK, /* Block is fine. */ + MCHECK_FREE, /* Block freed twice. */ + MCHECK_HEAD, /* Memory before the block was clobbered. */ + MCHECK_TAIL /* Memory after the block was clobbered. */ +}; + +typedef void (*mcheck_abortfunc_t)(enum mcheck_status, const void *p); + +int mcheck(mcheck_abortfunc_t func); + +/* + * Similar to `mcheck' but performs checks for all block whenever one of + * the memory handling functions is called. This can be very slow. + */ +int mcheck_pedantic(mcheck_abortfunc_t f); + +/* Force check of all blocks now. */ +void mcheck_check_all(void); + +/* + * Check for aberrations in a particular malloc'd block. These are the + * same checks that `mcheck' does, when you free or reallocate a block. + */ +enum mcheck_status mprobe(void *__ptr); + +#endif diff --git a/include/mmc.h b/include/mmc.h index 1022db3ffa7..4b8327f1f93 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -590,7 +590,7 @@ struct mmc_config { uint f_max; uint b_max; unsigned char part_type; -#ifdef CONFIG_MMC_PWRSEQ +#if CONFIG_IS_ENABLED(MMC_PWRSEQ) struct udevice *pwr_dev; #endif }; @@ -736,7 +736,8 @@ struct mmc { * accessing the boot partitions */ u32 quirks; - u8 hs400_tuning; + bool tuning:1; + bool hs400_tuning:1; enum bus_mode user_speed_mode; /* input speed mode from user */ }; @@ -795,7 +796,7 @@ int mmc_unbind(struct udevice *dev); int mmc_initialize(struct bd_info *bis); int mmc_init_device(int num); int mmc_init(struct mmc *mmc); -int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error); +int mmc_send_tuning(struct mmc *mmc, u32 opcode); int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data); int mmc_deinit(struct mmc *mmc); @@ -808,7 +809,7 @@ int mmc_deinit(struct mmc *mmc); */ int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg); -#ifdef CONFIG_MMC_PWRSEQ +#if CONFIG_IS_ENABLED(MMC_PWRSEQ) /** * mmc_pwrseq_get_power() - get a power device from device tree * diff --git a/include/u-boot/zlib.h b/include/u-boot/zlib.h index a33cc8780d3..ee19f460958 100644 --- a/include/u-boot/zlib.h +++ b/include/u-boot/zlib.h @@ -49,9 +49,6 @@ extern "C" { #endif -#define ZLIB_VERSION "1.2.3" -#define ZLIB_VERNUM 0x1230 - /* #include "zconf.h" */ /* included directly here */ /* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2005 Jean-loup Gailly. @@ -484,7 +481,6 @@ typedef gz_header FAR *gz_headerp; #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative * values are errors, positive values are used for special but normal events. */ @@ -523,11 +519,11 @@ typedef gz_header FAR *gz_headerp; ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); + int stream_size)); ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, int windowBits, int memLevel, - int strategy, const char *version, + int strategy, int stream_size)); ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, @@ -553,7 +549,7 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); + int stream_size)); ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input @@ -743,11 +739,11 @@ ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, */ ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); + int stream_size)); #define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) + inflateInit_((strm), sizeof(z_stream)) #define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + inflateInit2_((strm), (windowBits), sizeof(z_stream)) #if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) struct internal_state {int dummy;}; /* hack for buggy compilers */ diff --git a/include/usb.h b/include/usb.h index 09e3f0cb309..3aafdc8bfd1 100644 --- a/include/usb.h +++ b/include/usb.h @@ -49,6 +49,12 @@ extern bool usb_started; /* flag for the started/stopped USB status */ */ #define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000) +/* + * The xhcd hcd driver prepares only a limited number interfaces / endpoints. + * Define this limit so that drivers do not exceed it. + */ +#define USB_MAX_ACTIVE_INTERFACES 2 + /* device request (setup) */ struct devrequest { __u8 requesttype; diff --git a/lib/Kconfig b/lib/Kconfig index 37ac14f7bab..efb77978a65 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -348,7 +348,7 @@ config TRACE Enables function tracing within U-Boot. This allows recording of call traces including timing information. The command can write data to memory for exporting for analysis (e.g. using bootchart). - See doc/README.trace for full details. + See doc/develop/trace.rst for full details. config TRACE_BUFFER_SIZE hex "Size of trace buffer in U-Boot" diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 086521fb287..034e366967f 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -71,11 +71,11 @@ obj-y += efi_string.o obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o obj-y += efi_var_common.o obj-y += efi_var_mem.o -obj-y += efi_var_file.o ifeq ($(CONFIG_EFI_MM_COMM_TEE),y) obj-y += efi_variable_tee.o else obj-y += efi_variable.o +obj-y += efi_var_file.o obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o endif obj-y += efi_watchdog.o diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c index 67bbd2a01c0..67bd7f8ca24 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -41,7 +41,7 @@ efi_status_t efi_acpi_register(void) } addr = gd_acpi_start(); - printf("EFI using ACPI tables at %lx\n", addr); + log_debug("EFI using ACPI tables at %lx\n", addr); /* And expose them to our EFI payload */ return efi_install_configuration_table(&acpi_guid, diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index aba3100c768..12cf23fa3fa 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -15,6 +15,7 @@ #include <watchdog.h> #include <asm/cache.h> #include <asm/global_data.h> +#include <asm/sections.h> #include <linux/list_sort.h> #include <linux/sizes.h> diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index 16b2c3d4882..aa8feffd3ec 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -9,6 +9,7 @@ #include <efi_loader.h> #include <efi_variable.h> #include <stdlib.h> +#include <u-boot/crc.h> enum efi_secure_mode { EFI_MODE_SETUP, @@ -416,3 +417,76 @@ void *efi_get_var(const u16 *name, const efi_guid_t *vendor, efi_uintn_t *size) return buf; } + +/** + * efi_var_collect() - Copy EFI variables mstching attributes mask + * + * @bufp: buffer containing variable collection + * @lenp: buffer length + * @attr_mask: mask of matched attributes + * + * Return: Status code + */ +efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *lenp, + u32 check_attr_mask) +{ + size_t len = EFI_VAR_BUF_SIZE; + struct efi_var_file *buf; + struct efi_var_entry *var, *old_var; + size_t old_var_name_length = 2; + + *bufp = NULL; /* Avoid double free() */ + buf = calloc(1, len); + if (!buf) + return EFI_OUT_OF_RESOURCES; + var = buf->var; + old_var = var; + for (;;) { + efi_uintn_t data_length, var_name_length; + u8 *data; + efi_status_t ret; + + if ((uintptr_t)buf + len <= + (uintptr_t)var->name + old_var_name_length) + return EFI_BUFFER_TOO_SMALL; + + var_name_length = (uintptr_t)buf + len - (uintptr_t)var->name; + memcpy(var->name, old_var->name, old_var_name_length); + guidcpy(&var->guid, &old_var->guid); + ret = efi_get_next_variable_name_int( + &var_name_length, var->name, &var->guid); + if (ret == EFI_NOT_FOUND) + break; + if (ret != EFI_SUCCESS) { + free(buf); + return ret; + } + old_var_name_length = var_name_length; + old_var = var; + + data = (u8 *)var->name + old_var_name_length; + data_length = (uintptr_t)buf + len - (uintptr_t)data; + ret = efi_get_variable_int(var->name, &var->guid, + &var->attr, &data_length, data, + &var->time); + if (ret != EFI_SUCCESS) { + free(buf); + return ret; + } + if ((var->attr & check_attr_mask) == check_attr_mask) { + var->length = data_length; + var = (struct efi_var_entry *)ALIGN((uintptr_t)data + data_length, 8); + } + } + + buf->reserved = 0; + buf->magic = EFI_VAR_FILE_MAGIC; + len = (uintptr_t)var - (uintptr_t)buf; + buf->crc32 = crc32(0, (u8 *)buf->var, + len - sizeof(struct efi_var_file)); + buf->length = len; + *bufp = buf; + *lenp = len; + + return EFI_SUCCESS; +} diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c index 532b6b40eef..413e1794e88 100644 --- a/lib/efi_loader/efi_var_file.c +++ b/lib/efi_loader/efi_var_file.c @@ -52,70 +52,6 @@ static efi_status_t __maybe_unused efi_set_blk_dev_to_system_partition(void) return EFI_SUCCESS; } -efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *lenp, - u32 check_attr_mask) -{ - size_t len = EFI_VAR_BUF_SIZE; - struct efi_var_file *buf; - struct efi_var_entry *var, *old_var; - size_t old_var_name_length = 2; - - *bufp = NULL; /* Avoid double free() */ - buf = calloc(1, len); - if (!buf) - return EFI_OUT_OF_RESOURCES; - var = buf->var; - old_var = var; - for (;;) { - efi_uintn_t data_length, var_name_length; - u8 *data; - efi_status_t ret; - - if ((uintptr_t)buf + len <= - (uintptr_t)var->name + old_var_name_length) - return EFI_BUFFER_TOO_SMALL; - - var_name_length = (uintptr_t)buf + len - (uintptr_t)var->name; - memcpy(var->name, old_var->name, old_var_name_length); - guidcpy(&var->guid, &old_var->guid); - ret = efi_get_next_variable_name_int( - &var_name_length, var->name, &var->guid); - if (ret == EFI_NOT_FOUND) - break; - if (ret != EFI_SUCCESS) { - free(buf); - return ret; - } - old_var_name_length = var_name_length; - old_var = var; - - data = (u8 *)var->name + old_var_name_length; - data_length = (uintptr_t)buf + len - (uintptr_t)data; - ret = efi_get_variable_int(var->name, &var->guid, - &var->attr, &data_length, data, - &var->time); - if (ret != EFI_SUCCESS) { - free(buf); - return ret; - } - if ((var->attr & check_attr_mask) == check_attr_mask) { - var->length = data_length; - var = (struct efi_var_entry *)ALIGN((uintptr_t)data + data_length, 8); - } - } - - buf->reserved = 0; - buf->magic = EFI_VAR_FILE_MAGIC; - len = (uintptr_t)var - (uintptr_t)buf; - buf->crc32 = crc32(0, (u8 *)buf->var, - len - sizeof(struct efi_var_file)); - buf->length = len; - *bufp = buf; - *lenp = len; - - return EFI_SUCCESS; -} - /** * efi_var_to_file() - save non-volatile variables as file * diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 2951dc78c7d..e6c1219a11c 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -163,6 +163,7 @@ static efi_status_t efi_variable_authenticate(const u16 *variable, break; default: /* TODO: support private authenticated variables */ + ret = EFI_UNSUPPORTED; goto err; } diff --git a/lib/gzip.c b/lib/gzip.c index 5d9c19598d5..a9a3df524de 100644 --- a/lib/gzip.c +++ b/lib/gzip.c @@ -67,7 +67,7 @@ int zzip(void *dst, unsigned long *lenp, unsigned char *src, r = deflateInit2_(&s, Z_BEST_SPEED, Z_DEFLATED, window, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - ZLIB_VERSION, sizeof(z_stream)); + sizeof(z_stream)); if (r != Z_OK) { printf ("Error: deflateInit2_() returned %d\n", r); return -1; diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 1007b6979a4..d3b4f71d6be 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -342,7 +342,7 @@ static int rsa_verify_key(struct image_sign_info *info, return -EINVAL; } - debug("Checksum algorithm: %s", checksum->name); + debug("Checksum algorithm: %s\n", checksum->name); /* Sanity check for stack size */ if (sig_len > RSA_MAX_SIG_BITS / 8) { @@ -444,13 +444,13 @@ static int rsa_verify_with_keynode(struct image_sign_info *info, const char *algo; if (node < 0) { - debug("%s: Skipping invalid node", __func__); + debug("%s: Skipping invalid node\n", __func__); return -EBADF; } algo = fdt_getprop(blob, node, "algo", NULL); if (strcmp(info->name, algo)) { - debug("%s: Wrong algo: have %s, expected %s", __func__, + debug("%s: Wrong algo: have %s, expected %s\n", __func__, info->name, algo); return -EFAULT; } @@ -470,7 +470,7 @@ static int rsa_verify_with_keynode(struct image_sign_info *info, prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL); if (!prop.num_bits || !prop.modulus || !prop.rr) { - debug("%s: Missing RSA key info", __func__); + debug("%s: Missing RSA key info\n", __func__); return -EFAULT; } diff --git a/lib/zlib/deflate.c b/lib/zlib/deflate.c index 4549f4dc12a..7e1ed4f9b20 100644 --- a/lib/zlib/deflate.c +++ b/lib/zlib/deflate.c @@ -196,37 +196,30 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); /* ========================================================================= */ -int ZEXPORT deflateInit_(strm, level, version, stream_size) +int ZEXPORT deflateInit_(strm, level, stream_size) z_streamp strm; int level; - const char *version; int stream_size; { return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY, version, stream_size); + Z_DEFAULT_STRATEGY, stream_size); /* To do: ignore strm->next_in if we use it as window */ } /* ========================================================================= */ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, - version, stream_size) + stream_size) z_streamp strm; int level; int method; int windowBits; int memLevel; int strategy; - const char *version; int stream_size; { deflate_state *s; int wrap = 1; - static const char my_version[] = ZLIB_VERSION; - if (version == Z_NULL || version[0] != my_version[0] || - stream_size != sizeof(z_stream)) { - return Z_VERSION_ERROR; - } if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; diff --git a/lib/zlib/inffast.c b/lib/zlib/inffast.c index e3c7f3b892b..5e2a65ad4d2 100644 --- a/lib/zlib/inffast.c +++ b/lib/zlib/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2004 Mark Adler + * Copyright (C) 1995-2008, 2010, 2013 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,25 +12,6 @@ #ifndef ASMINF -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ -#else -# define OFF 1 -# define PUP(a) *++(a) -#endif - /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is @@ -66,12 +47,13 @@ requires strm->avail_out >= 258 for each loop to avoid checking for output space. */ -void inflate_fast(z_streamp strm, unsigned start) -/* start: inflate()'s starting value for strm->avail_out */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ @@ -80,7 +62,7 @@ void inflate_fast(z_streamp strm, unsigned start) #endif unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ + unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ unsigned long hold; /* local strm->hold */ unsigned bits; /* local strm->bits */ @@ -88,7 +70,7 @@ void inflate_fast(z_streamp strm, unsigned start) code const FAR *dcode; /* local strm->distcode */ unsigned lmask; /* mask for first level of length codes */ unsigned dmask; /* mask for first level of distance codes */ - code this; /* retrieved table entry */ + code here; /* retrieved table entry */ unsigned op; /* code bits, operation, extra bits, or */ /* window position, window bytes to copy */ unsigned len; /* match length, unused bytes */ @@ -97,7 +79,7 @@ void inflate_fast(z_streamp strm, unsigned start) /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; + in = strm->next_in; last = in + (strm->avail_in - 5); if (in > last && strm->avail_in > 5) { /* @@ -107,7 +89,7 @@ void inflate_fast(z_streamp strm, unsigned start) strm->avail_in = 0xffffffff - (uintptr_t)in; last = in + (strm->avail_in - 5); } - out = strm->next_out - OFF; + out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT @@ -115,7 +97,7 @@ void inflate_fast(z_streamp strm, unsigned start) #endif wsize = state->wsize; whave = state->whave; - write = state->write; + wnext = state->wnext; window = state->window; hold = state->hold; bits = state->bits; @@ -128,29 +110,29 @@ void inflate_fast(z_streamp strm, unsigned start) input data or output space */ do { if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } - this = lcode[hold & lmask]; + here = lcode[hold & lmask]; dolen: - op = (unsigned)(this.bits); + op = (unsigned)(here.bits); hold >>= op; bits -= op; - op = (unsigned)(this.op); + op = (unsigned)(here.op); if (op == 0) { /* literal */ - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - PUP(out) = (unsigned char)(this.val); + "inflate: literal 0x%02x\n", here.val)); + *out++ = (unsigned char)(here.val); } else if (op & 16) { /* length base */ - len = (unsigned)(this.val); + len = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); @@ -159,25 +141,25 @@ void inflate_fast(z_streamp strm, unsigned start) } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } - this = dcode[hold & dmask]; + here = dcode[hold & dmask]; dodist: - op = (unsigned)(this.bits); + op = (unsigned)(here.bits); hold >>= op; bits -= op; - op = (unsigned)(this.op); + op = (unsigned)(here.op); if (op & 16) { /* distance base */ - dist = (unsigned)(this.val); + dist = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } } @@ -196,108 +178,80 @@ void inflate_fast(z_streamp strm, unsigned start) if (dist > op) { /* see if copy from window */ op = dist - op; /* distance back in window */ if (op > whave) { - strm->msg = (char *)"invalid distance too far back"; + strm->msg = + (char *)"invalid distance too far back"; state->mode = BAD; break; } - from = window - OFF; - if (write == 0) { /* very common case */ + from = window; + if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } - else if (write < op) { /* wrap around window */ - from += wsize + write - op; - op -= write; + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; if (op < len) { /* some from end of window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); - from = window - OFF; - if (write < len) { /* some from start of window */ - op = write; + from = window; + if (wnext < len) { /* some from start of window */ + op = wnext; len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } } else { /* contiguous in window */ - from += write - op; + from += wnext - op; if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } else { - unsigned short *sout; - unsigned long loops; - from = out - dist; /* copy direct from output */ - /* minimum length is three */ - /* Align out addr */ - if (!((long)(out - 1 + OFF) & 1)) { - PUP(out) = PUP(from); - len--; - } - sout = (unsigned short *)(out - OFF); - if (dist > 2 ) { - unsigned short *sfrom; - - sfrom = (unsigned short *)(from - OFF); - loops = len >> 1; - do - PUP(sout) = get_unaligned(++sfrom); - while (--loops); - out = (unsigned char *)sout + OFF; - from = (unsigned char *)sfrom + OFF; - } else { /* dist == 1 or dist == 2 */ - unsigned short pat16; - - pat16 = *(sout-2+2*OFF); - if (dist == 1) -#if defined(__BIG_ENDIAN) - pat16 = (pat16 & 0xff) | ((pat16 & 0xff ) << 8); -#elif defined(__LITTLE_ENDIAN) - pat16 = (pat16 & 0xff00) | ((pat16 & 0xff00 ) >> 8); -#else -#error __BIG_ENDIAN nor __LITTLE_ENDIAN is defined -#endif - loops = len >> 1; - do - PUP(sout) = pat16; - while (--loops); - out = (unsigned char *)sout + OFF; - } - if (len & 1) - PUP(out) = PUP(from); + do { /* minimum length is three */ + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } while (len > 2); + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } } } else if ((op & 64) == 0) { /* 2nd level distance code */ - this = dcode[this.val + (hold & ((1U << op) - 1))]; + here = dcode[here.val + (hold & ((1U << op) - 1))]; goto dodist; } else { @@ -307,7 +261,7 @@ void inflate_fast(z_streamp strm, unsigned start) } } else if ((op & 64) == 0) { /* 2nd level length code */ - this = lcode[this.val + (hold & ((1U << op) - 1))]; + here = lcode[here.val + (hold & ((1U << op) - 1))]; goto dolen; } else if (op & 32) { /* end-of-block */ @@ -329,8 +283,8 @@ void inflate_fast(z_streamp strm, unsigned start) hold &= (1U << bits) - 1; /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; + strm->next_in = in; + strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); @@ -343,7 +297,7 @@ void inflate_fast(z_streamp strm, unsigned start) inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and write == 0 + - Three separate decoding do-loops for direct, window, and wnext == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes diff --git a/lib/zlib/inflate.c b/lib/zlib/inflate.c index 8f767b7b9d2..f7e81fc8b2a 100644 --- a/lib/zlib/inflate.c +++ b/lib/zlib/inflate.c @@ -21,7 +21,7 @@ int ZEXPORT inflateReset(z_streamp strm) state->head = Z_NULL; state->wsize = 0; state->whave = 0; - state->write = 0; + state->wnext = 0; state->hold = 0; state->bits = 0; state->lencode = state->distcode = state->next = state->codes; @@ -30,14 +30,11 @@ int ZEXPORT inflateReset(z_streamp strm) return Z_OK; } -int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, +int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, int stream_size) { struct inflate_state FAR *state; - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; if (strm == Z_NULL) return Z_STREAM_ERROR; strm->msg = Z_NULL; /* in case we return an error */ if (strm->zalloc == (alloc_func)0) { @@ -70,9 +67,9 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, return inflateReset(strm); } -int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) +int ZEXPORT inflateInit_(z_streamp strm, int stream_size) { - return inflateInit2_(strm, DEF_WBITS, version, stream_size); + return inflateInit2_(strm, DEF_WBITS, stream_size); } local void fixedtables(struct inflate_state FAR *state) @@ -115,7 +112,7 @@ local int updatewindow(z_streamp strm, unsigned out) /* if window not in use yet, initialize */ if (state->wsize == 0) { state->wsize = 1U << state->wbits; - state->write = 0; + state->wnext = 0; state->whave = 0; } @@ -123,22 +120,22 @@ local int updatewindow(z_streamp strm, unsigned out) copy = out - strm->avail_out; if (copy >= state->wsize) { zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); - state->write = 0; + state->wnext = 0; state->whave = state->wsize; } else { - dist = state->wsize - state->write; + dist = state->wsize - state->wnext; if (dist > copy) dist = copy; - zmemcpy(state->window + state->write, strm->next_out - copy, dist); + zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); copy -= dist; if (copy) { zmemcpy(state->window, strm->next_out - copy, copy); - state->write = copy; + state->wnext = copy; state->whave = state->wsize; } else { - state->write += dist; - if (state->write == state->wsize) state->write = 0; + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; if (state->whave < state->wsize) state->whave += dist; } } @@ -823,12 +820,12 @@ int ZEXPORT inflate(z_streamp strm, int flush) copy = out - left; if (state->offset > copy) { /* copy from window */ copy = state->offset - copy; - if (copy > state->write) { - copy -= state->write; + if (copy > state->wnext) { + copy -= state->wnext; from = state->window + (state->wsize - copy); } else - from = state->window + (state->write - copy); + from = state->window + (state->wnext - copy); if (copy > state->length) copy = state->length; } else { /* copy from output */ diff --git a/lib/zlib/inflate.h b/lib/zlib/inflate.h index 07bd3e78a7c..2657d611cda 100644 --- a/lib/zlib/inflate.h +++ b/lib/zlib/inflate.h @@ -88,7 +88,7 @@ struct inflate_state { unsigned wbits; /* log base 2 of requested window size */ unsigned wsize; /* window size or zero if not using window */ unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ + unsigned wnext; /* window write index */ unsigned char FAR *window; /* allocated sliding window, if needed */ /* bit accumulator */ unsigned long hold; /* input bit accumulator */ diff --git a/lib/zlib/zutil.c b/lib/zlib/zutil.c index 609aac55ce1..ec21b458fcc 100644 --- a/lib/zlib/zutil.c +++ b/lib/zlib/zutil.c @@ -21,7 +21,6 @@ const char * const z_errmsg[10] = { "data error", /* Z_DATA_ERROR (-3) */ "insufficient memory", /* Z_MEM_ERROR (-4) */ "buffer error", /* Z_BUF_ERROR (-5) */ -"incompatible version",/* Z_VERSION_ERROR (-6) */ ""}; #ifdef DEBUG diff --git a/net/nfs.c b/net/nfs.c index 7a8887ef236..c18282448cc 100644 --- a/net/nfs.c +++ b/net/nfs.c @@ -57,7 +57,8 @@ static int nfs_offset = -1; static int nfs_len; static const ulong nfs_timeout = CONFIG_NFS_TIMEOUT; -static char dirfh[NFS_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */ +static char dirfh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */ +static unsigned int dirfh3_length; /* (variable) length of dirfh when NFSv3 */ static char filefh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle */ static unsigned int filefh3_length; /* (variable) length of filefh when NFSv3 */ @@ -377,9 +378,9 @@ static void nfs_lookup_req(char *fname) rpc_req(PROG_NFS, NFS_LOOKUP, data, len); } else { /* NFS_V3 */ - *p++ = htonl(NFS_FHSIZE); /* Dir handle length */ - memcpy(p, dirfh, NFS_FHSIZE); - p += (NFS_FHSIZE / 4); + *p++ = htonl(dirfh3_length); /* Dir handle length */ + memcpy(p, dirfh, dirfh3_length); + p += (dirfh3_length / 4); *p++ = htonl(fnamelen); if (fnamelen & 3) *(p + fnamelen / 4) = 0; @@ -565,7 +566,14 @@ static int nfs_mount_reply(uchar *pkt, unsigned len) fs_mounted = 1; /* NFSv2 and NFSv3 use same structure */ - memcpy(dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE); + if (choosen_nfs_version != NFS_V3) { + memcpy(dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE); + } else { + dirfh3_length = ntohl(rpc_pkt.u.reply.data[1]); + if (dirfh3_length > NFS3_FHSIZE) + dirfh3_length = NFS3_FHSIZE; + memcpy(dirfh, rpc_pkt.u.reply.data + 2, dirfh3_length); + } return 0; } diff --git a/net/wget.c b/net/wget.c index 817c5ebd5d0..abab371e58e 100644 --- a/net/wget.c +++ b/net/wget.c @@ -50,6 +50,7 @@ static unsigned long content_length; static unsigned int packets; static unsigned int initial_data_seq_num; +static unsigned int next_data_seq_num; static enum wget_state current_wget_state; @@ -272,17 +273,18 @@ static void wget_connected(uchar *pkt, unsigned int tcp_seq_num, current_wget_state = WGET_TRANSFERRING; + initial_data_seq_num = tcp_seq_num + hlen; + next_data_seq_num = tcp_seq_num + len; + if (strstr((char *)pkt, http_ok) == 0) { debug_cond(DEBUG_WGET, "wget: Connected Bad Xfer\n"); - initial_data_seq_num = tcp_seq_num + hlen; wget_loop_state = NETLOOP_FAIL; wget_send(action, tcp_seq_num, tcp_ack_num, len); } else { debug_cond(DEBUG_WGET, "wget: Connctd pkt %p hlen %x\n", pkt, hlen); - initial_data_seq_num = tcp_seq_num + hlen; pos = strstr((char *)pkt, content_len); if (!pos) { @@ -396,9 +398,13 @@ static void wget_handler(uchar *pkt, u16 dport, "wget: Transferring, seq=%x, ack=%x,len=%x\n", tcp_seq_num, tcp_ack_num, len); - if (tcp_seq_num >= initial_data_seq_num && - store_block(pkt, tcp_seq_num - initial_data_seq_num, - len) != 0) { + if (next_data_seq_num != tcp_seq_num) { + debug_cond(DEBUG_WGET, "wget: seq=%x packet was lost\n", next_data_seq_num); + return; + } + next_data_seq_num = tcp_seq_num + len; + + if (store_block(pkt, tcp_seq_num - initial_data_seq_num, len) != 0) { wget_fail("wget: store error\n", tcp_seq_num, tcp_ack_num, action); net_set_state(NETLOOP_FAIL); diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl index d074ba23500..1868f1beef6 100644 --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@ -381,6 +381,11 @@ $(obj)/$(BOARD)-spl.bin: $(obj)/u-boot-spl.bin $(objtree)/tools/mkexynosspl) $(VAR_SIZE_PARAM) $< $@ endif +$(obj)/u-boot-spl.ldr: $(obj)/u-boot-spl + $(CREATE_LDR_ENV) + $(LDR) -T $(CONFIG_LDR_CPU) -c $@ $< $(LDR_FLAGS) + $(BOARD_SIZE_CHECK) + quiet_cmd_objcopy = OBJCOPY $@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ @@ -575,7 +580,7 @@ endif SPL_OF_LIST_TARGETS = $(patsubst %,dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) SHRUNK_ARCH_DTB = $(addprefix $(obj)/,$(SPL_OF_LIST_TARGETS)) -$(dir $(SHRUNK_ARCH_DTB)): +$(sort $(dir $(SHRUNK_ARCH_DTB))): $(shell [ -d $@ ] || mkdir -p $@) .SECONDEXPANSION: diff --git a/test/py/test.py b/test/py/test.py index 95859a66e29..7c477903d6b 100755 --- a/test/py/test.py +++ b/test/py/test.py @@ -11,7 +11,6 @@ import os import os.path import sys import pytest -from pkg_resources import load_entry_point if __name__ == '__main__': # argv; py.test test_directory_name user-supplied-arguments diff --git a/test/py/tests/test_scsi.py b/test/py/tests/test_scsi.py index be2e283e7d2..445693cafd7 100644 --- a/test/py/tests/test_scsi.py +++ b/test/py/tests/test_scsi.py @@ -87,6 +87,6 @@ def test_scsi_dev(u_boot_console): def test_scsi_part(u_boot_console): test_scsi_dev(u_boot_console) output = u_boot_console.run_command('scsi part') - assert 'Partition Map for SCSI device' in output + assert 'Partition Map for scsi device' in output output = u_boot_console.run_command('echo $?') assert output.endswith('0') diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py index fe81a1f51b1..c6df64c5316 100644 --- a/tools/binman/btool/openssl.py +++ b/tools/binman/btool/openssl.py @@ -283,6 +283,7 @@ emailAddress = {req_dist_name_dict['emailAddress']} basicConstraints = CA:true 1.3.6.1.4.1.294.1.3=ASN1:SEQUENCE:swrv 1.3.6.1.4.1.294.1.9=ASN1:SEQUENCE:ext_boot_info +1.3.6.1.4.1.294.1.8=ASN1:SEQUENCE:debug [swrv] swrv=INTEGER:{sw_rev} @@ -323,6 +324,12 @@ compSize = INTEGER:{imagesize_sysfw_data} shaType = OID:{sha_type} shaValue = FORMAT:HEX,OCT:{hashval_sysfw_data} +[ debug ] +debugUID = FORMAT:HEX,OCT:0000000000000000000000000000000000000000000000000000000000000000 +debugType = INTEGER:4 +coreDbgEn = INTEGER:0 +coreDbgSecEn = INTEGER:0 + {sysfw_inner_cert_ext_boot_block} {dm_data_ext_boot_block} diff --git a/tools/binman/etype/ti_board_config.py b/tools/binman/etype/ti_board_config.py index 2c3bb8f7b56..c10d66edcb1 100644 --- a/tools/binman/etype/ti_board_config.py +++ b/tools/binman/etype/ti_board_config.py @@ -248,7 +248,7 @@ class Entry_ti_board_config(Entry_section): yaml_config = config.YamlLintConfig("extends: default") for p in yamllint.linter.run(open(self._config_file, "r"), yaml_config): - self.Raise(f"Yamllint error: {p.line}: {p.rule}") + self.Raise(f"Yamllint error: Line {p.line} in {self._config_file}: {p.rule}") try: validate(self.file_yaml, self.schema_yaml) except Exception as e: diff --git a/tools/fit_image.c b/tools/fit_image.c index beef1fa86e2..0fccfbb4ebd 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -137,7 +137,7 @@ static int fdt_property_file(struct image_tool_params *params, int ret; int fd; - fd = open(fname, O_RDWR | O_BINARY); + fd = open(fname, O_RDONLY | O_BINARY); if (fd < 0) { fprintf(stderr, "%s: Can't open %s: %s\n", params->cmdname, fname, strerror(errno)); diff --git a/tools/image-host.c b/tools/image-host.c index b2a0f2e6d16..7bfc0cb6b18 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -346,17 +346,17 @@ static int fit_image_read_key_iv_data(const char *keydir, const char *key_iv_nam unsigned char *key_iv_data, int expected_size) { char filename[PATH_MAX]; - int ret = -1; + int ret; ret = snprintf(filename, sizeof(filename), "%s/%s%s", keydir, key_iv_name, ".bin"); if (ret >= sizeof(filename)) { - printf("Can't format the key or IV filename when setting up the cipher: insufficient buffer space\n"); - ret = -1; + fprintf(stderr, "Can't format the key or IV filename when setting up the cipher: insufficient buffer space\n"); + return -1; } if (ret < 0) { - printf("Can't format the key or IV filename when setting up the cipher: snprintf error\n"); - ret = -1; + fprintf(stderr, "Can't format the key or IV filename when setting up the cipher: snprintf error\n"); + return -1; } ret = fit_image_read_data(filename, key_iv_data, expected_size); diff --git a/tools/proftool.c b/tools/proftool.c index fca45e4a5af..c2e38099354 100644 --- a/tools/proftool.c +++ b/tools/proftool.c @@ -290,7 +290,7 @@ static void usage(void) "Options:\n" " -c <cfg>\tSpecify config file\n" " -f <subtype>\tSpecify output subtype\n" - " -m <map>\tSpecify Systen.map file\n" + " -m <map>\tSpecify System.map file\n" " -o <fname>\tSpecify output file\n" " -t <fname>\tSpecify trace data file (from U-Boot 'trace calls')\n" " -v <0-4>\tSpecify verbosity\n" @@ -306,7 +306,7 @@ static void usage(void) } /** - * h_cmp_offset - bsearch() function to compare two functions bny their offset + * h_cmp_offset - bsearch() function to compare two functions by their offset * * @v1: Pointer to first function (struct func_info) * @v2: Pointer to second function (struct func_info) @@ -431,7 +431,7 @@ static struct func_info *find_func_by_offset(uint offset) static struct func_info *find_caller_by_offset(uint offset) { int low; /* least function that could be a match */ - int high; /* greated function that could be a match */ + int high; /* greatest function that could be a match */ struct func_info key; low = 0; @@ -1352,7 +1352,7 @@ static int write_pages(struct twriter *tw, enum out_format_t out_format, } if (!(func->flags & FUNCF_TRACE)) { - debug("Funcion '%s' is excluded from trace\n", + debug("Function '%s' is excluded from trace\n", func->name); skip_count++; continue; @@ -1781,7 +1781,8 @@ static int make_flame_tree(enum out_format_t out_format, * * This works by maintaining a string shared across all recursive calls. The * function name for this node is added to the existing string, to make up the - * full call-stack description. For example, on entry, @str might contain: + * full call-stack description. For example, on entry, @str_buf->data might + * contain: * * "initf_bootstage;bootstage_mark_name" * ^ @base @@ -1795,18 +1796,18 @@ static int make_flame_tree(enum out_format_t out_format, * @fout: Output file * @out_format: Output format to use * @node: Node to output (pass the whole tree at first) - * @str: String to use to build the output line (e.g. 500 charas long) - * @maxlen: Maximum length of string + * @str_buf: String buffer to use to build the output line * @base: Current base position in the string * @treep: Returns the resulting flamegraph tree * Returns 0 if OK, -1 on error */ static int output_tree(FILE *fout, enum out_format_t out_format, - const struct flame_node *node, char *str, int maxlen, + const struct flame_node *node, struct abuf *str_buf, int base) { const struct flame_node *child; int pos; + char *str = abuf_data(str_buf); if (node->count) { if (out_format == OUT_FMT_FLAMEGRAPH_CALLS) { @@ -1832,18 +1833,29 @@ static int output_tree(FILE *fout, enum out_format_t out_format, if (pos) str[pos++] = ';'; list_for_each_entry(child, &node->child_head, sibling_node) { - int len; + int len, needed; len = strlen(child->func->name); - if (pos + len + 1 >= maxlen) { - fprintf(stderr, "String too short (%d chars)\n", - maxlen); - return -1; + needed = pos + len + 1; + if (needed > abuf_size(str_buf)) { + /* + * We need to re-allocate the string buffer; increase + * its size by multiples of 500 characters. + */ + needed = 500 * ((needed / 500) + 1); + if (!abuf_realloc(str_buf, needed)) + return -1; + str = abuf_data(str_buf); + memset(str + pos, 0, abuf_size(str_buf) - pos); } strcpy(str + pos, child->func->name); - if (output_tree(fout, out_format, child, str, maxlen, - pos + len)) + if (output_tree(fout, out_format, child, str_buf, pos + len)) return -1; + /* + * Update our pointer as the string buffer might have been + * re-allocated. + */ + str = abuf_data(str_buf); } return 0; @@ -1859,16 +1871,24 @@ static int output_tree(FILE *fout, enum out_format_t out_format, static int make_flamegraph(FILE *fout, enum out_format_t out_format) { struct flame_node *tree; - char str[500]; + struct abuf str_buf; + char *str; + int ret = 0; if (make_flame_tree(out_format, &tree)) return -1; - *str = '\0'; - if (output_tree(fout, out_format, tree, str, sizeof(str), 0)) + abuf_init(&str_buf); + if (!abuf_realloc(&str_buf, 500)) return -1; - return 0; + str = abuf_data(&str_buf); + memset(str, 0, abuf_size(&str_buf)); + if (output_tree(fout, out_format, tree, &str_buf, 0)) + ret = -1; + + abuf_uninit(&str_buf); + return ret; } /** |