diff options
216 files changed, 8421 insertions, 3529 deletions
@@ -42,6 +42,7 @@ Durga Challa <durga.challa@amd.com> <vnsl.durga.challa@xilinx.com> Eugen Hristev <eugen.hristev@linaro.org> <eugen.hristev@microchip.com> Eugen Hristev <eugen.hristev@linaro.org> <eugen.hristev@collabora.com> Fabio Estevam <fabio.estevam@nxp.com> +Greg Malysa <malysagreg@gmail.com> <greg.malysa@timesys.com> Harini Katakam <harini.katakam@amd.com> <harini.katakam@xilinx.com> Harsha <harsha.harsha@amd.com> <harsha.harsha@xilinx.com> Heiko Stuebner <heiko.stuebner@cherry.de> <heiko.stuebner@theobroma-systems.com> @@ -123,6 +124,7 @@ Srinivas Neeli <srinivas.neeli@amd.com> <srinivas.neeli@xilinx.com> Stefan Roese <sr@denx.de> <stroese> Stefano Babic <sbabic@denx.de> Stefano Stabellini <stefano.stabellini@amd.com> <stefano.stabellini@xilinx.com> +Sumit Garg <sumit.garg@kernel.org> <sumit.garg@linaro.org> Tom Rini <trini@konsulko.com> <trini@ti.com> Tomas Thoresen <tomas.thoresen@amd.com> <tomast@xilinx.com> TsiChung Liew <Tsi-Chung.Liew@freescale.com> diff --git a/MAINTAINERS b/MAINTAINERS index 687262b355d..e2339ecd2d0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -617,7 +617,7 @@ F: arch/arm/dts/am335x-sancloud* ARM SC5XX M: Nathan Barrett-Morrison <nathan.morrison@timesys.com> -M: Greg Malysa <greg.malysa@timesys.com> +M: Greg Malysa <malysagreg@gmail.com> M: Ian Roberts <ian.roberts@timesys.com> M: Vasileios Bimpikas <vasileios.bimpikas@analog.com> M: Utsav Agarwal <utsav.agarwal@analog.com> @@ -631,17 +631,30 @@ F: arch/arm/mach-sc5xx/ F: board/adi/ F: doc/device-tree-bindings/arm/adi/adi,sc5xx.yaml F: doc/device-tree-bindings/clock/adi,sc5xx-clocks.yaml +F: doc/device-tree-bindings/pinctrl/adi,adsp-pinctrl.yaml F: doc/device-tree-bindings/timer/adi,sc5xx-gptimer.yaml F: drivers/clk/adi/ +F: drivers/dma/adi_dma.c +F: drivers/gpio/adp5588_gpio.c +F: drivers/gpio/gpio-adi-adsp.c +F: drivers/i2c/adi_i2c.c +F: drivers/mmc/adi_sdhci.c +F: drivers/net/dwc_eth_qos_adi.c +F: drivers/pinctrl/pinctrl-adi-adsp.c +F: drivers/remoteproc/adi_sc5xx_rproc.c F: drivers/serial/serial_adi_uart4.c +F: drivers/spi/adi_spi3.c F: drivers/timer/adi_sc5xx_timer.c +F: drivers/usb/musb-new/sc5xx.c +F: drivers/watchdog/adi_wdt.c F: include/configs/sc5* +F: include/dt-bindings/pinctrl/adi-adsp.h F: include/env/adi/ ARM SNAPDRAGON M: Caleb Connolly <caleb.connolly@linaro.org> M: Neil Armstrong <neil.armstrong@linaro.org> -R: Sumit Garg <sumit.garg@linaro.org> +R: Sumit Garg <sumit.garg@kernel.org> L: u-boot-qcom@groups.io S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-snapdragon.git @@ -1045,9 +1058,10 @@ F: common/cyclic.c F: include/cyclic.h DEVICETREE REBASING SUBTREE -M: Sumit Garg <sumit.garg@linaro.org> +M: Sumit Garg <sumit.garg@kernel.org> S: Maintained F: dts/upstream/ +N: OF_UPSTREAM DFU M: Lukasz Majewski <lukma@denx.de> @@ -1453,7 +1467,7 @@ S: Maintained F: tools/patman/ PCIe DWC IMX -M: Sumit Garg <sumit.garg@linaro.org> +M: Sumit Garg <sumit.garg@kernel.org> S: Maintained F: drivers/pci/pcie_dw_imx.c F: drivers/phy/phy-imx8m-pcie.c @@ -3,7 +3,7 @@ VERSION = 2025 PATCHLEVEL = 04 SUBLEVEL = -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = # *DOCUMENTATION* @@ -829,7 +829,7 @@ KBUILD_HOSTCFLAGS += $(if $(CONFIG_TOOLS_DEBUG),-g) UBOOTINCLUDE := \ -Iinclude \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ - $(if $(CONFIG_MBEDTLS_LIB), \ + $(if $(CONFIG_$(XPL_)MBEDTLS_LIB), \ "-DMBEDTLS_CONFIG_FILE=\"mbedtls_def_config.h\"" \ -I$(srctree)/lib/mbedtls \ -I$(srctree)/lib/mbedtls/port \ @@ -878,7 +878,6 @@ libs-y += drivers/usb/dwc3/ libs-y += drivers/usb/common/ libs-y += drivers/usb/emul/ libs-y += drivers/usb/eth/ -libs-$(CONFIG_USB_DEVICE) += drivers/usb/gadget/ libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/ libs-$(CONFIG_USB_GADGET) += drivers/usb/gadget/udc/ libs-y += drivers/usb/host/ @@ -1864,6 +1863,7 @@ quiet_cmd_gen_envp = ENVP $@ $(CPP) -P $(cpp_flags) -x assembler-with-cpp -undef \ -D__ASSEMBLY__ \ -D__UBOOT_CONFIG__ \ + -DDEFAULT_DEVICE_TREE=$(subst ",,$(CONFIG_DEFAULT_DEVICE_TREE)) \ -I . -I include -I $(srctree)/include \ -include linux/kconfig.h -include include/config.h \ -I$(srctree)/arch/$(ARCH)/include \ diff --git a/arch/arm/cpu/armv7/exception_level.c b/arch/arm/cpu/armv7/exception_level.c index 7baade61b07..a55c158ce51 100644 --- a/arch/arm/cpu/armv7/exception_level.c +++ b/arch/arm/cpu/armv7/exception_level.c @@ -11,9 +11,9 @@ #include <bootm.h> #include <cpu_func.h> #include <log.h> +#include <setjmp.h> #include <asm/armv7.h> #include <asm/secure.h> -#include <asm/setjmp.h> /** * entry_non_secure() - entry point when switching to non-secure mode @@ -24,7 +24,7 @@ * * @non_secure_jmp: jump buffer for restoring stack and registers */ -static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) +static void entry_non_secure(jmp_buf non_secure_jmp) { dcache_enable(); debug("Reached non-secure mode\n"); @@ -42,10 +42,10 @@ static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) void switch_to_non_secure_mode(void) { static bool is_nonsec; - struct jmp_buf_data non_secure_jmp; + jmp_buf non_secure_jmp; if (armv7_boot_nonsec() && !is_nonsec) { - if (setjmp(&non_secure_jmp)) + if (setjmp(non_secure_jmp)) return; dcache_disable(); /* flush cache before switch to HYP */ armv7_init_nonsec(); diff --git a/arch/arm/cpu/armv8/exception_level.c b/arch/arm/cpu/armv8/exception_level.c index 85c78f55789..746737861e7 100644 --- a/arch/arm/cpu/armv8/exception_level.c +++ b/arch/arm/cpu/armv8/exception_level.c @@ -11,8 +11,8 @@ #include <bootm.h> #include <cpu_func.h> #include <log.h> +#include <setjmp.h> #include <asm/cache.h> -#include <asm/setjmp.h> /** * entry_non_secure() - entry point when switching to non-secure mode @@ -23,7 +23,7 @@ * * @non_secure_jmp: jump buffer for restoring stack and registers */ -static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) +static void entry_non_secure(jmp_buf non_secure_jmp) { dcache_enable(); debug("Reached non-secure mode\n"); @@ -42,11 +42,11 @@ static void entry_non_secure(struct jmp_buf_data *non_secure_jmp) */ void switch_to_non_secure_mode(void) { - struct jmp_buf_data non_secure_jmp; + jmp_buf non_secure_jmp; /* On AArch64 we need to make sure we call our payload in < EL3 */ if (current_el() == 3) { - if (setjmp(&non_secure_jmp)) + if (setjmp(non_secure_jmp)) return; dcache_disable(); /* flush cache before switch to EL2 */ diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 85a03b512b6..73231824526 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -121,6 +121,7 @@ dtb-$(CONFIG_ARCH_TEGRA) += \ tegra124-nyan-big.dtb \ tegra124-cei-tk1-som.dtb \ tegra124-venice2.dtb \ + tegra124-xiaomi-mocha.dtb \ tegra186-p2771-0000-000.dtb \ tegra186-p2771-0000-500.dtb \ tegra210-p2371-0000.dtb \ diff --git a/arch/arm/dts/k3-am625-phycore-som-binman.dtsi b/arch/arm/dts/k3-am625-phycore-som-binman.dtsi index 31456d23167..4a65427e877 100644 --- a/arch/arm/dts/k3-am625-phycore-som-binman.dtsi +++ b/arch/arm/dts/k3-am625-phycore-som-binman.dtsi @@ -321,8 +321,11 @@ compression = "none"; load = <0x8F000000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_rtc_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_rtc_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-rtc.dtbo"; }; }; @@ -333,8 +336,11 @@ compression = "none"; load = <0x8F001000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_spi_not_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_spi_not_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-spi-nor.dtbo"; }; }; @@ -345,8 +351,11 @@ compression = "none"; load = <0x8F002000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_eth_phy_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_eth_phy_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-eth-phy.dtbo"; }; }; @@ -357,8 +366,11 @@ compression = "none"; load = <0x8F003000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_qspi_nor_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_qspi_nor_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-qspi-nor.dtbo"; }; }; diff --git a/arch/arm/dts/k3-am642-phycore-som-binman.dtsi b/arch/arm/dts/k3-am642-phycore-som-binman.dtsi index 3710564cd4a..5228eed19bf 100644 --- a/arch/arm/dts/k3-am642-phycore-som-binman.dtsi +++ b/arch/arm/dts/k3-am642-phycore-som-binman.dtsi @@ -363,8 +363,11 @@ compression = "none"; load = <0x8F000000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_rtc_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_rtc_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-rtc.dtbo"; }; }; @@ -375,8 +378,11 @@ compression = "none"; load = <0x8F001000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_spi_not_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_spi_not_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-spi-nor.dtbo"; }; }; @@ -387,8 +393,11 @@ compression = "none"; load = <0x8F002000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_eth_phy_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_eth_phy_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-disable-eth-phy.dtbo"; }; }; @@ -399,8 +408,11 @@ compression = "none"; load = <0x8F003000>; arch = "arm"; - - blob-ext { + ti-secure { + content = <&am6xx_phycore_disable_qspi_nor_dtbo>; + keyfile = "custMpk.pem"; + }; + am6xx_phycore_disable_qspi_nor_dtbo: blob-ext { filename = "dts/upstream/src/arm64/ti/k3-am6xx-phycore-qspi-nor.dtbo"; }; }; diff --git a/arch/arm/dts/rk3308-rock-s0-u-boot.dtsi b/arch/arm/dts/rk3308-rock-s0-u-boot.dtsi index 84ca2ee0d5f..c8c56b17a15 100644 --- a/arch/arm/dts/rk3308-rock-s0-u-boot.dtsi +++ b/arch/arm/dts/rk3308-rock-s0-u-boot.dtsi @@ -7,6 +7,14 @@ bootph-some-ram; }; +&gpio4 { + bootph-pre-ram; +}; + +&sdmmc_2030 { + bootph-pre-ram; +}; + &uart0 { bootph-all; clock-frequency = <24000000>; @@ -16,6 +24,10 @@ bootph-all; }; +&vcc_sd { + bootph-pre-ram; +}; + &vdd_core { regulator-init-microvolt = <1015000>; }; diff --git a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi index 69800cc368d..931499b084c 100644 --- a/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi +++ b/arch/arm/dts/rk3399-nanopi-r4s-u-boot.dtsi @@ -36,3 +36,8 @@ }; }; }; + +&u2phy1_host { + phy-supply = <&vdd_5v>; + status = "okay"; +}; diff --git a/arch/arm/dts/tegra124-xiaomi-mocha.dts b/arch/arm/dts/tegra124-xiaomi-mocha.dts new file mode 100644 index 00000000000..6cb1781566f --- /dev/null +++ b/arch/arm/dts/tegra124-xiaomi-mocha.dts @@ -0,0 +1,592 @@ +// SPDX-License-Identifier: GPL-2.0 +/dts-v1/; + +#include <dt-bindings/input/input.h> +#include "tegra124.dtsi" + +/ { + model = "Xiaomi Mi Pad A0101"; + compatible = "xiaomi,mocha", "nvidia,tegra124"; + + chosen { + stdout-path = &uartd; + }; + + aliases { + i2c0 = &pwr_i2c; + i2c1 = &gen1_i2c; + + mmc0 = &sdmmc4; /* eMMC */ + mmc1 = &sdmmc3; /* uSD slot */ + + usb0 = &usb1; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x80000000>; + }; + + host1x@50000000 { + dsia: dsi@54300000 { + status = "okay"; + + avdd-dsi-csi-supply = <&avdd_dsi_csi>; + nvidia,ganged-mode = <&dsib>; + + panel@0 { + compatible = "sharp,lq079l1sx01"; + reg = <0>; + + link2 = <&panel_secondary>; + + avdd-supply = <&avdd_lcd>; + vddio-supply = <&vdd_lcd_io>; + + vsp-supply = <&vsp_5v5_lcd>; + vsn-supply = <&vsn_5v5_lcd>; + + reset-gpios = <&gpio TEGRA_GPIO(H, 3) GPIO_ACTIVE_LOW>; + + backlight = <&lp8556>; + }; + }; + + dsib: dsi@54400000 { + status = "okay"; + + avdd-dsi-csi-supply = <&avdd_dsi_csi>; + + panel_secondary: panel@0 { + compatible = "sharp,lq079l1sx01"; + reg = <0>; + }; + }; + }; + + pinmux@70000868 { + pinctrl-names = "default"; + pinctrl-0 = <&state_default>; + + state_default: pinmux { + /* Keys pinmux */ + keys { + nvidia,pins = "kb_col0_pq0", + "kb_col6_pq6", + "kb_col7_pq7"; + nvidia,function = "rsvd2"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + hall-front { + nvidia,pins = "pi5"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + hall-back { + nvidia,pins = "gpio_w3_aud_pw3"; + nvidia,function = "spi1"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* Leds pinmux */ + bl-en { + nvidia,pins = "pbb4"; + nvidia,function = "vgp4"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + keys-led { + nvidia,pins = "ph1"; + nvidia,function = "pwm1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* Panel pinmux */ + lcd-rst { + nvidia,pins = "ph3"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-vsp { + nvidia,pins = "pi4"; + nvidia,function = "gmi"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-vsn { + nvidia,pins = "kb_row10_ps2"; + nvidia,function = "kbc"; + nvidia,pull = <TEGRA_PIN_PULL_DOWN>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + lcd-id { + nvidia,pins = "kb_row6_pr6"; + nvidia,function = "displaya_alt"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + lcd-pwm { + nvidia,pins = "ph2"; + nvidia,function = "pwm2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* SDMMC3 pinmux */ + sdmmc3-clk { + nvidia,pins = "sdmmc3_clk_pa6"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + sdmmc3-cmd { + nvidia,pins = "sdmmc3_cmd_pa7", + "sdmmc3_dat0_pb7", + "sdmmc3_dat1_pb6", + "sdmmc3_dat2_pb5", + "sdmmc3_dat3_pb4", + "sdmmc3_clk_lb_out_pee4", + "sdmmc3_clk_lb_in_pee5"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + sdmmc3-cd { + nvidia,pins = "sdmmc3_cd_n_pv2"; + nvidia,function = "sdmmc3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + usd-pwr { + nvidia,pins = "kb_row0_pr0"; + nvidia,function = "rsvd4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_DISABLE>; + }; + + /* SDMMC4 pinmux */ + sdmmc4-clk { + nvidia,pins = "sdmmc4_clk_pcc4"; + nvidia,function = "sdmmc4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + sdmmc4-cmd { + nvidia,pins = "sdmmc4_cmd_pt7", + "sdmmc4_dat0_paa0", + "sdmmc4_dat1_paa1", + "sdmmc4_dat2_paa2", + "sdmmc4_dat3_paa3", + "sdmmc4_dat4_paa4", + "sdmmc4_dat5_paa5", + "sdmmc4_dat6_paa6", + "sdmmc4_dat7_paa7"; + nvidia,function = "sdmmc4"; + nvidia,pull = <TEGRA_PIN_PULL_UP>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + + /* I2C pinmux */ + gen1-i2c { + nvidia,pins = "gen1_i2c_sda_pc5", + "gen1_i2c_scl_pc4"; + nvidia,function = "i2c1"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <1>; + nvidia,open-drain = <1>; + }; + gen2-i2c { + nvidia,pins = "gen2_i2c_scl_pt5", + "gen2_i2c_sda_pt6"; + nvidia,function = "i2c2"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <1>; + nvidia,open-drain = <1>; + }; + cam-i2c { + nvidia,pins = "cam_i2c_scl_pbb1", + "cam_i2c_sda_pbb2"; + nvidia,function = "i2c3"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,lock = <1>; + nvidia,open-drain = <1>; + }; + ddc-i2c { + nvidia,pins = "ddc_scl_pv4", + "ddc_sda_pv5"; + nvidia,function = "i2c4"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + }; + pwr-i2c { + nvidia,pins = "pwr_i2c_scl_pz6", + "pwr_i2c_sda_pz7"; + nvidia,function = "i2cpwr"; + nvidia,pull = <TEGRA_PIN_PULL_NONE>; + nvidia,tristate = <TEGRA_PIN_DISABLE>; + nvidia,enable-input = <TEGRA_PIN_ENABLE>; + nvidia,open-drain = <1>; + }; + + dsi-b { + nvidia,pins = "mipi_pad_ctrl_dsi_b"; + nvidia,function = "dsi_b"; + }; + + /* GPIO power/drive control */ + drive-sdio1 { + nvidia,pins = "drive_sdio1"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <32>; + nvidia,pull-up-strength = <42>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + + drive-sdio3 { + nvidia,pins = "drive_sdio3"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <20>; + nvidia,pull-up-strength = <36>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + + drive-gma { + nvidia,pins = "drive_gma"; + nvidia,high-speed-mode = <TEGRA_PIN_ENABLE>; + nvidia,schmitt = <TEGRA_PIN_DISABLE>; + nvidia,low-power-mode = <TEGRA_PIN_LP_DRIVE_DIV_1>; + nvidia,pull-down-strength = <1>; + nvidia,pull-up-strength = <2>; + nvidia,slew-rate-rising = <TEGRA_PIN_SLEW_RATE_FASTEST>; + nvidia,slew-rate-falling = <TEGRA_PIN_SLEW_RATE_FASTEST>; + }; + }; + }; + + uartd: serial@70006300 { + status = "okay"; + }; + + gen1_i2c: i2c@7000c000 { + status = "okay"; + clock-frequency = <400000>; + + lp8556: backlight@2c { + compatible = "ti,lp8556"; + reg = <0x2c>; + + dev-ctrl = /bits/ 8 <0x83>; + init-brt = /bits/ 8 <0x1f>; + + power-supply = <&vdd_3v3_sys>; + enable-supply = <&vddio_1v8_bl>; + + rom-98h { + rom-addr = /bits/ 8 <0x98>; + rom-val = /bits/ 8 <0x80>; + }; + + rom-9eh { + rom-addr = /bits/ 8 <0x9e>; + rom-val = /bits/ 8 <0x21>; + }; + + rom-a0h { + rom-addr = /bits/ 8 <0xa0>; + rom-val = /bits/ 8 <0xff>; + }; + + rom-a1h { + rom-addr = /bits/ 8 <0xa1>; + rom-val = /bits/ 8 <0x3f>; + }; + + rom-a2h { + rom-addr = /bits/ 8 <0xa2>; + rom-val = /bits/ 8 <0x20>; + }; + + rom-a3h { + rom-addr = /bits/ 8 <0xa3>; + rom-val = /bits/ 8 <0x00>; + }; + + rom-a4h { + rom-addr = /bits/ 8 <0xa4>; + rom-val = /bits/ 8 <0x72>; + }; + + rom-a5h { + rom-addr = /bits/ 8 <0xa5>; + rom-val = /bits/ 8 <0x24>; + }; + + rom-a6h { + rom-addr = /bits/ 8 <0xa6>; + rom-val = /bits/ 8 <0x80>; + }; + + rom-a7h { + rom-addr = /bits/ 8 <0xa7>; + rom-val = /bits/ 8 <0xf5>; + }; + + rom-a8h { + rom-addr = /bits/ 8 <0xa8>; + rom-val = /bits/ 8 <0x24>; + }; + + rom-a9h { + rom-addr = /bits/ 8 <0xa9>; + rom-val = /bits/ 8 <0xb2>; + }; + + rom-aah { + rom-addr = /bits/ 8 <0xaa>; + rom-val = /bits/ 8 <0x8f>; + }; + + rom-aeh { + rom-addr = /bits/ 8 <0xae>; + rom-val = /bits/ 8 <0x0f>; + }; + }; + }; + + pwr_i2c: i2c@7000d000 { + status = "okay"; + clock-frequency = <400000>; + + /* Texas Instruments TPS65913 PMIC */ + pmic: tps65913@58 { + compatible = "ti,tps65913"; + reg = <0x58>; + + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; + #interrupt-cells = <2>; + interrupt-controller; + + ti,system-power-controller; + + palmas_gpio: gpio { + compatible = "ti,palmas-gpio"; + gpio-controller; + #gpio-cells = <2>; + }; + + pinmux { + compatible = "ti,tps65913-pinctrl"; + + pinctrl-names = "default"; + pinctrl-0 = <&palmas_default>; + + palmas_default: pinmux { + pin_gpio4 { + pins = "gpio4"; + function = "gpio"; + }; + }; + }; + + pmic { + compatible = "ti,tps65913-pmic"; + + regulators { + vdd_1v8_vio: smps8 { + regulator-name = "vdd_1v8_gen"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + regulator-boot-on; + }; + + vdd_hv_sdmmc: smps9 { + regulator-name = "vdd_hv_sdmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + avdd_lcd: ldo2 { + regulator-name = "avdd_lcd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-boot-on; + }; + + avdd_dsi_csi: ldo5 { + regulator-name = "avdd_dsi_csi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-boot-on; + }; + + vddio_usd: ldo9 { + regulator-name = "vddio_sdmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + + avdd_usb: ldousb { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-boot-on; + }; + }; + }; + }; + }; + + sdmmc3: sdhci@700b0400 { + status = "okay"; + bus-width = <4>; + + cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; + power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>; + + vmmc-supply = <&vdd_hv_sdmmc>; + vqmmc-supply = <&vddio_usd>; + }; + + sdmmc4: sdhci@700b0600 { + status = "okay"; + bus-width = <8>; + non-removable; + + vmmc-supply = <&vdd_hv_sdmmc>; + vqmmc-supply = <&vdd_1v8_vio>; + }; + + usb1: usb@7d000000 { + status = "okay"; + dr_mode = "otg"; + }; + + clk32k_in: clock-32k { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "ref-oscillator"; + }; + + extcon-keys { + compatible = "gpio-keys"; + + switch-back-hall-sensor { + label = "Hall sensor (back)"; + gpios = <&gpio TEGRA_GPIO(W, 3) GPIO_ACTIVE_LOW>; + linux,code = <SW_LID>; + }; + + switch-front-hall-sensor { + label = "Hall sensor (front)"; + gpios = <&gpio TEGRA_GPIO(I, 5) GPIO_ACTIVE_LOW>; + linux,code = <SW_LID>; + }; + }; + + gpio-keys { + compatible = "gpio-keys"; + + key-power { + label = "Power"; + gpios = <&gpio TEGRA_GPIO(Q, 0) GPIO_ACTIVE_LOW>; + linux,code = <KEY_ENTER>; + }; + + key-volume-down { + label = "Volume Down"; + gpios = <&gpio TEGRA_GPIO(Q, 7) GPIO_ACTIVE_LOW>; + linux,code = <KEY_DOWN>; + }; + + key-volume-up { + label = "Volume Up"; + gpios = <&gpio TEGRA_GPIO(Q, 6) GPIO_ACTIVE_LOW>; + linux,code = <KEY_UP>; + }; + }; + + vdd_3v3_sys: regulator-bl-en { + compatible = "regulator-fixed"; + regulator-name = "vdd_5v0_bl"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + enable-active-high; + }; + + vddio_1v8_bl: regulator-bl-io { + compatible = "regulator-fixed"; + regulator-name = "vddio_1v8_bl"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&gpio TEGRA_GPIO(BB, 4) GPIO_ACTIVE_HIGH>; + }; + + vdd_lcd_io: regulator-lcdvio { + compatible = "regulator-fixed"; + regulator-name = "dvdd_lcd"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + enable-active-high; + gpio = <&palmas_gpio 4 GPIO_ACTIVE_HIGH>; + }; + + vsp_5v5_lcd: regulator-vsp { + compatible = "regulator-fixed"; + regulator-name = "avdd_lcd_vsp"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + enable-active-high; + gpio = <&gpio TEGRA_GPIO(I, 4) GPIO_ACTIVE_HIGH>; + }; + + vsn_5v5_lcd: regulator-vsn { + compatible = "regulator-fixed"; + regulator-name = "avdd_lcd_vsn"; + regulator-min-microvolt = <5500000>; + regulator-max-microvolt = <5500000>; + enable-active-high; + gpio = <&gpio TEGRA_GPIO(S, 2) GPIO_ACTIVE_HIGH>; + }; +}; diff --git a/arch/arm/dts/tegra20-u-boot.dtsi b/arch/arm/dts/tegra20-u-boot.dtsi index fa582bcb9fd..b74aa5bb0d4 100644 --- a/arch/arm/dts/tegra20-u-boot.dtsi +++ b/arch/arm/dts/tegra20-u-boot.dtsi @@ -9,5 +9,9 @@ dc@54200000 { bootph-all; }; + + dc@54240000 { + bootph-all; + }; }; }; diff --git a/arch/arm/dts/tegra30-htc-endeavoru.dts b/arch/arm/dts/tegra30-htc-endeavoru.dts index dbff795bd89..8a0ba3c07cc 100644 --- a/arch/arm/dts/tegra30-htc-endeavoru.dts +++ b/arch/arm/dts/tegra30-htc-endeavoru.dts @@ -48,7 +48,17 @@ avdd-dsi-csi-supply = <&avdd_dsi_csi>; - panel = <&panel>; + panel@0 { + compatible = "htc,edge-panel"; + reg = <0>; + + reset-gpios = <&gpio TEGRA_GPIO(N, 6) GPIO_ACTIVE_LOW>; + + vdd-supply = <&vdd_3v3_panel>; + vddio-supply = <&vdd_1v8_panel>; + + backlight = <&backlight>; + }; }; }; @@ -1292,17 +1302,6 @@ }; }; - panel: panel { - compatible = "htc,edge-panel"; - - reset-gpios = <&gpio TEGRA_GPIO(N, 6) GPIO_ACTIVE_LOW>; - - vdd-supply = <&vdd_3v3_panel>; - vddio-supply = <&vdd_1v8_panel>; - - backlight = <&backlight>; - }; - vcore_emmc: regulator-emmc { compatible = "regulator-fixed"; regulator-name = "vdd_2v85_sdmmc"; diff --git a/arch/arm/include/asm/arch-tegra124/pinmux.h b/arch/arm/include/asm/arch-tegra124/pinmux.h index 3aba17d21e4..fbe15fc612d 100644 --- a/arch/arm/include/asm/arch-tegra124/pinmux.h +++ b/arch/arm/include/asm/arch-tegra124/pinmux.h @@ -578,6 +578,10 @@ static const char * const tegra_pinctrl_to_drvgrp[] = { [PMUX_DRVGRP_AO4] = "ao4", }; +static const char * const tegra_pinctrl_to_mipipadgrp[] = { + [PMUX_MIPIPADCTRLGRP_DSI_B] = "mipi_pad_ctrl_dsi_b", +}; + static const char * const tegra_pinctrl_to_func[] = { [PMUX_FUNC_DEFAULT] = "default", [PMUX_FUNC_BLINK] = "blink", diff --git a/arch/arm/include/asm/arch-tegra20/clock-tables.h b/arch/arm/include/asm/arch-tegra20/clock-tables.h index 861b3d5d07c..82685353bd1 100644 --- a/arch/arm/include/asm/arch-tegra20/clock-tables.h +++ b/arch/arm/include/asm/arch-tegra20/clock-tables.h @@ -32,6 +32,7 @@ enum clock_id { CLOCK_ID_COUNT, /* number of clocks */ CLOCK_ID_NONE = -1, + CLOCK_ID_DISPLAY2 = CLOCK_ID_NONE, /* for compatibility */ }; /* The clocks supported by the hardware */ @@ -159,6 +160,7 @@ enum periph_id { PERIPH_ID_COUNT, PERIPH_ID_NONE = -1, + PERIPH_ID_DSIB = CLOCK_ID_NONE, /* for compatibility */ }; enum pll_out_id { diff --git a/arch/arm/include/asm/setjmp.h b/arch/arm/include/asm/setjmp.h index 662bec86321..a9eccf7f632 100644 --- a/arch/arm/include/asm/setjmp.h +++ b/arch/arm/include/asm/setjmp.h @@ -4,13 +4,11 @@ * (C) Copyright 2016 Alexander Graf <agraf@suse.de> */ -#ifndef _SETJMP_H_ -#define _SETJMP_H_ 1 +#ifndef _ASM_SETJMP_H_ +#define _ASM_SETJMP_H_ 1 + +#include <asm-generic/int-ll64.h> -/* - * This really should be opaque, but the EFI implementation wrongly - * assumes that a 'struct jmp_buf_data' is defined. - */ struct jmp_buf_data { #if defined(__aarch64__) u64 regs[13]; @@ -19,9 +17,4 @@ struct jmp_buf_data { #endif }; -typedef struct jmp_buf_data jmp_buf[1]; - -int setjmp(jmp_buf jmp); -void longjmp(jmp_buf jmp, int ret); - -#endif /* _SETJMP_H_ */ +#endif /* _ASM_SETJMP_H_ */ diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 974cbfe8400..7eb764e1f4e 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -61,10 +61,6 @@ static void announce_and_cleanup(int fake) bootstage_report(); #endif -#ifdef CONFIG_USB_DEVICE - udc_disconnect(); -#endif - board_quiesce_devices(); printf("\nStarting kernel ...%s\n\n", fake ? diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 0fe9c46e499..89f2b50c8a2 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -92,6 +92,8 @@ config TARGET_IMX8MM_EVK select FSL_CAAM select ARCH_MISC_INIT select SPL_CRYPTO if SPL + imply BOOTSTD_FULL + imply BOOTSTD_BOOTCOMMAND imply OF_UPSTREAM config TARGET_IMX8MM_ICORE_MX8MM diff --git a/arch/arm/mach-rockchip/bootrom.c b/arch/arm/mach-rockchip/bootrom.c index 82a0b3efef9..1db38546d55 100644 --- a/arch/arm/mach-rockchip/bootrom.c +++ b/arch/arm/mach-rockchip/bootrom.c @@ -4,11 +4,11 @@ */ #include <hang.h> +#include <setjmp.h> #include <asm/arch-rockchip/bootrom.h> #include <asm/arch-rockchip/boot_mode.h> #include <asm/cache.h> #include <asm/io.h> -#include <asm/setjmp.h> #include <asm/system.h> /* diff --git a/arch/arm/mach-stm32mp/stm32mp1/cpu.c b/arch/arm/mach-stm32mp/stm32mp1/cpu.c index bc410128479..18175fd12cc 100644 --- a/arch/arm/mach-stm32mp/stm32mp1/cpu.c +++ b/arch/arm/mach-stm32mp/stm32mp1/cpu.c @@ -82,7 +82,7 @@ void dram_bank_mmu_setup(int bank) option = DCACHE_DEFAULT_OPTION; if (use_lmb && (lmb_is_reserved_flags(i << MMU_SECTION_SHIFT, LMB_NOMAP) || - addr >= gd->ram_top) + (gd->ram_top && addr >= gd->ram_top)) ) option = 0; /* INVALID ENTRY in TLB */ set_section_dcache(i, option); diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 78b89729f19..4690dcb3ea6 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -247,7 +247,7 @@ config CMD_ENTERRCM config CMD_EBTUPDATE bool "Enable 'ebtupdate' command" - depends on TEGRA20 || TEGRA30 + depends on TEGRA20 || TEGRA30 || TEGRA124 select TEGRA_CRYPTO help Updating u-boot from within u-boot in rather complex or even diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 157e6c4911a..a375693481e 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c @@ -358,6 +358,13 @@ unsigned long clock_get_periph_rate(enum periph_id periph_id, break; } + /* + * PLLD/PLLD2 raw clock rate is never used, instead plld_out0 is used + * that is PLLD/PLLD2 halved. + */ + if (parent == CLOCK_ID_DISPLAY || parent == CLOCK_ID_DISPLAY2) + parent_rate /= 2; + return get_rate_from_divider(parent_rate, div); } @@ -449,6 +456,7 @@ unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, enum clock_id parent, unsigned rate, int *extra_div) { unsigned effective_rate; + unsigned int parent_rate; int mux_bits, divider_bits, source; int divider; int xdiv = 0; @@ -457,7 +465,17 @@ unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, source = get_periph_clock_source(periph_id, parent, &mux_bits, ÷r_bits); - divider = find_best_divider(divider_bits, pll_rate[parent], + /* + * Clocks derived from PLLD/D2 are actually sourced from its halved + * output, plld_out0/plld2_out0. No peripheral clocks use the raw + * PLLD/D2 frequency. This halving must be accounted for in derived + * clock calculations. + */ + parent_rate = pll_rate[parent]; + if (parent == CLOCK_ID_DISPLAY || parent == CLOCK_ID_DISPLAY2) + parent_rate /= 2; + + divider = find_best_divider(divider_bits, parent_rate, rate, &xdiv); if (extra_div) *extra_div = xdiv; @@ -685,6 +703,16 @@ int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon) else writel(base_reg, &simple_pll->pll_base); + /* + * Changing clocks was never intended in the U-Boot for Tegra. + * If a clock is changed after clock_init() the parent rate is wrong. + * Usually there is no reason to change peripheral clocks, but Display + * PLLs which needs to generate a precise pixelclock might be adjusted. + * Especially in the case of HDMI display with changing and prior + * unknown resolution. + */ + pll_rate[clkid] = clock_get_rate(clkid); + return 0; } diff --git a/arch/arm/mach-tegra/tegra124/Kconfig b/arch/arm/mach-tegra/tegra124/Kconfig index 84c8f86bad0..a62b055f7e6 100644 --- a/arch/arm/mach-tegra/tegra124/Kconfig +++ b/arch/arm/mach-tegra/tegra124/Kconfig @@ -30,6 +30,10 @@ config TARGET_CEI_TK1_SOM the SoC are assigned to which functions, and the PCIEe configuration. +config TARGET_MOCHA + bool "Xiaomi Tegra124 Mi Pad board" + select BOARD_LATE_INIT + config TARGET_NYAN_BIG bool "Google/NVIDIA Nyan-big Chromebook" select BOARD_LATE_INIT @@ -54,5 +58,6 @@ source "board/nvidia/jetson-tk1/Kconfig" source "board/nvidia/nyan-big/Kconfig" source "board/nvidia/venice2/Kconfig" source "board/toradex/apalis-tk1/Kconfig" +source "board/xiaomi/mocha/Kconfig" endif diff --git a/arch/arm/mach-tegra/tegra124/Makefile b/arch/arm/mach-tegra/tegra124/Makefile index dee790015a3..7b93db89c0f 100644 --- a/arch/arm/mach-tegra/tegra124/Makefile +++ b/arch/arm/mach-tegra/tegra124/Makefile @@ -6,6 +6,7 @@ # obj-$(CONFIG_XPL_BUILD) += cpu.o +obj-$(CONFIG_$(XPL_)CMD_EBTUPDATE) += bct.o obj-y += clock.o obj-y += pmc.o diff --git a/arch/arm/mach-tegra/tegra124/bct.c b/arch/arm/mach-tegra/tegra124/bct.c new file mode 100644 index 00000000000..a71aa87fce1 --- /dev/null +++ b/arch/arm/mach-tegra/tegra124/bct.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2022, Ramin <raminterex@yahoo.com> + * Copyright (c) 2022, Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <command.h> +#include <log.h> +#include <vsprintf.h> +#include <asm/arch-tegra/crypto.h> +#include "bct.h" +#include "uboot_aes.h" + +/* Device with "sbk burned: false" will expose zero key */ +const u8 nosbk[AES128_KEY_LENGTH] = { 0 }; + +/* + * @param bct boot config table start in RAM + * @param ect bootloader start in RAM + * @param ebt_size bootloader file size in bytes + * Return: 0, or 1 if failed + */ +static int bct_patch(u8 *bct, u8 *ebt, u32 ebt_size) +{ + struct nvboot_config_table *bct_tbl = NULL; + u8 ebt_hash[AES128_KEY_LENGTH] = { 0 }; + u8 bct_hash[AES128_KEY_LENGTH] = { 0 }; + u8 sbk[AES128_KEY_LENGTH] = { 0 }; + u8 *sbct = bct + UBCT_LENGTH; + bool encrypted; + int ret; + + ebt_size = roundup(ebt_size, EBT_ALIGNMENT); + + memcpy(sbk, (u8 *)(bct + UBCT_LENGTH + SBCT_LENGTH), + NVBOOT_CMAC_AES_HASH_LENGTH * 4); + + encrypted = memcmp(&sbk, &nosbk, AES128_KEY_LENGTH); + + if (encrypted) { + ret = decrypt_data_block(sbct, SBCT_LENGTH, sbk); + if (ret) + return 1; + + ret = encrypt_data_block(ebt, ebt_size, sbk); + if (ret) + return 1; + } + + ret = sign_enc_data_block(ebt, ebt_size, ebt_hash, sbk); + if (ret) + return 1; + + bct_tbl = (struct nvboot_config_table *)bct; + + memcpy((u8 *)&bct_tbl->bootloader[0].crypto_hash, + ebt_hash, NVBOOT_CMAC_AES_HASH_LENGTH * 4); + bct_tbl->bootloader[0].entry_point = CONFIG_SPL_TEXT_BASE; + bct_tbl->bootloader[0].load_addr = CONFIG_SPL_TEXT_BASE; + bct_tbl->bootloader[0].length = ebt_size; + + if (encrypted) { + ret = encrypt_data_block(sbct, SBCT_LENGTH, sbk); + if (ret) + return 1; + } + + ret = sign_enc_data_block(sbct, SBCT_LENGTH, bct_hash, sbk); + if (ret) + return 1; + + memcpy((u8 *)&bct_tbl->crypto_hash, bct_hash, + NVBOOT_CMAC_AES_HASH_LENGTH * 4); + + return 0; +} + +static int do_ebtupdate(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + u32 bct_addr = hextoul(argv[1], NULL); + u32 ebt_addr = hextoul(argv[2], NULL); + u32 ebt_size = hextoul(argv[3], NULL); + + return bct_patch((u8 *)bct_addr, (u8 *)ebt_addr, ebt_size); +} + +U_BOOT_CMD(ebtupdate, 4, 0, do_ebtupdate, + "update bootloader on re-crypted Tegra124 devices", + "" +); diff --git a/arch/arm/mach-tegra/tegra124/bct.h b/arch/arm/mach-tegra/tegra124/bct.h new file mode 100644 index 00000000000..eb0f712d595 --- /dev/null +++ b/arch/arm/mach-tegra/tegra124/bct.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef _BCT_H_ +#define _BCT_H_ + +/* + * Defines the BCT parametres for T124 + */ +#define UBCT_LENGTH 0x6b0 /* bytes */ +#define SBCT_LENGTH 0x1950 /* bytes */ + +#define BCT_HASH 0x10 +#define EBT_ALIGNMENT 0x10 + +/* + * Defines the CMAC-AES-128 hash length in 32 bit words. (128 bits = 4 words) + */ +#define NVBOOT_CMAC_AES_HASH_LENGTH 4 + +/* + * Defines the RSA modulus length in 32 bit words used for PKC secure boot. + */ +#define NVBOOT_SE_RSA_MODULUS_LENGTH 64 + +/* + * Defines the maximum number of bootloader descriptions in the BCT. + */ +#define NVBOOT_MAX_BOOTLOADERS 4 + +struct nv_bootloader_info { + u32 version; + u32 start_blk; + u32 start_page; + u32 length; + u32 load_addr; + u32 entry_point; + u32 attribute; + + /* Specifies the AES-CMAC MAC or RSASSA-PSS signature of the BL. */ + u32 crypto_hash[NVBOOT_CMAC_AES_HASH_LENGTH]; + u32 bl_rsa_sig[NVBOOT_SE_RSA_MODULUS_LENGTH]; +}; + +struct nvboot_config_table { + u32 ubct_unused1[196]; + u32 crypto_hash[NVBOOT_CMAC_AES_HASH_LENGTH]; + u32 ubct_unused2[228]; + + u32 sbct_unused1[1318]; + u32 bootloader_used; + struct nv_bootloader_info bootloader[NVBOOT_MAX_BOOTLOADERS]; + u32 sbct_unused2; +}; + +#endif /* _BCT_H_ */ diff --git a/arch/arm/mach-versal2/include/mach/hardware.h b/arch/arm/mach-versal2/include/mach/hardware.h index 42e3061a0ae..15085f941e0 100644 --- a/arch/arm/mach-versal2/include/mach/hardware.h +++ b/arch/arm/mach-versal2/include/mach/hardware.h @@ -51,7 +51,8 @@ struct crp_regs { #define PMC_TAP_VERSION (PMC_TAP + 0x4) # define PMC_VERSION_MASK GENMASK(7, 0) # define PS_VERSION_MASK GENMASK(15, 8) -# define PS_VERSION_PRODUCTION 0x20 +# define PS_VERSION_MAJOR GENMASK(7, 4) +# define PS_VERSION_MINOR GENMASK(3, 0) # define RTL_VERSION_MASK GENMASK(23, 16) # define PLATFORM_MASK GENMASK(27, 24) # define PLATFORM_VERSION_MASK GENMASK(31, 28) diff --git a/arch/riscv/include/asm/setjmp.h b/arch/riscv/include/asm/setjmp.h index 72383d43303..08687e0f92b 100644 --- a/arch/riscv/include/asm/setjmp.h +++ b/arch/riscv/include/asm/setjmp.h @@ -3,13 +3,9 @@ * (C) Copyright 2018 Alexander Graf <agraf@suse.de> */ -#ifndef _SETJMP_H_ -#define _SETJMP_H_ 1 +#ifndef _ASM_SETJMP_H_ +#define _ASM_SETJMP_H_ 1 -/* - * This really should be opaque, but the EFI implementation wrongly - * assumes that a 'struct jmp_buf_data' is defined. - */ struct jmp_buf_data { /* x2, x8, x9, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, sp */ unsigned long s_regs[12]; /* s0 - s11 */ @@ -17,9 +13,4 @@ struct jmp_buf_data { unsigned long sp; }; -typedef struct jmp_buf_data jmp_buf[1]; - -int setjmp(jmp_buf jmp); -void longjmp(jmp_buf jmp, int ret); - -#endif /* _SETJMP_H_ */ +#endif /* _ASM_SETJMP_H_ */ diff --git a/arch/riscv/lib/bootm.c b/arch/riscv/lib/bootm.c index 76c610bcee0..9544907ab1e 100644 --- a/arch/riscv/lib/bootm.c +++ b/arch/riscv/lib/bootm.c @@ -46,10 +46,6 @@ static void announce_and_cleanup(int fake) bootstage_report(); #endif -#ifdef CONFIG_USB_DEVICE - udc_disconnect(); -#endif - board_quiesce_devices(); /* diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig index 4c169034d9a..d61a327f151 100644 --- a/arch/sandbox/Kconfig +++ b/arch/sandbox/Kconfig @@ -77,7 +77,7 @@ config SANDBOX_BITS_PER_LONG config SYS_FDT_LOAD_ADDR hex "Address at which to load devicetree" - default 0x100 + default 0x1000 help With sandbox the devicetree is loaded into the emulated RAM. This sets the address that is used. There must be enough space at this address diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 6407193c5f1..6db8739e66b 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -10,10 +10,10 @@ #include <errno.h> #include <log.h> #include <os.h> +#include <setjmp.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/malloc.h> -#include <asm/setjmp.h> #include <asm/state.h> #include <dm/ofnode.h> #include <linux/delay.h> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index b8f3012873e..52e9ddbf50f 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1047,6 +1047,31 @@ }; }; + lvds-encoder { + compatible = "lvds-encoder"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + bridge_input: endpoint { + /* link to output */ + }; + }; + + port@1 { + reg = <1>; + + bridge_output: endpoint { + remote-endpoint = <&panel_input>; + }; + }; + }; + }; + wdt-gpio-toggle { gpios = <&gpio_a 8 0>; compatible = "linux,wdt-gpio"; @@ -1402,6 +1427,27 @@ panel { compatible = "simple-panel"; backlight = <&backlight 0 100>; + + display-timings { + timing@0 { + /* 1280x800@60Hz */ + clock-frequency = <68000000>; + hactive = <1280>; + hfront-porch = <48>; + hback-porch = <18>; + hsync-len = <30>; + vactive = <800>; + vfront-porch = <3>; + vback-porch = <12>; + vsync-len = <5>; + }; + }; + + port { + panel_input: endpoint { + remote-endpoint = <&bridge_output>; + }; + }; }; scsi { @@ -2048,6 +2094,61 @@ sandbox,err-step-size = <512>; }; }; + + graph1 { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <0>; + + endpoint@0 { + reg = <0>; + }; + + endpoint@1 { + reg = <1>; + }; + }; + + port@1 { + reg = <1>; + + endpoint { + test-property-0; + }; + }; + + port@2 { + #address-cells = <1>; + #size-cells = <0>; + + reg = <2>; + + graph2_link: endpoint@0 { + reg = <0>; + test-property-1; + remote-endpoint = <&graph1_link>; + }; + + endpoint@1 { + reg = <1>; + }; + }; + }; + }; + + graph2 { + port { + graph1_link: endpoint { + remote-endpoint = <&graph2_link>; + }; + }; + }; }; #include "sandbox_pmic.dtsi" diff --git a/arch/sandbox/include/asm/setjmp.h b/arch/sandbox/include/asm/setjmp.h index 001c7ea322d..3413c747783 100644 --- a/arch/sandbox/include/asm/setjmp.h +++ b/arch/sandbox/include/asm/setjmp.h @@ -4,8 +4,8 @@ * Written by Simon Glass <sjg@chromium.org> */ -#ifndef _SETJMP_H_ -#define _SETJMP_H_ +#ifndef _ASM_SETJMP_H_ +#define _ASM_SETJMP_H_ struct jmp_buf_data { /* @@ -19,17 +19,7 @@ struct jmp_buf_data { * We don't need to worry about 16-byte alignment, since this does not * run on Windows. */ - ulong data[128]; + unsigned long data[128]; }; -typedef struct jmp_buf_data jmp_buf[1]; - -/* - * We have to directly link with the system versions of - * setjmp/longjmp, because setjmp must not return as otherwise - * the stack may become invalid. - */ -int setjmp(jmp_buf jmp); -__noreturn void longjmp(jmp_buf jmp, int ret); - -#endif /* _SETJMP_H_ */ +#endif /* _ASM_SETJMP_H_ */ diff --git a/arch/x86/cpu/intel_common/intel_opregion.c b/arch/x86/cpu/intel_common/intel_opregion.c index 78caff0dc12..4a2717b3584 100644 --- a/arch/x86/cpu/intel_common/intel_opregion.c +++ b/arch/x86/cpu/intel_common/intel_opregion.c @@ -31,6 +31,7 @@ static int locate_vbt(char **vbtp, int *sizep) size = vbt.size; if (size > sizeof(vbt_data)) return log_msg_ret("vbt", -E2BIG); + vbt.image_pos += CONFIG_ROM_SIZE; ret = spi_flash_read_dm(dev, vbt.image_pos, size, vbt_data); if (ret) return log_msg_ret("read", ret); diff --git a/arch/x86/include/asm/setjmp.h b/arch/x86/include/asm/setjmp.h index 15915d0dc6b..13772574e15 100644 --- a/arch/x86/include/asm/setjmp.h +++ b/arch/x86/include/asm/setjmp.h @@ -5,8 +5,8 @@ * From Linux arch/um/sys-i386/setjmp.S */ -#ifndef __setjmp_h -#define __setjmp_h +#ifndef _ASM_SETJMP_H_ +#define _ASM_SETJMP_H_ 1 #ifdef CONFIG_X86_64 @@ -34,9 +34,4 @@ struct jmp_buf_data { #endif -typedef struct jmp_buf_data jmp_buf[1]; - -int setjmp(jmp_buf env); -void longjmp(jmp_buf env, int val); - -#endif +#endif /* _ASM_SETJMP_H_ */ diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c index 1a2bf46c5c5..0be892b14dc 100644 --- a/arch/x86/lib/fsp2/fsp_init.c +++ b/arch/x86/lib/fsp2/fsp_init.c @@ -107,7 +107,6 @@ int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry, bool use_spi_flash, struct udevice **devp, struct fsp_header **hdrp, ulong *rom_offsetp) { - ulong mask = CONFIG_ROM_SIZE - 1; struct udevice *dev; ulong rom_offset = 0; uint map_size; @@ -141,7 +140,7 @@ int fsp_locate_fsp(enum fsp_type_t type, struct binman_entry *entry, if (ret) return log_msg_ret("binman entry", ret); if (!use_spi_flash) - rom_offset = (map_base & mask) - CONFIG_ROM_SIZE; + rom_offset = map_base + CONFIG_ROM_SIZE; } else { ret = -ENOENT; if (false) diff --git a/board/emulation/qemu-sbsa/Kconfig b/board/emulation/qemu-sbsa/Kconfig index 72c76b351fa..728cecae6b3 100644 --- a/board/emulation/qemu-sbsa/Kconfig +++ b/board/emulation/qemu-sbsa/Kconfig @@ -33,6 +33,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select OF_SEPARATE select PCI select PCIE_ECAM_GENERIC + select SYS_PCI_64BIT select USB select GIC_V3 select GIC_V3_ITS @@ -48,6 +49,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply CFI_FLASH imply SYS_MTDPARTS_RUNTIME imply SET_DFU_ALT_INFO + imply PCI_INIT_R if DEBUG_UART diff --git a/board/freescale/imx8mp_evk/imx8mp_evk.env b/board/freescale/imx8mp_evk/imx8mp_evk.env index 18f6c6e200e..f70e18fa9d9 100644 --- a/board/freescale/imx8mp_evk/imx8mp_evk.env +++ b/board/freescale/imx8mp_evk/imx8mp_evk.env @@ -16,6 +16,7 @@ mmcroot=/dev/mmcblk1p2 rootwait rw mmcautodetect=yes mmcargs=setenv bootargs ${jh_clk} ${mcore_clk} console=${console} root=${mmcroot} prepare_mcore=setenv mcore_clk clk-imx8mp.mcore_booted +kernel_addr_r=CONFIG_SYS_LOAD_ADDR loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile} mmcboot=echo Booting from mmc ...; diff --git a/board/freescale/imx93_evk/imx93_evk.env b/board/freescale/imx93_evk/imx93_evk.env index f692f42f78a..8c3aef6b557 100644 --- a/board/freescale/imx93_evk/imx93_evk.env +++ b/board/freescale/imx93_evk/imx93_evk.env @@ -16,6 +16,7 @@ mmcroot=/dev/mmcblk1p2 rootwait rw mmcautodetect=yes mmcargs=setenv bootargs ${jh_clk} ${mcore_clk} console=${console} root=${mmcroot} prepare_mcore=setenv mcore_clk clk-imx93.mcore_booted +kernel_addr_r=CONFIG_SYS_LOAD_ADDR loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image} loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr_r} ${fdtfile} loadcntr=fatload mmc ${mmcdev}:${mmcpart} ${cntr_addr} ${cntr_file} diff --git a/board/freescale/ls1021atsn/ls1021atsn.c b/board/freescale/ls1021atsn/ls1021atsn.c index d1acccec110..c92430c0896 100644 --- a/board/freescale/ls1021atsn/ls1021atsn.c +++ b/board/freescale/ls1021atsn/ls1021atsn.c @@ -166,10 +166,9 @@ void board_init_f(ulong dummy) get_clocks(); -#if defined(CONFIG_DEEP_SLEEP) - if (is_warm_boot()) - fsl_dp_disable_console(); -#endif + if (CONFIG_IS_ENABLED(DEEP_SLEEP)) + if (is_warm_boot()) + fsl_dp_disable_console(); preloader_console_init(); @@ -187,9 +186,11 @@ void board_init_f(ulong dummy) * it from SD since it has already been reserved in memory * in last boot. */ - if (is_warm_boot()) { - second_uboot = (void (*)(void))CONFIG_TEXT_BASE; - second_uboot(); + if (CONFIG_IS_ENABLED(DEEP_SLEEP)) { + if (is_warm_boot()) { + second_uboot = (void (*)(void))CONFIG_TEXT_BASE; + second_uboot(); + } } board_init_r(NULL, 0); diff --git a/board/freescale/ls1021atwr/ls1021atwr.c b/board/freescale/ls1021atwr/ls1021atwr.c index cc9665c0410..0758e5eae25 100644 --- a/board/freescale/ls1021atwr/ls1021atwr.c +++ b/board/freescale/ls1021atwr/ls1021atwr.c @@ -417,10 +417,9 @@ void board_init_f(ulong dummy) get_clocks(); -#if defined(CONFIG_DEEP_SLEEP) - if (is_warm_boot()) - fsl_dp_disable_console(); -#endif + if (CONFIG_IS_ENABLED(DEEP_SLEEP)) + if (is_warm_boot()) + fsl_dp_disable_console(); preloader_console_init(); @@ -438,9 +437,11 @@ void board_init_f(ulong dummy) * it from SD since it has already been reserved in memeory * in last boot. */ - if (is_warm_boot()) { - second_uboot = (void (*)(void))CONFIG_TEXT_BASE; - second_uboot(); + if (CONFIG_IS_ENABLED(DEEP_SLEEP)) { + if (is_warm_boot()) { + second_uboot = (void (*)(void))CONFIG_TEXT_BASE; + second_uboot(); + } } board_init_r(NULL, 0); diff --git a/board/gdsys/a38x/ihs_phys.c b/board/gdsys/a38x/ihs_phys.c index 0c68087912a..d51301869cd 100644 --- a/board/gdsys/a38x/ihs_phys.c +++ b/board/gdsys/a38x/ihs_phys.c @@ -123,9 +123,9 @@ struct gpio_mii { { 2, {}, {}, 46, 24, 1 }, }; -static int mii_mdio_init(struct bb_miiphy_bus *bus) +static int mii_mdio_init(const int k) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = &gpio_mii_set[k]; char name[32] = {}; struct udevice *gpio_dev1 = NULL; struct udevice *gpio_dev2 = NULL; @@ -164,27 +164,27 @@ static int mii_mdio_init(struct bb_miiphy_bus *bus) return 0; } -static int mii_mdio_active(struct bb_miiphy_bus *bus) +static int mii_mdio_active(struct mii_dev *miidev) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_value(&gpio_mii->mdc_gpio, gpio_mii->mdio_value); return 0; } -static int mii_mdio_tristate(struct bb_miiphy_bus *bus) +static int mii_mdio_tristate(struct mii_dev *miidev) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN); return 0; } -static int mii_set_mdio(struct bb_miiphy_bus *bus, int v) +static int mii_set_mdio(struct mii_dev *miidev, int v) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_OUT); dm_gpio_set_value(&gpio_mii->mdio_gpio, v); @@ -193,9 +193,9 @@ static int mii_set_mdio(struct bb_miiphy_bus *bus, int v) return 0; } -static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v) +static int mii_get_mdio(struct mii_dev *miidev, int *v) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_dir_flags(&gpio_mii->mdio_gpio, GPIOD_IS_IN); *v = (dm_gpio_get_value(&gpio_mii->mdio_gpio)); @@ -203,51 +203,61 @@ static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v) return 0; } -static int mii_set_mdc(struct bb_miiphy_bus *bus, int v) +static int mii_set_mdc(struct mii_dev *miidev, int v) { - struct gpio_mii *gpio_mii = bus->priv; + struct gpio_mii *gpio_mii = miidev->priv; dm_gpio_set_value(&gpio_mii->mdc_gpio, v); return 0; } -static int mii_delay(struct bb_miiphy_bus *bus) +static int mii_delay(struct mii_dev *miidev) { udelay(1); return 0; } +static const struct bb_miiphy_bus_ops mii_bb_miiphy_bus_ops = { + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, +}; + +static int mii_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) +{ + return bb_miiphy_read(miidev, &mii_bb_miiphy_bus_ops, + addr, devad, reg); +} + +static int mii_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) +{ + return bb_miiphy_write(miidev, &mii_bb_miiphy_bus_ops, + addr, devad, reg, value); +} + int register_miiphy_bus(uint k, struct mii_dev **bus) { - struct bb_miiphy_bus *bb_miiphy = bb_miiphy_alloc(); - struct mii_dev *mdiodev; + struct mii_dev *mdiodev = mdio_alloc(); int retval; - if (!bb_miiphy) - return -ENOMEM; - - mdiodev = &bb_miiphy->mii; snprintf(mdiodev->name, MDIO_NAME_LEN, "ihs%d", k); - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; - - /* Copy the bus accessors and private data */ - bb_miiphy->mdio_active = mii_mdio_active; - bb_miiphy->mdio_tristate = mii_mdio_tristate; - bb_miiphy->set_mdio = mii_set_mdio; - bb_miiphy->get_mdio = mii_get_mdio; - bb_miiphy->set_mdc = mii_set_mdc; - bb_miiphy->delay = mii_delay; - bb_miiphy->priv = &gpio_mii_set[k]; + mdiodev->read = mii_bb_miiphy_read; + mdiodev->write = mii_bb_miiphy_write; + mdiodev->priv = &gpio_mii_set[k]; retval = mdio_register(mdiodev); if (retval < 0) return retval; - *bus = &bb_miiphy->mii; + *bus = mdiodev; - return mii_mdio_init(bb_miiphy); + return mii_mdio_init(k); } struct porttype *get_porttype(uint octo_phy_mask, uint k) diff --git a/board/toradex/verdin-am62/verdin-am62.c b/board/toradex/verdin-am62/verdin-am62.c index b80b39b6767..a1c471111a0 100644 --- a/board/toradex/verdin-am62/verdin-am62.c +++ b/board/toradex/verdin-am62/verdin-am62.c @@ -15,6 +15,7 @@ #include <init.h> #include <k3-ddrss.h> #include <spl.h> +#include <asm/arch/k3-ddr.h> #include "../common/tdx-cfg-block.h" @@ -43,6 +44,9 @@ int dram_init_banksize(void) if (ret) printf("Error setting up memory banksize. %d\n", ret); + /* Use the detected RAM size, we only support 1 bank right now. */ + gd->bd->bi_dram[0].size = gd->ram_size; + return ret; } @@ -108,6 +112,13 @@ int board_late_init(void) #define CORE_VOLTAGE 0x80000000 #define MCU_CTRL_LFXOSC_32K_BYPASS_VAL BIT(4) +#if IS_ENABLED(CONFIG_XPL_BUILD) +void spl_perform_fixups(struct spl_image_info *spl_image) +{ + fixup_memory_node(spl_image); +} +#endif + #ifdef CONFIG_SPL_BOARD_INIT void spl_board_init(void) { diff --git a/board/xiaomi/mocha/Kconfig b/board/xiaomi/mocha/Kconfig new file mode 100644 index 00000000000..25c61d4169e --- /dev/null +++ b/board/xiaomi/mocha/Kconfig @@ -0,0 +1,12 @@ +if TARGET_MOCHA + +config SYS_BOARD + default "mocha" + +config SYS_VENDOR + default "xiaomi" + +config SYS_CONFIG_NAME + default "mocha" + +endif diff --git a/board/xiaomi/mocha/MAINTAINERS b/board/xiaomi/mocha/MAINTAINERS new file mode 100644 index 00000000000..c3871a15a35 --- /dev/null +++ b/board/xiaomi/mocha/MAINTAINERS @@ -0,0 +1,8 @@ +MOCHA BOARD +M: Svyatoslav Ryhel <clamor95@gmail.com> +S: Maintained +F: arch/arm/dts/tegra124-xiaomi-mocha.dts +F: board/xiaomi/mocha/ +F: configs/mocha_defconfig +F: doc/board/xiaomi/mocha.rst +F: include/configs/mocha.h diff --git a/board/xiaomi/mocha/Makefile b/board/xiaomi/mocha/Makefile new file mode 100644 index 00000000000..c42e42639b3 --- /dev/null +++ b/board/xiaomi/mocha/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2024, Svyatoslav Ryhel <clamor95@gmail.com> +# + +obj-$(CONFIG_XPL_BUILD) += mocha-spl.o + +obj-y += mocha.o + diff --git a/board/xiaomi/mocha/mocha-spl.c b/board/xiaomi/mocha/mocha-spl.c new file mode 100644 index 00000000000..5fb11df0a93 --- /dev/null +++ b/board/xiaomi/mocha/mocha-spl.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Mocha SPL stage configuration + * + * (C) Copyright 2024 + * Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <asm/arch/tegra.h> +#include <asm/arch-tegra/tegra_i2c.h> +#include <linux/delay.h> + +#define TPS65913_I2C_ADDR (0x58 << 1) + +#define TPS65913_SMPS12_CTRL 0x20 +#define TPS65913_SMPS12_VOLTAGE 0x23 +#define TPS65913_SMPS45_CTRL 0x28 +#define TPS65913_SMPS45_VOLTAGE 0x2B +#define TPS65913_SMPS7_CTRL 0x30 +#define TPS65913_SMPS7_VOLTAGE 0x33 + +#define TPS65913_SMPS12_CTRL_DATA (0x5100 | TPS65913_SMPS12_CTRL) +#define TPS65913_SMPS12_VOLTAGE_DATA (0x3800 | TPS65913_SMPS12_VOLTAGE) +#define TPS65913_SMPS45_CTRL_DATA (0x5100 | TPS65913_SMPS45_CTRL) +#define TPS65913_SMPS45_VOLTAGE_DATA (0x3800 | TPS65913_SMPS45_VOLTAGE) +#define TPS65913_SMPS7_CTRL_DATA (0x5100 | TPS65913_SMPS7_CTRL) +#define TPS65913_SMPS7_VOLTAGE_DATA (0x4700 | TPS65913_SMPS7_VOLTAGE) + +void pmic_enable_cpu_vdd(void) +{ + /* Set CORE VDD to 1.150V. */ + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS7_VOLTAGE_DATA); + udelay(1000); + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS7_CTRL_DATA); + + udelay(1000); + + /* Set CPU VDD to 1.0V. */ + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS12_VOLTAGE_DATA); + udelay(1000); + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS12_CTRL_DATA); + udelay(10 * 1000); + + /* Set GPU VDD to 1.0V. */ + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS45_VOLTAGE_DATA); + udelay(1000); + tegra_i2c_ll_write(TPS65913_I2C_ADDR, TPS65913_SMPS45_CTRL_DATA); + udelay(10 * 1000); +} diff --git a/board/xiaomi/mocha/mocha.c b/board/xiaomi/mocha/mocha.c new file mode 100644 index 00000000000..5026d541a5f --- /dev/null +++ b/board/xiaomi/mocha/mocha.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2024 + * Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <dm.h> +#include <fdt_support.h> +#include <i2c.h> +#include <log.h> + +#ifdef CONFIG_MMC_SDHCI_TEGRA + +#define TPS65913_I2C_ADDRESS 0x58 +#define TPS65913_PRIMARY_SECONDARY_PAD2 0xfb +#define GPIO_4 BIT(0) +#define TPS65913_PRIMARY_SECONDARY_PAD3 0xfe +#define DVFS2 BIT(1) +#define DVFS1 BIT(0) + +/* We are using this function only till palmas pinctrl driver is available */ +void pin_mux_mmc(void) +{ + struct udevice *dev; + int ret; + + ret = i2c_get_chip_for_busnum(0, TPS65913_I2C_ADDRESS, 1, &dev); + if (ret) { + log_debug("%s: cannot find PMIC I2C chip\n", __func__); + return; + } + + /* GPIO4 function has to be GPIO */ + dm_i2c_reg_clrset(dev, TPS65913_PRIMARY_SECONDARY_PAD2, + GPIO_4, 0); + + /* DVFS1 and DVFS2 are disabled */ + dm_i2c_reg_clrset(dev, TPS65913_PRIMARY_SECONDARY_PAD3, + DVFS2 | DVFS1, 0); +} +#endif diff --git a/board/xiaomi/mocha/mocha.env b/board/xiaomi/mocha/mocha.env new file mode 100644 index 00000000000..d93e24316f6 --- /dev/null +++ b/board/xiaomi/mocha/mocha.env @@ -0,0 +1,23 @@ +#include <env/nvidia/prod_upd.env> + +button_cmd_0_name=Volume Down +button_cmd_0=bootmenu +button_cmd_1_name=Hall sensor (back) +button_cmd_1=poweroff +button_cmd_1_name=Hall sensor (front) +button_cmd_1=poweroff + +partitions=name=emmc,start=0,size=-,uuid=${uuid_gpt_rootfs} + +boot_block_size_r=0x400000 +boot_block_size=0x2000 +boot_dev=1 + +bootmenu_0=mount internal storage=usb start && ums 0 mmc 0; bootmenu +bootmenu_1=mount external storage=usb start && ums 0 mmc 1; bootmenu +bootmenu_2=fastboot=echo Starting Fastboot protocol ...; fastboot usb 0; bootmenu +bootmenu_3=update bootloader=run flash_uboot +bootmenu_4=reboot RCM=enterrcm +bootmenu_5=reboot=reset +bootmenu_6=power off=poweroff +bootmenu_delay=-1 diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index a852d5b8ed5..8dbfa560423 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -179,6 +179,7 @@ void set_dfu_alt_info(char *interface, char *devstr) memset(buf, 0, sizeof(buf)); switch ((zynq_slcr_get_boot_mode()) & ZYNQ_BM_MASK) { +#if defined(CONFIG_SPL_FS_LOAD_PAYLOAD_NAME) case ZYNQ_BM_SD: snprintf(buf, DFU_ALT_BUF_LEN, "mmc 0=boot.bin fat 0 1;" @@ -193,6 +194,7 @@ void set_dfu_alt_info(char *interface, char *devstr) CONFIG_SYS_SPI_U_BOOT_OFFS); break; #endif +#endif default: return; } diff --git a/cmd/Kconfig b/cmd/Kconfig index 8dd42571abc..cd391d422ae 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2169,7 +2169,6 @@ config WGET_HTTPS select ASYMMETRIC_PUBLIC_KEY_SUBTYPE select X509_CERTIFICATE_PARSER select PKCS7_MESSAGE_PARSER - select MBEDTLS_LIB_CRYPTO select MBEDTLS_LIB_TLS select RSA_VERIFY_WITH_PKEY select X509_CERTIFICATE_PARSER @@ -2177,6 +2176,28 @@ config WGET_HTTPS help Enable TLS over http for wget. +config WGET_CACERT + bool "wget cacert" + depends on CMD_WGET + depends on WGET_HTTPS + help + Adds the "cacert" sub-command to wget to provide root certificates + to the HTTPS engine. Must be in DER format. + +config WGET_BUILTIN_CACERT + bool "Built-in CA certificates" + depends on WGET_HTTPS + select BUILD_BIN2C + +config WGET_BUILTIN_CACERT_PATH + string "Path to root certificates" + depends on WGET_BUILTIN_CACERT + default "cacert.crt" + help + Set this to the path to a DER-encoded X509 file containing + Certification Authority certificates, a.k.a. root certificates, for + the purpose of authenticating HTTPS connections. + endif # if CMD_NET config CMD_PXE diff --git a/cmd/net-lwip.c b/cmd/net-lwip.c index 0fd446ecb20..58c10fbec7d 100644 --- a/cmd/net-lwip.c +++ b/cmd/net-lwip.c @@ -27,9 +27,24 @@ U_BOOT_CMD(dns, 3, 1, do_dns, "lookup the IP of a hostname", #endif #if defined(CONFIG_CMD_WGET) -U_BOOT_CMD(wget, 3, 1, do_wget, - "boot image via network using HTTP/HTTPS protocol", +U_BOOT_CMD(wget, 4, 1, do_wget, + "boot image via network using HTTP/HTTPS protocol" +#if defined(CONFIG_WGET_CACERT) + "\nwget cacert - configure wget root certificates" +#endif + , "[loadAddress] url\n" - "wget [loadAddress] [host:]path" + "wget [loadAddress] [host:]path\n" + " - load file" +#if defined(CONFIG_WGET_CACERT) + "\nwget cacert <address> <length>\n" + " - provide CA certificates (0 0 to remove current)" + "\nwget cacert none|optional|required\n" + " - set server certificate verification mode (default: optional)" +#if defined(CONFIG_WGET_BUILTIN_CACERT) + "\nwget cacert builtin\n" + " - use the builtin CA certificates" +#endif +#endif ); #endif diff --git a/cmd/ufetch.c b/cmd/ufetch.c index ed5a856c7ab..46bd16824e6 100644 --- a/cmd/ufetch.c +++ b/cmd/ufetch.c @@ -24,8 +24,8 @@ DECLARE_GLOBAL_DATA_PTR; #define LINE_WIDTH 40 -#define BLUE "\033[38;5;4m" -#define YELLOW "\033[38;5;11m" +#define BLUE "\033[34m" +#define YELLOW "\033[33m" #define BOLD "\033[1m" #define RESET "\033[0m" static const char * const logo_lines[] = { diff --git a/common/Kconfig b/common/Kconfig index 1d6de8badf7..a1f65559a1b 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1080,7 +1080,7 @@ endchoice config BLOBLIST_ADDR hex "Address of bloblist" - default 0xb000 if SANDBOX + default 0x100 if SANDBOX depends on BLOBLIST_FIXED help Sets the address of the bloblist, set up by the first part of U-Boot diff --git a/common/board_f.c b/common/board_f.c index 2912320054f..baf98fb8ec8 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -828,13 +828,13 @@ static int initf_dm(void) bootstage_start(BOOTSTAGE_ID_ACCUM_DM_F, "dm_f"); ret = dm_init_and_scan(true); - bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F); if (ret) return ret; ret = dm_autoprobe(); if (ret) return ret; + bootstage_accum(BOOTSTAGE_ID_ACCUM_DM_F); if (IS_ENABLED(CONFIG_TIMER_EARLY)) { ret = dm_timer_init(); diff --git a/common/edid.c b/common/edid.c index 48a737690db..e2ac7100a88 100644 --- a/common/edid.c +++ b/common/edid.c @@ -16,6 +16,197 @@ #include <linux/ctype.h> #include <linux/string.h> +#define TIMING(c, ha, hfp, hbp, hsl, va, vfp, vbp, vsl, f) \ + .pixelclock = { (c), (c), (c) }, \ + .hactive = { (ha), (ha), (ha) }, \ + .hfront_porch = { (hfp), (hfp), (hfp) }, \ + .hback_porch = { (hbp), (hbp), (hbp) }, \ + .hsync_len = { (hsl), (hsl), (hsl) }, \ + .vactive = { (va), (va), (va) }, \ + .vfront_porch = { (vfp), (vfp), (vfp) }, \ + .vback_porch = { (vbp), (vbp), (vbp) }, \ + .vsync_len = { (vsl), (vsl), (vsl) }, \ + .flags = (f) + +static const struct display_timing dmt_timings[] = { + { TIMING(31500000, 640, 32, 64, 96, 350, 32, 3, 60, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(31500000, 640, 32, 64, 96, 400, 1, 3, 41, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(35500000, 720, 36, 72, 108, 400, 1, 3, 42, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(25175000, 640, 16, 96, 48, 480, 10, 2, 33, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(31500000, 640, 24, 40, 128, 480, 9, 3, 28, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(31500000, 640, 16, 64, 120, 480, 1, 3, 16, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(36000000, 640, 56, 56, 80, 480, 1, 3, 25, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(36000000, 800, 24, 72, 128, 600, 1, 2, 22, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(40000000, 800, 40, 128, 88, 600, 1, 4, 23, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(50000000, 800, 56, 120, 64, 600, 37, 6, 23, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(49500000, 800, 16, 80, 160, 600, 1, 3, 21, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(56250000, 800, 32, 64, 152, 600, 1, 3, 27, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(73250000, 800, 48, 32, 80, 600, 3, 4, 29, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(33750000, 848, 16, 112, 112, 480, 6, 8, 23, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(44900000, 1024, 8, 176, 56, 768, 0, 8, 41, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(65000000, 1024, 24, 136, 160, 768, 3, 6, 29, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(75000000, 1024, 24, 136, 144, 768, 3, 6, 29, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(78750000, 1024, 16, 96, 176, 768, 1, 3, 28, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(94500000, 1024, 48, 96, 208, 768, 1, 3, 36, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(115500000, 1024, 48, 32, 80, 768, 3, 4, 38, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(108000000, 1152, 64, 128, 256, 864, 1, 3, 32, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(74250000, 1280, 110, 40, 220, 720, 5, 5, 20, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(68250000, 1280, 48, 32, 80, 768, 3, 7, 12, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(79500000, 1280, 64, 128, 192, 768, 3, 7, 20, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(102250000, 1280, 80, 128, 208, 768, 3, 7, 27, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(117500000, 1280, 80, 136, 216, 768, 3, 7, 31, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(140250000, 1280, 48, 32, 80, 768, 3, 7, 35, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(71000000, 1280, 48, 32, 80, 800, 3, 6, 14, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(83500000, 1280, 72, 128, 200, 800, 3, 6, 22, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(106500000, 1280, 80, 128, 208, 800, 3, 6, 29, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(122500000, 1280, 80, 136, 216, 800, 3, 6, 34, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(146250000, 1280, 48, 32, 80, 800, 3, 6, 38, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(108000000, 1280, 96, 112, 312, 960, 1, 3, 36, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(148500000, 1280, 64, 160, 224, 960, 1, 3, 47, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(175500000, 1280, 48, 32, 80, 960, 3, 4, 50, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(108000000, 1280, 48, 112, 248, 1024, 1, 3, 38, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(135000000, 1280, 16, 144, 248, 1024, 1, 3, 38, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(157500000, 1280, 64, 160, 224, 1024, 1, 3, 44, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(187250000, 1280, 48, 32, 80, 1024, 3, 7, 50, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(85500000, 1360, 64, 112, 256, 768, 3, 6, 18, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(148250000, 1360, 48, 32, 80, 768, 3, 5, 37, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(85500000, 1366, 70, 143, 213, 768, 3, 3, 24, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(72000000, 1366, 14, 56, 64, 768, 1, 3, 28, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(101000000, 1400, 48, 32, 80, 1050, 3, 4, 23, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(121750000, 1400, 88, 144, 232, 1050, 3, 4, 32, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(156000000, 1400, 104, 144, 248, 1050, 3, 4, 42, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(179500000, 1400, 104, 152, 256, 1050, 3, 4, 48, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(208000000, 1400, 48, 32, 80, 1050, 3, 4, 55, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(88750000, 1440, 48, 32, 80, 900, 3, 6, 17, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(106500000, 1440, 80, 152, 232, 900, 3, 6, 25, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(136750000, 1440, 96, 152, 248, 900, 3, 6, 33, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(157000000, 1440, 104, 152, 256, 900, 3, 6, 39, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(182750000, 1440, 48, 32, 80, 900, 3, 6, 44, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(108000000, 1600, 24, 80, 96, 900, 1, 3, 96, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(162000000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(175500000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(189000000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(202500000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(229500000, 1600, 64, 192, 304, 1200, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(268250000, 1600, 48, 32, 80, 1200, 3, 4, 64, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(119000000, 1680, 48, 32, 80, 1050, 3, 6, 21, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(146250000, 1680, 104, 176, 280, 1050, 3, 6, 30, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(187000000, 1680, 120, 176, 296, 1050, 3, 6, 40, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(214750000, 1680, 128, 176, 304, 1050, 3, 6, 46, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(245500000, 1680, 48, 32, 80, 1050, 3, 6, 53, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(204750000, 1792, 128, 200, 328, 1344, 1, 3, 46, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(261000000, 1792, 96, 216, 352, 1344, 1, 3, 69, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(333250000, 1792, 48, 32, 80, 1344, 3, 4, 72, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(218250000, 1856, 96, 224, 352, 1392, 1, 3, 43, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(288000000, 1856, 128, 224, 352, 1392, 1, 3, 104, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(356500000, 1856, 48, 32, 80, 1392, 3, 4, 75, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(148500000, 1920, 88, 44, 148, 1080, 4, 5, 36, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(154000000, 1920, 48, 32, 80, 1200, 3, 6, 26, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(193250000, 1920, 136, 200, 336, 1200, 3, 6, 36, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(245250000, 1920, 136, 208, 344, 1200, 3, 6, 46, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(281250000, 1920, 144, 208, 352, 1200, 3, 6, 53, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(317000000, 1920, 48, 32, 80, 1200, 3, 6, 62, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(234000000, 1920, 128, 208, 344, 1440, 1, 3, 56, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(297000000, 1920, 144, 224, 352, 1440, 1, 3, 56, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(380500000, 1920, 48, 32, 80, 1440, 3, 4, 78, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(162000000, 2048, 26, 80, 96, 1152, 1, 3, 44, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(268500000, 2560, 48, 32, 80, 1600, 3, 6, 37, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(348500000, 2560, 192, 280, 472, 1600, 3, 6, 49, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(443250000, 2560, 208, 280, 488, 1600, 3, 6, 63, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(505250000, 2560, 208, 280, 488, 1600, 3, 6, 73, + DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_HIGH) }, + { TIMING(552750000, 2560, 48, 32, 80, 1600, 3, 6, 85, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(556744000, 4096, 8, 32, 40, 2160, 48, 8, 6, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, + { TIMING(556188000, 4096, 8, 32, 40, 2160, 48, 8, 6, + DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW) }, +}; + int edid_check_info(struct edid1_info *edid_info) { if ((edid_info == NULL) || (edid_info->version == 0)) @@ -168,11 +359,11 @@ static bool cea_is_hdmi_vsdb_present(struct edid_cea861_info *info) return false; } -static bool edid_find_valid_timing(void *buf, int count, - struct display_timing *timing, - bool (*mode_valid)(void *priv, - const struct display_timing *timing), - void *mode_valid_priv) +static bool edid_find_valid_detailed_timing(void *buf, int count, + struct display_timing *timing, + bool (*mode_valid)(void *priv, + const struct display_timing *timing), + void *mode_valid_priv) { struct edid_detailed_timing *t = buf; bool found = false; @@ -191,6 +382,71 @@ static bool edid_find_valid_timing(void *buf, int count, return found; } +static bool edid_get_standard_timing(struct edid1_info *edid, int i, unsigned int *x, + unsigned int *y, unsigned int *freq) +{ + unsigned int aspect = 10000; + unsigned char xres, vfreq; + + xres = EDID1_INFO_STANDARD_TIMING_XRESOLUTION(*edid, i); + vfreq = EDID1_INFO_STANDARD_TIMING_VFREQ(*edid, i); + if (xres != vfreq || (xres != 0 && xres != 1) || + (vfreq != 0 && vfreq != 1)) { + switch (EDID1_INFO_STANDARD_TIMING_ASPECT(*edid, i)) { + case ASPECT_625: // 16:10 + aspect = 6250; + break; + case ASPECT_75: // 4:3 + aspect = 7500; + break; + case ASPECT_8: // 5:4 + aspect = 8000; + break; + case ASPECT_5625: // 16:9 + aspect = 5625; + break; + } + + *x = (xres + 31) * 8; + *y = *x * aspect / 10000; + *freq = (vfreq & 0x3f) + 60; + + return true; + } + + return false; +} + +static bool edid_find_valid_standard_timing(struct edid1_info *buf, + struct display_timing *timing, + bool (*mode_valid)(void *priv, + const struct display_timing *timing), + void *mode_valid_priv) +{ + unsigned int x, y, freq; + bool found = false; + int i, k; + + for (i = 0; i < ARRAY_SIZE(buf->standard_timings); i++) { + if (!edid_get_standard_timing(buf, i, &x, &y, &freq)) + continue; + + for (k = 0; k < ARRAY_SIZE(dmt_timings); k++) { + const struct display_timing *dt = &dmt_timings[k]; + + if (dt->hactive.typ == x && dt->vactive.typ == y) { + found = mode_valid(mode_valid_priv, dt); + if (found) { + memcpy(timing, dt, sizeof(*timing)); + return true; + } + } + } + } + + return found; +} + int edid_get_timing_validate(u8 *buf, int buf_size, struct display_timing *timing, int *panel_bits_per_colourp, @@ -217,8 +473,8 @@ int edid_get_timing_validate(u8 *buf, int buf_size, } /* Look for detailed timing in base EDID */ - found = edid_find_valid_timing(edid->monitor_details.descriptor, 4, - timing, mode_valid, mode_valid_priv); + found = edid_find_valid_detailed_timing(edid->monitor_details.descriptor, 4, + timing, mode_valid, mode_valid_priv); /* Look for detailed timing in CTA-861 Extension Block */ if (!found && edid->extension_flag && buf_size >= EDID_EXT_SIZE) { @@ -231,12 +487,17 @@ int edid_get_timing_validate(u8 *buf, int buf_size, int size = count * sizeof(struct edid_detailed_timing); if (offset >= 4 && offset + size < EDID_SIZE) - found = edid_find_valid_timing( + found = edid_find_valid_detailed_timing( (u8 *)info + offset, count, timing, mode_valid, mode_valid_priv); } } + /* Look for timing in Standard Timings */ + if (!found) + found = edid_find_valid_standard_timing(edid, timing, mode_valid, + mode_valid_priv); + if (!found) return -EINVAL; @@ -461,34 +722,11 @@ void edid_print_info(struct edid1_info *edid_info) /* Standard timings. */ printf("Standard timings:\n"); for (i = 0; i < ARRAY_SIZE(edid_info->standard_timings); i++) { - unsigned int aspect = 10000; - unsigned int x, y; - unsigned char xres, vfreq; - - xres = EDID1_INFO_STANDARD_TIMING_XRESOLUTION(*edid_info, i); - vfreq = EDID1_INFO_STANDARD_TIMING_VFREQ(*edid_info, i); - if ((xres != vfreq) || - ((xres != 0) && (xres != 1)) || - ((vfreq != 0) && (vfreq != 1))) { - switch (EDID1_INFO_STANDARD_TIMING_ASPECT(*edid_info, - i)) { - case ASPECT_625: - aspect = 6250; - break; - case ASPECT_75: - aspect = 7500; - break; - case ASPECT_8: - aspect = 8000; - break; - case ASPECT_5625: - aspect = 5625; - break; - } - x = (xres + 31) * 8; - y = x * aspect / 10000; + unsigned int x, y, freq; + + if (edid_get_standard_timing(edid_info, i, &x, &y, &freq)) { printf("\t%dx%d%c\t%d Hz\n", x, y, - x > 1000 ? ' ' : '\t', (vfreq & 0x3f) + 60); + x > 1000 ? ' ' : '\t', freq); have_timing = 1; } } diff --git a/common/miiphyutil.c b/common/miiphyutil.c index 2a034d3a77c..274e88a4921 100644 --- a/common/miiphyutil.c +++ b/common/miiphyutil.c @@ -30,7 +30,7 @@ #define debug(fmt, args...) #endif /* MII_DEBUG */ -static struct list_head mii_devs; +static LIST_HEAD(mii_devs); static struct mii_dev *current_mii; /* @@ -55,24 +55,6 @@ struct mii_dev *miiphy_get_dev_by_name(const char *devname) return NULL; } -/***************************************************************************** - * - * Initialize global data. Need to be called before any other miiphy routine. - */ -void miiphy_init(void) -{ - INIT_LIST_HEAD(&mii_devs); - current_mii = NULL; -} - -void mdio_init(struct mii_dev *bus) -{ - memset(bus, 0, sizeof(*bus)); - - /* initialize mii_dev struct fields */ - INIT_LIST_HEAD(&bus->link); -} - struct mii_dev *mdio_alloc(void) { struct mii_dev *bus; @@ -81,7 +63,10 @@ struct mii_dev *mdio_alloc(void) if (!bus) return bus; - mdio_init(bus); + memset(bus, 0, sizeof(*bus)); + + /* initialize mii_dev struct fields */ + INIT_LIST_HEAD(&bus->link); return bus; } diff --git a/common/stdio.c b/common/stdio.c index a61220ce4b9..3eeb289dd8b 100644 --- a/common/stdio.c +++ b/common/stdio.c @@ -357,9 +357,6 @@ int stdio_add_devices(void) drv_system_init(); serial_stdio_init(); -#ifdef CONFIG_USB_TTY - drv_usbtty_init(); -#endif #ifdef CONFIG_USB_FUNCTION_ACM drv_usbacm_init (); #endif diff --git a/configs/amd_versal2_virt_defconfig b/configs/amd_versal2_virt_defconfig index 8bee002777a..9911caa0e46 100644 --- a/configs/amd_versal2_virt_defconfig +++ b/configs/amd_versal2_virt_defconfig @@ -70,7 +70,6 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_LWIP=y CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_TFTP_BLOCKSIZE=4096 CONFIG_SIMPLE_PM_BUS=y CONFIG_CLK_CCF=y CONFIG_CLK_SCMI=y diff --git a/configs/endeavoru_defconfig b/configs/endeavoru_defconfig index 1d1f1042291..cc8777e4d83 100644 --- a/configs/endeavoru_defconfig +++ b/configs/endeavoru_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/grouper_defconfig b/configs/grouper_defconfig index 9221ffb46a3..f265db8232f 100644 --- a/configs/grouper_defconfig +++ b/configs/grouper_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/imx8mm_evk_defconfig b/configs/imx8mm_evk_defconfig index 659fc9ec039..2048391439f 100644 --- a/configs/imx8mm_evk_defconfig +++ b/configs/imx8mm_evk_defconfig @@ -25,7 +25,8 @@ CONFIG_FIT=y CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_DEFAULT_FDT_FILE="imx8mp-evk.dtb" +CONFIG_BOOTCOMMAND="bootflow scan -lb; run bsp_bootcmd" +CONFIG_DEFAULT_FDT_FILE="imx8mm-evk.dtb" CONFIG_SYS_CBSIZE=2048 CONFIG_SYS_PBSIZE=2074 CONFIG_BOARD_LATE_INIT=y diff --git a/configs/imx8mm_evk_fspi_defconfig b/configs/imx8mm_evk_fspi_defconfig index 4a8d4994b80..59ebdc5782f 100644 --- a/configs/imx8mm_evk_fspi_defconfig +++ b/configs/imx8mm_evk_fspi_defconfig @@ -5,7 +5,6 @@ CONFIG_SYS_MALLOC_LEN=0x2000000 CONFIG_SPL_GPIO=y CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y -CONFIG_ENV_SOURCE_FILE="imx8mn_evk" CONFIG_SF_DEFAULT_SPEED=40000000 CONFIG_SF_DEFAULT_MODE=0 CONFIG_ENV_SIZE=0x1000 @@ -29,7 +28,8 @@ CONFIG_FIT=y CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_DEFAULT_FDT_FILE="imx8mp-evk.dtb" +CONFIG_BOOTCOMMAND="bootflow scan -lb; run bsp_bootcmd" +CONFIG_DEFAULT_FDT_FILE="imx8mm-evk.dtb" CONFIG_SYS_CBSIZE=2048 CONFIG_SYS_PBSIZE=2074 CONFIG_BOARD_LATE_INIT=y diff --git a/configs/imx8mq_evk_defconfig b/configs/imx8mq_evk_defconfig index 97ef352dfb8..0de98152b2b 100644 --- a/configs/imx8mq_evk_defconfig +++ b/configs/imx8mq_evk_defconfig @@ -32,7 +32,7 @@ CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_SPL_LOAD_FIT=y CONFIG_OF_SYSTEM_SETUP=y CONFIG_BOOTCOMMAND="bootflow scan -lb; run bsp_bootcmd" -CONFIG_DEFAULT_FDT_FILE="imx8mp-evk.dtb" +CONFIG_DEFAULT_FDT_FILE="imx8mq-evk.dtb" CONFIG_SYS_PBSIZE=1050 CONFIG_BOARD_EARLY_INIT_F=y CONFIG_BOARD_LATE_INIT=y diff --git a/configs/mocha_defconfig b/configs/mocha_defconfig new file mode 100644 index 00000000000..0cbedb21797 --- /dev/null +++ b/configs/mocha_defconfig @@ -0,0 +1,91 @@ +CONFIG_ARM=y +CONFIG_ARCH_TEGRA=y +CONFIG_SUPPORT_PASSING_ATAGS=y +CONFIG_CMDLINE_TAG=y +CONFIG_INITRD_TAG=y +CONFIG_TEXT_BASE=0x80110000 +CONFIG_SYS_MALLOC_LEN=0x2500000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_ENV_SOURCE_FILE="mocha" +CONFIG_ENV_SIZE=0x3000 +CONFIG_ENV_OFFSET=0xFFFFD000 +CONFIG_DEFAULT_DEVICE_TREE="tegra124-xiaomi-mocha" +CONFIG_SPL_STACK=0x800ffffc +CONFIG_SPL_TEXT_BASE=0x80108000 +CONFIG_SYS_LOAD_ADDR=0x82000000 +CONFIG_TEGRA124=y +CONFIG_TARGET_MOCHA=y +CONFIG_TEGRA_ENABLE_UARTD=y +CONFIG_CMD_EBTUPDATE=y +CONFIG_TEGRA_GPU=y +CONFIG_BUTTON_CMD=y +CONFIG_BOOTDELAY=0 +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_KEYED_CTRLC=y +CONFIG_OF_SYSTEM_SETUP=y +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" +CONFIG_SYS_PBSIZE=2086 +CONFIG_SPL_FOOTPRINT_LIMIT=y +CONFIG_SPL_MAX_FOOTPRINT=0x8000 +# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0x80090000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x10000 +CONFIG_SYS_PROMPT="Tegra124 (Mocha) # " +# CONFIG_CMD_BOOTEFI_BOOTMGR is not set +CONFIG_CMD_BOOTMENU=y +# CONFIG_CMD_IMI is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_GPT_RENAME=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_POWEROFF=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_CMD_UMS_ABORT_KEYED=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_PAUSE=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT4_WRITE=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_ENV_OVERWRITE=y +CONFIG_SYS_RELOC_GD_ENV_ADDR=y +CONFIG_SYS_MMC_ENV_PART=2 +CONFIG_BUTTON=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0x91000000 +CONFIG_FASTBOOT_BUF_SIZE=0x10000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_PALMAS_GPIO=y +CONFIG_SYS_I2C_TEGRA=y +CONFIG_BUTTON_KEYBOARD=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_PALMAS=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_PALMAS=y +CONFIG_PWM_TEGRA=y +CONFIG_SYS_NS16550=y +CONFIG_SYSRESET_PALMAS=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_TEGRA=y +CONFIG_USB_KEYBOARD=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Xiaomi" +CONFIG_USB_GADGET_VENDOR_NUM=0x18d1 +CONFIG_USB_GADGET_PRODUCT_NUM=0xd00d +CONFIG_CI_UDC=y +CONFIG_VIDEO=y +CONFIG_VIDEO_BRIDGE=y +# CONFIG_VIDEO_FONT_8X16 is not set +CONFIG_VIDEO_FONT_16X32=y +# CONFIG_VIDEO_LOGO is not set +CONFIG_VIDEO_LCD_SHARP_LQ079L1SX01=y +CONFIG_BACKLIGHT_LP855x=y +CONFIG_VIDEO_DSI_TEGRA30=y diff --git a/configs/nanopi-r3s-rk3566_defconfig b/configs/nanopi-r3s-rk3566_defconfig index 870613f690a..16e09753a72 100644 --- a/configs/nanopi-r3s-rk3566_defconfig +++ b/configs/nanopi-r3s-rk3566_defconfig @@ -54,7 +54,6 @@ CONFIG_PHY_REALTEK=y CONFIG_DWC_ETH_QOS=y CONFIG_DWC_ETH_QOS_ROCKCHIP=y CONFIG_RTL8169=y -CONFIG_NVME_PCI=y CONFIG_PCIE_DW_ROCKCHIP=y CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y diff --git a/configs/picasso_defconfig b/configs/picasso_defconfig index 994951bb81e..a9b7f91b735 100644 --- a/configs/picasso_defconfig +++ b/configs/picasso_defconfig @@ -21,7 +21,7 @@ CONFIG_BOOTDELAY=0 CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2085 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/qc750_defconfig b/configs/qc750_defconfig index 2485e64a2f0..e958e0d53ca 100644 --- a/configs/qc750_defconfig +++ b/configs/qc750_defconfig @@ -22,7 +22,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig index e4abfdf16bb..661a484f7bf 100644 --- a/configs/qcom_defconfig +++ b/configs/qcom_defconfig @@ -45,6 +45,7 @@ CONFIG_USE_DEFAULT_ENV_FILE=y CONFIG_DEFAULT_ENV_FILE="board/qualcomm/default.env" CONFIG_BUTTON_QCOM_PMIC=y CONFIG_CLK=y +CONFIG_CLK_STUB=y CONFIG_CLK_QCOM_APQ8016=y CONFIG_CLK_QCOM_APQ8096=y CONFIG_CLK_QCOM_QCM2290=y diff --git a/configs/qemu_arm64_lwip_defconfig b/configs/qemu_arm64_lwip_defconfig index 754c770c33f..814e98729a3 100644 --- a/configs/qemu_arm64_lwip_defconfig +++ b/configs/qemu_arm64_lwip_defconfig @@ -8,3 +8,4 @@ CONFIG_CMD_DNS=y CONFIG_CMD_WGET=y CONFIG_EFI_HTTP_BOOT=y CONFIG_WGET_HTTPS=y +CONFIG_WGET_CACERT=y diff --git a/configs/rcar3_salvator-x_defconfig b/configs/rcar3_salvator-x_defconfig index 6b095f63549..39a98ccf577 100644 --- a/configs/rcar3_salvator-x_defconfig +++ b/configs/rcar3_salvator-x_defconfig @@ -28,6 +28,8 @@ CONFIG_CMD_DFU=y CONFIG_CMD_MMC=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +CONFIG_DM_USB_GADGET=y CONFIG_OF_LIST="renesas/r8a77951-salvator-x renesas/r8a77960-salvator-x renesas/r8a77965-salvator-x" CONFIG_MULTI_DTB_FIT_LZO=y CONFIG_MULTI_DTB_FIT_USER_DEFINED_AREA=y @@ -74,4 +76,10 @@ CONFIG_USB=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Renesas" +CONFIG_USB_GADGET_VENDOR_NUM=0x045b +CONFIG_USB_GADGET_PRODUCT_NUM=0x023c +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_USB_RENESAS_USBHS=y CONFIG_USB_STORAGE=y diff --git a/configs/rock-s0-rk3308_defconfig b/configs/rock-s0-rk3308_defconfig index 0a46e7bb187..063e0b921d7 100644 --- a/configs/rock-s0-rk3308_defconfig +++ b/configs/rock-s0-rk3308_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_SKIP_LOWLEVEL_INIT=y CONFIG_COUNTER_FREQUENCY=24000000 CONFIG_ARCH_ROCKCHIP=y +CONFIG_SPL_GPIO=y CONFIG_DEFAULT_DEVICE_TREE="rockchip/rk3308-rock-s0" CONFIG_DM_RESET=y CONFIG_ROCKCHIP_RK3308=y @@ -53,6 +54,7 @@ CONFIG_PHY_ROCKCHIP_INNO_USB2=y CONFIG_PINCTRL=y CONFIG_REGULATOR_PWM=y CONFIG_DM_REGULATOR_FIXED=y +CONFIG_SPL_DM_REGULATOR_FIXED=y CONFIG_PWM_ROCKCHIP=y CONFIG_RAM=y CONFIG_BAUDRATE=1500000 diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 7b35ad8a88f..0b3c765389c 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -328,6 +328,8 @@ CONFIG_USB_ETH_CDC=y CONFIG_VIDEO=y CONFIG_VIDEO_FONT_SUN12X22=y CONFIG_VIDEO_COPY=y +CONFIG_VIDEO_BRIDGE=y +CONFIG_VIDEO_BRIDGE_LVDS_CODEC=y CONFIG_CONSOLE_ROTATION=y CONFIG_CONSOLE_TRUETYPE=y CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y @@ -354,7 +356,6 @@ CONFIG_ADDR_MAP=y CONFIG_PANIC_HANG=y CONFIG_CMD_DHRYSTONE=y CONFIG_MBEDTLS_LIB=y -CONFIG_MBEDTLS_LIB_CRYPTO=y CONFIG_HKDF_MBEDTLS=y CONFIG_ECDSA=y CONFIG_ECDSA_VERIFY=y diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig index f0315f6ab33..46329395ba5 100644 --- a/configs/sandbox_vpl_defconfig +++ b/configs/sandbox_vpl_defconfig @@ -252,8 +252,6 @@ CONFIG_FS_CBFS=y CONFIG_FS_CRAMFS=y # CONFIG_SPL_USE_TINY_PRINTF is not set CONFIG_CMD_DHRYSTONE=y -CONFIG_VPL_SHA1_LEGACY=y -CONFIG_VPL_SHA256_LEGACY=y CONFIG_RSA_VERIFY_WITH_PKEY=y CONFIG_TPM=y CONFIG_ZSTD=y diff --git a/configs/snow_defconfig b/configs/snow_defconfig index 7a1dc80b1cc..27698f5ef36 100644 --- a/configs/snow_defconfig +++ b/configs/snow_defconfig @@ -34,6 +34,8 @@ CONFIG_SYS_PBSIZE=1024 CONFIG_SILENT_CONSOLE=y CONFIG_BLOBLIST=y # CONFIG_SPL_BLOBLIST is not set +CONFIG_BLOBLIST_FIXED=y +CONFIG_BLOBLIST_ADDR=0x43d00000 # CONFIG_SPL_FRAMEWORK is not set CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x3800 diff --git a/configs/transformer_t20_defconfig b/configs/transformer_t20_defconfig index b69366581a4..6f823ec720e 100644 --- a/configs/transformer_t20_defconfig +++ b/configs/transformer_t20_defconfig @@ -21,7 +21,7 @@ CONFIG_BOOTDELAY=0 CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2085 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/transformer_t30_defconfig b/configs/transformer_t30_defconfig index c5f0bc2a613..9d63755533a 100644 --- a/configs/transformer_t30_defconfig +++ b/configs/transformer_t30_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/x3_t30_defconfig b/configs/x3_t30_defconfig index c8da5b4ce35..2d72a3bd56f 100644 --- a/configs/x3_t30_defconfig +++ b/configs/x3_t30_defconfig @@ -21,7 +21,7 @@ CONFIG_AUTOBOOT_KEYED=y CONFIG_AUTOBOOT_KEYED_CTRLC=y CONFIG_OF_BOARD_SETUP=y CONFIG_OF_SYSTEM_SETUP=y -CONFIG_BOOTCOMMAND="bootflow scan; poweroff" +CONFIG_BOOTCOMMAND="bootflow scan; echo 'Boot configuration not found... Power off in 3 sec'; sleep 3; poweroff" CONFIG_SYS_PBSIZE=2084 CONFIG_SPL_FOOTPRINT_LIMIT=y CONFIG_SPL_MAX_FOOTPRINT=0x8000 diff --git a/configs/xilinx_versal_net_virt_defconfig b/configs/xilinx_versal_net_virt_defconfig index 5ef5fd44fd3..1604b5915db 100644 --- a/configs/xilinx_versal_net_virt_defconfig +++ b/configs/xilinx_versal_net_virt_defconfig @@ -70,7 +70,6 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_LWIP=y CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_TFTP_BLOCKSIZE=4096 CONFIG_SIMPLE_PM_BUS=y CONFIG_CLK_VERSAL=y CONFIG_DFU_RAM=y diff --git a/configs/xilinx_versal_virt_defconfig b/configs/xilinx_versal_virt_defconfig index f228eef7c95..baa4b8e412e 100644 --- a/configs/xilinx_versal_virt_defconfig +++ b/configs/xilinx_versal_virt_defconfig @@ -74,7 +74,6 @@ CONFIG_SYS_REDUNDAND_ENVIRONMENT=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_LWIP=y CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_TFTP_BLOCKSIZE=4096 CONFIG_SIMPLE_PM_BUS=y CONFIG_CLK_VERSAL=y CONFIG_DFU_TIMEOUT=y diff --git a/doc/arch/sandbox/sandbox.rst b/doc/arch/sandbox/sandbox.rst index a8b0d7f0395..7e641306da2 100644 --- a/doc/arch/sandbox/sandbox.rst +++ b/doc/arch/sandbox/sandbox.rst @@ -658,10 +658,10 @@ that are mapped into that memory: ======== ======================== =============================== Addr Config Usage ======== ======================== =============================== - 100 CONFIG_SYS_FDT_LOAD_ADDR Device tree - b000 CONFIG_BLOBLIST_ADDR Blob list - 10000 CFG_MALLOC_F_ADDR Early memory allocation + 100 CONFIG_BLOBLIST_ADDR Blob list + 1000 CONFIG_SYS_FDT_LOAD_ADDR Device tree f0000 CONFIG_PRE_CON_BUF_ADDR Pre-console buffer + f4000 CFG_MALLOC_F_ADDR Early memory allocation 100000 TCG Event log TCG Event Log 200000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled). Also used 400000 CONFIG_TEXT_BASE Load buffer for U-Boot (sandbox_spl only) diff --git a/doc/board/index.rst b/doc/board/index.rst index b055046e649..84c135e02c1 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -69,4 +69,5 @@ Board-specific doc variscite/index wexler/index xen/index + xiaomi/index xilinx/index diff --git a/doc/board/xiaomi/index.rst b/doc/board/xiaomi/index.rst new file mode 100644 index 00000000000..109ab4a251f --- /dev/null +++ b/doc/board/xiaomi/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Xiaomi +====== + +.. toctree:: + :maxdepth: 2 + + mocha diff --git a/doc/board/xiaomi/mocha.rst b/doc/board/xiaomi/mocha.rst new file mode 100644 index 00000000000..be3e333127b --- /dev/null +++ b/doc/board/xiaomi/mocha.rst @@ -0,0 +1,112 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot for the Xiaomi Mi Pad tablet +=================================== + +``DISCLAMER!`` Moving your Xiaomi Mi Pad to use U-Boot assumes replacement +of the vendor bootloader. Vendor Android firmwares will no longer be able +to run on the device. This replacement IS reversible. + +Quick Start +----------- + +- Build U-Boot +- Boot U-Boot +- Process and flash U-Boot +- Boot Linux +- Self Upgrading +- Chainload configuration + +Build U-Boot +------------ + +.. code-block:: bash + + $ export CROSS_COMPILE=arm-none-eabi- + $ make mocha_defconfig + $ make + +After the build succeeds, you will obtain the final ``u-boot-dtb-tegra.bin`` +image, ready for booting or further processing. + +Boot U-Boot +----------- +Existing tegrarcm loader can be used to pre-load U-Boot you have build +into RAM and basically perform a tethered cold-boot. + +.. code-block:: bash + + $ tegrarcm --bct mocha.bct --bootloader u-boot-dtb-tegra.bin --loadaddr 0x80108000 + +U-Boot will try to load Linux kernel and if fails, it will turn the +tablet off. While pre-loading U-Boot, hold the ``volume down`` button +which will trigger the bootmenu. + +Process and flash U-Boot +------------------------ + +``DISCLAMER!`` All questions related to the re-crypt work should be asked +in re-crypt repo issues. NOT HERE! + +re-crypt is a tool that processes the ``u-boot-dtb-tegra.bin`` binary into +form usable by device. This process is required only on the first +installation or to recover the device in case of a failed update. + +.. code-block:: bash + + $ git clone https://gitlab.com/grate-driver/re-crypt.git + $ cd re-crypt # place your u-boot-dtb-tegra.bin here + $ ./re-crypt.py --dev mocha + +The script will produce ``bct.img`` and ``ebt.img`` ready to flash. + +Permanent installation can be performed by pre-loading just built U-Boot +into RAM via tegrarcm. While pre-loading U-Boot, hold the ``volume down`` +button which will trigger the bootmenu. There, select ``fastboot`` using +the volume and power buttons. + +After, on host PC, do: + +.. code-block:: bash + + $ fastboot flash 0.1 bct.img + $ fastboot flash 0.2 ebt.img + $ fastboot reboot + +Device will reboot. + +Boot Linux +---------- + +To boot Linux, U-Boot will look for an ``extlinux.conf`` on MicroSD and then on +eMMC. Additionally, if the ``volume down`` button is pressed while booting, the +device will enter bootmenu. Bootmenu contains entries to mount MicroSD and eMMC +as mass storage, fastboot, reboot, reboot RCM, poweroff, enter U-Boot console +and update bootloader (check the next chapter). + +Flashing ``bct.img`` and ``ebt.img`` eliminates vendor restrictions on eMMC and +allows the user to use/partition it in any way the user desires. + +Self Upgrading +-------------- + +Place your ``u-boot-dtb-tegra.bin`` on the first partition of the MicroSD card +and insert it into the tablet. Enter bootmenu, choose update the bootloader +option with the Power button and U-Boot should update itself. Once the process +is completed, U-Boot will ask to press any button to reboot. + +Chainload configuration +----------------------- + +To build U-Boot without SPL suitable for chainloading adjust mocha_defconfig: + +.. code-block:: + + CONFIG_TEXT_BASE=0x80A00000 + CONFIG_SKIP_LOWLEVEL_INIT=y + # CONFIG_OF_BOARD_SETUP is not set + CONFIG_TEGRA_SUPPORT_NON_SECURE=y + +After the build succeeds, you will obtain the final ``u-boot-dtb.bin`` +file, ready for booting using vendor bootloader's fastboot or which can be +further processed into a flashable image. diff --git a/doc/develop/release_cycle.rst b/doc/develop/release_cycle.rst index b6ad7218614..dc5bb340ff2 100644 --- a/doc/develop/release_cycle.rst +++ b/doc/develop/release_cycle.rst @@ -74,7 +74,7 @@ For the next scheduled release, release candidates were made on:: * U-Boot v2025.04-rc3 was released on Mon 24 February 2025. -.. * U-Boot v2025.04-rc4 was released on Mon 10 March 2025. +* U-Boot v2025.04-rc4 was released on Mon 10 March 2025. .. * U-Boot v2025.04-rc5 was released on Mon 24 March 2025. diff --git a/doc/device-tree-bindings/pinctrl/adi,adsp-pinctrl.yaml b/doc/device-tree-bindings/pinctrl/adi,adsp-pinctrl.yaml new file mode 100644 index 00000000000..418ebd5ce41 --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/adi,adsp-pinctrl.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/adi,adsp-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Pinctrl Driver for Analog Devices SC5xx Processors + +maintainers: + - Vasileios Bimpikas <vasileios.bimpikas@analog.com> + - Utsav Agarwal <utsav.agarwal@analog.com> + - Arturs Artamonovs <arturs.artamonovs@analog.com> + +description: | + This driver provides an interface for performing pin configuration + Analog Devices SoCs using the ADSP PORT hardware for pin + configuration according to the HRM. Currently this is only the + SC5xx series. + +properties: + compatible: + const: adi,adsp-pinctrl + + reg: + maxItems: 1 + + adi,npins: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Total number of pins available to this SoC's pin controller, + found in the HRM. + +patternProperties: + '_pins$': + type: object + + properties: + adi,pins: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + For n pins, 2n values must be provided as a sequence of pin + name as identified with the ADI_ADSP_PIN() macro and a pin + function constant, both defined in + include/dt-bindings/pinctrl/adi-adsp.h. + + required: + - adi,pins + + additionalProperties: false + +required: + - compatible + - reg + - adi,npins + +additionalProperties: false + +examples: + - | + #include <dt-bindings/pinctrl/adi-adsp.h> + + soc { + pinctrl0: pinctrl@0x31004000 { + compatible = "adi,adsp-pinctrl"; + reg = <0x31004000 0x500>; + adi,npins = <135>; + uart0_default: uart0_pins { + adi,pins = <ADI_ADSP_PIN('A', 6) ADI_ADSP_PINFUNC_ALT1>, + <ADI_ADSP_PIN('A', 7) ADI_ADSP_PINFUNC_ALT1>; + }; + }; + + }; diff --git a/doc/usage/cmd/wget.rst b/doc/usage/cmd/wget.rst index 48bedf1e845..cc82e495a29 100644 --- a/doc/usage/cmd/wget.rst +++ b/doc/usage/cmd/wget.rst @@ -12,7 +12,9 @@ Synopsis :: wget [address] [host:]path - wget [address] url # lwIP only + wget [address] url # lwIP only + wget cacert none|optional|required # lwIP only + wget cacert <address> <size> # lwIP only Description @@ -54,6 +56,32 @@ address url HTTP or HTTPS URL, that is: http[s]://<host>[:<port>]/<path>. +The cacert (stands for 'Certification Authority certificates') subcommand is +used to provide root certificates for the purpose of HTTPS authentication. It +also allows to enable or disable authentication. + +wget cacert <address> <size> + +address + memory address of the root certificates in X509 DER format + +size + the size of the root certificates + +wget cacert none|optional|required + +none + certificate verification is disabled. HTTPS is used without any server + authentication (unsafe) +optional + certificate verification is enabled provided root certificates have been + provided via wget cacert <addr> <size> or wget cacert builtin. Otherwise + HTTPS is used without any server authentication (unsafe). +required + certificate verification is mandatory. If no root certificates have been + configured, HTTPS transfers will fail. + + Examples -------- @@ -97,11 +125,61 @@ In the example the following steps are executed: 1694892032 bytes transferred in 492181 ms (3.3 MiB/s) Bytes transferred = 1694892032 (65060000 hex) +Here is an example showing how to configure built-in root certificates as +well as providing some at run time. In this example it is assumed that +CONFIG_WGET_BUILTIN_CACERT_PATH=DigiCertTLSRSA4096RootG5.crt downloaded from +https://cacerts.digicert.com/DigiCertTLSRSA4096RootG5.crt. + +:: + + # Make sure IP is configured + => dhcp + # When built-in certificates are configured, authentication is mandatory + # (i.e., "wget cacert required"). Use a test server... + => wget https://digicert-tls-rsa4096-root-g5.chain-demos.digicert.com/ + 1864 bytes transferred in 1 ms (1.8 MiB/s) + Bytes transferred = 1864 (748 hex) + # Another server not signed against Digicert will fail + => wget https://www.google.com/ + Certificate verification failed + + HTTP client error 4 + # Disable authentication to allow the command to proceed anyways + => wget cacert none + => wget https://www.google.com/ + WARNING: no CA certificates, HTTPS connections not authenticated + 16683 bytes transferred in 15 ms (1.1 MiB/s) + Bytes transferred = 16683 (412b hex) + # Force verification but unregister the CA certificates + => wget cacert required + => wget cacert 0 0 + # Unsurprisingly, download fails + => wget https://digicert-tls-rsa4096-root-g5.chain-demos.digicert.com/ + Error: cacert authentication mode is 'required' but no CA certificates given + # Get the same certificates as above from the network + => wget cacert none + => wget https://cacerts.digicert.com/DigiCertTLSRSA4096RootG5.crt + WARNING: no CA certificates, HTTPS connections not authenticated + 1386 bytes transferred in 1 ms (1.3 MiB/s) + Bytes transferred = 1386 (56a hex) + # Register them and force authentication + => wget cacert $fileaddr $filesize + => wget cacert required + # Authentication is operational again + => wget https://digicert-tls-rsa4096-root-g5.chain-demos.digicert.com/ + 1864 bytes transferred in 1 ms (1.8 MiB/s) + Bytes transferred = 1864 (748 hex) + # The builtin certificates can be restored at any time + => wget cacert builtin + Configuration ------------- The command is only available if CONFIG_CMD_WGET=y. -To enable lwIP support set CONFIG_NET_LWIP=y. +To enable lwIP support set CONFIG_NET_LWIP=y. In this case, root certificates +support can be enabled via CONFIG_WGET_BUILTIN_CACERT=y +CONFIG_WGET_BUILTIN_CACERT_PATH=<some path> (for built-in certificates) and/or +CONFIG_WGET_CACERT=y (for the wget cacert command). TCP Selective Acknowledgments in the legacy network stack can be enabled via CONFIG_PROT_TCP_SACK=y. This will improve the download speed. Selective diff --git a/doc/usage/environment.rst b/doc/usage/environment.rst index 30fc16794fc..7e2f2863d06 100644 --- a/doc/usage/environment.rst +++ b/doc/usage/environment.rst @@ -87,6 +87,18 @@ settings. For example:: #include <env/ti/mmc.env> +Quotes are not suppressed, for example:: + + fdtfile=CONFIG_DEFAULT_DEVICE_TREE.dtb + # produces: fdtfile="sun7i-a20-pcduino3.dtb" + +For this particular issue you can use ``DEFAULT_DEVICE_TREE`` instead:: + + fdtfile=DEFAULT_DEVICE_TREE.dtb + # produces: fdtfile=sun7i-a20-pcduino3.dtb + +There is no general way to remove quotes. + If CONFIG_ENV_SOURCE_FILE is empty and the default filename is not present, then the old-style C environment is used instead. See below. diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index d9d518d7038..18bd640a68b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -96,6 +96,13 @@ config SPL_CLK_GPIO Enable this option to add GPIO-controlled clock gate driver in U-Boot SPL. +config CLK_STUB + bool "Stub clock driver" + depends on CLK + help + Enable this to provide a stub clock driver for non-essential clock + controllers. + config CLK_BCM6345 bool "Clock controller driver for BCM6345" depends on CLK && ARCH_BMIPS diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 7f84f22d4b1..fe0e49f6112 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_$(PHASE_)CLK_CCF) += clk.o clk-divider.o clk-mux.o clk-gate.o obj-$(CONFIG_$(PHASE_)CLK_CCF) += clk-fixed-factor.o obj-$(CONFIG_$(PHASE_)CLK_COMPOSITE_CCF) += clk-composite.o obj-$(CONFIG_$(PHASE_)CLK_GPIO) += clk-gpio.o +obj-$(CONFIG_$(PHASE_)CLK_STUB) += clk-stub.o obj-y += adi/ obj-y += analogbits/ diff --git a/drivers/clk/clk-stub.c b/drivers/clk/clk-stub.c new file mode 100644 index 00000000000..5fbbb07b7f7 --- /dev/null +++ b/drivers/clk/clk-stub.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Stub clk driver for non-essential clocks. + * + * This driver should be used for clock controllers + * which are described as dependencies in DT but aren't + * actually necessary for hardware functionality. + */ + +#include <clk-uclass.h> +#include <dm.h> + +/* NOP parent nodes to stub clocks */ +static const struct udevice_id nop_parent_ids[] = { + { .compatible = "qcom,rpm-proc" }, + { .compatible = "qcom,glink-rpm" }, + { .compatible = "qcom,rpm-sm6115" }, + { } +}; + +U_BOOT_DRIVER(nop_parent) = { + .name = "nop_parent", + .id = UCLASS_NOP, + .of_match = nop_parent_ids, + .bind = dm_scan_fdt_dev, + .flags = DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; + +static ulong stub_clk_set_rate(struct clk *clk, ulong rate) +{ + return (clk->rate = rate); +} + +static ulong stub_clk_get_rate(struct clk *clk) +{ + return clk->rate; +} + +static int stub_clk_nop(struct clk *clk) +{ + return 0; +} + +static struct clk_ops stub_clk_ops = { + .set_rate = stub_clk_set_rate, + .get_rate = stub_clk_get_rate, + .enable = stub_clk_nop, + .disable = stub_clk_nop, +}; + +static const struct udevice_id stub_clk_ids[] = { + { .compatible = "qcom,rpmcc" }, + { .compatible = "qcom,sm8150-rpmh-clk" }, + { .compatible = "qcom,sm8250-rpmh-clk" }, + { .compatible = "qcom,sm8550-rpmh-clk" }, + { .compatible = "qcom,sm8650-rpmh-clk" }, + { } +}; + +U_BOOT_DRIVER(clk_stub) = { + .name = "clk_stub", + .id = UCLASS_CLK, + .ops = &stub_clk_ops, + .of_match = stub_clk_ids, + .flags = DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; + diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c index 35ee56d0693..cb98f34b5ec 100644 --- a/drivers/clk/clk_versal.c +++ b/drivers/clk/clk_versal.c @@ -106,8 +106,8 @@ struct versal_clk_priv { struct versal_clock *clk; }; -static ulong pl_alt_ref_clk; -static ulong ref_clk; +static ulong pl_alt_ref_clk __section(".data"); +static ulong ref_clk __section(".data"); struct versal_pm_query_data { u32 qid; @@ -116,8 +116,8 @@ struct versal_pm_query_data { u32 arg3; }; -static struct versal_clock *clock; -static unsigned int clock_max_idx; +static struct versal_clock *clock __section(".data"); +static unsigned int clock_max_idx __section(".data"); #define PM_QUERY_DATA 35 @@ -679,12 +679,21 @@ static int versal_clk_probe(struct udevice *dev) debug("%s\n", __func__); - ret = versal_clock_get_freq_by_name("pl_alt_ref_clk", + ret = versal_clock_get_freq_by_name("pl_alt_ref", dev, &pl_alt_ref_clk); + if (ret == -ENODATA) { + /* Fallback to old DT binding clk name "pl_alt_ref_clk" */ + ret = versal_clock_get_freq_by_name("pl_alt_ref_clk", + dev, &pl_alt_ref_clk); + } if (ret < 0) return -EINVAL; - ret = versal_clock_get_freq_by_name("ref_clk", dev, &ref_clk); + ret = versal_clock_get_freq_by_name("ref", dev, &ref_clk); + if (ret == -ENODATA) { + /* Fallback to old DT binding clk name "ref_clk" */ + ret = versal_clock_get_freq_by_name("ref_clk", dev, &ref_clk); + } if (ret < 0) return -EINVAL; diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index 3c5340df8ee..7fce1f70d13 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -70,17 +70,12 @@ static int rzg2l_cpg_clk_set(struct clk *clk, bool enable) dev_dbg(clk->dev, "%s %s clock %u\n", enable ? "enable" : "disable", is_mod_clk(clk->id) ? "module" : "core", cpg_clk_id); - if (!is_mod_clk(clk->id)) { - /* - * Non-module clocks are always on. Ignore attempts to enable - * them and reject attempts to disable them. - */ - if (enable) - return 0; - - dev_err(clk->dev, "ID %lu is not a module clock\n", clk->id); - return -EINVAL; - } + /* + * Non-module clocks are always on. Ignore attempts to enable or disable + * them. + */ + if (!is_mod_clk(clk->id)) + return 0; for (i = 0; i < data->info->num_mod_clks; i++) { if (data->info->mod_clks[i].id == cpg_clk_id) { diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c index 977699d509d..533031caead 100644 --- a/drivers/clk/rockchip/clk_rk3568.c +++ b/drivers/clk/rockchip/clk_rk3568.c @@ -2680,7 +2680,7 @@ static ulong rk3568_clk_set_rate(struct clk *clk, ulong rate) return ret; }; -#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA)) +#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA)) static int rk3568_gmac0_src_set_parent(struct clk *clk, struct clk *parent) { struct rk3568_clk_priv *priv = dev_get_priv(clk->dev); @@ -2859,7 +2859,7 @@ static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent) static struct clk_ops rk3568_clk_ops = { .get_rate = rk3568_clk_get_rate, .set_rate = rk3568_clk_set_rate, -#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA)) +#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA)) .set_parent = rk3568_clk_set_parent, #endif }; diff --git a/drivers/clk/rockchip/clk_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c index 6042fc10cdb..8c3a113526f 100644 --- a/drivers/clk/rockchip/clk_rk3588.c +++ b/drivers/clk/rockchip/clk_rk3588.c @@ -1822,7 +1822,7 @@ static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate) */ #define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60 -#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA)) +#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA)) static int __maybe_unused rk3588_dclk_vop_set_parent(struct clk *clk, struct clk *parent) { @@ -1915,7 +1915,7 @@ static int rk3588_clk_set_parent(struct clk *clk, struct clk *parent) static struct clk_ops rk3588_clk_ops = { .get_rate = rk3588_clk_get_rate, .set_rate = rk3588_clk_set_rate, -#if (IS_ENABLED(OF_CONTROL)) || (!IS_ENABLED(OF_PLATDATA)) +#if (CONFIG_IS_ENABLED(OF_CONTROL)) || (!CONFIG_IS_ENABLED(OF_PLATDATA)) .set_parent = rk3588_clk_set_parent, #endif }; diff --git a/drivers/core/Makefile b/drivers/core/Makefile index 9ea57911f89..657e589c286 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -16,6 +16,6 @@ ifndef CONFIG_DM_DEV_READ_INLINE obj-$(CONFIG_OF_CONTROL) += read.o endif obj-$(CONFIG_$(XPL_)OF_PLATDATA) += read.o -obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o +obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o ofnode_graph.o ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG diff --git a/drivers/core/ofnode_graph.c b/drivers/core/ofnode_graph.c new file mode 100644 index 00000000000..90c92af3258 --- /dev/null +++ b/drivers/core/ofnode_graph.c @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#define LOG_CATEGORY LOGC_DT + +#include <dm.h> +#include <log.h> +#include <dm/ofnode.h> +#include <linux/err.h> + +/** + * ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode + * @parent: ofnode to the device containing ports and endpoints + * + * Return: count of endpoint of this device ofnode + */ +unsigned int ofnode_graph_get_endpoint_count(ofnode parent) +{ + ofnode ports, port, endpoint; + unsigned int num = 0; + + /* Check if ports node exists */ + ports = ofnode_find_subnode(parent, "ports"); + if (ofnode_valid(ports)) + parent = ports; + + ofnode_for_each_subnode(port, parent) { + if (!strncmp(ofnode_get_name(port), "port", 4)) { + /* Port node can only contain endpoints */ + ofnode_for_each_subnode(endpoint, port) + num++; + } + }; + + log_debug("%s: detected %d endpoints\n", __func__, num); + + return num++; +} + +/** + * ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode + * @parent: ofnode to the device or ports node + * + * Return: count of port of this device or ports node + */ +unsigned int ofnode_graph_get_port_count(ofnode parent) +{ + ofnode ports, port; + unsigned int num = 0; + + /* Check if ports node exists */ + ports = ofnode_find_subnode(parent, "ports"); + if (ofnode_valid(ports)) + parent = ports; + + ofnode_for_each_subnode(port, parent) + if (!strncmp(ofnode_get_name(port), "port", 4)) + num++; + + log_debug("%s: detected %d ports\n", __func__, num); + + return num++; +} + +/** + * ofnode_graph_get_port_by_id() - get the port matching a given id + * @parent: parent ofnode + * @id: id of the port + * + * Return: ofnode in given port. + */ +ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id) +{ + ofnode ports, port; + u32 port_id; + + ports = ofnode_find_subnode(parent, "ports"); + if (!ofnode_valid(ports)) + return ofnode_null(); + + /* Check ports for node with desired id */ + ofnode_for_each_subnode(port, ports) { + ofnode_read_u32(port, "reg", &port_id); + log_debug("%s: detected port %d\n", __func__, port_id); + if (port_id == id) + return port; + } + + return ofnode_null(); +} + +/** + * ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id + * @parent: parent ofnode + * @reg_id: id of the port + * @id: id for the endpoint + * + * Return: ofnode in given endpoint or ofnode_null() if not found. + * reg and port_reg are ignored when they are -1. + */ +ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, int reg_id, int id) +{ + ofnode port, endpoint; + u32 ep_id; + + /* get the port to work with */ + if (reg_id < 0) + port = ofnode_find_subnode(parent, "port"); + else + port = ofnode_graph_get_port_by_id(parent, reg_id); + + if (!ofnode_valid(port)) { + log_debug("%s: port node is not found\n", __func__); + return ofnode_null(); + } + + if (id < 0) + return ofnode_find_subnode(port, "endpoint"); + + /* Check endpoints for node with desired id */ + ofnode_for_each_subnode(endpoint, port) { + ofnode_read_u32(endpoint, "reg", &ep_id); + log_debug("%s: detected endpoint %d\n", __func__, ep_id); + if (ep_id == id) + return endpoint; + } + + return ofnode_null(); +} + +/** + * ofnode_graph_get_remote_endpoint() - get remote endpoint node + * @endpoint: ofnode of a local endpoint + * + * Return: Remote endpoint ofnode linked with local endpoint. + */ +ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint) +{ + /* Get remote endpoint node. */ + return ofnode_parse_phandle(endpoint, "remote-endpoint", 0); +} + +/** + * ofnode_graph_get_port_parent() - get port's parent node + * @endpoint: ofnode of a local endpoint + * + * Return: device ofnode associated with endpoint + */ +ofnode ofnode_graph_get_port_parent(ofnode endpoint) +{ + ofnode port = ofnode_get_parent(endpoint); + ofnode parent = ofnode_get_parent(port); + + /* check if we are on top level or in ports node */ + if (!strcmp(ofnode_get_name(parent), "ports")) + parent = ofnode_get_parent(parent); + + return parent; +} + +/** + * ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode + * @endpoint: ofnode of a local endpoint + * + * Return: device ofnode associated with endpoint linked to local endpoint. + */ +ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint) +{ + ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint); + if (!ofnode_valid(remote_endpoint)) { + log_debug("%s: remote endpoint is not found\n", __func__); + return ofnode_null(); + } + + return ofnode_graph_get_port_parent(remote_endpoint); +} + +/** + * ofnode_graph_get_remote_port() - get remote port ofnode + * @endpoint: ofnode of a local endpoint + * + * Return: port ofnode associated with remote endpoint node linked + * to local endpoint. + */ +ofnode ofnode_graph_get_remote_port(ofnode endpoint) +{ + ofnode remote_endpoint = ofnode_graph_get_remote_endpoint(endpoint); + if (!ofnode_valid(remote_endpoint)) { + log_debug("%s: remote endpoint is not found\n", __func__); + return ofnode_null(); + } + + return ofnode_get_parent(remote_endpoint); +} + +/** + * ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint + * @parent: parent ofnode containing graph port/endpoint + * @port: identifier (value of reg property) of the parent port ofnode + * @endpoint: identifier (value of reg property) of the endpoint ofnode + * + * Return: device ofnode associated with endpoint linked to local endpoint. + */ +ofnode ofnode_graph_get_remote_node(ofnode parent, int port, int endpoint) +{ + ofnode endpoint_ofnode; + + endpoint_ofnode = ofnode_graph_get_endpoint_by_regs(parent, port, endpoint); + if (!ofnode_valid(endpoint_ofnode)) { + log_debug("%s: endpoint is not found\n", __func__); + return ofnode_null(); + } + + return ofnode_graph_get_remote_port_parent(endpoint_ofnode); +} diff --git a/drivers/core/root.c b/drivers/core/root.c index 15b8c83fee9..e53381e3b32 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -295,22 +295,29 @@ void *dm_priv_to_rw(void *priv) * all its children recursively to do the same. * * @dev: Device to (maybe) probe + * @pre_reloc_only: Probe only devices marked with the DM_FLAG_PRE_RELOC flag * Return 0 if OK, -ve on error */ -static int dm_probe_devices(struct udevice *dev) +static int dm_probe_devices(struct udevice *dev, bool pre_reloc_only) { + ofnode node = dev_ofnode(dev); struct udevice *child; + int ret; - if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) { - int ret; + if (pre_reloc_only && + (!ofnode_valid(node) || !ofnode_pre_reloc(node)) && + !(dev->driver->flags & DM_FLAG_PRE_RELOC)) + goto probe_children; + if (dev_get_flags(dev) & DM_FLAG_PROBE_AFTER_BIND) { ret = device_probe(dev); if (ret) return ret; } +probe_children: list_for_each_entry(child, &dev->child_head, sibling_node) - dm_probe_devices(child); + dm_probe_devices(child, pre_reloc_only); return 0; } @@ -319,7 +326,7 @@ int dm_autoprobe(void) { int ret; - ret = dm_probe_devices(gd->dm_root); + ret = dm_probe_devices(gd->dm_root, !(gd->flags & GD_FLG_RELOC)); if (ret) return log_msg_ret("pro", ret); diff --git a/drivers/crypto/fsl/fsl_hash.c b/drivers/crypto/fsl/fsl_hash.c index 79b32e2627c..b721c866095 100644 --- a/drivers/crypto/fsl/fsl_hash.c +++ b/drivers/crypto/fsl/fsl_hash.c @@ -183,6 +183,7 @@ int caam_hash(const unsigned char *pbuf, unsigned int buf_len, { int ret = 0; uint32_t *desc; + unsigned long pbuf_aligned; unsigned int size; desc = malloc_cache_aligned(sizeof(int) * MAX_CAAM_DESCSIZE); @@ -191,8 +192,9 @@ int caam_hash(const unsigned char *pbuf, unsigned int buf_len, return -ENOMEM; } - size = ALIGN(buf_len, ARCH_DMA_MINALIGN); - flush_dcache_range((unsigned long)pbuf, (unsigned long)pbuf + size); + pbuf_aligned = ALIGN_DOWN((unsigned long)pbuf, ARCH_DMA_MINALIGN); + size = ALIGN(buf_len + ((unsigned long)pbuf - pbuf_aligned), ARCH_DMA_MINALIGN); + flush_dcache_range(pbuf_aligned, pbuf_aligned + size); inline_cnstr_jobdesc_hash(desc, pbuf, buf_len, pout, driver_hash[algo].alg_type, diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 3c64e894646..4b47be6b016 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -76,6 +76,13 @@ config XILINX_DPDMA this file is used as placeholder for driver. The main reason is to record compatible string and calling power domain driver. +config ADI_DMA + bool "ADI DMA driver" + depends on DMA && DMA_CHANNELS + help + Enable DMA support for Analog Devices SOCs, such as the SC5xx. + Currently this is a minimalistic driver tested against OSPI use only. + if APBH_DMA config APBH_DMA_BURST bool "Enable DMA BURST" diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 48811eaaeb3..00d765864cd 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -13,5 +13,6 @@ obj-$(CONFIG_TI_KSNAV) += keystone_nav.o keystone_nav_cfg.o obj-$(CONFIG_TI_EDMA3) += ti-edma3.o obj-$(CONFIG_DMA_LPC32XX) += lpc32xx_dma.o obj-$(CONFIG_XILINX_DPDMA) += xilinx_dpdma.o +obj-$(CONFIG_ADI_DMA) += adi_dma.o obj-y += ti/ diff --git a/drivers/dma/adi_dma.c b/drivers/dma/adi_dma.c new file mode 100644 index 00000000000..28afe488db0 --- /dev/null +++ b/drivers/dma/adi_dma.c @@ -0,0 +1,253 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Analog Devices DMA controller driver + * + * (C) Copyright 2024 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * Contact: Ian Roberts <ian.roberts@timesys.com> + * + */ +#include <dm.h> +#include <dma.h> +#include <dma-uclass.h> +#include <dm/device_compat.h> +#include <linux/errno.h> +#include <linux/io.h> + +#define HAS_MDMA BIT(0) + +#define REG_ADDRSTART 0x04 +#define REG_CFG 0x08 +#define REG_XCNT 0x0C +#define REG_XMOD 0x10 +#define REG_STAT 0x30 + +#define BITP_DMA_CFG_MSIZE 8 +#define BITP_DMA_CFG_PSIZE 4 +#define BITM_DMA_CFG_WNR 0x00000002 +#define BITM_DMA_CFG_EN 0x00000001 +#define ENUM_DMA_CFG_XCNT_INT 0x00100000 + +#define BITP_DMA_STAT_PBWID 12 +#define BITP_DMA_STAT_ERRC 4 +#define BITM_DMA_STAT_PBWID 0x00003000 +#define BITM_DMA_STAT_ERRC 0x00000070 +#define BITM_DMA_STAT_PIRQ 0x00000004 +#define BITM_DMA_STAT_IRQERR 0x00000002 +#define BITM_DMA_STAT_IRQDONE 0x00000001 + +#define DMA_MDMA_SRC_DEFAULT_CONFIG(psize, msize) \ + (BITM_DMA_CFG_EN | ((psize) << BITP_DMA_CFG_PSIZE) | ((msize) << BITP_DMA_CFG_MSIZE)) +#define DMA_MDMA_DST_DEFAULT_CONFIG(psize, msize) \ + (BITM_DMA_CFG_EN | BITM_DMA_CFG_WNR | ENUM_DMA_CFG_XCNT_INT | \ + ((psize) << BITP_DMA_CFG_PSIZE) | ((msize) << BITP_DMA_CFG_MSIZE)) + +struct adi_dma_channel { + int id; + struct adi_dma *dma; + void __iomem *iosrc; + void __iomem *iodest; +}; + +struct adi_dma { + struct udevice *dev; + struct adi_dma_channel channels[1]; + void __iomem *ioaddr; + unsigned long hw_cfg; +}; + +static const struct udevice_id dma_dt_ids[] = { + { .compatible = "adi,mdma-controller", .data = HAS_MDMA }, + { } +}; + +static u8 adi_dma_get_msize(u32 n_bytecount, u32 n_address) +{ + /* Calculate MSIZE, PSIZE, XCNT and XMOD */ + u8 n_msize = 0; + u32 n_value = n_bytecount | n_address; + u32 n_mask = 0x1; + + for (n_msize = 0; n_msize < 5; n_msize++, n_mask <<= 1) { + if ((n_value & n_mask) == n_mask) + break; + } + + return n_msize; +} + +static int adi_dma_get_ch_error(void __iomem *ch) +{ + u32 cause = (ioread32(ch + REG_STAT) & BITM_DMA_STAT_ERRC) >> + BITP_DMA_STAT_ERRC; + switch (cause) { + case 0: + return -EINVAL; + case 1: + return -EBUSY; + case 2: + return -EFAULT; + case 3: + fallthrough; + case 5: + fallthrough; + case 6: + fallthrough; + default: + return -EIO; + } +} + +static int adi_mdma_transfer(struct udevice *dev, int direction, + dma_addr_t dst, dma_addr_t src, size_t len) +{ + struct adi_dma *priv = dev_get_priv(dev); + void __iomem *chsrc = priv->channels[0].iosrc; + void __iomem *chdst = priv->channels[0].iodest; + + int result = 0; + u32 reg; + u32 bytecount = len; + + u8 n_srcmsize; + u8 n_dstmsize; + u8 n_srcpsize; + u8 n_dstpsize; + u8 n_psize; + u32 srcconfig; + u32 dstconfig; + u8 srcpsizemax = (ioread32(chsrc + REG_STAT) & BITM_DMA_STAT_PBWID) >> + BITP_DMA_STAT_PBWID; + u8 dstpsizemax = (ioread32(chdst + REG_STAT) & BITM_DMA_STAT_PBWID) >> + BITP_DMA_STAT_PBWID; + + const u32 CLRSTAT = (BITM_DMA_STAT_IRQDONE | BITM_DMA_STAT_IRQERR | + BITM_DMA_STAT_PIRQ); + + if (len == 0) + return -EINVAL; + + /* Clear DMA status */ + iowrite32(CLRSTAT, chsrc + REG_STAT); + iowrite32(CLRSTAT, chdst + REG_STAT); + + /* Calculate MSIZE, PSIZE, XCNT and XMOD */ + n_srcmsize = adi_dma_get_msize(bytecount, src); + n_dstmsize = adi_dma_get_msize(bytecount, dst); + n_srcpsize = min(n_srcmsize, srcpsizemax); + n_dstpsize = min(n_dstmsize, dstpsizemax); + n_psize = min(n_srcpsize, n_dstpsize); + + srcconfig = DMA_MDMA_SRC_DEFAULT_CONFIG(n_psize, n_srcmsize); + dstconfig = DMA_MDMA_DST_DEFAULT_CONFIG(n_psize, n_dstmsize); + + /* Load the DMA descriptors */ + iowrite32(src, chsrc + REG_ADDRSTART); + iowrite32(bytecount >> n_srcmsize, chsrc + REG_XCNT); + iowrite32(1 << n_srcmsize, chsrc + REG_XMOD); + iowrite32(dst, chdst + REG_ADDRSTART); + iowrite32(bytecount >> n_dstmsize, chdst + REG_XCNT); + iowrite32(1 << n_dstmsize, chdst + REG_XMOD); + + iowrite32(dstconfig, chdst + REG_CFG); + iowrite32(srcconfig, chsrc + REG_CFG); + + /* Wait for DMA to complete while checking for a DMA error */ + do { + reg = ioread32(chsrc + REG_STAT); + if ((reg & BITM_DMA_STAT_IRQERR) == BITM_DMA_STAT_IRQERR) { + result = adi_dma_get_ch_error(chsrc); + break; + } + reg = ioread32(chdst + REG_STAT); + if ((reg & BITM_DMA_STAT_IRQERR) == BITM_DMA_STAT_IRQERR) { + result = adi_dma_get_ch_error(chdst); + break; + } + } while ((reg & BITM_DMA_STAT_IRQDONE) == 0); + + clrbits_32(chsrc + REG_CFG, 1); + clrbits_32(chdst + REG_CFG, 1); + + return result; +} + +static int adi_dma_init_channel(struct adi_dma *dma, + struct adi_dma_channel *channel, ofnode node) +{ + u32 offset; + + if (ofnode_read_u32(node, "adi,id", &channel->id)) { + dev_err(dma->dev, "Missing adi,id for channel %s\n", + ofnode_get_name(node)); + return -ENOENT; + } + + if (ofnode_read_u32(node, "adi,src-offset", &offset)) { + dev_err(dma->dev, "Missing adi,src-offset for channel %s\n", + ofnode_get_name(node)); + return -ENOENT; + } + + channel->iosrc = dma->ioaddr + offset; + channel->dma = dma; + + if (dma->hw_cfg & HAS_MDMA) { + if (ofnode_read_u32(node, "adi,dest-offset", &offset)) { + dev_err(dma->dev, + "Missing adi,dest-offset for channel %s\n", + ofnode_get_name(node)); + return -ENOENT; + } + channel->iodest = dma->ioaddr + offset; + } + + return 0; +} + +static int adi_dma_probe(struct udevice *dev) +{ + struct dma_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct adi_dma *priv = dev_get_priv(dev); + ofnode node, child; + + priv->hw_cfg = dev_get_driver_data(dev); + if (priv->hw_cfg & HAS_MDMA) + uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM; + + priv->ioaddr = dev_remap_addr(dev); + if (!priv->ioaddr) + return -EINVAL; + + node = dev_read_first_subnode(dev); + if (!ofnode_valid(node)) { + dev_err(dev, + "Error: device tree DMA channel config missing!\n"); + return -ENODEV; + } + + node = dev_ofnode(dev); + ofnode_for_each_subnode(child, node) { + adi_dma_init_channel(priv, priv->channels, child); + break; //Only 1 channel supported for now + } + + return 0; +} + +static const struct dma_ops adi_dma_ops = { + .transfer = adi_mdma_transfer, +}; + +U_BOOT_DRIVER(adi_dma) = { + .name = "adi_dma", + .id = UCLASS_DMA, + .of_match = dma_dt_ids, + .ops = &adi_dma_ops, + .probe = adi_dma_probe, + .priv_auto = sizeof(struct adi_dma), +}; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f4a453e1cdd..e11109fb56d 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -97,6 +97,15 @@ config SPL_DM_GPIO_LOOKUP_LABEL different gpios on different hardware versions for the same functionality in board code. +config ADI_GPIO + bool "ADI GPIO driver" + depends on DM_GPIO && ARCH_SC5XX + help + This driver supports GPIO banks on SC5xx processors. It + supports inputs and outputs but does not support pin + interrupt functionality (PINT) or other features in the + Linux version of the driver. + config ALTERA_PIO bool "Altera PIO driver" depends on DM_GPIO @@ -516,7 +525,7 @@ config ZYNQ_GPIO config DM_74X164 bool "74x164 serial-in/parallel-out 8-bits shift register" - depends on DM_GPIO + depends on DM_GPIO && DM_SPI help Driver for 74x164 compatible serial-in/parallel-out 8-outputs shift registers, such as 74lv165, 74hc595. @@ -545,6 +554,14 @@ config DM_PCA953X Now, max 24 bits chips and PCA953X compatible chips are supported +config ADP5588_GPIO + bool "ADP5588 GPIO expander driver" + depends on DM_GPIO && DM_I2C + help + Say yes here to support GPIO functionality of ADI ADP5588 chips. + + The ADP5588 is an 18-port I2C GPIO expander and keypad controller. + config SPL_DM_PCA953X bool "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports in SPL" depends on SPL_DM_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 3f882c065d8..d426d3a2d7b 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_$(PHASE_)DM_GPIO) += gpio-uclass.o obj-$(CONFIG_$(XPL_)DM_PCA953X) += pca953x_gpio.o +obj-$(CONFIG_ADI_GPIO) += gpio-adi-adsp.o obj-$(CONFIG_ASPEED_GPIO) += gpio-aspeed.o obj-$(CONFIG_ASPEED_G7_GPIO) += gpio-aspeed-g7.o obj-$(CONFIG_ASPEED_SGPIO) += gpio-aspeed-sgpio.o @@ -74,6 +75,7 @@ obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o obj-$(CONFIG_$(XPL_)MAX77663_GPIO) += max77663_gpio.o obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o +obj-$(CONFIG_ADP5588_GPIO) += adp5588_gpio.o obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o obj-$(CONFIG_FTGPIO010) += ftgpio010.o diff --git a/drivers/gpio/adp5588_gpio.c b/drivers/gpio/adp5588_gpio.c new file mode 100644 index 00000000000..d081e169897 --- /dev/null +++ b/drivers/gpio/adp5588_gpio.c @@ -0,0 +1,208 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * GPIO Chip driver for Analog Devices + * ADP5588/ADP5587 I/O Expander and QWERTY Keypad Controller + * + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + * Based on Michael Hennerich's Linux driver: + * Michael Hennerich <michael.hennerich@analog.com> + * + */ + +#include <dm.h> +#include <i2c.h> +#include <asm-generic/gpio.h> + +#define ADP5588_MAXGPIO 18 +#define ADP5588_BANK(offs) ((offs) >> 3) +#define ADP5588_BIT(offs) (1u << ((offs) & 0x7)) + +#define DEV_ID 0x00 /* Device ID */ +#define GPIO_DAT_STAT1 0x14 /* GPIO Data Status, Read twice to clear */ +#define GPIO_DAT_STAT2 0x15 /* GPIO Data Status, Read twice to clear */ +#define GPIO_DAT_STAT3 0x16 /* GPIO Data Status, Read twice to clear */ +#define GPIO_DAT_OUT1 0x17 /* GPIO DATA OUT */ +#define GPIO_DAT_OUT2 0x18 /* GPIO DATA OUT */ +#define GPIO_DAT_OUT3 0x19 /* GPIO DATA OUT */ +#define GPIO_INT_EN1 0x1A /* GPIO Interrupt Enable */ +#define GPIO_INT_EN2 0x1B /* GPIO Interrupt Enable */ +#define GPIO_INT_EN3 0x1C /* GPIO Interrupt Enable */ +#define KP_GPIO1 0x1D /* Keypad or GPIO Selection */ +#define KP_GPIO2 0x1E /* Keypad or GPIO Selection */ +#define KP_GPIO3 0x1F /* Keypad or GPIO Selection */ +#define GPIO_DIR1 0x23 /* GPIO Data Direction */ +#define GPIO_DIR2 0x24 /* GPIO Data Direction */ +#define GPIO_DIR3 0x25 /* GPIO Data Direction */ +#define GPIO_PULL1 0x2C /* GPIO Pull Disable */ +#define GPIO_PULL2 0x2D /* GPIO Pull Disable */ +#define GPIO_PULL3 0x2E /* GPIO Pull Disable */ +#define ID_MASK 0x0F + +struct adp5588_gpio { + u8 dat_out[3]; + u8 dir[3]; +}; + +static int adp5588_gpio_read(struct udevice *dev, u8 reg) +{ + int ret; + u8 val; + + ret = dm_i2c_read(dev, reg, &val, 1); + + if (ret < 0) { + pr_err("%s: read error\n", __func__); + return ret; + } + + return val; +} + +static int adp5588_gpio_write(struct udevice *dev, u8 reg, u8 val) +{ + int ret; + + ret = dm_i2c_write(dev, reg, &val, 1); + if (ret < 0) { + pr_err("%s: write error\n", __func__); + return ret; + } + + return 0; +} + +static int adp5588_get_value(struct udevice *dev, u32 offset) +{ + struct adp5588_gpio *plat = dev_get_plat(dev); + unsigned int bank = ADP5588_BANK(offset); + unsigned int bit = ADP5588_BIT(offset); + int val; + + if (plat->dir[bank] & bit) + val = plat->dat_out[bank]; + else + val = adp5588_gpio_read(dev, GPIO_DAT_STAT1 + bank); + + return !!(val & bit); +} + +static int adp5588_set_value(struct udevice *dev, u32 offset, + int32_t value) +{ + unsigned int bank, bit; + int ret; + struct adp5588_gpio *plat = dev_get_plat(dev); + + bank = ADP5588_BANK(offset); + bit = ADP5588_BIT(offset); + + if (value) + plat->dat_out[bank] |= bit; + else + plat->dat_out[bank] &= ~bit; + + ret = adp5588_gpio_write(dev, GPIO_DAT_OUT1 + bank, + plat->dat_out[bank]); + + return ret; +} + +static int adp5588_direction_input(struct udevice *dev, u32 offset) +{ + int ret; + unsigned int bank; + struct adp5588_gpio *plat = dev_get_plat(dev); + + bank = ADP5588_BANK(offset); + + plat->dir[bank] &= ~ADP5588_BIT(offset); + ret = adp5588_gpio_write(dev, GPIO_DIR1 + bank, plat->dir[bank]); + + return ret; +} + +static int adp5588_direction_output(struct udevice *dev, + u32 offset, int value) +{ + int ret; + unsigned int bank, bit; + struct adp5588_gpio *plat = dev_get_plat(dev); + + bank = ADP5588_BANK(offset); + bit = ADP5588_BIT(offset); + + plat->dir[bank] |= bit; + + if (value) + plat->dat_out[bank] |= bit; + else + plat->dat_out[bank] &= ~bit; + + ret = adp5588_gpio_write(dev, GPIO_DAT_OUT1 + bank, + plat->dat_out[bank]); + ret |= adp5588_gpio_write(dev, GPIO_DIR1 + bank, + plat->dir[bank]); + + return ret; +} + +static int adp5588_ofdata_platdata(struct udevice *dev) +{ + struct adp5588_gpio *plat = dev_get_plat(dev); + struct gpio_dev_priv *priv = dev_get_uclass_priv(dev); + int node = dev_of_offset(dev); + int ret, i, revid; + + priv->gpio_count = ADP5588_MAXGPIO; + priv->bank_name = fdt_get_name(gd->fdt_blob, node, NULL); + + ret = adp5588_gpio_read(dev, DEV_ID); + if (ret < 0) + return ret; + + revid = ret & ID_MASK; + + printf("ADP5588 Detected: Rev %x, Rev ID %x\n", ret, revid); + + for (i = 0, ret = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) { + plat->dat_out[i] = adp5588_gpio_read(dev, GPIO_DAT_OUT1 + i); + plat->dir[i] = adp5588_gpio_read(dev, GPIO_DIR1 + i); + ret |= adp5588_gpio_write(dev, KP_GPIO1 + i, 0); + ret |= adp5588_gpio_write(dev, GPIO_PULL1 + i, 0); + ret |= adp5588_gpio_write(dev, GPIO_INT_EN1 + i, 0); + if (ret) { + pr_err("%s: Initialization error\n", __func__); + return ret; + } + } + + return 0; +} + +static const struct dm_gpio_ops adp5588_ops = { + .direction_input = adp5588_direction_input, + .direction_output = adp5588_direction_output, + .get_value = adp5588_get_value, + .set_value = adp5588_set_value, +}; + +static const struct udevice_id adp5588_of_match_list[] = { + { .compatible = "adi,adp5588"}, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(gpio_adp5588) = { + .name = "gpio_adp5588", + .id = UCLASS_GPIO, + .ops = &adp5588_ops, + .of_match = adp5588_of_match_list, + .of_to_plat = adp5588_ofdata_platdata, + .plat_auto = sizeof(struct adp5588_gpio), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/gpio/gpio-adi-adsp.c b/drivers/gpio/gpio-adi-adsp.c new file mode 100644 index 00000000000..0ce00572e08 --- /dev/null +++ b/drivers/gpio/gpio-adi-adsp.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Author: Greg Malysa <greg.malysa@timesys.com> + * Additional Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + */ + +#include <dm.h> +#include <asm-generic/gpio.h> +#include <dm/device_compat.h> +#include <linux/bitops.h> +#include <linux/io.h> + +#define ADSP_PORT_MMIO_SIZE 0x80 +#define ADSP_PORT_PIN_SIZE 16 + +#define ADSP_PORT_REG_FER 0x00 +#define ADSP_PORT_REG_FER_SET 0x04 +#define ADSP_PORT_REG_FER_CLEAR 0x08 +#define ADSP_PORT_REG_DATA 0x0c +#define ADSP_PORT_REG_DATA_SET 0x10 +#define ADSP_PORT_REG_DATA_CLEAR 0x14 +#define ADSP_PORT_REG_DIR 0x18 +#define ADSP_PORT_REG_DIR_SET 0x1c +#define ADSP_PORT_REG_DIR_CLEAR 0x20 +#define ADSP_PORT_REG_INEN 0x24 +#define ADSP_PORT_REG_INEN_SET 0x28 +#define ADSP_PORT_REG_INEN_CLEAR 0x2c +#define ADSP_PORT_REG_PORT_MUX 0x30 +#define ADSP_PORT_REG_DATA_TGL 0x34 +#define ADSP_PORT_REG_POLAR 0x38 +#define ADSP_PORT_REG_POLAR_SET 0x3c +#define ADSP_PORT_REG_POLAR_CLEAR 0x40 +#define ADSP_PORT_REG_LOCK 0x44 +#define ADSP_PORT_REG_TRIG_TGL 0x48 + +struct adsp_gpio_priv { + void __iomem *base; + int ngpio; +}; + +static u32 get_port(unsigned int pin) +{ + return pin / ADSP_PORT_PIN_SIZE; +} + +static u32 get_offset(unsigned int pin) +{ + return pin % ADSP_PORT_PIN_SIZE; +} + +static int adsp_gpio_input(struct udevice *udev, unsigned int pin) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + u32 port, offset; + void __iomem *portbase; + + if (pin < priv->ngpio) { + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_FER_CLEAR); + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DIR_CLEAR); + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_INEN_SET); + return 0; + } + + return -EINVAL; +} + +static int adsp_gpio_output(struct udevice *udev, unsigned int pin, int value) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + u32 port, offset; + void __iomem *portbase; + + if (pin < priv->ngpio) { + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_FER_CLEAR); + + if (value) + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DATA_SET); + else + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DATA_CLEAR); + + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DIR_SET); + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_INEN_CLEAR); + return 0; + } + + return -EINVAL; +} + +static int adsp_gpio_get_value(struct udevice *udev, unsigned int pin) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + u32 port, offset; + u16 val; + void __iomem *portbase; + + if (pin < priv->ngpio) { + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + val = ioread16(portbase + ADSP_PORT_REG_DATA); + return !!(val & BIT(offset)); + } + + return 0; +} + +static int adsp_gpio_set_value(struct udevice *udev, unsigned int pin, int value) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + u32 port, offset; + void __iomem *portbase; + + if (pin < priv->ngpio) { + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + if (value) + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DATA_SET); + else + iowrite16(BIT(offset), portbase + ADSP_PORT_REG_DATA_CLEAR); + } + + return 0; +} + +static const struct dm_gpio_ops adsp_gpio_ops = { + .direction_input = adsp_gpio_input, + .direction_output = adsp_gpio_output, + .get_value = adsp_gpio_get_value, + .set_value = adsp_gpio_set_value, +}; + +static int adsp_gpio_probe(struct udevice *udev) +{ + struct adsp_gpio_priv *priv = dev_get_priv(udev); + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(udev); + + uc_priv->bank_name = "adsp gpio"; + uc_priv->gpio_count = dev_read_u32_default(udev, "adi,ngpios", 0); + + if (!uc_priv->gpio_count) { + dev_err(udev, "Missing adi,ngpios property!\n"); + return -ENOENT; + } + + priv->base = dev_read_addr_ptr(udev); + priv->ngpio = uc_priv->gpio_count; + + return 0; +} + +static const struct udevice_id adsp_gpio_match[] = { + { .compatible = "adi,adsp-gpio" }, + { }, +}; + +U_BOOT_DRIVER(adi_adsp_gpio) = { + .name = "adi_adsp_gpio", + .id = UCLASS_GPIO, + .ops = &adsp_gpio_ops, + .probe = adsp_gpio_probe, + .priv_auto = sizeof(struct adsp_gpio_priv), + .of_match = adsp_gpio_match, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index cdae6825736..46e76385961 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -154,6 +154,13 @@ config SPL_DM_I2C_GPIO bindings are supported. Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt +config SYS_I2C_ADI + bool "ADI I2C driver" + depends on DM_I2C && ARCH_SC5XX + help + Add support for the ADI (Analog Devices) I2C driver as used + in SC57X, SC58X, SC59X, SC59X_64. + config SYS_I2C_AT91 bool "Atmel I2C driver" depends on DM_I2C && ARCH_AT91 diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index bebd728e7da..2713289f7db 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_$(XPL_)I2C_CROS_EC_TUNNEL) += cros_ec_tunnel.o obj-$(CONFIG_$(XPL_)I2C_CROS_EC_LDO) += cros_ec_ldo.o obj-$(CONFIG_$(XPL_)SYS_I2C_LEGACY) += i2c_core.o +obj-$(CONFIG_SYS_I2C_ADI) += adi_i2c.o obj-$(CONFIG_SYS_I2C_ASPEED) += ast_i2c.o obj-$(CONFIG_SYS_I2C_AST2600) += ast2600_i2c.o obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o diff --git a/drivers/i2c/adi_i2c.c b/drivers/i2c/adi_i2c.c new file mode 100644 index 00000000000..4cddcfa6b7f --- /dev/null +++ b/drivers/i2c/adi_i2c.c @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Converted to driver model by Nathan Barrett-Morrison + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + */ + +#include <clk.h> +#include <dm.h> +#include <i2c.h> +#include <mapmem.h> +#include <linux/io.h> + +#define CLKLOW(x) ((x) & 0xFF) // Periods Clock Is Held Low +#define CLKHI(y) (((y) & 0xFF) << 0x8) // Periods Clock Is High + +#define PRESCALE 0x007F // SCLKs Per Internal Time Reference (10MHz) +#define TWI_ENA 0x0080 // TWI Enable +#define SCCB 0x0200 // SCCB Compatibility Enable + +#define SEN 0x0001 // Slave Enable +#define SADD_LEN 0x0002 // Slave Address Length +#define STDVAL 0x0004 // Slave Transmit Data Valid +#define TSC_NAK 0x0008 // NAK Generated At Conclusion Of Transfer +#define GEN 0x0010 // General Call Adrress Matching Enabled + +#define SDIR 0x0001 // Slave Transfer Direction +#define GCALL 0x0002 // General Call Indicator + +#define MEN 0x0001 // Master Mode Enable +#define MADD_LEN 0x0002 // Master Address Length +#define MDIR 0x0004 // Master Transmit Direction (RX/TX*) +#define FAST 0x0008 // Use Fast Mode Timing Specs +#define STOP 0x0010 // Issue Stop Condition +#define RSTART 0x0020 // Repeat Start or Stop* At End Of Transfer +#define DCNT 0x3FC0 // Data Bytes To Transfer +#define SDAOVR 0x4000 // Serial Data Override +#define SCLOVR 0x8000 // Serial Clock Override + +#define MPROG 0x0001 // Master Transfer In Progress +#define LOSTARB 0x0002 // Lost Arbitration Indicator (Xfer Aborted) +#define ANAK 0x0004 // Address Not Acknowledged +#define DNAK 0x0008 // Data Not Acknowledged +#define BUFRDERR 0x0010 // Buffer Read Error +#define BUFWRERR 0x0020 // Buffer Write Error +#define SDASEN 0x0040 // Serial Data Sense +#define SCLSEN 0x0080 // Serial Clock Sense +#define BUSBUSY 0x0100 // Bus Busy Indicator + +#define SINIT 0x0001 // Slave Transfer Initiated +#define SCOMP 0x0002 // Slave Transfer Complete +#define SERR 0x0004 // Slave Transfer Error +#define SOVF 0x0008 // Slave Overflow +#define MCOMP 0x0010 // Master Transfer Complete +#define MERR 0x0020 // Master Transfer Error +#define XMTSERV 0x0040 // Transmit FIFO Service +#define RCVSERV 0x0080 // Receive FIFO Service + +#define XMTFLUSH 0x0001 // Transmit Buffer Flush +#define RCVFLUSH 0x0002 // Receive Buffer Flush +#define XMTINTLEN 0x0004 // Transmit Buffer Interrupt Length +#define RCVINTLEN 0x0008 // Receive Buffer Interrupt Length + +#define XMTSTAT 0x0003 // Transmit FIFO Status +#define XMT_EMPTY 0x0000 // Transmit FIFO Empty +#define XMT_HALF 0x0001 // Transmit FIFO Has 1 Byte To Write +#define XMT_FULL 0x0003 // Transmit FIFO Full (2 Bytes To Write) + +#define RCVSTAT 0x000C // Receive FIFO Status +#define RCV_EMPTY 0x0000 // Receive FIFO Empty +#define RCV_HALF 0x0004 // Receive FIFO Has 1 Byte To Read +#define RCV_FULL 0x000C // Receive FIFO Full (2 Bytes To Read) + +/* Every register is 32bit aligned, but only 16bits in size */ +#define ureg(name) u16 name; u16 __pad_##name + +struct twi_regs { + ureg(clkdiv); + ureg(control); + ureg(slave_ctl); + ureg(slave_stat); + ureg(slave_addr); + ureg(master_ctl); + ureg(master_stat); + ureg(master_addr); + ureg(int_stat); + ureg(int_mask); + ureg(fifo_ctl); + ureg(fifo_stat); + u8 __pad[0x50]; + + ureg(xmt_data8); + ureg(xmt_data16); + ureg(rcv_data8); + ureg(rcv_data16); +}; + +#undef ureg + +/* + * The way speed is changed into duty often results in integer truncation + * with 50% duty, so we'll force rounding up to the next duty by adding 1 + * to the max. In practice this will get us a speed of something like + * 385 KHz. The other limit is easy to handle as it is only 8 bits. + */ +#define I2C_SPEED_MAX 400000 +#define I2C_SPEED_TO_DUTY(speed) (5000000 / (speed)) +#define I2C_DUTY_MAX (I2C_SPEED_TO_DUTY(I2C_SPEED_MAX) + 1) +#define I2C_DUTY_MIN 0xff /* 8 bit limited */ + +#define I2C_M_COMBO 0x4 +#define I2C_M_STOP 0x2 +#define I2C_M_READ 0x1 + +/* + * All transfers are described by this data structure + */ +struct adi_i2c_msg { + u8 flags; + u32 len; /* msg length */ + u8 *buf; /* pointer to msg data */ + u32 olen; /* addr length */ + u8 *obuf; /* addr buffer */ +}; + +struct adi_i2c_dev { + struct twi_regs __iomem *base; + u32 i2c_clk; + uint speed; +}; + +/* Allow msec timeout per ~byte transfer */ +#define I2C_TIMEOUT 10 + +/** + * wait_for_completion - manage the actual i2c transfer + * @msg: the i2c msg + */ +static int wait_for_completion(struct twi_regs *twi, struct adi_i2c_msg *msg) +{ + u16 int_stat; + ulong timebase = get_timer(0); + + do { + int_stat = ioread16(&twi->int_stat); + + if (int_stat & XMTSERV) { + iowrite16(XMTSERV, &twi->int_stat); + if (msg->olen) { + iowrite16(*(msg->obuf++), &twi->xmt_data8); + --msg->olen; + } else if (!(msg->flags & I2C_M_COMBO) && msg->len) { + iowrite16(*(msg->buf++), &twi->xmt_data8); + --msg->len; + } else { + if (msg->flags & I2C_M_COMBO) + setbits_16(&twi->master_ctl, RSTART | MDIR); + else + setbits_16(&twi->master_ctl, STOP); + } + } + if (int_stat & RCVSERV) { + iowrite16(RCVSERV, &twi->int_stat); + if (msg->len) { + *(msg->buf++) = ioread16(&twi->rcv_data8); + --msg->len; + } else if (msg->flags & I2C_M_STOP) { + setbits_16(&twi->master_ctl, STOP); + } + } + if (int_stat & MERR) { + pr_err("%s: master transmit terror: %d\n", __func__, + ioread16(&twi->master_stat)); + iowrite16(MERR, &twi->int_stat); + return -EIO; + } + if (int_stat & MCOMP) { + iowrite16(MCOMP, &twi->int_stat); + if (msg->flags & I2C_M_COMBO && msg->len) { + u16 mlen = min(msg->len, 0xffu) << 6; + clrsetbits_16(&twi->master_ctl, RSTART, mlen | MEN | MDIR); + } else { + break; + } + } + + /* If we were able to do something, reset timeout */ + if (int_stat) + timebase = get_timer(0); + + } while (get_timer(timebase) < I2C_TIMEOUT); + + return 0; +} + +static int i2c_transfer(struct twi_regs *twi, u8 chip, u8 *offset, + int olen, u8 *buffer, int len, u8 flags) +{ + int ret; + u16 ctl; + + struct adi_i2c_msg msg = { + .flags = flags | (len >= 0xff ? I2C_M_STOP : 0), + .buf = buffer, + .len = len, + .obuf = offset, + .olen = olen, + }; + + /* wait for things to settle */ + while (ioread16(&twi->master_stat) & BUSBUSY) + if (!IS_ENABLED(CONFIG_SPL_BUILD) && ctrlc()) + return -EINTR; + + /* Set Transmit device address */ + iowrite16(chip, &twi->master_addr); + + /* Clear the FIFO before starting things */ + iowrite16(XMTFLUSH | RCVFLUSH, &twi->fifo_ctl); + iowrite16(0, &twi->fifo_ctl); + + /* Prime the pump */ + if (msg.olen) { + len = (msg.flags & I2C_M_COMBO) ? msg.olen : msg.olen + len; + iowrite16(*(msg.obuf++), &twi->xmt_data8); + --msg.olen; + } else if (!(msg.flags & I2C_M_READ) && msg.len) { + iowrite16(*(msg.buf++), &twi->xmt_data8); + --msg.len; + } + + /* clear int stat */ + iowrite16(-1, &twi->master_stat); + iowrite16(-1, &twi->int_stat); + iowrite16(0, &twi->int_mask); + + /* Master enable */ + ctl = ioread16(&twi->master_ctl); + ctl = (ctl & FAST) | (min(len, 0xff) << 6) | MEN | + ((msg.flags & I2C_M_READ) ? MDIR : 0); + iowrite16(ctl, &twi->master_ctl); + + /* Process the rest */ + ret = wait_for_completion(twi, &msg); + + clrbits_16(&twi->master_ctl, MEN); + clrbits_16(&twi->control, TWI_ENA); + setbits_16(&twi->control, TWI_ENA); + return ret; +} + +static int adi_i2c_read(struct twi_regs *twi, u8 chip, + u8 *offset, int olen, u8 *buffer, int len) +{ + return i2c_transfer(twi, chip, offset, olen, buffer, + len, olen ? I2C_M_COMBO : I2C_M_READ); +} + +static int adi_i2c_write(struct twi_regs *twi, u8 chip, + u8 *offset, int olen, u8 *buffer, int len) +{ + return i2c_transfer(twi, chip, offset, olen, buffer, len, 0); +} + +static int adi_i2c_set_bus_speed(struct udevice *bus, uint speed) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + struct twi_regs *twi = dev->base; + u16 clkdiv = I2C_SPEED_TO_DUTY(speed); + + /* Set TWI interface clock */ + if (clkdiv < I2C_DUTY_MAX || clkdiv > I2C_DUTY_MIN) + return -1; + clkdiv = (clkdiv << 8) | (clkdiv & 0xff); + iowrite16(clkdiv, &twi->clkdiv); + + /* Don't turn it on */ + iowrite16(speed > 100000 ? FAST : 0, &twi->master_ctl); + + return 0; +} + +static int adi_i2c_of_to_plat(struct udevice *bus) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + struct clk clock; + u32 ret; + + dev->base = map_sysmem(dev_read_addr(bus), sizeof(struct twi_regs)); + + if (!dev->base) + return -ENOMEM; + + dev->speed = dev_read_u32_default(bus, "clock-frequency", + I2C_SPEED_FAST_RATE); + + ret = clk_get_by_name(bus, "i2c", &clock); + if (ret < 0) + printf("%s: Can't get I2C clk: %d\n", __func__, ret); + else + dev->i2c_clk = clk_get_rate(&clock); + + return 0; +} + +static int adi_i2c_probe_chip(struct udevice *bus, u32 chip_addr, + u32 chip_flags) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + u8 byte; + + return adi_i2c_read(dev->base, chip_addr, NULL, 0, &byte, 1); +} + +static int adi_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + struct i2c_msg *dmsg, *omsg, dummy; + + memset(&dummy, 0, sizeof(struct i2c_msg)); + + /* + * We expect either two messages (one with an offset and one with the + * actual data) or one message (just data) + */ + if (nmsgs > 2 || nmsgs == 0) { + debug("%s: Only one or two messages are supported.", __func__); + return -EINVAL; + } + + omsg = nmsgs == 1 ? &dummy : msg; + dmsg = nmsgs == 1 ? msg : msg + 1; + + if (dmsg->flags & I2C_M_RD) + return adi_i2c_read(dev->base, dmsg->addr, omsg->buf, omsg->len, + dmsg->buf, dmsg->len); + else + return adi_i2c_write(dev->base, dmsg->addr, omsg->buf, omsg->len, + dmsg->buf, dmsg->len); +} + +int adi_i2c_probe(struct udevice *bus) +{ + struct adi_i2c_dev *dev = dev_get_priv(bus); + struct twi_regs *twi = dev->base; + + u16 prescale = ((dev->i2c_clk / 1000 / 1000 + 5) / 10) & 0x7F; + + /* Set TWI internal clock as 10MHz */ + iowrite16(prescale, &twi->control); + + /* Set TWI interface clock as specified */ + adi_i2c_set_bus_speed(bus, dev->speed); + + /* Enable it */ + iowrite16(TWI_ENA | prescale, &twi->control); + + return 0; +} + +static const struct dm_i2c_ops adi_i2c_ops = { + .xfer = adi_i2c_xfer, + .probe_chip = adi_i2c_probe_chip, + .set_bus_speed = adi_i2c_set_bus_speed, +}; + +static const struct udevice_id adi_i2c_ids[] = { + { .compatible = "adi-i2c", }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(i2c_adi) = { + .name = "i2c_adi", + .id = UCLASS_I2C, + .of_match = adi_i2c_ids, + .probe = adi_i2c_probe, + .of_to_plat = adi_i2c_of_to_plat, + .priv_auto = sizeof(struct adi_i2c_dev), + .ops = &adi_i2c_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c index 22f61d12d38..edcdeee1e9a 100644 --- a/drivers/led/led-uclass.c +++ b/drivers/led/led-uclass.c @@ -273,8 +273,12 @@ static const char *led_get_function_name(struct udevice *dev) /* Now try to detect function label name */ func = dev_read_string(dev, "function"); cp = dev_read_u32(dev, "color", &color); - // prevent coverity scan error CID 541279: (TAINTED_SCALAR) - if (color < LED_COLOR_ID_WHITE || color >= LED_COLOR_ID_MAX) + /* + * prevent coverity scan error CID 541279: (TAINTED_SCALAR) + * only check the upper bound. No need to check the lower bound + * as color is from type u32 and never can be lower than 0. + */ + if (color >= LED_COLOR_ID_MAX) cp = -EINVAL; if (cp == 0 || func) { diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 4827834b4aa..ab56bd3939f 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -292,6 +292,15 @@ config MMC_DW_ROCKCHIP SD 3.0, SDIO 3.0 and MMC 4.5 and supports common eMMC chips as well as removeable SD and micro-SD cards. +config MMC_SDHCI_ADI + bool "ADI SD/MMC controller support" + depends on ARCH_SC5XX + depends on DM_MMC && OF_CONTROL + depends on MMC_SDHCI && MMC_SDHCI_ADMA + help + This enables support for the SD/MMC controller included in some Analog + Devices SC5XX Socs. + config MMC_DW_SOCFPGA bool "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" depends on ARCH_SOCFPGA diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 90e76f90769..94ed28ead71 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_MMC_SDHCI_MV) += mv_sdhci.o obj-$(CONFIG_MMC_SDHCI_NPCM) += npcm_sdhci.o obj-$(CONFIG_MMC_SDHCI_PIC32) += pic32_sdhci.o obj-$(CONFIG_MMC_SDHCI_ROCKCHIP) += rockchip_sdhci.o +obj-$(CONFIG_MMC_SDHCI_ADI) += adi_sdhci.o obj-$(CONFIG_MMC_SDHCI_S5P) += s5p_sdhci.o obj-$(CONFIG_MMC_SDHCI_SNPS) += snps_sdhci.o obj-$(CONFIG_MMC_SDHCI_STI) += sti_sdhci.o diff --git a/drivers/mmc/adi_sdhci.c b/drivers/mmc/adi_sdhci.c new file mode 100644 index 00000000000..65a22cefb71 --- /dev/null +++ b/drivers/mmc/adi_sdhci.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + * Based on Rockchip's sdhci.c file + */ + +#include <clk.h> +#include <dm.h> +#include <malloc.h> +#include <sdhci.h> +#include <asm/cache.h> + +/* 400KHz is max freq for card ID etc. Use that as min */ +#define EMMC_MIN_FREQ 400000 + +/* Check if an operation crossed a boundary of size ADMA_BOUNDARY_ALIGN */ +#define ADMA_BOUNDARY_ALGN SZ_128M +#define BOUNDARY_OK(addr, len) \ + (((addr) | (ADMA_BOUNDARY_ALGN - 1)) == (((addr) + (len) - 1) | \ + (ADMA_BOUNDARY_ALGN - 1))) + +/* We split a descriptor for every crossing of the ADMA alignment boundary, + * so we need an additional descriptor for every expected crossing. + * As I understand it, the max expected transaction size is: + * CONFIG_SYS_MMC_MAX_BLK_COUNT * MMC_MAX_BLOCK_LEN + * + * With the way the SDHCI-ADMA driver is implemented, if ADMA_MAX_LEN was a + * clean power of two, we'd only ever need +1 descriptor as the first + * descriptor that got split would then bring the remaining DMA + * destination addresses into alignment. Unfortunately, it's currently + * hardcoded to a non-power-of-two value. + * + * If that ever becomes parameterized, ADMA max length can be set to + * 0x10000, and set this to 1. + */ +#define ADMA_POTENTIAL_CROSSINGS \ + DIV_ROUND_UP((CONFIG_SYS_MMC_MAX_BLK_COUNT * MMC_MAX_BLOCK_LEN), \ + ADMA_BOUNDARY_ALGN) +/* +1 descriptor for each crossing. + */ +#define ADMA_TABLE_EXTRA_SZ (ADMA_POTENTIAL_CROSSINGS * ADMA_DESC_LEN) + +struct adi_sdhc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +void adi_dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc, + dma_addr_t addr, int len, bool end) +{ + int tmplen, offset; + + if (likely(!len || BOUNDARY_OK(addr, len))) { + sdhci_adma_write_desc(host, desc, addr, len, end); + return; + } + + offset = addr & (ADMA_BOUNDARY_ALGN - 1); + tmplen = ADMA_BOUNDARY_ALGN - offset; + sdhci_adma_write_desc(host, desc, addr, tmplen, false); + + addr += tmplen; + len -= tmplen; + sdhci_adma_write_desc(host, desc, addr, len, end); +} + +struct sdhci_ops adi_dwcmshc_sdhci_ops = { + .adma_write_desc = adi_dwcmshc_adma_write_desc, +}; + +static int adi_dwcmshc_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct adi_sdhc_plat *plat = dev_get_plat(dev); + struct sdhci_host *host = dev_get_priv(dev); + int max_frequency, ret; + struct clk clk; + + max_frequency = dev_read_u32_default(dev, "max-frequency", 0); + ret = clk_get_by_index(dev, 0, &clk); + + host->quirks = 0; + host->max_clk = max_frequency; + /* + * The sdhci-driver only supports 4bit and 8bit, as sdhci_setup_cfg + * doesn't allow us to clear MMC_MODE_4BIT. Consequently, we don't + * check for other bus-width values. + */ + if (host->bus_width == 8) + host->host_caps |= MMC_MODE_8BIT; + + host->mmc = &plat->mmc; + host->mmc->priv = host; + host->mmc->dev = dev; + upriv->mmc = host->mmc; + + host->ops = &adi_dwcmshc_sdhci_ops; + host->adma_desc_table = memalign(ARCH_DMA_MINALIGN, + ADMA_TABLE_SZ + ADMA_TABLE_EXTRA_SZ); + host->adma_addr = virt_to_phys(host->adma_desc_table); + + ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ); + if (ret) + return ret; + + return sdhci_probe(dev); +} + +static int adi_dwcmshc_sdhci_of_to_plat(struct udevice *dev) +{ + struct sdhci_host *host = dev_get_priv(dev); + + host->name = dev->name; + host->ioaddr = dev_read_addr_ptr(dev); + host->bus_width = dev_read_u32_default(dev, "bus-width", 4); + + return 0; +} + +static int adi_sdhci_bind(struct udevice *dev) +{ + struct adi_sdhc_plat *plat = dev_get_plat(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static const struct udevice_id adi_dwcmshc_sdhci_ids[] = { + { .compatible = "adi,dwc-sdhci" }, + { } +}; + +U_BOOT_DRIVER(adi_dwcmshc_sdhci_drv) = { + .name = "adi_sdhci", + .id = UCLASS_MMC, + .of_match = adi_dwcmshc_sdhci_ids, + .of_to_plat = adi_dwcmshc_sdhci_of_to_plat, + .ops = &sdhci_ops, + .bind = adi_sdhci_bind, + .probe = adi_dwcmshc_sdhci_probe, + .priv_auto = sizeof(struct sdhci_host), + .plat_auto = sizeof(struct adi_sdhc_plat), +}; diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1563404ca17..3db784faedd 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -237,6 +237,13 @@ config DWC_ETH_QOS Of Service) IP block. The IP supports many options for bus type, clocking/reset structure, and feature list. +config DWC_ETH_QOS_ADI + bool "Synopsys DWC Ethernet QOS device support for ADI SC59x-64 parts" + depends on DWC_ETH_QOS + help + The Synopsis Designware Ethernet QoS IP block with the specific + configuration used in the ADI ADSP-SC59X 64 bit SoCs + config DWC_ETH_QOS_IMX bool "Synopsys DWC Ethernet QOS device support for IMX" depends on DWC_ETH_QOS @@ -852,6 +859,7 @@ config RENESAS_ETHER_SWITCH config RENESAS_RAVB bool "Renesas Ethernet AVB MAC" depends on RCAR_64 + select BITBANGMII select PHYLIB select PHY_ETHERNET_ID help diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 80d70212971..d919d437c08 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_DM_ETH_PHY) += eth-phy-uclass.o obj-$(CONFIG_DRIVER_DM9000) += dm9000x.o obj-$(CONFIG_DSA_SANDBOX) += dsa_sandbox.o obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o +obj-$(CONFIG_DWC_ETH_QOS_ADI) += dwc_eth_qos_adi.o obj-$(CONFIG_DWC_ETH_QOS_IMX) += dwc_eth_qos_imx.o obj-$(CONFIG_DWC_ETH_QOS_INTEL) += dwc_eth_qos_intel.o obj-$(CONFIG_DWC_ETH_QOS_ROCKCHIP) += dwc_eth_qos_rockchip.o diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 5a6e89c0575..0f93c25e3fe 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -227,9 +227,9 @@ static int dw_dm_mdio_init(const char *name, void *priv) #endif #if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) -static int dw_eth_bb_mdio_active(struct bb_miiphy_bus *bus) +static int dw_eth_bb_mdio_active(struct mii_dev *miidev) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; struct gpio_desc *desc = &priv->mdio_gpio; desc->flags = 0; @@ -238,9 +238,9 @@ static int dw_eth_bb_mdio_active(struct bb_miiphy_bus *bus) return 0; } -static int dw_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) +static int dw_eth_bb_mdio_tristate(struct mii_dev *miidev) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; struct gpio_desc *desc = &priv->mdio_gpio; desc->flags = 0; @@ -249,9 +249,9 @@ static int dw_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) return 0; } -static int dw_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) +static int dw_eth_bb_set_mdio(struct mii_dev *miidev, int v) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; if (v) dm_gpio_set_value(&priv->mdio_gpio, 1); @@ -261,18 +261,18 @@ static int dw_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) return 0; } -static int dw_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) +static int dw_eth_bb_get_mdio(struct mii_dev *miidev, int *v) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; *v = dm_gpio_get_value(&priv->mdio_gpio); return 0; } -static int dw_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) +static int dw_eth_bb_set_mdc(struct mii_dev *miidev, int v) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; if (v) dm_gpio_set_value(&priv->mdc_gpio, 1); @@ -282,28 +282,48 @@ static int dw_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) return 0; } -static int dw_eth_bb_delay(struct bb_miiphy_bus *bus) +static int dw_eth_bb_delay(struct mii_dev *miidev) { - struct dw_eth_dev *priv = bus->priv; + struct dw_eth_dev *priv = miidev->priv; udelay(priv->bb_delay); return 0; } +static const struct bb_miiphy_bus_ops dw_eth_bb_miiphy_bus_ops = { + .mdio_active = dw_eth_bb_mdio_active, + .mdio_tristate = dw_eth_bb_mdio_tristate, + .set_mdio = dw_eth_bb_set_mdio, + .get_mdio = dw_eth_bb_get_mdio, + .set_mdc = dw_eth_bb_set_mdc, + .delay = dw_eth_bb_delay, +}; + +static int dw_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) +{ + return bb_miiphy_read(miidev, &dw_eth_bb_miiphy_bus_ops, + addr, devad, reg); +} + +static int dw_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) +{ + return bb_miiphy_write(miidev, &dw_eth_bb_miiphy_bus_ops, + addr, devad, reg, value); +} + static int dw_bb_mdio_init(const char *name, struct udevice *dev) { struct dw_eth_dev *dwpriv = dev_get_priv(dev); - struct bb_miiphy_bus *bb_miiphy = bb_miiphy_alloc(); - struct mii_dev *bus; + struct mii_dev *bus = mdio_alloc(); int ret; - if (!bb_miiphy) { + if (!bus) { printf("Failed to allocate MDIO bus\n"); return -ENOMEM; } - bus = &bb_miiphy->mii; - debug("\n%s: use bitbang mii..\n", dev->name); ret = gpio_request_by_name(dev, "snps,mdc-gpio", 0, &dwpriv->mdc_gpio, @@ -325,21 +345,13 @@ static int dw_bb_mdio_init(const char *name, struct udevice *dev) dwpriv->dev = dev; snprintf(bus->name, sizeof(bus->name), "%s", name); - bus->read = bb_miiphy_read; - bus->write = bb_miiphy_write; + bus->read = dw_bb_miiphy_read; + bus->write = dw_bb_miiphy_write; #if CONFIG_IS_ENABLED(DM_GPIO) bus->reset = dw_mdio_reset; #endif bus->priv = dwpriv; - /* Copy the bus accessors and private data */ - bb_miiphy->mdio_active = dw_eth_bb_mdio_active; - bb_miiphy->mdio_tristate = dw_eth_bb_mdio_tristate; - bb_miiphy->set_mdio = dw_eth_bb_set_mdio; - bb_miiphy->get_mdio = dw_eth_bb_get_mdio; - bb_miiphy->set_mdc = dw_eth_bb_set_mdc; - bb_miiphy->delay = dw_eth_bb_delay; - return mdio_register(bus); } #endif @@ -840,7 +852,6 @@ int designware_eth_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct dw_eth_dev *priv = dev_get_priv(dev); - bool __maybe_unused bbmiiphy = false; phys_addr_t iobase = pdata->iobase; void *ioaddr; int ret, err; @@ -932,8 +943,7 @@ int designware_eth_probe(struct udevice *dev) priv->max_speed = pdata->max_speed; #if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) - bbmiiphy = dev_read_bool(dev, "snps,bitbang-mii"); - if (bbmiiphy) { + if (dev_read_bool(dev, "snps,bitbang-mii")) { ret = dw_bb_mdio_init(dev->name, dev); if (ret) { err = ret; @@ -963,12 +973,7 @@ int designware_eth_probe(struct udevice *dev) /* continue here for cleanup if no PHY found */ err = ret; mdio_unregister(priv->bus); -#if IS_ENABLED(CONFIG_BITBANGMII) && IS_ENABLED(CONFIG_DM_GPIO) - if (bbmiiphy) - bb_miiphy_free(container_of(priv->bus, struct bb_miiphy_bus, mii)); - else -#endif - mdio_free(priv->bus); + mdio_free(priv->bus); mdio_err: #ifdef CONFIG_CLK diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 2279481d935..b4ec3614696 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1632,6 +1632,12 @@ static const struct udevice_id eqos_ids[] = { .data = (ulong)&eqos_jh7110_config }, #endif +#if IS_ENABLED(CONFIG_DWC_ETH_QOS_ADI) + { + .compatible = "adi,sc59x-dwmac-eqos", + .data = (ulong)&eqos_adi_config + }, +#endif { } }; diff --git a/drivers/net/dwc_eth_qos.h b/drivers/net/dwc_eth_qos.h index 123f98d5d53..403e8203974 100644 --- a/drivers/net/dwc_eth_qos.h +++ b/drivers/net/dwc_eth_qos.h @@ -87,6 +87,7 @@ struct eqos_mac_regs { #define EQOS_MAC_MDIO_ADDRESS_CR_MASK GENMASK(11, 8) #define EQOS_MAC_MDIO_ADDRESS_CR_100_150 1 #define EQOS_MAC_MDIO_ADDRESS_CR_20_35 2 +#define EQOS_MAC_MDIO_ADDRESS_CR_150_250 4 #define EQOS_MAC_MDIO_ADDRESS_CR_250_300 5 #define EQOS_MAC_MDIO_ADDRESS_SKAP BIT(4) #define EQOS_MAC_MDIO_ADDRESS_GOC_MASK GENMASK(3, 2) @@ -301,3 +302,4 @@ extern struct eqos_config eqos_qcom_config; extern struct eqos_config eqos_stm32mp13_config; extern struct eqos_config eqos_stm32mp15_config; extern struct eqos_config eqos_jh7110_config; +extern struct eqos_config eqos_adi_config; diff --git a/drivers/net/dwc_eth_qos_adi.c b/drivers/net/dwc_eth_qos_adi.c new file mode 100644 index 00000000000..0e6a901e303 --- /dev/null +++ b/drivers/net/dwc_eth_qos_adi.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * (C) Copyright 2024 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Author: Greg Malysa <greg.malysa@timesys.com> + * Additional Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + */ + +#include <clk.h> +#include <dm.h> +#include <net.h> +#include <phy.h> +#include <reset.h> +#include <linux/io.h> + +#include <asm/arch-adi/sc5xx/sc5xx.h> + +#include "dwc_eth_qos.h" + +static int eqos_start_resets_adi(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + + /* + * Settings need to latch with the DMA reset below. Currently only + * rgmii is supported but other phy interfaces may be supported in + * the future + */ + sc5xx_enable_rgmii(); + setbits_32(&eqos->dma_regs->mode, EQOS_DMA_MODE_SWR); + + return 0; +} + +static int eqos_probe_resources_adi(struct udevice *dev) +{ + struct eqos_priv *eqos = dev_get_priv(dev); + phy_interface_t interface; + int ret; + + ret = eqos_get_base_addr_dt(dev); + if (ret) { + pr_err("eqos_get_base_addr_dt failed: %d\n", ret); + return ret; + } + + interface = eqos->config->interface(dev); + if (interface == PHY_INTERFACE_MODE_NA) { + pr_err("Invalid PHY interface\n"); + return -EINVAL; + } + + return 0; +} + +/** + * rgmii tx clock rate is set to 125 MHz regardless of phy mode, and + * by default the internal clock is always connected to 125 MHz. According + * to the HRM it is invalid for this clock to have any other speed, so + * the hardware won't work anyway if this is wrong. + */ +static ulong eqos_get_tick_clk_rate_adi(struct udevice *dev) +{ + return 125 * 1000000; +} + +static int eqos_get_enetaddr_adi(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + + return eth_env_get_enetaddr("ethaddr", pdata->enetaddr); +} + +static struct eqos_ops eqos_adi_ops = { + .eqos_inval_desc = eqos_inval_desc_generic, + .eqos_flush_desc = eqos_flush_desc_generic, + .eqos_inval_buffer = eqos_inval_buffer_generic, + .eqos_flush_buffer = eqos_flush_buffer_generic, + .eqos_probe_resources = eqos_probe_resources_adi, + .eqos_remove_resources = eqos_null_ops, + .eqos_start_resets = eqos_start_resets_adi, + .eqos_stop_resets = eqos_null_ops, + .eqos_start_clks = eqos_null_ops, + .eqos_stop_clks = eqos_null_ops, + .eqos_calibrate_pads = eqos_null_ops, + .eqos_disable_calibration = eqos_null_ops, + .eqos_set_tx_clk_speed = eqos_null_ops, + .eqos_get_enetaddr = eqos_get_enetaddr_adi, + .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_adi, +}; + +struct eqos_config __maybe_unused eqos_adi_config = { + .reg_access_always_ok = true, + .mdio_wait = 20, + .swr_wait = 50, + .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, + .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_150_250, + .axi_bus_width = EQOS_AXI_WIDTH_32, + .interface = dev_read_phy_mode, + .ops = &eqos_adi_ops, +}; diff --git a/drivers/net/phy/miiphybb.c b/drivers/net/phy/miiphybb.c index 553af2c1032..76463da7299 100644 --- a/drivers/net/phy/miiphybb.c +++ b/drivers/net/phy/miiphybb.c @@ -14,40 +14,16 @@ #include <ioports.h> #include <ppc_asm.tmpl> -#include <malloc.h> #include <miiphy.h> #include <asm/global_data.h> -static inline struct bb_miiphy_bus *bb_miiphy_getbus(struct mii_dev *miidev) -{ - return container_of(miidev, struct bb_miiphy_bus, mii); -} - -struct bb_miiphy_bus *bb_miiphy_alloc(void) -{ - struct bb_miiphy_bus *bus; - - bus = malloc(sizeof(*bus)); - if (!bus) - return bus; - - mdio_init(&bus->mii); - - return bus; -} - -void bb_miiphy_free(struct bb_miiphy_bus *bus) -{ - free(bus); -} - /***************************************************************************** * * Utility to send the preamble, address, and register (common to read * and write). */ -static void miiphy_pre(struct bb_miiphy_bus *bus, char read, - unsigned char addr, unsigned char reg) +static void miiphy_pre(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + char read, unsigned char addr, unsigned char reg) { int j; @@ -59,62 +35,62 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read, * but it is safer and will be much more robust. */ - bus->mdio_active(bus); - bus->set_mdio(bus, 1); + ops->mdio_active(miidev); + ops->set_mdio(miidev, 1); for (j = 0; j < 32; j++) { - bus->set_mdc(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); } /* send the start bit (01) and the read opcode (10) or write (10) */ - bus->set_mdc(bus, 0); - bus->set_mdio(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->set_mdio(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->set_mdio(bus, read); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->set_mdio(bus, !read); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, read); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, !read); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); /* send the PHY address */ for (j = 0; j < 5; j++) { - bus->set_mdc(bus, 0); + ops->set_mdc(miidev, 0); if ((addr & 0x10) == 0) { - bus->set_mdio(bus, 0); + ops->set_mdio(miidev, 0); } else { - bus->set_mdio(bus, 1); + ops->set_mdio(miidev, 1); } - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); addr <<= 1; } /* send the register address */ for (j = 0; j < 5; j++) { - bus->set_mdc(bus, 0); + ops->set_mdc(miidev, 0); if ((reg & 0x10) == 0) { - bus->set_mdio(bus, 0); + ops->set_mdio(miidev, 0); } else { - bus->set_mdio(bus, 1); + ops->set_mdio(miidev, 1); } - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); reg <<= 1; } } @@ -126,62 +102,57 @@ static void miiphy_pre(struct bb_miiphy_bus *bus, char read, * Returns: * 0 on success */ -int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg) +int bb_miiphy_read(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + int addr, int devad, int reg) { unsigned short rdreg; /* register working value */ int v; int j; /* counter */ - struct bb_miiphy_bus *bus; - bus = bb_miiphy_getbus(miidev); - if (bus == NULL) { - return -1; - } - - miiphy_pre (bus, 1, addr, reg); + miiphy_pre(miidev, ops, 1, addr, reg); /* tri-state our MDIO I/O pin so we can read */ - bus->set_mdc(bus, 0); - bus->mdio_tristate(bus); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->mdio_tristate(miidev); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); /* check the turnaround bit: the PHY should be driving it to zero */ - bus->get_mdio(bus, &v); + ops->get_mdio(miidev, &v); if (v != 0) { /* puts ("PHY didn't drive TA low\n"); */ for (j = 0; j < 32; j++) { - bus->set_mdc(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); } /* There is no PHY, return */ return -1; } - bus->set_mdc(bus, 0); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->delay(miidev); /* read 16 bits of register data, MSB first */ rdreg = 0; for (j = 0; j < 16; j++) { - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 1); + ops->delay(miidev); rdreg <<= 1; - bus->get_mdio(bus, &v); + ops->get_mdio(miidev, &v); rdreg |= (v & 0x1); - bus->set_mdc(bus, 0); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->delay(miidev); } - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); debug("%s[%s](0x%x) @ 0x%x = 0x%04x\n", __func__, miidev->name, reg, addr, rdreg); @@ -195,54 +166,47 @@ int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg) * Returns: * 0 on success */ -int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg, - u16 value) +int bb_miiphy_write(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + int addr, int devad, int reg, u16 value) { - struct bb_miiphy_bus *bus; int j; /* counter */ - bus = bb_miiphy_getbus(miidev); - if (bus == NULL) { - /* Bus not found! */ - return -1; - } - - miiphy_pre (bus, 0, addr, reg); + miiphy_pre(miidev, ops, 0, addr, reg); /* send the turnaround (10) */ - bus->set_mdc(bus, 0); - bus->set_mdio(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); - bus->set_mdc(bus, 0); - bus->set_mdio(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); + ops->set_mdc(miidev, 0); + ops->set_mdio(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); /* write 16 bits of register data, MSB first */ for (j = 0; j < 16; j++) { - bus->set_mdc(bus, 0); + ops->set_mdc(miidev, 0); if ((value & 0x00008000) == 0) { - bus->set_mdio(bus, 0); + ops->set_mdio(miidev, 0); } else { - bus->set_mdio(bus, 1); + ops->set_mdio(miidev, 1); } - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); value <<= 1; } /* * Tri-state the MDIO line. */ - bus->mdio_tristate(bus); - bus->set_mdc(bus, 0); - bus->delay(bus); - bus->set_mdc(bus, 1); - bus->delay(bus); + ops->mdio_tristate(miidev); + ops->set_mdc(miidev, 0); + ops->delay(miidev); + ops->set_mdc(miidev, 1); + ops->delay(miidev); return 0; } diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c index cb727ae9bc1..c39bef17b79 100644 --- a/drivers/net/ravb.c +++ b/drivers/net/ravb.c @@ -354,8 +354,15 @@ static int ravb_mac_init(struct ravb_priv *eth) /* Disable MAC Interrupt */ writel(0, eth->iobase + RAVB_REG_ECSIPR); - /* Recv frame limit set register */ - writel(RFLR_RFL_MIN, eth->iobase + RAVB_REG_RFLR); + /* + * Set receive frame length + * + * The length set here describes the frame from the destination address + * up to and including the CRC data. However only the frame data, + * excluding the CRC, are transferred to memory. To allow for the + * largest frames add the CRC length to the maximum Rx descriptor size. + */ + writel(RFLR_RFL_MIN + ETH_FCS_LEN, eth->iobase + RAVB_REG_RFLR); return 0; } @@ -491,27 +498,27 @@ static void ravb_stop(struct udevice *dev) } /* Bitbang MDIO access */ -static int ravb_bb_mdio_active(struct bb_miiphy_bus *bus) +static int ravb_bb_mdio_active(struct mii_dev *miidev) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MMD); return 0; } -static int ravb_bb_mdio_tristate(struct bb_miiphy_bus *bus) +static int ravb_bb_mdio_tristate(struct mii_dev *miidev) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; clrbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MMD); return 0; } -static int ravb_bb_set_mdio(struct bb_miiphy_bus *bus, int v) +static int ravb_bb_set_mdio(struct mii_dev *miidev, int v) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; if (v) setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MDO); @@ -521,18 +528,18 @@ static int ravb_bb_set_mdio(struct bb_miiphy_bus *bus, int v) return 0; } -static int ravb_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) +static int ravb_bb_get_mdio(struct mii_dev *miidev, int *v) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; *v = (readl(eth->iobase + RAVB_REG_PIR) & PIR_MDI) >> 3; return 0; } -static int ravb_bb_set_mdc(struct bb_miiphy_bus *bus, int v) +static int ravb_bb_set_mdc(struct mii_dev *miidev, int v) { - struct ravb_priv *eth = bus->priv; + struct ravb_priv *eth = miidev->priv; if (v) setbits_le32(eth->iobase + RAVB_REG_PIR, PIR_MDC); @@ -542,18 +549,40 @@ static int ravb_bb_set_mdc(struct bb_miiphy_bus *bus, int v) return 0; } -static int ravb_bb_delay(struct bb_miiphy_bus *bus) +static int ravb_bb_delay(struct mii_dev *miidev) { udelay(10); return 0; } +static const struct bb_miiphy_bus_ops ravb_bb_miiphy_bus_ops = { + .mdio_active = ravb_bb_mdio_active, + .mdio_tristate = ravb_bb_mdio_tristate, + .set_mdio = ravb_bb_set_mdio, + .get_mdio = ravb_bb_get_mdio, + .set_mdc = ravb_bb_set_mdc, + .delay = ravb_bb_delay, +}; + +static int ravb_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) +{ + return bb_miiphy_read(miidev, &ravb_bb_miiphy_bus_ops, + addr, devad, reg); +} + +static int ravb_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) +{ + return bb_miiphy_write(miidev, &ravb_bb_miiphy_bus_ops, + addr, devad, reg, value); +} + static int ravb_probe(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct ravb_priv *eth = dev_get_priv(dev); - struct bb_miiphy_bus *bb_miiphy; struct mii_dev *mdiodev; void __iomem *iobase; int ret; @@ -565,32 +594,22 @@ static int ravb_probe(struct udevice *dev) if (ret < 0) goto err_mdio_alloc; - bb_miiphy = bb_miiphy_alloc(); - if (!bb_miiphy) { + mdiodev = mdio_alloc(); + if (!mdiodev) { ret = -ENOMEM; goto err_mdio_alloc; } - mdiodev = &bb_miiphy->mii; - - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; + mdiodev->read = ravb_bb_miiphy_read; + mdiodev->write = ravb_bb_miiphy_write; + mdiodev->priv = eth; snprintf(mdiodev->name, sizeof(mdiodev->name), dev->name); - /* Copy the bus accessors and private data */ - bb_miiphy->mdio_active = ravb_bb_mdio_active; - bb_miiphy->mdio_tristate = ravb_bb_mdio_tristate; - bb_miiphy->set_mdio = ravb_bb_set_mdio; - bb_miiphy->get_mdio = ravb_bb_get_mdio; - bb_miiphy->set_mdc = ravb_bb_set_mdc; - bb_miiphy->delay = ravb_bb_delay; - bb_miiphy->priv = eth; - ret = mdio_register(mdiodev); if (ret < 0) goto err_mdio_register; - eth->bus = &bb_miiphy->mii; + eth->bus = mdiodev; /* Bring up PHY */ ret = clk_enable_bulk(ð->clks); @@ -610,7 +629,7 @@ static int ravb_probe(struct udevice *dev) err_mdio_reset: clk_release_bulk(ð->clks); err_mdio_register: - bb_miiphy_free(bb_miiphy); + mdio_free(mdiodev); err_mdio_alloc: unmap_physmem(eth->iobase, MAP_NOCACHE); return ret; diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 83e48609224..f695a3a41d2 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -644,9 +644,9 @@ static void sh_ether_stop(struct udevice *dev) } /******* for bb_miiphy *******/ -static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus) +static int sh_eth_bb_mdio_active(struct mii_dev *miidev) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; sh_eth_write(port_info, sh_eth_read(port_info, PIR) | PIR_MMD, PIR); @@ -654,9 +654,9 @@ static int sh_eth_bb_mdio_active(struct bb_miiphy_bus *bus) return 0; } -static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) +static int sh_eth_bb_mdio_tristate(struct mii_dev *miidev) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; sh_eth_write(port_info, sh_eth_read(port_info, PIR) & ~PIR_MMD, PIR); @@ -664,9 +664,9 @@ static int sh_eth_bb_mdio_tristate(struct bb_miiphy_bus *bus) return 0; } -static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) +static int sh_eth_bb_set_mdio(struct mii_dev *miidev, int v) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; if (v) @@ -679,9 +679,9 @@ static int sh_eth_bb_set_mdio(struct bb_miiphy_bus *bus, int v) return 0; } -static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) +static int sh_eth_bb_get_mdio(struct mii_dev *miidev, int *v) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; *v = (sh_eth_read(port_info, PIR) & PIR_MDI) >> 3; @@ -689,9 +689,9 @@ static int sh_eth_bb_get_mdio(struct bb_miiphy_bus *bus, int *v) return 0; } -static int sh_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) +static int sh_eth_bb_set_mdc(struct mii_dev *miidev, int v) { - struct sh_eth_dev *eth = bus->priv; + struct sh_eth_dev *eth = miidev->priv; struct sh_eth_info *port_info = ð->port_info[eth->port]; if (v) @@ -704,19 +704,41 @@ static int sh_eth_bb_set_mdc(struct bb_miiphy_bus *bus, int v) return 0; } -static int sh_eth_bb_delay(struct bb_miiphy_bus *bus) +static int sh_eth_bb_delay(struct mii_dev *miidev) { udelay(10); return 0; } +static const struct bb_miiphy_bus_ops sh_ether_bb_miiphy_bus_ops = { + .mdio_active = sh_eth_bb_mdio_active, + .mdio_tristate = sh_eth_bb_mdio_tristate, + .set_mdio = sh_eth_bb_set_mdio, + .get_mdio = sh_eth_bb_get_mdio, + .set_mdc = sh_eth_bb_set_mdc, + .delay = sh_eth_bb_delay, +}; + +static int sh_eth_bb_miiphy_read(struct mii_dev *miidev, int addr, + int devad, int reg) +{ + return bb_miiphy_read(miidev, &sh_ether_bb_miiphy_bus_ops, + addr, devad, reg); +} + +static int sh_eth_bb_miiphy_write(struct mii_dev *miidev, int addr, + int devad, int reg, u16 value) +{ + return bb_miiphy_write(miidev, &sh_ether_bb_miiphy_bus_ops, + addr, devad, reg, value); +} + static int sh_ether_probe(struct udevice *udev) { struct eth_pdata *pdata = dev_get_plat(udev); struct sh_ether_priv *priv = dev_get_priv(udev); struct sh_eth_dev *eth = &priv->shdev; - struct bb_miiphy_bus *bb_miiphy; struct mii_dev *mdiodev; int ret; @@ -727,32 +749,22 @@ static int sh_ether_probe(struct udevice *udev) if (ret < 0) return ret; #endif - bb_miiphy = bb_miiphy_alloc(); - if (!bb_miiphy) { + mdiodev = mdio_alloc(); + if (!mdiodev) { ret = -ENOMEM; return ret; } - mdiodev = &bb_miiphy->mii; - - mdiodev->read = bb_miiphy_read; - mdiodev->write = bb_miiphy_write; + mdiodev->read = sh_eth_bb_miiphy_read; + mdiodev->write = sh_eth_bb_miiphy_write; + mdiodev->priv = eth; snprintf(mdiodev->name, sizeof(mdiodev->name), udev->name); - /* Copy the bus accessors and private data */ - bb_miiphy->mdio_active = sh_eth_bb_mdio_active; - bb_miiphy->mdio_tristate = sh_eth_bb_mdio_tristate; - bb_miiphy->set_mdio = sh_eth_bb_set_mdio; - bb_miiphy->get_mdio = sh_eth_bb_get_mdio; - bb_miiphy->set_mdc = sh_eth_bb_set_mdc; - bb_miiphy->delay = sh_eth_bb_delay; - bb_miiphy->priv = eth; - ret = mdio_register(mdiodev); if (ret < 0) goto err_mdio_register; - priv->bus = &bb_miiphy->mii; + priv->bus = mdiodev; eth->port = CFG_SH_ETHER_USE_PORT; eth->port_info[eth->port].phy_addr = CFG_SH_ETHER_PHY_ADDR; @@ -782,7 +794,7 @@ err_phy_config: clk_disable(&priv->clk); #endif err_mdio_register: - bb_miiphy_free(bb_miiphy); + mdio_free(mdiodev); return ret; } diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 6481ee24a60..bd4ebdd745a 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -278,6 +278,24 @@ static int tsec_send(struct udevice *dev, void *packet, int length) return result; } +static int tsec_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct tsec_private *priv = (struct tsec_private *)dev_get_priv(dev); + u16 status; + + out_be16(&priv->rxbd[priv->rx_idx].length, 0); + + status = RXBD_EMPTY; + /* Set the wrap bit if this is the last element in the list */ + if ((priv->rx_idx + 1) == PKTBUFSRX) + status |= RXBD_WRAP; + out_be16(&priv->rxbd[priv->rx_idx].status, status); + + priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX; + + return 0; +} + static int tsec_recv(struct udevice *dev, int flags, uchar **packetp) { struct tsec_private *priv = (struct tsec_private *)dev_get_priv(dev); @@ -296,6 +314,9 @@ static int tsec_recv(struct udevice *dev, int flags, uchar **packetp) ret = length - 4; } else { printf("Got error %x\n", (status & RXBD_STATS)); + + /* Rearm the packet buffer */ + tsec_free_pkt(dev, NULL, 0); } } @@ -307,24 +328,6 @@ static int tsec_recv(struct udevice *dev, int flags, uchar **packetp) return ret; } -static int tsec_free_pkt(struct udevice *dev, uchar *packet, int length) -{ - struct tsec_private *priv = (struct tsec_private *)dev_get_priv(dev); - u16 status; - - out_be16(&priv->rxbd[priv->rx_idx].length, 0); - - status = RXBD_EMPTY; - /* Set the wrap bit if this is the last element in the list */ - if ((priv->rx_idx + 1) == PKTBUFSRX) - status |= RXBD_WRAP; - out_be16(&priv->rxbd[priv->rx_idx].status, status); - - priv->rx_idx = (priv->rx_idx + 1) % PKTBUFSRX; - - return 0; -} - static void tsec_halt(struct udevice *dev) { struct tsec_private *priv; diff --git a/drivers/pci/pci_auto.c b/drivers/pci/pci_auto.c index 90f81886445..e68e31a8227 100644 --- a/drivers/pci/pci_auto.c +++ b/drivers/pci/pci_auto.c @@ -107,7 +107,8 @@ static void dm_pciauto_setup_device(struct udevice *dev, } if (prefetch && - (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH)) + (bar_response & PCI_BASE_ADDRESS_MEM_PREFETCH) && + (found_mem64 || prefetch->bus_lower < 0x100000000ULL)) bar_res = prefetch; else bar_res = mem; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 6ee7dc1cce8..687fb339ea0 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -178,6 +178,14 @@ config PINCTRL_APPLE both the GPIO definitions and pin control functions for each available multiplex function. +config PINCTRL_ADI + bool "ADI pinctrl driver" + depends on DM && ARCH_SC5XX + help + This driver enables pinctrl support on SC5xx processors. This + driver covers only the pin configuration functionality, and + GPIO functionality is contained in the separate GPIO driver. + config PINCTRL_AR933X bool "QCA/Athores ar933x pin control driver" depends on DM && SOC_AR933X diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 634047a91f4..6deb6aaf6eb 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -3,6 +3,7 @@ obj-y += pinctrl-uclass.o obj-$(CONFIG_$(XPL_)PINCTRL_GENERIC) += pinctrl-generic.o +obj-$(CONFIG_PINCTRL_ADI) += pinctrl-adi-adsp.o obj-$(CONFIG_PINCTRL_APPLE) += pinctrl-apple.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o @@ -15,7 +16,6 @@ obj-$(CONFIG_ARCH_MTMIPS) += mtmips/ obj-$(CONFIG_ARCH_NPCM) += nuvoton/ obj-$(CONFIG_PINCTRL_QCOM) += qcom/ obj-$(CONFIG_ARCH_RENESAS) += renesas/ -obj-$(CONFIG_ARCH_RZN1) += renesas/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ obj-$(CONFIG_$(XPL_)PINCTRL_TEGRA) += tegra/ diff --git a/drivers/pinctrl/pinctrl-adi-adsp.c b/drivers/pinctrl/pinctrl-adi-adsp.c new file mode 100644 index 00000000000..debf434212d --- /dev/null +++ b/drivers/pinctrl/pinctrl-adi-adsp.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Author: Greg Malysa <greg.malysa@timesys.com> + * Additional Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * + * dm pinctrl implementation for ADI ADSP SoCs + * + */ + +#include <dm.h> +#include <dm/pinctrl.h> +#include <dm/device_compat.h> +#include <linux/bitops.h> +#include <linux/io.h> + +#define ADSP_PORT_MMIO_SIZE 0x80 +#define ADSP_PORT_PIN_SIZE 16 + +#define ADSP_PORT_PORT_MUX_BITS 2 +#define ADSP_PORT_PORT_MUX_MASK 0x03 +#define ADSP_PINCTRL_FUNCTION_COUNT 4 + +#define ADSP_PORT_REG_FER 0x00 +#define ADSP_PORT_REG_FER_SET 0x04 +#define ADSP_PORT_REG_FER_CLEAR 0x08 +#define ADSP_PORT_REG_DATA 0x0c +#define ADSP_PORT_REG_DATA_SET 0x10 +#define ADSP_PORT_REG_DATA_CLEAR 0x14 +#define ADSP_PORT_REG_DIR 0x18 +#define ADSP_PORT_REG_DIR_SET 0x1c +#define ADSP_PORT_REG_DIR_CLEAR 0x20 +#define ADSP_PORT_REG_INEN 0x24 +#define ADSP_PORT_REG_INEN_SET 0x28 +#define ADSP_PORT_REG_INEN_CLEAR 0x2c +#define ADSP_PORT_REG_PORT_MUX 0x30 +#define ADSP_PORT_REG_DATA_TGL 0x34 +#define ADSP_PORT_REG_POLAR 0x38 +#define ADSP_PORT_REG_POLAR_SET 0x3c +#define ADSP_PORT_REG_POLAR_CLEAR 0x40 +#define ADSP_PORT_REG_LOCK 0x44 +#define ADSP_PORT_REG_TRIG_TGL 0x48 + +struct adsp_pinctrl_priv { + void __iomem *base; + int npins; + char pinbuf[16]; +}; + +static u32 get_port(unsigned int pin) +{ + return pin / ADSP_PORT_PIN_SIZE; +} + +static u32 get_offset(unsigned int pin) +{ + return pin % ADSP_PORT_PIN_SIZE; +} + +static int adsp_pinctrl_pinmux_set(struct udevice *udev, unsigned int pin, unsigned int func) +{ + struct adsp_pinctrl_priv *priv = dev_get_priv(udev); + void __iomem *portbase; + u32 port, offset; + u32 val; + + if (pin >= priv->npins) + return -ENODEV; + + if (func >= ADSP_PINCTRL_FUNCTION_COUNT) + return -EINVAL; + + port = get_port(pin); + offset = get_offset(pin); + portbase = priv->base + port * ADSP_PORT_MMIO_SIZE; + + val = ioread32(portbase + ADSP_PORT_REG_PORT_MUX); + val &= ~(ADSP_PORT_PORT_MUX_MASK << (ADSP_PORT_PORT_MUX_BITS * offset)); + val |= func << (ADSP_PORT_PORT_MUX_BITS * offset); + iowrite32(val, portbase + ADSP_PORT_REG_PORT_MUX); + + iowrite32(BIT(offset), portbase + ADSP_PORT_REG_FER_SET); + return 0; +} + +static int adsp_pinctrl_set_state(struct udevice *udev, struct udevice *config) +{ + const struct fdt_property *pinlist; + int length = 0; + int ret, i; + u32 pin, function; + + pinlist = dev_read_prop(config, "adi,pins", &length); + if (!pinlist) { + dev_err(udev, "missing adi,pins property in pinctrl config node\n"); + return -EINVAL; + } + + if (length % (sizeof(uint32_t) * 2)) { + dev_err(udev, "adi,pins property must be a multiple of two uint32_ts\n"); + return -EINVAL; + } + + for (i = 0; i < length / sizeof(uint32_t); i += 2) { + ret = dev_read_u32_index(config, "adi,pins", i, &pin); + if (ret) + return ret; + + ret = dev_read_u32_index(config, "adi,pins", i + 1, &function); + if (ret) + return ret; + + ret = adsp_pinctrl_pinmux_set(udev, pin, function); + if (ret) + return ret; + } + + return 0; +} + +const struct pinctrl_ops adsp_pinctrl_ops = { + .set_state = adsp_pinctrl_set_state, +}; + +static int adsp_pinctrl_probe(struct udevice *udev) +{ + struct adsp_pinctrl_priv *priv = dev_get_priv(udev); + + priv->base = dev_read_addr_ptr(udev); + priv->npins = dev_read_u32_default(udev, "adi,npins", 0); + + if (!priv->base) { + dev_err(udev, "Missing or invalid pinctrl base address\n"); + return -ENOENT; + } + + if (!priv->npins) { + dev_err(udev, "Missing adi,npins property!\n"); + return -ENOENT; + } + + return 0; +} + +static const struct udevice_id adsp_pinctrl_match[] = { + { .compatible = "adi,adsp-pinctrl" }, + { }, +}; + +U_BOOT_DRIVER(adi_adsp_pinctrl) = { + .name = "adi_adsp_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = adsp_pinctrl_match, + .probe = adsp_pinctrl_probe, + .priv_auto = sizeof(struct adsp_pinctrl_priv), + .ops = &adsp_pinctrl_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/pinctrl/qcom/pinctrl-sm8250.c b/drivers/pinctrl/qcom/pinctrl-sm8250.c index cab42fa64ed..b21cdc4d24b 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8250.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8250.c @@ -107,7 +107,7 @@ static unsigned int sm8250_get_function_mux(__maybe_unused unsigned int pin, uns static struct msm_pinctrl_data sm8250_data = { .pin_data = { .pin_offsets = sm8250_pin_offsets, - .pin_count = ARRAY_SIZE(sm8250_pin_offsets), + .pin_count = 184, .special_pins_start = 180, .special_pins_data = sm8250_special_pins_data, }, diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c index ad7112a05e6..e6b957f5537 100644 --- a/drivers/pinctrl/tegra/pinctrl-tegra.c +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -67,6 +67,58 @@ exit: kfree(drive_group); } +#ifdef TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS +static void tegra_pinctrl_set_mipipad(struct udevice *config, int padcnt) +{ + struct pmux_mipipadctrlgrp_config *mipipad_group; + int i, ret, pad_id; + const char *function; + const char **pads; + + mipipad_group = kmalloc_array(padcnt, sizeof(*mipipad_group), GFP_KERNEL); + if (!mipipad_group) { + log_debug("%s: cannot allocate mipi pad group array\n", __func__); + return; + } + + /* decode function id and fill the first copy of pmux_mipipadctrlgrp_config */ + function = dev_read_string(config, "nvidia,function"); + if (function) + for (i = 0; i < PMUX_FUNC_COUNT; i++) + if (tegra_pinctrl_to_func[i]) + if (!strcmp(function, tegra_pinctrl_to_func[i])) + break; + + mipipad_group[0].func = i; + + for (i = 1; i < padcnt; i++) + memcpy(&mipipad_group[i], &mipipad_group[0], sizeof(mipipad_group[0])); + + ret = dev_read_string_list(config, "nvidia,pins", &pads); + if (ret < 0) { + log_debug("%s: could not parse property nvidia,pins\n", __func__); + goto exit; + } + + for (i = 0; i < padcnt; i++) { + for (pad_id = 0; pad_id < PMUX_MIPIPADCTRLGRP_COUNT; pad_id++) + if (tegra_pinctrl_to_mipipadgrp[pad_id]) + if (!strcmp(pads[i], tegra_pinctrl_to_mipipadgrp[pad_id])) { + mipipad_group[i].grp = pad_id; + break; + } + } + + pinmux_config_mipipadctrlgrp_table(mipipad_group, padcnt); + + free(pads); +exit: + kfree(mipipad_group); +} +#else +static void tegra_pinctrl_set_mipipad(struct udevice *config, int padcnt) { } +#endif + static void tegra_pinctrl_set_pin(struct udevice *config, int pincnt) { struct pmux_pingrp_config *pinmux_group; @@ -170,6 +222,9 @@ static int tegra_pinctrl_set_state(struct udevice *dev, struct udevice *config) if (!strncmp(name, "drive_", 6)) /* Drive node is detected */ tegra_pinctrl_set_drive(child, ret); + else if (!strncmp(name, "mipi_pad_ctrl_", 14)) + /* Handle T124 specific pinconfig */ + tegra_pinctrl_set_mipipad(child, ret); else /* Pin node is detected */ tegra_pinctrl_set_pin(child, ret); @@ -236,6 +291,7 @@ static int tegra_pinctrl_bind(struct udevice *dev) static const struct udevice_id tegra_pinctrl_ids[] = { { .compatible = "nvidia,tegra30-pinmux" }, { .compatible = "nvidia,tegra114-pinmux" }, + { .compatible = "nvidia,tegra124-pinmux" }, { }, }; diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c b/drivers/power/regulator/qcom-rpmh-regulator.c index 70df51b5fa4..cd2b1a654c1 100644 --- a/drivers/power/regulator/qcom-rpmh-regulator.c +++ b/drivers/power/regulator/qcom-rpmh-regulator.c @@ -481,6 +481,13 @@ static const struct rpmh_vreg_init_data pm8150_vreg_data[] = { static const struct rpmh_vreg_init_data pm8150l_vreg_data[] = { RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l8"), + RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"), + RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"), + RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo_lv, "vdd-l1-l8"), + RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"), + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"), RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"), {} }; diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 3d2831a3e36..a3ecea05e20 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -13,6 +13,7 @@ config REMOTEPROC depends on DM # Please keep the configuration alphabetically sorted. + config K3_SYSTEM_CONTROLLER bool "Support for TI' K3 System Controller" select REMOTEPROC @@ -22,6 +23,16 @@ config K3_SYSTEM_CONTROLLER help Say 'y' here to add support for TI' K3 System Controller. +config REMOTEPROC_ADI_SC5XX + bool "Support for ADI SC5xx SHARC cores" + select REMOTEPROC + depends on DM + depends on ARCH_SC5XX + depends on SYSCON + help + Say 'y' here to add support for loading code onto SHARC cores in + an ADSP-SC5xx SoC from Analog Devices + config REMOTEPROC_RENESAS_APMU bool "Support for Renesas R-Car Gen4 APMU start of CR52 processor" select REMOTEPROC diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index f81e5009c5e..bd94ea771be 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_$(XPL_)REMOTEPROC) += rproc-uclass.o rproc-elf-loader.o # Remote proc drivers - Please keep this list alphabetically sorted. obj-$(CONFIG_K3_SYSTEM_CONTROLLER) += k3_system_controller.o +obj-$(CONFIG_REMOTEPROC_ADI_SC5XX) += adi_sc5xx_rproc.o obj-$(CONFIG_REMOTEPROC_RENESAS_APMU) += renesas_apmu.o obj-$(CONFIG_REMOTEPROC_SANDBOX) += sandbox_testproc.o obj-$(CONFIG_REMOTEPROC_STM32_COPRO) += stm32_copro.o diff --git a/drivers/remoteproc/adi_sc5xx_rproc.c b/drivers/remoteproc/adi_sc5xx_rproc.c new file mode 100644 index 00000000000..86acd1b98c7 --- /dev/null +++ b/drivers/remoteproc/adi_sc5xx_rproc.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + * Analog Devices SC5xx remoteproc driver for loading code onto SHARC cores + */ + +#include <dm.h> +#include <regmap.h> +#include <remoteproc.h> +#include <syscon.h> +#include <dm/device_compat.h> +#include <linux/delay.h> +#include <linux/io.h> + +/* Register offsets */ +#ifdef CONFIG_SC58X +#define ADI_RCU_REG_CTL 0x00 +#define ADI_RCU_REG_STAT 0x04 +#define ADI_RCU_REG_CRCTL 0x08 +#define ADI_RCU_REG_CRSTAT 0x0c +#define ADI_RCU_REG_SIDIS 0x10 +#define ADI_RCU_REG_SISTAT 0x14 +#define ADI_RCU_REG_BCODE 0x1c +#define ADI_RCU_REG_SVECT0 0x20 +#define ADI_RCU_REG_SVECT1 0x24 +#define ADI_RCU_REG_SVECT2 0x28 +#define ADI_RCU_REG_MSG 0x60 +#define ADI_RCU_REG_MSG_SET 0x64 +#define ADI_RCU_REG_MSG_CLR 0x68 +#else +#define ADI_RCU_REG_CTL 0x00 +#define ADI_RCU_REG_STAT 0x04 +#define ADI_RCU_REG_CRCTL 0x08 +#define ADI_RCU_REG_CRSTAT 0x0c +#define ADI_RCU_REG_SRRQSTAT 0x18 +#define ADI_RCU_REG_SIDIS 0x1c +#define ADI_RCU_REG_SISTAT 0x20 +#define ADI_RCU_REG_SVECT_LCK 0x24 +#define ADI_RCU_REG_BCODE 0x28 +#define ADI_RCU_REG_SVECT0 0x2c +#define ADI_RCU_REG_SVECT1 0x30 +#define ADI_RCU_REG_SVECT2 0x34 +#define ADI_RCU_REG_MSG 0x6c +#define ADI_RCU_REG_MSG_SET 0x70 +#define ADI_RCU_REG_MSG_CLR 0x74 +#endif /* CONFIG_SC58X */ + +/* Register bit definitions */ +#define ADI_RCU_CTL_SYSRST BIT(0) + +/* Bit values for the RCU0_MSG register */ +#define RCU0_MSG_C0IDLE 0x00000100 /* Core 0 Idle */ +#define RCU0_MSG_C1IDLE 0x00000200 /* Core 1 Idle */ +#define RCU0_MSG_C2IDLE 0x00000400 /* Core 2 Idle */ +#define RCU0_MSG_CRR0 0x00001000 /* Core 0 reset request */ +#define RCU0_MSG_CRR1 0x00002000 /* Core 1 reset request */ +#define RCU0_MSG_CRR2 0x00004000 /* Core 2 reset request */ +#define RCU0_MSG_C1ACTIVATE 0x00080000 /* Core 1 Activated */ +#define RCU0_MSG_C2ACTIVATE 0x00100000 /* Core 2 Activated */ + +struct sc5xx_rproc_data { + /* Address to load to svect when rebooting core */ + u32 load_addr; + + /* RCU parameters */ + struct regmap *rcu; + u32 svect_offset; + u32 coreid; +}; + +struct block_code_flag { + u32 bcode:4, /* 0-3 */ + bflag_save:1, /* 4 */ + bflag_aux:1, /* 5 */ + breserved:1, /* 6 */ + bflag_forward:1, /* 7 */ + bflag_fill:1, /* 8 */ + bflag_quickboot:1, /* 9 */ + bflag_callback:1, /* 10 */ + bflag_init:1, /* 11 */ + bflag_ignore:1, /* 12 */ + bflag_indirect:1, /* 13 */ + bflag_first:1, /* 14 */ + bflag_final:1, /* 15 */ + bhdrchk:8, /* 16-23 */ + bhdrsign:8; /* 0xAD, 0xAC or 0xAB */ +}; + +struct ldr_hdr { + struct block_code_flag bcode_flag; + u32 target_addr; + u32 byte_count; + u32 argument; +}; + +static int is_final(struct ldr_hdr *hdr) +{ + return hdr->bcode_flag.bflag_final; +} + +static int is_empty(struct ldr_hdr *hdr) +{ + return hdr->bcode_flag.bflag_ignore || (hdr->byte_count == 0); +} + +static int adi_valid_firmware(struct ldr_hdr *adi_ldr_hdr) +{ + if (!adi_ldr_hdr->byte_count && + (adi_ldr_hdr->bcode_flag.bhdrsign == 0xAD || + adi_ldr_hdr->bcode_flag.bhdrsign == 0xAC || + adi_ldr_hdr->bcode_flag.bhdrsign == 0xAB)) + return 1; + + return 0; +} + +static int sharc_load(struct udevice *dev, ulong addr, ulong size) +{ + struct sc5xx_rproc_data *priv = dev_get_priv(dev); + size_t offset; + u8 *buf = (u8 *)addr; + struct ldr_hdr *ldr = (struct ldr_hdr *)addr; + struct ldr_hdr *block_hdr; + struct ldr_hdr *next_hdr; + + if (!adi_valid_firmware(ldr)) { + dev_err(dev, "Firmware at 0x%lx does not appear to be an LDR image\n", addr); + dev_err(dev, "Note: Signed firmware is not currently supported\n"); + return -EINVAL; + } + + do { + block_hdr = (struct ldr_hdr *)buf; + offset = sizeof(struct ldr_hdr) + (block_hdr->bcode_flag.bflag_fill ? + 0 : block_hdr->byte_count); + next_hdr = (struct ldr_hdr *)(buf + offset); + + if (block_hdr->bcode_flag.bflag_first) + priv->load_addr = (unsigned long)block_hdr->target_addr; + + if (!is_empty(block_hdr)) { + if (block_hdr->bcode_flag.bflag_fill) { + memset_io((void *)(phys_addr_t)block_hdr->target_addr, + block_hdr->argument, + block_hdr->byte_count); + } else { + memcpy_toio((void *)(phys_addr_t)block_hdr->target_addr, + buf + sizeof(struct ldr_hdr), + block_hdr->byte_count); + } + } + + if (is_final(block_hdr)) + break; + + buf += offset; + } while (1); + + return 0; +} + +static void sharc_reset(struct sc5xx_rproc_data *priv) +{ + u32 coreid = priv->coreid; + u32 val; + + /* First put core in reset. + * Clear CRSTAT bit for given coreid. + */ + regmap_write(priv->rcu, ADI_RCU_REG_CRSTAT, 1 << coreid); + + /* Set SIDIS to disable the system interface */ + regmap_read(priv->rcu, ADI_RCU_REG_SIDIS, &val); + regmap_write(priv->rcu, ADI_RCU_REG_SIDIS, val | (1 << (coreid - 1))); + + /* + * Wait for access to coreX have been disabled and all the pending + * transactions have completed + */ + udelay(50); + + /* Set CRCTL bit to put core in reset */ + regmap_read(priv->rcu, ADI_RCU_REG_CRCTL, &val); + regmap_write(priv->rcu, ADI_RCU_REG_CRCTL, val | (1 << coreid)); + + /* Poll until Core is in reset */ + while (!(regmap_read(priv->rcu, ADI_RCU_REG_CRSTAT, &val), val & (1 << coreid))) + ; + + /* Clear SIDIS to reenable the system interface */ + regmap_read(priv->rcu, ADI_RCU_REG_SIDIS, &val); + regmap_write(priv->rcu, ADI_RCU_REG_SIDIS, val & ~(1 << (coreid - 1))); + + udelay(50); + + /* Take Core out of reset */ + regmap_read(priv->rcu, ADI_RCU_REG_CRCTL, &val); + regmap_write(priv->rcu, ADI_RCU_REG_CRCTL, val & ~(1 << coreid)); + + /* Wait for done */ + udelay(50); +} + +static int sharc_start(struct udevice *dev) +{ + struct sc5xx_rproc_data *priv = dev_get_priv(dev); + + /* Write load address to appropriate SVECT for core */ + regmap_write(priv->rcu, priv->svect_offset, priv->load_addr); + + sharc_reset(priv); + + /* Clear the IDLE bit when start the SHARC core */ + regmap_write(priv->rcu, ADI_RCU_REG_MSG_CLR, RCU0_MSG_C0IDLE << priv->coreid); + + /* Notify CCES */ + regmap_write(priv->rcu, ADI_RCU_REG_MSG_SET, RCU0_MSG_C1ACTIVATE << (priv->coreid - 1)); + return 0; +} + +static const struct dm_rproc_ops sc5xx_ops = { + .load = sharc_load, + .start = sharc_start, +}; + +static int sc5xx_probe(struct udevice *dev) +{ + struct sc5xx_rproc_data *priv = dev_get_priv(dev); + u32 coreid; + + if (dev_read_u32(dev, "coreid", &coreid)) { + dev_err(dev, "Missing property coreid\n"); + return -ENOENT; + } + + priv->coreid = coreid; + switch (coreid) { + case 1: + priv->svect_offset = ADI_RCU_REG_SVECT1; + break; + case 2: + priv->svect_offset = ADI_RCU_REG_SVECT2; + break; + default: + dev_err(dev, "Invalid value %d for coreid, must be 1 or 2\n", coreid); + return -EINVAL; + } + + priv->rcu = syscon_regmap_lookup_by_phandle(dev, "adi,rcu"); + if (IS_ERR(priv->rcu)) + return PTR_ERR(priv->rcu); + + dev_err(dev, "sc5xx remoteproc core %d available\n", priv->coreid); + + return 0; +} + +static const struct udevice_id sc5xx_ids[] = { + { .compatible = "adi,sc5xx-rproc" }, + { } +}; + +U_BOOT_DRIVER(adi_sc5xx_rproc) = { + .name = "adi_sc5xx_rproc", + .of_match = sc5xx_ids, + .id = UCLASS_REMOTEPROC, + .ops = &sc5xx_ops, + .probe = sc5xx_probe, + .priv_auto = sizeof(struct sc5xx_rproc_data), + .flags = 0, +}; diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index ebe692a9963..2ef8ba20cf5 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -63,7 +63,4 @@ obj-$(CONFIG_XEN_SERIAL) += serial_xen.o obj-$(CONFIG_XTENSA_SEMIHOSTING_SERIAL) += serial_xtensa_semihosting.o obj-$(CONFIG_S5P4418_PL011_SERIAL) += serial_s5p4418_pl011.o -ifndef CONFIG_XPL_BUILD -obj-$(CONFIG_USB_TTY) += usbtty.o -endif obj-$(CONFIG_UART4_SERIAL) += serial_adi_uart4.o diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 7e460f6d2c7..4f7de3ea215 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -294,13 +294,9 @@ void ns16550_putc(struct ns16550 *com_port, char c) #if !CONFIG_IS_ENABLED(NS16550_MIN_FUNCTIONS) char ns16550_getc(struct ns16550 *com_port) { - while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) { -#if !defined(CONFIG_XPL_BUILD) && defined(CONFIG_USB_TTY) - extern void usbtty_poll(void); - usbtty_poll(); -#endif + while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) schedule(); - } + return serial_in(&com_port->rbr); } diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c deleted file mode 100644 index b7d77fbb6a9..00000000000 --- a/drivers/serial/usbtty.c +++ /dev/null @@ -1,983 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * (C) Copyright 2006 - * Bryan O'Donoghue, bodonoghue@codehermit.ie - */ - -#include <config.h> -#include <circbuf.h> -#include <env.h> -#include <serial.h> -#include <stdio_dev.h> -#include <asm/unaligned.h> -#include "usbtty.h" -#include "usb_cdc_acm.h" -#include "usbdescriptors.h" - -#ifdef DEBUG -#define TTYDBG(fmt,args...)\ - serial_printf("[%s] %s %d: "fmt, __FILE__,__FUNCTION__,__LINE__,##args) -#else -#define TTYDBG(fmt,args...) do{}while(0) -#endif - -#if 1 -#define TTYERR(fmt,args...)\ - serial_printf("ERROR![%s] %s %d: "fmt, __FILE__,__FUNCTION__,\ - __LINE__,##args) -#else -#define TTYERR(fmt,args...) do{}while(0) -#endif - -/* - * Defines - */ -#define NUM_CONFIGS 1 -#define MAX_INTERFACES 2 -#define NUM_ENDPOINTS 3 -#define ACM_TX_ENDPOINT 3 -#define ACM_RX_ENDPOINT 2 -#define GSERIAL_TX_ENDPOINT 2 -#define GSERIAL_RX_ENDPOINT 1 -#define NUM_ACM_INTERFACES 2 -#define NUM_GSERIAL_INTERFACES 1 -#define CFG_USBD_DATA_INTERFACE_STR "Bulk Data Interface" -#define CFG_USBD_CTRL_INTERFACE_STR "Control Interface" - -/* - * Buffers to hold input and output data - */ -#define USBTTY_BUFFER_SIZE 2048 -static circbuf_t usbtty_input; -static circbuf_t usbtty_output; - -/* - * Instance variables - */ -static struct stdio_dev usbttydev; -static struct usb_device_instance device_instance[1]; -static struct usb_bus_instance bus_instance[1]; -static struct usb_configuration_instance config_instance[NUM_CONFIGS]; -static struct usb_interface_instance interface_instance[MAX_INTERFACES]; -static struct usb_alternate_instance alternate_instance[MAX_INTERFACES]; -/* one extra for control endpoint */ -static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS+1]; - -/* - * Global flag - */ -int usbtty_configured_flag = 0; - -/* - * Serial number - */ -static char serial_number[16]; - -/* - * Descriptors, Strings, Local variables. - */ - -/* defined and used by gadget/ep0.c */ -extern struct usb_string_descriptor **usb_strings; - -/* Indicies, References */ -static unsigned short rx_endpoint = 0; -static unsigned short tx_endpoint = 0; -static unsigned short interface_count = 0; -static struct usb_string_descriptor *usbtty_string_table[STR_COUNT]; - -/* USB Descriptor Strings */ -static u8 wstrLang[4] = {4,USB_DT_STRING,0x9,0x4}; -static u8 wstrManufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)]; -static u8 wstrProduct[2 + 2*(sizeof(CONFIG_USBD_PRODUCT_NAME)-1)]; -static u8 wstrSerial[2 + 2*(sizeof(serial_number) - 1)]; -static u8 wstrConfiguration[2 + 2*(sizeof(CFG_USBD_CONFIGURATION_STR)-1)]; -static u8 wstrDataInterface[2 + 2*(sizeof(CFG_USBD_DATA_INTERFACE_STR)-1)]; -static u8 wstrCtrlInterface[2 + 2*(sizeof(CFG_USBD_DATA_INTERFACE_STR)-1)]; - -/* Standard USB Data Structures */ -static struct usb_interface_descriptor interface_descriptors[MAX_INTERFACES]; -static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS]; -static struct usb_configuration_descriptor *configuration_descriptor = 0; -static struct usb_device_descriptor device_descriptor = { - .bLength = sizeof(struct usb_device_descriptor), - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = cpu_to_le16(USB_BCD_VERSION), - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE, - .idVendor = cpu_to_le16(CONFIG_USBD_VENDORID), - .bcdDevice = cpu_to_le16(USBTTY_BCD_DEVICE), - .iManufacturer = STR_MANUFACTURER, - .iProduct = STR_PRODUCT, - .iSerialNumber = STR_SERIAL, - .bNumConfigurations = NUM_CONFIGS -}; - -/* - * Static CDC ACM specific descriptors - */ - -struct acm_config_desc { - struct usb_configuration_descriptor configuration_desc; - - /* Master Interface */ - struct usb_interface_descriptor interface_desc; - - struct usb_class_header_function_descriptor usb_class_header; - struct usb_class_call_management_descriptor usb_class_call_mgt; - struct usb_class_abstract_control_descriptor usb_class_acm; - struct usb_class_union_function_descriptor usb_class_union; - struct usb_endpoint_descriptor notification_endpoint; - - /* Slave Interface */ - struct usb_interface_descriptor data_class_interface; - struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS-1]; -} __attribute__((packed)); - -static struct acm_config_desc acm_configuration_descriptors[NUM_CONFIGS] = { - { - .configuration_desc ={ - .bLength = - sizeof(struct usb_configuration_descriptor), - .bDescriptorType = USB_DT_CONFIG, - .wTotalLength = - cpu_to_le16(sizeof(struct acm_config_desc)), - .bNumInterfaces = NUM_ACM_INTERFACES, - .bConfigurationValue = 1, - .iConfiguration = STR_CONFIG, - .bmAttributes = - BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, - .bMaxPower = USBTTY_MAXPOWER - }, - /* Interface 1 */ - .interface_desc = { - .bLength = sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 0x01, - .bInterfaceClass = - COMMUNICATIONS_INTERFACE_CLASS_CONTROL, - .bInterfaceSubClass = COMMUNICATIONS_ACM_SUBCLASS, - .bInterfaceProtocol = COMMUNICATIONS_V25TER_PROTOCOL, - .iInterface = STR_CTRL_INTERFACE, - }, - .usb_class_header = { - .bFunctionLength = - sizeof(struct usb_class_header_function_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_ST_HEADER, - .bcdCDC = cpu_to_le16(110), - }, - .usb_class_call_mgt = { - .bFunctionLength = - sizeof(struct usb_class_call_management_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_ST_CMF, - .bmCapabilities = 0x00, - .bDataInterface = 0x01, - }, - .usb_class_acm = { - .bFunctionLength = - sizeof(struct usb_class_abstract_control_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_ST_ACMF, - .bmCapabilities = 0x00, - }, - .usb_class_union = { - .bFunctionLength = - sizeof(struct usb_class_union_function_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_ST_UF, - .bMasterInterface = 0x00, - .bSlaveInterface0 = 0x01, - }, - .notification_endpoint = { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize - = cpu_to_le16(CFG_USBD_SERIAL_INT_PKTSIZE), - .bInterval = 0xFF, - }, - - /* Interface 2 */ - .data_class_interface = { - .bLength = - sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0x01, - .bAlternateSetting = 0x00, - .bNumEndpoints = 0x02, - .bInterfaceClass = - COMMUNICATIONS_INTERFACE_CLASS_DATA, - .bInterfaceSubClass = DATA_INTERFACE_SUBCLASS_NONE, - .bInterfaceProtocol = DATA_INTERFACE_PROTOCOL_NONE, - .iInterface = STR_DATA_INTERFACE, - }, - .data_endpoints = { - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT, - .bmAttributes = - USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_BULK_PKTSIZE), - .bInterval = 0xFF, - }, - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN, - .bmAttributes = - USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_BULK_PKTSIZE), - .bInterval = 0xFF, - }, - }, - }, -}; - -static struct rs232_emu rs232_desc={ - .dter = 115200, - .stop_bits = 0x00, - .parity = 0x00, - .data_bits = 0x08 -}; - -/* - * Static Generic Serial specific data - */ - -struct gserial_config_desc { - - struct usb_configuration_descriptor configuration_desc; - struct usb_interface_descriptor interface_desc[NUM_GSERIAL_INTERFACES]; - struct usb_endpoint_descriptor data_endpoints[NUM_ENDPOINTS]; - -} __attribute__((packed)); - -static struct gserial_config_desc -gserial_configuration_descriptors[NUM_CONFIGS] ={ - { - .configuration_desc ={ - .bLength = sizeof(struct usb_configuration_descriptor), - .bDescriptorType = USB_DT_CONFIG, - .wTotalLength = - cpu_to_le16(sizeof(struct gserial_config_desc)), - .bNumInterfaces = NUM_GSERIAL_INTERFACES, - .bConfigurationValue = 1, - .iConfiguration = STR_CONFIG, - .bmAttributes = - BMATTRIBUTE_SELF_POWERED|BMATTRIBUTE_RESERVED, - .bMaxPower = USBTTY_MAXPOWER - }, - .interface_desc = { - { - .bLength = - sizeof(struct usb_interface_descriptor), - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = NUM_ENDPOINTS, - .bInterfaceClass = - COMMUNICATIONS_INTERFACE_CLASS_VENDOR, - .bInterfaceSubClass = - COMMUNICATIONS_NO_SUBCLASS, - .bInterfaceProtocol = - COMMUNICATIONS_NO_PROTOCOL, - .iInterface = STR_DATA_INTERFACE - }, - }, - .data_endpoints = { - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_OUT_ENDPOINT | USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_OUT_PKTSIZE), - .bInterval= 0xFF, - }, - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_IN_ENDPOINT | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_IN_PKTSIZE), - .bInterval = 0xFF, - }, - { - .bLength = - sizeof(struct usb_endpoint_descriptor), - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = UDC_INT_ENDPOINT | USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = - cpu_to_le16(CFG_USBD_SERIAL_INT_PKTSIZE), - .bInterval = 0xFF, - }, - }, - }, -}; - -/* - * Static Function Prototypes - */ - -static void usbtty_init_strings (void); -static void usbtty_init_instances (void); -static void usbtty_init_endpoints (void); -static void usbtty_init_terminal_type(short type); -static void usbtty_event_handler (struct usb_device_instance *device, - usb_device_event_t event, int data); -static int usbtty_cdc_setup(struct usb_device_request *request, - struct urb *urb); -static int usbtty_configured (void); -static int write_buffer (circbuf_t * buf); -static int fill_buffer (circbuf_t * buf); - -void usbtty_poll (void); - -/* utility function for converting char* to wide string used by USB */ -static void str2wide (char *str, u16 * wide) -{ - int i; - for (i = 0; i < strlen (str) && str[i]; i++){ - #if defined(__LITTLE_ENDIAN) - wide[i] = (u16) str[i]; - #elif defined(__BIG_ENDIAN) - wide[i] = ((u16)(str[i])<<8); - #else - #error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined" - #endif - } -} - -/* - * Test whether a character is in the RX buffer - */ - -int usbtty_tstc(struct stdio_dev *dev) -{ - struct usb_endpoint_instance *endpoint = - &endpoint_instance[rx_endpoint]; - - /* If no input data exists, allow more RX to be accepted */ - if(usbtty_input.size <= 0){ - udc_unset_nak(endpoint->endpoint_address&0x03); - } - - usbtty_poll (); - return (usbtty_input.size > 0); -} - -/* - * Read a single byte from the usb client port. Returns 1 on success, 0 - * otherwise. When the function is succesfull, the character read is - * written into its argument c. - */ - -int usbtty_getc(struct stdio_dev *dev) -{ - char c; - struct usb_endpoint_instance *endpoint = - &endpoint_instance[rx_endpoint]; - - while (usbtty_input.size <= 0) { - udc_unset_nak(endpoint->endpoint_address&0x03); - usbtty_poll (); - } - - buf_pop (&usbtty_input, &c, 1); - udc_set_nak(endpoint->endpoint_address&0x03); - - return c; -} - -/* - * Output a single byte to the usb client port. - */ -void usbtty_putc(struct stdio_dev *dev, const char c) -{ - if (!usbtty_configured ()) - return; - - /* If \n, also do \r */ - if (c == '\n') - buf_push (&usbtty_output, "\r", 1); - - buf_push(&usbtty_output, &c, 1); - - /* Poll at end to handle new data... */ - if ((usbtty_output.size + 2) >= usbtty_output.totalsize) { - usbtty_poll (); - } -} - -/* usbtty_puts() helper function for finding the next '\n' in a string */ -static int next_nl_pos (const char *s) -{ - int i; - - for (i = 0; s[i] != '\0'; i++) { - if (s[i] == '\n') - return i; - } - return i; -} - -/* - * Output a string to the usb client port - implementing flow control - */ - -static void __usbtty_puts (const char *str, int len) -{ - int maxlen = usbtty_output.totalsize; - int space, n; - - /* break str into chunks < buffer size, if needed */ - while (len > 0) { - usbtty_poll (); - - space = maxlen - usbtty_output.size; - /* Empty buffer here, if needed, to ensure space... */ - if (space) { - write_buffer (&usbtty_output); - - n = min(space, min(len, maxlen)); - buf_push (&usbtty_output, str, n); - - str += n; - len -= n; - } - } -} - -void usbtty_puts(struct stdio_dev *dev, const char *str) -{ - int n; - int len; - - if (!usbtty_configured ()) - return; - - len = strlen (str); - /* add '\r' for each '\n' */ - while (len > 0) { - n = next_nl_pos (str); - - if (str[n] == '\n') { - __usbtty_puts(str, n); - __usbtty_puts("\r\n", 2); - str += (n + 1); - len -= (n + 1); - } else { - /* No \n found. All done. */ - __usbtty_puts (str, n); - break; - } - } - - /* Poll at end to handle new data... */ - usbtty_poll (); -} - -/* - * Initialize the usb client port. - * - */ -int drv_usbtty_init (void) -{ - int rc; - char * sn; - char * tt; - int snlen; - - /* Get serial number */ - sn = env_get("serial#"); - if (!sn) - sn = "000000000000"; - snlen = strlen(sn); - if (snlen > sizeof(serial_number) - 1) { - printf ("Warning: serial number %s is too long (%d > %lu)\n", - sn, snlen, (ulong)(sizeof(serial_number) - 1)); - snlen = sizeof(serial_number) - 1; - } - memcpy (serial_number, sn, snlen); - serial_number[snlen] = '\0'; - - /* Decide on which type of UDC device to be. - */ - tt = env_get("usbtty"); - if (!tt) - tt = "generic"; - usbtty_init_terminal_type(strcmp(tt,"cdc_acm")); - - /* prepare buffers... */ - buf_init (&usbtty_input, USBTTY_BUFFER_SIZE); - buf_init (&usbtty_output, USBTTY_BUFFER_SIZE); - - /* Now, set up USB controller and infrastructure */ - udc_init (); /* Basic USB initialization */ - - usbtty_init_strings (); - usbtty_init_instances (); - - usbtty_init_endpoints (); - - udc_startup_events (device_instance);/* Enable dev, init udc pointers */ - udc_connect (); /* Enable pullup for host detection */ - - /* Device initialization */ - memset (&usbttydev, 0, sizeof (usbttydev)); - - strcpy (usbttydev.name, "usbtty"); - usbttydev.ext = 0; /* No extensions */ - usbttydev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_OUTPUT; - usbttydev.tstc = usbtty_tstc; /* 'tstc' function */ - usbttydev.getc = usbtty_getc; /* 'getc' function */ - usbttydev.putc = usbtty_putc; /* 'putc' function */ - usbttydev.puts = usbtty_puts; /* 'puts' function */ - - rc = stdio_register (&usbttydev); - - return (rc == 0) ? 1 : rc; -} - -static void usbtty_init_strings (void) -{ - struct usb_string_descriptor *string; - - usbtty_string_table[STR_LANG] = - (struct usb_string_descriptor*)wstrLang; - - string = (struct usb_string_descriptor *) wstrManufacturer; - string->bLength = sizeof(wstrManufacturer); - string->bDescriptorType = USB_DT_STRING; - str2wide (CONFIG_USBD_MANUFACTURER, string->wData); - usbtty_string_table[STR_MANUFACTURER]=string; - - string = (struct usb_string_descriptor *) wstrProduct; - string->bLength = sizeof(wstrProduct); - string->bDescriptorType = USB_DT_STRING; - str2wide (CONFIG_USBD_PRODUCT_NAME, string->wData); - usbtty_string_table[STR_PRODUCT]=string; - - string = (struct usb_string_descriptor *) wstrSerial; - string->bLength = sizeof(serial_number); - string->bDescriptorType = USB_DT_STRING; - str2wide (serial_number, string->wData); - usbtty_string_table[STR_SERIAL]=string; - - string = (struct usb_string_descriptor *) wstrConfiguration; - string->bLength = sizeof(wstrConfiguration); - string->bDescriptorType = USB_DT_STRING; - str2wide (CFG_USBD_CONFIGURATION_STR, string->wData); - usbtty_string_table[STR_CONFIG]=string; - - string = (struct usb_string_descriptor *) wstrDataInterface; - string->bLength = sizeof(wstrDataInterface); - string->bDescriptorType = USB_DT_STRING; - str2wide (CFG_USBD_DATA_INTERFACE_STR, string->wData); - usbtty_string_table[STR_DATA_INTERFACE]=string; - - string = (struct usb_string_descriptor *) wstrCtrlInterface; - string->bLength = sizeof(wstrCtrlInterface); - string->bDescriptorType = USB_DT_STRING; - str2wide (CFG_USBD_CTRL_INTERFACE_STR, string->wData); - usbtty_string_table[STR_CTRL_INTERFACE]=string; - - /* Now, initialize the string table for ep0 handling */ - usb_strings = usbtty_string_table; -} - -#define init_wMaxPacketSize(x) le16_to_cpu(get_unaligned(\ - &ep_descriptor_ptrs[(x) - 1]->wMaxPacketSize)); - -static void usbtty_init_instances (void) -{ - int i; - - /* initialize device instance */ - memset (device_instance, 0, sizeof (struct usb_device_instance)); - device_instance->device_state = STATE_INIT; - device_instance->device_descriptor = &device_descriptor; - device_instance->event = usbtty_event_handler; - device_instance->cdc_recv_setup = usbtty_cdc_setup; - device_instance->bus = bus_instance; - device_instance->configurations = NUM_CONFIGS; - device_instance->configuration_instance_array = config_instance; - - /* initialize bus instance */ - memset (bus_instance, 0, sizeof (struct usb_bus_instance)); - bus_instance->device = device_instance; - bus_instance->endpoint_array = endpoint_instance; - bus_instance->max_endpoints = 1; - bus_instance->maxpacketsize = 64; - bus_instance->serial_number_str = serial_number; - - /* configuration instance */ - memset (config_instance, 0, - sizeof (struct usb_configuration_instance)); - config_instance->interfaces = interface_count; - config_instance->configuration_descriptor = configuration_descriptor; - config_instance->interface_instance_array = interface_instance; - - /* interface instance */ - memset (interface_instance, 0, - sizeof (struct usb_interface_instance)); - interface_instance->alternates = 1; - interface_instance->alternates_instance_array = alternate_instance; - - /* alternates instance */ - memset (alternate_instance, 0, - sizeof (struct usb_alternate_instance)); - alternate_instance->interface_descriptor = interface_descriptors; - alternate_instance->endpoints = NUM_ENDPOINTS; - alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs; - - /* endpoint instances */ - memset (&endpoint_instance[0], 0, - sizeof (struct usb_endpoint_instance)); - endpoint_instance[0].endpoint_address = 0; - endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE; - endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL; - endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE; - endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL; - udc_setup_ep (device_instance, 0, &endpoint_instance[0]); - - for (i = 1; i <= NUM_ENDPOINTS; i++) { - memset (&endpoint_instance[i], 0, - sizeof (struct usb_endpoint_instance)); - - endpoint_instance[i].endpoint_address = - ep_descriptor_ptrs[i - 1]->bEndpointAddress; - - endpoint_instance[i].rcv_attributes = - ep_descriptor_ptrs[i - 1]->bmAttributes; - - endpoint_instance[i].rcv_packetSize = init_wMaxPacketSize(i); - - endpoint_instance[i].tx_attributes = - ep_descriptor_ptrs[i - 1]->bmAttributes; - - endpoint_instance[i].tx_packetSize = init_wMaxPacketSize(i); - - endpoint_instance[i].tx_attributes = - ep_descriptor_ptrs[i - 1]->bmAttributes; - - urb_link_init (&endpoint_instance[i].rcv); - urb_link_init (&endpoint_instance[i].rdy); - urb_link_init (&endpoint_instance[i].tx); - urb_link_init (&endpoint_instance[i].done); - - if (endpoint_instance[i].endpoint_address & USB_DIR_IN) - endpoint_instance[i].tx_urb = - usbd_alloc_urb (device_instance, - &endpoint_instance[i]); - else - endpoint_instance[i].rcv_urb = - usbd_alloc_urb (device_instance, - &endpoint_instance[i]); - } -} - -static void usbtty_init_endpoints (void) -{ - int i; - - bus_instance->max_endpoints = NUM_ENDPOINTS + 1; - for (i = 1; i <= NUM_ENDPOINTS; i++) { - udc_setup_ep (device_instance, i, &endpoint_instance[i]); - } -} - -/* usbtty_init_terminal_type - * - * Do some late binding for our device type. - */ -static void usbtty_init_terminal_type(short type) -{ - switch(type){ - /* CDC ACM */ - case 0: - /* Assign endpoint descriptors */ - ep_descriptor_ptrs[0] = - &acm_configuration_descriptors[0].notification_endpoint; - ep_descriptor_ptrs[1] = - &acm_configuration_descriptors[0].data_endpoints[0]; - ep_descriptor_ptrs[2] = - &acm_configuration_descriptors[0].data_endpoints[1]; - - /* Enumerate Device Descriptor */ - device_descriptor.bDeviceClass = - COMMUNICATIONS_DEVICE_CLASS; - device_descriptor.idProduct = - cpu_to_le16(CONFIG_USBD_PRODUCTID_CDCACM); - - /* Assign endpoint indices */ - tx_endpoint = ACM_TX_ENDPOINT; - rx_endpoint = ACM_RX_ENDPOINT; - - /* Configuration Descriptor */ - configuration_descriptor = - (struct usb_configuration_descriptor*) - &acm_configuration_descriptors; - - /* Interface count */ - interface_count = NUM_ACM_INTERFACES; - break; - - /* BULK IN/OUT & Default */ - case 1: - default: - /* Assign endpoint descriptors */ - ep_descriptor_ptrs[0] = - &gserial_configuration_descriptors[0].data_endpoints[0]; - ep_descriptor_ptrs[1] = - &gserial_configuration_descriptors[0].data_endpoints[1]; - ep_descriptor_ptrs[2] = - &gserial_configuration_descriptors[0].data_endpoints[2]; - - /* Enumerate Device Descriptor */ - device_descriptor.bDeviceClass = 0xFF; - device_descriptor.idProduct = - cpu_to_le16(CONFIG_USBD_PRODUCTID_GSERIAL); - /* Assign endpoint indices */ - tx_endpoint = GSERIAL_TX_ENDPOINT; - rx_endpoint = GSERIAL_RX_ENDPOINT; - - /* Configuration Descriptor */ - configuration_descriptor = - (struct usb_configuration_descriptor*) - &gserial_configuration_descriptors; - - /* Interface count */ - interface_count = NUM_GSERIAL_INTERFACES; - break; - } -} - -/******************************************************************************/ - -static struct urb *next_urb (struct usb_device_instance *device, - struct usb_endpoint_instance *endpoint) -{ - struct urb *current_urb = NULL; - int space; - - /* If there's a queue, then we should add to the last urb */ - if (!endpoint->tx_queue) { - current_urb = endpoint->tx_urb; - } else { - /* Last urb from tx chain */ - current_urb = - p2surround (struct urb, link, endpoint->tx.prev); - } - - /* Make sure this one has enough room */ - space = current_urb->buffer_length - current_urb->actual_length; - if (space > 0) { - return current_urb; - } else { /* No space here */ - /* First look at done list */ - current_urb = first_urb_detached (&endpoint->done); - if (!current_urb) { - current_urb = usbd_alloc_urb (device, endpoint); - } - - urb_append (&endpoint->tx, current_urb); - endpoint->tx_queue++; - } - return current_urb; -} - -static int write_buffer (circbuf_t * buf) -{ - if (!usbtty_configured ()) { - return 0; - } - - struct usb_endpoint_instance *endpoint = - &endpoint_instance[tx_endpoint]; - struct urb *current_urb = NULL; - - /* TX data still exists - send it now - */ - if(endpoint->sent < endpoint->tx_urb->actual_length){ - if(udc_endpoint_write (endpoint)){ - /* Write pre-empted by RX */ - return -1; - } - } - - if (buf->size) { - char *dest; - - int space_avail; - int popnum, popped; - int total = 0; - - /* Break buffer into urb sized pieces, - * and link each to the endpoint - */ - while (buf->size > 0) { - - current_urb = next_urb (device_instance, endpoint); - - dest = (char*)current_urb->buffer + - current_urb->actual_length; - - space_avail = - current_urb->buffer_length - - current_urb->actual_length; - popnum = min(space_avail, (int)buf->size); - if (popnum == 0) - break; - - popped = buf_pop (buf, dest, popnum); - if (popped == 0) - break; - current_urb->actual_length += popped; - total += popped; - - /* If endpoint->last == 0, then transfers have - * not started on this endpoint - */ - if (endpoint->last == 0) { - if(udc_endpoint_write (endpoint)){ - /* Write pre-empted by RX */ - return -1; - } - } - - }/* end while */ - return total; - } - - return 0; -} - -static int fill_buffer (circbuf_t * buf) -{ - struct usb_endpoint_instance *endpoint = - &endpoint_instance[rx_endpoint]; - - if (endpoint->rcv_urb && endpoint->rcv_urb->actual_length) { - unsigned int nb = 0; - char *src = (char *) endpoint->rcv_urb->buffer; - unsigned int rx_avail = buf->totalsize - buf->size; - - if(rx_avail >= endpoint->rcv_urb->actual_length){ - - nb = endpoint->rcv_urb->actual_length; - buf_push (buf, src, nb); - endpoint->rcv_urb->actual_length = 0; - - } - return nb; - } - return 0; -} - -static int usbtty_configured (void) -{ - return usbtty_configured_flag; -} - -/******************************************************************************/ - -static void usbtty_event_handler (struct usb_device_instance *device, - usb_device_event_t event, int data) -{ - switch (event) { - case DEVICE_RESET: - case DEVICE_BUS_INACTIVE: - usbtty_configured_flag = 0; - break; - case DEVICE_CONFIGURED: - usbtty_configured_flag = 1; - break; - - case DEVICE_ADDRESS_ASSIGNED: - usbtty_init_endpoints (); - - default: - break; - } -} - -/******************************************************************************/ - -int usbtty_cdc_setup(struct usb_device_request *request, struct urb *urb) -{ - switch (request->bRequest){ - - case ACM_SET_CONTROL_LINE_STATE: /* Implies DTE ready */ - break; - case ACM_SEND_ENCAPSULATED_COMMAND : /* Required */ - break; - case ACM_SET_LINE_ENCODING : /* DTE stop/parity bits - * per character */ - break; - case ACM_GET_ENCAPSULATED_RESPONSE : /* request response */ - break; - case ACM_GET_LINE_ENCODING : /* request DTE rate, - * stop/parity bits */ - memcpy (urb->buffer , &rs232_desc, sizeof(rs232_desc)); - urb->actual_length = sizeof(rs232_desc); - - break; - default: - return 1; - } - return 0; -} - -/******************************************************************************/ - -/* - * Since interrupt handling has not yet been implemented, we use this function - * to handle polling. This is called by the tstc,getc,putc,puts routines to - * update the USB state. - */ -void usbtty_poll (void) -{ - /* New interrupts? */ - udc_irq(); - - /* Write any output data to host buffer - * (do this before checking interrupts to avoid missing one) - */ - if (usbtty_configured ()) { - write_buffer (&usbtty_output); - } - - /* New interrupts? */ - udc_irq(); - - /* Check for new data from host.. - * (do this after checking interrupts to get latest data) - */ - if (usbtty_configured ()) { - fill_buffer (&usbtty_input); - } - - /* New interrupts? */ - udc_irq(); - -} diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h deleted file mode 100644 index b176a7961b8..00000000000 --- a/drivers/serial/usbtty.h +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ */ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * (C) Copyright 2006 - * Bryan O'Donoghue, bodonoghue@codehermit.ie, CodeHermit - */ - -#ifndef __USB_TTY_H__ -#define __USB_TTY_H__ - -#include <usbdevice.h> -#if defined(CONFIG_PPC) -#include <usb/mpc8xx_udc.h> -#elif defined(CONFIG_CI_UDC) -#include <usb/ci_udc.h> -#endif - -#include <usb/udc.h> -#include <version.h> - -#ifndef CFG_USBD_CONFIGURATION_STR -#define CFG_USBD_CONFIGURATION_STR "TTY via USB" -#endif - -#define CFG_USBD_SERIAL_OUT_ENDPOINT UDC_OUT_ENDPOINT -#define CFG_USBD_SERIAL_OUT_PKTSIZE UDC_OUT_PACKET_SIZE -#define CFG_USBD_SERIAL_IN_ENDPOINT UDC_IN_ENDPOINT -#define CFG_USBD_SERIAL_IN_PKTSIZE UDC_IN_PACKET_SIZE -#define CFG_USBD_SERIAL_INT_ENDPOINT UDC_INT_ENDPOINT -#define CFG_USBD_SERIAL_INT_PKTSIZE UDC_INT_PACKET_SIZE -#define CFG_USBD_SERIAL_BULK_PKTSIZE UDC_BULK_PACKET_SIZE - -#define USBTTY_DEVICE_CLASS COMMUNICATIONS_DEVICE_CLASS - -#define USBTTY_BCD_DEVICE 0x00 -#define USBTTY_MAXPOWER 0x00 - -#define STR_LANG 0x00 -#define STR_MANUFACTURER 0x01 -#define STR_PRODUCT 0x02 -#define STR_SERIAL 0x03 -#define STR_CONFIG 0x04 -#define STR_DATA_INTERFACE 0x05 -#define STR_CTRL_INTERFACE 0x06 -#define STR_COUNT 0x07 - -#endif diff --git a/drivers/soc/soc_amd_versal2.c b/drivers/soc/soc_amd_versal2.c index 66bcb22b4fa..8507da0bd22 100644 --- a/drivers/soc/soc_amd_versal2.c +++ b/drivers/soc/soc_amd_versal2.c @@ -35,7 +35,9 @@ static int soc_amd_versal2_get_revision(struct udevice *dev, char *buf, int size { struct soc_amd_versal2_priv *priv = dev_get_priv(dev); - return snprintf(buf, size, "v%d", priv->revision); + return snprintf(buf, size, "v%d.%d", + (u32)FIELD_GET(PS_VERSION_MAJOR, priv->revision), + (u32)FIELD_GET(PS_VERSION_MINOR, priv->revision)); } static const struct soc_ops soc_amd_versal2_ops = { diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index a916b711ba8..f475f341c9c 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -52,6 +52,13 @@ config SPI_DIRMAP if DM_SPI +config ADI_SPI3 + bool "Enable ADI SPI Driver" + depends on ARCH_SC5XX + help + Enable the ADI (Analog Devices) SPI controller driver. This + driver enables the support for SC5XX spi controller. + config ALTERA_SPI bool "Altera SPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 7051e2a00c6..21895d46429 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -19,6 +19,7 @@ obj-y += spi.o obj-$(CONFIG_SPI_MEM) += spi-mem-nodm.o endif +obj-$(CONFIG_ADI_SPI3) += adi_spi3.o obj-$(CONFIG_ALTERA_SPI) += altera_spi.o obj-$(CONFIG_APPLE_SPI) += apple_spi.o obj-$(CONFIG_ATH79_SPI) += ath79_spi.o diff --git a/drivers/spi/adi_spi3.c b/drivers/spi/adi_spi3.c new file mode 100644 index 00000000000..2125d25561a --- /dev/null +++ b/drivers/spi/adi_spi3.c @@ -0,0 +1,679 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Converted to driver model by Nathan Barrett-Morrison + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * Contact: Ian Roberts <ian.roberts@timesys.com> + * Contact: Piotr Wojtaszczyk <piotr.wojtaszczyk@timesys.com> + * + */ + +#include <clk.h> +#include <dm.h> +#include <mapmem.h> +#include <spi.h> +#include <spi-mem.h> +#include <dm/device_compat.h> +#include <linux/io.h> + +#define SPI_IDLE_VAL 0xff + +#define MAX_CTRL_CS 7 + +/* SPI_CONTROL */ +#define SPI_CTL_EN 0x00000001 /* Enable */ +#define SPI_CTL_MSTR 0x00000002 /* Master/Slave */ +#define SPI_CTL_PSSE 0x00000004 /* controls modf error in master mode */ +#define SPI_CTL_ODM 0x00000008 /* Open Drain Mode */ +#define SPI_CTL_CPHA 0x00000010 /* Clock Phase */ +#define SPI_CTL_CPOL 0x00000020 /* Clock Polarity */ +#define SPI_CTL_ASSEL 0x00000040 /* Slave Select Pin Control */ +#define SPI_CTL_SELST 0x00000080 /* Slave Select Polarity in transfers */ +#define SPI_CTL_EMISO 0x00000100 /*Enable MISO */ +#define SPI_CTL_SIZE 0x00000600 /*Word Transfer Size */ +#define SPI_CTL_SIZE08 0x00000000 /*SIZE: 8 bits */ +#define SPI_CTL_SIZE16 0x00000200 /*SIZE: 16 bits */ +#define SPI_CTL_SIZE32 0x00000400 /*SIZE: 32 bits */ +#define SPI_CTL_LSBF 0x00001000 /*LSB First */ +#define SPI_CTL_FCEN 0x00002000 /*Flow-Control Enable */ +#define SPI_CTL_FCCH 0x00004000 /*Flow-Control Channel Selection */ +#define SPI_CTL_FCPL 0x00008000 /*Flow-Control Polarity */ +#define SPI_CTL_FCWM 0x00030000 /*Flow-Control Water-Mark */ +#define SPI_CTL_FIFO0 0x00000000 /*FCWM: Tx empty or Rx Full */ +#define SPI_CTL_FIFO1 0x00010000 /*FCWM: Tx empty or Rx full (>=75%) */ +#define SPI_CTL_FIFO2 0x00020000 /*FCWM: Tx empty or Rx full (>=50%) */ +#define SPI_CTL_FMODE 0x00040000 /*Fast-mode Enable */ +#define SPI_CTL_MIOM 0x00300000 /*Multiple I/O Mode */ +#define SPI_CTL_MIO_DIS 0x00000000 /*MIOM: Disable */ +#define SPI_CTL_MIO_DUAL 0x00100000 /*MIOM: Enable DIOM (Dual I/O Mode) */ +#define SPI_CTL_MIO_QUAD 0x00200000 /*MIOM: Enable QUAD (Quad SPI Mode) */ +#define SPI_CTL_SOSI 0x00400000 /*Start on MOSI */ +#define SPI_CTL_MMWEM 0x40000000 /*Start on MMWEM */ +#define SPI_CTL_MMSE 0x80000000 /*Start on MMSE */ +/* SPI_RX_CONTROL */ +#define SPI_RXCTL_REN 0x00000001 /*Receive Channel Enable */ +#define SPI_RXCTL_RTI 0x00000004 /*Receive Transfer Initiate */ +#define SPI_RXCTL_RWCEN 0x00000008 /*Receive Word Counter Enable */ +#define SPI_RXCTL_RDR 0x00000070 /*Receive Data Request */ +#define SPI_RXCTL_RDR_DIS 0x00000000 /*RDR: Disabled */ +#define SPI_RXCTL_RDR_NE 0x00000010 /*RDR: RFIFO not empty */ +#define SPI_RXCTL_RDR_25 0x00000020 /*RDR: RFIFO 25% full */ +#define SPI_RXCTL_RDR_50 0x00000030 /*RDR: RFIFO 50% full */ +#define SPI_RXCTL_RDR_75 0x00000040 /*RDR: RFIFO 75% full */ +#define SPI_RXCTL_RDR_FULL 0x00000050 /*RDR: RFIFO full */ +#define SPI_RXCTL_RDO 0x00000100 /*Receive Data Over-Run */ +#define SPI_RXCTL_RRWM 0x00003000 /*FIFO Regular Water-Mark */ +#define SPI_RXCTL_RWM_0 0x00000000 /*RRWM: RFIFO Empty */ +#define SPI_RXCTL_RWM_25 0x00001000 /*RRWM: RFIFO 25% full */ +#define SPI_RXCTL_RWM_50 0x00002000 /*RRWM: RFIFO 50% full */ +#define SPI_RXCTL_RWM_75 0x00003000 /*RRWM: RFIFO 75% full */ +#define SPI_RXCTL_RUWM 0x00070000 /*FIFO Urgent Water-Mark */ +#define SPI_RXCTL_UWM_DIS 0x00000000 /*RUWM: Disabled */ +#define SPI_RXCTL_UWM_25 0x00010000 /*RUWM: RFIFO 25% full */ +#define SPI_RXCTL_UWM_50 0x00020000 /*RUWM: RFIFO 50% full */ +#define SPI_RXCTL_UWM_75 0x00030000 /*RUWM: RFIFO 75% full */ +#define SPI_RXCTL_UWM_FULL 0x00040000 /*RUWM: RFIFO full */ +/* SPI_TX_CONTROL */ +#define SPI_TXCTL_TEN 0x00000001 /*Transmit Channel Enable */ +#define SPI_TXCTL_TTI 0x00000004 /*Transmit Transfer Initiate */ +#define SPI_TXCTL_TWCEN 0x00000008 /*Transmit Word Counter Enable */ +#define SPI_TXCTL_TDR 0x00000070 /*Transmit Data Request */ +#define SPI_TXCTL_TDR_DIS 0x00000000 /*TDR: Disabled */ +#define SPI_TXCTL_TDR_NF 0x00000010 /*TDR: TFIFO not full */ +#define SPI_TXCTL_TDR_25 0x00000020 /*TDR: TFIFO 25% empty */ +#define SPI_TXCTL_TDR_50 0x00000030 /*TDR: TFIFO 50% empty */ +#define SPI_TXCTL_TDR_75 0x00000040 /*TDR: TFIFO 75% empty */ +#define SPI_TXCTL_TDR_EMPTY 0x00000050 /*TDR: TFIFO empty */ +#define SPI_TXCTL_TDU 0x00000100 /*Transmit Data Under-Run */ +#define SPI_TXCTL_TRWM 0x00003000 /*FIFO Regular Water-Mark */ +#define SPI_TXCTL_RWM_FULL 0x00000000 /*TRWM: TFIFO full */ +#define SPI_TXCTL_RWM_25 0x00001000 /*TRWM: TFIFO 25% empty */ +#define SPI_TXCTL_RWM_50 0x00002000 /*TRWM: TFIFO 50% empty */ +#define SPI_TXCTL_RWM_75 0x00003000 /*TRWM: TFIFO 75% empty */ +#define SPI_TXCTL_TUWM 0x00070000 /*FIFO Urgent Water-Mark */ +#define SPI_TXCTL_UWM_DIS 0x00000000 /*TUWM: Disabled */ +#define SPI_TXCTL_UWM_25 0x00010000 /*TUWM: TFIFO 25% empty */ +#define SPI_TXCTL_UWM_50 0x00020000 /*TUWM: TFIFO 50% empty */ +#define SPI_TXCTL_UWM_75 0x00030000 /*TUWM: TFIFO 75% empty */ +#define SPI_TXCTL_UWM_EMPTY 0x00040000 /*TUWM: TFIFO empty */ +/* SPI_CLOCK */ +#define SPI_CLK_BAUD 0x0000FFFF /*Baud Rate */ +/* SPI_DELAY */ +#define SPI_DLY_STOP 0x000000FF /*Transfer delay time */ +#define SPI_DLY_LEADX 0x00000100 /*Extended (1 SCK) LEAD Control */ +#define SPI_DLY_LAGX 0x00000200 /*Extended (1 SCK) LAG control */ +/* SPI_SSEL */ +#define SPI_SLVSEL_SSE1 0x00000002 /*SPISSEL1 Enable */ +#define SPI_SLVSEL_SSE2 0x00000004 /*SPISSEL2 Enable */ +#define SPI_SLVSEL_SSE3 0x00000008 /*SPISSEL3 Enable */ +#define SPI_SLVSEL_SSE4 0x00000010 /*SPISSEL4 Enable */ +#define SPI_SLVSEL_SSE5 0x00000020 /*SPISSEL5 Enable */ +#define SPI_SLVSEL_SSE6 0x00000040 /*SPISSEL6 Enable */ +#define SPI_SLVSEL_SSE7 0x00000080 /*SPISSEL7 Enable */ +#define SPI_SLVSEL_SSEL1 0x00000200 /*SPISSEL1 Value */ +#define SPI_SLVSEL_SSEL2 0x00000400 /*SPISSEL2 Value */ +#define SPI_SLVSEL_SSEL3 0x00000800 /*SPISSEL3 Value */ +#define SPI_SLVSEL_SSEL4 0x00001000 /*SPISSEL4 Value */ +#define SPI_SLVSEL_SSEL5 0x00002000 /*SPISSEL5 Value */ +#define SPI_SLVSEL_SSEL6 0x00004000 /*SPISSEL6 Value */ +#define SPI_SLVSEL_SSEL7 0x00008000 /*SPISSEL7 Value */ +/* SPI_RWC */ +#define SPI_RWC_VALUE 0x0000FFFF /*Received Word-Count */ +/* SPI_RWCR */ +#define SPI_RWCR_VALUE 0x0000FFFF /*Received Word-Count Reload */ +/* SPI_TWC */ +#define SPI_TWC_VALUE 0x0000FFFF /*Transmitted Word-Count */ +/* SPI_TWCR */ +#define SPI_TWCR_VALUE 0x0000FFFF /*Transmitted Word-Count Reload */ +/* SPI_IMASK */ +#define SPI_IMSK_RUWM 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_IMASKCL */ +#define SPI_IMSK_CLR_RUW 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_CLR_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_CLR_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_CLR_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_CLR_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_CLR_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_CLR_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_CLR_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_CLR_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_CLR_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_IMASKST */ +#define SPI_IMSK_SET_RUWM 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_SET_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_SET_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_SET_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_SET_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_SET_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_SET_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_SET_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_SET_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_SET_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_STATUS */ +#define SPI_STAT_SPIF 0x00000001 /*SPI Finished */ +#define SPI_STAT_RUWM 0x00000002 /*Receive Water-Mark Breached */ +#define SPI_STAT_TUWM 0x00000004 /*Transmit Water-Mark Breached */ +#define SPI_STAT_ROE 0x00000010 /*Receive Over-Run Indication */ +#define SPI_STAT_TUE 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_STAT_TCE 0x00000040 /*Transmit Collision Indication */ +#define SPI_STAT_MODF 0x00000080 /*Mode Fault Indication */ +#define SPI_STAT_RS 0x00000100 /*Receive Start Indication */ +#define SPI_STAT_TS 0x00000200 /*Transmit Start Indication */ +#define SPI_STAT_RF 0x00000400 /*Receive Finish Indication */ +#define SPI_STAT_TF 0x00000800 /*Transmit Finish Indication */ +#define SPI_STAT_RFS 0x00007000 /*SPI_RFIFO status */ +#define SPI_STAT_RFIFO_EMPTY 0x00000000 /*RFS: RFIFO Empty */ +#define SPI_STAT_RFIFO_25 0x00001000 /*RFS: RFIFO 25% Full */ +#define SPI_STAT_RFIFO_50 0x00002000 /*RFS: RFIFO 50% Full */ +#define SPI_STAT_RFIFO_75 0x00003000 /*RFS: RFIFO 75% Full */ +#define SPI_STAT_RFIFO_FULL 0x00004000 /*RFS: RFIFO Full */ +#define SPI_STAT_TFS 0x00070000 /*SPI_TFIFO status */ +#define SPI_STAT_TFIFO_FULL 0x00000000 /*TFS: TFIFO full */ +#define SPI_STAT_TFIFO_25 0x00010000 /*TFS: TFIFO 25% empty */ +#define SPI_STAT_TFIFO_50 0x00020000 /*TFS: TFIFO 50% empty */ +#define SPI_STAT_TFIFO_75 0x00030000 /*TFS: TFIFO 75% empty */ +#define SPI_STAT_TFIFO_EMPTY 0x00040000 /*TFS: TFIFO empty */ +#define SPI_STAT_FCS 0x00100000 /*Flow-Control Stall Indication */ +#define SPI_STAT_RFE 0x00400000 /*SPI_RFIFO Empty */ +#define SPI_STAT_TFF 0x00800000 /*SPI_TFIFO Full */ +/* SPI_ILAT */ +#define SPI_ILAT_RUWMI 0x00000002 /*Receive Water Mark Interrupt */ +#define SPI_ILAT_TUWMI 0x00000004 /*Transmit Water Mark Interrupt */ +#define SPI_ILAT_ROI 0x00000010 /*Receive Over-Run Indication */ +#define SPI_ILAT_TUI 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_ILAT_TCI 0x00000040 /*Transmit Collision Indication */ +#define SPI_ILAT_MFI 0x00000080 /*Mode Fault Indication */ +#define SPI_ILAT_RSI 0x00000100 /*Receive Start Indication */ +#define SPI_ILAT_TSI 0x00000200 /*Transmit Start Indication */ +#define SPI_ILAT_RFI 0x00000400 /*Receive Finish Indication */ +#define SPI_ILAT_TFI 0x00000800 /*Transmit Finish Indication */ +/* SPI_ILATCL */ +#define SPI_ILAT_CLR_RUWMI 0x00000002 /*Receive Water Mark Interrupt */ +#define SPI_ILAT_CLR_TUWMI 0x00000004 /*Transmit Water Mark Interrupt */ +#define SPI_ILAT_CLR_ROI 0x00000010 /*Receive Over-Run Indication */ +#define SPI_ILAT_CLR_TUI 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_ILAT_CLR_TCI 0x00000040 /*Transmit Collision Indication */ +#define SPI_ILAT_CLR_MFI 0x00000080 /*Mode Fault Indication */ +#define SPI_ILAT_CLR_RSI 0x00000100 /*Receive Start Indication */ +#define SPI_ILAT_CLR_TSI 0x00000200 /*Transmit Start Indication */ +#define SPI_ILAT_CLR_RFI 0x00000400 /*Receive Finish Indication */ +#define SPI_ILAT_CLR_TFI 0x00000800 /*Transmit Finish Indication */ +/* SPI_MMRDH */ +#define SPI_MMRDH_MERGE 0x04000000 /*Merge Enable */ +#define SPI_MMRDH_DMY_SZ 0x00007000 /*Bytes of Dummy */ +#define SPI_MMRDH_ADDR_PINS 0x00000800 /*Pins used for Address */ +#define SPI_MMRDH_ADDR_SZ 0x00000700 /*Bytes of Read Address */ +#define SPI_MMRDH_OPCODE 0x000000FF /*Read Opcode */ + +#define SPI_MMRDH_TRIDMY_OFF 24 /*Bytes of Dummy offset */ +#define SPI_MMRDH_DMY_SZ_OFF 12 /*Bytes of Dummy offset */ +#define SPI_MMRDH_ADDR_SZ_OFF 8 /*Bytes of Read Address offset */ + +#define BIT_SSEL_VAL(x) ((1 << 8) << (x)) /* Slave Select input value bit */ +#define BIT_SSEL_EN(x) (1 << (x)) /* Slave Select enable bit*/ + +struct adi_spi_regs { + u32 revid; + u32 control; + u32 rx_control; + u32 tx_control; + u32 clock; + u32 delay; + u32 ssel; + u32 rwc; + u32 rwcr; + u32 twc; + u32 twcr; + u32 reserved0; + u32 emask; + u32 emaskcl; + u32 emaskst; + u32 reserved1; + u32 status; + u32 elat; + u32 elatcl; + u32 reserved2; + u32 rfifo; + u32 reserved3; + u32 tfifo; + u32 reserved4; + u32 mmrdh; + u32 mmtop; +}; + +struct adi_spi_platdata { + u32 max_hz; + u32 bus_num; + struct adi_spi_regs __iomem *regs; +}; + +struct adi_spi_priv { + u32 control; + u32 clock; + u32 bus_num; + u32 max_cs; + struct adi_spi_regs __iomem *regs; +}; + +/** + * By convention, this driver uses the same CS numbering that is used with the SSEL bit + * definitions (both here and in the TRM on which this is based), which are 1-indexed not + * 0-indexed. The valid CS range is therefore [1,max_cs], in contrast with other drivers + * where it is [0,max_cs-1]. + */ +static int adi_spi_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + struct adi_spi_priv *priv = dev_get_priv(bus); + + if (cs == 0 || cs > priv->max_cs) { + dev_err(bus, "invalid chipselect %u\n", cs); + return -EINVAL; + } + + return 0; +} + +static int adi_spi_of_to_plat(struct udevice *bus) +{ + struct adi_spi_platdata *plat = dev_get_plat(bus); + fdt_addr_t addr; + + plat->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 500000); + plat->bus_num = dev_read_u32_default(bus, "bus-num", 0); + addr = dev_read_addr(bus); + + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->regs = map_sysmem(addr, sizeof(*plat->regs)); + + return 0; +} + +static int adi_spi_probe(struct udevice *bus) +{ + struct adi_spi_platdata *plat = dev_get_plat(bus); + struct adi_spi_priv *priv = dev_get_priv(bus); + + priv->bus_num = plat->bus_num; + priv->regs = plat->regs; + priv->max_cs = dev_read_u32_default(bus, "num-cs", MAX_CTRL_CS); + + iowrite32(0x0, &plat->regs->control); + iowrite32(0x0, &plat->regs->rx_control); + iowrite32(0x0, &plat->regs->tx_control); + + return 0; +} + +static int adi_spi_remove(struct udevice *dev) +{ + return -ENODEV; +} + +static int adi_spi_claim_bus(struct udevice *dev) +{ + struct adi_spi_priv *priv; + struct udevice *bus = dev->parent; + + priv = dev_get_priv(bus); + + debug("%s: control:%i clock:%i\n", + __func__, priv->control, priv->clock); + + iowrite32(priv->control, &priv->regs->control); + iowrite32(priv->clock, &priv->regs->clock); + iowrite32(0x0, &priv->regs->delay); + + return 0; +} + +static int adi_spi_release_bus(struct udevice *dev) +{ + struct adi_spi_priv *priv; + struct udevice *bus = dev->parent; + + priv = dev_get_priv(bus); + + debug("%s: control:%i clock:%i\n", + __func__, priv->control, priv->clock); + + iowrite32(0x0, &priv->regs->rx_control); + iowrite32(0x0, &priv->regs->tx_control); + iowrite32(0x0, &priv->regs->control); + + return 0; +} + +void adi_spi_enable_ssel(struct adi_spi_priv *priv, int cs) +{ + setbits_32(&priv->regs->ssel, BIT_SSEL_EN(cs)); +} + +void adi_spi_set_ssel(struct adi_spi_priv *priv, int cs, int high) +{ + if (high) + setbits_32(&priv->regs->ssel, BIT_SSEL_VAL(cs)); + else + clrbits_32(&priv->regs->ssel, BIT_SSEL_VAL(cs)); +} + +void adi_spi_cs_activate(struct adi_spi_priv *priv, struct dm_spi_slave_plat *slave_plat) +{ + bool high = slave_plat->mode & SPI_CS_HIGH; + + adi_spi_set_ssel(priv, slave_plat->cs[0], high); + adi_spi_enable_ssel(priv, slave_plat->cs[0]); +} + +void adi_spi_cs_deactivate(struct adi_spi_priv *priv, struct dm_spi_slave_plat *slave_plat) +{ + bool high = slave_plat->mode & SPI_CS_HIGH; + + /* invert CS for matching SSEL to deactivate */ + adi_spi_set_ssel(priv, slave_plat->cs[0], !high); +} + +static void discard_rx_fifo_contents(struct adi_spi_regs *regs) +{ + while (!(ioread32(®s->status) & SPI_STAT_RFE)) + ioread32(®s->rfifo); +} + +static int adi_spi_fifo_mio_xfer(struct adi_spi_priv *priv, const u8 *tx, u8 *rx, + uint bytes, uint32_t mio_mode) +{ + u8 value; + + /* switch current SPI transfer to mio SPI mode */ + clrsetbits_32(&priv->regs->control, SPI_CTL_SOSI, mio_mode); + /* + * Data can only be transferred in one direction in multi-io SPI + * modes, trigger the transfer in respective direction. + */ + if (rx) { + iowrite32(0x0, &priv->regs->tx_control); + iowrite32(SPI_RXCTL_REN | SPI_RXCTL_RTI, &priv->regs->rx_control); + + while (bytes--) { + while (ioread32(&priv->regs->status) & + SPI_STAT_RFE) + if (ctrlc()) + return -1; + value = ioread32(&priv->regs->rfifo); + *rx++ = value; + } + } else if (tx) { + iowrite32(0x0, &priv->regs->rx_control); + iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI, &priv->regs->tx_control); + + while (bytes--) { + value = *tx++; + iowrite32(value, &priv->regs->tfifo); + while (ioread32(&priv->regs->status) & + SPI_STAT_TFF) + if (ctrlc()) + return -1; + } + + /* Wait till the tfifo is empty */ + while ((ioread32(&priv->regs->status) & SPI_STAT_TFS) != SPI_STAT_TFIFO_EMPTY) + if (ctrlc()) + return -1; + } else { + return -1; + } + return 0; +} + +static int adi_spi_fifo_1x_xfer(struct adi_spi_priv *priv, const u8 *tx, u8 *rx, + uint bytes) +{ + u8 value; + + /* + * Set current SPI transfer in normal mode and trigger + * the bi-direction transfer by tx write operation. + */ + iowrite32(priv->control, &priv->regs->control); + iowrite32(SPI_RXCTL_REN, &priv->regs->rx_control); + iowrite32(SPI_TXCTL_TEN | SPI_TXCTL_TTI, &priv->regs->tx_control); + + while (bytes--) { + value = (tx ? *tx++ : SPI_IDLE_VAL); + debug("%s: tx:%x ", __func__, value); + iowrite32(value, &priv->regs->tfifo); + while (ioread32(&priv->regs->status) & SPI_STAT_RFE) + if (ctrlc()) + return -1; + value = ioread32(&priv->regs->rfifo); + if (rx) + *rx++ = value; + debug("rx:%x\n", value); + } + return 0; +} + +static int adi_spi_fifo_xfer(struct adi_spi_priv *priv, int buswidth, + const u8 *tx, u8 *rx, uint bytes) +{ + switch (buswidth) { + case 1: + return adi_spi_fifo_1x_xfer(priv, tx, rx, bytes); + case 2: + return adi_spi_fifo_mio_xfer(priv, tx, rx, bytes, SPI_CTL_MIO_DUAL); + case 4: + return adi_spi_fifo_mio_xfer(priv, tx, rx, bytes, SPI_CTL_MIO_QUAD); + default: + return -ENOTSUPP; + } +} + +static int adi_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = dev->parent; + struct adi_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); + + const u8 *tx = dout; + u8 *rx = din; + uint bytes = bitlen / 8; + int ret = 0; + + debug("%s: bus_num:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__, + priv->bus_num, slave_plat->cs[0], bitlen, bytes, flags); + + if (flags & SPI_XFER_BEGIN) + adi_spi_cs_activate(priv, slave_plat); + + if (bitlen == 0) + goto done; + + /* we can only do 8 bit transfers */ + if (bitlen % 8) { + flags |= SPI_XFER_END; + goto done; + } + + /* Discard invalid rx data and empty rfifo */ + discard_rx_fifo_contents(priv->regs); + + ret = adi_spi_fifo_1x_xfer(priv, tx, rx, bytes); + + done: + if (flags & SPI_XFER_END) + adi_spi_cs_deactivate(priv, slave_plat); + + return ret; +} + +static int adi_spi_set_speed(struct udevice *bus, uint speed) +{ + struct adi_spi_platdata *plat = dev_get_plat(bus); + struct adi_spi_priv *priv = dev_get_priv(bus); + int ret; + u32 clock, spi_base_clk; + struct clk spi_clk; + + ret = clk_get_by_name(bus, "spi", &spi_clk); + if (ret < 0) { + dev_err(bus, "Can't get SPI clk: %d\n", ret); + return ret; + } + spi_base_clk = clk_get_rate(&spi_clk); + + if (speed > plat->max_hz) + speed = plat->max_hz; + + if (speed > spi_base_clk) + return -ENODEV; + + clock = spi_base_clk / speed; + if (clock) + clock--; + + priv->clock = clock; + + debug("%s: priv->clock: %x, speed: %x, get_spi_clk(): %x\n", + __func__, clock, speed, spi_base_clk); + + return 0; +} + +static int adi_spi_set_mode(struct udevice *bus, uint mode) +{ + struct adi_spi_priv *priv = dev_get_priv(bus); + u32 reg; + + reg = SPI_CTL_EN | SPI_CTL_MSTR; + if (mode & SPI_CPHA) + reg |= SPI_CTL_CPHA; + if (mode & SPI_CPOL) + reg |= SPI_CTL_CPOL; + if (mode & SPI_LSB_FIRST) + reg |= SPI_CTL_LSBF; + reg &= ~SPI_CTL_ASSEL; + + priv->control = reg; + + debug("%s: control=%d, cs_pol=%d\n", __func__, reg, mode & SPI_CS_HIGH ? 1 : 0); + + return 0; +} + +/** + * U-boot's version of spi-mem does not support mixed bus-width + * commands nor anything more than 1x mode. + * Using a custom exec_op implementation, we can support it. + */ +static int adi_spi_mem_exec_op(struct spi_slave *slave, + const struct spi_mem_op *op) +{ + int rv = 0; + struct udevice *bus = slave->dev->parent; + struct adi_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(slave->dev); + u8 tmpbuf[64]; + int i; + + if ((op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes) > + sizeof(tmpbuf)) + return -ENOMEM; + + for (i = 0; i < op->cmd.nbytes; i++) + tmpbuf[i] = op->cmd.opcode >> + (8 * (op->cmd.nbytes - i - 1)); + for (i = 0; i < op->addr.nbytes; i++) + tmpbuf[i + op->cmd.nbytes] = op->addr.val >> + (8 * (op->addr.nbytes - i - 1)); + memset(tmpbuf + op->addr.nbytes + op->cmd.nbytes, 0xff, + op->dummy.nbytes); + + adi_spi_cs_activate(priv, slave_plat); + discard_rx_fifo_contents(priv->regs); + + if (op->cmd.nbytes) { + rv = adi_spi_fifo_xfer(priv, op->cmd.buswidth, + tmpbuf, NULL, op->cmd.nbytes); + if (rv != 0) + goto cleanup; + } + + if (op->addr.nbytes) { + rv = adi_spi_fifo_xfer(priv, op->addr.buswidth, + tmpbuf + op->cmd.nbytes, NULL, + op->addr.nbytes); + if (rv != 0) + goto cleanup; + } + + if (op->dummy.nbytes) { + rv = adi_spi_fifo_xfer(priv, op->dummy.buswidth, + tmpbuf + op->cmd.nbytes + + op->addr.nbytes, + NULL, op->dummy.nbytes); + if (rv != 0) + goto cleanup; + } + + if (op->data.dir == SPI_MEM_DATA_IN) + rv = adi_spi_fifo_xfer(priv, op->data.buswidth, + NULL, op->data.buf.in, + op->data.nbytes); + else if (op->data.dir == SPI_MEM_DATA_OUT) + rv = adi_spi_fifo_xfer(priv, op->data.buswidth, + op->data.buf.out, NULL, + op->data.nbytes); + +cleanup: + adi_spi_cs_deactivate(priv, slave_plat); + return rv; +} + +static const struct spi_controller_mem_ops adi_spi_mem_ops = { + .exec_op = adi_spi_mem_exec_op, +}; + +static const struct dm_spi_ops adi_spi_ops = { + .claim_bus = adi_spi_claim_bus, + .release_bus = adi_spi_release_bus, + .xfer = adi_spi_xfer, + .set_speed = adi_spi_set_speed, + .set_mode = adi_spi_set_mode, + .cs_info = adi_spi_cs_info, + .mem_ops = &adi_spi_mem_ops, +}; + +static const struct udevice_id adi_spi_ids[] = { + { .compatible = "adi,spi3" }, + { } +}; + +U_BOOT_DRIVER(adi_spi3) = { + .name = "adi_spi3", + .id = UCLASS_SPI, + .of_match = adi_spi_ids, + .ops = &adi_spi_ops, + .of_to_plat = adi_spi_of_to_plat, + .probe = adi_spi_probe, + .remove = adi_spi_remove, + .plat_auto = sizeof(struct adi_spi_platdata), + .priv_auto = sizeof(struct adi_spi_priv), + .per_child_auto = sizeof(struct spi_slave), +}; diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 4bda224ff1a..db5f8895a33 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -35,7 +35,3 @@ endif endif obj-$(CONFIG_CI_UDC) += ci_udc.o - -# Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE -# This is really only N900 and USBTTY now. -obj-$(CONFIG_USB_DEVICE) += core.o ep0.o diff --git a/drivers/usb/gadget/core.c b/drivers/usb/gadget/core.c deleted file mode 100644 index bcb1ad3082c..00000000000 --- a/drivers/usb/gadget/core.c +++ /dev/null @@ -1,621 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * Based on - * linux/drivers/usbd/usbd.c.c - USB Device Core Layer - * - * Copyright (c) 2000, 2001, 2002 Lineo - * Copyright (c) 2001 Hewlett Packard - * - * By: - * Stuart Lynne <sl@lineo.com>, - * Tom Rushworth <tbr@lineo.com>, - * Bruce Balden <balden@lineo.com> - */ - -#include <log.h> -#include <malloc.h> -#include <serial.h> -#include <usbdevice.h> - -#define MAX_INTERFACES 2 - -int maxstrings = 20; - -/* Global variables ************************************************************************** */ - -struct usb_string_descriptor **usb_strings; - -int usb_devices; - -extern struct usb_function_driver ep0_driver; - -int registered_functions; -int registered_devices; - -__maybe_unused static char *usbd_device_events[] = { - "DEVICE_UNKNOWN", - "DEVICE_INIT", - "DEVICE_CREATE", - "DEVICE_HUB_CONFIGURED", - "DEVICE_RESET", - "DEVICE_ADDRESS_ASSIGNED", - "DEVICE_CONFIGURED", - "DEVICE_SET_INTERFACE", - "DEVICE_SET_FEATURE", - "DEVICE_CLEAR_FEATURE", - "DEVICE_DE_CONFIGURED", - "DEVICE_BUS_INACTIVE", - "DEVICE_BUS_ACTIVITY", - "DEVICE_POWER_INTERRUPTION", - "DEVICE_HUB_RESET", - "DEVICE_DESTROY", - "DEVICE_FUNCTION_PRIVATE", -}; - -__maybe_unused static char *usbd_device_status[] = { - "USBD_OPENING", - "USBD_OK", - "USBD_SUSPENDED", - "USBD_CLOSING", -}; - -#define USBD_DEVICE_STATUS(x) (((unsigned int)x <= USBD_CLOSING) ? usbd_device_status[x] : "UNKNOWN") - -/* Descriptor support functions ************************************************************** */ - -/** - * usbd_get_string - find and return a string descriptor - * @index: string index to return - * - * Find an indexed string and return a pointer to a it. - */ -struct usb_string_descriptor *usbd_get_string (__u8 index) -{ - if (index >= maxstrings) { - return NULL; - } - return usb_strings[index]; -} - -/* Access to device descriptor functions ***************************************************** */ - -/* * - * usbd_device_configuration_instance - find a configuration instance for this device - * @device: - * @configuration: index to configuration, 0 - N-1 - * - * Get specifed device configuration. Index should be bConfigurationValue-1. - */ -static struct usb_configuration_instance *usbd_device_configuration_instance (struct usb_device_instance *device, - unsigned int port, unsigned int configuration) -{ - if (configuration >= device->configurations) - return NULL; - - return device->configuration_instance_array + configuration; -} - -/* * - * usbd_device_interface_instance - * @device: - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * - * Return the specified interface descriptor for the specified device. - */ -struct usb_interface_instance *usbd_device_interface_instance (struct usb_device_instance *device, int port, int configuration, int interface) -{ - struct usb_configuration_instance *configuration_instance; - - if ((configuration_instance = usbd_device_configuration_instance (device, port, configuration)) == NULL) { - return NULL; - } - if (interface >= configuration_instance->interfaces) { - return NULL; - } - return configuration_instance->interface_instance_array + interface; -} - -/* * - * usbd_device_alternate_descriptor_list - * @device: - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * - * Return the specified alternate descriptor for the specified device. - */ -struct usb_alternate_instance *usbd_device_alternate_instance (struct usb_device_instance *device, int port, int configuration, int interface, int alternate) -{ - struct usb_interface_instance *interface_instance; - - if ((interface_instance = usbd_device_interface_instance (device, port, configuration, interface)) == NULL) { - return NULL; - } - - if (alternate >= interface_instance->alternates) { - return NULL; - } - - return interface_instance->alternates_instance_array + alternate; -} - -/* * - * usbd_device_device_descriptor - * @device: which device - * @configuration: index to configuration, 0 - N-1 - * @port: which port - * - * Return the specified configuration descriptor for the specified device. - */ -struct usb_device_descriptor *usbd_device_device_descriptor (struct usb_device_instance *device, int port) -{ - return (device->device_descriptor); -} - -/** - * usbd_device_configuration_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * - * Return the specified configuration descriptor for the specified device. - */ -struct usb_configuration_descriptor *usbd_device_configuration_descriptor (struct - usb_device_instance - *device, int port, int configuration) -{ - struct usb_configuration_instance *configuration_instance; - if (!(configuration_instance = usbd_device_configuration_instance (device, port, configuration))) { - return NULL; - } - return (configuration_instance->configuration_descriptor); -} - -/** - * usbd_device_interface_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * - * Return the specified interface descriptor for the specified device. - */ -struct usb_interface_descriptor *usbd_device_interface_descriptor (struct usb_device_instance - *device, int port, int configuration, int interface, int alternate) -{ - struct usb_interface_instance *interface_instance; - if (!(interface_instance = usbd_device_interface_instance (device, port, configuration, interface))) { - return NULL; - } - if ((alternate < 0) || (alternate >= interface_instance->alternates)) { - return NULL; - } - return (interface_instance->alternates_instance_array[alternate].interface_descriptor); -} - -/** - * usbd_device_endpoint_descriptor_index - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: index setting - * @index: which index - * - * Return the specified endpoint descriptor for the specified device. - */ -struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor_index (struct usb_device_instance - *device, int port, int configuration, int interface, int alternate, int index) -{ - struct usb_alternate_instance *alternate_instance; - - if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) { - return NULL; - } - if (index >= alternate_instance->endpoints) { - return NULL; - } - return *(alternate_instance->endpoints_descriptor_array + index); -} - -/** - * usbd_device_endpoint_transfersize - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @index: which index - * - * Return the specified endpoint transfer size; - */ -int usbd_device_endpoint_transfersize (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int index) -{ - struct usb_alternate_instance *alternate_instance; - - if (!(alternate_instance = usbd_device_alternate_instance (device, port, configuration, interface, alternate))) { - return 0; - } - if (index >= alternate_instance->endpoints) { - return 0; - } - return *(alternate_instance->endpoint_transfersize_array + index); -} - -/** - * usbd_device_endpoint_descriptor - * @device: which device - * @port: which port - * @configuration: index to configuration, 0 - N-1 - * @interface: index to interface - * @alternate: alternate setting - * @endpoint: which endpoint - * - * Return the specified endpoint descriptor for the specified device. - */ -struct usb_endpoint_descriptor *usbd_device_endpoint_descriptor (struct usb_device_instance *device, int port, int configuration, int interface, int alternate, int endpoint) -{ - struct usb_endpoint_descriptor *endpoint_descriptor; - int i; - - for (i = 0; !(endpoint_descriptor = usbd_device_endpoint_descriptor_index (device, port, configuration, interface, alternate, i)); i++) { - if (endpoint_descriptor->bEndpointAddress == endpoint) { - return endpoint_descriptor; - } - } - return NULL; -} - -/** - * usbd_endpoint_halted - * @device: point to struct usb_device_instance - * @endpoint: endpoint to check - * - * Return non-zero if endpoint is halted. - */ -int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint) -{ - return (device->status == USB_STATUS_HALT); -} - -/** - * usbd_rcv_complete - complete a receive - * @endpoint: - * @len: - * @urb_bad: - * - * Called from rcv interrupt to complete. - */ -void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad) -{ - if (endpoint) { - struct urb *rcv_urb; - - /*usbdbg("len: %d urb: %p\n", len, endpoint->rcv_urb); */ - - /* if we had an urb then update actual_length, dispatch if neccessary */ - if ((rcv_urb = endpoint->rcv_urb)) { - - /*usbdbg("actual: %d buffer: %d\n", */ - /*rcv_urb->actual_length, rcv_urb->buffer_length); */ - - /* check the urb is ok, are we adding data less than the packetsize */ - if (!urb_bad && (len <= endpoint->rcv_packetSize)) { - /*usbdbg("updating actual_length by %d\n",len); */ - - /* increment the received data size */ - rcv_urb->actual_length += len; - - } else { - usberr(" RECV_ERROR actual: %d buffer: %d urb_bad: %d\n", - rcv_urb->actual_length, rcv_urb->buffer_length, urb_bad); - - rcv_urb->actual_length = 0; - rcv_urb->status = RECV_ERROR; - } - } else { - usberr("no rcv_urb!"); - } - } else { - usberr("no endpoint!"); - } - -} - -/** - * usbd_tx_complete - complete a transmit - * @endpoint: - * @resetart: - * - * Called from tx interrupt to complete. - */ -void usbd_tx_complete (struct usb_endpoint_instance *endpoint) -{ - if (endpoint) { - struct urb *tx_urb; - - /* if we have a tx_urb advance or reset, finish if complete */ - if ((tx_urb = endpoint->tx_urb)) { - int sent = endpoint->last; - endpoint->sent += sent; - endpoint->last -= sent; - - if( (endpoint->tx_urb->actual_length - endpoint->sent) <= 0 ) { - tx_urb->actual_length = 0; - endpoint->sent = 0; - endpoint->last = 0; - - /* Remove from active, save for re-use */ - urb_detach(tx_urb); - urb_append(&endpoint->done, tx_urb); - /*usbdbg("done->next %p, tx_urb %p, done %p", */ - /* endpoint->done.next, tx_urb, &endpoint->done); */ - - endpoint->tx_urb = first_urb_detached(&endpoint->tx); - if( endpoint->tx_urb ) { - endpoint->tx_queue--; - usbdbg("got urb from tx list"); - } - if( !endpoint->tx_urb ) { - /*usbdbg("taking urb from done list"); */ - endpoint->tx_urb = first_urb_detached(&endpoint->done); - } - if( !endpoint->tx_urb ) { - usbdbg("allocating new urb for tx_urb"); - endpoint->tx_urb = usbd_alloc_urb(tx_urb->device, endpoint); - } - } - } - } -} - -/* URB linked list functions ***************************************************** */ - -/* - * Initialize an urb_link to be a single element list. - * If the urb_link is being used as a distinguished list head - * the list is empty when the head is the only link in the list. - */ -void urb_link_init (urb_link * ul) -{ - if (ul) { - ul->prev = ul->next = ul; - } -} - -/* - * Detach an urb_link from a list, and set it - * up as a single element list, so no dangling - * pointers can be followed, and so it can be - * joined to another list if so desired. - */ -void urb_detach (struct urb *urb) -{ - if (urb) { - urb_link *ul = &urb->link; - ul->next->prev = ul->prev; - ul->prev->next = ul->next; - urb_link_init (ul); - } -} - -/* - * Return the first urb_link in a list with a distinguished - * head "hd", or NULL if the list is empty. This will also - * work as a predicate, returning NULL if empty, and non-NULL - * otherwise. - */ -urb_link *first_urb_link (urb_link * hd) -{ - urb_link *nx; - if (NULL != hd && NULL != (nx = hd->next) && nx != hd) { - /* There is at least one element in the list */ - /* (besides the distinguished head). */ - return (nx); - } - /* The list is empty */ - return (NULL); -} - -/* - * Return the first urb in a list with a distinguished - * head "hd", or NULL if the list is empty. - */ -struct urb *first_urb (urb_link * hd) -{ - urb_link *nx; - if (NULL == (nx = first_urb_link (hd))) { - /* The list is empty */ - return (NULL); - } - return (p2surround (struct urb, link, nx)); -} - -/* - * Detach and return the first urb in a list with a distinguished - * head "hd", or NULL if the list is empty. - * - */ -struct urb *first_urb_detached (urb_link * hd) -{ - struct urb *urb; - if ((urb = first_urb (hd))) { - urb_detach (urb); - } - return urb; -} - -/* - * Append an urb_link (or a whole list of - * urb_links) to the tail of another list - * of urb_links. - */ -void urb_append (urb_link * hd, struct urb *urb) -{ - if (hd && urb) { - urb_link *new = &urb->link; - - /* This allows the new urb to be a list of urbs, */ - /* with new pointing at the first, but the link */ - /* must be initialized. */ - /* Order is important here... */ - urb_link *pul = hd->prev; - new->prev->next = hd; - hd->prev = new->prev; - new->prev = pul; - pul->next = new; - } -} - -/* URB create/destroy functions ***************************************************** */ - -/** - * usbd_alloc_urb - allocate an URB appropriate for specified endpoint - * @device: device instance - * @endpoint: endpoint - * - * Allocate an urb structure. The usb device urb structure is used to - * contain all data associated with a transfer, including a setup packet for - * control transfers. - * - * NOTE: endpoint_address MUST contain a direction flag. - */ -struct urb *usbd_alloc_urb (struct usb_device_instance *device, - struct usb_endpoint_instance *endpoint) -{ - struct urb *urb; - - if (!(urb = (struct urb *) malloc (sizeof (struct urb)))) { - usberr (" F A T A L: malloc(%zu) FAILED!!!!", - sizeof (struct urb)); - return NULL; - } - - /* Fill in known fields */ - memset (urb, 0, sizeof (struct urb)); - urb->endpoint = endpoint; - urb->device = device; - urb->buffer = (u8 *) urb->buffer_data; - urb->buffer_length = sizeof (urb->buffer_data); - - urb_link_init (&urb->link); - - return urb; -} - -/** - * usbd_dealloc_urb - deallocate an URB and associated buffer - * @urb: pointer to an urb structure - * - * Deallocate an urb structure and associated data. - */ -void usbd_dealloc_urb (struct urb *urb) -{ - if (urb) { - free (urb); - } -} - -/* Event signaling functions ***************************************************** */ - -/** - * usbd_device_event - called to respond to various usb events - * @device: pointer to struct device - * @event: event to respond to - * - * Used by a Bus driver to indicate an event. - */ -void usbd_device_event_irq (struct usb_device_instance *device, usb_device_event_t event, int data) -{ - usb_device_state_t state; - - if (!device || !device->bus) { - usberr("(%p,%d) NULL device or device->bus", device, event); - return; - } - - state = device->device_state; - - usbinfo("%s", usbd_device_events[event]); - - switch (event) { - case DEVICE_UNKNOWN: - break; - case DEVICE_INIT: - device->device_state = STATE_INIT; - break; - - case DEVICE_CREATE: - device->device_state = STATE_ATTACHED; - break; - - case DEVICE_HUB_CONFIGURED: - device->device_state = STATE_POWERED; - break; - - case DEVICE_RESET: - device->device_state = STATE_DEFAULT; - device->address = 0; - break; - - case DEVICE_ADDRESS_ASSIGNED: - device->device_state = STATE_ADDRESSED; - break; - - case DEVICE_CONFIGURED: - device->device_state = STATE_CONFIGURED; - break; - - case DEVICE_DE_CONFIGURED: - device->device_state = STATE_ADDRESSED; - break; - - case DEVICE_BUS_INACTIVE: - if (device->status != USBD_CLOSING) { - device->status = USBD_SUSPENDED; - } - break; - case DEVICE_BUS_ACTIVITY: - if (device->status != USBD_CLOSING) { - device->status = USBD_OK; - } - break; - - case DEVICE_SET_INTERFACE: - break; - case DEVICE_SET_FEATURE: - break; - case DEVICE_CLEAR_FEATURE: - break; - - case DEVICE_POWER_INTERRUPTION: - device->device_state = STATE_POWERED; - break; - case DEVICE_HUB_RESET: - device->device_state = STATE_ATTACHED; - break; - case DEVICE_DESTROY: - device->device_state = STATE_UNKNOWN; - break; - - case DEVICE_FUNCTION_PRIVATE: - break; - - default: - usbdbg("event %d - not handled",event); - break; - } - debug("%s event: %d oldstate: %d newstate: %d status: %d address: %d", - device->name, event, state, - device->device_state, device->status, device->address); - - /* tell the bus interface driver */ - if( device->event ) { - /* usbdbg("calling device->event"); */ - device->event(device, event, data); - } -} diff --git a/drivers/usb/gadget/ep0.c b/drivers/usb/gadget/ep0.c deleted file mode 100644 index 8c7fc17c2ea..00000000000 --- a/drivers/usb/gadget/ep0.c +++ /dev/null @@ -1,619 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2003 - * Gerry Hamel, geh@ti.com, Texas Instruments - * - * (C) Copyright 2006 - * Bryan O'Donoghue, deckard@CodeHermit.ie - * - * Based on - * linux/drivers/usbd/ep0.c - * - * Copyright (c) 2000, 2001, 2002 Lineo - * Copyright (c) 2001 Hewlett Packard - * - * By: - * Stuart Lynne <sl@lineo.com>, - * Tom Rushworth <tbr@lineo.com>, - * Bruce Balden <balden@lineo.com> - */ - -/* - * This is the builtin ep0 control function. It implements all required functionality - * for responding to control requests (SETUP packets). - * - * XXX - * - * Currently we do not pass any SETUP packets (or other) to the configured - * function driver. This may need to change. - * - * XXX - * - * As alluded to above, a simple callback cdc_recv_setup has been implemented - * in the usb_device data structure to facilicate passing - * Common Device Class packets to a function driver. - * - * XXX - */ - -#include <serial.h> -#include <usbdevice.h> - -#if 0 -#define dbg_ep0(lvl,fmt,args...) serial_printf("[%s] %s:%d: "fmt"\n",__FILE__,__FUNCTION__,__LINE__,##args) -#else -#define dbg_ep0(lvl,fmt,args...) -#endif - -__maybe_unused static char *usbd_device_descriptors[] = { - "UNKNOWN", /* 0 */ - "DEVICE", /* 1 */ - "CONFIG", /* 2 */ - "STRING", /* 3 */ - "INTERFACE", /* 4 */ - "ENDPOINT", /* 5 */ - "DEVICE QUALIFIER", /* 6 */ - "OTHER SPEED", /* 7 */ - "INTERFACE POWER", /* 8 */ -}; - -#define USBD_DEVICE_DESCRIPTORS(x) (((unsigned int)x <= USB_DESCRIPTOR_TYPE_INTERFACE_POWER) ? \ - usbd_device_descriptors[x] : "UNKNOWN") - -__maybe_unused static char *usbd_device_states[] = { - "STATE_INIT", - "STATE_CREATED", - "STATE_ATTACHED", - "STATE_POWERED", - "STATE_DEFAULT", - "STATE_ADDRESSED", - "STATE_CONFIGURED", - "STATE_UNKNOWN", -}; - -#define USBD_DEVICE_STATE(x) (((unsigned int)x <= STATE_UNKNOWN) ? usbd_device_states[x] : "UNKNOWN") - -__maybe_unused static char *usbd_device_requests[] = { - "GET STATUS", /* 0 */ - "CLEAR FEATURE", /* 1 */ - "RESERVED", /* 2 */ - "SET FEATURE", /* 3 */ - "RESERVED", /* 4 */ - "SET ADDRESS", /* 5 */ - "GET DESCRIPTOR", /* 6 */ - "SET DESCRIPTOR", /* 7 */ - "GET CONFIGURATION", /* 8 */ - "SET CONFIGURATION", /* 9 */ - "GET INTERFACE", /* 10 */ - "SET INTERFACE", /* 11 */ - "SYNC FRAME", /* 12 */ -}; - -#define USBD_DEVICE_REQUESTS(x) (((unsigned int)x <= USB_REQ_SYNCH_FRAME) ? usbd_device_requests[x] : "UNKNOWN") - -/* EP0 Configuration Set ********************************************************************* */ - -/** - * ep0_get_status - fill in URB data with appropriate status - * @device: - * @urb: - * @index: - * @requesttype: - * - */ -static int ep0_get_status (struct usb_device_instance *device, - struct urb *urb, int index, int requesttype) -{ - char *cp; - - urb->actual_length = 2; - cp = (char*)urb->buffer; - cp[0] = cp[1] = 0; - - switch (requesttype) { - case USB_REQ_RECIPIENT_DEVICE: - cp[0] = USB_STATUS_SELFPOWERED; - break; - case USB_REQ_RECIPIENT_INTERFACE: - break; - case USB_REQ_RECIPIENT_ENDPOINT: - cp[0] = usbd_endpoint_halted (device, index); - break; - case USB_REQ_RECIPIENT_OTHER: - urb->actual_length = 0; - default: - break; - } - dbg_ep0 (2, "%02x %02x", cp[0], cp[1]); - return 0; -} - -/** - * ep0_get_one - * @device: - * @urb: - * @result: - * - * Set a single byte value in the urb send buffer. Return non-zero to signal - * a request error. - */ -static int ep0_get_one (struct usb_device_instance *device, struct urb *urb, - __u8 result) -{ - urb->actual_length = 1; /* XXX 2? */ - ((char *) urb->buffer)[0] = result; - return 0; -} - -/** - * copy_config - * @urb: pointer to urb - * @data: pointer to configuration data - * @length: length of data - * - * Copy configuration data to urb transfer buffer if there is room for it. - */ -void copy_config (struct urb *urb, void *data, int max_length, - int max_buf) -{ - int available; - int length; - - /*dbg_ep0(3, "-> actual: %d buf: %d max_buf: %d max_length: %d data: %p", */ - /* urb->actual_length, urb->buffer_length, max_buf, max_length, data); */ - - if (!data) { - dbg_ep0 (1, "data is NULL"); - return; - } - length = max_length; - - if (length > max_length) { - dbg_ep0 (1, "length: %d >= max_length: %d", length, - max_length); - return; - } - /*dbg_ep0(1, " actual: %d buf: %d max_buf: %d max_length: %d length: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, max_length, length); */ - - if ((available = - /*urb->buffer_length */ max_buf - urb->actual_length) <= 0) { - return; - } - /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ - - if (length > available) { - length = available; - } - /*dbg_ep0(1, "actual: %d buf: %d max_buf: %d length: %d available: %d", */ - /* urb->actual_length, urb->buffer_length, max_buf, length, available); */ - - memcpy (urb->buffer + urb->actual_length, data, length); - urb->actual_length += length; - - dbg_ep0 (3, - "copy_config: <- actual: %d buf: %d max_buf: %d max_length: %d available: %d", - urb->actual_length, urb->buffer_length, max_buf, max_length, - available); -} - -/** - * ep0_get_descriptor - * @device: - * @urb: - * @max: - * @descriptor_type: - * @index: - * - * Called by ep0_rx_process for a get descriptor device command. Determine what - * descriptor is being requested, copy to send buffer. Return zero if ok to send, - * return non-zero to signal a request error. - */ -static int ep0_get_descriptor (struct usb_device_instance *device, - struct urb *urb, int max, int descriptor_type, - int index) -{ - int port = 0; /* XXX compound device */ - - /*dbg_ep0(3, "max: %x type: %x index: %x", max, descriptor_type, index); */ - - if (!urb || !urb->buffer || !urb->buffer_length - || (urb->buffer_length < 255)) { - dbg_ep0 (2, "invalid urb %p", urb); - return -1L; - } - - /* setup tx urb */ - urb->actual_length = 0; - - dbg_ep0 (2, "%s", USBD_DEVICE_DESCRIPTORS (descriptor_type)); - - switch (descriptor_type) { - case USB_DESCRIPTOR_TYPE_DEVICE: - { - struct usb_device_descriptor *device_descriptor; - if (! - (device_descriptor = - usbd_device_device_descriptor (device, port))) { - return -1; - } - /* copy descriptor for this device */ - copy_config (urb, device_descriptor, - sizeof (struct usb_device_descriptor), - max); - - /* correct the correct control endpoint 0 max packet size into the descriptor */ - device_descriptor = - (struct usb_device_descriptor *) urb->buffer; - - } - dbg_ep0(3, "copied device configuration, actual_length: 0x%x", urb->actual_length); - break; - - case USB_DESCRIPTOR_TYPE_CONFIGURATION: - { - struct usb_configuration_descriptor - *configuration_descriptor; - struct usb_device_descriptor *device_descriptor; - if (! - (device_descriptor = - usbd_device_device_descriptor (device, port))) { - return -1; - } - /*dbg_ep0(2, "%d %d", index, device_descriptor->bNumConfigurations); */ - if (index >= device_descriptor->bNumConfigurations) { - dbg_ep0 (0, "index too large: %d >= %d", index, - device_descriptor-> - bNumConfigurations); - return -1; - } - - if (! - (configuration_descriptor = - usbd_device_configuration_descriptor (device, - port, - index))) { - dbg_ep0 (0, - "usbd_device_configuration_descriptor failed: %d", - index); - return -1; - } - dbg_ep0(0, "attempt to copy %d bytes to urb\n",cpu_to_le16(configuration_descriptor->wTotalLength)); - copy_config (urb, configuration_descriptor, - - cpu_to_le16(configuration_descriptor->wTotalLength), - max); - } - - break; - - case USB_DESCRIPTOR_TYPE_STRING: - { - struct usb_string_descriptor *string_descriptor; - if (!(string_descriptor = usbd_get_string (index))) { - dbg_ep0(0, "Invalid string index %d\n", index); - return -1; - } - dbg_ep0(3, "string_descriptor: %p length %d", string_descriptor, string_descriptor->bLength); - copy_config (urb, string_descriptor, string_descriptor->bLength, max); - } - break; - case USB_DESCRIPTOR_TYPE_INTERFACE: - dbg_ep0(2, "USB_DESCRIPTOR_TYPE_INTERFACE - error not implemented\n"); - return -1; - case USB_DESCRIPTOR_TYPE_ENDPOINT: - dbg_ep0(2, "USB_DESCRIPTOR_TYPE_ENDPOINT - error not implemented\n"); - return -1; - case USB_DESCRIPTOR_TYPE_HID: - { - dbg_ep0(2, "USB_DESCRIPTOR_TYPE_HID - error not implemented\n"); - return -1; /* unsupported at this time */ -#if 0 - int bNumInterface = - le16_to_cpu (urb->device_request.wIndex); - int bAlternateSetting = 0; - int class = 0; - struct usb_class_descriptor *class_descriptor; - - if (!(class_descriptor = - usbd_device_class_descriptor_index (device, - port, 0, - bNumInterface, - bAlternateSetting, - class)) - || class_descriptor->descriptor.hid.bDescriptorType != USB_DT_HID) { - dbg_ep0 (3, "[%d] interface is not HID", - bNumInterface); - return -1; - } - /* copy descriptor for this class */ - copy_config (urb, class_descriptor, - class_descriptor->descriptor.hid.bLength, - max); -#endif - } - break; - case USB_DESCRIPTOR_TYPE_REPORT: - { - dbg_ep0(2, "USB_DESCRIPTOR_TYPE_REPORT - error not implemented\n"); - return -1; /* unsupported at this time */ -#if 0 - int bNumInterface = - le16_to_cpu (urb->device_request.wIndex); - int bAlternateSetting = 0; - int class = 0; - struct usb_class_report_descriptor *report_descriptor; - - if (!(report_descriptor = - usbd_device_class_report_descriptor_index - (device, port, 0, bNumInterface, - bAlternateSetting, class)) - || report_descriptor->bDescriptorType != - USB_DT_REPORT) { - dbg_ep0 (3, "[%d] descriptor is not REPORT", - bNumInterface); - return -1; - } - /* copy report descriptor for this class */ - /*copy_config(urb, &report_descriptor->bData[0], report_descriptor->wLength, max); */ - if (max - urb->actual_length > 0) { - int length = - min(report_descriptor->wLength, - max - urb->actual_length); - memcpy (urb->buffer + urb->actual_length, - &report_descriptor->bData[0], length); - urb->actual_length += length; - } -#endif - } - break; - case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: - return -1; - - default: - return -1; - } - - dbg_ep0 (1, "urb: buffer: %p buffer_length: %2d actual_length: %2d tx_packetSize: %2d", - urb->buffer, urb->buffer_length, urb->actual_length, - device->bus->endpoint_array[0].tx_packetSize); -/* - if ((urb->actual_length < max) && !(urb->actual_length % device->bus->endpoint_array[0].tx_packetSize)) { - dbg_ep0(0, "adding null byte"); - urb->buffer[urb->actual_length++] = 0; - dbg_ep0(0, "urb: buffer_length: %2d actual_length: %2d packet size: %2d", - urb->buffer_length, urb->actual_length device->bus->endpoint_array[0].tx_packetSize); - } -*/ - return 0; - -} - -/** - * ep0_recv_setup - called to indicate URB has been received - * @urb: pointer to struct urb - * - * Check if this is a setup packet, process the device request, put results - * back into the urb and return zero or non-zero to indicate success (DATA) - * or failure (STALL). - * - */ -int ep0_recv_setup (struct urb *urb) -{ - /*struct usb_device_request *request = urb->buffer; */ - /*struct usb_device_instance *device = urb->device; */ - - struct usb_device_request *request; - struct usb_device_instance *device; - int address; - - dbg_ep0 (0, "entering ep0_recv_setup()"); - if (!urb || !urb->device) { - dbg_ep0 (3, "invalid URB %p", urb); - return -1; - } - - request = &urb->device_request; - device = urb->device; - - dbg_ep0 (3, "urb: %p device: %p", urb, urb->device); - - /*dbg_ep0(2, "- - - - - - - - - -"); */ - - dbg_ep0 (2, - "bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %s", - request->bmRequestType, request->bRequest, - le16_to_cpu (request->wValue), le16_to_cpu (request->wIndex), - le16_to_cpu (request->wLength), - USBD_DEVICE_REQUESTS (request->bRequest)); - - /* handle USB Standard Request (c.f. USB Spec table 9-2) */ - if ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0) { - if(device->device_state <= STATE_CONFIGURED){ - /* Attempt to handle a CDC specific request if we are - * in the configured state. - */ - return device->cdc_recv_setup(request,urb); - } - dbg_ep0 (1, "non standard request: %x", - request->bmRequestType & USB_REQ_TYPE_MASK); - return -1; /* Stall here */ - } - - switch (device->device_state) { - case STATE_CREATED: - case STATE_ATTACHED: - case STATE_POWERED: - /* It actually is important to allow requests in these states, - * Windows will request descriptors before assigning an - * address to the client. - */ - - /*dbg_ep0 (1, "request %s not allowed in this state: %s", */ - /* USBD_DEVICE_REQUESTS(request->bRequest), */ - /* usbd_device_states[device->device_state]); */ - /*return -1; */ - break; - - case STATE_INIT: - case STATE_DEFAULT: - switch (request->bRequest) { - case USB_REQ_GET_STATUS: - case USB_REQ_GET_INTERFACE: - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - case USB_REQ_SET_DESCRIPTOR: - /* case USB_REQ_SET_CONFIGURATION: */ - case USB_REQ_SET_INTERFACE: - dbg_ep0 (1, - "request %s not allowed in DEFAULT state: %s", - USBD_DEVICE_REQUESTS (request->bRequest), - usbd_device_states[device->device_state]); - return -1; - - case USB_REQ_SET_CONFIGURATION: - case USB_REQ_SET_ADDRESS: - case USB_REQ_GET_DESCRIPTOR: - case USB_REQ_GET_CONFIGURATION: - break; - } - case STATE_ADDRESSED: - case STATE_CONFIGURED: - break; - case STATE_UNKNOWN: - dbg_ep0 (1, "request %s not allowed in UNKNOWN state: %s", - USBD_DEVICE_REQUESTS (request->bRequest), - usbd_device_states[device->device_state]); - return -1; - } - - /* handle all requests that return data (direction bit set on bm RequestType) */ - if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) { - - dbg_ep0 (3, "Device-to-Host"); - - switch (request->bRequest) { - - case USB_REQ_GET_STATUS: - return ep0_get_status (device, urb, request->wIndex, - request->bmRequestType & - USB_REQ_RECIPIENT_MASK); - - case USB_REQ_GET_DESCRIPTOR: - return ep0_get_descriptor (device, urb, - le16_to_cpu (request->wLength), - le16_to_cpu (request->wValue) >> 8, - le16_to_cpu (request->wValue) & 0xff); - - case USB_REQ_GET_CONFIGURATION: - dbg_ep0(2, "get config %d\n", device->configuration); - return ep0_get_one (device, urb, - device->configuration); - - case USB_REQ_GET_INTERFACE: - return ep0_get_one (device, urb, device->alternate); - - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - return -1; - - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - case USB_REQ_SET_ADDRESS: - case USB_REQ_SET_DESCRIPTOR: - case USB_REQ_SET_CONFIGURATION: - case USB_REQ_SET_INTERFACE: - return -1; - } - } - /* handle the requests that do not return data */ - else { - - /*dbg_ep0(3, "Host-to-Device"); */ - switch (request->bRequest) { - - case USB_REQ_CLEAR_FEATURE: - case USB_REQ_SET_FEATURE: - dbg_ep0 (0, "Host-to-Device"); - switch (request-> - bmRequestType & USB_REQ_RECIPIENT_MASK) { - case USB_REQ_RECIPIENT_DEVICE: - /* XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here */ - /* XXX fall through for now as we do not support either */ - case USB_REQ_RECIPIENT_INTERFACE: - case USB_REQ_RECIPIENT_OTHER: - dbg_ep0 (0, "request %s not", - USBD_DEVICE_REQUESTS (request->bRequest)); - default: - return -1; - - case USB_REQ_RECIPIENT_ENDPOINT: - dbg_ep0 (0, "ENDPOINT: %x", le16_to_cpu (request->wValue)); - if (le16_to_cpu (request->wValue) == USB_ENDPOINT_HALT) { - /*return usbd_device_feature (device, le16_to_cpu (request->wIndex), */ - /* request->bRequest == USB_REQ_SET_FEATURE); */ - /* NEED TO IMPLEMENT THIS!!! */ - return -1; - } else { - dbg_ep0 (1, "request %s bad wValue: %04x", - USBD_DEVICE_REQUESTS - (request->bRequest), - le16_to_cpu (request->wValue)); - return -1; - } - } - - case USB_REQ_SET_ADDRESS: - /* check if this is a re-address, reset first if it is (this shouldn't be possible) */ - if (device->device_state != STATE_DEFAULT) { - dbg_ep0 (1, "set_address: %02x state: %s", - le16_to_cpu (request->wValue), - usbd_device_states[device->device_state]); - return -1; - } - address = le16_to_cpu (request->wValue); - if ((address & 0x7f) != address) { - dbg_ep0 (1, "invalid address %04x %04x", - address, address & 0x7f); - return -1; - } - device->address = address; - - /*dbg_ep0(2, "address: %d %d %d", */ - /* request->wValue, le16_to_cpu(request->wValue), device->address); */ - - return 0; - - case USB_REQ_SET_DESCRIPTOR: /* XXX should we support this? */ - dbg_ep0 (0, "set descriptor: NOT SUPPORTED"); - return -1; - - case USB_REQ_SET_CONFIGURATION: - /* c.f. 9.4.7 - the top half of wValue is reserved */ - device->configuration = le16_to_cpu(request->wValue) & 0xff; - - /* reset interface and alternate settings */ - device->interface = device->alternate = 0; - - /*dbg_ep0(2, "set configuration: %d", device->configuration); */ - /*dbg_ep0(2, "DEVICE_CONFIGURED.. event?\n"); */ - return 0; - - case USB_REQ_SET_INTERFACE: - device->interface = le16_to_cpu (request->wIndex); - device->alternate = le16_to_cpu (request->wValue); - /*dbg_ep0(2, "set interface: %d alternate: %d", device->interface, device->alternate); */ - dbg_ep0(2, "DEVICE_SET_INTERFACE.. event?\n"); - return 0; - - case USB_REQ_GET_STATUS: - case USB_REQ_GET_DESCRIPTOR: - case USB_REQ_GET_CONFIGURATION: - case USB_REQ_GET_INTERFACE: - case USB_REQ_SYNCH_FRAME: /* XXX should never see this (?) */ - return -1; - } - } - return -1; -} diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig index c52afd41a75..ad9072a5327 100644 --- a/drivers/usb/musb-new/Kconfig +++ b/drivers/usb/musb-new/Kconfig @@ -22,6 +22,13 @@ config USB_MUSB_GADGET Enables the MUSB USB dual-role controller in gadget mode. if USB_MUSB_HOST || USB_MUSB_GADGET +config USB_MUSB_SC5XX + bool "Analog Devices MUSB support" + depends on (SC57X || SC58X) + help + Say y here to enable support for the USB controller on + ADI SC57X/SC58X processors. + config USB_MUSB_DA8XX bool "Enable DA8xx MUSB Controller" depends on ARCH_DAVINCI diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile index 396ff02654b..6638772daca 100644 --- a/drivers/usb/musb-new/Makefile +++ b/drivers/usb/musb-new/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o obj-$(CONFIG_USB_MUSB_TI) += ti-musb.o obj-$(CONFIG_USB_MUSB_UX500) += ux500.o +obj-$(CONFIG_USB_MUSB_SC5XX) += sc5xx.o ccflags-y := $(call cc-option,-Wno-unused-variable) \ $(call cc-option,-Wno-unused-but-set-variable) \ diff --git a/drivers/usb/musb-new/sc5xx.c b/drivers/usb/musb-new/sc5xx.c new file mode 100644 index 00000000000..16201480b43 --- /dev/null +++ b/drivers/usb/musb-new/sc5xx.c @@ -0,0 +1,202 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * ADI SC5XX MUSB "glue layer" + * + * Written and/or maintained by Timesys Corporation + * + * Loosely ported from Linux driver: + * Author: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * + */ + +#include <dm.h> +#include <dm/device_compat.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/usb/musb.h> +#include "linux-compat.h" +#include "musb_core.h" +#include "musb_uboot.h" + +#define MUSB_SOFTRST 0x7f +#define MUSB_SOFTRST_NRST BIT(0) +#define MUSB_SOFTRST_NRSTX BIT(1) + +#define REG_USB_VBUS_CTL 0x380 +#define REG_USB_ID_CTL 0x382 +#define REG_USB_PHY_CTL 0x394 +#define REG_USB_PLL_OSC 0x398 +#define REG_USB_UTMI_CTL 0x39c + +/* controller data */ +struct sc5xx_musb_data { + struct musb_host_data mdata; + struct device dev; +}; + +#define to_sc5xx_musb_data(d) \ + container_of(d, struct sc5xx_musb_data, dev) + +static void sc5xx_musb_disable(struct musb *musb) +{ + /* no way to shut the controller */ +} + +static int sc5xx_musb_enable(struct musb *musb) +{ + /* soft reset by NRSTx */ + musb_writeb(musb->mregs, MUSB_SOFTRST, MUSB_SOFTRST_NRSTX); + /* set mode */ + musb_platform_set_mode(musb, musb->board_mode); + + return 0; +} + +static irqreturn_t sc5xx_interrupt(int irq, void *hci) +{ + struct musb *musb = hci; + irqreturn_t ret = IRQ_NONE; + u8 devctl; + + musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); + musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); + musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); + + if (musb->int_usb & MUSB_INTR_VBUSERROR) { + musb->int_usb &= ~MUSB_INTR_VBUSERROR; + devctl = musb_readw(musb->mregs, MUSB_DEVCTL); + devctl |= MUSB_DEVCTL_SESSION; + musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); + } + if (musb->int_usb || musb->int_tx || musb->int_rx) { + musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); + musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); + musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); + ret = musb_interrupt(musb); + } + + if (musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb)) + musb_writeb(musb->mregs, REG_USB_VBUS_CTL, 0x0); + + return ret; +} + +static int sc5xx_musb_set_mode(struct musb *musb, u8 mode) +{ + struct device *dev = musb->controller; + struct sc5xx_musb_data *pdata = to_sc5xx_musb_data(dev); + + switch (mode) { + case MUSB_HOST: + musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x1); + break; + case MUSB_PERIPHERAL: + musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x3); + break; + case MUSB_OTG: + musb_writeb(musb->mregs, REG_USB_ID_CTL, 0x0); + break; + default: + dev_err(dev, "unsupported mode %d\n", mode); + return -EINVAL; + } + + return 0; +} + +static int sc5xx_musb_init(struct musb *musb) +{ + struct sc5xx_musb_data *pdata = to_sc5xx_musb_data(musb->controller); + + musb->isr = sc5xx_interrupt; + + musb_writel(musb->mregs, REG_USB_PLL_OSC, 20 << 1); + musb_writeb(musb->mregs, REG_USB_VBUS_CTL, 0x0); + musb_writeb(musb->mregs, REG_USB_PHY_CTL, 0x80); + musb_writel(musb->mregs, REG_USB_UTMI_CTL, + 0x40 | musb_readl(musb->mregs, REG_USB_UTMI_CTL)); + + return 0; +} + +const struct musb_platform_ops sc5xx_musb_ops = { + .init = sc5xx_musb_init, + .set_mode = sc5xx_musb_set_mode, + .disable = sc5xx_musb_disable, + .enable = sc5xx_musb_enable, +}; + +static struct musb_hdrc_config sc5xx_musb_config = { + .multipoint = 1, + .dyn_fifo = 1, + .num_eps = 16, + .ram_bits = 12, +}; + +/* has one MUSB controller which can be host or gadget */ +static struct musb_hdrc_platform_data sc5xx_musb_plat = { + .mode = MUSB_HOST, + .config = &sc5xx_musb_config, + .power = 100, + .platform_ops = &sc5xx_musb_ops, +}; + +static int musb_usb_probe(struct udevice *dev) +{ + struct usb_bus_priv *priv = dev_get_uclass_priv(dev); + struct sc5xx_musb_data *pdata = dev_get_priv(dev); + struct musb_host_data *mdata = &pdata->mdata; + void __iomem *mregs; + int ret; + + priv->desc_before_addr = true; + + mregs = dev_remap_addr(dev); + if (!mregs) + return -EINVAL; + + /* init controller */ + if (IS_ENABLED(CONFIG_USB_MUSB_HOST)) { + mdata->host = musb_init_controller(&sc5xx_musb_plat, + &pdata->dev, mregs); + if (!mdata->host) + return -EIO; + + ret = musb_lowlevel_init(mdata); + } else { + sc5xx_musb_plat.mode = MUSB_PERIPHERAL; + mdata->host = musb_register(&sc5xx_musb_plat, &pdata->dev, mregs); + if (!mdata->host) + return -EIO; + } + return ret; +} + +static int musb_usb_remove(struct udevice *dev) +{ + struct sc5xx_musb_data *pdata = dev_get_priv(dev); + + musb_stop(pdata->mdata.host); + + return 0; +} + +static const struct udevice_id sc5xx_musb_ids[] = { + { .compatible = "adi,sc5xx-musb" }, + { } +}; + +U_BOOT_DRIVER(usb_musb) = { + .name = "sc5xx-musb", + .id = UCLASS_USB, + .of_match = sc5xx_musb_ids, + .probe = musb_usb_probe, + .remove = musb_usb_remove, +#ifdef CONFIG_USB_MUSB_HOST + .ops = &musb_usb_ops, +#endif + .plat_auto = sizeof(struct usb_plat), + .priv_auto = sizeof(struct sc5xx_musb_data), +}; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3c3cebaacd0..b1ef73f3e5c 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -599,6 +599,15 @@ config VIDEO_LCD_SAMSUNG_LTL106HL02 LCD module found in Microsoft Surface 2. The panel has a FullHD resolution (1920x1080). +config VIDEO_LCD_SHARP_LQ079L1SX01 + tristate "Sharp LQ079L1SX01 1536x2048 DSI video mode panel" + depends on PANEL && BACKLIGHT + select VIDEO_MIPI_DSI + help + Say Y here if you want to enable support for Sharp LQ079L1SX01 + LCD module found in Xiaomi Mi Pad tablet. The panel has a QXGA + resolution (1536x2048). + config VIDEO_LCD_SHARP_LQ101R1SX01 tristate "Sharp LQ101R1SX01 2560x1600 DSI video mode panel" depends on PANEL && BACKLIGHT @@ -743,6 +752,16 @@ config BACKLIGHT_LM3533 LM3533 Lighting Power chip. Only Bank A is supported as for now. Supported backlight level range is from 2 to 255 with step of 1. +config BACKLIGHT_LP855x + bool "Backlight Driver for LP855x" + depends on BACKLIGHT + select DM_I2C + help + Say Y to enable the backlight driver for National Semiconductor / TI + LP8550/1/2/3/5/6/7 LED Backlight Driver. Only register driven mode is + supported for now, PWM mode can be added if there will be any need in + it. Supported backlight level range is from 0 to 255 with step of 1. + source "drivers/video/ti/Kconfig" source "drivers/video/exynos/Kconfig" diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 5a00438ce06..6073bc5234a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_$(PHASE_)BMP) += bmp.o endif obj-$(CONFIG_BACKLIGHT_LM3533) += lm3533_backlight.o +obj-$(CONFIG_BACKLIGHT_LP855x) += lp855x_backlight.o obj-${CONFIG_EXYNOS_FB} += exynos/ obj-${CONFIG_VIDEO_ROCKCHIP} += rockchip/ obj-${CONFIG_VIDEO_STM32} += stm32/ @@ -64,6 +65,7 @@ obj-$(CONFIG_VIDEO_LCD_RAYDIUM_RM68200) += raydium-rm68200.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R61307) += renesas-r61307.o obj-$(CONFIG_VIDEO_LCD_RENESAS_R69328) += renesas-r69328.o obj-$(CONFIG_VIDEO_LCD_SAMSUNG_LTL106HL02) += samsung-ltl106hl02.o +obj-$(CONFIG_VIDEO_LCD_SHARP_LQ079L1SX01) += sharp-lq079l1sx01.o obj-$(CONFIG_VIDEO_LCD_SHARP_LQ101R1SX01) += sharp-lq101r1sx01.o obj-$(CONFIG_VIDEO_LCD_SSD2828) += ssd2828.o obj-$(CONFIG_VIDEO_LCD_TDO_TL070WSH30) += tdo-tl070wsh30.o diff --git a/drivers/video/bridge/Kconfig b/drivers/video/bridge/Kconfig index ab917273720..21c5a043e02 100644 --- a/drivers/video/bridge/Kconfig +++ b/drivers/video/bridge/Kconfig @@ -59,3 +59,10 @@ config VIDEO_BRIDGE_TOSHIBA_TC358768 help Toshiba TC358768AXBG/TC358778XBG DSI bridge chip driver. Found in Asus Transformer Infinity TF700T. + +config VIDEO_BRIDGE_LVDS_CODEC + bool "Transparent LVDS encoders and decoders support" + depends on VIDEO_BRIDGE && PANEL && DM_GPIO + help + Support for transparent LVDS encoders and decoders that don't + require any configuration. diff --git a/drivers/video/bridge/Makefile b/drivers/video/bridge/Makefile index 58697e3cbe9..63dc6e62c49 100644 --- a/drivers/video/bridge/Makefile +++ b/drivers/video/bridge/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_VIDEO_BRIDGE_NXP_PTN3460) += ptn3460.o obj-$(CONFIG_VIDEO_BRIDGE_ANALOGIX_ANX6345) += anx6345.o obj-$(CONFIG_VIDEO_BRIDGE_SOLOMON_SSD2825) += ssd2825.o obj-$(CONFIG_VIDEO_BRIDGE_TOSHIBA_TC358768) += tc358768.o +obj-$(CONFIG_VIDEO_BRIDGE_LVDS_CODEC) += lvds-codec.o diff --git a/drivers/video/bridge/lvds-codec.c b/drivers/video/bridge/lvds-codec.c new file mode 100644 index 00000000000..6cd8368a39e --- /dev/null +++ b/drivers/video/bridge/lvds-codec.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com> + * Loosely based on Linux lvds-codec.c driver + */ + +#include <dm.h> +#include <dm/ofnode_graph.h> +#include <log.h> +#include <panel.h> +#include <video_bridge.h> +#include <asm/gpio.h> +#include <power/regulator.h> + +struct lvds_codec_priv { + struct udevice *panel; + struct display_timing timing; + + struct gpio_desc powerdown_gpio; + struct udevice *power; +}; + +static int lvds_codec_attach(struct udevice *dev) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + + regulator_set_enable_if_allowed(priv->power, 1); + dm_gpio_set_value(&priv->powerdown_gpio, 0); + + return panel_enable_backlight(priv->panel); +} + +static int lvds_codec_set_panel(struct udevice *dev, int percent) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + + return panel_set_backlight(priv->panel, percent); +} + +static int lvds_codec_panel_timings(struct udevice *dev, + struct display_timing *timing) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + + memcpy(timing, &priv->timing, sizeof(*timing)); + + return 0; +} + +/* Function is purely for sandbox testing */ +static int lvds_codec_read_edid(struct udevice *dev, u8 *buf, int buf_size) +{ + return 0; +} + +static int lvds_codec_get_panel(struct udevice *dev) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + int i, ret; + + u32 num = ofnode_graph_get_port_count(dev_ofnode(dev)); + + for (i = 0; i < num; i++) { + ofnode remote = ofnode_graph_get_remote_node(dev_ofnode(dev), i, -1); + + ret = uclass_get_device_by_of_offset(UCLASS_PANEL, + ofnode_to_offset(remote), + &priv->panel); + if (!ret) + return 0; + } + + /* If this point is reached, no panels were found */ + return -ENODEV; +} + +static int lvds_codec_probe(struct udevice *dev) +{ + struct lvds_codec_priv *priv = dev_get_priv(dev); + int ret; + + ret = lvds_codec_get_panel(dev); + if (ret) { + log_debug("%s: cannot get panel: ret=%d\n", __func__, ret); + return log_ret(ret); + } + + panel_get_display_timing(priv->panel, &priv->timing); + + ret = gpio_request_by_name(dev, "powerdown-gpios", 0, + &priv->powerdown_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: could not get powerdown-gpios (%d)\n", __func__, ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + ret = device_get_supply_regulator(dev, "power-supply", &priv->power); + if (ret) { + log_debug("%s: power regulator error: %d\n", __func__, ret); + if (ret != -ENOENT) + return log_ret(ret); + } + + return 0; +} + +static const struct video_bridge_ops lvds_codec_ops = { + .attach = lvds_codec_attach, + .set_backlight = lvds_codec_set_panel, + .get_display_timing = lvds_codec_panel_timings, + .read_edid = lvds_codec_read_edid, +}; + +static const struct udevice_id lvds_codec_ids[] = { + { .compatible = "lvds-decoder" }, + { .compatible = "lvds-encoder" }, + { } +}; + +U_BOOT_DRIVER(lvds_codec) = { + .name = "lvds_codec", + .id = UCLASS_VIDEO_BRIDGE, + .of_match = lvds_codec_ids, + .ops = &lvds_codec_ops, + .probe = lvds_codec_probe, + .priv_auto = sizeof(struct lvds_codec_priv), +}; diff --git a/drivers/video/bridge/video-bridge-uclass.c b/drivers/video/bridge/video-bridge-uclass.c index 2084a2e03ee..1b8aa12b9e8 100644 --- a/drivers/video/bridge/video-bridge-uclass.c +++ b/drivers/video/bridge/video-bridge-uclass.c @@ -33,6 +33,17 @@ int video_bridge_attach(struct udevice *dev) return ops->attach(dev); } +int video_bridge_get_display_timing(struct udevice *dev, + struct display_timing *timings) +{ + struct video_bridge_ops *ops = video_bridge_get_ops(dev); + + if (!ops->get_display_timing) + return -ENOSYS; + + return ops->get_display_timing(dev, timings); +} + int video_bridge_check_attached(struct udevice *dev) { struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev); diff --git a/drivers/video/lp855x_backlight.c b/drivers/video/lp855x_backlight.c new file mode 100644 index 00000000000..5debc0aa453 --- /dev/null +++ b/drivers/video/lp855x_backlight.c @@ -0,0 +1,302 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2011 Texas Instruments + * Copyright (c) 2024 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#define LOG_CATEGORY UCLASS_PANEL_BACKLIGHT + +#include <malloc.h> +#include <backlight.h> +#include <dm.h> +#include <dm/devres.h> +#include <i2c.h> +#include <log.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <asm/gpio.h> +#include <power/regulator.h> + +#define LP855x_MIN_BRIGHTNESS 0x00 +#define LP855x_MAX_BRIGHTNESS 0xff + +/* LP8550/1/2/3/6 Registers */ +#define LP855X_BRIGHTNESS_CTRL 0x00 +#define LP855X_DEVICE_CTRL 0x01 +#define LP855X_EEPROM_START 0xa0 +#define LP855X_EEPROM_END 0xa7 +#define LP8556_EPROM_START 0x98 +#define LP8556_EPROM_END 0xaf + +/* LP8555/7 Registers */ +#define LP8557_BL_CMD 0x00 +#define LP8557_BL_MASK 0x01 +#define LP8557_BL_ON 0x01 +#define LP8557_BL_OFF 0x00 +#define LP8557_BRIGHTNESS_CTRL 0x04 +#define LP8557_CONFIG 0x10 +#define LP8555_EPROM_START 0x10 +#define LP8555_EPROM_END 0x7a +#define LP8557_EPROM_START 0x10 +#define LP8557_EPROM_END 0x1e + +struct lp855x_rom_data { + u8 addr; + u8 val; +}; + +struct lp855x_backlight_priv; + +/* + * struct lp855x_device_config + * @pre_init_device: init device function call before updating the brightness + * @reg_brightness: register address for brigthenss control + * @reg_devicectrl: register address for device control + * @post_init_device: late init device function call + */ +struct lp855x_device_config { + int (*pre_init_device)(struct udevice *dev); + u8 reg_brightness; + u8 reg_devicectrl; + u8 reg_eepromstart; + u8 reg_eepromend; + int (*post_init_device)(struct udevice *dev); +}; + +struct lp855x_backlight_priv { + struct udevice *supply; /* regulator for VDD input */ + struct udevice *enable; /* regulator for EN/VDDIO input */ + + u8 device_control; + u8 initial_brightness; + + int size_program; + struct lp855x_rom_data *rom_data; + struct lp855x_device_config *cfg; +}; + +static int lp855x_backlight_enable(struct udevice *dev) +{ + struct lp855x_backlight_priv *priv = dev_get_priv(dev); + int ret; + + ret = regulator_set_enable_if_allowed(priv->supply, 1); + if (ret) { + log_debug("%s: enabling power-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(priv->enable, 1); + if (ret) { + log_debug("%s: enabling enable-supply failed (%d)\n", + __func__, ret); + return ret; + } + mdelay(2); + + if (priv->cfg->pre_init_device) { + ret = priv->cfg->pre_init_device(dev); + if (ret) { + log_debug("%s: pre init device err: %d\n", + __func__, ret); + return ret; + } + } + + ret = dm_i2c_reg_write(dev, priv->cfg->reg_brightness, + priv->initial_brightness); + if (ret) + return ret; + + ret = dm_i2c_reg_write(dev, priv->cfg->reg_devicectrl, + priv->device_control); + if (ret) + return ret; + + if (priv->size_program > 0) { + int i; + u8 val, addr; + + for (i = 0; i < priv->size_program; i++) { + addr = priv->rom_data[i].addr; + val = priv->rom_data[i].val; + + if (addr < priv->cfg->reg_eepromstart && + addr > priv->cfg->reg_eepromend) + continue; + + ret = dm_i2c_reg_write(dev, addr, val); + if (ret) + return ret; + } + } + + if (priv->cfg->post_init_device) { + ret = priv->cfg->post_init_device(dev); + if (ret) { + log_debug("%s: post init device err: %d\n", + __func__, ret); + return ret; + } + } + + return 0; +} + +static int lp855x_backlight_set_brightness(struct udevice *dev, int percent) +{ + struct lp855x_backlight_priv *priv = dev_get_priv(dev); + + if (percent == BACKLIGHT_DEFAULT) + percent = priv->initial_brightness; + + if (percent < LP855x_MIN_BRIGHTNESS) + percent = LP855x_MIN_BRIGHTNESS; + + if (percent > LP855x_MAX_BRIGHTNESS) + percent = LP855x_MAX_BRIGHTNESS; + + /* Set brightness level */ + return dm_i2c_reg_write(dev, priv->cfg->reg_brightness, + percent); +} + +static int lp855x_backlight_probe(struct udevice *dev) +{ + struct lp855x_backlight_priv *priv = dev_get_priv(dev); + int rom_length, ret; + + if (device_get_uclass_id(dev->parent) != UCLASS_I2C) + return -EPROTONOSUPPORT; + + priv->cfg = (struct lp855x_device_config *)dev_get_driver_data(dev); + + dev_read_u8(dev, "dev-ctrl", &priv->device_control); + dev_read_u8(dev, "init-brt", &priv->initial_brightness); + + /* Fill ROM platform data if defined */ + rom_length = dev_get_child_count(dev); + if (rom_length > 0) { + struct lp855x_rom_data *rom; + ofnode child; + int i = 0; + + rom = devm_kcalloc(dev, rom_length, sizeof(*rom), GFP_KERNEL); + if (!rom) + return -ENOMEM; + + dev_for_each_subnode(child, dev) { + ofnode_read_u8(child, "rom-addr", &rom[i].addr); + ofnode_read_u8(child, "rom-val", &rom[i].val); + i++; + } + + priv->size_program = rom_length; + priv->rom_data = &rom[0]; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "power-supply", &priv->supply); + if (ret) { + log_err("%s: cannot get power-supply: ret = %d\n", __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "enable-supply", &priv->enable); + if (ret) { + log_err("%s: cannot get enable-supply: ret = %d\n", __func__, ret); + return ret; + } + + return 0; +} + +static const struct backlight_ops lp855x_backlight_ops = { + .enable = lp855x_backlight_enable, + .set_brightness = lp855x_backlight_set_brightness, +}; + +static int lp8556_bl_rst(struct udevice *dev) +{ + int ret; + + /* Reset backlight after updating EPROM settings */ + ret = dm_i2c_reg_clrset(dev, LP855X_DEVICE_CTRL, LP8557_BL_MASK, + LP8557_BL_OFF); + if (ret) + return ret; + + mdelay(10); + + return dm_i2c_reg_clrset(dev, LP855X_DEVICE_CTRL, LP8557_BL_MASK, + LP8557_BL_ON); +} + +static int lp8557_bl_off(struct udevice *dev) +{ + /* BL_ON = 0 before updating EPROM settings */ + return dm_i2c_reg_clrset(dev, LP8557_BL_CMD, LP8557_BL_MASK, + LP8557_BL_OFF); +} + +static int lp8557_bl_on(struct udevice *dev) +{ + /* BL_ON = 1 after updating EPROM settings */ + return dm_i2c_reg_clrset(dev, LP8557_BL_CMD, LP8557_BL_MASK, + LP8557_BL_ON); +} + +static struct lp855x_device_config lp855x_dev_cfg = { + .reg_brightness = LP855X_BRIGHTNESS_CTRL, + .reg_devicectrl = LP855X_DEVICE_CTRL, + .reg_eepromstart = LP855X_EEPROM_START, + .reg_eepromend = LP855X_EEPROM_END, +}; + +static struct lp855x_device_config lp8555_dev_cfg = { + .reg_brightness = LP8557_BRIGHTNESS_CTRL, + .reg_devicectrl = LP8557_CONFIG, + .reg_eepromstart = LP8555_EPROM_START, + .reg_eepromend = LP8555_EPROM_END, + .pre_init_device = lp8557_bl_off, + .post_init_device = lp8557_bl_on, +}; + +static struct lp855x_device_config lp8556_dev_cfg = { + .reg_brightness = LP855X_BRIGHTNESS_CTRL, + .reg_devicectrl = LP855X_DEVICE_CTRL, + .reg_eepromstart = LP8556_EPROM_START, + .reg_eepromend = LP8556_EPROM_END, + .post_init_device = lp8556_bl_rst, +}; + +static struct lp855x_device_config lp8557_dev_cfg = { + .reg_brightness = LP8557_BRIGHTNESS_CTRL, + .reg_devicectrl = LP8557_CONFIG, + .reg_eepromstart = LP8557_EPROM_START, + .reg_eepromend = LP8557_EPROM_END, + .pre_init_device = lp8557_bl_off, + .post_init_device = lp8557_bl_on, +}; + +static const struct udevice_id lp855x_backlight_ids[] = { + { .compatible = "ti,lp8550", .data = (ulong)&lp855x_dev_cfg }, + { .compatible = "ti,lp8551", .data = (ulong)&lp855x_dev_cfg }, + { .compatible = "ti,lp8552", .data = (ulong)&lp855x_dev_cfg }, + { .compatible = "ti,lp8553", .data = (ulong)&lp855x_dev_cfg }, + { .compatible = "ti,lp8555", .data = (ulong)&lp8555_dev_cfg }, + { .compatible = "ti,lp8556", .data = (ulong)&lp8556_dev_cfg }, + { .compatible = "ti,lp8557", .data = (ulong)&lp8557_dev_cfg }, + { } +}; + +U_BOOT_DRIVER(lp855x_backlight) = { + .name = "lp855x_backlight", + .id = UCLASS_PANEL_BACKLIGHT, + .of_match = lp855x_backlight_ids, + .probe = lp855x_backlight_probe, + .ops = &lp855x_backlight_ops, + .priv_auto = sizeof(struct lp855x_backlight_priv), +}; diff --git a/drivers/video/sharp-lq079l1sx01.c b/drivers/video/sharp-lq079l1sx01.c new file mode 100644 index 00000000000..a8197f40fc7 --- /dev/null +++ b/drivers/video/sharp-lq079l1sx01.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Sharp LQ079L1SX01 DSI panel driver + * + * Copyright (c) 2024 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <backlight.h> +#include <dm.h> +#include <panel.h> +#include <log.h> +#include <mipi_dsi.h> +#include <linux/delay.h> +#include <asm/gpio.h> +#include <power/regulator.h> + +struct sharp_lq079l1sx01_priv { + struct udevice *backlight; + struct udevice *panel_sec; + + struct udevice *avdd; + struct udevice *vddio; + struct udevice *vsp; + struct udevice *vsn; + + struct gpio_desc reset_gpio; +}; + +static struct display_timing default_timing = { + .pixelclock.typ = 215000000, + .hactive.typ = 1536, + .hfront_porch.typ = 136, + .hback_porch.typ = 28, + .hsync_len.typ = 28, + .vactive.typ = 2048, + .vfront_porch.typ = 14, + .vback_porch.typ = 8, + .vsync_len.typ = 2, +}; + +static int dcs_write_one(struct mipi_dsi_device *dsi, u8 cmd, u8 data) +{ + return mipi_dsi_dcs_write(dsi, cmd, &data, 1); +} + +static int sharp_lq079l1sx01_configure_link(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + struct mipi_dsi_device *dsi = plat->device; + int ret; + + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + log_debug("%s: failed to exit sleep mode %s: %d\n", + __func__, dev->parent->name, ret); + } + mdelay(120); + + ret = dcs_write_one(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, 0xff); + if (ret < 0) { + log_debug("%s: failed to SET_DISPLAY_BRIGHTNESS %s: %d\n", + __func__, dev->parent->name, ret); + } + ret = dcs_write_one(dsi, MIPI_DCS_WRITE_POWER_SAVE, 0x01); + if (ret < 0) { + log_debug("%s: failed to WRITE_POWER_SAVE %s: %d\n", + __func__, dev->parent->name, ret); + } + ret = dcs_write_one(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c); + if (ret < 0) { + log_debug("%s: failed to WRITE_CONTROL_DISPLAY %s: %d\n", + __func__, dev->parent->name, ret); + } + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) { + log_debug("%s: failed to set panel on %s: %d\n", + __func__, dev->parent->name, ret); + } + + return 0; +} + +static int sharp_lq079l1sx01_enable_backlight(struct udevice *dev) +{ + struct sharp_lq079l1sx01_priv *priv = dev_get_priv(dev); + + if (!priv->panel_sec) + return 0; + + sharp_lq079l1sx01_configure_link(dev); + sharp_lq079l1sx01_configure_link(priv->panel_sec); + + return 0; +} + +static int sharp_lq079l1sx01_set_backlight(struct udevice *dev, int percent) +{ + struct sharp_lq079l1sx01_priv *priv = dev_get_priv(dev); + int ret; + + if (!priv->panel_sec) + return 0; + + ret = backlight_enable(priv->backlight); + if (ret) + return ret; + + return backlight_set_brightness(priv->backlight, percent); +} + +static int sharp_lq079l1sx01_timings(struct udevice *dev, + struct display_timing *timing) +{ + memcpy(timing, &default_timing, sizeof(*timing)); + return 0; +} + +static int sharp_lq079l1sx01_of_to_plat(struct udevice *dev) +{ + struct sharp_lq079l1sx01_priv *priv = dev_get_priv(dev); + int ret; + + /* If node has no link2 it is secondary panel */ + if (!dev_read_bool(dev, "link2")) + return 0; + + ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, + "link2", &priv->panel_sec); + if (ret) { + log_debug("%s: cannot get secondary panel: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, + "backlight", &priv->backlight); + if (ret) { + log_debug("%s: cannot get backlight: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "avdd-supply", &priv->avdd); + if (ret) { + log_debug("%s: cannot get avdd-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vddio-supply", &priv->vddio); + if (ret) { + log_debug("%s: cannot get vddio-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vsp-supply", &priv->vsp); + if (ret) { + log_debug("%s: cannot get vsp-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, + "vsn-supply", &priv->vsn); + if (ret) { + log_debug("%s: cannot get vsn-supply: ret = %d\n", + __func__, ret); + return ret; + } + + ret = gpio_request_by_name(dev, "reset-gpios", 0, + &priv->reset_gpio, GPIOD_IS_OUT); + if (ret) { + log_debug("%s: cannot get reser-gpios (%d)\n", + __func__, ret); + return ret; + } + + return 0; +} + +static int sharp_lq079l1sx01_hw_init(struct udevice *dev) +{ + struct sharp_lq079l1sx01_priv *priv = dev_get_priv(dev); + int ret; + + if (!priv->panel_sec) + return 0; + + ret = regulator_set_enable_if_allowed(priv->vddio, 1); + if (ret) { + log_debug("%s: enabling vddio-supply failed (%d)\n", + __func__, ret); + return ret; + } + + ret = regulator_set_enable_if_allowed(priv->avdd, 1); + if (ret) { + log_debug("%s: enabling avdd-supply failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(12); + + ret = regulator_set_enable_if_allowed(priv->vsp, 1); + if (ret) { + log_debug("%s: enabling vsp-supply failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(12); + + ret = regulator_set_enable_if_allowed(priv->vsn, 1); + if (ret) { + log_debug("%s: enabling vsn-supply failed (%d)\n", + __func__, ret); + return ret; + } + + mdelay(24); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error disabling reset-gpios (%d)\n", + __func__, ret); + return ret; + } + udelay(3); + + ret = dm_gpio_set_value(&priv->reset_gpio, 1); + if (ret) { + log_debug("%s: error enabling reset-gpios (%d)\n", + __func__, ret); + return ret; + } + udelay(3); + + ret = dm_gpio_set_value(&priv->reset_gpio, 0); + if (ret) { + log_debug("%s: error disabling reset-gpios (%d)\n", + __func__, ret); + return ret; + } + mdelay(32); + + return 0; +} + +static int sharp_lq079l1sx01_probe(struct udevice *dev) +{ + struct mipi_dsi_panel_plat *plat = dev_get_plat(dev); + + /* fill characteristics of DSI data link */ + plat->lanes = 4; + plat->format = MIPI_DSI_FMT_RGB888; + plat->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_LPM; + + return sharp_lq079l1sx01_hw_init(dev); +} + +static const struct panel_ops sharp_lq079l1sx01_ops = { + .enable_backlight = sharp_lq079l1sx01_enable_backlight, + .set_backlight = sharp_lq079l1sx01_set_backlight, + .get_display_timing = sharp_lq079l1sx01_timings, +}; + +static const struct udevice_id sharp_lq079l1sx01_ids[] = { + { .compatible = "sharp,lq079l1sx01" }, + { } +}; + +U_BOOT_DRIVER(sharp_lq079l1sx01) = { + .name = "sharp_lq079l1sx01", + .id = UCLASS_PANEL, + .of_match = sharp_lq079l1sx01_ids, + .ops = &sharp_lq079l1sx01_ops, + .of_to_plat = sharp_lq079l1sx01_of_to_plat, + .probe = sharp_lq079l1sx01_probe, + .plat_auto = sizeof(struct mipi_dsi_panel_plat), + .priv_auto = sizeof(struct sharp_lq079l1sx01_priv), +}; diff --git a/drivers/video/tegra20/tegra-dc.c b/drivers/video/tegra20/tegra-dc.c index d24aa375b39..16a2b5281bf 100644 --- a/drivers/video/tegra20/tegra-dc.c +++ b/drivers/video/tegra20/tegra-dc.c @@ -5,24 +5,16 @@ #include <backlight.h> #include <cpu_func.h> +#include <clk.h> #include <dm.h> #include <fdtdec.h> #include <log.h> #include <panel.h> -#include <part.h> -#include <pwm.h> #include <video.h> -#include <asm/cache.h> -#include <asm/global_data.h> #include <asm/system.h> -#include <asm/gpio.h> #include <asm/io.h> - #include <asm/arch/clock.h> -#include <asm/arch/funcmux.h> -#include <asm/arch/pinmux.h> #include <asm/arch/powergate.h> -#include <asm/arch/pwm.h> #include "tegra-dc.h" @@ -44,7 +36,8 @@ struct tegra_lcd_priv { const struct tegra_dc_soc_info *soc; fdt_addr_t frame_buffer; /* Address of frame buffer */ unsigned pixel_clock; /* Pixel clock in Hz */ - int dc_clk[2]; /* Contains clk and its parent */ + struct clk *clk; + struct clk *clk_parent; ulong scdiv; /* Clock divider used by disp_clk_ctrl */ bool rotation; /* 180 degree panel turn */ int pipe; /* DC controller: 0 for A, 1 for B */ @@ -144,10 +137,9 @@ static int update_display_mode(struct tegra_lcd_priv *priv) val |= DATA_ALIGNMENT_MSB << DATA_ALIGNMENT_SHIFT; val |= DATA_ORDER_RED_BLUE << DATA_ORDER_SHIFT; writel(val, &disp->disp_interface_ctrl); - } - if (priv->soc->has_rgb) writel(0x00010001, &disp->shift_clk_opt); + } val = PIXEL_CLK_DIVIDER_PCD1 << PIXEL_CLK_DIVIDER_SHIFT; val |= priv->scdiv << SHIFT_CLK_DIVIDER_SHIFT; @@ -267,7 +259,9 @@ static int setup_window(struct tegra_lcd_priv *priv, win->out_h = priv->height; win->phys_addr = priv->frame_buffer; win->stride = priv->width * (1 << priv->log2_bpp) / 8; - debug("%s: depth = %d\n", __func__, priv->log2_bpp); + + log_debug("%s: depth = %d\n", __func__, priv->log2_bpp); + switch (priv->log2_bpp) { case VIDEO_BPP32: win->fmt = COLOR_DEPTH_R8G8B8A8; @@ -279,7 +273,7 @@ static int setup_window(struct tegra_lcd_priv *priv, break; default: - debug("Unsupported LCD bit depth"); + log_debug("Unsupported LCD bit depth\n"); return -1; } @@ -301,7 +295,8 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, void *default_lcd_base) { struct disp_ctl_win window; - unsigned long rate = clock_get_rate(priv->dc_clk[1]); + unsigned long rate = clk_get_rate(priv->clk_parent); + int ret; priv->frame_buffer = (u32)default_lcd_base; @@ -309,14 +304,9 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, * We halve the rate if DISP1 parent is PLLD, since actual parent * is plld_out0 which is PLLD divided by 2. */ - if (priv->dc_clk[1] == CLOCK_ID_DISPLAY) - rate /= 2; - -#ifndef CONFIG_TEGRA20 - /* PLLD2 obeys same rules as PLLD but it is present only on T30+ */ - if (priv->dc_clk[1] == CLOCK_ID_DISPLAY2) + if (priv->clk_parent->id == CLOCK_ID_DISPLAY || + priv->clk_parent->id == CLOCK_ID_DISPLAY2) rate /= 2; -#endif /* * The pixel clock divider is in 7.1 format (where the bottom bit @@ -327,14 +317,14 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, if (!priv->scdiv) priv->scdiv = ((rate * 2 + priv->pixel_clock / 2) / priv->pixel_clock) - 2; - debug("Display clock %lu, divider %lu\n", rate, priv->scdiv); + log_debug("Display clock %lu, divider %lu\n", rate, priv->scdiv); /* * HOST1X is init by default at 150MHz with PLLC as parent */ clock_start_periph_pll(PERIPH_ID_HOST1X, CLOCK_ID_CGENERAL, 150 * 1000000); - clock_start_periph_pll(priv->dc_clk[0], priv->dc_clk[1], + clock_start_periph_pll(priv->clk->id, priv->clk_parent->id, rate); basic_init(&priv->dc->cmd); @@ -348,8 +338,9 @@ static int tegra_display_probe(struct tegra_lcd_priv *priv, if (priv->pixel_clock) update_display_mode(priv); - if (setup_window(priv, &window)) - return -1; + ret = setup_window(priv, &window); + if (ret) + return ret; update_window(priv, &window); @@ -364,10 +355,6 @@ static int tegra_lcd_probe(struct udevice *dev) int ret; /* Initialize the Tegra display controller */ -#ifdef CONFIG_TEGRA20 - funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); -#endif - if (priv->soc->has_pgate) { uint powergate; @@ -378,14 +365,14 @@ static int tegra_lcd_probe(struct udevice *dev) ret = tegra_powergate_power_off(powergate); if (ret < 0) { - log_err("failed to power off DISP gate: %d", ret); + log_debug("failed to power off DISP gate: %d", ret); return ret; } ret = tegra_powergate_sequence_power_up(powergate, - priv->dc_clk[0]); + priv->clk->id); if (ret < 0) { - log_err("failed to power up DISP gate: %d", ret); + log_debug("failed to power up DISP gate: %d", ret); return ret; } } @@ -402,19 +389,15 @@ static int tegra_lcd_probe(struct udevice *dev) memset((u8 *)plat->base, 0, plat->size); flush_dcache_all(); - if (tegra_display_probe(priv, (void *)plat->base)) { - debug("%s: Failed to probe display driver\n", __func__); - return -1; + ret = tegra_display_probe(priv, (void *)plat->base); + if (ret) { + log_debug("%s: Failed to probe display driver\n", __func__); + return ret; } -#ifdef CONFIG_TEGRA20 - pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM); - pinmux_tristate_disable(PMUX_PINGRP_GPU); -#endif - ret = panel_enable_backlight(priv->panel); if (ret) { - debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret); + log_debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret); return ret; } @@ -427,8 +410,8 @@ static int tegra_lcd_probe(struct udevice *dev) uc_priv->xsize = priv->width; uc_priv->ysize = priv->height; uc_priv->bpix = priv->log2_bpp; - debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer, - plat->size); + log_debug("LCD frame buffer at %08x, size %x\n", priv->frame_buffer, + plat->size); return panel_set_backlight(priv->panel, BACKLIGHT_DEFAULT); } @@ -445,17 +428,24 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) priv->dc = (struct dc_ctlr *)dev_read_addr_ptr(dev); if (!priv->dc) { - debug("%s: No display controller address\n", __func__); + log_debug("%s: No display controller address\n", __func__); return -EINVAL; } priv->soc = (struct tegra_dc_soc_info *)dev_get_driver_data(dev); - ret = clock_decode_pair(dev, priv->dc_clk); - if (ret < 0) { - debug("%s: Cannot decode clocks for '%s' (ret = %d)\n", - __func__, dev->name, ret); - return -EINVAL; + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + log_debug("%s: Could not get DC clock: %ld\n", + __func__, PTR_ERR(priv->clk)); + return PTR_ERR(priv->clk); + } + + priv->clk_parent = devm_clk_get(dev, "parent"); + if (IS_ERR(priv->clk_parent)) { + log_debug("%s: Could not get DC clock parent: %ld\n", + __func__, PTR_ERR(priv->clk_parent)); + return PTR_ERR(priv->clk_parent); } priv->rotation = dev_read_bool(dev, "nvidia,180-rotation"); @@ -463,8 +453,8 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) rgb = fdt_subnode_offset(blob, node, "rgb"); if (rgb < 0) { - debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", - __func__, dev->name, rgb); + log_debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", + __func__, dev->name, rgb); return -EINVAL; } @@ -474,15 +464,15 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) */ panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); if (panel_node < 0) { - debug("%s: Cannot find panel information\n", __func__); + log_debug("%s: Cannot find panel information\n", __func__); return -EINVAL; } ret = uclass_get_device_by_of_offset(UCLASS_PANEL, panel_node, &priv->panel); if (ret) { - debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__, - dev->name, ret); + log_debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__, + dev->name, ret); return ret; } @@ -500,8 +490,8 @@ static int tegra_lcd_of_to_plat(struct udevice *dev) if (ret) { ret = fdtdec_decode_display_timing(blob, rgb, 0, &priv->timing); if (ret) { - debug("%s: Cannot read display timing for '%s' (ret=%d)\n", - __func__, dev->name, ret); + log_debug("%s: Cannot read display timing for '%s' (ret=%d)\n", + __func__, dev->name, ret); return -EINVAL; } } @@ -564,6 +554,9 @@ static const struct udevice_id tegra_lcd_ids[] = { .compatible = "nvidia,tegra114-dc", .data = (ulong)&tegra114_dc_soc_info }, { + .compatible = "nvidia,tegra124-dc", + .data = (ulong)&tegra114_dc_soc_info + }, { /* sentinel */ } }; diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index 6327266dd22..9f39ac7589b 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -5,6 +5,7 @@ */ #include <dm.h> +#include <clk.h> #include <log.h> #include <misc.h> #include <mipi_display.h> @@ -46,10 +47,13 @@ struct tegra_dsi_priv { enum tegra_dsi_format format; - int dsi_clk; + struct clk *clk; + struct clk *clk_parent; + int video_fifo_depth; int host_fifo_depth; + u32 calibration_pads; u32 version; /* for ganged-mode support */ @@ -515,8 +519,9 @@ static void tegra_dsi_pad_calibrate(struct dsi_pad_ctrl_reg *pad) writel(value, TEGRA_VI_BASE + (CSI_CIL_PAD_CONFIG << 2)); } -static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv) +static void tegra_dsi_mipi_calibrate(struct udevice *dev) { + struct tegra_dsi_priv *priv = dev_get_priv(dev); struct dsi_pad_ctrl_reg *pad = &priv->dsi->pad; u32 value; int ret; @@ -545,15 +550,20 @@ static void tegra_dsi_mipi_calibrate(struct tegra_dsi_priv *priv) DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); writel(value, &pad->pad_ctrl_3); - ret = misc_write(priv->mipi, 0, NULL, 0); + ret = misc_write(priv->mipi, priv->calibration_pads, NULL, 0); if (ret) log_debug("%s: MIPI calibration failed %d\n", __func__, ret); + + if (priv->slave) + tegra_dsi_mipi_calibrate(priv->slave); } -static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout, +static void tegra_dsi_set_timeout(struct udevice *dev, unsigned long bclk, unsigned int vrefresh) { + struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct dsi_timeout_reg *rtimeout = &priv->dsi->timeout; unsigned int timeout; u32 value; @@ -569,12 +579,17 @@ static void tegra_dsi_set_timeout(struct dsi_timeout_reg *rtimeout, value = DSI_TALLY_TA(0) | DSI_TALLY_LRX(0) | DSI_TALLY_HTX(0); writel(value, &rtimeout->dsi_to_tally); + + if (priv->slave) + tegra_dsi_set_timeout(priv->slave, bclk, vrefresh); } -static void tegra_dsi_set_phy_timing(struct dsi_timing_reg *ptiming, +static void tegra_dsi_set_phy_timing(struct udevice *dev, unsigned long period, const struct mipi_dphy_timing *dphy_timing) { + struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct dsi_timing_reg *ptiming = &priv->dsi->ptiming; u32 value; value = DSI_TIMING_FIELD(dphy_timing->hsexit, period, 1) << 24 | @@ -598,6 +613,31 @@ static void tegra_dsi_set_phy_timing(struct dsi_timing_reg *ptiming, DSI_TIMING_FIELD(dphy_timing->tasure, period, 1) << 8 | DSI_TIMING_FIELD(dphy_timing->tago, period, 1); writel(value, &ptiming->dsi_bta_timing); + + if (priv->slave) + tegra_dsi_set_phy_timing(priv->slave, period, dphy_timing); +} + +static u32 tegra_dsi_get_lanes(struct udevice *dev) +{ + struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct mipi_dsi_device *device = &priv->device; + + if (priv->master) { + struct tegra_dsi_priv *mpriv = dev_get_priv(priv->master); + struct mipi_dsi_device *mdevice = &mpriv->device; + + return mdevice->lanes + device->lanes; + } + + if (priv->slave) { + struct tegra_dsi_priv *spriv = dev_get_priv(priv->slave); + struct mipi_dsi_device *sdevice = &spriv->device; + + return device->lanes + sdevice->lanes; + } + + return device->lanes; } static void tegra_dsi_ganged_enable(struct udevice *dev, unsigned int start, @@ -611,7 +651,7 @@ static void tegra_dsi_ganged_enable(struct udevice *dev, unsigned int start, writel(DSI_GANGED_MODE_CONTROL_ENABLE, &ganged->ganged_mode_ctrl); } -static void tegra_dsi_configure(struct udevice *dev, +static void tegra_dsi_configure(struct udevice *dev, unsigned int pipe, unsigned long mode_flags) { struct tegra_dsi_priv *priv = dev_get_priv(dev); @@ -642,7 +682,7 @@ static void tegra_dsi_configure(struct udevice *dev, value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(priv->format) | DSI_CONTROL_LANES(device->lanes - 1) | - DSI_CONTROL_SOURCE(0); + DSI_CONTROL_SOURCE(pipe); writel(value, &misc->dsi_ctrl); writel(priv->video_fifo_depth, &misc->dsi_max_threshold); @@ -680,12 +720,19 @@ static void tegra_dsi_configure(struct udevice *dev, /* horizontal back porch */ hbp = timing->hback_porch.typ * mul / div; - if ((mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0) - hbp += hsw; - /* horizontal front porch */ hfp = timing->hfront_porch.typ * mul / div; + if (priv->master || priv->slave) { + hact /= 2; + hsw /= 2; + hbp = hbp / 2 - 1; + hfp /= 2; + } + + if ((mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) == 0) + hbp += hsw; + /* subtract packet overhead */ hsw -= 10; hbp -= 14; @@ -695,9 +742,6 @@ static void tegra_dsi_configure(struct udevice *dev, writel(hact << 16 | hbp, &len->dsi_pkt_len_2_3); writel(hfp, &len->dsi_pkt_len_4_5); writel(0x0f0f << 16, &len->dsi_pkt_len_6_7); - - /* set SOL delay (for non-burst mode only) */ - writel(8 * mul / div, &misc->dsi_sol_delay); } else { if (priv->master || priv->slave) { /* @@ -717,32 +761,33 @@ static void tegra_dsi_configure(struct udevice *dev, value = MIPI_DCS_WRITE_MEMORY_START << 8 | MIPI_DCS_WRITE_MEMORY_CONTINUE; writel(value, &len->dsi_dcs_cmds); + } - /* set SOL delay */ - if (priv->master || priv->slave) { - unsigned long delay, bclk, bclk_ganged; - unsigned int lanes = device->lanes; - unsigned long htotal = timing->hactive.typ + timing->hfront_porch.typ + - timing->hback_porch.typ + timing->hsync_len.typ; - - /* SOL to valid, valid to FIFO and FIFO write delay */ - delay = 4 + 4 + 2; - delay = DIV_ROUND_UP(delay * mul, div * lanes); - /* FIFO read delay */ - delay = delay + 6; - - bclk = DIV_ROUND_UP(htotal * mul, div * lanes); - bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes); - value = bclk - bclk_ganged + delay + 20; - } else { - /* TODO: revisit for non-ganged mode */ - value = 8 * mul / div; - } - - writel(value, &misc->dsi_sol_delay); + /* set SOL delay */ + if (priv->master || priv->slave) { + unsigned long delay, bclk, bclk_ganged; + unsigned int lanes = tegra_dsi_get_lanes(dev); + unsigned long htotal = timing->hactive.typ + timing->hfront_porch.typ + + timing->hback_porch.typ + timing->hsync_len.typ; + + /* SOL to valid, valid to FIFO and FIFO write delay */ + delay = 4 + 4 + 2; + delay = DIV_ROUND_UP(delay * mul, div * lanes); + /* FIFO read delay */ + delay = delay + 6; + + bclk = DIV_ROUND_UP(htotal * mul, div * lanes); + bclk_ganged = DIV_ROUND_UP(bclk * lanes / 2, lanes); + value = bclk - bclk_ganged + delay + 20; + } else { + /* set SOL delay (for non-burst mode only) */ + value = 8 * mul / div; } + writel(value, &misc->dsi_sol_delay); + if (priv->slave) { + tegra_dsi_configure(priv->slave, pipe, mode_flags); /* * TODO: Support modes other than symmetrical left-right * split. @@ -753,15 +798,31 @@ static void tegra_dsi_configure(struct udevice *dev, } } +static void tegra_dsi_enable(struct udevice *dev) +{ + struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct dsi_misc_reg *misc = &priv->dsi->misc; + u32 value; + + /* enable DSI controller */ + value = readl(&misc->dsi_pwr_ctrl); + value |= DSI_POWER_CONTROL_ENABLE; + writel(value, &misc->dsi_pwr_ctrl); + + if (priv->slave) + tegra_dsi_enable(priv->slave); +} + static int tegra_dsi_encoder_enable(struct udevice *dev) { struct tegra_dsi_priv *priv = dev_get_priv(dev); + struct tegra_dc_plat *dc_plat = dev_get_plat(dev); struct mipi_dsi_device *device = &priv->device; struct display_timing *timing = &priv->timing; struct dsi_misc_reg *misc = &priv->dsi->misc; unsigned int mul, div; unsigned long bclk, plld, period; - u32 value; + u32 value, lanes; int ret; /* If for some reasone DSI is enabled then it needs to @@ -780,16 +841,17 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) writel(0, &misc->int_enable); if (priv->version) - tegra_dsi_mipi_calibrate(priv); + tegra_dsi_mipi_calibrate(dev); else tegra_dsi_pad_calibrate(&priv->dsi->pad); tegra_dsi_get_muldiv(device->format, &mul, &div); /* compute byte clock */ - bclk = (timing->pixelclock.typ * mul) / (div * device->lanes); + lanes = tegra_dsi_get_lanes(dev); + bclk = (timing->pixelclock.typ * mul) / (div * lanes); - tegra_dsi_set_timeout(&priv->dsi->timeout, bclk, 60); + tegra_dsi_set_timeout(dev, bclk, 60); /* * Compute bit clock and round up to the next MHz. @@ -813,25 +875,18 @@ static int tegra_dsi_encoder_enable(struct udevice *dev) * The D-PHY timing fields are expressed in byte-clock cycles, so * multiply the period by 8. */ - tegra_dsi_set_phy_timing(&priv->dsi->ptiming, - period * 8, &priv->dphy_timing); + tegra_dsi_set_phy_timing(dev, period * 8, &priv->dphy_timing); /* Perform panel HW setup */ ret = panel_enable_backlight(priv->panel); if (ret) return ret; - tegra_dsi_configure(dev, device->mode_flags); + tegra_dsi_configure(dev, dc_plat->pipe, device->mode_flags); tegra_dc_enable_controller(dev); - /* enable DSI controller */ - value = readl(&misc->dsi_pwr_ctrl); - value |= DSI_POWER_CONTROL_ENABLE; - writel(value, &misc->dsi_pwr_ctrl); - - if (priv->slave) - tegra_dsi_encoder_enable(priv->slave); + tegra_dsi_enable(dev); return 0; } @@ -859,21 +914,35 @@ static void tegra_dsi_init_clocks(struct udevice *dev) struct tegra_dsi_priv *priv = dev_get_priv(dev); struct tegra_dc_plat *dc_plat = dev_get_plat(dev); struct mipi_dsi_device *device = &priv->device; - unsigned int mul, div; + unsigned int mul, div, lanes; unsigned long bclk, plld; - if (!priv->slave) { + /* Switch parents of DSI clocks in case of not standard parent */ + if (priv->clk->id == PERIPH_ID_DSI && + priv->clk_parent->id == CLOCK_ID_DISPLAY2) { + /* Change DSIA clock parent to PLLD2 */ + struct clk_rst_ctlr *clkrst = + (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; + + /* DSIA_CLK_SRC */ + setbits_le32(&clkrst->crc_pll[CLOCK_ID_DISPLAY].pll_base, + BIT(25)); + } + + if (priv->clk->id == PERIPH_ID_DSIB && + priv->clk_parent->id == CLOCK_ID_DISPLAY) { /* Change DSIB clock parent to match DSIA */ struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - clrbits_le32(&clkrst->plld2.pll_base, BIT(25)); /* DSIB_CLK_SRC */ + /* DSIB_CLK_SRC */ + clrbits_le32(&clkrst->plld2.pll_base, BIT(25)); } tegra_dsi_get_muldiv(device->format, &mul, &div); - bclk = (priv->timing.pixelclock.typ * mul) / - (div * device->lanes); + lanes = tegra_dsi_get_lanes(dev); + bclk = (priv->timing.pixelclock.typ * mul) / (div * lanes); plld = DIV_ROUND_UP(bclk * 8, USEC_PER_SEC); @@ -893,16 +962,16 @@ static void tegra_dsi_init_clocks(struct udevice *dev) switch (clock_get_osc_freq()) { case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ case CLOCK_OSC_FREQ_48_0: /* OSC is 48Mhz */ - clock_set_rate(CLOCK_ID_DISPLAY, plld, 12, 0, 8); + clock_set_rate(priv->clk_parent->id, plld, 12, 0, 8); break; case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ - clock_set_rate(CLOCK_ID_DISPLAY, plld, 26, 0, 8); + clock_set_rate(priv->clk_parent->id, plld, 26, 0, 8); break; case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ case CLOCK_OSC_FREQ_16_8: /* OSC is 16.8Mhz */ - clock_set_rate(CLOCK_ID_DISPLAY, plld, 13, 0, 8); + clock_set_rate(priv->clk_parent->id, plld, 13, 0, 8); break; case CLOCK_OSC_FREQ_19_2: @@ -914,11 +983,7 @@ static void tegra_dsi_init_clocks(struct udevice *dev) break; } - priv->dsi_clk = clock_decode_periph_id(dev); - - clock_enable(priv->dsi_clk); - udelay(2); - reset_set_enable(priv->dsi_clk, 0); + clk_enable(priv->clk); } static int tegra_dsi_ganged_probe(struct udevice *dev) @@ -955,6 +1020,20 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) return -EINVAL; } + priv->clk = devm_clk_get(dev, NULL); + if (IS_ERR(priv->clk)) { + log_debug("%s: Could not get DSI clock: %ld\n", + __func__, PTR_ERR(priv->clk)); + return PTR_ERR(priv->clk); + } + + priv->clk_parent = devm_clk_get(dev, "parent"); + if (IS_ERR(priv->clk_parent)) { + log_debug("%s: Could not get DSI clock parent: %ld\n", + __func__, PTR_ERR(priv->clk_parent)); + return PTR_ERR(priv->clk_parent); + } + priv->video_fifo_depth = 1920; priv->host_fifo_depth = 64; @@ -973,10 +1052,22 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) debug("%s: Cannot get avdd-dsi-csi-supply: error %d\n", __func__, ret); - ret = uclass_get_device_by_phandle(UCLASS_PANEL, dev, - "panel", &priv->panel); + /* Check all DSI children */ + device_foreach_child(priv->panel, dev) { + if (device_get_uclass_id(priv->panel) == UCLASS_PANEL) + break; + } + + /* if loop exits without panel device return error */ + if (device_get_uclass_id(priv->panel) != UCLASS_PANEL) { + log_debug("%s: panel not found, ret %d\n", __func__, ret); + return -EINVAL; + } + + ret = uclass_get_device_by_ofnode(UCLASS_PANEL, dev_ofnode(priv->panel), + &priv->panel); if (ret) { - printf("%s: Cannot get panel: error %d\n", __func__, ret); + log_debug("%s: Cannot get panel: error %d\n", __func__, ret); return log_ret(ret); } @@ -988,6 +1079,14 @@ static int tegra_dsi_bridge_probe(struct udevice *dev) log_debug("%s: cannot get MIPI: error %d\n", __func__, ret); return ret; } + + ret = dev_read_u32_index(dev, "nvidia,mipi-calibrate", 1, + &priv->calibration_pads); + if (ret) { + log_debug("%s: cannot get calibration pads: error %d\n", + __func__, ret); + return ret; + } } panel_get_display_timing(priv->panel, &priv->timing); @@ -1028,6 +1127,7 @@ static const struct panel_ops tegra_dsi_bridge_ops = { static const struct udevice_id tegra_dsi_bridge_ids[] = { { .compatible = "nvidia,tegra30-dsi", .data = DSI_V0 }, { .compatible = "nvidia,tegra114-dsi", .data = DSI_V1 }, + { .compatible = "nvidia,tegra124-dsi", .data = DSI_V1 }, { } }; @@ -1036,6 +1136,7 @@ U_BOOT_DRIVER(tegra_dsi) = { .id = UCLASS_PANEL, .of_match = tegra_dsi_bridge_ids, .ops = &tegra_dsi_bridge_ops, + .bind = dm_scan_fdt_dev, .probe = tegra_dsi_bridge_probe, .plat_auto = sizeof(struct tegra_dc_plat), .priv_auto = sizeof(struct tegra_dsi_priv), diff --git a/drivers/video/tegra20/tegra-mipi.c b/drivers/video/tegra20/tegra-mipi.c index 2df3c1a9942..a4f4343d008 100644 --- a/drivers/video/tegra20/tegra-mipi.c +++ b/drivers/video/tegra20/tegra-mipi.c @@ -10,9 +10,10 @@ #include <linux/delay.h> #include <linux/iopoll.h> +#include <asm/arch/clock.h> #include <asm/io.h> -/* MIPI control registers 0x00 ~ 0x60 */ +/* MIPI control registers 0x00 ~ 0x74 */ struct mipi_ctlr { uint mipi_cal_ctrl; uint mipi_cal_autocal_ctrl; @@ -38,8 +39,17 @@ struct mipi_ctlr { uint mipi_cal_bias_pad_cfg0; uint mipi_cal_bias_pad_cfg1; uint mipi_cal_bias_pad_cfg2; + + uint mipi_cal_dsia_config_2; + uint mipi_cal_dsib_config_2; + uint mipi_cal_cilc_config_2; + uint mipi_cal_cild_config_2; + uint mipi_cal_csie_config_2; }; +#define MIPI_DSIA_PADS 0x60 +#define MIPI_DSIB_PADS 0x180 + #define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26) #define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24) #define MIPI_CAL_CTRL_CLKEN_OVR BIT(4) @@ -64,26 +74,25 @@ struct mipi_ctlr { #define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4) #define MIPI_CAL_BIAS_PAD_PDVREG BIT(1) +#define MIPI_CAL_HSCLKPDOSDSI(x) (((x) & 0x1f) << 8) +#define MIPI_CAL_HSCLKPUOSDSI(x) (((x) & 0x1f) << 0) + struct tegra_mipi_priv { struct mipi_ctlr *mipi; struct clk *mipi_cal; + u32 version; }; -static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf, - int size) +enum { + T114, + T124, +}; + +static void tegra114_mipi_pads_cal(struct tegra_mipi_priv *priv, + int calibration_pads) { - struct tegra_mipi_priv *priv = dev_get_priv(dev); u32 value; - value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) | - MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0); - writel(value, &priv->mipi->mipi_cal_bias_pad_cfg1); - - value = readl(&priv->mipi->mipi_cal_bias_pad_cfg2); - value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); - value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); - writel(value, &priv->mipi->mipi_cal_bias_pad_cfg2); - value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x4) | MIPI_CAL_TERMOS(0x5); @@ -99,6 +108,95 @@ static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf value = readl(&priv->mipi->mipi_cal_config_dsid); value &= ~(MIPI_CAL_SEL(0x1)); writel(value, &priv->mipi->mipi_cal_config_dsid); +} + +static void tegra124_mipi_pads_cal(struct tegra_mipi_priv *priv, + int calibration_pads) +{ + u32 value; + + /* Calibrate DSI-A */ + if (calibration_pads == MIPI_DSIA_PADS) { + printf("Calibrating DSI-A pads\n"); + + value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x0) | + MIPI_CAL_TERMOS(0x0); + writel(value, &priv->mipi->mipi_cal_config_dsia); + writel(value, &priv->mipi->mipi_cal_config_dsib); + + value = MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSCLKPDOSDSI(0x1) | + MIPI_CAL_HSCLKPUOSDSI(0x2); + writel(value, &priv->mipi->mipi_cal_dsia_config_2); + writel(value, &priv->mipi->mipi_cal_dsib_config_2); + + /* Deselect PAD C */ + value = readl(&priv->mipi->mipi_cal_cilc_config_2); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, &priv->mipi->mipi_cal_cilc_config_2); + + /* Deselect PAD D */ + value = readl(&priv->mipi->mipi_cal_cild_config_2); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, &priv->mipi->mipi_cal_cild_config_2); + } + + /* Calibrate DSI-B */ + if (calibration_pads == MIPI_DSIB_PADS) { + printf("Calibrating DSI-B pads\n"); + + value = MIPI_CAL_OVERIDE(0x0) | MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSPDOS(0x0) | MIPI_CAL_HSPUOS(0x0) | + MIPI_CAL_TERMOS(0x0); + writel(value, &priv->mipi->mipi_cal_config_csic); + writel(value, &priv->mipi->mipi_cal_config_csid); + + value = MIPI_CAL_SEL(0x1) | + MIPI_CAL_HSCLKPDOSDSI(0x1) | + MIPI_CAL_HSCLKPUOSDSI(0x2); + writel(value, &priv->mipi->mipi_cal_cilc_config_2); + writel(value, &priv->mipi->mipi_cal_cild_config_2); + + /* Deselect PAD A */ + value = readl(&priv->mipi->mipi_cal_dsia_config_2); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, &priv->mipi->mipi_cal_dsia_config_2); + + /* Deselect PAD B */ + value = readl(&priv->mipi->mipi_cal_dsib_config_2); + value &= ~(MIPI_CAL_SEL(0x1)); + writel(value, &priv->mipi->mipi_cal_dsib_config_2); + } +} + +static int tegra_mipi_calibrate(struct udevice *dev, int offset, const void *buf, + int size) +{ + struct tegra_mipi_priv *priv = dev_get_priv(dev); + u32 value; + + value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(0x2) | + MIPI_CAL_BIAS_PAD_DRV_UP_REF(0x0); + writel(value, &priv->mipi->mipi_cal_bias_pad_cfg1); + + value = readl(&priv->mipi->mipi_cal_bias_pad_cfg2); + value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7); + value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7); + writel(value, &priv->mipi->mipi_cal_bias_pad_cfg2); + + switch (priv->version) { + case T114: + tegra114_mipi_pads_cal(priv, offset); + break; + + case T124: + tegra124_mipi_pads_cal(priv, offset); + break; + + default: + return -EINVAL; + } value = readl(&priv->mipi->mipi_cal_ctrl); value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf); @@ -134,6 +232,11 @@ static int tegra_mipi_enable(struct udevice *dev, bool val) struct tegra_mipi_priv *priv = dev_get_priv(dev); u32 value; + reset_set_enable(priv->mipi_cal->id, 1); + mdelay(100); + reset_set_enable(priv->mipi_cal->id, 0); + mdelay(1); + clk_enable(priv->mipi_cal); value = readl(&priv->mipi->mipi_cal_bias_pad_cfg0); @@ -157,6 +260,8 @@ static int tegra_mipi_probe(struct udevice *dev) { struct tegra_mipi_priv *priv = dev_get_priv(dev); + priv->version = dev_get_driver_data(dev); + priv->mipi = (struct mipi_ctlr *)dev_read_addr_ptr(dev); if (!priv->mipi) { log_debug("%s: no MIPI controller address\n", __func__); @@ -174,7 +279,8 @@ static int tegra_mipi_probe(struct udevice *dev) } static const struct udevice_id tegra_mipi_ids[] = { - { .compatible = "nvidia,tegra114-mipi" }, + { .compatible = "nvidia,tegra114-mipi", .data = T114 }, + { .compatible = "nvidia,tegra124-mipi", .data = T124 }, { } }; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index b39b2546e5c..1bb67f50352 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -95,6 +95,15 @@ config WDT_APPLE The watchdog will perform a full SoC reset resulting in a reboot of the entire system. +config WDT_ADI + bool "Analog Devices watchdog timer support" + select WDT + select SPL_WDT if SPL + depends on ARCH_SC5XX + help + Enable this to support Watchdog Timer on ADI SC57X, SC58X, SC59X, + and SC59X_64 processors + config WDT_ARMADA_37XX bool "Marvell Armada 37xx watchdog timer support" depends on WDT && ARMADA_3700 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 9b6b1a8e8ad..e6bd4c587af 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -53,3 +53,4 @@ obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o obj-$(CONFIG_WDT_SUNXI) += sunxi_wdt.o obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o obj-$(CONFIG_WDT_XILINX) += xilinx_wwdt.o +obj-$(CONFIG_WDT_ADI) += adi_wdt.o diff --git a/drivers/watchdog/adi_wdt.c b/drivers/watchdog/adi_wdt.c new file mode 100644 index 00000000000..6f5b3d5d042 --- /dev/null +++ b/drivers/watchdog/adi_wdt.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Converted to driver model by Nathan Barrett-Morrison + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + * adi_wtd.c - driver for ADI on-chip watchdog + * + */ + +#include <clk.h> +#include <dm.h> +#include <wdt.h> +#include <linux/delay.h> +#include <linux/ioport.h> +#include <linux/io.h> + +#define WDOG_CTL 0x0 +#define WDOG_CNT 0x4 +#define WDOG_STAT 0x8 + +#define RCU_CTL 0x0 +#define RCU_STAT 0x4 + +#define SEC_GCTL 0x0 +#define SEC_FCTL 0x10 +#define SEC_SCTL0 0x800 + +#define WDEN 0x0010 +#define WDDIS 0x0AD0 + +struct adi_wdt_priv { + void __iomem *rcu_base; + void __iomem *sec_base; + void __iomem *wdt_base; + struct clk clock; +}; + +static int adi_wdt_reset(struct udevice *dev) +{ + struct adi_wdt_priv *priv = dev_get_priv(dev); + + iowrite32(0, priv->wdt_base + WDOG_STAT); + + return 0; +} + +static int adi_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + struct adi_wdt_priv *priv = dev_get_priv(dev); + + /* Disable SYSCD_RESETb input and clear the RCU0 reset status */ + iowrite32(0xf, priv->rcu_base + RCU_STAT); + iowrite32(0x0, priv->rcu_base + RCU_CTL); + + /* reset the SEC controller */ + iowrite32(0x2, priv->sec_base + SEC_GCTL); + iowrite32(0x2, priv->sec_base + SEC_FCTL); + + udelay(50); + + /* enable SEC fault event */ + iowrite32(0x1, priv->sec_base + SEC_GCTL); + + /* ANOMALY 36100004 Spurious External Fault event occurs when FCTL + * is re-programmed when currently active fault is not cleared + */ + iowrite32(0xc0, priv->sec_base + SEC_FCTL); + iowrite32(0xc1, priv->sec_base + SEC_FCTL); + + /* enable SEC fault source for watchdog0 */ + setbits_32(priv->sec_base + SEC_SCTL0 + (3*8), 0x6); + + /* Enable SYSCD_RESETb input */ + iowrite32(0x100, priv->rcu_base + RCU_CTL); + + /* enable watchdog0 */ + iowrite32(WDDIS, priv->wdt_base + WDOG_CTL); + + iowrite32(timeout_ms / 1000 * + (clk_get_rate(&priv->clock) / (IS_ENABLED(CONFIG_SC58X) ? 2 : 1)), + priv->wdt_base + WDOG_CNT); + + iowrite32(0, priv->wdt_base + WDOG_STAT); + iowrite32(WDEN, priv->wdt_base + WDOG_CTL); + + return 0; +} + +static int adi_wdt_probe(struct udevice *dev) +{ + struct adi_wdt_priv *priv = dev_get_priv(dev); + int ret; + struct resource res; + + ret = dev_read_resource_byname(dev, "rcu", &res); + if (ret) + return ret; + priv->rcu_base = devm_ioremap(dev, res.start, resource_size(&res)); + + ret = dev_read_resource_byname(dev, "sec", &res); + if (ret) + return ret; + priv->sec_base = devm_ioremap(dev, res.start, resource_size(&res)); + + ret = dev_read_resource_byname(dev, "wdt", &res); + if (ret) + return ret; + priv->wdt_base = devm_ioremap(dev, res.start, resource_size(&res)); + + ret = clk_get_by_name(dev, "sclk0", &priv->clock); + if (ret < 0) { + printf("Can't get WDT clk: %d\n", ret); + return ret; + } + + return 0; +} + +static const struct wdt_ops adi_wdt_ops = { + .start = adi_wdt_start, + .reset = adi_wdt_reset, +}; + +static const struct udevice_id adi_wdt_ids[] = { + { .compatible = "adi,wdt" }, + {} +}; + +U_BOOT_DRIVER(adi_wdt) = { + .name = "adi_wdt", + .id = UCLASS_WDT, + .of_match = adi_wdt_ids, + .probe = adi_wdt_probe, + .ops = &adi_wdt_ops, + .priv_auto = sizeof(struct adi_wdt_priv), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index 8fac6c6c5a9..7c364686f14 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -1712,7 +1712,8 @@ static int sqfs_size_nest(const char *filename, loff_t *size) case SQFS_LSYMLINK_TYPE: if (++symlinknest == MAX_SYMLINK_NEST) { *size = 0; - return -ELOOP; + ret = -ELOOP; + break; } symlink = (struct squashfs_symlink_inode *)ipos; diff --git a/include/configs/mocha.h b/include/configs/mocha.h new file mode 100644 index 00000000000..1c2eb906085 --- /dev/null +++ b/include/configs/mocha.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + * + * Copyright (c) 2024, Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include "tegra124-common.h" + +/* High-level configuration options */ +#define CFG_TEGRA_BOARD_STRING "Xiaomi Mocha" + +/* Board-specific serial config */ +#define CFG_SYS_NS16550_COM1 NV_PA_APB_UARTD_BASE + +#ifdef CONFIG_TEGRA_SUPPORT_NON_SECURE + #define CFG_PRAM 0x38400 /* 225 MB */ +#endif + +#include "tegra-common-post.h" + +#endif /* __CONFIG_H */ diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 2372485c84e..db2ac7f83bb 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -6,7 +6,7 @@ #ifndef __CONFIG_H #define __CONFIG_H -#define CFG_MALLOC_F_ADDR 0x0010000 +#define CFG_MALLOC_F_ADDR 0x000f4000 /* Size of our emulated memory */ #define SB_CONCAT(x, y) x ## y diff --git a/include/crypto/mscode.h b/include/crypto/mscode.h index 678e69001b9..55501c22acb 100644 --- a/include/crypto/mscode.h +++ b/include/crypto/mscode.h @@ -10,6 +10,7 @@ #include <crypto/hash_info.h> #endif #if CONFIG_IS_ENABLED(MBEDTLS_LIB_X509) +#include "mbedtls_options.h" #include <mbedtls/asn1.h> #include <mbedtls/oid.h> #endif diff --git a/include/crypto/pkcs7_parser.h b/include/crypto/pkcs7_parser.h index 469c2711fa6..fd1e48da09e 100644 --- a/include/crypto/pkcs7_parser.h +++ b/include/crypto/pkcs7_parser.h @@ -12,6 +12,7 @@ #include <crypto/pkcs7.h> #include <crypto/x509_parser.h> #if CONFIG_IS_ENABLED(MBEDTLS_LIB_X509) +#include "mbedtls_options.h" #include <mbedtls/pkcs7.h> #include <library/x509_internal.h> #include <mbedtls/asn1.h> diff --git a/include/dm/ofnode_graph.h b/include/dm/ofnode_graph.h new file mode 100644 index 00000000000..908c990a3f3 --- /dev/null +++ b/include/dm/ofnode_graph.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#ifndef _DM_OFNODE_GRAPH_H +#define _DM_OFNODE_GRAPH_H + +#include <dm/of.h> + +/** + * ofnode_graph_get_endpoint_count() - get the number of endpoints in a device ofnode + * @parent: ofnode to the device containing ports and endpoints + * + * Return: count of endpoint of this device ofnode + */ +unsigned int ofnode_graph_get_endpoint_count(ofnode parent); + +/** + * ofnode_graph_get_port_count() - get the number of port in a device or ports ofnode + * @parent: ofnode to the device or ports node + * + * Return: count of port of this device or ports node + */ +unsigned int ofnode_graph_get_port_count(ofnode parent); + +/** + * ofnode_graph_get_port_by_id() - get the port matching a given id + * @parent: parent ofnode + * @id: id of the port + * + * Return: ofnode in given port. + */ +ofnode ofnode_graph_get_port_by_id(ofnode parent, u32 id); + +/** + * ofnode_graph_get_endpoint_by_regs() - get the endpoint matching a given id + * @parent: parent ofnode + * @reg_id: id of the port + * @id: id for the endpoint + * + * Return: ofnode in given endpoint or NULL if not found. + * reg and port_reg are ignored when they are -1. + */ +ofnode ofnode_graph_get_endpoint_by_regs(ofnode parent, u32 reg_id, u32 id); + +/** + * ofnode_graph_get_remote_endpoint() - get remote endpoint node + * @endoint: ofnode of a local endpoint + * + * Return: Remote endpoint ofnode linked with local endpoint. + */ +ofnode ofnode_graph_get_remote_endpoint(ofnode endpoint); + +/** + * ofnode_graph_get_port_parent() - get port's parent node + * @endpoint: ofnode of a local endpoint + * + * Return: device ofnode associated with endpoint + */ +ofnode ofnode_graph_get_port_parent(ofnode endpoint); + +/** + * ofnode_graph_get_remote_port_parent() - get remote port's parent ofnode + * @endoint: ofnode of a local endpoint + * + * Return: device ofnode associated with endpoint linked to local endpoint. + */ +ofnode ofnode_graph_get_remote_port_parent(ofnode endpoint); + +/** + * ofnode_graph_get_remote_port() - get remote port ofnode + * @endoint: ofnode of a local endpoint + * + * Return: port ofnode associated with remote endpoint node linked + * to local endpoint. + */ +ofnode ofnode_graph_get_remote_port(ofnode endpoint); + +/** + * ofnode_graph_get_remote_node() - get remote parent ofnode for given port/endpoint + * @parent: parent ofnode containing graph port/endpoint + * @port: identifier (value of reg property) of the parent port ofnode + * @endpoint: identifier (value of reg property) of the endpoint ofnode + * + * Return: device ofnode associated with endpoint linked to local endpoint. + */ +ofnode ofnode_graph_get_remote_node(ofnode parent, u32 port, u32 endpoint); + +#endif diff --git a/include/dt-bindings/pinctrl/adi-adsp.h b/include/dt-bindings/pinctrl/adi-adsp.h new file mode 100644 index 00000000000..7dc8a1ef5c4 --- /dev/null +++ b/include/dt-bindings/pinctrl/adi-adsp.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * (C) Copyright 2022 - Analog Devices, Inc. + * + * Written and/or maintained by Timesys Corporation + * + * Contact: Nathan Barrett-Morrison <nathan.morrison@timesys.com> + * Contact: Greg Malysa <greg.malysa@timesys.com> + * + */ + +#ifndef DT_BINDINGS_PINCTRL_ADI_ADSP +#define DT_BINDINGS_PINCTRL_ADI_ADSP + +#define ADI_ADSP_PIN(port, pin) (16 * ((port) - 'A') + (pin)) +#define ADI_ADSP_PINFUNC_ALT0 0 +#define ADI_ADSP_PINFUNC_ALT1 1 +#define ADI_ADSP_PINFUNC_ALT2 2 +#define ADI_ADSP_PINFUNC_ALT3 3 + +#endif diff --git a/include/efi_loader.h b/include/efi_loader.h index 1d75d97ebbc..e9c10819ba2 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -15,13 +15,13 @@ #include <efi_api.h> #include <image.h> #include <pe.h> +#include <setjmp.h> #include <linux/list.h> #include <linux/sizes.h> #include <linux/oid_registry.h> struct blk_desc; struct bootflow; -struct jmp_buf_data; #if CONFIG_IS_ENABLED(EFI_LOADER) @@ -129,17 +129,22 @@ static inline void efi_set_bootdev(const char *dev, const char *devnr, #if CONFIG_IS_ENABLED(NETDEVICES) && CONFIG_IS_ENABLED(EFI_LOADER) /* Call this to update the current device path of the efi net device */ -efi_status_t efi_net_set_dp(const char *dev, const char *server); +efi_status_t efi_net_new_dp(const char *dev, const char *server, struct udevice *udev); /* Call this to get the current device path of the efi net device */ -void efi_net_get_dp(struct efi_device_path **dp); +void efi_net_dp_from_dev(struct efi_device_path **dp, struct udevice *udev, bool cache_only); void efi_net_get_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw); + struct efi_ipv4_address *gw, + struct udevice *dev); void efi_net_set_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw); + struct efi_ipv4_address *gw, + struct udevice *dev); +#if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL) efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buffer, - u32 *status_code, ulong *file_size, char *headers_buffer); + u32 *status_code, ulong *file_size, char *headers_buffer, + struct efi_service_binding_protocol *parent); +#endif #define MAX_HTTP_HEADERS_SIZE SZ_64K #define MAX_HTTP_HEADERS 100 #define MAX_HTTP_HEADER_NAME 128 @@ -151,13 +156,16 @@ struct http_header { void efi_net_parse_headers(ulong *num_headers, struct http_header *headers); #else -static inline void efi_net_get_dp(struct efi_device_path **dp) { } +static inline void efi_net_dp_from_dev(struct efi_device_path **dp, + struct udevice *udev, bool cache_only) { } static inline void efi_net_get_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw) { } + struct efi_ipv4_address *gw, + struct udevice *dev) { } static inline void efi_net_set_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw) { } + struct efi_ipv4_address *gw, + struct udevice *dev) { } #endif /* Maximum number of configuration tables */ @@ -321,6 +329,8 @@ extern const efi_guid_t efi_guid_host_dev; #endif /* GUID of the EFI_BLOCK_IO_PROTOCOL */ extern const efi_guid_t efi_block_io_guid; +/* GUID of the EFI_SIMPLE_NETWORK_PROTOCOL */ +extern const efi_guid_t efi_net_guid; extern const efi_guid_t efi_global_variable_guid; extern const efi_guid_t efi_guid_console_control; extern const efi_guid_t efi_guid_device_path; @@ -485,7 +495,7 @@ struct efi_loaded_image_obj { efi_status_t *exit_status; efi_uintn_t *exit_data_size; u16 **exit_data; - struct jmp_buf_data *exit_jmp; + jmp_buf *exit_jmp; EFIAPI efi_status_t (*entry)(efi_handle_t image_handle, struct efi_system_table *st); u16 image_type; @@ -647,7 +657,8 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, /* Called by bootefi to make GOP (graphical) interface available */ efi_status_t efi_gop_register(void); /* Called by bootefi to make the network interface available */ -efi_status_t efi_net_register(void); +efi_status_t efi_net_register(struct udevice *dev); +efi_status_t efi_net_do_start(struct udevice *dev); /* Called by efi_net_register to make the ip4 config2 protocol available */ efi_status_t efi_ipconfig_register(const efi_handle_t handle, struct efi_ip4_config2_protocol *ip4config); @@ -733,6 +744,10 @@ efi_status_t efi_search_protocol(const efi_handle_t handle, efi_status_t efi_add_protocol(const efi_handle_t handle, const efi_guid_t *protocol, void *protocol_interface); +/* Uninstall new protocol on a handle */ +efi_status_t efi_uninstall_protocol + (efi_handle_t handle, const efi_guid_t *protocol, + void *protocol_interface, bool preserve); /* Reinstall a protocol on a handle */ efi_status_t EFIAPI efi_reinstall_protocol_interface( efi_handle_t handle, @@ -748,6 +763,15 @@ efi_status_t EFIAPI efi_install_multiple_protocol_interfaces(efi_handle_t *handle, ...); efi_status_t EFIAPI efi_uninstall_multiple_protocol_interfaces(efi_handle_t handle, ...); +/* Connect and disconnect controller */ +efi_status_t EFIAPI efi_connect_controller(efi_handle_t controller_handle, + efi_handle_t *driver_image_handle, + struct efi_device_path *remain_device_path, + bool recursive); +efi_status_t EFIAPI efi_disconnect_controller( + efi_handle_t controller_handle, + efi_handle_t driver_image_handle, + efi_handle_t child_handle); /* Get handles that support a given protocol */ efi_status_t EFIAPI efi_locate_handle_buffer( enum efi_locate_search_type search_type, @@ -768,6 +792,8 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl, void *context), void *notify_context, const efi_guid_t *group, struct efi_event **event); +/* Call this to close an event */ +efi_status_t EFIAPI efi_close_event(struct efi_event *event); /* Call this to set a timer */ efi_status_t efi_set_timer(struct efi_event *event, enum efi_timer_delay type, uint64_t trigger_time); @@ -907,8 +933,8 @@ struct efi_device_path *efi_dp_from_part(struct blk_desc *desc, int part); struct efi_device_path *efi_dp_part_node(struct blk_desc *desc, int part); struct efi_device_path *efi_dp_from_file(const struct efi_device_path *dp, const char *path); -struct efi_device_path *efi_dp_from_eth(void); -struct efi_device_path *efi_dp_from_http(const char *server); +struct efi_device_path *efi_dp_from_eth(struct udevice *dev); +struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev); struct efi_device_path *efi_dp_from_mem(uint32_t mem_type, uint64_t start_address, size_t size); diff --git a/include/interrupt.h b/include/interrupt.h index 46ef2e196d4..6ea28b54a56 100644 --- a/include/interrupt.h +++ b/include/interrupt.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include <asm/setjmp.h> +#include <setjmp.h> /** * struct resume_data - data for resume after interrupt diff --git a/include/mcheck.h b/include/mcheck.h index bd506ae6291..4b11751ebcc 100644 --- a/include/mcheck.h +++ b/include/mcheck.h @@ -1,18 +1,7 @@ -/* SPDX-License-Identifier: GPL-2.1+ */ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * 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 diff --git a/include/miiphy.h b/include/miiphy.h index b879fd16ae3..00d0b9b6a43 100644 --- a/include/miiphy.h +++ b/include/miiphy.h @@ -33,8 +33,6 @@ int miiphy_is_1000base_x(const char *devname, unsigned char addr); int miiphy_link(const char *devname, unsigned char addr); #endif -void miiphy_init(void); - int miiphy_set_current_dev(const char *devname); const char *miiphy_get_current_dev(void); struct mii_dev *mdio_get_current_dev(void); @@ -44,7 +42,6 @@ struct phy_device *mdio_phydev_for_ethname(const char *devname); void miiphy_listdev(void); -void mdio_init(struct mii_dev *bus); struct mii_dev *mdio_alloc(void); void mdio_free(struct mii_dev *bus); int mdio_register(struct mii_dev *bus); @@ -64,23 +61,19 @@ void mdio_list_devices(void); #define BB_MII_DEVNAME "bb_miiphy" -struct bb_miiphy_bus { - int (*mdio_active)(struct bb_miiphy_bus *bus); - int (*mdio_tristate)(struct bb_miiphy_bus *bus); - int (*set_mdio)(struct bb_miiphy_bus *bus, int v); - int (*get_mdio)(struct bb_miiphy_bus *bus, int *v); - int (*set_mdc)(struct bb_miiphy_bus *bus, int v); - int (*delay)(struct bb_miiphy_bus *bus); - void *priv; - struct mii_dev mii; +struct bb_miiphy_bus_ops { + int (*mdio_active)(struct mii_dev *miidev); + int (*mdio_tristate)(struct mii_dev *miidev); + int (*set_mdio)(struct mii_dev *miidev, int v); + int (*get_mdio)(struct mii_dev *miidev, int *v); + int (*set_mdc)(struct mii_dev *miidev, int v); + int (*delay)(struct mii_dev *miidev); }; -struct bb_miiphy_bus *bb_miiphy_alloc(void); -void bb_miiphy_free(struct bb_miiphy_bus *bus); - -int bb_miiphy_read(struct mii_dev *miidev, int addr, int devad, int reg); -int bb_miiphy_write(struct mii_dev *miidev, int addr, int devad, int reg, - u16 value); +int bb_miiphy_read(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + int addr, int devad, int reg); +int bb_miiphy_write(struct mii_dev *miidev, const struct bb_miiphy_bus_ops *ops, + int addr, int devad, int reg, u16 value); #endif /* phy seed setup */ diff --git a/include/net-common.h b/include/net-common.h index 29d31f37263..1d507b13b06 100644 --- a/include/net-common.h +++ b/include/net-common.h @@ -291,6 +291,7 @@ struct eth_ops { #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops) struct udevice *eth_get_dev(void); /* get the current device */ +void eth_set_dev(struct udevice *dev); /* set a device */ unsigned char *eth_get_ethaddr(void); /* get the current device MAC */ int eth_rx(void); /* Check for received packets */ void eth_halt(void); /* stop SCC */ diff --git a/include/serial.h b/include/serial.h index e5f6d984d28..0a707ca730d 100644 --- a/include/serial.h +++ b/include/serial.h @@ -48,26 +48,6 @@ extern int serial_assign(const char *name); extern void serial_reinit_all(void); int serial_initialize(void); -/* For usbtty */ -#ifdef CONFIG_USB_TTY - -struct stdio_dev; - -int usbtty_getc(struct stdio_dev *dev); -void usbtty_putc(struct stdio_dev *dev, const char c); -void usbtty_puts(struct stdio_dev *dev, const char *str); -int usbtty_tstc(struct stdio_dev *dev); - -#else - -/* stubs */ -#define usbtty_getc(dev) 0 -#define usbtty_putc(dev, a) -#define usbtty_puts(dev, a) -#define usbtty_tstc(dev) 0 - -#endif /* CONFIG_USB_TTY */ - struct udevice; enum serial_par { diff --git a/include/setjmp.h b/include/setjmp.h new file mode 100644 index 00000000000..37d3a8af85d --- /dev/null +++ b/include/setjmp.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef _SETJMP_H_ +#define _SETJMP_H_ 1 + +#ifdef CONFIG_HAVE_SETJMP +#include <asm/setjmp.h> +#else +struct jmp_buf_data { +}; +#endif + +/** + * typedef jmp_buf - information needed to restore a calling environment + */ +typedef struct jmp_buf_data jmp_buf[1]; + +/** + * setjmp() - prepare for a long jump + * + * Registers, the stack pointer, and the return address are saved in the + * jump bufffer. The function returns zero afterwards. When longjmp() is + * executed the function returns a second time with a non-zero value. + * + * @env: jump buffer used to store register values + * Return: 0 after setting up jump buffer, non-zero after longjmp() + */ +int setjmp(jmp_buf env); + +/** + * longjmp() - long jump + * + * Jump back to the address and the register state saved by setjmp(). + * + * @env: jump buffer + * @val: value to be returned by setjmp(), 0 is replaced by 1 + */ +void longjmp(jmp_buf env, int val); + +#endif /* _SETJMP_H_ */ diff --git a/include/stdio_dev.h b/include/stdio_dev.h index 4e3c4708f80..f7f9c10199e 100644 --- a/include/stdio_dev.h +++ b/include/stdio_dev.h @@ -101,7 +101,6 @@ struct stdio_dev *stdio_clone(struct stdio_dev *dev); int drv_lcd_init(void); int drv_video_init(void); int drv_keyboard_init(void); -int drv_usbtty_init(void); int drv_usbacm_init(void); int drv_nc_init(void); int drv_jtag_console_init(void); diff --git a/include/u-boot/sha1.h b/include/u-boot/sha1.h index dd66258bbe9..c2d62e9cf0f 100644 --- a/include/u-boot/sha1.h +++ b/include/u-boot/sha1.h @@ -18,17 +18,7 @@ #include <linux/types.h> #if CONFIG_IS_ENABLED(MBEDTLS_LIB_CRYPTO) -/* - * FIXME: - * MbedTLS define the members of "mbedtls_sha256_context" as private, - * but "state" needs to be access by arch/arm/cpu/armv8/sha1_ce_glue. - * MBEDTLS_ALLOW_PRIVATE_ACCESS needs to be enabled to allow the external - * access. - * Directly including <external/mbedtls/library/common.h> is not allowed, - * since this will include <malloc.h> and break the sandbox test. - */ -#define MBEDTLS_ALLOW_PRIVATE_ACCESS - +#include "mbedtls_options.h" #include <mbedtls/sha1.h> #endif diff --git a/include/u-boot/sha256.h b/include/u-boot/sha256.h index d7a3403270b..2d86508332e 100644 --- a/include/u-boot/sha256.h +++ b/include/u-boot/sha256.h @@ -7,17 +7,7 @@ #include <linux/types.h> #if CONFIG_IS_ENABLED(MBEDTLS_LIB_CRYPTO) -/* - * FIXME: - * MbedTLS define the members of "mbedtls_sha256_context" as private, - * but "state" needs to be access by arch/arm/cpu/armv8/sha256_ce_glue. - * MBEDTLS_ALLOW_PRIVATE_ACCESS needs to be enabled to allow the external - * access. - * Directly including <external/mbedtls/library/common.h> is not allowed, - * since this will include <malloc.h> and break the sandbox test. - */ -#define MBEDTLS_ALLOW_PRIVATE_ACCESS - +#include "mbedtls_options.h" #include <mbedtls/sha256.h> #endif diff --git a/include/video_bridge.h b/include/video_bridge.h index 3b429eac578..00e9804565c 100644 --- a/include/video_bridge.h +++ b/include/video_bridge.h @@ -54,6 +54,19 @@ struct video_bridge_ops { int (*set_backlight)(struct udevice *dev, int percent); /** + * get_display_timing() - Get display timings from bridge. + * + * @dev: Bridge device containing the linked display timings + * @tim: Place to put timings + * @return 0 if OK, -ve on error + * + * This call it totally optional and useful mainly for integrated + * bridges with fixed output device. + */ + int (*get_display_timing)(struct udevice *dev, + struct display_timing *timing); + + /** * read_edid() - Read information from EDID * * @dev: Device to read from @@ -67,6 +80,7 @@ struct video_bridge_ops { #define video_bridge_get_ops(dev) \ ((struct video_bridge_ops *)(dev)->driver->ops) +#if CONFIG_IS_ENABLED(VIDEO_BRIDGE) /** * video_bridge_attach() - attach a video bridge * @@ -99,6 +113,14 @@ int video_bridge_set_active(struct udevice *dev, bool active); int video_bridge_check_attached(struct udevice *dev); /** + * video_bridge_get_display_timing() - Get display timings from bridge. + * + * @dev: Bridge device containing the linked display timings + * Return: 0 if OK, -ve on error + */ +int video_bridge_get_display_timing(struct udevice *dev, + struct display_timing *timing); +/** * video_bridge_read_edid() - Read information from EDID * * @dev: Device to read from @@ -107,5 +129,37 @@ int video_bridge_check_attached(struct udevice *dev); * Return: number of bytes read, <=0 for error */ int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size); +#else +static inline int video_bridge_attach(struct udevice *dev) +{ + return -ENOSYS; +} + +static inline int video_bridge_set_backlight(struct udevice *dev, int percent) +{ + return -ENOSYS; +} + +static inline int video_bridge_set_active(struct udevice *dev, bool active) +{ + return -ENOSYS; +} + +static inline int video_bridge_check_attached(struct udevice *dev) +{ + return -ENOSYS; +} + +static inline int video_bridge_get_display_timing(struct udevice *dev, + struct display_timing *timing) +{ + return -ENOSYS; +} + +static inline int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size) +{ + return -ENOSYS; +} +#endif /* CONFIG_VIDEO_BRIDGE */ #endif diff --git a/lib/Kconfig b/lib/Kconfig index 1a683dea670..a21b3378fa7 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -1008,14 +1008,14 @@ config OF_LIBFDT_OVERLAY This enables the FDT library (libfdt) overlay support. config SYS_FDT_PAD - hex "Maximum size of the FDT memory area passeed to the OS" + hex "Free space added to device-tree before booting" depends on OF_LIBFDT default 0x13000 if FMAN_ENET || QE || U_QE default 0x3000 help - During OS boot, we allocate a region of memory within the bootmap - for the FDT. This is the size that we will expand the FDT that we - are using will be extended to be, in bytes. + The operating system may need a free area at the end of the device- + tree for fix-ups. This setting defines by how many bytes U-Boot + extends the device-tree before booting. config SPL_OF_LIBFDT bool "Enable the FDT library for SPL" diff --git a/lib/Makefile b/lib/Makefile index a7bc2f3134a..a30ce1595d5 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -28,11 +28,7 @@ obj-y += charset.o endif endif -ifdef CONFIG_USB_TTY -obj-y += circbuf.o -else obj-$(CONFIG_CIRCBUF) += circbuf.o -endif obj-y += crc8.o obj-$(CONFIG_ERRNO_STR) += errno_str.o diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index 10ec5e9ada3..deafb2ce1c2 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -16,6 +16,7 @@ #include <log.h> #include <malloc.h> #include <mapmem.h> +#include <net.h> static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; @@ -67,7 +68,7 @@ static efi_status_t calculate_paths(const char *dev, const char *devnr, #if IS_ENABLED(CONFIG_NETDEVICES) if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) { - ret = efi_net_set_dp(dev, devnr); + ret = efi_net_new_dp(dev, devnr, eth_get_dev()); if (ret != EFI_SUCCESS) return ret; } diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 5164cb15986..c8d9a6037f7 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -21,7 +21,6 @@ #include <usb.h> #include <watchdog.h> #include <asm/global_data.h> -#include <asm/setjmp.h> #include <linux/libfdt_env.h> DECLARE_GLOBAL_DATA_PTR; @@ -60,9 +59,9 @@ static efi_handle_t current_image; static volatile gd_t *efi_gd, *app_gd; #endif -static efi_status_t efi_uninstall_protocol - (efi_handle_t handle, const efi_guid_t *protocol, - void *protocol_interface, bool preserve); +efi_status_t efi_uninstall_protocol + (efi_handle_t handle, const efi_guid_t *protocol, + void *protocol_interface, bool preserve); /* 1 if inside U-Boot code, 0 if inside EFI payload code */ static int entry_count = 1; @@ -100,12 +99,11 @@ const efi_guid_t efi_guid_load_file2_protocol = EFI_LOAD_FILE2_PROTOCOL_GUID; /* GUID of the SMBIOS table */ const efi_guid_t smbios_guid = SMBIOS_TABLE_GUID; -static efi_status_t EFIAPI efi_disconnect_controller( +efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t controller_handle, efi_handle_t driver_image_handle, efi_handle_t child_handle); -static efi_status_t EFIAPI efi_connect_controller(efi_handle_t controller_handle, efi_handle_t *driver_image_handle, struct efi_device_path *remain_device_path, @@ -1039,7 +1037,7 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event) * * Return: status code */ -static efi_status_t EFIAPI efi_close_event(struct efi_event *event) +efi_status_t EFIAPI efi_close_event(struct efi_event *event) { struct efi_register_notify_event *item, *next; @@ -1380,9 +1378,9 @@ static efi_status_t efi_disconnect_all_drivers * * Return: status code */ -static efi_status_t efi_uninstall_protocol - (efi_handle_t handle, const efi_guid_t *protocol, - void *protocol_interface, bool preserve) +efi_status_t efi_uninstall_protocol + (efi_handle_t handle, const efi_guid_t *protocol, + void *protocol_interface, bool preserve) { struct efi_handler *handler; struct efi_open_protocol_info_item *item; @@ -2233,8 +2231,6 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle, if (!efi_st_keep_devices) { bootm_disable_interrupts(); - if (IS_ENABLED(CONFIG_USB_DEVICE)) - udc_disconnect(); board_quiesce_devices(); dm_remove_devices_active(); } @@ -3199,7 +3195,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, void *info; efi_handle_t parent_image = current_image; efi_status_t exit_status; - struct jmp_buf_data exit_jmp; + jmp_buf exit_jmp; EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data); @@ -3238,7 +3234,7 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, } /* call the image! */ - if (setjmp(&exit_jmp)) { + if (setjmp(exit_jmp)) { /* * We called the entry point of the child image with EFI_CALL * in the lines below. The child image called the Exit() boot @@ -3444,7 +3440,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, struct efi_loaded_image *loaded_image_protocol; struct efi_loaded_image_obj *image_obj = (struct efi_loaded_image_obj *)image_handle; - struct jmp_buf_data *exit_jmp; + jmp_buf *exit_jmp; EFI_ENTRY("%p, %ld, %zu, %p", image_handle, exit_status, exit_data_size, exit_data); @@ -3511,7 +3507,7 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, */ efi_restore_gd(); - longjmp(exit_jmp, 1); + longjmp(*exit_jmp, 1); panic("EFI application exited"); out: @@ -3665,7 +3661,7 @@ static efi_status_t efi_connect_single_controller( * * Return: status code */ -static efi_status_t EFIAPI efi_connect_controller( +efi_status_t EFIAPI efi_connect_controller( efi_handle_t controller_handle, efi_handle_t *driver_image_handle, struct efi_device_path *remain_device_path, @@ -3844,7 +3840,7 @@ static efi_status_t efi_get_child_controllers( * * Return: status code */ -static efi_status_t EFIAPI efi_disconnect_controller( +efi_status_t EFIAPI efi_disconnect_controller( efi_handle_t controller_handle, efi_handle_t driver_image_handle, efi_handle_t child_handle) diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index c0633a736b6..c9bf2726fe2 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -954,20 +954,20 @@ struct efi_device_path *efi_dp_from_uart(void) return buf; } -struct efi_device_path __maybe_unused *efi_dp_from_eth(void) +struct efi_device_path __maybe_unused *efi_dp_from_eth(struct udevice *dev) { void *buf, *start; unsigned dpsize = 0; - assert(eth_get_dev()); + assert(dev); - dpsize += dp_size(eth_get_dev()); + dpsize += dp_size(dev); start = buf = efi_alloc(dpsize + sizeof(END)); if (!buf) return NULL; - buf = dp_fill(buf, eth_get_dev()); + buf = dp_fill(buf, dev); *((struct efi_device_path *)buf) = END; @@ -984,11 +984,13 @@ struct efi_device_path __maybe_unused *efi_dp_from_eth(void) * @ip: IPv4 local address * @mask: network mask * @srv: IPv4 remote/server address + * @dev: net udevice * Return: pointer to device path, NULL on error */ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *srv) + struct efi_ipv4_address *srv, + struct udevice *dev) { struct efi_device_path *dp1, *dp2, *pos; struct { @@ -1010,7 +1012,7 @@ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, pos = &dp.end; memcpy(pos, &END, sizeof(END)); - dp1 = efi_dp_from_eth(); + dp1 = efi_dp_from_eth(dev); if (!dp1) return NULL; @@ -1029,9 +1031,10 @@ static struct efi_device_path *efi_dp_from_ipv4(struct efi_ipv4_address *ip, * and an END node. * * @server: URI of remote server + * @dev: net udevice * Return: pointer to HTTP device path, NULL on error */ -struct efi_device_path *efi_dp_from_http(const char *server) +struct efi_device_path *efi_dp_from_http(const char *server, struct udevice *dev) { struct efi_device_path *dp1, *dp2; struct efi_device_path_uri *uridp; @@ -1045,12 +1048,13 @@ struct efi_device_path *efi_dp_from_http(const char *server) (!server && IS_ENABLED(CONFIG_NET_LWIP))) return NULL; - efi_net_get_addr(&ip, &mask, NULL); + efi_net_get_addr(&ip, &mask, NULL, dev); - dp1 = efi_dp_from_ipv4(&ip, &mask, NULL); + dp1 = efi_dp_from_ipv4(&ip, &mask, NULL, dev); if (!dp1) return NULL; + strcpy(tmp, "http://"); if (server) { @@ -1185,8 +1189,8 @@ efi_status_t efi_dp_from_name(const char *dev, const char *devnr, dp = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, (uintptr_t)image_addr, image_size); } else if (IS_ENABLED(CONFIG_NETDEVICES) && - (!strcmp(dev, "Net") || !strcmp(dev, "Http"))) { - efi_net_get_dp(&dp); + (!strcmp(dev, "Net") || !strcmp(dev, "Http"))) { + efi_net_dp_from_dev(&dp, eth_get_dev(), false); } else if (!strcmp(dev, "Uart")) { dp = efi_dp_from_uart(); } else { diff --git a/lib/efi_loader/efi_http.c b/lib/efi_loader/efi_http.c index 88816256b03..189317fe2d2 100644 --- a/lib/efi_loader/efi_http.c +++ b/lib/efi_loader/efi_http.c @@ -36,6 +36,7 @@ static const efi_guid_t efi_http_guid = EFI_HTTP_PROTOCOL_GUID; struct efi_http_instance { struct efi_http_protocol http; efi_handle_t handle; + struct efi_service_binding_protocol *parent; bool configured; void *http_load_addr; ulong file_size; @@ -188,7 +189,7 @@ static efi_status_t EFIAPI efi_http_configure(struct efi_http_protocol *this, if (!ipv4_node->use_default_address) { efi_net_set_addr((struct efi_ipv4_address *)&ipv4_node->local_address, - (struct efi_ipv4_address *)&ipv4_node->local_subnet, NULL); + (struct efi_ipv4_address *)&ipv4_node->local_subnet, NULL, NULL); } http_instance->current_offset = 0; @@ -243,7 +244,7 @@ static efi_status_t EFIAPI efi_http_request(struct efi_http_protocol *this, ret = efi_net_do_request(url_8, current_method, &http_instance->http_load_addr, &http_instance->status_code, &http_instance->file_size, - http_instance->headers_buffer); + http_instance->headers_buffer, http_instance->parent); if (ret != EFI_SUCCESS) goto out; @@ -408,6 +409,7 @@ static efi_status_t EFIAPI efi_http_service_binding_create_child( goto failure_to_add_protocol; } + new_instance->parent = this; efi_add_handle(new_instance->handle); *child_handle = new_instance->handle; diff --git a/lib/efi_loader/efi_ipconfig.c b/lib/efi_loader/efi_ipconfig.c index f1c092daafd..9f51f77fa9a 100644 --- a/lib/efi_loader/efi_ipconfig.c +++ b/lib/efi_loader/efi_ipconfig.c @@ -60,7 +60,7 @@ static efi_status_t EFIAPI efi_ip4_config2_set_data(struct efi_ip4_config2_proto memcpy((void *)¤t_http_ip, data, sizeof(struct efi_ip4_config2_manual_address)); efi_net_set_addr(¤t_http_ip.address, - ¤t_http_ip.subnet_mask, NULL); + ¤t_http_ip.subnet_mask, NULL, NULL); return EFI_EXIT(EFI_SUCCESS); } return EFI_EXIT(EFI_BAD_BUFFER_SIZE); @@ -133,7 +133,7 @@ static efi_status_t EFIAPI efi_ip4_config2_get_data(struct efi_ip4_config2_proto return EFI_EXIT(EFI_BUFFER_TOO_SMALL); } - efi_net_get_addr(¤t_http_ip.address, ¤t_http_ip.subnet_mask, NULL); + efi_net_get_addr(¤t_http_ip.address, ¤t_http_ip.subnet_mask, NULL, NULL); memcpy(data, (void *)¤t_http_ip, sizeof(struct efi_ip4_config2_manual_address)); diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index ce9272fa240..b3291b4f1d5 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -24,54 +24,70 @@ #include <vsprintf.h> #include <net.h> -static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; +#define MAX_EFI_NET_OBJS 10 +#define MAX_NUM_DHCP_ENTRIES 10 +#define MAX_NUM_DP_ENTRIES 10 + +const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; static const efi_guid_t efi_pxe_base_code_protocol_guid = EFI_PXE_BASE_CODE_PROTOCOL_GUID; -static struct efi_pxe_packet *dhcp_ack; -static void *new_tx_packet; -static void *transmit_buffer; -static uchar **receive_buffer; -static size_t *receive_lengths; -static int rx_packet_idx; -static int rx_packet_num; -static struct efi_net_obj *netobj; + +struct dp_entry { + struct efi_device_path *net_dp; + struct udevice *dev; + bool is_valid; +}; /* - * The current network device path. This device path is updated when a new - * bootfile is downloaded from the network. If then the bootfile is loaded - * as an efi image, net_dp is passed as the device path of the loaded image. + * The network device path cache. An entry is added when a new bootfile + * is downloaded from the network. If the bootfile is then loaded as an + * efi image, the most recent entry corresponding to the device is passed + * as the device path of the loaded image. */ -static struct efi_device_path *net_dp; +static struct dp_entry dp_cache[MAX_NUM_DP_ENTRIES]; +static int next_dp_entry; +#if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL) static struct wget_http_info efi_wget_info = { .set_bootdev = false, .check_buffer_size = true, }; +#endif -/* - * The notification function of this event is called in every timer cycle - * to check if a new network packet has been received. - */ -static struct efi_event *network_timer_event; -/* - * This event is signaled when a packet has been received. - */ -static struct efi_event *wait_for_packet; +struct dhcp_entry { + struct efi_pxe_packet *dhcp_ack; + struct udevice *dev; + bool is_valid; +}; + +static struct dhcp_entry dhcp_cache[MAX_NUM_DHCP_ENTRIES]; +static int next_dhcp_entry; /** * struct efi_net_obj - EFI object representing a network interface * * @header: EFI object header + * @dev: net udevice * @net: simple network protocol interface * @net_mode: status of the network interface * @pxe: PXE base code protocol interface * @pxe_mode: status of the PXE base code protocol * @ip4_config2: IP4 Config2 protocol interface * @http_service_binding: Http service binding protocol interface + * @new_tx_packet: new transmit packet + * @transmit_buffer: transmit buffer + * @receive_buffer: array of receive buffers + * @receive_lengths: array of lengths for received packets + * @rx_packet_idx: index of the current receive packet + * @rx_packet_num: number of received packets + * @wait_for_packet: signaled when a packet has been received + * @network_timer_event: event to check for new network packets. + * @efi_seq_num: sequence number of the EFI net object. */ struct efi_net_obj { struct efi_object header; + struct udevice *dev; struct efi_simple_network net; struct efi_simple_network_mode net_mode; struct efi_pxe_base_code_protocol pxe; @@ -82,8 +98,54 @@ struct efi_net_obj { #if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL) struct efi_service_binding_protocol http_service_binding; #endif + void *new_tx_packet; + void *transmit_buffer; + uchar **receive_buffer; + size_t *receive_lengths; + int rx_packet_idx; + int rx_packet_num; + struct efi_event *wait_for_packet; + struct efi_event *network_timer_event; + int efi_seq_num; }; +static int curr_efi_net_obj; +static struct efi_net_obj *net_objs[MAX_EFI_NET_OBJS]; + +/** + * efi_netobj_is_active() - checks if a netobj is active in the efi subsystem + * + * @netobj: pointer to efi_net_obj + * Return: true if active + */ +static bool efi_netobj_is_active(struct efi_net_obj *netobj) +{ + if (!netobj || !efi_search_obj(&netobj->header)) + return false; + + return true; +} + +/* + * efi_netobj_from_snp() - get efi_net_obj from simple network protocol + * + * + * @snp: pointer to the simple network protocol + * Return: pointer to efi_net_obj, NULL on error + */ +static struct efi_net_obj *efi_netobj_from_snp(struct efi_simple_network *snp) +{ + int i; + + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && &net_objs[i]->net == snp) { + // Do not register duplicate devices + return net_objs[i]; + } + } + return NULL; +} + /* * efi_net_start() - start the network interface * @@ -97,20 +159,22 @@ struct efi_net_obj { static efi_status_t EFIAPI efi_net_start(struct efi_simple_network *this) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p", this); - /* Check parameters */ if (!this) { ret = EFI_INVALID_PARAMETER; goto out; } + nt = efi_netobj_from_snp(this); + if (this->mode->state != EFI_NETWORK_STOPPED) { ret = EFI_ALREADY_STARTED; } else { this->int_status = 0; - wait_for_packet->is_signaled = false; + nt->wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_STARTED; } out: @@ -130,6 +194,7 @@ out: static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p", this); @@ -139,13 +204,17 @@ static efi_status_t EFIAPI efi_net_stop(struct efi_simple_network *this) goto out; } + nt = efi_netobj_from_snp(this); + if (this->mode->state == EFI_NETWORK_STOPPED) { ret = EFI_NOT_STARTED; } else { /* Disable hardware and put it into the reset state */ + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); eth_halt(); /* Clear cache of packets */ - rx_packet_num = 0; + nt->rx_packet_num = 0; this->mode->state = EFI_NETWORK_STOPPED; } out: @@ -169,6 +238,7 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, { int ret; efi_status_t r = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p, %lx, %lx", this, extra_rx, extra_tx); @@ -177,6 +247,7 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, r = EFI_INVALID_PARAMETER; goto out; } + nt = efi_netobj_from_snp(this); switch (this->mode->state) { case EFI_NETWORK_INITIALIZED: @@ -189,14 +260,13 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, /* Setup packet buffers */ net_init(); - /* Disable hardware and put it into the reset state */ - eth_halt(); /* Clear cache of packets */ - rx_packet_num = 0; - /* Set current device according to environment variables */ - eth_set_current(); + nt->rx_packet_num = 0; + /* Set the net device corresponding to the efi net object */ + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); /* Get hardware ready for send and receive operations */ - ret = eth_init(); + ret = eth_start_udev(nt->dev); if (ret < 0) { eth_halt(); this->mode->state = EFI_NETWORK_STOPPED; @@ -204,7 +274,7 @@ static efi_status_t EFIAPI efi_net_initialize(struct efi_simple_network *this, goto out; } else { this->int_status = 0; - wait_for_packet->is_signaled = false; + nt->wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_INITIALIZED; } out: @@ -265,6 +335,7 @@ out: static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p", this); @@ -273,6 +344,7 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this) ret = EFI_INVALID_PARAMETER; goto out; } + nt = efi_netobj_from_snp(this); switch (this->mode->state) { case EFI_NETWORK_INITIALIZED: @@ -285,9 +357,12 @@ static efi_status_t EFIAPI efi_net_shutdown(struct efi_simple_network *this) goto out; } + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); eth_halt(); + this->int_status = 0; - wait_for_packet->is_signaled = false; + nt->wait_for_packet->is_signaled = false; this->mode->state = EFI_NETWORK_STARTED; out: @@ -463,6 +538,7 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, u32 *int_status, void **txbuf) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p, %p, %p", this, int_status, txbuf); @@ -474,6 +550,8 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, goto out; } + nt = efi_netobj_from_snp(this); + switch (this->mode->state) { case EFI_NETWORK_STOPPED: ret = EFI_NOT_STARTED; @@ -490,9 +568,9 @@ static efi_status_t EFIAPI efi_net_get_status(struct efi_simple_network *this, this->int_status = 0; } if (txbuf) - *txbuf = new_tx_packet; + *txbuf = nt->new_tx_packet; - new_tx_packet = NULL; + nt->new_tx_packet = NULL; out: return EFI_EXIT(ret); } @@ -519,6 +597,7 @@ static efi_status_t EFIAPI efi_net_transmit struct efi_mac_address *dest_addr, u16 *protocol) { efi_status_t ret = EFI_SUCCESS; + struct efi_net_obj *nt; EFI_ENTRY("%p, %lu, %lu, %p, %p, %p, %p", this, (unsigned long)header_size, (unsigned long)buffer_size, @@ -532,6 +611,8 @@ static efi_status_t EFIAPI efi_net_transmit goto out; } + nt = efi_netobj_from_snp(this); + /* We do not support jumbo packets */ if (buffer_size > PKTSIZE_ALIGN) { ret = EFI_INVALID_PARAMETER; @@ -576,11 +657,14 @@ static efi_status_t EFIAPI efi_net_transmit break; } + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); + /* Ethernet packets always fit, just bounce */ - memcpy(transmit_buffer, buffer, buffer_size); - net_send_packet(transmit_buffer, buffer_size); + memcpy(nt->transmit_buffer, buffer, buffer_size); + net_send_packet(nt->transmit_buffer, buffer_size); - new_tx_packet = buffer; + nt->new_tx_packet = buffer; this->int_status |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; out: return EFI_EXIT(ret); @@ -611,6 +695,7 @@ static efi_status_t EFIAPI efi_net_receive struct ethernet_hdr *eth_hdr; size_t hdr_size = sizeof(struct ethernet_hdr); u16 protlen; + struct efi_net_obj *nt; EFI_ENTRY("%p, %p, %p, %p, %p, %p, %p", this, header_size, buffer_size, buffer, src_addr, dest_addr, protocol); @@ -624,6 +709,8 @@ static efi_status_t EFIAPI efi_net_receive goto out; } + nt = efi_netobj_from_snp(this); + switch (this->mode->state) { case EFI_NETWORK_STOPPED: ret = EFI_NOT_STARTED; @@ -635,16 +722,16 @@ static efi_status_t EFIAPI efi_net_receive break; } - if (!rx_packet_num) { + if (!nt->rx_packet_num) { ret = EFI_NOT_READY; goto out; } /* Fill export parameters */ - eth_hdr = (struct ethernet_hdr *)receive_buffer[rx_packet_idx]; + eth_hdr = (struct ethernet_hdr *)nt->receive_buffer[nt->rx_packet_idx]; protlen = ntohs(eth_hdr->et_protlen); if (protlen == 0x8100) { hdr_size += 4; - protlen = ntohs(*(u16 *)&receive_buffer[rx_packet_idx][hdr_size - 2]); + protlen = ntohs(*(u16 *)&nt->receive_buffer[nt->rx_packet_idx][hdr_size - 2]); } if (header_size) *header_size = hdr_size; @@ -654,20 +741,20 @@ static efi_status_t EFIAPI efi_net_receive memcpy(src_addr, eth_hdr->et_src, ARP_HLEN); if (protocol) *protocol = protlen; - if (*buffer_size < receive_lengths[rx_packet_idx]) { + if (*buffer_size < nt->receive_lengths[nt->rx_packet_idx]) { /* Packet doesn't fit, try again with bigger buffer */ - *buffer_size = receive_lengths[rx_packet_idx]; + *buffer_size = nt->receive_lengths[nt->rx_packet_idx]; ret = EFI_BUFFER_TOO_SMALL; goto out; } /* Copy packet */ - memcpy(buffer, receive_buffer[rx_packet_idx], - receive_lengths[rx_packet_idx]); - *buffer_size = receive_lengths[rx_packet_idx]; - rx_packet_idx = (rx_packet_idx + 1) % ETH_PACKETS_BATCH_RECV; - rx_packet_num--; - if (rx_packet_num) - wait_for_packet->is_signaled = true; + memcpy(buffer, nt->receive_buffer[nt->rx_packet_idx], + nt->receive_lengths[nt->rx_packet_idx]); + *buffer_size = nt->receive_lengths[nt->rx_packet_idx]; + nt->rx_packet_idx = (nt->rx_packet_idx + 1) % ETH_PACKETS_BATCH_RECV; + nt->rx_packet_num--; + if (nt->rx_packet_num) + nt->wait_for_packet->is_signaled = true; else this->int_status &= ~EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; out: @@ -684,18 +771,35 @@ out: */ void efi_net_set_dhcp_ack(void *pkt, int len) { - int maxsize = sizeof(*dhcp_ack); + struct efi_pxe_packet **dhcp_ack; + struct udevice *dev; + int i; + + dhcp_ack = &dhcp_cache[next_dhcp_entry].dhcp_ack; + + /* For now this function gets called only by the current device */ + dev = eth_get_dev(); - if (!dhcp_ack) { - dhcp_ack = malloc(maxsize); - if (!dhcp_ack) + int maxsize = sizeof(**dhcp_ack); + + if (!*dhcp_ack) { + *dhcp_ack = malloc(maxsize); + if (!*dhcp_ack) return; } - memset(dhcp_ack, 0, maxsize); - memcpy(dhcp_ack, pkt, min(len, maxsize)); + memset(*dhcp_ack, 0, maxsize); + memcpy(*dhcp_ack, pkt, min(len, maxsize)); + + dhcp_cache[next_dhcp_entry].is_valid = true; + dhcp_cache[next_dhcp_entry].dev = dev; + next_dhcp_entry++; + next_dhcp_entry %= MAX_NUM_DHCP_ENTRIES; - if (netobj) - netobj->pxe_mode.dhcp_ack = *dhcp_ack; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == dev) { + net_objs[i]->pxe_mode.dhcp_ack = **dhcp_ack; + } + } } /** @@ -709,6 +813,11 @@ void efi_net_set_dhcp_ack(void *pkt, int len) static void efi_net_push(void *pkt, int len) { int rx_packet_next; + struct efi_net_obj *nt; + + nt = net_objs[curr_efi_net_obj]; + if (!nt) + return; /* Check that we at least received an Ethernet header */ if (len < sizeof(struct ethernet_hdr)) @@ -719,15 +828,15 @@ static void efi_net_push(void *pkt, int len) return; /* Can't store more than pre-alloced buffer */ - if (rx_packet_num >= ETH_PACKETS_BATCH_RECV) + if (nt->rx_packet_num >= ETH_PACKETS_BATCH_RECV) return; - rx_packet_next = (rx_packet_idx + rx_packet_num) % + rx_packet_next = (nt->rx_packet_idx + nt->rx_packet_num) % ETH_PACKETS_BATCH_RECV; - memcpy(receive_buffer[rx_packet_next], pkt, len); - receive_lengths[rx_packet_next] = len; + memcpy(nt->receive_buffer[rx_packet_next], pkt, len); + nt->receive_lengths[rx_packet_next] = len; - rx_packet_num++; + nt->rx_packet_num++; } /** @@ -742,6 +851,7 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event, void *context) { struct efi_simple_network *this = (struct efi_simple_network *)context; + struct efi_net_obj *nt; EFI_ENTRY("%p, %p", event, context); @@ -752,14 +862,19 @@ static void EFIAPI efi_network_timer_notify(struct efi_event *event, if (!this || this->mode->state != EFI_NETWORK_INITIALIZED) goto out; - if (!rx_packet_num) { + nt = efi_netobj_from_snp(this); + curr_efi_net_obj = nt->efi_seq_num; + + if (!nt->rx_packet_num) { + eth_set_dev(nt->dev); + env_set("ethact", eth_get_name()); push_packet = efi_net_push; eth_rx(); push_packet = NULL; - if (rx_packet_num) { + if (nt->rx_packet_num) { this->int_status |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; - wait_for_packet->is_signaled = true; + nt->wait_for_packet->is_signaled = true; } } out: @@ -879,30 +994,179 @@ static efi_status_t EFIAPI efi_pxe_base_code_set_packets( } /** + * efi_netobj_set_dp() - set device path of a netobj + * + * @netobj: pointer to efi_net_obj + * @dp: device path to set, allocated by caller + * Return: status code + */ +efi_status_t efi_netobj_set_dp(struct efi_net_obj *netobj, struct efi_device_path *dp) +{ + efi_status_t ret; + struct efi_handler *phandler; + struct efi_device_path *new_net_dp; + + if (!efi_netobj_is_active(netobj)) + return EFI_SUCCESS; + + // Create a device path for the netobj + new_net_dp = dp; + if (!new_net_dp) + return EFI_OUT_OF_RESOURCES; + + phandler = NULL; + efi_search_protocol(&netobj->header, &efi_guid_device_path, &phandler); + + // If the device path protocol is not yet installed, install it + if (!phandler) + goto add; + + // If it is already installed, try to update it + ret = efi_reinstall_protocol_interface(&netobj->header, &efi_guid_device_path, + phandler->protocol_interface, new_net_dp); + if (ret != EFI_SUCCESS) + return ret; + + return EFI_SUCCESS; +add: + ret = efi_add_protocol(&netobj->header, &efi_guid_device_path, + new_net_dp); + if (ret != EFI_SUCCESS) + return ret; + + return EFI_SUCCESS; +} + +/** + * efi_netobj_get_dp() - get device path of a netobj + * + * @netobj: pointer to efi_net_obj + * Return: device path, NULL on error + */ +static struct efi_device_path *efi_netobj_get_dp(struct efi_net_obj *netobj) +{ + struct efi_handler *phandler; + + if (!efi_netobj_is_active(netobj)) + return NULL; + + phandler = NULL; + efi_search_protocol(&netobj->header, &efi_guid_device_path, &phandler); + + if (phandler && phandler->protocol_interface) + return efi_dp_dup(phandler->protocol_interface); + + return NULL; +} + +/** + * efi_net_do_start() - start the efi network stack + * + * This gets called from do_bootefi_exec() each time a payload gets executed. + * + * @dev: net udevice + * Return: status code + */ +efi_status_t efi_net_do_start(struct udevice *dev) +{ + efi_status_t r = EFI_SUCCESS; + struct efi_net_obj *netobj; + struct efi_device_path *net_dp; + int i; + + netobj = NULL; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == dev) { + netobj = net_objs[i]; + break; + } + } + + if (!efi_netobj_is_active(netobj)) + return r; + + efi_net_dp_from_dev(&net_dp, netobj->dev, true); + // If no dp cache entry applies and there already + // is a device path installed, continue + if (!net_dp) { + if (efi_netobj_get_dp(netobj)) + goto set_addr; + else + net_dp = efi_dp_from_eth(netobj->dev); + + } + + if (!net_dp) + return EFI_OUT_OF_RESOURCES; + + r = efi_netobj_set_dp(netobj, net_dp); + if (r != EFI_SUCCESS) + return r; +set_addr: +#ifdef CONFIG_EFI_HTTP_PROTOCOL + /* + * No harm on doing the following. If the PXE handle is present, the client could + * find it and try to get its IP address from it. In here the PXE handle is present + * but the PXE protocol is not yet implmenented, so we add this in the meantime. + */ + efi_net_get_addr((struct efi_ipv4_address *)&netobj->pxe_mode.station_ip, + (struct efi_ipv4_address *)&netobj->pxe_mode.subnet_mask, NULL, dev); +#endif + + return r; +} + +/** * efi_net_register() - register the simple network protocol * * This gets called from do_bootefi_exec(). + * @dev: net udevice */ -efi_status_t efi_net_register(void) +efi_status_t efi_net_register(struct udevice *dev) { efi_status_t r; - int i; - - if (!eth_get_dev()) { + int seq_num; + struct efi_net_obj *netobj; + void *transmit_buffer = NULL; + uchar **receive_buffer = NULL; + size_t *receive_lengths; + int i, j; + + if (!dev) { /* No network device active, don't expose any */ return EFI_SUCCESS; } + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == dev) { + // Do not register duplicate devices + return EFI_SUCCESS; + } + } + + seq_num = -1; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (!net_objs[i]) { + seq_num = i; + break; + } + } + if (seq_num < 0) + return EFI_OUT_OF_RESOURCES; + /* We only expose the "active" network device, so one is enough */ netobj = calloc(1, sizeof(*netobj)); if (!netobj) goto out_of_resources; + netobj->dev = dev; + /* Allocate an aligned transmit buffer */ transmit_buffer = calloc(1, PKTSIZE_ALIGN + PKTALIGN); if (!transmit_buffer) goto out_of_resources; transmit_buffer = (void *)ALIGN((uintptr_t)transmit_buffer, PKTALIGN); + netobj->transmit_buffer = transmit_buffer; /* Allocate a number of receive buffers */ receive_buffer = calloc(ETH_PACKETS_BATCH_RECV, @@ -914,10 +1178,13 @@ efi_status_t efi_net_register(void) if (!receive_buffer[i]) goto out_of_resources; } + netobj->receive_buffer = receive_buffer; + receive_lengths = calloc(ETH_PACKETS_BATCH_RECV, sizeof(*receive_lengths)); if (!receive_lengths) goto out_of_resources; + netobj->receive_lengths = receive_lengths; /* Hook net up to the device list */ efi_add_handle(&netobj->header); @@ -927,12 +1194,7 @@ efi_status_t efi_net_register(void) &netobj->net); if (r != EFI_SUCCESS) goto failure_to_add_protocol; - if (!net_dp) - efi_net_set_dp("Net", NULL); - r = efi_add_protocol(&netobj->header, &efi_guid_device_path, - net_dp); - if (r != EFI_SUCCESS) - goto failure_to_add_protocol; + r = efi_add_protocol(&netobj->header, &efi_pxe_base_code_protocol_guid, &netobj->pxe); if (r != EFI_SUCCESS) @@ -953,7 +1215,9 @@ efi_status_t efi_net_register(void) netobj->net.receive = efi_net_receive; netobj->net.mode = &netobj->net_mode; netobj->net_mode.state = EFI_NETWORK_STOPPED; - memcpy(netobj->net_mode.current_address.mac_addr, eth_get_ethaddr(), 6); + if (dev_get_plat(dev)) + memcpy(netobj->net_mode.current_address.mac_addr, + ((struct eth_pdata *)dev_get_plat(dev))->enetaddr, 6); netobj->net_mode.hwaddr_size = ARP_HLEN; netobj->net_mode.media_header_size = ETHER_HDR_SIZE; netobj->net_mode.max_packet_size = PKTSIZE; @@ -973,20 +1237,31 @@ efi_status_t efi_net_register(void) netobj->pxe.set_station_ip = efi_pxe_base_code_set_station_ip; netobj->pxe.set_packets = efi_pxe_base_code_set_packets; netobj->pxe.mode = &netobj->pxe_mode; - if (dhcp_ack) - netobj->pxe_mode.dhcp_ack = *dhcp_ack; + + /* + * Scan dhcp entries for one corresponding + * to this udevice, from newest to oldest + */ + i = (next_dhcp_entry + MAX_NUM_DHCP_ENTRIES - 1) % MAX_NUM_DHCP_ENTRIES; + for (j = 0; dhcp_cache[i].is_valid && j < MAX_NUM_DHCP_ENTRIES; + i = (i + MAX_NUM_DHCP_ENTRIES - 1) % MAX_NUM_DHCP_ENTRIES, j++) { + if (dev == dhcp_cache[i].dev) { + netobj->pxe_mode.dhcp_ack = *dhcp_cache[i].dhcp_ack; + break; + } + } /* * Create WaitForPacket event. */ r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_network_timer_notify, NULL, NULL, - &wait_for_packet); + &netobj->wait_for_packet); if (r != EFI_SUCCESS) { printf("ERROR: Failed to register network event\n"); return r; } - netobj->net.wait_for_packet = wait_for_packet; + netobj->net.wait_for_packet = netobj->wait_for_packet; /* * Create a timer event. * @@ -997,13 +1272,13 @@ efi_status_t efi_net_register(void) */ r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, efi_network_timer_notify, &netobj->net, NULL, - &network_timer_event); + &netobj->network_timer_event); if (r != EFI_SUCCESS) { printf("ERROR: Failed to register network event\n"); return r; } /* Network is time critical, create event in every timer cycle */ - r = efi_set_timer(network_timer_event, EFI_TIMER_PERIODIC, 0); + r = efi_set_timer(netobj->network_timer_event, EFI_TIMER_PERIODIC, 0); if (r != EFI_SUCCESS) { printf("ERROR: Failed to set network timer\n"); return r; @@ -1019,15 +1294,9 @@ efi_status_t efi_net_register(void) r = efi_http_register(&netobj->header, &netobj->http_service_binding); if (r != EFI_SUCCESS) goto failure_to_add_protocol; - /* - * No harm on doing the following. If the PXE handle is present, the client could - * find it and try to get its IP address from it. In here the PXE handle is present - * but the PXE protocol is not yet implmenented, so we add this in the meantime. - */ - efi_net_get_addr((struct efi_ipv4_address *)&netobj->pxe_mode.station_ip, - (struct efi_ipv4_address *)&netobj->pxe_mode.subnet_mask, NULL); #endif - + netobj->efi_seq_num = seq_num; + net_objs[seq_num] = netobj; return EFI_SUCCESS; failure_to_add_protocol: printf("ERROR: Failure to add protocol\n"); @@ -1046,46 +1315,103 @@ out_of_resources: } /** - * efi_net_set_dp() - set device path of efi net device + * efi_net_new_dp() - update device path associated to a net udevice * * This gets called to update the device path when a new boot * file is downloaded * * @dev: dev to set the device path from * @server: remote server address + * @udev: net udevice * Return: status code */ -efi_status_t efi_net_set_dp(const char *dev, const char *server) +efi_status_t efi_net_new_dp(const char *dev, const char *server, struct udevice *udev) { - efi_free_pool(net_dp); + efi_status_t ret; + struct efi_net_obj *netobj; + struct efi_device_path *old_net_dp, *new_net_dp; + struct efi_device_path **dp; + int i; + + dp = &dp_cache[next_dp_entry].net_dp; - net_dp = NULL; + dp_cache[next_dp_entry].dev = udev; + dp_cache[next_dp_entry].is_valid = true; + next_dp_entry++; + next_dp_entry %= MAX_NUM_DP_ENTRIES; + + old_net_dp = *dp; + new_net_dp = NULL; if (!strcmp(dev, "Net")) - net_dp = efi_dp_from_eth(); + new_net_dp = efi_dp_from_eth(udev); else if (!strcmp(dev, "Http")) - net_dp = efi_dp_from_http(server); + new_net_dp = efi_dp_from_http(server, udev); + if (!new_net_dp) + return EFI_OUT_OF_RESOURCES; - if (!net_dp) + *dp = new_net_dp; + // Free the old cache entry + efi_free_pool(old_net_dp); + + netobj = NULL; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == udev) { + netobj = net_objs[i]; + break; + } + } + if (!netobj) + return EFI_SUCCESS; + + new_net_dp = efi_dp_dup(*dp); + if (!new_net_dp) return EFI_OUT_OF_RESOURCES; + ret = efi_netobj_set_dp(netobj, new_net_dp); + if (ret != EFI_SUCCESS) + efi_free_pool(new_net_dp); - return EFI_SUCCESS; + return ret; } /** - * efi_net_get_dp() - get device path of efi net device + * efi_net_dp_from_dev() - get device path associated to a net udevice * * Produce a copy of the current device path * - * @dp: copy of the current device path, or NULL on error + * @dp: copy of the current device path + * @udev: net udevice + * @cache_only: get device path from cache only */ -void efi_net_get_dp(struct efi_device_path **dp) +void efi_net_dp_from_dev(struct efi_device_path **dp, struct udevice *udev, bool cache_only) { + int i, j; + if (!dp) return; - if (!net_dp) - efi_net_set_dp("Net", NULL); - if (net_dp) - *dp = efi_dp_dup(net_dp); + + *dp = NULL; + + if (cache_only) + goto cache; + + // If a netobj matches: + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && net_objs[i]->dev == udev) { + *dp = efi_netobj_get_dp(net_objs[i]); + if (*dp) + return; + } + } +cache: + // Search in the cache + i = (next_dp_entry + MAX_NUM_DP_ENTRIES - 1) % MAX_NUM_DP_ENTRIES; + for (j = 0; dp_cache[i].is_valid && j < MAX_NUM_DP_ENTRIES; + i = (i + MAX_NUM_DP_ENTRIES - 1) % MAX_NUM_DP_ENTRIES, j++) { + if (dp_cache[i].dev == udev) { + *dp = efi_dp_dup(dp_cache[i].net_dp); + return; + } + } } /** @@ -1101,11 +1427,15 @@ void efi_net_get_dp(struct efi_device_path **dp) * be filled with the current network mask * @gw: pointer to an efi_ipv4_address struct to be * filled with the current network gateway + * @dev: udevice */ void efi_net_get_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw) + struct efi_ipv4_address *gw, + struct udevice *dev) { + if (!dev) + dev = eth_get_dev(); #ifdef CONFIG_NET_LWIP char ipstr[] = "ipaddr\0\0"; char maskstr[] = "netmask\0\0"; @@ -1114,7 +1444,7 @@ void efi_net_get_addr(struct efi_ipv4_address *ip, struct in_addr tmp; char *env; - idx = dev_seq(eth_get_dev()); + idx = dev_seq(dev); if (idx < 0 || idx > 99) { log_err("unexpected idx %d\n", idx); @@ -1161,11 +1491,15 @@ void efi_net_get_addr(struct efi_ipv4_address *ip, * @ip: pointer to new IP address * @mask: pointer to new network mask to set * @gw: pointer to new network gateway + * @dev: udevice */ void efi_net_set_addr(struct efi_ipv4_address *ip, struct efi_ipv4_address *mask, - struct efi_ipv4_address *gw) + struct efi_ipv4_address *gw, + struct udevice *dev) { + if (!dev) + dev = eth_get_dev(); #ifdef CONFIG_NET_LWIP char ipstr[] = "ipaddr\0\0"; char maskstr[] = "netmask\0\0"; @@ -1174,7 +1508,7 @@ void efi_net_set_addr(struct efi_ipv4_address *ip, struct in_addr *addr; char tmp[46]; - idx = dev_seq(eth_get_dev()); + idx = dev_seq(dev); if (idx < 0 || idx > 99) { log_err("unexpected idx %d\n", idx); @@ -1212,6 +1546,7 @@ void efi_net_set_addr(struct efi_ipv4_address *ip, #endif } +#if IS_ENABLED(CONFIG_EFI_HTTP_PROTOCOL) /** * efi_net_set_buffer() - allocate a buffer of min 64K * @@ -1299,26 +1634,41 @@ void efi_net_parse_headers(ulong *num_headers, struct http_header *headers) * @status_code: HTTP status code * @file_size: file size in bytes * @headers_buffer: headers buffer + * @parent: service binding protocol * Return: status code */ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buffer, - u32 *status_code, ulong *file_size, char *headers_buffer) + u32 *status_code, ulong *file_size, char *headers_buffer, + struct efi_service_binding_protocol *parent) { efi_status_t ret = EFI_SUCCESS; int wget_ret; static bool last_head; + struct udevice *dev; + int i; - if (!buffer || !file_size) + if (!buffer || !file_size || !parent) return EFI_ABORTED; efi_wget_info.method = (enum wget_http_method)method; efi_wget_info.headers = headers_buffer; + // Set corresponding udevice + dev = NULL; + for (i = 0; i < MAX_EFI_NET_OBJS; i++) { + if (net_objs[i] && &net_objs[i]->http_service_binding == parent) + dev = net_objs[i]->dev; + } + if (!dev) + return EFI_ABORTED; + switch (method) { case HTTP_METHOD_GET: ret = efi_net_set_buffer(buffer, last_head ? (size_t)efi_wget_info.hdr_cont_len : 0); if (ret != EFI_SUCCESS) goto out; + eth_set_dev(dev); + env_set("ethact", eth_get_name()); wget_ret = wget_request((ulong)*buffer, url, &efi_wget_info); if ((ulong)efi_wget_info.hdr_cont_len > efi_wget_info.buffer_size) { // Try again with updated buffer size @@ -1326,6 +1676,8 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf ret = efi_net_set_buffer(buffer, (size_t)efi_wget_info.hdr_cont_len); if (ret != EFI_SUCCESS) goto out; + eth_set_dev(dev); + env_set("ethact", eth_get_name()); if (wget_request((ulong)*buffer, url, &efi_wget_info)) { efi_free_pool(*buffer); ret = EFI_DEVICE_ERROR; @@ -1345,6 +1697,8 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf ret = efi_net_set_buffer(buffer, 0); if (ret != EFI_SUCCESS) goto out; + eth_set_dev(dev); + env_set("ethact", eth_get_name()); wget_request((ulong)*buffer, url, &efi_wget_info); *file_size = 0; *status_code = efi_wget_info.status_code; @@ -1358,3 +1712,4 @@ efi_status_t efi_net_do_request(u8 *url, enum efi_http_method method, void **buf out: return ret; } +#endif diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index aa59bc7779d..48f91da5df7 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -11,7 +11,9 @@ #include <efi_variable.h> #include <log.h> #include <asm-generic/unaligned.h> +#include <net.h> +#define OBJ_LIST_INITIALIZED 0 #define OBJ_LIST_NOT_INITIALIZED 1 efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; @@ -209,6 +211,21 @@ out: } /** + * efi_start_obj_list() - Start EFI object list + * + * Return: status code + */ +static efi_status_t efi_start_obj_list(void) +{ + efi_status_t ret = EFI_SUCCESS; + + if (IS_ENABLED(CONFIG_NETDEVICES)) + ret = efi_net_do_start(eth_get_dev()); + + return ret; +} + +/** * efi_init_obj_list() - Initialize and populate EFI object list * * Return: status code @@ -217,7 +234,9 @@ efi_status_t efi_init_obj_list(void) { efi_status_t ret = EFI_SUCCESS; - /* Initialize once only */ + /* Initialize only once, but start every time if correctly initialized*/ + if (efi_obj_list_initialized == OBJ_LIST_INITIALIZED) + return efi_start_obj_list(); if (efi_obj_list_initialized != OBJ_LIST_NOT_INITIALIZED) return efi_obj_list_initialized; @@ -318,7 +337,7 @@ efi_status_t efi_init_obj_list(void) goto out; } if (IS_ENABLED(CONFIG_NETDEVICES)) { - ret = efi_net_register(); + ret = efi_net_register(eth_get_dev()); if (ret != EFI_SUCCESS) goto out; } @@ -349,6 +368,10 @@ efi_status_t efi_init_obj_list(void) if (IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK) && !IS_ENABLED(CONFIG_EFI_CAPSULE_ON_DISK_EARLY)) ret = efi_launch_capsules(); + if (ret != EFI_SUCCESS) + goto out; + + ret = efi_start_obj_list(); out: efi_obj_list_initialized = ret; return ret; diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index 15af8d3e18c..b00c76c2f17 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -67,7 +67,6 @@ struct dhcp { static struct efi_boot_services *boottime; static struct efi_simple_network *net; static struct efi_event *timer; -static const efi_guid_t efi_net_guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID; /* IP packet ID */ static unsigned int net_ip_id; diff --git a/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c b/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c index 46421588fef..ef51a5ac168 100644 --- a/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c +++ b/lib/lwip/lwip/src/apps/altcp_tls/altcp_tls_mbedtls.c @@ -298,6 +298,9 @@ altcp_mbedtls_lower_recv_process(struct altcp_pcb *conn, altcp_mbedtls_state_t * if (ret != 0) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_handshake failed: %d\n", ret)); /* handshake failed, connection has to be closed */ + if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { + printf("Certificate verification failed\n"); + } if (conn->err) { conn->err(conn->arg, ERR_CLSD); } @@ -786,6 +789,7 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav int ret; struct altcp_tls_config *conf; mbedtls_x509_crt *mem; + int authmode = have_ca ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE; if (TCP_WND < MBEDTLS_SSL_IN_CONTENT_LEN || TCP_WND < MBEDTLS_SSL_OUT_CONTENT_LEN) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS, @@ -840,7 +844,10 @@ altcp_tls_create_config(int is_server, u8_t cert_count, u8_t pkey_count, int hav altcp_mbedtls_free_config(conf); return NULL; } - mbedtls_ssl_conf_authmode(&conf->conf, ALTCP_MBEDTLS_AUTHMODE); + if (authmode == MBEDTLS_SSL_VERIFY_NONE) { + printf("WARNING: no CA certificates, HTTPS connections not authenticated\n"); + } + mbedtls_ssl_conf_authmode(&conf->conf, authmode); mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &altcp_tls_entropy_rng->ctr_drbg); #if ALTCP_MBEDTLS_LIB_DEBUG != LWIP_DBG_OFF diff --git a/lib/lwip/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h b/lib/lwip/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h index e41301c061c..71aa5993935 100644 --- a/lib/lwip/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h +++ b/lib/lwip/lwip/src/include/lwip/apps/altcp_tls_mbedtls_opts.h @@ -100,12 +100,6 @@ #define ALTCP_MBEDTLS_SESSION_TICKET_TIMEOUT_SECONDS (60 * 60 * 24) #endif -/** Certificate verification mode: MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL (default), - * MBEDTLS_SSL_VERIFY_REQUIRED (recommended)*/ -#ifndef ALTCP_MBEDTLS_AUTHMODE -#define ALTCP_MBEDTLS_AUTHMODE MBEDTLS_SSL_VERIFY_OPTIONAL -#endif - #endif /* LWIP_ALTCP */ #endif /* LWIP_HDR_ALTCP_TLS_OPTS_H */ diff --git a/lib/mbedtls/Kconfig b/lib/mbedtls/Kconfig index 35d8c507a89..789721ee6cd 100644 --- a/lib/mbedtls/Kconfig +++ b/lib/mbedtls/Kconfig @@ -1,57 +1,54 @@ +# For U-Boot Proper + choice - prompt "Select crypto libraries" - default LEGACY_CRYPTO + prompt "Crypto libraries (U-Boot Proper)" + default LEGACY_HASHING_AND_CRYPTO help Select crypto libraries. - LEGACY_CRYPTO for legacy crypto libraries, + LEGACY_HASHING_AND_CRYPTO for legacy crypto libraries, MBEDTLS_LIB for MbedTLS libraries. -config LEGACY_CRYPTO +config LEGACY_HASHING_AND_CRYPTO bool "legacy crypto libraries" - select LEGACY_CRYPTO_BASIC - select LEGACY_CRYPTO_CERT + select LEGACY_HASHING + select LEGACY_CRYPTO config MBEDTLS_LIB bool "MbedTLS libraries" select MBEDTLS_LIB_X509 endchoice -if LEGACY_CRYPTO || MBEDTLS_LIB_CRYPTO_ALT +if LEGACY_HASHING_AND_CRYPTO || MBEDTLS_LIB_HASHING_ALT -config LEGACY_CRYPTO_BASIC - bool "legacy basic crypto libraries" +config LEGACY_HASHING + bool "Use U-Boot legacy hashing libraries" select MD5_LEGACY if MD5 select SHA1_LEGACY if SHA1 select SHA256_LEGACY if SHA256 select SHA512_LEGACY if SHA512 select SHA384_LEGACY if SHA384 - select SPL_MD5_LEGACY if SPL_MD5 - select SPL_SHA1_LEGACY if SPL_SHA1 - select SPL_SHA256_LEGACY if SPL_SHA256 - select SPL_SHA512_LEGACY if SPL_SHA512 - select SPL_SHA384_LEGACY if SPL_SHA384 help - Enable legacy basic crypto libraries. + Enable U-Boot legacy hashing libraries. -if LEGACY_CRYPTO_BASIC +if LEGACY_HASHING config SHA1_LEGACY bool "Enable SHA1 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SHA1 + depends on LEGACY_HASHING && SHA1 help This option enables support of hashing using SHA1 algorithm with legacy crypto library. config SHA256_LEGACY bool "Enable SHA256 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SHA256 + depends on LEGACY_HASHING && SHA256 help This option enables support of hashing using SHA256 algorithm with legacy crypto library. config SHA512_LEGACY bool "Enable SHA512 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SHA512 + depends on LEGACY_HASHING && SHA512 default y if TI_SECURE_DEVICE && FIT_SIGNATURE help This option enables support of hashing using SHA512 algorithm @@ -59,7 +56,7 @@ config SHA512_LEGACY config SHA384_LEGACY bool "Enable SHA384 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SHA384 + depends on LEGACY_HASHING && SHA384 select SHA512_LEGACY help This option enables support of hashing using SHA384 algorithm @@ -67,95 +64,16 @@ config SHA384_LEGACY config MD5_LEGACY bool "Enable MD5 support with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && MD5 + depends on LEGACY_HASHING && MD5 help This option enables support of hashing using MD5 algorithm with legacy crypto library. -if SPL - -config SPL_SHA1_LEGACY - bool "Enable SHA1 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_SHA1 - help - This option enables support of hashing using SHA1 algorithm - with legacy crypto library. - -config SPL_SHA256_LEGACY - bool "Enable SHA256 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_SHA256 - help - This option enables support of hashing using SHA256 algorithm - with legacy crypto library. +endif # LEGACY_HASHING -config SPL_SHA512_LEGACY - bool "Enable SHA512 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_SHA512 - help - This option enables support of hashing using SHA512 algorithm - with legacy crypto library. - -config SPL_SHA384_LEGACY - bool "Enable SHA384 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_SHA384 - select SPL_SHA512_LEGACY - help - This option enables support of hashing using SHA384 algorithm - with legacy crypto library. - -config SPL_MD5_LEGACY - bool "Enable MD5 support in SPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && SPL_MD5 - help - This option enables support of hashing using MD5 algorithm - with legacy crypto library. - -endif # SPL - -if VPL - -config VPL_SHA1_LEGACY - bool "Enable SHA1 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_SHA1 - help - This option enables support of hashing using SHA1 algorithm - with legacy crypto library. - -config VPL_SHA256_LEGACY - bool "Enable SHA256 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_SHA256 - help - This option enables support of hashing using SHA256 algorithm - with legacy crypto library. - -config VPL_SHA512_LEGACY - bool "Enable SHA512 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_SHA512 - help - This option enables support of hashing using SHA512 algorithm - with legacy crypto library. - -config VPL_SHA384_LEGACY - bool "Enable SHA384 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_SHA384 - select VPL_SHA512_LEGACY - help - This option enables support of hashing using SHA384 algorithm - with legacy crypto library. - -config VPL_MD5_LEGACY - bool "Enable MD5 support in VPL with legacy crypto library" - depends on LEGACY_CRYPTO_BASIC && VPL_MD5 - help - This option enables support of hashing using MD5 algorithm - with legacy crypto library. - -endif # VPL - -endif # LEGACY_CRYPTO_BASIC - -config LEGACY_CRYPTO_CERT +config LEGACY_CRYPTO bool "legacy certificate libraries" + depends on LEGACY_HASHING_AND_CRYPTO select ASN1_DECODER_LEGACY if ASN1_DECODER select ASYMMETRIC_PUBLIC_KEY_LEGACY if \ ASYMMETRIC_PUBLIC_KEY_SUBTYPE @@ -163,24 +81,20 @@ config LEGACY_CRYPTO_CERT select X509_CERTIFICATE_PARSER_LEGACY if X509_CERTIFICATE_PARSER select PKCS7_MESSAGE_PARSER_LEGACY if PKCS7_MESSAGE_PARSER select MSCODE_PARSER_LEGACY if MSCODE_PARSER - select SPL_ASN1_DECODER_LEGACY if SPL_ASN1_DECODER - select SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY if \ - SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE - select SPL_RSA_PUBLIC_KEY_PARSER_LEGACY if SPL_RSA_PUBLIC_KEY_PARSER help Enable legacy certificate libraries. -if LEGACY_CRYPTO_CERT +if LEGACY_CRYPTO config ASN1_DECODER_LEGACY bool "ASN1 decoder with legacy certificate library" - depends on LEGACY_CRYPTO_CERT && ASN1_DECODER + depends on LEGACY_CRYPTO && ASN1_DECODER help This option chooses legacy certificate library for ASN1 decoder. config ASYMMETRIC_PUBLIC_KEY_LEGACY bool "Asymmetric public key crypto with legacy certificate library" - depends on LEGACY_CRYPTO_CERT && ASYMMETRIC_PUBLIC_KEY_SUBTYPE + depends on LEGACY_CRYPTO && ASYMMETRIC_PUBLIC_KEY_SUBTYPE help This option chooses legacy certificate library for asymmetric public key crypto algorithm. @@ -211,68 +125,41 @@ config PKCS7_MESSAGE_PARSER_LEGACY config MSCODE_PARSER_LEGACY bool "MS authenticode parser with legacy certificate library" - depends on LEGACY_CRYPTO_CERT && MSCODE_PARSER + depends on LEGACY_CRYPTO && MSCODE_PARSER select ASN1_DECODER_LEGACY help This option chooses legacy certificate library for MS authenticode parser. -if SPL - -config SPL_ASN1_DECODER_LEGACY - bool "ASN1 decoder with legacy certificate library in SPL" - depends on LEGACY_CRYPTO_CERT && SPL_ASN1_DECODER - help - This option chooses legacy certificate library for ASN1 decoder in - SPL. - -config SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY - bool "Asymmetric public key crypto with legacy certificate library in SPL" - depends on LEGACY_CRYPTO_CERT && SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE - help - This option chooses legacy certificate library for asymmetric public - key crypto algorithm in SPL. - -config SPL_RSA_PUBLIC_KEY_PARSER_LEGACY - bool "RSA public key parser with legacy certificate library in SPL" - depends on SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY - select SPL_ASN1_DECODER_LEGACY - help - This option chooses legacy certificate library for RSA public key - parser in SPL. - -endif # SPL - -endif # LEGACY_CRYPTO_CERT - endif # LEGACY_CRYPTO +endif # LEGACY_HASHING_AND_CRYPTO || MBEDTLS_LIB_HASHING_ALT + if MBEDTLS_LIB -config MBEDTLS_LIB_CRYPTO_ALT - bool "MbedTLS crypto alternatives" +config MBEDTLS_LIB_HASHING_ALT + bool "Replace MbedTLS native hashing with U-Boot legacy libraries" depends on MBEDTLS_LIB && !MBEDTLS_LIB_CRYPTO - select LEGACY_CRYPTO_BASIC + select LEGACY_HASHING default y if MBEDTLS_LIB && !MBEDTLS_LIB_CRYPTO help - Enable MbedTLS crypto alternatives. + Enable MbedTLS hashing alternatives and replace them with legacy hashing + libraries. + This allows user to use U-Boot legacy hashing algorithms together with + other MbedTLS modules. Mutually incompatible with MBEDTLS_LIB_CRYPTO. config MBEDTLS_LIB_CRYPTO - bool "MbedTLS crypto libraries" + bool "Use MbedTLS native crypto libraries for hashing" + default y if MBEDTLS_LIB select MD5_MBEDTLS if MD5 select SHA1_MBEDTLS if SHA1 select SHA256_MBEDTLS if SHA256 select SHA512_MBEDTLS if SHA512 select SHA384_MBEDTLS if SHA384 - select SPL_MD5_MBEDTLS if SPL_MD5 - select SPL_SHA1_MBEDTLS if SPL_SHA1 - select SPL_SHA256_MBEDTLS if SPL_SHA256 - select SPL_SHA512_MBEDTLS if SPL_SHA512 - select SPL_SHA384_MBEDTLS if SPL_SHA384 help - Enable MbedTLS crypto libraries. - Mutually incompatible with MBEDTLS_LIB_CRYPTO_ALT. + Enable MbedTLS native crypto libraries. + Mutually incompatible with MBEDTLS_LIB_HASHING_ALT. if MBEDTLS_LIB_CRYPTO @@ -344,53 +231,6 @@ config HKDF_MBEDTLS This option enables support of key derivation using HKDF algorithm with MbedTLS crypto library. -if SPL - -config SPL_SHA1_MBEDTLS - bool "Enable SHA1 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_SHA1 - help - This option enables support of hashing using SHA1 algorithm - with MbedTLS crypto library. - -config SPL_SHA256_MBEDTLS - bool "Enable SHA256 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_SHA256 - help - This option enables support of hashing using SHA256 algorithm - with MbedTLS crypto library. - -config SPL_SHA512_MBEDTLS - bool "Enable SHA512 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_SHA512 - help - This option enables support of hashing using SHA512 algorithm - with MbedTLS crypto library. - -config SPL_SHA384_MBEDTLS - bool "Enable SHA384 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_SHA384 - select SPL_SHA512 - help - This option enables support of hashing using SHA384 algorithm - with MbedTLS crypto library. - -config SPL_MD5_MBEDTLS - bool "Enable MD5 support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO && SPL_MD5 - help - This option enables support of hashing using MD5 algorithm - with MbedTLS crypto library. - -config SPL_HKDF_MBEDTLS - bool "Enable HKDF support in SPL with MbedTLS crypto library" - depends on MBEDTLS_LIB_CRYPTO - help - This option enables support of key derivation using HKDF algorithm - with MbedTLS crypto library. - -endif # SPL - endif # MBEDTLS_LIB_CRYPTO config MBEDTLS_LIB_X509 @@ -402,10 +242,6 @@ config MBEDTLS_LIB_X509 select X509_CERTIFICATE_PARSER_MBEDTLS if X509_CERTIFICATE_PARSER select PKCS7_MESSAGE_PARSER_MBEDTLS if PKCS7_MESSAGE_PARSER select MSCODE_PARSER_MBEDTLS if MSCODE_PARSER - select SPL_ASN1_DECODER_MBEDTLS if SPL_ASN1_DECODER - select SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS if \ - SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE - select SPL_RSA_PUBLIC_KEY_PARSER_MBEDTLS if SPL_RSA_PUBLIC_KEY_PARSER help Enable MbedTLS certificate libraries. @@ -456,44 +292,554 @@ config MSCODE_PARSER_MBEDTLS This option chooses MbedTLS certificate library for MS authenticode parser. +endif # MBEDTLS_LIB_X509 + +config MBEDTLS_LIB_TLS + bool "MbedTLS TLS library" + depends on RSA_PUBLIC_KEY_PARSER_MBEDTLS + depends on X509_CERTIFICATE_PARSER_MBEDTLS + depends on ASYMMETRIC_PUBLIC_KEY_MBEDTLS + depends on ASN1_DECODER_MBEDTLS + depends on MBEDTLS_LIB + help + Enable MbedTLS TLS library. Required for HTTPs support + in wget + +endif # MBEDTLS_LIB + +# For SPL + if SPL +choice + prompt "Crypto libraries (SPL)" + default SPL_LEGACY_HASHING_AND_CRYPTO + help + Select crypto libraries in SPL. + SPL_LEGACY_HASHING_AND_CRYPTO for legacy crypto libraries, + SPL_MBEDTLS_LIB for MbedTLS libraries. + +config SPL_LEGACY_HASHING_AND_CRYPTO + bool "legacy crypto libraries" + select SPL_LEGACY_HASHING + select SPL_LEGACY_CRYPTO + +config SPL_MBEDTLS_LIB + bool "MbedTLS libraries" + select SPL_MBEDTLS_LIB_X509 +endchoice + +if SPL_LEGACY_HASHING_AND_CRYPTO || SPL_MBEDTLS_LIB_HASHING_ALT + +config SPL_LEGACY_HASHING + bool "Use U-Boot legacy hashing libraries (SPL)" + select SPL_MD5_LEGACY if SPL_MD5 + select SPL_SHA1_LEGACY if SPL_SHA1 + select SPL_SHA256_LEGACY if SPL_SHA256 + select SPL_SHA512_LEGACY if SPL_SHA512 + select SPL_SHA384_LEGACY if SPL_SHA384 + help + Enable U-Boot legacy hashing libraries in SPL. + +if SPL_LEGACY_HASHING + +config SPL_SHA1_LEGACY + bool "Enable SHA1 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with legacy crypto library in SPL. + +config SPL_SHA256_LEGACY + bool "Enable SHA256 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with legacy crypto library in SPL. + +config SPL_SHA512_LEGACY + bool "Enable SHA512 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with legacy crypto library in SPL. + +config SPL_SHA384_LEGACY + bool "Enable SHA384 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_SHA384 + select SPL_SHA512_LEGACY + help + This option enables support of hashing using SHA384 algorithm + with legacy crypto library in SPL. + +config SPL_MD5_LEGACY + bool "Enable MD5 support with legacy crypto library (SPL)" + depends on SPL_LEGACY_HASHING && SPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with legacy crypto library in SPL. + +endif # SPL_LEGACY_HASHING + +config SPL_LEGACY_CRYPTO + bool "legacy certificate libraries (SPL)" + depends on SPL_LEGACY_HASHING_AND_CRYPTO + select SPL_ASN1_DECODER_LEGACY if SPL_ASN1_DECODER + select SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY if \ + SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select SPL_RSA_PUBLIC_KEY_PARSER_LEGACY if SPL_RSA_PUBLIC_KEY_PARSER + help + Enable legacy certificate libraries in SPL. + +if SPL_LEGACY_CRYPTO + +config SPL_ASN1_DECODER_LEGACY + bool "ASN1 decoder with legacy certificate library (SPL)" + depends on SPL_LEGACY_CRYPTO && SPL_ASN1_DECODER + help + This option chooses legacy certificate library for ASN1 decoder in + SPL. + +config SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY + bool "Asymmetric public key crypto with legacy certificate library (SPL)" + depends on SPL_LEGACY_CRYPTO && SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + help + This option chooses legacy certificate library for asymmetric public + key crypto algorithm in SPL. + +config SPL_RSA_PUBLIC_KEY_PARSER_LEGACY + bool "RSA public key parser with legacy certificate library (SPL)" + depends on SPL_ASYMMETRIC_PUBLIC_KEY_LEGACY + select SPL_ASN1_DECODER_LEGACY + help + This option chooses legacy certificate library for RSA public key + parser in SPL. + +endif # SPL_LEGACY_CRYPTO + +endif # SPL_LEGACY_HASHING_AND_CRYPTO || SPL_MBEDTLS_LIB_HASHING_ALT + +if SPL_MBEDTLS_LIB + +config SPL_MBEDTLS_LIB_HASHING_ALT + bool "Replace MbedTLS native hashing with U-Boot legacy libraries (SPL)" + depends on SPL_MBEDTLS_LIB && !SPL_MBEDTLS_LIB_CRYPTO + select SPL_LEGACY_HASHING + default y if SPL_MBEDTLS_LIB && !SPL_MBEDTLS_LIB_CRYPTO + help + Enable MbedTLS hashing alternatives and replace them with legacy hashing + libraries in SPL. + This allows user to use U-Boot legacy hashing algorithms together with + other MbedTLS modules. + Mutually incompatible with SPL_MBEDTLS_LIB_CRYPTO. + +config SPL_MBEDTLS_LIB_CRYPTO + bool "Use MbedTLS native crypto libraries for hashing (SPL)" + default y if SPL_MBEDTLS_LIB + select SPL_MD5_MBEDTLS if SPL_MD5 + select SPL_SHA1_MBEDTLS if SPL_SHA1 + select SPL_SHA256_MBEDTLS if SPL_SHA256 + select SPL_SHA512_MBEDTLS if SPL_SHA512 + select SPL_SHA384_MBEDTLS if SPL_SHA384 + help + Enable MbedTLS native crypto libraries in SPL. + +if SPL_MBEDTLS_LIB_CRYPTO + +config SPL_SHA1_MBEDTLS + bool "Enable SHA1 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with MbedTLS crypto library in SPL. + +config SPL_SHA256_MBEDTLS + bool "Enable SHA256 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with MbedTLS crypto library in SPL. + +config SPL_SHA512_MBEDTLS + bool "Enable SHA512 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with MbedTLS crypto library in SPL. + +config SPL_SHA384_MBEDTLS + bool "Enable SHA384 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_SHA384 + select SPL_SHA512 + help + This option enables support of hashing using SHA384 algorithm + with MbedTLS crypto library in SPL. + +config SPL_MD5_MBEDTLS + bool "Enable MD5 support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO && SPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with MbedTLS crypto library in SPL. + +config SPL_HKDF_MBEDTLS + bool "Enable HKDF support with MbedTLS crypto library (SPL)" + depends on SPL_MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library in SPL. + +endif # SPL_MBEDTLS_LIB_CRYPTO + +config SPL_MBEDTLS_LIB_X509 + bool "MbedTLS certificate libraries (SPL)" + select SPL_ASN1_DECODER_MBEDTLS if SPL_ASN1_DECODER + select SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS if \ + SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select SPL_RSA_PUBLIC_KEY_PARSER_MBEDTLS if SPL_RSA_PUBLIC_KEY_PARSER + help + Enable MbedTLS certificate libraries in SPL. + +if SPL_MBEDTLS_LIB_X509 + config SPL_ASN1_DECODER_MBEDTLS - bool "ASN1 decoder with MbedTLS certificate library in SPL" - depends on MBEDTLS_LIB_X509 && SPL_ASN1_DECODER + bool "ASN1 decoder with MbedTLS certificate library (SPL)" + depends on SPL_MBEDTLS_LIB_X509 && SPL_ASN1_DECODER help This option chooses MbedTLS certificate library for ASN1 decoder in SPL. config SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS - bool "Asymmetric public key crypto with MbedTLS certificate library in SPL" - depends on MBEDTLS_LIB_X509 && SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE + bool "Asymmetric public key crypto with MbedTLS certificate library (SPL)" + depends on SPL_MBEDTLS_LIB_X509 && SPL_ASYMMETRIC_PUBLIC_KEY_SUBTYPE help This option chooses MbedTLS certificate library for asymmetric public key crypto algorithm in SPL. config SPL_RSA_PUBLIC_KEY_PARSER_MBEDTLS - bool "RSA public key parser with MbedTLS certificate library in SPL" + bool "RSA public key parser with MbedTLS certificate library (SPL)" depends on SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS select SPL_ASN1_DECODER_MBEDTLS help This option chooses MbedTLS certificate library for RSA public key parser in SPL. +endif # SPL_MBEDTLS_LIB_X509 + +config SPL_MBEDTLS_LIB_TLS + bool "MbedTLS TLS library (SPL)" + depends on SPL_RSA_PUBLIC_KEY_PARSER_MBEDTLS + depends on SPL_X509_CERTIFICATE_PARSER_MBEDTLS + depends on SPL_ASYMMETRIC_PUBLIC_KEY_MBEDTLS + depends on SPL_ASN1_DECODER_MBEDTLS + depends on SPL_MBEDTLS_LIB + help + Enable MbedTLS TLS library in SPL. Required for HTTPs support + in wget + +endif # SPL_MBEDTLS_LIB + endif # SPL -endif # MBEDTLS_LIB_X509 +# For TPL -config MBEDTLS_LIB_TLS - bool "MbedTLS TLS library" - depends on RSA_PUBLIC_KEY_PARSER_MBEDTLS - depends on X509_CERTIFICATE_PARSER_MBEDTLS - depends on ASYMMETRIC_PUBLIC_KEY_MBEDTLS - depends on ASN1_DECODER_MBEDTLS - depends on ASYMMETRIC_PUBLIC_KEY_MBEDTLS - depends on MBEDTLS_LIB_CRYPTO +if TPL + +choice + prompt "Crypto libraries (TPL)" + default TPL_LEGACY_HASHING_AND_CRYPTO help - Enable MbedTLS TLS library. Required for HTTPs support - in wget + Select crypto libraries in TPL. + TPL_LEGACY_HASHING_AND_CRYPTO for legacy crypto libraries, + TPL_MBEDTLS_LIB for MbedTLS libraries. -endif # MBEDTLS_LIB +config TPL_LEGACY_HASHING_AND_CRYPTO + bool "legacy crypto libraries" + select TPL_LEGACY_HASHING + select TPL_LEGACY_CRYPTO + +config TPL_MBEDTLS_LIB + bool "MbedTLS libraries" + +endchoice + +if TPL_LEGACY_HASHING_AND_CRYPTO || TPL_MBEDTLS_LIB_HASHING_ALT + +config TPL_LEGACY_HASHING + bool "Use U-Boot legacy hashing libraries (TPL)" + select TPL_MD5_LEGACY if TPL_MD5 + select TPL_SHA1_LEGACY if TPL_SHA1 + select TPL_SHA256_LEGACY if TPL_SHA256 + select TPL_SHA512_LEGACY if TPL_SHA512 + select TPL_SHA384_LEGACY if TPL_SHA384 + help + Enable U-Boot legacy hashing libraries in TPL. + +if TPL_LEGACY_HASHING + +config TPL_SHA1_LEGACY + bool "Enable SHA1 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with legacy crypto library in TPL. + +config TPL_SHA256_LEGACY + bool "Enable SHA256 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with legacy crypto library in TPL. + +config TPL_SHA512_LEGACY + bool "Enable SHA512 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with legacy crypto library in TPL. + +config TPL_SHA384_LEGACY + bool "Enable SHA384 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_SHA384 + select TPL_SHA512_LEGACY + help + This option enables support of hashing using SHA384 algorithm + with legacy crypto library in TPL. + +config TPL_MD5_LEGACY + bool "Enable MD5 support with legacy crypto library (TPL)" + depends on TPL_LEGACY_HASHING && TPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with legacy crypto library in TPL. + +endif # TPL_LEGACY_HASHING + +endif # TPL_LEGACY_HASHING_AND_CRYPTO || TPL_MBEDTLS_LIB_HASHING_ALT + +if TPL_MBEDTLS_LIB + +config TPL_MBEDTLS_LIB_HASHING_ALT + bool "Replace MbedTLS native hashing with U-Boot legacy libraries (TPL)" + depends on TPL_MBEDTLS_LIB && !TPL_MBEDTLS_LIB_CRYPTO + select TPL_LEGACY_HASHING + default y if TPL_MBEDTLS_LIB && !TPL_MBEDTLS_LIB_CRYPTO + help + Enable MbedTLS hashing alternatives and replace them with legacy hashing + libraries in TPL. + This allows user to use U-Boot legacy hashing algorithms together with + other MbedTLS modules. + Mutually incompatible with TPL_MBEDTLS_LIB_CRYPTO. + +config TPL_MBEDTLS_LIB_CRYPTO + bool "Use MbedTLS native crypto libraries for hashing (TPL)" + default y if TPL_MBEDTLS_LIB + select TPL_MD5_MBEDTLS if TPL_MD5 + select TPL_SHA1_MBEDTLS if TPL_SHA1 + select TPL_SHA256_MBEDTLS if TPL_SHA256 + select TPL_SHA512_MBEDTLS if TPL_SHA512 + select TPL_SHA384_MBEDTLS if TPL_SHA384 + help + Enable MbedTLS native crypto libraries in TPL. + +if TPL_MBEDTLS_LIB_CRYPTO + +config TPL_SHA1_MBEDTLS + bool "Enable SHA1 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with MbedTLS crypto library in TPL. + +config TPL_SHA256_MBEDTLS + bool "Enable SHA256 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with MbedTLS crypto library in TPL. + +config TPL_SHA512_MBEDTLS + bool "Enable SHA512 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with MbedTLS crypto library in TPL. + +config TPL_SHA384_MBEDTLS + bool "Enable SHA384 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_SHA384 + select TPL_SHA512 + help + This option enables support of hashing using SHA384 algorithm + with MbedTLS crypto library in TPL. + +config TPL_MD5_MBEDTLS + bool "Enable MD5 support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO && TPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with MbedTLS crypto library in TPL. + +config TPL_HKDF_MBEDTLS + bool "Enable HKDF support with MbedTLS crypto library (TPL)" + depends on TPL_MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library in TPL. + +endif # TPL_MBEDTLS_LIB_CRYPTO + +endif # TPL_MBEDTLS_LIB + +endif # TPL + +# For VPL + +if VPL + +choice + prompt "Crypto libraries (VPL)" + default VPL_LEGACY_HASHING_AND_CRYPTO + help + Select crypto libraries in VPL. + VPL_LEGACY_HASHING_AND_CRYPTO for legacy crypto libraries, + VPL_MBEDTLS_LIB for MbedTLS libraries. + +config VPL_LEGACY_HASHING_AND_CRYPTO + bool "legacy crypto libraries" + select VPL_LEGACY_HASHING + +config VPL_MBEDTLS_LIB + bool "MbedTLS libraries" + +endchoice + +if VPL_LEGACY_HASHING_AND_CRYPTO || VPL_MBEDTLS_LIB_HASHING_ALT + +config VPL_LEGACY_HASHING + bool "Use U-Boot legacy hashing libraries (VPL)" + select VPL_MD5_LEGACY if VPL_MD5 + select VPL_SHA1_LEGACY if VPL_SHA1 + select VPL_SHA256_LEGACY if VPL_SHA256 + select VPL_SHA512_LEGACY if VPL_SHA512 + select VPL_SHA384_LEGACY if VPL_SHA384 + help + Enable U-Boot legacy hashing libraries in VPL. + +if VPL_LEGACY_HASHING + +config VPL_SHA1_LEGACY + bool "Enable SHA1 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with legacy crypto library in VPL. + +config VPL_SHA256_LEGACY + bool "Enable SHA256 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with legacy crypto library in VPL. + +config VPL_SHA512_LEGACY + bool "Enable SHA512 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with legacy crypto library in VPL. + +config VPL_SHA384_LEGACY + bool "Enable SHA384 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_SHA384 + select VPL_SHA512_LEGACY + help + This option enables support of hashing using SHA384 algorithm + with legacy crypto library in VPL. + +config VPL_MD5_LEGACY + bool "Enable MD5 support with legacy crypto library (VPL)" + depends on VPL_LEGACY_HASHING && VPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with legacy crypto library in VPL. + +endif # VPL_LEGACY_HASHING + +endif # VPL_LEGACY_HASHING_AND_CRYPTO || VPL_MBEDTLS_LIB_HASHING_ALT + +if VPL_MBEDTLS_LIB + +config VPL_MBEDTLS_LIB_HASHING_ALT + bool "Replace MbedTLS native hashing with U-Boot legacy libraries (VPL)" + depends on VPL_MBEDTLS_LIB && !VPL_MBEDTLS_LIB_CRYPTO + select VPL_LEGACY_HASHING + default y if VPL_MBEDTLS_LIB && !VPL_MBEDTLS_LIB_CRYPTO + help + Enable MbedTLS hashing alternatives and replace them with legacy hashing + libraries in VPL. + This allows user to use U-Boot legacy hashing algorithms together with + other MbedTLS modules. + Mutually incompatible with VPL_MBEDTLS_LIB_CRYPTO. + +config VPL_MBEDTLS_LIB_CRYPTO + bool "Use MbedTLS native crypto libraries for hashing (VPL)" + default y if VPL_MBEDTLS_LIB + select VPL_MD5_MBEDTLS if VPL_MD5 + select VPL_SHA1_MBEDTLS if VPL_SHA1 + select VPL_SHA256_MBEDTLS if VPL_SHA256 + select VPL_SHA512_MBEDTLS if VPL_SHA512 + select VPL_SHA384_MBEDTLS if VPL_SHA384 + help + Enable MbedTLS native crypto libraries in VPL. + +if VPL_MBEDTLS_LIB_CRYPTO + +config VPL_SHA1_MBEDTLS + bool "Enable SHA1 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with MbedTLS crypto library in VPL. + +config VPL_SHA256_MBEDTLS + bool "Enable SHA256 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with MbedTLS crypto library in VPL. + +config VPL_SHA512_MBEDTLS + bool "Enable SHA512 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with MbedTLS crypto library in VPL. + +config VPL_SHA384_MBEDTLS + bool "Enable SHA384 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_SHA384 + select VPL_SHA512 + help + This option enables support of hashing using SHA384 algorithm + with MbedTLS crypto library in VPL. + +config VPL_MD5_MBEDTLS + bool "Enable MD5 support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO && VPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with MbedTLS crypto library in VPL. + +config VPL_HKDF_MBEDTLS + bool "Enable HKDF support with MbedTLS crypto library (VPL)" + depends on VPL_MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library in VPL. + +endif # VPL_MBEDTLS_LIB_CRYPTO + +endif # VPL_MBEDTLS_LIB + +endif # VPL diff --git a/lib/mbedtls/Makefile b/lib/mbedtls/Makefile index e66c2018d97..4bbe7ceec45 100644 --- a/lib/mbedtls/Makefile +++ b/lib/mbedtls/Makefile @@ -6,60 +6,60 @@ MBEDTLS_LIB_DIR = external/mbedtls/library # shim layer for hash -obj-$(CONFIG_$(SPL_)MD5_MBEDTLS) += md5.o -obj-$(CONFIG_$(SPL_)SHA1_MBEDTLS) += sha1.o -obj-$(CONFIG_$(SPL_)SHA256_MBEDTLS) += sha256.o -obj-$(CONFIG_$(SPL_)SHA512_MBEDTLS) += sha512.o +obj-$(CONFIG_$(XPL_)MD5_MBEDTLS) += md5.o +obj-$(CONFIG_$(XPL_)SHA1_MBEDTLS) += sha1.o +obj-$(CONFIG_$(XPL_)SHA256_MBEDTLS) += sha256.o +obj-$(CONFIG_$(XPL_)SHA512_MBEDTLS) += sha512.o # x509 libraries -obj-$(CONFIG_$(SPL_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ +obj-$(CONFIG_$(XPL_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ public_key.o -obj-$(CONFIG_$(SPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \ +obj-$(CONFIG_$(XPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \ x509_cert_parser.o -obj-$(CONFIG_$(SPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += pkcs7_parser.o -obj-$(CONFIG_$(SPL_)MSCODE_PARSER_MBEDTLS) += mscode_parser.o -obj-$(CONFIG_$(SPL_)RSA_PUBLIC_KEY_PARSER_MBEDTLS) += rsa_helper.o +obj-$(CONFIG_$(XPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += pkcs7_parser.o +obj-$(CONFIG_$(XPL_)MSCODE_PARSER_MBEDTLS) += mscode_parser.o +obj-$(CONFIG_$(XPL_)RSA_PUBLIC_KEY_PARSER_MBEDTLS) += rsa_helper.o # MbedTLS crypto library -obj-$(CONFIG_MBEDTLS_LIB) += mbedtls_lib_crypto.o +obj-$(CONFIG_$(XPL_)MBEDTLS_LIB) += mbedtls_lib_crypto.o mbedtls_lib_crypto-y := \ $(MBEDTLS_LIB_DIR)/platform_util.o \ $(MBEDTLS_LIB_DIR)/constant_time.o \ $(MBEDTLS_LIB_DIR)/md.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)MD5_MBEDTLS) += $(MBEDTLS_LIB_DIR)/md5.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA1_MBEDTLS) += $(MBEDTLS_LIB_DIR)/sha1.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA256_MBEDTLS) += \ +mbedtls_lib_crypto-$(CONFIG_$(XPL_)MD5_MBEDTLS) += $(MBEDTLS_LIB_DIR)/md5.o +mbedtls_lib_crypto-$(CONFIG_$(XPL_)SHA1_MBEDTLS) += $(MBEDTLS_LIB_DIR)/sha1.o +mbedtls_lib_crypto-$(CONFIG_$(XPL_)SHA256_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/sha256.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA512_MBEDTLS) += \ +mbedtls_lib_crypto-$(CONFIG_$(XPL_)SHA512_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/sha512.o -mbedtls_lib_crypto-$(CONFIG_$(SPL_)HKDF_MBEDTLS) += \ +mbedtls_lib_crypto-$(CONFIG_$(XPL_)HKDF_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/hkdf.o # MbedTLS X509 library -obj-$(CONFIG_MBEDTLS_LIB_X509) += mbedtls_lib_x509.o +obj-$(CONFIG_$(XPL_)MBEDTLS_LIB_X509) += mbedtls_lib_x509.o mbedtls_lib_x509-y := $(MBEDTLS_LIB_DIR)/x509.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)ASN1_DECODER_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)ASN1_DECODER_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/asn1parse.o \ $(MBEDTLS_LIB_DIR)/asn1write.o \ $(MBEDTLS_LIB_DIR)/oid.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)RSA_PUBLIC_KEY_PARSER_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)RSA_PUBLIC_KEY_PARSER_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/bignum.o \ $(MBEDTLS_LIB_DIR)/bignum_core.o \ $(MBEDTLS_LIB_DIR)/rsa.o \ $(MBEDTLS_LIB_DIR)/rsa_alt_helpers.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)ASYMMETRIC_PUBLIC_KEY_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/pk.o \ $(MBEDTLS_LIB_DIR)/pk_wrap.o \ $(MBEDTLS_LIB_DIR)/pkparse.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)X509_CERTIFICATE_PARSER_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/x509_crl.o \ $(MBEDTLS_LIB_DIR)/x509_crt.o -mbedtls_lib_x509-$(CONFIG_$(SPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += \ +mbedtls_lib_x509-$(CONFIG_$(XPL_)PKCS7_MESSAGE_PARSER_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/pkcs7.o #mbedTLS TLS support -obj-$(CONFIG_MBEDTLS_LIB_TLS) += mbedtls_lib_tls.o +obj-$(CONFIG_$(XPL_)MBEDTLS_LIB_TLS) += mbedtls_lib_tls.o mbedtls_lib_tls-y := \ $(MBEDTLS_LIB_DIR)/mps_reader.o \ $(MBEDTLS_LIB_DIR)/mps_trace.o \ diff --git a/lib/mbedtls/mbedtls_def_config.h b/lib/mbedtls/mbedtls_def_config.h index fd440c392f9..dda3f4dd6e4 100644 --- a/lib/mbedtls/mbedtls_def_config.h +++ b/lib/mbedtls/mbedtls_def_config.h @@ -11,12 +11,12 @@ * Author: Raymond Mao <raymond.mao@linaro.org> */ -#if defined CONFIG_MBEDTLS_LIB +#if CONFIG_IS_ENABLED(MBEDTLS_LIB) #if CONFIG_IS_ENABLED(MD5) #define MBEDTLS_MD_C #define MBEDTLS_MD5_C -#if defined CONFIG_MBEDTLS_LIB_CRYPTO_ALT +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_HASHING_ALT) #define MBEDTLS_MD5_ALT #endif #endif @@ -24,7 +24,7 @@ #if CONFIG_IS_ENABLED(SHA1) #define MBEDTLS_MD_C #define MBEDTLS_SHA1_C -#if defined CONFIG_MBEDTLS_LIB_CRYPTO_ALT +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_HASHING_ALT) #define MBEDTLS_SHA1_ALT #endif #endif @@ -32,7 +32,7 @@ #if CONFIG_IS_ENABLED(SHA256) #define MBEDTLS_MD_C #define MBEDTLS_SHA256_C -#if defined CONFIG_MBEDTLS_LIB_CRYPTO_ALT +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_HASHING_ALT) #define MBEDTLS_SHA256_ALT #endif #if CONFIG_IS_ENABLED(SHA256_SMALLER) @@ -48,7 +48,7 @@ #if CONFIG_IS_ENABLED(SHA512) #define MBEDTLS_MD_C #define MBEDTLS_SHA512_C -#if defined CONFIG_MBEDTLS_LIB_CRYPTO_ALT +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_HASHING_ALT) #define MBEDTLS_SHA512_ALT #endif #if CONFIG_IS_ENABLED(SHA512_SMALLER) @@ -60,7 +60,7 @@ #define MBEDTLS_HKDF_C #endif -#if defined CONFIG_MBEDTLS_LIB_X509 +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_X509) #if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) #define MBEDTLS_X509_USE_C @@ -89,9 +89,9 @@ #define MBEDTLS_ASN1_WRITE_C #endif -#endif /* #if defined CONFIG_MBEDTLS_LIB_X509 */ +#endif /* #if CONFIG_IS_ENABLED(MBEDTLS_LIB_X509) */ -#if IS_ENABLED(CONFIG_MBEDTLS_LIB_TLS) +#if CONFIG_IS_ENABLED(MBEDTLS_LIB_TLS) #include "rtc.h" /* Generic options */ @@ -106,25 +106,36 @@ #define MBEDTLS_ENTROPY_C #define MBEDTLS_NO_PLATFORM_ENTROPY #define MBEDTLS_SSL_PROTO_TLS1_2 +#if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) #define MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif #define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED /* RSA */ +#if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) && \ + CONFIG_IS_ENABLED(RSA_PUBLIC_KEY_PARSER) #define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED #define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif #define MBEDTLS_GCM_C /* ECDSA */ +#if CONFIG_IS_ENABLED(ASN1_DECODER) #define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C #define MBEDTLS_ECDH_C +#endif #define MBEDTLS_ECDSA_DETERMINISTIC #define MBEDTLS_HMAC_DRBG_C -#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED -#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + #define MBEDTLS_CAN_ECDH #define MBEDTLS_PK_CAN_ECDSA_SIGN -#define MBEDTLS_ECP_C +#if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif + #define MBEDTLS_ECP_DP_SECP256K1_ENABLED #define MBEDTLS_ECP_DP_SECP192R1_ENABLED #define MBEDTLS_ECP_DP_SECP224R1_ENABLED @@ -138,6 +149,6 @@ #define MBEDTLS_ECP_DP_BP384R1_ENABLED #define MBEDTLS_ECP_DP_BP512R1_ENABLED -#endif /* #if defined CONFIG_MBEDTLS_LIB_TLS */ +#endif /* #if CONFIG_IS_ENABLED(MBEDTLS_LIB_TLS) */ -#endif /* #if defined CONFIG_MBEDTLS_LIB */ +#endif /* #if CONFIG_IS_ENABLED(MBEDTLS_LIB) */ diff --git a/lib/mbedtls/port/mbedtls_options.h b/lib/mbedtls/port/mbedtls_options.h new file mode 100644 index 00000000000..885ed6990b6 --- /dev/null +++ b/lib/mbedtls/port/mbedtls_options.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Internal build options for MbedTLS + * + * Copyright (c) 2025 Linaro Limited + * Author: Raymond Mao <raymond.mao@linaro.org> + */ + +#ifndef _MBEDTLS_OPT_H +#define _MBEDTLS_OPT_H + +/* + * FIXME: + * U-Boot/MbedTLS port requires to access a few of members which are defined + * as private in MbedTLS context. + * E.g: x509_internal.h, mbedtls_sha256_context and mbedtls_sha1_context. + * MBEDTLS_ALLOW_PRIVATE_ACCESS needs to be enabled to allow the external + * access, but directly including <external/mbedtls/library/common.h> is not + * allowed, since this will include <malloc.h> and break the sandbox test. + */ +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + +#endif /* _MBEDTLS_OPT_H */ diff --git a/net/eth_common.c b/net/eth_common.c index 89b5bb37189..ba57d836b0b 100644 --- a/net/eth_common.c +++ b/net/eth_common.c @@ -31,11 +31,6 @@ int eth_env_set_enetaddr_by_index(const char *base_name, int index, void eth_common_init(void) { bootstage_mark(BOOTSTAGE_ID_NET_ETH_START); -#if CONFIG_IS_ENABLED(ETH) -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) || defined(CONFIG_PHYLIB) - miiphy_init(); -#endif -#endif } int eth_mac_skip(int index) diff --git a/net/lwip/Kconfig b/net/lwip/Kconfig index 40345ced9c9..d28a8a7df94 100644 --- a/net/lwip/Kconfig +++ b/net/lwip/Kconfig @@ -10,6 +10,12 @@ config LWIP_DEBUG Prints messages to the console regarding network packets that go in and out of the lwIP library. +config LWIP_DEBUG_RXTX + bool "Dump packets sent and received by lwIP" + help + Performs an hexadecimal & ASCII dump of the data received and sent by + the lwIP network stack. + config LWIP_ASSERT bool "Enable assertions in the lwIP library" help diff --git a/net/lwip/Makefile b/net/lwip/Makefile index 79dd6b3fb50..950c5316bb9 100644 --- a/net/lwip/Makefile +++ b/net/lwip/Makefile @@ -6,3 +6,9 @@ obj-$(CONFIG_CMD_DNS) += dns.o obj-$(CONFIG_CMD_PING) += ping.o obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o obj-$(CONFIG_WGET) += wget.o + +ifeq (y,$(CONFIG_WGET_BUILTIN_CACERT)) +$(obj)/builtin_cacert.c: $(CONFIG_WGET_BUILTIN_CACERT_PATH:"%"=%) FORCE + $(call if_changed,bin2c,builtin_cacert) +obj-y += builtin_cacert.o +endif diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c index cab1dd7d483..c00a7fe97cd 100644 --- a/net/lwip/net-lwip.c +++ b/net/lwip/net-lwip.c @@ -5,6 +5,7 @@ #include <command.h> #include <dm/device.h> #include <dm/uclass.h> +#include <hexdump.h> #include <lwip/ip4_addr.h> #include <lwip/err.h> #include <lwip/netif.h> @@ -30,12 +31,18 @@ char *pxelinux_configfile; struct in_addr net_ip; char net_boot_file_name[1024]; -static err_t linkoutput(struct netif *netif, struct pbuf *p) +static err_t net_lwip_tx(struct netif *netif, struct pbuf *p) { struct udevice *udev = netif->state; void *pp = NULL; int err; + if (CONFIG_IS_ENABLED(LWIP_DEBUG_RXTX)) { + printf("net_lwip_tx: %u bytes, udev %s\n", p->len, udev->name); + print_hex_dump("net_lwip_tx: ", 0, 16, 1, p->payload, p->len, + true); + } + if ((unsigned long)p->payload % PKTALIGN) { /* * Some net drivers have strict alignment requirements and may @@ -60,7 +67,7 @@ static err_t linkoutput(struct netif *netif, struct pbuf *p) static err_t net_lwip_if_init(struct netif *netif) { netif->output = etharp_output; - netif->linkoutput = linkoutput; + netif->linkoutput = net_lwip_tx; netif->mtu = 1500; netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP; @@ -265,6 +272,13 @@ int net_lwip_rx(struct udevice *udev, struct netif *netif) flags = 0; if (len > 0) { + if (CONFIG_IS_ENABLED(LWIP_DEBUG_RXTX)) { + printf("net_lwip_tx: %u bytes, udev %s \n", len, + udev->name); + print_hex_dump("net_lwip_rx: ", 0, 16, 1, + packet, len, true); + } + pbuf = alloc_pbuf_and_copy(packet, len); if (pbuf) netif->input(pbuf, netif); diff --git a/net/lwip/wget.c b/net/lwip/wget.c index 14f27d42998..ec098148835 100644 --- a/net/lwip/wget.c +++ b/net/lwip/wget.c @@ -285,9 +285,96 @@ static err_t httpc_headers_done_cb(httpc_state_t *connection, void *arg, struct return ERR_OK; } +#if CONFIG_IS_ENABLED(WGET_HTTPS) +enum auth_mode { + AUTH_NONE, + AUTH_OPTIONAL, + AUTH_REQUIRED, +}; + +static char *cacert; +static size_t cacert_size; +static enum auth_mode cacert_auth_mode = AUTH_OPTIONAL; +#endif + +#if CONFIG_IS_ENABLED(WGET_CACERT) +static int set_auth(enum auth_mode auth) +{ + cacert_auth_mode = auth; + + return CMD_RET_SUCCESS; +} +#endif + +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) +extern const char builtin_cacert[]; +extern const size_t builtin_cacert_size; +static bool cacert_initialized; +#endif + +#if CONFIG_IS_ENABLED(WGET_CACERT) || CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) +static int _set_cacert(const void *addr, size_t sz) +{ + mbedtls_x509_crt crt; + void *p; + int ret; + + if (cacert) + free(cacert); + + if (!addr) { + cacert = NULL; + cacert_size = 0; + return CMD_RET_SUCCESS; + } + + p = malloc(sz); + if (!p) + return CMD_RET_FAILURE; + cacert = p; + cacert_size = sz; + + memcpy(cacert, (void *)addr, sz); + + mbedtls_x509_crt_init(&crt); + ret = mbedtls_x509_crt_parse(&crt, cacert, cacert_size); + if (ret) { + printf("Could not parse certificates (%d)\n", ret); + free(cacert); + cacert = NULL; + cacert_size = 0; + return CMD_RET_FAILURE; + } + +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) + cacert_initialized = true; +#endif + return CMD_RET_SUCCESS; +} + +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) +static int set_cacert_builtin(void) +{ + return _set_cacert(builtin_cacert, builtin_cacert_size); +} +#endif + +#if CONFIG_IS_ENABLED(WGET_CACERT) +static int set_cacert(char * const saddr, char * const ssz) +{ + ulong addr, sz; + + addr = hextoul(saddr, NULL); + sz = hextoul(ssz, NULL); + + return _set_cacert((void *)addr, sz); +} +#endif +#endif /* CONFIG_WGET_CACERT || CONFIG_WGET_BUILTIN_CACERT */ + static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) { -#if defined CONFIG_WGET_HTTPS +#if CONFIG_IS_ENABLED(WGET_HTTPS) altcp_allocator_t tls_allocator; #endif httpc_connection_t conn; @@ -312,11 +399,41 @@ static int wget_loop(struct udevice *udev, ulong dst_addr, char *uri) return -1; memset(&conn, 0, sizeof(conn)); -#if defined CONFIG_WGET_HTTPS +#if CONFIG_IS_ENABLED(WGET_HTTPS) if (is_https) { + char *ca; + size_t ca_sz; + +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) + if (!cacert_initialized) + set_cacert_builtin(); +#endif + ca = cacert; + ca_sz = cacert_size; + + if (cacert_auth_mode == AUTH_REQUIRED) { + if (!ca || !ca_sz) { + printf("Error: cacert authentication mode is " + "'required' but no CA certificates " + "given\n"); + return CMD_RET_FAILURE; + } + } else if (cacert_auth_mode == AUTH_NONE) { + ca = NULL; + ca_sz = 0; + } else if (cacert_auth_mode == AUTH_OPTIONAL) { + /* + * Nothing to do, this is the default behavior of + * altcp_tls to check server certificates against CA + * certificates when the latter are provided and proceed + * with no verification if not. + */ + } + tls_allocator.alloc = &altcp_tls_alloc; tls_allocator.arg = - altcp_tls_create_config_client(NULL, 0, ctx.server_name); + altcp_tls_create_config_client(ca, ca_sz, + ctx.server_name); if (!tls_allocator.arg) { log_err("error: Cannot create a TLS connection\n"); @@ -369,6 +486,24 @@ int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) ulong dst_addr; char nurl[1024]; +#if CONFIG_IS_ENABLED(WGET_CACERT) + if (argc == 4 && !strncmp(argv[1], "cacert", strlen("cacert"))) + return set_cacert(argv[2], argv[3]); + if (argc == 3 && !strncmp(argv[1], "cacert", strlen("cacert"))) { +#if CONFIG_IS_ENABLED(WGET_BUILTIN_CACERT) + if (!strncmp(argv[2], "builtin", strlen("builtin"))) + return set_cacert_builtin(); +#endif + if (!strncmp(argv[2], "none", strlen("none"))) + return set_auth(AUTH_NONE); + if (!strncmp(argv[2], "optional", strlen("optional"))) + return set_auth(AUTH_OPTIONAL); + if (!strncmp(argv[2], "required", strlen("required"))) + return set_auth(AUTH_REQUIRED); + return CMD_RET_USAGE; + } +#endif + if (argc < 2 || argc > 3) return CMD_RET_USAGE; diff --git a/net/wget.c b/net/wget.c index 0b082c61947..c73836cbc9d 100644 --- a/net/wget.c +++ b/net/wget.c @@ -53,6 +53,9 @@ static inline int store_block(uchar *src, unsigned int offset, unsigned int len) ulong store_addr = image_load_addr + offset; uchar *ptr; + // Avoid overflow + if (wget_info->buffer_size && wget_info->buffer_size < offset + len) + return -1; if (CONFIG_IS_ENABLED(LMB) && wget_info->set_bootdev) { if (store_addr < image_load_addr || lmb_read_check(store_addr, len)) { @@ -98,12 +101,6 @@ static void tcp_stream_on_closed(struct tcp_stream *tcp) net_set_state(wget_loop_state); if (wget_loop_state != NETLOOP_SUCCESS) { net_boot_file_size = 0; - if (wget_info->status_code == HTTP_STATUS_OK) { - wget_info->status_code = HTTP_STATUS_BAD; - wget_info->hdr_cont_len = 0; - if (wget_info->headers) - wget_info->headers[0] = 0; - } printf("\nwget: Transfer Fail, TCP status - %d\n", tcp->status); return; } @@ -212,6 +209,11 @@ static void tcp_stream_on_rcv_nxt_update(struct tcp_stream *tcp, u32 rx_bytes) "wget: Connected Len %lu\n", content_length); wget_info->hdr_cont_len = content_length; + if (wget_info->buffer_size && wget_info->buffer_size < wget_info->hdr_cont_len){ + tcp_stream_reset(tcp); + goto end; + } + } net_boot_file_size = rx_bytes - http_hdr_size; @@ -227,7 +229,9 @@ static int tcp_stream_rx(struct tcp_stream *tcp, u32 rx_offs, void *buf, int len if ((max_rx_pos == (u32)(-1)) || (max_rx_pos < rx_offs + len - 1)) max_rx_pos = rx_offs + len - 1; - store_block(buf, rx_offs - http_hdr_size, len); + // Avoid overflow + if (store_block(buf, rx_offs - http_hdr_size, len) < 0) + return -1; return len; } diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index b8eb57f38c7..f9f8891c0c4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -7205,8 +7205,8 @@ sub process { # check for IS_ENABLED() without CONFIG_<FOO> ($rawline for comments too) if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) { - WARN("IS_ENABLED_CONFIG", - "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr); + ERROR("IS_ENABLED_CONFIG", + "IS_ENABLED($1) must be used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr); } # check for #if defined CONFIG_<FOO> || defined CONFIG_<FOO>_MODULE diff --git a/test/dm/Makefile b/test/dm/Makefile index e44f3d89e77..3afcc26ca57 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_SOUND) += i2s.o obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o obj-$(CONFIG_IOMMU) += iommu.o obj-$(CONFIG_LED) += led.o +obj-$(CONFIG_VIDEO_BRIDGE_LVDS_CODEC) += video_bridge.o obj-$(CONFIG_DM_MAILBOX) += mailbox.o obj-$(CONFIG_DM_MDIO) += mdio.o obj-$(CONFIG_DM_MDIO_MUX) += mdio_mux.o diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c index cc8b444ff9a..0f60c2a6281 100644 --- a/test/dm/ofnode.c +++ b/test/dm/ofnode.c @@ -23,6 +23,7 @@ #include <dm/device-internal.h> #include <dm/lists.h> #include <dm/of_extra.h> +#include <dm/ofnode_graph.h> #include <dm/root.h> #include <dm/test.h> #include <dm/uclass-internal.h> @@ -1651,3 +1652,56 @@ static int dm_test_bool(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_bool, UTF_SCAN_FDT); + +/* test all helpers found in drivers/core/ofnode_graph.c */ +static int dm_test_ofnode_graph(struct unit_test_state *uts) +{ + /* 3 ports with 5 endpoints (2-1-2) */ + ofnode graph1 = ofnode_path("/graph1"); + /* 1 port with 1 endpoint */ + ofnode graph2 = ofnode_path("/graph2"); + ofnode node; + u32 id; + + ut_asserteq(ofnode_graph_get_endpoint_count(graph1), 5); + ut_asserteq(ofnode_graph_get_endpoint_count(graph2), 1); + + ut_asserteq(ofnode_graph_get_port_count(graph1), 3); + ut_asserteq(ofnode_graph_get_port_count(graph2), 1); + + /* Request port with reg 2 */ + node = ofnode_graph_get_port_by_id(graph1, 2); + ofnode_read_u32(node, "reg", &id); + ut_asserteq(id, 2); + + /* Reqest parent from prev requested endpoint */ + node = ofnode_graph_get_port_parent(node); + ut_asserteq_str(ofnode_get_name(node), "graph1"); + + /* Request endpoint under port 1 */ + node = ofnode_graph_get_endpoint_by_regs(graph1, 1, -1); + ut_assert(ofnode_has_property(node, "test-property-0")); + + /* Reqest remote endpoint from graph2 in graph1 */ + node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1); + node = ofnode_graph_get_remote_endpoint(node); + ut_assert(ofnode_has_property(node, "test-property-1")); + + /* Reqest remote parent from graph2 linked endpoint */ + node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1); + node = ofnode_graph_get_remote_port_parent(node); + ut_asserteq_str(ofnode_get_name(node), "graph1"); + + /* Reqest remote port from graph2 linked endpoint */ + node = ofnode_graph_get_endpoint_by_regs(graph2, -1, -1); + node = ofnode_graph_get_remote_port(node); + ofnode_read_u32(node, "reg", &id); + ut_asserteq(id, 2); + + /* Reqest remote parent from graph2 linked endpoint */ + node = ofnode_graph_get_remote_node(graph2, -1, -1); + ut_asserteq_str(ofnode_get_name(node), "graph1"); + + return 0; +} +DM_TEST(dm_test_ofnode_graph, UTF_SCAN_FDT); diff --git a/test/dm/video_bridge.c b/test/dm/video_bridge.c new file mode 100644 index 00000000000..f55a333c0b8 --- /dev/null +++ b/test/dm/video_bridge.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for video bridge uclass + * + * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <backlight.h> +#include <dm.h> +#include <panel.h> +#include <video.h> +#include <video_bridge.h> +#include <asm/gpio.h> +#include <asm/test.h> +#include <dm/test.h> +#include <power/regulator.h> +#include <test/test.h> +#include <test/ut.h> + +/* Basic test of the video uclass, test is based on driven panel */ +static int dm_test_video_bridge(struct unit_test_state *uts) +{ + struct udevice *dev, *pwm, *gpio, *reg; + uint period_ns, duty_ns; + bool enable, polarity; + struct display_timing timing; + + ut_assertok(uclass_first_device_err(UCLASS_VIDEO_BRIDGE, &dev)); + ut_assertok(uclass_get_device_by_name(UCLASS_PWM, "pwm", &pwm)); + ut_assertok(uclass_get_device(UCLASS_GPIO, 1, &gpio)); + ut_assertok(regulator_get_by_platname("VDD_EMMC_1.8V", ®)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(false, enable); + ut_asserteq(true, regulator_get_enable(reg)); + + /* bridge calls panel_enable_backlight() of panel */ + ut_assertok(video_bridge_attach(dev)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(1000, period_ns); + ut_asserteq(170 * 1000 / 255, duty_ns); + ut_asserteq(true, enable); + ut_asserteq(false, polarity); + ut_asserteq(1, sandbox_gpio_get_value(gpio, 1)); + ut_asserteq(true, regulator_get_enable(reg)); + + /* bridge calls panel_set_backlight() of panel */ + ut_assertok(video_bridge_set_backlight(dev, BACKLIGHT_DEFAULT)); + ut_assertok(sandbox_pwm_get_config(pwm, 0, &period_ns, &duty_ns, + &enable, &polarity)); + ut_asserteq(true, enable); + ut_asserteq(170 * 1000 / 255, duty_ns); + + /* bridge should be active */ + ut_assertok(video_bridge_set_active(dev, true)); + + /* bridge is internal and has no hotplug gpio */ + ut_asserteq(-ENOENT, video_bridge_check_attached(dev)); + + /* check passing timings and EDID */ + ut_assertok(video_bridge_get_display_timing(dev, &timing)); + ut_assertok(video_bridge_read_edid(dev, NULL, 0)); + + return 0; +} +DM_TEST(dm_test_video_bridge, UTF_SCAN_PDATA | UTF_SCAN_FDT); diff --git a/test/lib/kconfig.c b/test/lib/kconfig.c index a3645abf946..2f47af9acf1 100644 --- a/test/lib/kconfig.c +++ b/test/lib/kconfig.c @@ -22,10 +22,10 @@ static int lib_test_is_enabled(struct unit_test_state *uts) ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED)); if (IS_ENABLED(CONFIG_BLOBLIST)) { - ut_asserteq(0xb000, IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, - CONFIG_BLOBLIST_ADDR)); - ut_asserteq(0xb000, CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED, - BLOBLIST_ADDR)); + ut_asserteq(0x100, IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, + CONFIG_BLOBLIST_ADDR)); + ut_asserteq(0x100, CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED, + BLOBLIST_ADDR)); } /* diff --git a/test/lib/longjmp.c b/test/lib/longjmp.c index 79d889bdd5f..74c3465b8c2 100644 --- a/test/lib/longjmp.c +++ b/test/lib/longjmp.c @@ -5,10 +5,10 @@ * Copyright (c) 2021, Heinrich Schuchardt <xypron.glpk@gmx.de> */ +#include <setjmp.h> #include <test/lib.h> #include <test/test.h> #include <test/ut.h> -#include <asm/setjmp.h> struct test_jmp_buf { jmp_buf env; diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst index 990fc295770..84b1331df5c 100644 --- a/tools/binman/binman.rst +++ b/tools/binman/binman.rst @@ -823,24 +823,6 @@ multiple-images: }; }; -end-at-4gb: - For x86 machines the ROM offsets start just before 4GB and extend - up so that the image finished at the 4GB boundary. This boolean - option can be enabled to support this. The image size must be - provided so that binman knows when the image should start. For an - 8MB ROM, the offset of the first entry would be 0xfff80000 with - this option, instead of 0 without this option. - -skip-at-start: - This property specifies the entry offset of the first entry. - - For PowerPC mpc85xx based CPU, CONFIG_TEXT_BASE is the entry - offset of the first entry. It can be 0xeff40000 or 0xfff40000 for - nor flash boot, 0x201000 for sd boot etc. - - 'end-at-4gb' property is not applicable where CONFIG_TEXT_BASE + - Image size != 4gb. - align-default: Specifies the default alignment for entries in this section if they do not specify an alignment. Note that this only applies to top-level entries @@ -957,6 +939,35 @@ filename: section in different image, since there is currently no way to share data between images other than through files. +end-at-4gb: + For x86 machines the ROM offsets start just before 4GB and extend + up so that the image finished at the 4GB boundary. This boolean + option can be enabled to support this. The image size must be + provided so that binman knows when the image should start. For an + 8MB ROM, the offset of the first entry would be 0xfff80000 with + this option, instead of 0 without this option. + +skip-at-start: + This property specifies the entry offset of the first entry in the section. + It is useful when the Binman image is written to a particular offset in the + media. It allows the offset of the first entry to be the media offset, even + though it is at the start of the image. It effectively creates a hole at the + start of the image, an implied, empty area. + + For example, if the image is written to offset 4K on the media, set + skip-at-start to 0x1000. At runtime, the Binman image will assume that it + has be written at offset 4K and all symbols and offsets will take account of + that. The image-pos values will also be adjusted. The effect is similar to + adding an empty 4K region at the start, except that Binman does not actually + output it. + + For PowerPC mpc85xx based CPU, CONFIG_TEXT_BASE is the entry + offset of the first entry. It can be 0xeff40000 or 0xfff40000 for + nor flash boot, 0x201000 for sd boot etc. + + 'end-at-4gb' property is not applicable where CONFIG_TEXT_BASE + + Image size != 4gb. + Image Properties ---------------- diff --git a/tools/binman/bintool.py b/tools/binman/bintool.py index 3c4ad1adbb9..81872db377f 100644 --- a/tools/binman/bintool.py +++ b/tools/binman/bintool.py @@ -328,7 +328,8 @@ class Bintool: return result.stdout @classmethod - def build_from_git(cls, git_repo, make_targets, bintool_path, flags=None): + def build_from_git(cls, git_repo, make_targets, bintool_path, + flags=None, git_branch=None, make_path=None): """Build a bintool from a git repo This clones the repo in a temporary directory, builds it with 'make', @@ -341,6 +342,9 @@ class Bintool: bintool_path (str): Relative path of the tool in the repo, after build is complete flags (list of str): Flags or variables to pass to make, or None + git_branch (str): Branch of git repo, or None to use the default + make_path (str): Relative path inside git repo containing the + Makefile, or None Returns: tuple: @@ -350,10 +354,17 @@ class Bintool: """ tmpdir = tempfile.mkdtemp(prefix='binmanf.') print(f"- clone git repo '{git_repo}' to '{tmpdir}'") - tools.run('git', 'clone', '--depth', '1', git_repo, tmpdir) + if git_branch: + tools.run('git', 'clone', '--depth', '1', '--branch', git_branch, + git_repo, tmpdir) + else: + tools.run('git', 'clone', '--depth', '1', git_repo, tmpdir) for target in make_targets: print(f"- build target '{target}'") - cmd = ['make', '-C', tmpdir, '-j', f'{multiprocessing.cpu_count()}', + makedir = tmpdir + if make_path: + makedir = os.path.join(tmpdir, make_path) + cmd = ['make', '-C', makedir, '-j', f'{multiprocessing.cpu_count()}', target] if flags: cmd += flags diff --git a/tools/binman/bintool_test.py b/tools/binman/bintool_test.py index f9b16d4c73b..949d6f4c8a9 100644 --- a/tools/binman/bintool_test.py +++ b/tools/binman/bintool_test.py @@ -303,6 +303,7 @@ class TestBintool(unittest.TestCase): # See Bintool.build_from_git() tmpdir = cmd[2] self.fname = os.path.join(tmpdir, 'pathname') + os.makedirs(os.path.dirname(tmpdir), exist_ok=True) tools.write_file(self.fname, b'hello') expected = b'this is a test' diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst index cd05ad8cb26..9f6cab544a5 100644 --- a/tools/binman/bintools.rst +++ b/tools/binman/bintools.rst @@ -52,6 +52,14 @@ Bintool: cst: Image generation for U-Boot This bintool supports running `cst` with some basic parameters as needed by binman. +cst (imx code signing tool) is used for sigining bootloader binaries for +various i.MX SoCs. + +See `Code Signing Tool Users Guide`_ for more information. + +.. _`Code Signing Tool Users Guide`: + https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/imx-processors/202591/1/CST_UG.pdf + Bintool: fdt_add_pubkey: Add public key to control dtb (spl or u-boot proper) diff --git a/tools/binman/btool/cst.py b/tools/binman/btool/cst.py index 30e78bdbbd9..8a3981adc89 100644 --- a/tools/binman/btool/cst.py +++ b/tools/binman/btool/cst.py @@ -12,6 +12,14 @@ class Bintoolcst(bintool.Bintool): This bintool supports running `cst` with some basic parameters as needed by binman. + + cst (imx code signing tool) is used for sigining bootloader binaries for + various i.MX SoCs. + + See `Code Signing Tool Users Guide`_ for more information. + + .. _`Code Signing Tool Users Guide`: + https://community.nxp.com/pwmxy87654/attachments/pwmxy87654/imx-processors/202591/1/CST_UG.pdf """ def __init__(self, name): super().__init__(name, 'Sign NXP i.MX image') @@ -29,20 +37,17 @@ class Bintoolcst(bintool.Bintool): return self.run_cmd(*args) def fetch(self, method): - """Fetch handler for cst - - This installs cst using the apt utility. - - Args: - method (FETCH_...): Method to use - - Returns: - True if the file was fetched and now installed, None if a method - other than FETCH_BIN was requested - - Raises: - Valuerror: Fetching could not be completed - """ - if method != bintool.FETCH_BIN: + """Build cst from git""" + if method != bintool.FETCH_BUILD: return None - return self.apt_install('imx-code-signing-tool') + + from platform import architecture + arch = 'linux64' if architecture()[0] == '64bit' else 'linux32' + result = self.build_from_git( + 'https://gitlab.apertis.org/pkg/imx-code-signing-tool', + ['all'], + f'code/obj.{arch}/cst', + flags=[f'OSTYPE={arch}', 'ENCRYPTION=yes'], + git_branch='debian/unstable', + make_path=f'code/obj.{arch}/') + return result diff --git a/tools/binman/entry.py b/tools/binman/entry.py index 68f8d62bba9..bdc60e47fca 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -392,9 +392,8 @@ class Entry(object): """Set the value of device-tree properties calculated by binman""" state.SetInt(self._node, 'offset', self.offset) state.SetInt(self._node, 'size', self.size) - base = self.section.GetRootSkipAtStart() if self.section else 0 if self.image_pos is not None: - state.SetInt(self._node, 'image-pos', self.image_pos - base) + state.SetInt(self._node, 'image-pos', self.image_pos) if self.GetImage().allow_repack: if self.orig_offset is not None: state.SetInt(self._node, 'orig-offset', self.orig_offset, True) @@ -722,7 +721,7 @@ class Entry(object): is_elf = self.GetDefaultFilename() == self.elf_fname symbols_base = self.symbols_base - if symbols_base is None and self.GetImage()._end_4gb: + if symbols_base is None and self.GetImage()._end_at_4gb: symbols_base = 0 elf.LookupAndWriteSymbols(self.elf_fname, self, section.GetImage(), diff --git a/tools/binman/etype/fmap.py b/tools/binman/etype/fmap.py index 3669d91a0bc..35ca8490f79 100644 --- a/tools/binman/etype/fmap.py +++ b/tools/binman/etype/fmap.py @@ -65,7 +65,7 @@ class Entry_fmap(Entry): if entry.image_pos is None: pos = 0 else: - pos = entry.image_pos - entry.GetRootSkipAtStart() + pos = entry.image_pos # Drop @ symbols in name name = entry.name.replace('@', '') @@ -75,8 +75,6 @@ class Entry_fmap(Entry): _AddEntries(areas, subentry) else: pos = entry.image_pos - if pos is not None: - pos -= entry.section.GetRootSkipAtStart() areas.append(fmap_util.FmapArea(pos or 0, entry.size or 0, entry.name, flags)) diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index f4f48c00e87..5e11cf58d28 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -165,7 +165,7 @@ class Entry_section(Entry): self._pad_byte = 0 self._sort = False self._skip_at_start = None - self._end_4gb = False + self._end_at_4gb = False self._ignore_missing = False self._filename = None self.align_default = 0 @@ -187,9 +187,9 @@ class Entry_section(Entry): super().ReadNode() self._pad_byte = fdt_util.GetInt(self._node, 'pad-byte', 0) self._sort = fdt_util.GetBool(self._node, 'sort-by-offset') - self._end_4gb = fdt_util.GetBool(self._node, 'end-at-4gb') + self._end_at_4gb = fdt_util.GetBool(self._node, 'end-at-4gb') self._skip_at_start = fdt_util.GetInt(self._node, 'skip-at-start') - if self._end_4gb: + if self._end_at_4gb: if not self.size: self.Raise("Section size must be provided when using end-at-4gb") if self._skip_at_start is not None: @@ -801,7 +801,7 @@ class Entry_section(Entry): if not entry: self._Raise("Unable to set offset/size for unknown entry '%s'" % name) - entry.SetOffsetSize(self._skip_at_start + offset if offset is not None + entry.SetOffsetSize(offset + self._skip_at_start if offset is not None else None, size) def GetEntryOffsets(self): diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 1bc2fca26ea..1a92a99b511 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -2308,16 +2308,17 @@ class TestFunctional(unittest.TestCase): fhdr, fentries = fmap_util.DecodeFmap(data[32:]) self.assertEqual(0x100, fhdr.image_size) + base = (1 << 32) - 0x100 - self.assertEqual(0, fentries[0].offset) + self.assertEqual(base, fentries[0].offset) self.assertEqual(4, fentries[0].size) self.assertEqual(b'U_BOOT', fentries[0].name) - self.assertEqual(4, fentries[1].offset) + self.assertEqual(base + 4, fentries[1].offset) self.assertEqual(3, fentries[1].size) self.assertEqual(b'INTEL_MRC', fentries[1].name) - self.assertEqual(32, fentries[2].offset) + self.assertEqual(base + 32, fentries[2].offset) self.assertEqual(fmap_util.FMAP_HEADER_LEN + fmap_util.FMAP_AREA_LEN * 3, fentries[2].size) self.assertEqual(b'FMAP', fentries[2].name) @@ -2330,27 +2331,28 @@ class TestFunctional(unittest.TestCase): fhdr, fentries = fmap_util.DecodeFmap(data[36:]) self.assertEqual(0x180, fhdr.image_size) + base = (1 << 32) - 0x180 expect_size = fmap_util.FMAP_HEADER_LEN + fmap_util.FMAP_AREA_LEN * 4 fiter = iter(fentries) fentry = next(fiter) self.assertEqual(b'U_BOOT', fentry.name) - self.assertEqual(0, fentry.offset) + self.assertEqual(base, fentry.offset) self.assertEqual(4, fentry.size) fentry = next(fiter) self.assertEqual(b'SECTION', fentry.name) - self.assertEqual(4, fentry.offset) + self.assertEqual(base + 4, fentry.offset) self.assertEqual(0x20 + expect_size, fentry.size) fentry = next(fiter) self.assertEqual(b'INTEL_MRC', fentry.name) - self.assertEqual(4, fentry.offset) + self.assertEqual(base + 4, fentry.offset) self.assertEqual(3, fentry.size) fentry = next(fiter) self.assertEqual(b'FMAP', fentry.name) - self.assertEqual(36, fentry.offset) + self.assertEqual(base + 36, fentry.offset) self.assertEqual(expect_size, fentry.size) def testElf(self): @@ -3546,8 +3548,8 @@ class TestFunctional(unittest.TestCase): image = control.images['image'] entries = image.GetEntries() desc = entries['intel-descriptor'] - self.assertEqual(0xff800000, desc.offset); - self.assertEqual(0xff800000, desc.image_pos); + self.assertEqual(0xff800000, desc.offset) + self.assertEqual(0xff800000, desc.image_pos) def testReplaceCbfs(self): """Test replacing a single file in CBFS without changing the size""" @@ -3789,8 +3791,8 @@ class TestFunctional(unittest.TestCase): image = control.images['image'] entries = image.GetEntries() - expected_ptr = entries['intel-fit'].image_pos - (1 << 32) - self.assertEqual(expected_ptr, ptr) + expected_ptr = entries['intel-fit'].image_pos #- (1 << 32) + self.assertEqual(expected_ptr, ptr + (1 << 32)) def testPackIntelFitMissing(self): """Test detection of a FIT pointer with not FIT region""" @@ -4784,7 +4786,7 @@ class TestFunctional(unittest.TestCase): entry = image.GetEntries()['fdtmap'] self.assertEqual(orig_entry.offset, entry.offset) self.assertEqual(orig_entry.size, entry.size) - self.assertEqual(16, entry.image_pos) + self.assertEqual((1 << 32) - 0x400 + 16, entry.image_pos) u_boot = image.GetEntries()['section'].GetEntries()['u-boot'] |