diff options
author | Tom Rini <trini@konsulko.com> | 2021-12-18 08:52:40 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-12-18 08:52:40 -0500 |
commit | e19c88e1ff3172ed17cd12d647f2d72a272bf447 (patch) | |
tree | e2540498952eb76ee04a6329201c5da4da38a075 | |
parent | 0ebf465d343868bf1080d540ab64de39bb927a09 (diff) | |
parent | 2548e6b8fcaf923bdf43c24e89acc12c0e897053 (diff) | |
download | u-boot-WIP/18Dec2021-next.zip u-boot-WIP/18Dec2021-next.tar.gz u-boot-WIP/18Dec2021-next.tar.bz2 |
Merge branch 'next' of https://source.denx.de/u-boot/custodians/u-boot-marvell into nextWIP/18Dec2021-next
- Armada XP etc: Move to DM_I2C (Stefan)
- Some mvebu comphy + mox + fdt_support changes (Marek & Pali)
- mvebu: a38x: improve USB3 serdes configuration (Stefan Eichenberger)
- mvebu: Some maintainer updates (Pali)
- mvebu: Misc minor cleanup (Pali)
127 files changed, 3665 insertions, 1178 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 9045e50..f4bd3d7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -274,10 +274,24 @@ F: drivers/ata/ahci_mvebu.c F: drivers/ddr/marvell/ F: drivers/gpio/mvebu_gpio.c F: drivers/spi/kirkwood_spi.c -F: drivers/pci/pci_mvebu.c F: drivers/pci/pcie_dw_mvebu.c F: drivers/watchdog/orion_wdt.c +ARM MARVELL PCIE CONTROLLER DRIVERS +M: Pali Rohár <pali@kernel.org> +M: Stefan Roese <sr@denx.de> +S: Maintained +T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git +F: drivers/pci/pci-aardvark.c +F: drivers/pci/pci_mvebu.c + +ARM MARVELL SERIAL DRIVERS +M: Pali Rohár <pali@kernel.org> +M: Stefan Roese <sr@denx.de> +S: Maintained +T: git https://source.denx.de/u-boot/custodians/u-boot-marvell.git +F: drivers/serial/serial_mvebu_a3700.c + ARM MARVELL PXA M: Marek Vasut <marex@denx.de> S: Maintained @@ -714,8 +728,11 @@ W: https://u-boot.readthedocs.io/en/latest/develop/uefi/u-boot_on_efi.html F: board/efi/efi-x86_app F: configs/efi-x86_app* F: doc/develop/uefi/u-boot_on_efi.rst +F: drivers/block/efi-media-uclass.c +F: drivers/block/sb_efi_media.c F: lib/efi/efi_app.c F: scripts/build-efi.sh +F: test/dm/efi_media.c EFI PAYLOAD M: Heinrich Schuchardt <xypron.glpk@gmx.de> diff --git a/arch/arm/cpu/armv7/ls102xa/fdt.c b/arch/arm/cpu/armv7/ls102xa/fdt.c index 0daf823..bf6cc6d 100644 --- a/arch/arm/cpu/armv7/ls102xa/fdt.c +++ b/arch/arm/cpu/armv7/ls102xa/fdt.c @@ -184,13 +184,13 @@ void ft_cpu_setup(void *blob, struct bd_info *bd) #if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI) off = fdt_node_offset_by_compat_reg(blob, FSL_IFC_COMPAT, CONFIG_SYS_IFC_ADDR); - fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED); #else off = fdt_node_offset_by_compat_reg(blob, FSL_QSPI_COMPAT, QSPI0_BASE_ADDR); - fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED); off = fdt_node_offset_by_compat_reg(blob, FSL_DSPI_COMPAT, DSPI1_BASE_ADDR); - fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED); #endif } diff --git a/arch/arm/dts/armada-3720-espressobin.dts b/arch/arm/dts/armada-3720-espressobin.dts index cba6139..360d521 100644 --- a/arch/arm/dts/armada-3720-espressobin.dts +++ b/arch/arm/dts/armada-3720-espressobin.dts @@ -80,24 +80,6 @@ }; }; -&comphy { - max-lanes = <3>; - phy0 { - phy-type = <COMPHY_TYPE_USB3_HOST0>; - phy-speed = <COMPHY_SPEED_5G>; - }; - - phy1 { - phy-type = <COMPHY_TYPE_PEX0>; - phy-speed = <COMPHY_SPEED_2_5G>; - }; - - phy2 { - phy-type = <COMPHY_TYPE_SATA0>; - phy-speed = <COMPHY_SPEED_5G>; - }; -}; - ð0 { status = "okay"; pinctrl-names = "default"; @@ -119,6 +101,7 @@ /* CON3 */ &sata { status = "okay"; + phys = <&comphy2 0>; }; &sdhci0 { @@ -200,6 +183,7 @@ /* CON31 */ &usb3 { status = "okay"; + phys = <&comphy0 0>; }; &pcie0 { @@ -207,4 +191,5 @@ pinctrl-0 = <&pcie_pins>; reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>; status = "okay"; + phys = <&comphy1 0>; }; diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts index f47ced0..d017570 100644 --- a/arch/arm/dts/armada-3720-turris-mox.dts +++ b/arch/arm/dts/armada-3720-turris-mox.dts @@ -94,24 +94,6 @@ }; }; -&comphy { - max-lanes = <3>; - phy0 { - phy-type = <COMPHY_TYPE_SGMII1>; - phy-speed = <COMPHY_SPEED_3_125G>; - }; - - phy1 { - phy-type = <COMPHY_TYPE_PEX0>; - phy-speed = <COMPHY_SPEED_5G>; - }; - - phy2 { - phy-type = <COMPHY_TYPE_USB3_HOST0>; - phy-speed = <COMPHY_SPEED_5G>; - }; -}; - ð0 { status = "okay"; pinctrl-names = "default"; @@ -120,6 +102,11 @@ phy = <ð_phy1>; }; +ð1 { + phy-mode = "2500base-x"; + phys = <&comphy0 1>; +}; + &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_pins>; @@ -222,6 +209,7 @@ &usb3 { vbus-supply = <®_usb3_vbus>; status = "okay"; + phys = <&comphy2 0>; }; &pcie0 { @@ -229,4 +217,5 @@ pinctrl-0 = <&pcie_pins>; reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>; status = "disabled"; + phys = <&comphy1 0>; }; diff --git a/arch/arm/dts/armada-3720-uDPU.dts b/arch/arm/dts/armada-3720-uDPU.dts index 4bf6d2e..58557c6 100644 --- a/arch/arm/dts/armada-3720-uDPU.dts +++ b/arch/arm/dts/armada-3720-uDPU.dts @@ -106,36 +106,21 @@ }; }; -&comphy { - phy0 { - phy-type = <COMPHY_TYPE_SGMII1>; - phy-speed = <COMPHY_SPEED_1_25G>; - }; - - phy1 { - phy-type = <COMPHY_TYPE_SGMII0>; - phy-speed = <COMPHY_SPEED_1_25G>; - }; - - phy2 { - phy-type = <COMPHY_TYPE_USB3_HOST1>; - phy-speed = <COMPHY_SPEED_5G>; - }; -}; - ð0 { pinctrl-0 = <&pcie_pins>; status = "okay"; - phy-mode = "2500base-x"; + phy-mode = "sgmii"; managed = "in-band-status"; phy = <ðphy0>; + phys = <&comphy1 0>; }; ð1 { status = "okay"; - phy-mode = "2500base-x"; + phy-mode = "sgmii"; managed = "in-band-status"; phy = <ðphy1>; + phys = <&comphy0 1>; }; &i2c0 { diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi index fec3460..bef6ef0 100644 --- a/arch/arm/dts/armada-37xx.dtsi +++ b/arch/arm/dts/armada-37xx.dtsi @@ -316,9 +316,23 @@ compatible = "marvell,mvebu-comphy", "marvell,comphy-armada-3700"; reg = <0x18300 0x28>, <0x1f300 0x3d000>; - mux-bitcount = <4>; - mux-lane-order = <1 0 2>; - max-lanes = <3>; + #address-cells = <1>; + #size-cells = <0>; + + comphy0: phy@0 { + reg = <0>; + #phy-cells = <1>; + }; + + comphy1: phy@1 { + reg = <1>; + #phy-cells = <1>; + }; + + comphy2: phy@2 { + reg = <2>; + #phy-cells = <1>; + }; }; }; diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts index 6a1df87..24cc1cc 100644 --- a/arch/arm/dts/armada-xp-theadorable.dts +++ b/arch/arm/dts/armada-xp-theadorable.dts @@ -71,6 +71,8 @@ spi0 = &spi0; spi1 = &spi1; ethernet0 = ð0; + i2c0 = &i2c0; + i2c1 = &i2c1; }; memory { @@ -156,6 +158,16 @@ }; }; +&i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <100000>; +}; + &spi0 { status = "okay"; u-boot,dm-pre-reloc; diff --git a/arch/arm/dts/beacon-renesom-baseboard.dtsi b/arch/arm/dts/beacon-renesom-baseboard.dtsi index 5f998d4..2692cc6 100644 --- a/arch/arm/dts/beacon-renesom-baseboard.dtsi +++ b/arch/arm/dts/beacon-renesom-baseboard.dtsi @@ -197,6 +197,14 @@ compatible = "audio-graph-card"; label = "rcar-sound"; dais = <&rsnd_port0>, <&rsnd_port1>; + widgets = "Microphone", "Mic Jack", + "Line", "Line In Jack", + "Headphone", "Headphone Jack"; + mic-det-gpio = <&gpio0 2 GPIO_ACTIVE_LOW>; + routing = "Headphone Jack", "HPOUTL", + "Headphone Jack", "HPOUTR", + "IN3R", "MICBIAS", + "Mic Jack", "IN3R"; }; vccq_sdhi0: regulator-vccq-sdhi0 { @@ -271,12 +279,12 @@ &ehci0 { dr_mode = "otg"; status = "okay"; - clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, <&versaclock5 3>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, <&usb2_clksel>, <&versaclock5 3>; }; &ehci1 { status = "okay"; - clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>; + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, <&usb2_clksel>, <&versaclock5 3>; }; &hdmi0 { @@ -615,7 +623,7 @@ }; &rcar_sound { - pinctrl-0 = <&sound_pins &sound_clk_pins>; + pinctrl-0 = <&sound_pins>, <&sound_clk_pins>; pinctrl-names = "default"; /* Single DAI */ @@ -639,7 +647,7 @@ bitclock-master = <&rsnd_endpoint0>; frame-master = <&rsnd_endpoint0>; - playback = <&ssi1 &dvc1 &src1>; + playback = <&ssi1>, <&dvc1>, <&src1>; capture = <&ssi0>; }; }; diff --git a/arch/arm/dts/beacon-renesom-som.dtsi b/arch/arm/dts/beacon-renesom-som.dtsi index d30bab3..0d13680 100644 --- a/arch/arm/dts/beacon-renesom-som.dtsi +++ b/arch/arm/dts/beacon-renesom-som.dtsi @@ -7,19 +7,10 @@ #include <dt-bindings/clk/versaclock.h> / { - aliases { - spi0 = &rpc; - }; - memory@48000000 { device_type = "memory"; /* first 128MB is reserved for secure area. */ - reg = <0x0 0x48000000 0x0 0xc000000>; - }; - - memory@57000000 { - device_type = "memory"; - reg = <0x0 0x57000000 0x0 0x29000000>; + reg = <0x0 0x48000000 0x0 0x78000000>; }; osc_32k: osc_32k { @@ -59,12 +50,17 @@ &avb { pinctrl-0 = <&avb_pins>; pinctrl-names = "default"; + phy-mode = "rgmii-rxid"; phy-handle = <&phy0>; rx-internal-delay-ps = <1800>; tx-internal-delay-ps = <2000>; + clocks = <&cpg CPG_MOD 812>, <&versaclock5 4>; + clock-names = "fck", "refclk"; status = "okay"; phy0: ethernet-phy@0 { + compatible = "ethernet-phy-id004d.d074", + "ethernet-phy-ieee802.3-c22"; reg = <0>; interrupt-parent = <&gpio2>; interrupts = <11 IRQ_TYPE_LEVEL_LOW>; @@ -153,7 +149,7 @@ }; eeprom@50 { - compatible = "microchip,at24c64", "atmel,24c64"; + compatible = "microchip,24c64", "atmel,24c64"; pagesize = <32>; read-only; /* Manufacturing EEPROM programmed at factory */ reg = <0x50>; @@ -279,25 +275,6 @@ }; }; -&rpc { - compatible = "renesas,rcar-gen3-rpc"; - num-cs = <1>; - spi-max-frequency = <40000000>; - #address-cells = <1>; - #size-cells = <0>; - status = "okay"; - - flash0: spi-flash@0 { - #address-cells = <1>; - #size-cells = <1>; - reg = <0>; - compatible = "spi-flash", "jedec,spi-nor"; - spi-max-frequency = <40000000>; - spi-tx-bus-width = <1>; - spi-rx-bus-width = <1>; - }; -}; - &scif_clk { clock-frequency = <14745600>; }; @@ -340,17 +317,17 @@ vqmmc-supply = <®_1p8v>; bus-width = <8>; mmc-hs200-1_8v; + no-sd; + no-sdio; non-removable; fixed-emmc-driver-type = <1>; status = "okay"; }; &usb2_clksel { - status = "okay"; clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, - <&versaclock5 3>, <&usb3s0_clk>; - clock-names = "ehci_ohci", "hs-usb-if", - "usb_extal", "usb_xtal"; + <&versaclock5 3>, <&usb3s0_clk>; + status = "okay"; }; &usb3s0_clk { diff --git a/arch/arm/dts/r8a774a1-beacon-rzg2m-kit-u-boot.dtsi b/arch/arm/dts/r8a774a1-beacon-rzg2m-kit-u-boot.dtsi index a0c0a7f..85336d5 100644 --- a/arch/arm/dts/r8a774a1-beacon-rzg2m-kit-u-boot.dtsi +++ b/arch/arm/dts/r8a774a1-beacon-rzg2m-kit-u-boot.dtsi @@ -1,34 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright 2020 Compass Electronics Group, LLC + * Copyright 2021 LogicPD dba Beacon EmbeddedWorks */ -/ { - soc { - u-boot,dm-pre-reloc; - }; -}; - -&cpg { - u-boot,dm-pre-reloc; -}; - -&extal_clk { - u-boot,dm-pre-reloc; -}; - -&prr { - u-boot,dm-pre-reloc; -}; - -&extalr_clk { - u-boot,dm-pre-reloc; -}; - -&sdhi0 { - /delete-property/ cd-gpios; -}; - -&sdhi2 { - status = "disabled"; -}; +#include "rz-g2-beacon-u-boot.dtsi" diff --git a/arch/arm/dts/r8a774a1-beacon-rzg2m-kit.dts b/arch/arm/dts/r8a774a1-beacon-rzg2m-kit.dts index 501cb05..3cf2e07 100644 --- a/arch/arm/dts/r8a774a1-beacon-rzg2m-kit.dts +++ b/arch/arm/dts/r8a774a1-beacon-rzg2m-kit.dts @@ -21,6 +21,9 @@ serial4 = &hscif2; serial5 = &scif5; ethernet0 = &avb; + mmc0 = &sdhi3; + mmc1 = &sdhi0; + mmc2 = &sdhi2; }; chosen { diff --git a/arch/arm/dts/r8a774b1-beacon-rzg2n-kit-u-boot.dtsi b/arch/arm/dts/r8a774b1-beacon-rzg2n-kit-u-boot.dtsi index a0c0a7f..85336d5 100644 --- a/arch/arm/dts/r8a774b1-beacon-rzg2n-kit-u-boot.dtsi +++ b/arch/arm/dts/r8a774b1-beacon-rzg2n-kit-u-boot.dtsi @@ -1,34 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright 2020 Compass Electronics Group, LLC + * Copyright 2021 LogicPD dba Beacon EmbeddedWorks */ -/ { - soc { - u-boot,dm-pre-reloc; - }; -}; - -&cpg { - u-boot,dm-pre-reloc; -}; - -&extal_clk { - u-boot,dm-pre-reloc; -}; - -&prr { - u-boot,dm-pre-reloc; -}; - -&extalr_clk { - u-boot,dm-pre-reloc; -}; - -&sdhi0 { - /delete-property/ cd-gpios; -}; - -&sdhi2 { - status = "disabled"; -}; +#include "rz-g2-beacon-u-boot.dtsi" diff --git a/arch/arm/dts/r8a774b1-beacon-rzg2n-kit.dts b/arch/arm/dts/r8a774b1-beacon-rzg2n-kit.dts index 71763f4..3c0d59d 100644 --- a/arch/arm/dts/r8a774b1-beacon-rzg2n-kit.dts +++ b/arch/arm/dts/r8a774b1-beacon-rzg2n-kit.dts @@ -22,6 +22,9 @@ serial5 = &scif5; serial6 = &scif4; ethernet0 = &avb; + mmc0 = &sdhi3; + mmc1 = &sdhi0; + mmc2 = &sdhi2; }; chosen { diff --git a/arch/arm/dts/r8a774e1-beacon-rzg2h-kit-u-boot.dtsi b/arch/arm/dts/r8a774e1-beacon-rzg2h-kit-u-boot.dtsi index eef200a..85336d5 100644 --- a/arch/arm/dts/r8a774e1-beacon-rzg2h-kit-u-boot.dtsi +++ b/arch/arm/dts/r8a774e1-beacon-rzg2h-kit-u-boot.dtsi @@ -1,44 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright 2020 Compass Electronics Group, LLC + * Copyright 2021 LogicPD dba Beacon EmbeddedWorks */ -/ { - soc { - u-boot,dm-pre-reloc; - }; -}; - -&cpg { - u-boot,dm-pre-reloc; -}; - -&extal_clk { - u-boot,dm-pre-reloc; -}; - -&prr { - u-boot,dm-pre-reloc; -}; - -&extalr_clk { - u-boot,dm-pre-reloc; -}; - -&sdhi0 { - /delete-property/ cd-gpios; - sd-uhs-sdr12; - sd-uhs-sdr25; - sd-uhs-sdr104; - max-frequency = <208000000>; -}; - -&sdhi2 { - status = "disabled"; -}; - -&sdhi3 { - mmc-ddr-1_8v; - mmc-hs200-1_8v; - mmc-hs400-1_8v; -}; +#include "rz-g2-beacon-u-boot.dtsi" diff --git a/arch/arm/dts/r8a774e1-beacon-rzg2h-kit.dts b/arch/arm/dts/r8a774e1-beacon-rzg2h-kit.dts index 273f062..7b6649a 100644 --- a/arch/arm/dts/r8a774e1-beacon-rzg2h-kit.dts +++ b/arch/arm/dts/r8a774e1-beacon-rzg2h-kit.dts @@ -22,6 +22,9 @@ serial5 = &scif5; serial6 = &scif4; ethernet0 = &avb; + mmc0 = &sdhi3; + mmc1 = &sdhi0; + mmc2 = &sdhi2; }; chosen { diff --git a/arch/arm/dts/rz-g2-beacon-u-boot.dtsi b/arch/arm/dts/rz-g2-beacon-u-boot.dtsi new file mode 100644 index 0000000..ef0b96a --- /dev/null +++ b/arch/arm/dts/rz-g2-beacon-u-boot.dtsi @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2021 LogicPD dba Beacon EmbeddedWorks + */ + +/ { + aliases { + spi0 = &rpc; + }; + + soc { + u-boot,dm-pre-reloc; + }; +}; + +&cpg { + u-boot,dm-pre-reloc; +}; + +&ehci0 { + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, <&versaclock5 3>; +}; + +&ehci1 { + clocks = <&cpg CPG_MOD 703>, <&cpg CPG_MOD 704>, <&versaclock5 3>; +}; + +&extal_clk { + u-boot,dm-pre-reloc; +}; + +&extalr_clk { + u-boot,dm-pre-reloc; +}; + +&prr { + u-boot,dm-pre-reloc; +}; + +&rpc { + compatible = "renesas,rcar-gen3-rpc"; + num-cs = <1>; + spi-max-frequency = <40000000>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash0: spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + reg = <0>; + compatible = "spi-flash", "jedec,spi-nor"; + spi-max-frequency = <40000000>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <1>; + }; +}; + +&sdhi0 { + /delete-property/ cd-gpios; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr104; + max-frequency = <208000000>; +}; + +&sdhi2 { + status = "disabled"; +}; + +&sdhi3 { + mmc-ddr-1_8v; + mmc-hs200-1_8v; + mmc-hs400-1_8v; +}; diff --git a/arch/arm/dts/sunxi-u-boot.dtsi b/arch/arm/dts/sunxi-u-boot.dtsi index b7244c1..f2d7361 100644 --- a/arch/arm/dts/sunxi-u-boot.dtsi +++ b/arch/arm/dts/sunxi-u-boot.dtsi @@ -13,7 +13,7 @@ / { aliases { mmc0 = &mmc0; -#if CONFIG_MMC_SUNXI_EXTRA_SLOT == 2 +#if CONFIG_MMC_SUNXI_SLOT_EXTRA == 2 mmc1 = &mmc2; #endif }; diff --git a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c index d2bc3ab..9ba60b5 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c +++ b/arch/arm/mach-mvebu/serdes/a38x/high_speed_env_spec.c @@ -459,18 +459,41 @@ struct op_params usb3_electrical_config_serdes_rev1_params[] = { }; struct op_params usb3_electrical_config_serdes_rev2_params[] = { - /* Spread Spectrum Clock Enable */ - {LANE_CFG4_REG, 0x800, 0x80, {0x80}, 0, 0}, + /* Spread Spectrum Clock Enable, CFG_DFE_OVERRIDE and PIN_DFE_PAT_DIS */ + {LANE_CFG4_REG, 0x800, 0xc2, {0xc0}, 0, 0}, + /* CFG_SQ_DET_SEL and CFG_RX_INIT_SEL */ + {LANE_CFG5_REG, 0x800, 0x3, {0x3}, 0, 0}, /* G2_TX_SSC_AMP[6:0]=4.5k_p_pM and TX emphasis mode=m_v */ {G2_SETTINGS_2_REG, 0x800, 0xfe40, {0x4440}, 0, 0}, - /* G2_RX SELMUFF, SELMUFI, SELMUPF and SELMUPI */ + /* FFE Setting Force, FFE_RES[2:0]=0x6 and FFE_CAP[3:0]=0xf */ + {G2_SETTINGS_3_REG, 0x800, 0xff, {0xef}, 0, 0}, + /* G2_DFE_RES[1:0]=0x0(3mV)*/ + {G2_SETTINGS_4_REG, 0x800, 0x300, {0x300}, 0, 0}, + /* HPF_Bw[1:0]=0x3 */ + {PLLINTP_REG1, 0x800, 0x300, {0x300}, 0, 0}, + /* TXIMPCAL_TH[3:0]=0x3, RXIMPCAL_TH[3:0]=0x0 */ + {VTHIMPCAL_CTRL_REG, 0x800, 0xff00, {0x3000}, 0, 0}, + /* CFG_SQ_DET_SEL and CFG_RX_INIT_SEL*/ + {LANE_CFG5_REG, 0x800, 0x3, {0x3}, 0, 0}, + /* REFCLK_SEL(25Mhz), ICP_FORCE, ICP[3:0]=0xa(210uA); */ + {MISC_REG, 0x800, 0x42f, {0x42a}, 0, 0}, + /* REF_FREF_SEL[4:0]=0x2(25Mhz) */ + {POWER_AND_PLL_CTRL_REG, 0x800, 0x1f, {0x02}, 0, 0}, + /* + * G2_RX SELMUFF[1:0]=3, G2_RX_SELMUFI[1:0]=3, G2_RX_SELMUPF[2:0]=2 + * and G2_RX_SELMUPI[2:0]=2 + */ {G2_SETTINGS_1_REG, 0x800, 0x3ff, {0x3d2}, 0, 0}, /* Dtl Clamping disable and Dtl-clamping-Sel(6000ppm) */ {RX_REG2, 0x800, 0xf0, {0x70}, 0, 0}, + /* tx_amp_pipe_v0[4:0]=0x1a */ + {PCIE_REG1, 0x800, 0xf80, {0xd00}, 0, 0}, /* vco_cal_vth_sel */ {REF_REG0, 0x800, 0x38, {0x20}, 0, 0}, - /* Spread Spectrum Clock Enable */ - {LANE_CFG5_REG, 0x800, 0x4, {0x4}, 0, 0}, + /* PRD_TXDEEMPH0 */ + {LANE_CFG0_REG, 0x800, 0x1, {0x1}, 0, 0}, + /* MODE_MARGIN_OVERRIDE */ + {GLOBAL_TEST_CTRL, 0x800, 0x4, {0x4}, 0, 0}, }; /* PEX and USB3 - TX config seq */ @@ -490,11 +513,11 @@ struct op_params pex_and_usb3_tx_config_params1[] = { /* 10ms delay */ {0x0, 0x0, 0x0, {0x0, 0x0}, 10, 0}, /* os_ph_offset_force (align 90) */ - {RX_REG3, 0x800, 0xff, {0xdc, NO_DATA}, 0, 0}, + {RX_REG3, 0x800, 0xff, {0xdc, 0xd8}, 0, 0}, /* Set os_ph_valid */ - {RX_REG3, 0x800, 0x100, {0x100, NO_DATA}, 0, 0}, + {RX_REG3, 0x800, 0x100, {0x100, 0x100}, 0, 0}, /* Unset os_ph_valid */ - {RX_REG3, 0x800, 0x100, {0x0, NO_DATA}, 0, 0}, + {RX_REG3, 0x800, 0x100, {0x0, 0x0}, 0, 0}, }; struct op_params pex_and_usb3_tx_config_params2[] = { @@ -1204,7 +1227,7 @@ int hws_serdes_seq_db_init(void) sizeof(usb3_electrical_config_serdes_rev2_params) / sizeof(struct op_params); } - serdes_seq_db[USB3_ELECTRICAL_CONFIG_SEQ].data_arr_idx = USB3; + serdes_seq_db[USB3_ELECTRICAL_CONFIG_SEQ].data_arr_idx = 0; /* USB3_TX_CONFIG_SEQ sequence init */ serdes_seq_db[USB3_TX_CONFIG_SEQ1].op_params_ptr = diff --git a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h index 118bf56..94c43b4 100644 --- a/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h +++ b/arch/arm/mach-mvebu/serdes/a38x/sys_env_lib.h @@ -50,6 +50,7 @@ #define MISC_REG 0xa013c #define GLUE_REG 0xa0140 #define GENERATION_DIVIDER_FORCE_REG 0xa0144 +#define PLLINTP_REG1 0xa0150 #define PCIE_REG0 0xa0120 #define LANE_ALIGN_REG0 0xa0124 #define SQUELCH_FFE_SETTING_REG 0xa0018 @@ -78,6 +79,7 @@ #define LANE_CFG4_REG 0xa0620 #define LANE_CFG5_REG 0xa0624 #define GLOBAL_CLK_CTRL 0xa0704 +#define GLOBAL_TEST_CTRL 0xa0708 #define GLOBAL_MISC_CTRL 0xa0718 #define GLOBAL_CLK_SRC_HI 0xa0710 diff --git a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c index ea3b4c7..0b63664 100644 --- a/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c +++ b/arch/arm/mach-mvebu/serdes/axp/high_speed_env_lib.c @@ -77,6 +77,7 @@ static u32 board_id_get(void) __weak u8 board_sat_r_get(u8 dev_num, u8 reg) { + struct udevice *udev; u8 data; u8 *dev; u32 board_id = board_id_get(); @@ -107,8 +108,11 @@ __weak u8 board_sat_r_get(u8 dev_num, u8 reg) } /* Read MPP module ID */ - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); - ret = i2c_read(dev[dev_num], 0, 1, (u8 *)&data, 1); + ret = i2c_get_chip_for_busnum(0, dev[dev_num], 1, &udev); + if (ret) + return MV_ERROR; + + ret = dm_i2c_read(udev, 0, &data, 1); if (ret) return MV_ERROR; @@ -124,13 +128,18 @@ static int board_modules_scan(void) /* Perform scan only for DB board */ if ((board_id == DB_88F78XX0_BP_ID) || (board_id == DB_88F78XX0_BP_REV2_ID)) { + struct udevice *udev; + /* reset modules flags */ config_module = 0; - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + ret = i2c_get_chip_for_busnum(0, MV_BOARD_PEX_MODULE_ADDR, + 1, &udev); + if (ret) + return MV_ERROR; /* SERDES module (only PEX model is supported now) */ - ret = i2c_read(MV_BOARD_PEX_MODULE_ADDR, 0, 1, (u8 *)&val, 1); + ret = dm_i2c_read(udev, 0, &val, 1); if (ret) return MV_ERROR; diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index 73c4b9a..aada83f 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -5,7 +5,6 @@ #include <common.h> #include <dm.h> -#include <debug_uart.h> #include <fdtdec.h> #include <hang.h> #include <image.h> @@ -250,18 +249,6 @@ void board_init_f(ulong dummy) */ board_early_init_f(); - /* Example code showing how to enable the debug UART on MVEBU */ -#ifdef EARLY_UART - /* - * Debug UART can be used from here if required: - * - * debug_uart_init(); - * printch('a'); - * printhex8(0x1234); - * printascii("string"); - */ -#endif - /* * Use special translation offset for SPL. This needs to be * configured *before* spl_init() is called as this function @@ -273,7 +260,7 @@ void board_init_f(ulong dummy) ret = spl_init(); if (ret) { - debug("spl_init() failed: %d\n", ret); + printf("spl_init() failed: %d\n", ret); hang(); } @@ -289,7 +276,7 @@ void board_init_f(ulong dummy) /* Setup DDR */ ret = ddr3_init(); if (ret) { - debug("ddr3_init() failed: %d\n", ret); + printf("ddr3_init() failed: %d\n", ret); hang(); } #endif diff --git a/arch/arm/mach-socfpga/include/mach/misc.h b/arch/arm/mach-socfpga/include/mach/misc.h index 649d2f6..8460acb 100644 --- a/arch/arm/mach-socfpga/include/mach/misc.h +++ b/arch/arm/mach-socfpga/include/mach/misc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2016-2017 Intel Corporation + * Copyright (C) 2016-2021 Intel Corporation */ #ifndef _SOCFPGA_MISC_H_ @@ -45,7 +45,12 @@ int is_fpga_config_ready(void); #endif void do_bridge_reset(int enable, unsigned int mask); +void force_periph_program(unsigned int status); +bool is_regular_boot_valid(void); +bool is_periph_program_force(void); +void set_regular_boot(unsigned int status); void socfpga_pl310_clear(void); void socfpga_get_managers_addr(void); +int qspi_flash_software_reset(void); #endif /* _SOCFPGA_MISC_H_ */ diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h index 19507c2..26faa62 100644 --- a/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/reset_manager_arria10.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2016-2017 Intel Corporation + * Copyright (C) 2016-2021 Intel Corporation */ #ifndef _RESET_MANAGER_ARRIA10_H_ @@ -22,6 +22,7 @@ int socfpga_bridges_reset(void); #define RSTMGR_A10_PER1MODRST 0x28 #define RSTMGR_A10_BRGMODRST 0x2c #define RSTMGR_A10_SYSMODRST 0x30 +#define RSTMGR_A10_SYSWARMMASK 0x50 #define RSTMGR_CTRL RSTMGR_A10_CTRL @@ -115,4 +116,7 @@ int socfpga_bridges_reset(void); #define ALT_RSTMGR_HDSKEN_FPGAHSEN_SET_MSK BIT(2) #define ALT_RSTMGR_HDSKEN_ETRSTALLEN_SET_MSK BIT(3) +#define ALT_RSTMGR_FPGAMGRWARMMASK_S2F_SET_MSK BIT(3) +#define ALT_RSTMGR_SYSWARMMASK_S2F_SET_MSK BIT(4) + #endif /* _RESET_MANAGER_ARRIA10_H_ */ diff --git a/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h b/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h index e4fc6d2..0afe63e 100644 --- a/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h +++ b/arch/arm/mach-socfpga/include/mach/system_manager_arria10.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (C) 2016-2017 Intel Corporation <www.intel.com> + * Copyright (C) 2016-2021 Intel Corporation <www.intel.com> */ #ifndef _SYSTEM_MANAGER_ARRIA10_H_ @@ -31,6 +31,11 @@ #define SYSMGR_A10_NOC_IDLEACK 0xd0 #define SYSMGR_A10_NOC_IDLESTATUS 0xd4 #define SYSMGR_A10_FPGA2SOC_CTRL 0xd8 +#define SYSMGR_A10_ROMCODE_CTRL 0x204 +#define SYSMGR_A10_ROMCODE_INITSWSTATE 0x20C +#define SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND 0x208 +#define SYSMGR_A10_ISW_HANDOFF_BASE 0x230 +#define SYSMGR_A10_ISW_HANDOFF_7 0x1c #define SYSMGR_SDMMC SYSMGR_A10_SDMMC diff --git a/arch/arm/mach-socfpga/misc_arria10.c b/arch/arm/mach-socfpga/misc_arria10.c index bf97805..0ed2adf 100644 --- a/arch/arm/mach-socfpga/misc_arria10.c +++ b/arch/arm/mach-socfpga/misc_arria10.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2016-2017 Intel Corporation + * Copyright (C) 2016-2021 Intel Corporation */ #include <altera.h> @@ -11,6 +11,7 @@ #include <miiphy.h> #include <netdev.h> #include <ns16550.h> +#include <spi_flash.h> #include <watchdog.h> #include <asm/arch/misc.h> #include <asm/arch/pinmux.h> @@ -21,6 +22,7 @@ #include <asm/arch/nic301.h> #include <asm/io.h> #include <asm/pl310.h> +#include <linux/sizes.h> #define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q1_3 0x08 #define PINMUX_UART0_TX_SHARED_IO_OFFSET_Q2_11 0x58 @@ -29,6 +31,13 @@ #define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q3_7 0x78 #define PINMUX_UART1_TX_SHARED_IO_OFFSET_Q4_3 0x98 +#define REGULAR_BOOT_MAGIC 0xd15ea5e +#define PERIPH_RBF_PROG_FORCE 0x50455249 + +#define QSPI_S25FL_SOFT_RESET_COMMAND 0x00f0ff82 +#define QSPI_N25_SOFT_RESET_COMMAND 0x00000001 +#define QSPI_NO_SOFT_RESET 0x00000000 + /* * FPGA programming support for SoC FPGA Arria 10 */ @@ -122,3 +131,118 @@ void do_bridge_reset(int enable, unsigned int mask) else socfpga_bridges_reset(); } + +/* + * This function set/unset flag with number "0x50455249" to + * handoff register isw_handoff[7] - 0xffd0624c + * This flag is used to force periph RBF program regardless FPGA status + * and double periph RBF config are needed on some devices or boards to + * stabilize the IO config system. + */ +void force_periph_program(unsigned int status) +{ + if (status) + writel(PERIPH_RBF_PROG_FORCE, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); + else + writel(0, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); +} + +/* + * This function is used to check whether + * handoff register isw_handoff[7] contains + * flag for forcing the periph RBF program "0x50455249". + */ +bool is_periph_program_force(void) +{ + unsigned int status; + + status = readl(socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); + + if (status == PERIPH_RBF_PROG_FORCE) + return true; + else + return false; +} + +/* + * This function set/unset magic number "0xd15ea5e" to + * handoff register isw_handoff[7] - 0xffd0624c + * This magic number is part of boot progress tracking + * and it's required for warm reset workaround on MPFE hang issue. + */ +void set_regular_boot(unsigned int status) +{ + if (status) + writel(REGULAR_BOOT_MAGIC, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); + else + writel(0, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); +} + +/* + * This function is used to check whether + * handoff register isw_handoff[7] contains + * magic number "0xd15ea5e". + */ +bool is_regular_boot_valid(void) +{ + unsigned int status; + + status = readl(socfpga_get_sysmgr_addr() + + SYSMGR_A10_ISW_HANDOFF_BASE + SYSMGR_A10_ISW_HANDOFF_7); + + if (status == REGULAR_BOOT_MAGIC) + return true; + else + return false; +} + +#if IS_ENABLED(CONFIG_CADENCE_QSPI) +/* This function is used to trigger software reset + * to the QSPI flash. On some boards, the QSPI flash reset may + * not be connected to the HPS warm reset. + */ +int qspi_flash_software_reset(void) +{ + struct udevice *flash; + int ret; + + /* Get the flash info */ + ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE, + &flash); + + if (ret) { + debug("Failed to initialize SPI flash at "); + debug("%u:%u (error %d)\n", CONFIG_SF_DEFAULT_BUS, + CONFIG_SF_DEFAULT_CS, ret); + return -ENODEV; + } + + if (!flash) + return -EINVAL; + + /* + * QSPI flash software reset command, for the case where + * no HPS reset connected to QSPI flash reset + */ + if (!memcmp(flash->name, "N25", SZ_1 + SZ_2)) + writel(QSPI_N25_SOFT_RESET_COMMAND, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); + else if (!memcmp(flash->name, "S25FL", SZ_1 + SZ_4)) + writel(QSPI_S25FL_SOFT_RESET_COMMAND, + socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); + else /* No software reset */ + writel(QSPI_NO_SOFT_RESET, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_QSPIRESETCOMMAND); + + return 0; +} +#endif diff --git a/arch/arm/mach-socfpga/spl_a10.c b/arch/arm/mach-socfpga/spl_a10.c index ecb656e..d2f454c 100644 --- a/arch/arm/mach-socfpga/spl_a10.c +++ b/arch/arm/mach-socfpga/spl_a10.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright (C) 2012-2019 Altera Corporation <www.altera.com> + * Copyright (C) 2012-2021 Altera Corporation <www.altera.com> */ #include <common.h> @@ -30,8 +30,13 @@ #include <asm/arch/fpga_manager.h> #include <mmc.h> #include <memalign.h> +#include <linux/delay.h> #define FPGA_BUFSIZ 16 * 1024 +#define FSBL_IMAGE_IS_VALID 0x49535756 + +#define FSBL_IMAGE_IS_INVALID 0x0 +#define BOOTROM_CONFIGURES_IO_PINMUX 0x3 DECLARE_GLOBAL_DATA_PTR; @@ -106,6 +111,8 @@ u32 spl_mmc_boot_mode(const u32 boot_device) void spl_board_init(void) { + int ret; + ALLOC_CACHE_ALIGN_BUFFER(char, buf, FPGA_BUFSIZ); /* enable console uart printing */ @@ -116,8 +123,7 @@ void spl_board_init(void) /* If the full FPGA is already loaded, ie.from EPCQ, config fpga pins */ if (is_fpgamgr_user_mode()) { - int ret = config_pins(gd->fdt_blob, "shared"); - + ret = config_pins(gd->fdt_blob, "shared"); if (ret) return; @@ -127,11 +133,110 @@ void spl_board_init(void) } else if (!is_fpgamgr_early_user_mode()) { /* Program IOSSM(early IO release) or full FPGA */ fpgamgr_program(buf, FPGA_BUFSIZ, 0); + + /* Skipping double program for combined RBF */ + if (!is_fpgamgr_user_mode()) { + /* + * Expect FPGA entered early user mode, so + * the flag is set to re-program IOSSM + */ + force_periph_program(true); + + /* Re-program IOSSM to stabilize IO system */ + fpgamgr_program(buf, FPGA_BUFSIZ, 0); + + force_periph_program(false); + } } /* If the IOSSM/full FPGA is already loaded, start DDR */ - if (is_fpgamgr_early_user_mode() || is_fpgamgr_user_mode()) + if (is_fpgamgr_early_user_mode() || is_fpgamgr_user_mode()) { + if (!is_regular_boot_valid()) { + /* + * Ensure all signals in stable state before triggering + * warm reset. This value is recommended from stress + * test. + */ + mdelay(10); + +#if IS_ENABLED(CONFIG_CADENCE_QSPI) + /* + * Trigger software reset to QSPI flash. + * On some boards, the QSPI flash reset may not be + * connected to the HPS warm reset. + */ + qspi_flash_software_reset(); +#endif + + ret = readl(socfpga_get_rstmgr_addr() + + RSTMGR_A10_SYSWARMMASK); + /* + * Masking s2f & FPGA manager module reset from warm + * reset + */ + writel(ret & (~(ALT_RSTMGR_SYSWARMMASK_S2F_SET_MSK | + ALT_RSTMGR_FPGAMGRWARMMASK_S2F_SET_MSK)), + socfpga_get_rstmgr_addr() + + RSTMGR_A10_SYSWARMMASK); + + /* + * BootROM will configure both IO and pin mux after a + * warm reset + */ + ret = readl(socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_CTRL); + writel(ret | BOOTROM_CONFIGURES_IO_PINMUX, + socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_CTRL); + + /* + * Up to here, image is considered valid and should be + * set as valid before warm reset is triggered + */ + writel(FSBL_IMAGE_IS_VALID, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_INITSWSTATE); + + /* + * Set this flag to scratch register, so that a proper + * boot progress before / after warm reset can be + * tracked by FSBL + */ + set_regular_boot(true); + + WATCHDOG_RESET(); + + reset_cpu(); + } + + /* + * Reset this flag to scratch register, so that a proper + * boot progress before / after warm reset can be + * tracked by FSBL + */ + set_regular_boot(false); + + ret = readl(socfpga_get_rstmgr_addr() + + RSTMGR_A10_SYSWARMMASK); + + /* + * Unmasking s2f & FPGA manager module reset from warm + * reset + */ + writel(ret | ALT_RSTMGR_SYSWARMMASK_S2F_SET_MSK | + ALT_RSTMGR_FPGAMGRWARMMASK_S2F_SET_MSK, + socfpga_get_rstmgr_addr() + RSTMGR_A10_SYSWARMMASK); + + /* + * Up to here, MPFE hang workaround is considered done and + * should be reset as invalid until FSBL successfully loading + * SSBL, and prepare jumping to SSBL, then only setting as + * valid + */ + writel(FSBL_IMAGE_IS_INVALID, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_INITSWSTATE); + ddr_calibration_sequence(); + } if (!is_fpgamgr_user_mode()) fpgamgr_program(buf, FPGA_BUFSIZ, 0); @@ -169,3 +274,10 @@ void board_init_f(ulong dummy) config_dedicated_pins(gd->fdt_blob); WATCHDOG_RESET(); } + +/* board specific function prior loading SSBL / U-Boot proper */ +void spl_board_prepare_for_boot(void) +{ + writel(FSBL_IMAGE_IS_VALID, socfpga_get_sysmgr_addr() + + SYSMGR_A10_ROMCODE_INITSWSTATE); +} diff --git a/arch/riscv/cpu/fu740/Kconfig b/arch/riscv/cpu/fu740/Kconfig index 049a0a0..3e0c1fd 100644 --- a/arch/riscv/cpu/fu740/Kconfig +++ b/arch/riscv/cpu/fu740/Kconfig @@ -40,3 +40,16 @@ config SIFIVE_FU740 imply DM_I2C imply SYS_I2C_OCORES imply SPL_I2C + +if ENV_IS_IN_SPI_FLASH + +config ENV_OFFSET + default 0x505000 + +config ENV_SIZE + default 0x20000 + +config ENV_SECT_SIZE + default 0x10000 + +endif # ENV_IS_IN_SPI_FLASH diff --git a/arch/riscv/dts/hifive-unmatched-a00-u-boot.dtsi b/arch/riscv/dts/hifive-unmatched-a00-u-boot.dtsi index c5475aa..1ee8ab1 100644 --- a/arch/riscv/dts/hifive-unmatched-a00-u-boot.dtsi +++ b/arch/riscv/dts/hifive-unmatched-a00-u-boot.dtsi @@ -16,6 +16,10 @@ u-boot,dm-spl; }; + config { + u-boot,spl-payload-offset = <0x105000>; /* loader2 @1044KB */ + }; + hfclk { u-boot,dm-spl; }; @@ -30,6 +34,13 @@ clocks = <&rtcclk>; }; +&qspi0 { + u-boot,dm-spl; + flash@0 { + u-boot,dm-spl; + }; +}; + &spi0 { mmc@0 { u-boot,dm-spl; diff --git a/arch/riscv/dts/microchip-mpfs-icicle-kit.dts b/arch/riscv/dts/microchip-mpfs-icicle-kit.dts index 89c4cf5..287ef3d 100644 --- a/arch/riscv/dts/microchip-mpfs-icicle-kit.dts +++ b/arch/riscv/dts/microchip-mpfs-icicle-kit.dts @@ -1,417 +1,157 @@ -// SPDX-License-Identifier: (GPL-2.0 OR MIT) -/* Copyright (c) 2020 Microchip Technology Inc */ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (C) 2021 Microchip Technology Inc. + * Padmarao Begari <padmarao.begari@microchip.com> + */ /dts-v1/; -#include "dt-bindings/clock/microchip-mpfs-clock.h" + +#include "microchip-mpfs.dtsi" /* Clock frequency (in Hz) of the rtcclk */ #define RTCCLK_FREQ 1000000 / { - #address-cells = <2>; - #size-cells = <2>; - model = "Microchip MPFS Icicle Kit"; - compatible = "microchip,mpfs-icicle-kit"; + model = "Microchip PolarFire-SoC Icicle Kit"; + compatible = "microchip,mpfs-icicle-kit", "microchip,mpfs"; aliases { - serial0 = &uart0; - ethernet0 = &emac1; + serial1 = &uart1; + ethernet0 = &mac1; }; chosen { - stdout-path = "serial0"; + stdout-path = "serial1"; }; - cpucomplex: cpus { - #address-cells = <1>; - #size-cells = <0>; + cpus { timebase-frequency = <RTCCLK_FREQ>; - cpu0: cpu@0 { - clocks = <&clkcfg CLK_CPU>; - compatible = "sifive,e51", "sifive,rocket0", "riscv"; - device_type = "cpu"; - i-cache-block-size = <64>; - i-cache-sets = <128>; - i-cache-size = <16384>; - reg = <0>; - riscv,isa = "rv64imac"; - status = "disabled"; - operating-points = < - /* kHz uV */ - 600000 1100000 - 300000 950000 - 150000 750000 - >; - cpu0intc: interrupt-controller { - #interrupt-cells = <1>; - compatible = "riscv,cpu-intc"; - interrupt-controller; - }; - }; - cpu1: cpu@1 { - clocks = <&clkcfg CLK_CPU>; - compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; - d-cache-block-size = <64>; - d-cache-sets = <64>; - d-cache-size = <32768>; - d-tlb-sets = <1>; - d-tlb-size = <32>; - device_type = "cpu"; - i-cache-block-size = <64>; - i-cache-sets = <64>; - i-cache-size = <32768>; - i-tlb-sets = <1>; - i-tlb-size = <32>; - mmu-type = "riscv,sv39"; - reg = <1>; - riscv,isa = "rv64imafdc"; - tlb-split; - status = "okay"; - operating-points = < - /* kHz uV */ - 600000 1100000 - 300000 950000 - 150000 750000 - >; - cpu1intc: interrupt-controller { - #interrupt-cells = <1>; - compatible = "riscv,cpu-intc"; - interrupt-controller; - }; - }; - cpu2: cpu@2 { - clocks = <&clkcfg CLK_CPU>; - compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; - d-cache-block-size = <64>; - d-cache-sets = <64>; - d-cache-size = <32768>; - d-tlb-sets = <1>; - d-tlb-size = <32>; - device_type = "cpu"; - i-cache-block-size = <64>; - i-cache-sets = <64>; - i-cache-size = <32768>; - i-tlb-sets = <1>; - i-tlb-size = <32>; - mmu-type = "riscv,sv39"; - reg = <2>; - riscv,isa = "rv64imafdc"; - tlb-split; - status = "okay"; - operating-points = < - /* kHz uV */ - 600000 1100000 - 300000 950000 - 150000 750000 - >; - cpu2intc: interrupt-controller { - #interrupt-cells = <1>; - compatible = "riscv,cpu-intc"; - interrupt-controller; - }; + }; + + reserved-memory { + ranges; + #size-cells = <2>; + #address-cells = <2>; + + fabricbuf0: fabricbuf@0 { + compatible = "shared-dma-pool"; + reg = <0x0 0xae000000 0x0 0x2000000>; + label = "fabricbuf0-ddr-c"; }; - cpu3: cpu@3 { - clocks = <&clkcfg CLK_CPU>; - compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; - d-cache-block-size = <64>; - d-cache-sets = <64>; - d-cache-size = <32768>; - d-tlb-sets = <1>; - d-tlb-size = <32>; - device_type = "cpu"; - i-cache-block-size = <64>; - i-cache-sets = <64>; - i-cache-size = <32768>; - i-tlb-sets = <1>; - i-tlb-size = <32>; - mmu-type = "riscv,sv39"; - reg = <3>; - riscv,isa = "rv64imafdc"; - tlb-split; - status = "okay"; - operating-points = < - /* kHz uV */ - 600000 1100000 - 300000 950000 - 150000 750000 - >; - cpu3intc: interrupt-controller { - #interrupt-cells = <1>; - compatible = "riscv,cpu-intc"; - interrupt-controller; - }; + + fabricbuf1: fabricbuf@1 { + compatible = "shared-dma-pool"; + reg = <0x0 0xc0000000 0x0 0x8000000>; + label = "fabricbuf1-ddr-nc"; }; - cpu4: cpu@4 { - clocks = <&clkcfg CLK_CPU>; - compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; - d-cache-block-size = <64>; - d-cache-sets = <64>; - d-cache-size = <32768>; - d-tlb-sets = <1>; - d-tlb-size = <32>; - device_type = "cpu"; - i-cache-block-size = <64>; - i-cache-sets = <64>; - i-cache-size = <32768>; - i-tlb-sets = <1>; - i-tlb-size = <32>; - mmu-type = "riscv,sv39"; - reg = <4>; - riscv,isa = "rv64imafdc"; - tlb-split; - status = "okay"; - operating-points = < - /* kHz uV */ - 600000 1100000 - 300000 950000 - 150000 750000 - >; - cpu4intc: interrupt-controller { - #interrupt-cells = <1>; - compatible = "riscv,cpu-intc"; - interrupt-controller; - }; + + fabricbuf2: fabricbuf@2 { + compatible = "shared-dma-pool"; + reg = <0x0 0xd8000000 0x0 0x8000000>; + label = "fabricbuf2-ddr-nc-wcb"; }; }; - refclk: refclk { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <600000000>; - clock-output-names = "msspllclk"; + + udmabuf0 { + compatible = "ikwzm,u-dma-buf"; + device-name = "udmabuf-ddr-c0"; + minor-number = <0>; + size = <0x0 0x2000000>; + memory-region = <&fabricbuf0>; + sync-mode = <3>; + }; + + udmabuf1 { + compatible = "ikwzm,u-dma-buf"; + device-name = "udmabuf-ddr-nc0"; + minor-number = <1>; + size = <0x0 0x8000000>; + memory-region = <&fabricbuf1>; + sync-mode = <3>; + }; + + udmabuf2 { + compatible = "ikwzm,u-dma-buf"; + device-name = "udmabuf-ddr-nc-wcb0"; + minor-number = <2>; + size = <0x0 0x8000000>; + memory-region = <&fabricbuf2>; + sync-mode = <3>; }; - ddr: memory@80000000 { + + ddrc_cache_lo: memory@80000000 { device_type = "memory"; - reg = <0x0 0x80000000 0x0 0x40000000>; + reg = <0x0 0x80000000 0x0 0x2e000000>; clocks = <&clkcfg CLK_DDRC>; + status = "okay"; }; - soc: soc { - #address-cells = <2>; - #size-cells = <2>; - compatible = "microchip,mpfs-icicle-kit", "simple-bus"; - ranges; - clint0: clint@2000000 { - compatible = "riscv,clint0"; - interrupts-extended = <&cpu0intc 3 &cpu0intc 7 - &cpu1intc 3 &cpu1intc 7 - &cpu2intc 3 &cpu2intc 7 - &cpu3intc 3 &cpu3intc 7 - &cpu4intc 3 &cpu4intc 7>; - reg = <0x0 0x2000000 0x0 0x10000>; - reg-names = "control"; - clock-frequency = <RTCCLK_FREQ>; - }; - cachecontroller: cache-controller@2010000 { - compatible = "sifive,fu540-c000-ccache", "cache"; - cache-block-size = <64>; - cache-level = <2>; - cache-sets = <1024>; - cache-size = <2097152>; - cache-unified; - interrupt-parent = <&plic>; - interrupts = <1 2 3>; - reg = <0x0 0x2010000 0x0 0x1000>; - }; - plic: interrupt-controller@c000000 { - #interrupt-cells = <1>; - compatible = "sifive,plic-1.0.0"; - reg = <0x0 0xc000000 0x0 0x4000000>; - riscv,max-priority = <7>; - riscv,ndev = <186>; - interrupt-controller; - interrupts-extended = < - &cpu0intc 11 - &cpu1intc 11 &cpu1intc 9 - &cpu2intc 11 &cpu2intc 9 - &cpu3intc 11 &cpu3intc 9 - &cpu4intc 11 &cpu4intc 9>; - }; - uart0: serial@20000000 { - compatible = "ns16550a"; - reg = <0x0 0x20000000 0x0 0x400>; - reg-io-width = <4>; - reg-shift = <2>; - interrupt-parent = <&plic>; - interrupts = <90>; - clocks = <&clkcfg CLK_MMUART0>; - status = "okay"; - }; - clkcfg: clkcfg@20002000 { - compatible = "microchip,mpfs-clkcfg"; - reg = <0x0 0x20002000 0x0 0x1000>; - reg-names = "mss_sysreg"; - clocks = <&refclk>; - #clock-cells = <1>; - clock-output-names = "cpu", "axi", "ahb", "envm", - "mac0", "mac1", "mmc", "timer", - "mmuart0", "mmuart1", "mmuart2", - "mmuart3", "mmuart4", "spi0", "spi1", - "i2c0", "i2c1", "can0", "can1", "usb", - "reserved", "rtc", "qspi", "gpio0", - "gpio1", "gpio2", "ddrc", "fic0", - "fic1", "fic2", "fic3", "athena", - "cfm"; - }; - emmc: mmc@20008000 { - compatible = "cdns,sd4hc"; - reg = <0x0 0x20008000 0x0 0x1000>; - interrupt-parent = <&plic>; - interrupts = <88 89>; - pinctrl-names = "default"; - clocks = <&clkcfg CLK_MMC>; - bus-width = <4>; - cap-mmc-highspeed; - mmc-ddr-3_3v; - max-frequency = <200000000>; - non-removable; - no-sd; - no-sdio; - voltage-ranges = <3300 3300>; - status = "okay"; - }; - sdcard: sd@20008000 { - compatible = "cdns,sd4hc"; - reg = <0x0 0x20008000 0x0 0x1000>; - interrupt-parent = <&plic>; - interrupts = <88>; - pinctrl-names = "default"; - clocks = <&clkcfg CLK_MMC>; - bus-width = <4>; - disable-wp; - cap-sd-highspeed; - card-detect-delay = <200>; - sd-uhs-sdr12; - sd-uhs-sdr25; - sd-uhs-sdr50; - sd-uhs-sdr104; - max-frequency = <200000000>; - status = "disabled"; - }; - uart1: serial@20100000 { - compatible = "ns16550a"; - reg = <0x0 0x20100000 0x0 0x400>; - reg-io-width = <4>; - reg-shift = <2>; - interrupt-parent = <&plic>; - interrupts = <91>; - clocks = <&clkcfg CLK_MMUART1>; - status = "okay"; - }; - uart2: serial@20102000 { - compatible = "ns16550a"; - reg = <0x0 0x20102000 0x0 0x400>; - reg-io-width = <4>; - reg-shift = <2>; - interrupt-parent = <&plic>; - interrupts = <92>; - clocks = <&clkcfg CLK_MMUART2>; - status = "okay"; - }; - uart3: serial@20104000 { - compatible = "ns16550a"; - reg = <0x0 0x20104000 0x0 0x400>; - reg-io-width = <4>; - reg-shift = <2>; - interrupt-parent = <&plic>; - interrupts = <93>; - clocks = <&clkcfg CLK_MMUART3>; - status = "okay"; - }; - i2c0: i2c@2010a000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "microchip,mpfs-mss-i2c"; - reg = <0x0 0x2010a000 0x0 0x1000>; - interrupt-parent = <&plic>; - interrupts = <58>; - clocks = <&clkcfg CLK_I2C0>; - status = "disabled"; - }; - i2c1: i2c@2010b000 { - #address-cells = <1>; - #size-cells = <0>; - compatible = "microchip,mpfs-mss-i2c"; - reg = <0x0 0x2010b000 0x0 0x1000>; - interrupt-parent = <&plic>; - interrupts = <61>; - clocks = <&clkcfg CLK_I2C1>; - status = "disabled"; - pac193x@10 { - compatible = "microchip,pac1934"; - reg = <0x10>; - samp-rate = <64>; - status = "disabled"; - ch1: channel0 { - uohms-shunt-res = <10000>; - rail-name = "VDD"; - channel_enabled; - }; - ch2: channel1 { - uohms-shunt-res = <10000>; - rail-name = "VDDA25"; - channel_enabled; - }; - ch3: channel2 { - uohms-shunt-res = <10000>; - rail-name = "VDD25"; - channel_enabled; - }; - ch4: channel3 { - uohms-shunt-res = <10000>; - rail-name = "VDDA"; - channel_enabled; - }; - }; - }; - emac0: ethernet@20110000 { - compatible = "microchip,mpfs-mss-gem"; - reg = <0x0 0x20110000 0x0 0x2000>; - interrupt-parent = <&plic>; - interrupts = <64 65 66 67>; - local-mac-address = [56 34 00 FC 00 02]; - phy-mode = "sgmii"; - clocks = <&clkcfg CLK_MAC0>, <&clkcfg CLK_AXI>; - clock-names = "pclk", "hclk"; - status = "disabled"; - #address-cells = <1>; - #size-cells = <0>; - phy-handle = <&phy0>; - phy0: ethernet-phy@8 { - reg = <8>; - ti,fifo-depth = <0x01>; - }; - }; - emac1: ethernet@20112000 { - compatible = "microchip,mpfs-mss-gem"; - reg = <0x0 0x20112000 0x0 0x2000>; - interrupt-parent = <&plic>; - interrupts = <70 71 72 73>; - local-mac-address = [00 00 00 00 00 00]; - phy-mode = "sgmii"; - clocks = <&clkcfg CLK_MAC1>, <&clkcfg CLK_AHB>; - clock-names = "pclk", "hclk"; - status = "okay"; + ddrc_cache_hi: memory@1000000000 { + device_type = "memory"; + reg = <0x10 0x0 0x0 0x40000000>; + clocks = <&clkcfg CLK_DDRC>; + status = "okay"; + }; +}; - #address-cells = <1>; - #size-cells = <0>; - phy-handle = <&phy1>; - phy1: ethernet-phy@9 { - reg = <9>; - ti,fifo-depth = <0x01>; - }; - }; - gpio: gpio@20122000 { - compatible = "microchip,mpfs-mss-gpio"; - interrupt-parent = <&plic>; - interrupts = <13 14 15 16 17 18 19 20 21 22 23 24 25 26 - 27 28 29 30 31 32 33 34 35 36 37 38 39 - 40 41 42 43 44>; - gpio-controller; - clocks = <&clkcfg CLK_GPIO2>; - reg = <0x00 0x20122000 0x0 0x1000>; - reg-names = "control"; - #gpio-cells = <2>; - status = "disabled"; +&uart1 { + status = "okay"; +}; + +&mmc { + status = "okay"; + + bus-width = <4>; + disable-wp; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <200>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-sdr104; +}; + +&i2c1 { + status = "okay"; + clock-frequency = <100000>; + + pac193x: pac193x@10 { + compatible = "microchip,pac1934"; + reg = <0x10>; + samp-rate = <64>; + status = "okay"; + ch1: channel0 { + uohms-shunt-res = <10000>; + rail-name = "VDDREG"; + channel_enabled; + }; + ch2: channel1 { + uohms-shunt-res = <10000>; + rail-name = "VDDA25"; + channel_enabled; + }; + ch3: channel2 { + uohms-shunt-res = <10000>; + rail-name = "VDD25"; + channel_enabled; + }; + ch4: channel3 { + uohms-shunt-res = <10000>; + rail-name = "VDDA_REG"; + channel_enabled; }; }; }; + +&mac1 { + status = "okay"; + phy-mode = "sgmii"; + phy-handle = <&phy1>; + phy1: ethernet-phy@9 { + reg = <9>; + ti,fifo-depth = <0x1>; + }; +}; diff --git a/arch/riscv/dts/microchip-mpfs.dtsi b/arch/riscv/dts/microchip-mpfs.dtsi new file mode 100644 index 0000000..4f449a3 --- /dev/null +++ b/arch/riscv/dts/microchip-mpfs.dtsi @@ -0,0 +1,571 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* Copyright (c) 2020-2021 Microchip Technology Inc */ + +#include "dt-bindings/clock/microchip-mpfs-clock.h" +#include "dt-bindings/interrupt-controller/microchip-mpfs-plic.h" +#include "dt-bindings/interrupt-controller/riscv-hart.h" + +/ { + #address-cells = <2>; + #size-cells = <2>; + model = "Microchip PolarFire SoC"; + compatible = "microchip,mpfs"; + + chosen { + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "sifive,e51", "sifive,rocket0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <16384>; + reg = <0>; + riscv,isa = "rv64imac"; + clocks = <&clkcfg CLK_CPU>; + status = "disabled"; + operating-points = < + /* kHz uV */ + 600000 1100000 + 300000 950000 + 150000 750000 + >; + cpu0_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu1: cpu@1 { + compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + reg = <1>; + riscv,isa = "rv64imafdc"; + clocks = <&clkcfg CLK_CPU>; + tlb-split; + status = "okay"; + operating-points = < + /* kHz uV */ + 600000 1100000 + 300000 950000 + 150000 750000 + >; + cpu1_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu2: cpu@2 { + compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + reg = <2>; + riscv,isa = "rv64imafdc"; + clocks = <&clkcfg CLK_CPU>; + tlb-split; + status = "okay"; + operating-points = < + /* kHz uV */ + 600000 1100000 + 300000 950000 + 150000 750000 + >; + cpu2_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu3: cpu@3 { + compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + reg = <3>; + riscv,isa = "rv64imafdc"; + clocks = <&clkcfg CLK_CPU>; + tlb-split; + status = "okay"; + operating-points = < + /* kHz uV */ + 600000 1100000 + 300000 950000 + 150000 750000 + >; + cpu3_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu4: cpu@4 { + compatible = "sifive,u54-mc", "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + reg = <4>; + riscv,isa = "rv64imafdc"; + clocks = <&clkcfg CLK_CPU>; + tlb-split; + status = "okay"; + operating-points = < + /* kHz uV */ + 600000 1100000 + 300000 950000 + 150000 750000 + >; + cpu4_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "microchip,mpfs-soc", "simple-bus"; + ranges; + + clint: clint@2000000 { + compatible = "sifive,clint0"; + reg = <0x0 0x2000000 0x0 0xC000>; + interrupts-extended = + <&cpu0_intc HART_INT_M_SOFT &cpu0_intc HART_INT_M_TIMER + &cpu1_intc HART_INT_M_SOFT &cpu1_intc HART_INT_M_TIMER + &cpu2_intc HART_INT_M_SOFT &cpu2_intc HART_INT_M_TIMER + &cpu3_intc HART_INT_M_SOFT &cpu3_intc HART_INT_M_TIMER + &cpu4_intc HART_INT_M_SOFT &cpu4_intc HART_INT_M_TIMER>; + }; + + cachecontroller: cache-controller@2010000 { + compatible = "sifive,fu540-c000-ccache", "cache"; + reg = <0x0 0x2010000 0x0 0x1000>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_L2_METADATA_CORR + PLIC_INT_L2_METADATA_UNCORR + PLIC_INT_L2_DATA_CORR>; + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <1024>; + cache-size = <2097152>; + cache-unified; + }; + + pdma: pdma@3000000 { + compatible = "microchip,mpfs-pdma-uio","sifive,fu540-c000-pdma"; + reg = <0x0 0x3000000 0x0 0x8000>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_DMA_CH0_DONE PLIC_INT_DMA_CH0_ERR + PLIC_INT_DMA_CH1_DONE PLIC_INT_DMA_CH1_ERR + PLIC_INT_DMA_CH2_DONE PLIC_INT_DMA_CH2_ERR + PLIC_INT_DMA_CH3_DONE PLIC_INT_DMA_CH3_ERR>; + #dma-cells = <1>; + }; + + plic: interrupt-controller@c000000 { + compatible = "sifive,plic-1.0.0"; + reg = <0x0 0xc000000 0x0 0x4000000>; + #interrupt-cells = <1>; + riscv,ndev = <186>; + interrupt-controller; + interrupts-extended = <&cpu0_intc HART_INT_M_EXT + &cpu1_intc HART_INT_M_EXT &cpu1_intc HART_INT_S_EXT + &cpu2_intc HART_INT_M_EXT &cpu2_intc HART_INT_S_EXT + &cpu3_intc HART_INT_M_EXT &cpu3_intc HART_INT_S_EXT + &cpu4_intc HART_INT_M_EXT &cpu4_intc HART_INT_S_EXT>; + }; + + refclk: refclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <600000000>; + clock-output-names = "msspllclk"; + }; + + clkcfg: clkcfg@20002000 { + compatible = "microchip,mpfs-clkcfg"; + reg = <0x0 0x20002000 0x0 0x1000>; + reg-names = "mss_sysreg"; + clocks = <&refclk>; + #clock-cells = <1>; + clock-output-names = "cpu", "axi", "ahb", "envm", /* 0-3 */ + "mac0", "mac1", "mmc", "timer", /* 4-7 */ + "mmuart0", "mmuart1", "mmuart2", "mmuart3", /* 8-11 */ + "mmuart4", "spi0", "spi1", "i2c0", /* 12-15 */ + "i2c1", "can0", "can1", "usb", /* 16-19 */ + "rsvd", "rtc", "qspi", "gpio0", /* 20-23 */ + "gpio1", "gpio2", "ddrc", "fic0", /* 24-27 */ + "fic1", "fic2", "fic3", "athena", "cfm"; /* 28-32 */ + }; + + /* Common node entry for eMMC/SD */ + mmc: mmc@20008000 { + compatible = "microchip,mpfs-sd4hc","cdns,sd4hc"; + reg = <0x0 0x20008000 0x0 0x1000>; + clocks = <&clkcfg CLK_MMC>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_MMC_MAIN PLIC_INT_MMC_WAKEUP>; + max-frequency = <200000000>; + status = "disabled"; + }; + + uart0: serial@20000000 { + compatible = "ns16550a"; + reg = <0x0 0x20000000 0x0 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_MMUART0>; + clocks = <&clkcfg CLK_MMUART0>; + status = "disabled"; /* Reserved for the HSS */ + }; + + uart1: serial@20100000 { + compatible = "ns16550a"; + reg = <0x0 0x20100000 0x0 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_MMUART1>; + clocks = <&clkcfg CLK_MMUART1>; + status = "disabled"; + }; + + uart2: serial@20102000 { + compatible = "ns16550a"; + reg = <0x0 0x20102000 0x0 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_MMUART2>; + clocks = <&clkcfg CLK_MMUART2>; + status = "disabled"; + }; + + uart3: serial@20104000 { + compatible = "ns16550a"; + reg = <0x0 0x20104000 0x0 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_MMUART3>; + clocks = <&clkcfg CLK_MMUART3>; + status = "disabled"; + }; + + uart4: serial@20106000 { + compatible = "ns16550a"; + reg = <0x0 0x20106000 0x0 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_MMUART4>; + clocks = <&clkcfg CLK_MMUART4>; + status = "disabled"; + }; + + spi0: spi@20108000 { + compatible = "microchip,mpfs-spi"; + reg = <0x0 0x20108000 0x0 0x1000>; + clocks = <&clkcfg CLK_SPI0>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_SPI0>; + num-cs = <8>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + spi1: spi@20109000 { + compatible = "microchip,mpfs-spi"; + reg = <0x0 0x20109000 0x0 0x1000>; + clocks = <&clkcfg CLK_SPI1>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_SPI1>; + num-cs = <8>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c0: i2c@2010a000 { + compatible = "microchip,mpfs-i2c"; + reg = <0x0 0x2010a000 0x0 0x1000>; + clocks = <&clkcfg CLK_I2C0>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_I2C0_MAIN>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + i2c1: i2c@2010b000 { + compatible = "microchip,mpfs-i2c"; + reg = <0x0 0x2010b000 0x0 0x1000>; + clocks = <&clkcfg CLK_I2C1>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_I2C1_MAIN>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + can0: can@2010c000 { + compatible = "microchip,mpfs-can-uio"; + reg = <0x0 0x2010c000 0x0 0x1000>; + clocks = <&clkcfg CLK_CAN0>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_CAN0>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + can1: can@2010d000 { + compatible = "microchip,mpfs-can-uio"; + reg = <0x0 0x2010d000 0x0 0x1000>; + clocks = <&clkcfg CLK_CAN1>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_CAN1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + mac0: ethernet@20110000 { + compatible = "cdns,macb"; + reg = <0x0 0x20110000 0x0 0x2000>; + clocks = <&clkcfg CLK_MAC0>, <&clkcfg CLK_AHB>; + clock-names = "pclk", "hclk"; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_MAC0_INT + PLIC_INT_MAC0_QUEUE1 + PLIC_INT_MAC0_QUEUE2 + PLIC_INT_MAC0_QUEUE3 + PLIC_INT_MAC0_EMAC + PLIC_INT_MAC0_MMSL>; + local-mac-address = [00 00 00 00 00 00]; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + mac1: ethernet@20112000 { + compatible = "cdns,macb"; + reg = <0x0 0x20112000 0x0 0x2000>; + clocks = <&clkcfg CLK_MAC1>, <&clkcfg CLK_AHB>; + clock-names = "pclk", "hclk"; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_MAC1_INT + PLIC_INT_MAC1_QUEUE1 + PLIC_INT_MAC1_QUEUE2 + PLIC_INT_MAC1_QUEUE3 + PLIC_INT_MAC1_EMAC + PLIC_INT_MAC1_MMSL>; + local-mac-address = [00 00 00 00 00 00]; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + + gpio0: gpio@20120000 { + compatible = "microchip,mpfs-gpio"; + reg = <0x0 0x20120000 0x0 0x1000>; + reg-names = "control"; + clocks = <&clkcfg CLK_GPIO0>; + interrupt-parent = <&plic>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + gpio1: gpio@20121000 { + compatible = "microchip,mpfs-gpio"; + reg = <000 0x20121000 0x0 0x1000>; + reg-names = "control"; + clocks = <&clkcfg CLK_GPIO1>; + interrupt-parent = <&plic>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + gpio2: gpio@20122000 { + compatible = "microchip,mpfs-gpio"; + reg = <0x0 0x20122000 0x0 0x1000>; + reg-names = "control"; + clocks = <&clkcfg CLK_GPIO2>; + interrupt-parent = <&plic>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + rtc: rtc@20124000 { + compatible = "microchip,mpfs-rtc"; + reg = <0x0 0x20124000 0x0 0x1000>; + clocks = <&clkcfg CLK_RTC>; + clock-names = "rtc"; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_RTC_WAKEUP PLIC_INT_RTC_MATCH>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + usb: usb@20201000 { + compatible = "microchip,mpfs-usb-host"; + reg = <0x0 0x20201000 0x0 0x1000>; + reg-names = "mc","control"; + clocks = <&clkcfg CLK_USB>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_USB_DMA PLIC_INT_USB_MC>; + interrupt-names = "dma","mc"; + dr_mode = "host"; + status = "disabled"; + }; + + qspi: qspi@21000000 { + compatible = "microchip,mpfs-qspi"; + reg = <0x0 0x21000000 0x0 0x1000>; + clocks = <&clkcfg CLK_QSPI>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_QSPI>; + num-cs = <8>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + mbox: mailbox@37020000 { + compatible = "microchip,mpfs-mailbox"; + reg = <0x0 0x37020000 0x0 0x1000>, <0x0 0x2000318C 0x0 0x40>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_G5C_MESSAGE>; + #mbox-cells = <1>; + status = "disabled"; + }; + + pcie: pcie@2000000000 { + compatible = "microchip,pcie-host-1.0"; + #address-cells = <0x3>; + #interrupt-cells = <0x1>; + #size-cells = <0x2>; + device_type = "pci"; + reg = <0x20 0x0 0x0 0x8000000 0x0 0x43000000 0x0 0x10000>; + reg-names = "cfg", "apb"; + clocks = <&clkcfg CLK_FIC0>, <&clkcfg CLK_FIC1>, <&clkcfg CLK_FIC3>; + clock-names = "fic0", "fic1", "fic3"; + bus-range = <0x0 0x7f>; + interrupt-parent = <&plic>; + interrupts = <PLIC_INT_FABRIC_F2H_2>; + interrupt-map = <0 0 0 1 &pcie_intc 0>, + <0 0 0 2 &pcie_intc 1>, + <0 0 0 3 &pcie_intc 2>, + <0 0 0 4 &pcie_intc 3>; + interrupt-map-mask = <0 0 0 7>; + ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>; + msi-parent = <&pcie>; + msi-controller; + mchp,axi-m-atr0 = <0x10 0x0>; + status = "disabled"; + pcie_intc: legacy-interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + + syscontroller: syscontroller { + compatible = "microchip,mpfs-sys-controller"; + #address-cells = <1>; + #size-cells = <1>; + mboxes = <&mbox 0>; + }; + + hwrandom: hwrandom { + compatible = "microchip,mpfs-rng"; + #address-cells = <1>; + #size-cells = <1>; + syscontroller = <&syscontroller>; + }; + + serialnum: serialnum { + compatible = "microchip,mpfs-serial-number"; + #address-cells = <1>; + #size-cells = <1>; + syscontroller = <&syscontroller>; + }; + + fpgadigest: fpgadigest { + compatible = "microchip,mpfs-digest"; + #address-cells = <1>; + #size-cells = <1>; + syscontroller = <&syscontroller>; + }; + + devicecert: cert { + compatible = "microchip,mpfs-device-cert"; + #address-cells = <1>; + #size-cells = <1>; + syscontroller = <&syscontroller>; + }; + + signature: signature { + compatible = "microchip,mpfs-signature"; + #address-cells = <1>; + #size-cells = <1>; + syscontroller = <&syscontroller>; + }; + }; +}; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e5261bb..48ca3e1 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -499,6 +499,10 @@ compatible = "sandbox,clk-ccf"; }; + efi-media { + compatible = "sandbox,efi-media"; + }; + eth@10002000 { compatible = "sandbox,eth"; reg = <0x10002000 0x1000>; diff --git a/board/CZ.NIC/turris_mox/turris_mox.c b/board/CZ.NIC/turris_mox/turris_mox.c index 2202eb8..b61c5b1 100644 --- a/board/CZ.NIC/turris_mox/turris_mox.c +++ b/board/CZ.NIC/turris_mox/turris_mox.c @@ -41,22 +41,14 @@ #define ARMADA_37XX_SPI_DOUT (MVEBU_REGISTER(0x10608)) #define ARMADA_37XX_SPI_DIN (MVEBU_REGISTER(0x1060c)) -#define ETH1_PATH "/soc/internal-regs@d0000000/ethernet@40000" -#define MDIO_PATH "/soc/internal-regs@d0000000/mdio@32004" -#define SFP_GPIO_PATH "/soc/internal-regs@d0000000/spi@10600/moxtet@1/gpio@0" -#define PCIE_PATH "/soc/pcie@d0070000" -#define SFP_PATH "/sfp" -#define LED_PATH "/leds/led" -#define BUTTON_PATH "/gpio-keys/reset" - DECLARE_GLOBAL_DATA_PTR; #if defined(CONFIG_OF_BOARD_FIXUP) int board_fix_fdt(void *blob) { + enum fdt_status status_pcie, status_eth1; u8 topology[MAX_MOX_MODULES]; - int i, size, node; - bool enable; + int i, size, ret; /* * SPI driver is not loaded in driver model yet, but we have to find out @@ -64,15 +56,20 @@ int board_fix_fdt(void *blob) * to read SPI by reading/writing SPI registers directly */ - writel(0x10df, ARMADA_37XX_SPI_CFG); /* put pin from GPIO to SPI mode */ clrbits_le32(ARMADA_37XX_NB_GPIO_SEL, BIT(12)); + /* configure cpol, cpha, prescale */ + writel(0x10df, ARMADA_37XX_SPI_CFG); + mdelay(1); /* enable SPI CS1 */ setbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17)); while (!(readl(ARMADA_37XX_SPI_CTRL) & 0x2)) udelay(1); + status_pcie = FDT_STATUS_DISABLED; + status_eth1 = FDT_STATUS_DISABLED; + for (i = 0; i < MAX_MOX_MODULES; ++i) { writel(0x0, ARMADA_37XX_SPI_DOUT); @@ -84,6 +81,11 @@ int board_fix_fdt(void *blob) break; topology[i] &= 0xf; + + if (topology[i] == MOX_MODULE_SFP || + topology[i] == MOX_MODULE_TOPAZ || + topology[i] == MOX_MODULE_PERIDOT) + status_eth1 = FDT_STATUS_OKAY; } size = i; @@ -91,24 +93,21 @@ int board_fix_fdt(void *blob) /* disable SPI CS1 */ clrbits_le32(ARMADA_37XX_SPI_CTRL, BIT(17)); + ret = fdt_set_status_by_alias(blob, "ethernet1", status_eth1); + if (ret < 0) + printf("Cannot set status for eth1 in U-Boot's device tree: %s!\n", + fdt_strerror(ret)); + if (size > 1 && (topology[1] == MOX_MODULE_PCI || topology[1] == MOX_MODULE_USB3 || topology[1] == MOX_MODULE_PASSPCI)) - enable = true; - else - enable = false; - - node = fdt_path_offset(blob, PCIE_PATH); - - if (node < 0) { - printf("Cannot find PCIe node in U-Boot's device tree!\n"); - return 0; - } + status_pcie = FDT_STATUS_OKAY; - if (fdt_setprop_string(blob, node, "status", - enable ? "okay" : "disabled") < 0) { - printf("Cannot %s PCIe in U-Boot's device tree!\n", - enable ? "enable" : "disable"); + ret = fdt_set_status_by_compatible(blob, "marvell,armada-3700-pcie", + status_pcie); + if (ret < 0) { + printf("Cannot set status for PCIe in U-Boot's device tree: %s!\n", + fdt_strerror(ret)); return 0; } @@ -416,12 +415,18 @@ static bool read_reset_button(void) struct udevice *button, *led; int i; - if (device_get_global_by_ofnode(ofnode_path(BUTTON_PATH), &button)) { + if (device_get_global_by_ofnode( + ofnode_first_subnode(ofnode_by_compatible(ofnode_null(), + "gpio-keys")), + &button)) { printf("Cannot find reset button!\n"); return false; } - if (device_get_global_by_ofnode(ofnode_path(LED_PATH), &led)) { + if (device_get_global_by_ofnode( + ofnode_first_subnode(ofnode_by_compatible(ofnode_null(), + "gpio-leds")), + &led)) { printf("Cannot find status LED!\n"); return false; } @@ -664,92 +669,34 @@ handle_reset_btn: #if defined(CONFIG_OF_BOARD_SETUP) -static int vnode_by_path(void *blob, const char *fmt, va_list ap) +static bool is_topaz(int id) { - char path[128]; - - vsnprintf(path, 128, fmt, ap); - return fdt_path_offset(blob, path); + return topaz && id == peridot + topaz - 1; } -static int node_by_path(void *blob, const char *fmt, ...) +static int switch_addr(int id) { - va_list ap; - int res; - - va_start(ap, fmt); - res = vnode_by_path(blob, fmt, ap); - va_end(ap); - - return res; + return is_topaz(id) ? 0x2 : 0x10 + id; } -static int phandle_by_path(void *blob, const char *fmt, ...) +static int setup_switch(void *blob, int id) { - va_list ap; - int node, phandle, res; - - va_start(ap, fmt); - node = vnode_by_path(blob, fmt, ap); - va_end(ap); + int res, addr, i, node; + char mdio_path[64]; + node = fdt_node_offset_by_compatible(blob, -1, "marvell,orion-mdio"); if (node < 0) return node; - phandle = fdt_get_phandle(blob, node); - if (phandle > 0) - return phandle; - - phandle = fdt_get_max_phandle(blob); - if (phandle < 0) - return phandle; - - phandle += 1; - - res = fdt_setprop_u32(blob, node, "linux,phandle", phandle); + res = fdt_get_path(blob, node, mdio_path, sizeof(mdio_path)); if (res < 0) return res; - res = fdt_setprop_u32(blob, node, "phandle", phandle); - if (res < 0) - return res; - - return phandle; -} - -static int enable_by_path(void *blob, const char *fmt, ...) -{ - va_list ap; - int node; - - va_start(ap, fmt); - node = vnode_by_path(blob, fmt, ap); - va_end(ap); - - if (node < 0) - return node; - - return fdt_setprop_string(blob, node, "status", "okay"); -} - -static bool is_topaz(int id) -{ - return topaz && id == peridot + topaz - 1; -} - -static int switch_addr(int id) -{ - return is_topaz(id) ? 0x2 : 0x10 + id; -} - -static int setup_switch(void *blob, int id) -{ - int res, addr, i, node, phandle; - addr = switch_addr(id); /* first enable the switch by setting status = "okay" */ - res = enable_by_path(blob, MDIO_PATH "/switch%i@%x", id, addr); + res = fdt_status_okay_by_pathf(blob, "%s/switch%i@%x", mdio_path, id, + addr); if (res < 0) return res; @@ -758,13 +705,13 @@ static int setup_switch(void *blob, int id) * enable corresponding ports */ if (id < peridot + topaz - 1) { - res = enable_by_path(blob, - MDIO_PATH "/switch%i@%x/ports/port@a", - id, addr); + res = fdt_status_okay_by_pathf(blob, + "%s/switch%i@%x/ports/port@a", + mdio_path, id, addr); } else if (id == peridot - 1 && !topaz && sfp) { - res = enable_by_path(blob, - MDIO_PATH "/switch%i@%x/ports/port-sfp@a", - id, addr); + res = fdt_status_okay_by_pathf(blob, + "%s/switch%i@%x/ports/port-sfp@a", + mdio_path, id, addr); } else { res = 0; } @@ -775,18 +722,21 @@ static int setup_switch(void *blob, int id) return 0; /* finally change link property if needed */ - node = node_by_path(blob, MDIO_PATH "/switch%i@%x/ports/port@a", id, - addr); + node = fdt_node_offset_by_pathf(blob, "%s/switch%i@%x/ports/port@a", + mdio_path, id, addr); if (node < 0) return node; for (i = id + 1; i < peridot + topaz; ++i) { - phandle = phandle_by_path(blob, - MDIO_PATH "/switch%i@%x/ports/port@%x", - i, switch_addr(i), - is_topaz(i) ? 5 : 9); - if (phandle < 0) - return phandle; + unsigned int phandle; + + phandle = fdt_create_phandle_by_pathf(blob, + "%s/switch%i@%x/ports/port@%x", + mdio_path, i, + switch_addr(i), + is_topaz(i) ? 5 : 9); + if (!phandle) + return -FDT_ERR_NOPHANDLES; if (i == id + 1) res = fdt_setprop_u32(blob, node, "link", phandle); @@ -799,38 +749,17 @@ static int setup_switch(void *blob, int id) return 0; } -static int remove_disabled_nodes(void *blob) -{ - while (1) { - int res, offset; - - offset = fdt_node_offset_by_prop_value(blob, -1, "status", - "disabled", 9); - if (offset < 0) - break; - - res = fdt_del_node(blob, offset); - if (res < 0) - return res; - } - - return 0; -} - int ft_board_setup(void *blob, struct bd_info *bd) { - int node, phandle, res; + int res; /* * If MOX B (PCI), MOX F (USB) or MOX G (Passthrough PCI) modules are * connected, enable the PCIe node. */ if (pci || usb || passpci) { - node = fdt_path_offset(blob, PCIE_PATH); - if (node < 0) - return node; - - res = fdt_setprop_string(blob, node, "status", "okay"); + res = fdt_status_okay_by_compatible(blob, + "marvell,armada-3700-pcie"); if (res < 0) return res; @@ -847,7 +776,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) if (peridot || topaz) { int i; - res = enable_by_path(blob, ETH1_PATH); + res = fdt_status_okay_by_alias(blob, "ethernet1"); if (res < 0) return res; @@ -865,20 +794,25 @@ int ft_board_setup(void *blob, struct bd_info *bd) * Also enable and configure SFP GPIO controller node. */ if (sfp) { - res = enable_by_path(blob, SFP_PATH); + int node; + + res = fdt_status_okay_by_compatible(blob, "sff,sfp"); if (res < 0) return res; - res = enable_by_path(blob, ETH1_PATH); + res = fdt_status_okay_by_alias(blob, "ethernet1"); if (res < 0) return res; if (!peridot) { - phandle = phandle_by_path(blob, SFP_PATH); - if (phandle < 0) - return res; + unsigned int phandle; + + phandle = fdt_create_phandle_by_compatible(blob, + "sff,sfp"); + if (!phandle) + return -FDT_ERR_NOPHANDLES; - node = node_by_path(blob, ETH1_PATH); + node = fdt_path_offset(blob, "ethernet1"); if (node < 0) return node; @@ -892,7 +826,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) return res; } - res = enable_by_path(blob, SFP_GPIO_PATH); + res = fdt_status_okay_by_compatible(blob, "cznic,moxtet-gpio"); if (res < 0) return res; @@ -900,7 +834,8 @@ int ft_board_setup(void *blob, struct bd_info *bd) char newname[16]; /* moxtet-sfp is on non-zero position, change default */ - node = node_by_path(blob, SFP_GPIO_PATH); + node = fdt_node_offset_by_compatible(blob, -1, + "cznic,moxtet-gpio"); if (node < 0) return node; @@ -919,7 +854,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) fdt_fixup_ethernet(blob); /* Finally remove disabled nodes, as per Rob Herring's request. */ - remove_disabled_nodes(blob); + fdt_delete_disabled_nodes(blob); return 0; } diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c index 36c596e..ae24d14 100644 --- a/board/CZ.NIC/turris_omnia/turris_omnia.c +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c @@ -43,6 +43,23 @@ DECLARE_GLOBAL_DATA_PTR; #define OMNIA_I2C_EEPROM_CHIP_LEN 2 #define OMNIA_I2C_EEPROM_MAGIC 0x0341a034 +#define SYS_RSTOUT_MASK MVEBU_REGISTER(0x18260) +#define SYS_RSTOUT_MASK_WD BIT(10) + +#define A385_WDT_GLOBAL_CTRL MVEBU_REGISTER(0x20300) +#define A385_WDT_GLOBAL_RATIO_MASK GENMASK(18, 16) +#define A385_WDT_GLOBAL_RATIO_SHIFT 16 +#define A385_WDT_GLOBAL_25MHZ BIT(10) +#define A385_WDT_GLOBAL_ENABLE BIT(8) + +#define A385_WDT_GLOBAL_STATUS MVEBU_REGISTER(0x20304) +#define A385_WDT_GLOBAL_EXPIRED BIT(31) + +#define A385_WDT_DURATION MVEBU_REGISTER(0x20334) + +#define A385_WD_RSTOUT_UNMASK MVEBU_REGISTER(0x20704) +#define A385_WD_RSTOUT_UNMASK_GLOBAL BIT(8) + enum mcu_commands { CMD_GET_STATUS_WORD = 0x01, CMD_GET_RESET = 0x09, @@ -141,6 +158,47 @@ static int omnia_mcu_write(u8 cmd, const void *buf, int len) return dm_i2c_write(chip, cmd, buf, len); } +static void enable_a385_watchdog(unsigned int timeout_minutes) +{ + struct sar_freq_modes sar_freq; + u32 watchdog_freq; + + printf("Enabling A385 watchdog with %u minutes timeout...\n", + timeout_minutes); + + /* + * Use NBCLK clock (a.k.a. L2 clock) as watchdog input clock with + * its maximal ratio 7 instead of default fixed 25 MHz clock. + * It allows to set watchdog duration up to the 22 minutes. + */ + clrsetbits_32(A385_WDT_GLOBAL_CTRL, + A385_WDT_GLOBAL_25MHZ | A385_WDT_GLOBAL_RATIO_MASK, + 7 << A385_WDT_GLOBAL_RATIO_SHIFT); + + /* + * Calculate watchdog clock frequency. It is defined by formula: + * freq = NBCLK / 2 / (2 ^ ratio) + * We set ratio to the maximal possible value 7. + */ + get_sar_freq(&sar_freq); + watchdog_freq = sar_freq.nb_clk * 1000000 / 2 / (1 << 7); + + /* Set watchdog duration */ + writel(timeout_minutes * 60 * watchdog_freq, A385_WDT_DURATION); + + /* Clear the watchdog expiration bit */ + clrbits_32(A385_WDT_GLOBAL_STATUS, A385_WDT_GLOBAL_EXPIRED); + + /* Enable watchdog timer */ + setbits_32(A385_WDT_GLOBAL_CTRL, A385_WDT_GLOBAL_ENABLE); + + /* Enable reset on watchdog */ + setbits_32(A385_WD_RSTOUT_UNMASK, A385_WD_RSTOUT_UNMASK_GLOBAL); + + /* Unmask reset for watchdog */ + clrbits_32(SYS_RSTOUT_MASK, SYS_RSTOUT_MASK_WD); +} + static bool disable_mcu_watchdog(void) { int ret; @@ -423,10 +481,13 @@ void spl_board_init(void) { /* * If booting from UART, disable MCU watchdog in SPL, since uploading - * U-Boot proper can take too much time and trigger it. + * U-Boot proper can take too much time and trigger it. Instead enable + * A385 watchdog with very high timeout (10 minutes) to prevent hangup. */ - if (get_boot_device() == BOOT_DEVICE_UART) + if (get_boot_device() == BOOT_DEVICE_UART) { + enable_a385_watchdog(10); disable_mcu_watchdog(); + } } int board_init(void) diff --git a/board/Marvell/octeon_ebb7304/board.c b/board/Marvell/octeon_ebb7304/board.c index e8e2d54..c6c7c13 100644 --- a/board/Marvell/octeon_ebb7304/board.c +++ b/board/Marvell/octeon_ebb7304/board.c @@ -205,7 +205,7 @@ static int fdt_fix_mix(const void *fdt) int env_lmac = -1; int lmac_fdt_node = -1; int mix_fdt_node = -1; - int lmac_phandle; + unsigned int lmac_phandle; char *compat; /* Get the lmac for this environment variable */ @@ -229,8 +229,7 @@ static int fdt_fix_mix(const void *fdt) } } - lmac_phandle = fdt_alloc_phandle((void *)fdt); - fdt_set_phandle((void *)fdt, lmac_fdt_node, lmac_phandle); + lmac_phandle = fdt_create_phandle((void *)fdt, lmac_fdt_node); /* Get the fdt mix node corresponding to this lmac */ mix_fdt_node = get_mix_fdt_node(fdt, env_node, env_lmac); diff --git a/board/beacon/beacon-rzg2m/MAINTAINERS b/board/beacon/beacon-rzg2m/MAINTAINERS index 77c4057..f8042bb 100644 --- a/board/beacon/beacon-rzg2m/MAINTAINERS +++ b/board/beacon/beacon-rzg2m/MAINTAINERS @@ -4,3 +4,13 @@ S: Maintained F: board/beacon/beacon-rzg2m/ F: include/configs/beacon-rzg2m.h F: configs/rzg2_beacon_defconfig +F: arch/arm/dts/beacon-renesom-baseboard.dtsi +F: arch/arm/dts/beacon-renesom-som.dtsi +F: arch/arm/dts/r8a774a1-beacon-rzg2m-kit.dts +F: arch/arm/dts/r8a774b1-beacon-rzg2n-kit.dts +F: arch/arm/dts/r8a774e1-beacon-rzg2h-kit.dts +F: arch/arm/dts/r8a774a1-beacon-rzg2m-kit-u-boot.dtsi +F: arch/arm/dts/r8a774b1-beacon-rzg2n-kit-u-boot.dtsi +F: arch/arm/dts/r8a774e1-beacon-rzg2h-kit-u-boot.dtsi +F: arch/arm/dts/rz-g2-beacon-u-boot.dtsi + diff --git a/board/freescale/lx2160a/eth_lx2160aqds.c b/board/freescale/lx2160a/eth_lx2160aqds.c index a2b6442..1819b27 100644 --- a/board/freescale/lx2160a/eth_lx2160aqds.c +++ b/board/freescale/lx2160a/eth_lx2160aqds.c @@ -775,10 +775,11 @@ int fdt_fixup_board_phy(void *fdt) int fpga_offset, offset, subnodeoffset; struct mii_dev *mii_dev; struct list_head *mii_devs, *entry; - int ret, dpmac_id, phandle, i; + int ret, dpmac_id, i; struct phy_device *phy_dev; char ethname[ETH_NAME_LEN]; phy_interface_t phy_iface; + uint32_t phandle; ret = 0; /* we know FPGA is connected to i2c0, therefore search path directly, @@ -794,7 +795,10 @@ int fdt_fixup_board_phy(void *fdt) return fpga_offset; } - phandle = fdt_alloc_phandle(fdt); + ret = fdt_generate_phandle(fdt, &phandle); + if (ret < 0) + return ret; + mii_devs = mdio_get_list_head(); list_for_each(entry, mii_devs) { diff --git a/board/freescale/lx2160a/eth_lx2162aqds.c b/board/freescale/lx2160a/eth_lx2162aqds.c index 3b04dea..ac6218e 100644 --- a/board/freescale/lx2160a/eth_lx2162aqds.c +++ b/board/freescale/lx2160a/eth_lx2162aqds.c @@ -787,10 +787,11 @@ int fdt_fixup_board_phy(void *fdt) int fpga_offset, offset, subnodeoffset; struct mii_dev *mii_dev; struct list_head *mii_devs, *entry; - int ret, dpmac_id, phandle, i; + int ret, dpmac_id, i; struct phy_device *phy_dev; char ethname[ETH_NAME_LEN]; phy_interface_t phy_iface; + uint32_t phandle; ret = 0; /* we know FPGA is connected to i2c0, therefore search path directly, @@ -806,7 +807,10 @@ int fdt_fixup_board_phy(void *fdt) return fpga_offset; } - phandle = fdt_alloc_phandle(fdt); + ret = fdt_generate_phandle(fdt, &phandle); + if (ret < 0) + return ret; + mii_devs = mdio_get_list_head(); list_for_each(entry, mii_devs) { diff --git a/board/gateworks/gw_ventana/common.c b/board/gateworks/gw_ventana/common.c index 2be921f..7ec931c 100644 --- a/board/gateworks/gw_ventana/common.c +++ b/board/gateworks/gw_ventana/common.c @@ -1681,8 +1681,7 @@ void ft_early_fixup(void *blob, int board_type) * disable serial2 node for GW54xx for compatibility with older * 3.10.x kernel that improperly had this node enabled in the DT */ - fdt_set_status_by_alias(blob, "serial2", FDT_STATUS_DISABLED, - 0); + fdt_set_status_by_alias(blob, "serial2", FDT_STATUS_DISABLED); /* GW54xx-E adds WDOG2_B external reset */ if (rev < 'E') diff --git a/board/kontron/sl28/sl28.c b/board/kontron/sl28/sl28.c index c8ed7ac..e84b356 100644 --- a/board/kontron/sl28/sl28.c +++ b/board/kontron/sl28/sl28.c @@ -75,7 +75,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) if (CONFIG_IS_ENABLED(SL28_SPL_LOADS_OPTEE_BL32)) { node = fdt_node_offset_by_compatible(blob, -1, "linaro,optee-tz"); if (node) - fdt_set_node_status(blob, node, FDT_STATUS_OKAY, 0); + fdt_set_node_status(blob, node, FDT_STATUS_OKAY); } return 0; diff --git a/board/microchip/mpfs_icicle/Kconfig b/board/microchip/mpfs_icicle/Kconfig index 4678462..092e411 100644 --- a/board/microchip/mpfs_icicle/Kconfig +++ b/board/microchip/mpfs_icicle/Kconfig @@ -45,5 +45,10 @@ config BOARD_SPECIFIC_OPTIONS # dummy imply MMC_WRITE imply MMC_SDHCI imply MMC_SDHCI_CADENCE + imply MMC_SDHCI_ADMA + imply MMC_HS200_SUPPORT + imply CMD_I2C + imply DM_I2C + imply SYS_I2C_MICROCHIP endif diff --git a/board/microchip/mpfs_icicle/mpfs_icicle.c b/board/microchip/mpfs_icicle/mpfs_icicle.c index afef719..e74c9fb 100644 --- a/board/microchip/mpfs_icicle/mpfs_icicle.c +++ b/board/microchip/mpfs_icicle/mpfs_icicle.c @@ -119,7 +119,22 @@ int board_late_init(void) if (icicle_mac_addr[idx] == ':') icicle_mac_addr[idx] = ' '; } - env_set("icicle_mac_addr", icicle_mac_addr); + env_set("icicle_mac_addr0", icicle_mac_addr); + + mac_addr[5] = device_serial_number[0] + 1; + + icicle_mac_addr[0] = '['; + + sprintf(&icicle_mac_addr[1], "%pM", mac_addr); + + icicle_mac_addr[18] = ']'; + icicle_mac_addr[19] = '\0'; + + for (idx = 0; idx < 20; idx++) { + if (icicle_mac_addr[idx] == ':') + icicle_mac_addr[idx] = ' '; + } + env_set("icicle_mac_addr1", icicle_mac_addr); return 0; } diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index cd7d6df..17b8108 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -72,7 +72,7 @@ struct msg_get_clock_rate { #endif /* - * https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md + * https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-revision-codes */ struct rpi_model { const char *name; @@ -157,6 +157,11 @@ static const struct rpi_model rpi_models_new_scheme[] = { DTB_DIR "bcm2711-rpi-4-b.dtb", true, }, + [0x12] = { + "Zero 2 W", + DTB_DIR "bcm2837-rpi-zero-2.dtb", + false, + }, [0x13] = { "400", DTB_DIR "bcm2711-rpi-400.dtb", diff --git a/board/sifive/unmatched/Kconfig b/board/sifive/unmatched/Kconfig index fb2c1fb..fe213fd 100644 --- a/board/sifive/unmatched/Kconfig +++ b/board/sifive/unmatched/Kconfig @@ -26,6 +26,7 @@ config SPL_OPENSBI_LOAD_ADDR config BOARD_SPECIFIC_OPTIONS # dummy def_bool y select SIFIVE_FU740 + select ENV_IS_IN_SPI_FLASH select SUPPORT_SPL select RESET_SIFIVE select BINMAN diff --git a/board/sifive/unmatched/spl.c b/board/sifive/unmatched/spl.c index d566327..7c0beed 100644 --- a/board/sifive/unmatched/spl.c +++ b/board/sifive/unmatched/spl.c @@ -22,6 +22,7 @@ #define GEM_PHY_RESET SIFIVE_GENERIC_GPIO_NR(0, 12) #define MODE_SELECT_REG 0x1000 +#define MODE_SELECT_SPI 0x6 #define MODE_SELECT_SD 0xb #define MODE_SELECT_MASK GENMASK(3, 0) @@ -123,6 +124,8 @@ u32 spl_boot_device(void) u32 boot_device = mode_select & MODE_SELECT_MASK; switch (boot_device) { + case MODE_SELECT_SPI: + return BOOT_DEVICE_SPI; case MODE_SELECT_SD: return BOOT_DEVICE_MMC1; default: diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 4f5747c..fdbcd40 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -698,13 +698,7 @@ int g_dnl_board_usb_cable_connected(void) return ret; } - ret = sun4i_usb_phy_vbus_detect(&phy); - if (ret == 1) { - pr_err("A charger is plugged into the OTG\n"); - return -ENODEV; - } - - return ret; + return sun4i_usb_phy_vbus_detect(&phy); } #endif diff --git a/board/theadorable/theadorable.c b/board/theadorable/theadorable.c index bb2d514..6e41ca2 100644 --- a/board/theadorable/theadorable.c +++ b/board/theadorable/theadorable.c @@ -298,10 +298,19 @@ int board_late_init(void) bootcount_inc(); if (bootcount > PEX_SWITCH_NOT_FOUNT_LIMIT) { - printf("Issuing power-switch via uC!\n"); + struct udevice *dev; printf("Issuing power-switch via uC!\n"); - i2c_set_bus_num(STM_I2C_BUS); + ret = i2c_get_chip_for_busnum(STM_I2C_BUS, STM_I2C_ADDR, + 1, &dev); + if (ret) { + printf("Error selecting STM on I2C bus (ret=%d)\n", + ret); + printf("Issuing soft-reset...\n"); + /* default handling: SOFT reset */ + do_reset(NULL, 0, 0, NULL); + } + i2c_buf[0] = STM_I2C_ADDR << 1; i2c_buf[1] = 0xc5; /* cmd */ i2c_buf[2] = 0x01; /* enable */ @@ -313,7 +322,7 @@ int board_late_init(void) i2c_buf[6] = 0x00; i2c_buf[7] = crc8(0x72, &i2c_buf[0], 7); - ret = i2c_write(STM_I2C_ADDR, 0, 0, &i2c_buf[1], 7); + ret = dm_i2c_write(dev, 0, &i2c_buf[1], 7); if (ret) { printf("I2C write error (ret=%d)\n", ret); printf("Issuing soft-reset...\n"); diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c index daae911..4ea5f9f 100644 --- a/cmd/tpm-v2.c +++ b/cmd/tpm-v2.c @@ -151,7 +151,8 @@ static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc, data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0); - rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, data, &updates); + rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, TPM2_ALG_SHA256, + data, TPM2_DIGEST_LEN, &updates); if (!rc) { printf("PCR #%u content (%u known updates):\n", index, updates); print_byte_string(data, TPM2_DIGEST_LEN); diff --git a/common/fdt_support.c b/common/fdt_support.c index 8992ac5..b2ba082 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -695,6 +695,29 @@ int fdt_shrink_to_minimum(void *blob, uint extrasize) return actualsize; } +/** + * fdt_delete_disabled_nodes: Delete all nodes with status == "disabled" + * + * @blob: ptr to device tree + */ +int fdt_delete_disabled_nodes(void *blob) +{ + while (1) { + int ret, offset; + + offset = fdt_node_offset_by_prop_value(blob, -1, "status", + "disabled", 9); + if (offset < 0) + break; + + ret = fdt_del_node(blob, offset); + if (ret < 0) + return ret; + } + + return 0; +} + #ifdef CONFIG_PCI #define CONFIG_SYS_PCI_NR_INBOUND_WIN 4 @@ -1463,22 +1486,35 @@ int fdt_node_offset_by_compat_reg(void *blob, const char *compat, return -FDT_ERR_NOTFOUND; } +static int vnode_offset_by_pathf(void *blob, const char *fmt, va_list ap) +{ + char path[512]; + int len; + + len = vsnprintf(path, sizeof(path), fmt, ap); + if (len < 0 || len + 1 > sizeof(path)) + return -FDT_ERR_NOSPACE; + + return fdt_path_offset(blob, path); +} + /** - * fdt_alloc_phandle: Return next free phandle value + * fdt_node_offset_by_pathf: Find node offset by sprintf formatted path * * @blob: ptr to device tree + * @fmt: path format + * @ap: vsnprintf arguments */ -int fdt_alloc_phandle(void *blob) +int fdt_node_offset_by_pathf(void *blob, const char *fmt, ...) { - int offset; - uint32_t phandle = 0; + va_list ap; + int res; - for (offset = fdt_next_node(blob, -1, NULL); offset >= 0; - offset = fdt_next_node(blob, offset, NULL)) { - phandle = max(phandle, fdt_get_phandle(blob, offset)); - } + va_start(ap, fmt); + res = vnode_offset_by_pathf(blob, fmt, ap); + va_end(ap); - return phandle + 1; + return res; } /* @@ -1522,7 +1558,7 @@ int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle) } /* - * fdt_create_phandle: Create a phandle property for the given node + * fdt_create_phandle: Get or create a phandle property for the given node * * @fdt: ptr to device tree * @nodeoffset: node to update @@ -1530,13 +1566,19 @@ int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle) unsigned int fdt_create_phandle(void *fdt, int nodeoffset) { /* see if there is a phandle already */ - int phandle = fdt_get_phandle(fdt, nodeoffset); + uint32_t phandle = fdt_get_phandle(fdt, nodeoffset); /* if we got 0, means no phandle so create one */ if (phandle == 0) { int ret; - phandle = fdt_alloc_phandle(fdt); + ret = fdt_generate_phandle(fdt, &phandle); + if (ret < 0) { + printf("Can't generate phandle: %s\n", + fdt_strerror(ret)); + return 0; + } + ret = fdt_set_phandle(fdt, nodeoffset, phandle); if (ret < 0) { printf("Can't set phandle %u: %s\n", phandle, @@ -1548,19 +1590,60 @@ unsigned int fdt_create_phandle(void *fdt, int nodeoffset) return phandle; } +/** + * fdt_create_phandle_by_compatible: Get or create a phandle for first node with + * given compatible + * + * @fdt: ptr to device tree + * @compat: node's compatible string + */ +unsigned int fdt_create_phandle_by_compatible(void *fdt, const char *compat) +{ + int offset = fdt_node_offset_by_compatible(fdt, -1, compat); + + if (offset < 0) { + printf("Can't find node with compatible \"%s\": %s\n", compat, + fdt_strerror(offset)); + return 0; + } + + return fdt_create_phandle(fdt, offset); +} + +/** + * fdt_create_phandle_by_pathf: Get or create a phandle for node given by + * sprintf-formatted path + * + * @fdt: ptr to device tree + * @fmt, ...: path format string and arguments to pass to sprintf + */ +unsigned int fdt_create_phandle_by_pathf(void *fdt, const char *fmt, ...) +{ + va_list ap; + int offset; + + va_start(ap, fmt); + offset = vnode_offset_by_pathf(fdt, fmt, ap); + va_end(ap); + + if (offset < 0) { + printf("Can't find node by given path: %s\n", + fdt_strerror(offset)); + return 0; + } + + return fdt_create_phandle(fdt, offset); +} + /* * fdt_set_node_status: Set status for the given node * * @fdt: ptr to device tree * @nodeoffset: node to update - * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, - * FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE - * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE + * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, FDT_STATUS_FAIL */ -int fdt_set_node_status(void *fdt, int nodeoffset, - enum fdt_status status, unsigned int error_code) +int fdt_set_node_status(void *fdt, int nodeoffset, enum fdt_status status) { - char buf[16]; int ret = 0; if (nodeoffset < 0) @@ -1576,10 +1659,6 @@ int fdt_set_node_status(void *fdt, int nodeoffset, case FDT_STATUS_FAIL: ret = fdt_setprop_string(fdt, nodeoffset, "status", "fail"); break; - case FDT_STATUS_FAIL_ERROR_CODE: - sprintf(buf, "fail-%d", error_code); - ret = fdt_setprop_string(fdt, nodeoffset, "status", buf); - break; default: printf("Invalid fdt status: %x\n", status); ret = -1; @@ -1594,16 +1673,57 @@ int fdt_set_node_status(void *fdt, int nodeoffset, * * @fdt: ptr to device tree * @alias: alias of node to update - * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, - * FDT_STATUS_FAIL, FDT_STATUS_FAIL_ERROR_CODE - * @error_code: optional, only used if status is FDT_STATUS_FAIL_ERROR_CODE + * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, FDT_STATUS_FAIL */ int fdt_set_status_by_alias(void *fdt, const char* alias, - enum fdt_status status, unsigned int error_code) + enum fdt_status status) { int offset = fdt_path_offset(fdt, alias); - return fdt_set_node_status(fdt, offset, status, error_code); + return fdt_set_node_status(fdt, offset, status); +} + +/** + * fdt_set_status_by_compatible: Set node status for first node with given + * compatible + * + * @fdt: ptr to device tree + * @compat: node's compatible string + * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, FDT_STATUS_FAIL + */ +int fdt_set_status_by_compatible(void *fdt, const char *compat, + enum fdt_status status) +{ + int offset = fdt_node_offset_by_compatible(fdt, -1, compat); + + if (offset < 0) + return offset; + + return fdt_set_node_status(fdt, offset, status); +} + +/** + * fdt_set_status_by_pathf: Set node status for node given by sprintf-formatted + * path + * + * @fdt: ptr to device tree + * @status: FDT_STATUS_OKAY, FDT_STATUS_DISABLED, FDT_STATUS_FAIL + * @fmt, ...: path format string and arguments to pass to sprintf + */ +int fdt_set_status_by_pathf(void *fdt, enum fdt_status status, const char *fmt, + ...) +{ + va_list ap; + int offset; + + va_start(ap, fmt); + offset = vnode_offset_by_pathf(fdt, fmt, ap); + va_end(ap); + + if (offset < 0) + return offset; + + return fdt_set_node_status(fdt, offset, status); } #if defined(CONFIG_VIDEO) || defined(CONFIG_LCD) diff --git a/configs/db-mv784mp-gp_defconfig b/configs/db-mv784mp-gp_defconfig index b82b637..6a11aa0 100644 --- a/configs/db-mv784mp-gp_defconfig +++ b/configs/db-mv784mp-gp_defconfig @@ -50,10 +50,8 @@ CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SPL_OF_TRANSLATE=y CONFIG_SATA_MV=y -CONFIG_SYS_I2C_LEGACY=y -CONFIG_SPL_SYS_I2C_LEGACY=y +CONFIG_DM_I2C=y CONFIG_SYS_I2C_MVTWSI=y -CONFIG_SYS_I2C_SLAVE=0x0 # CONFIG_MMC is not set CONFIG_MTD=y CONFIG_MTD_RAW_NAND=y diff --git a/configs/ds414_defconfig b/configs/ds414_defconfig index 773dbc1..5a7c958 100644 --- a/configs/ds414_defconfig +++ b/configs/ds414_defconfig @@ -55,10 +55,8 @@ CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SPL_OF_TRANSLATE=y -CONFIG_SYS_I2C_LEGACY=y -CONFIG_SPL_SYS_I2C_LEGACY=y +CONFIG_DM_I2C=y CONFIG_SYS_I2C_MVTWSI=y -CONFIG_SYS_I2C_SLAVE=0x0 # CONFIG_MMC is not set CONFIG_MTD=y CONFIG_SPI_FLASH_STMICRO=y diff --git a/configs/maxbcm_defconfig b/configs/maxbcm_defconfig index ce870c9..9fa2f51 100644 --- a/configs/maxbcm_defconfig +++ b/configs/maxbcm_defconfig @@ -37,10 +37,8 @@ CONFIG_USE_ENV_SPI_MAX_HZ=y CONFIG_ENV_SPI_MAX_HZ=50000000 CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SPL_OF_TRANSLATE=y -CONFIG_SYS_I2C_LEGACY=y -CONFIG_SPL_SYS_I2C_LEGACY=y +CONFIG_DM_I2C=y CONFIG_SYS_I2C_MVTWSI=y -CONFIG_SYS_I2C_SLAVE=0x0 # CONFIG_MMC is not set CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y diff --git a/configs/microchip_mpfs_icicle_defconfig b/configs/microchip_mpfs_icicle_defconfig index 54458b7..e51afc1 100644 --- a/configs/microchip_mpfs_icicle_defconfig +++ b/configs/microchip_mpfs_icicle_defconfig @@ -6,7 +6,6 @@ CONFIG_DEFAULT_DEVICE_TREE="microchip-mpfs-icicle-kit" CONFIG_TARGET_MICROCHIP_ICICLE=y CONFIG_ARCH_RV64I=y CONFIG_RISCV_SMODE=y -CONFIG_SBI_V01=y CONFIG_DISTRO_DEFAULTS=y CONFIG_SYS_LOAD_ADDR=0x80200000 CONFIG_FIT=y diff --git a/configs/qemu_arm64_defconfig b/configs/qemu_arm64_defconfig index 02a5e940..0ac3b47 100644 --- a/configs/qemu_arm64_defconfig +++ b/configs/qemu_arm64_defconfig @@ -26,6 +26,7 @@ CONFIG_CMD_DFU=y CONFIG_CMD_MTD=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y +CONFIG_CMD_TPM=y CONFIG_CMD_MTDPARTS=y CONFIG_OF_BOARD=y CONFIG_ENV_IS_IN_FLASH=y diff --git a/configs/qemu_arm_defconfig b/configs/qemu_arm_defconfig index d4f6d0b..8ce5540 100644 --- a/configs/qemu_arm_defconfig +++ b/configs/qemu_arm_defconfig @@ -28,6 +28,7 @@ CONFIG_CMD_DFU=y CONFIG_CMD_MTD=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y +CONFIG_CMD_TPM=y CONFIG_CMD_MTDPARTS=y CONFIG_OF_BOARD=y CONFIG_ENV_IS_IN_FLASH=y diff --git a/configs/rzg2_beacon_defconfig b/configs/rzg2_beacon_defconfig index 9b5f5bc..e1af7b4 100644 --- a/configs/rzg2_beacon_defconfig +++ b/configs/rzg2_beacon_defconfig @@ -41,7 +41,6 @@ CONFIG_MULTI_DTB_FIT_LZO=y CONFIG_MULTI_DTB_FIT_USER_DEFINED_AREA=y CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_MMC=y -CONFIG_SYS_MMC_ENV_DEV=1 CONFIG_SYS_MMC_ENV_PART=2 CONFIG_VERSION_VARIABLE=y CONFIG_REGMAP=y diff --git a/configs/sifive_unmatched_defconfig b/configs/sifive_unmatched_defconfig index 9cc18b0..d400ed0 100644 --- a/configs/sifive_unmatched_defconfig +++ b/configs/sifive_unmatched_defconfig @@ -8,6 +8,7 @@ CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="hifive-unmatched-a00" CONFIG_SPL_MMC=y CONFIG_SPL=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI=y CONFIG_AHCI=y CONFIG_TARGET_SIFIVE_UNMATCHED=y @@ -23,17 +24,22 @@ CONFIG_DISPLAY_BOARDINFO=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_ID_EEPROM=y CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_DM_RESET=y +CONFIG_SPL_SPI_LOAD=y CONFIG_CMD_EEPROM=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_PWM=y CONFIG_CMD_GPT_RENAME=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y +CONFIG_USE_ENV_SPI_BUS=y +CONFIG_ENV_SPI_BUS=1 CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_SCSI_AHCI=y CONFIG_AHCI_PCI=y CONFIG_SPL_CLK=y +CONFIG_SPI_FLASH_ISSI=y CONFIG_SYS_I2C_EEPROM_ADDR=0x54 CONFIG_E1000=y CONFIG_NVME=y diff --git a/configs/theadorable_debug_defconfig b/configs/theadorable_debug_defconfig index 556c91f..cfa1bac 100644 --- a/configs/theadorable_debug_defconfig +++ b/configs/theadorable_debug_defconfig @@ -58,10 +58,8 @@ CONFIG_SATA_MV=y CONFIG_BOOTCOUNT_LIMIT=y CONFIG_BOOTCOUNT_RAM=y CONFIG_FPGA_ALTERA=y -CONFIG_SYS_I2C_LEGACY=y -CONFIG_SPL_SYS_I2C_LEGACY=y +CONFIG_DM_I2C=y CONFIG_SYS_I2C_MVTWSI=y -CONFIG_SYS_I2C_SLAVE=0x0 # CONFIG_MMC is not set CONFIG_SF_DEFAULT_SPEED=27777777 CONFIG_SPI_FLASH_MACRONIX=y diff --git a/disk/part.c b/disk/part.c index fe1ebd4..e857a9f 100644 --- a/disk/part.c +++ b/disk/part.c @@ -296,8 +296,11 @@ static void print_part_header(const char *type, struct blk_desc *dev_desc) case IF_TYPE_VIRTIO: puts("VirtIO"); break; + case IF_TYPE_EFI_MEDIA: + puts("EFI"); + break; default: - puts ("UNKNOWN"); + puts("UNKNOWN"); break; } printf (" device %d -- Partition Type: %s\n\n", diff --git a/doc/board/emulation/qemu-arm.rst b/doc/board/emulation/qemu-arm.rst index 584ef0a..7c24e29 100644 --- a/doc/board/emulation/qemu-arm.rst +++ b/doc/board/emulation/qemu-arm.rst @@ -65,7 +65,8 @@ can be enabled with the following command line parameters: - To add a Serial ATA disk via an Intel ICH9 AHCI controller, pass e.g.:: - -drive if=none,file=disk.img,id=mydisk -device ich9-ahci,id=ahci -device ide-drive,drive=mydisk,bus=ahci.0 + -drive if=none,file=disk.img,format=raw,id=mydisk \ + -device ich9-ahci,id=ahci -device ide-drive,drive=mydisk,bus=ahci.0 - To add an Intel E1000 network adapter, pass e.g.:: @@ -75,10 +76,14 @@ can be enabled with the following command line parameters: -device usb-ehci,id=ehci -- To add a NVMe disk, pass e.g.:: +- To add an NVMe disk, pass e.g.:: -drive if=none,file=disk.img,id=mydisk -device nvme,drive=mydisk,serial=foo +- To add a random number generator, pass e.g.:: + + -device virtio-rng-pci + These have been tested in QEMU 2.9.0 but should work in at least 2.5.0 as well. Enabling TPMv2 support diff --git a/doc/board/microchip/mpfs_icicle.rst b/doc/board/microchip/mpfs_icicle.rst index c71c2f3..a4b10c6 100644 --- a/doc/board/microchip/mpfs_icicle.rst +++ b/doc/board/microchip/mpfs_icicle.rst @@ -20,6 +20,7 @@ The support for following drivers are already enabled: 2. Microchip Clock Driver. 3. Cadence MACB ethernet driver for networking support. 4. Cadence MMC Driver for eMMC/SD support. +5. Microchip I2C Driver. Booting from eMMC using HSS --------------------------- @@ -214,7 +215,8 @@ GPT partition. Booting ~~~~~~~ -You should see the U-Boot prompt on UART0. +You should see the U-Boot prompt on UART1. +(Note: UART0 is reserved for HSS) Sample boot log from MPFS Icicle Kit '''''''''''''''''''''''''''''''''''' @@ -451,7 +453,8 @@ copied payload and Linux image. sudo dd if=<payload_binary> of=/dev/sdX2 bs=512 -You should see the U-Boot prompt on UART0. +You should see the U-Boot prompt on UART1. +(Note: UART0 is reserved for HSS) GUID type ~~~~~~~~~ diff --git a/doc/board/sifive/unmatched.rst b/doc/board/sifive/unmatched.rst index 6b024f0..b52a1f6 100644 --- a/doc/board/sifive/unmatched.rst +++ b/doc/board/sifive/unmatched.rst @@ -534,3 +534,34 @@ Sample boot log from HiFive Unmatched board OpenEmbedded nodistro.0 unmatched ttySIF0 unmatched login: + + +Booting from SPI +---------------- + +Use Building steps from "Booting from uSD using U-Boot SPL" section. + +Partition the SPI in Linux via mtdblock. The partition types here are +"HiFive Unleashed FSBL", "HiFive Unleashed BBL", and "U-Boot environment" +for partitions one through three respectively. + +.. code-block:: none + + sgdisk --clear -a 1 \ + --new=1:40:2087 --change-name=1:spl --typecode=1:5B193300-FC78-40CD-8002-E86C45580B47 \ + --new=2:2088:10279 --change-name=2:uboot --typecode=2:2E54B353-1271-4842-806F-E436D6AF6985 \ + --new=3:10280:10535 --change-name=3:env --typecode=3:3DE21764-95BD-54BD-A5C3-4ABE786F38A8 \ + /dev/mtdblock0 + +Write U-boot SPL and U-boot to their partitions. + +.. code-block:: none + + dd if=u-boot-spl.bin of=/dev/mtdblock0 bs=4096 seek=5 conv=sync + dd if=u-boot.itb of=/dev/mtdblock0 bs=4096 seek=261 conv=sync + +Power off the board. + +Change DIP switches MSEL[3:0] to 0110. + +Power up the board. diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index f17138f..a3e2656 100644 --- a/doc/develop/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -620,12 +620,12 @@ EFI_DRIVER_BINDING_PROTOCOL implementation for the UEFI drivers. A linker created list is used to keep track of the UEFI drivers. To create an entry in the list the UEFI driver uses the U_BOOT_DRIVER macro specifying -UCLASS_EFI as the ID of its uclass, e.g:: +UCLASS_EFI_LOADER as the ID of its uclass, e.g:: /* Identify as UEFI driver */ U_BOOT_DRIVER(efi_block) = { .name = "EFI block driver", - .id = UCLASS_EFI, + .id = UCLASS_EFI_LOADER, .ops = &driver_ops, }; @@ -651,8 +651,8 @@ UEFI block IO driver The UEFI block IO driver supports devices exposing the EFI_BLOCK_IO_PROTOCOL. When connected it creates a new U-Boot block IO device with interface type -IF_TYPE_EFI, adds child controllers mapping the partitions, and installs the -EFI_SIMPLE_FILE_SYSTEM_PROTOCOL on these. This can be used together with the +IF_TYPE_EFI_LOADER, adds child controllers mapping the partitions, and installs +the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL on these. This can be used together with the software iPXE to boot from iSCSI network drives [4]. This driver is only available if U-Boot is configured with:: diff --git a/doc/usage/fdt_overlays.rst b/doc/usage/fdt_overlays.rst index ea39713..7f113ed 100644 --- a/doc/usage/fdt_overlays.rst +++ b/doc/usage/fdt_overlays.rst @@ -102,7 +102,7 @@ Manually Loading and Applying Overlays :: - => fdtaddr $fdtaddr + => fdt addr $fdtaddr 4. Grow it enough so it can encompass all applied overlays diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 56a4eec..8235430 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -61,6 +61,39 @@ config TPL_BLOCK_CACHE help This option enables the disk-block cache in TPL +config EFI_MEDIA + bool "Support EFI media drivers" + default y if EFI || SANDBOX + help + Enable this to support media devices on top of UEFI. This enables + just the uclass so you also need a specific driver to make this do + anything. + + For sandbox there is a test driver. + +if EFI_MEDIA + +config EFI_MEDIA_SANDBOX + bool "Sandbox EFI media driver" + depends on SANDBOX + default y + help + Enables a simple sandbox media driver, used for testing just the + EFI_MEDIA uclass. It does not do anything useful, since sandbox does + not actually support running on top of UEFI. + +config EFI_MEDIA_BLK + bool "EFI media block driver" + depends on EFI_APP + default y + help + Enables a block driver for providing access to UEFI devices. This + allows use of block devices detected by the underlying UEFI + implementation. With this it is possible to use filesystems on these + devices, for example. + +endif # EFI_MEDIA + config IDE bool "Support IDE controllers" select HAVE_BLOCK_DEVICE diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 94ab5c6..b221a7c 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -14,3 +14,7 @@ obj-$(CONFIG_IDE) += ide.o endif obj-$(CONFIG_SANDBOX) += sandbox.o obj-$(CONFIG_$(SPL_TPL_)BLOCK_CACHE) += blkcache.o + +obj-$(CONFIG_EFI_MEDIA) += efi-media-uclass.o +obj-$(CONFIG_EFI_MEDIA_SANDBOX) += sb_efi_media.o +obj-$(CONFIG_EFI_MEDIA_BLK) += efi_blk.o diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 83682dc..4ae8af6 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -28,7 +28,8 @@ static const char *if_typename_str[IF_TYPE_COUNT] = { [IF_TYPE_SATA] = "sata", [IF_TYPE_HOST] = "host", [IF_TYPE_NVME] = "nvme", - [IF_TYPE_EFI] = "efi", + [IF_TYPE_EFI_MEDIA] = "efi", + [IF_TYPE_EFI_LOADER] = "efiloader", [IF_TYPE_VIRTIO] = "virtio", [IF_TYPE_PVBLOCK] = "pvblock", }; @@ -44,7 +45,8 @@ static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { [IF_TYPE_SATA] = UCLASS_AHCI, [IF_TYPE_HOST] = UCLASS_ROOT, [IF_TYPE_NVME] = UCLASS_NVME, - [IF_TYPE_EFI] = UCLASS_EFI, + [IF_TYPE_EFI_MEDIA] = UCLASS_EFI_MEDIA, + [IF_TYPE_EFI_LOADER] = UCLASS_EFI_LOADER, [IF_TYPE_VIRTIO] = UCLASS_VIRTIO, [IF_TYPE_PVBLOCK] = UCLASS_PVBLOCK, }; diff --git a/drivers/block/efi-media-uclass.c b/drivers/block/efi-media-uclass.c new file mode 100644 index 0000000..e012f6f --- /dev/null +++ b/drivers/block/efi-media-uclass.c @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Uclass for EFI media devices + * + * Copyright 2021 Google LLC + */ + +#include <common.h> +#include <dm.h> + +UCLASS_DRIVER(efi_media) = { + .id = UCLASS_EFI_MEDIA, + .name = "efi_media", + .flags = DM_UC_FLAG_SEQ_ALIAS, +}; diff --git a/drivers/block/efi_blk.c b/drivers/block/efi_blk.c new file mode 100644 index 0000000..9d25ecb --- /dev/null +++ b/drivers/block/efi_blk.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Block driver for EFI devices + * This supports a media driver of UCLASS_EFI with a child UCLASS_BLK + * It allows block-level access to EFI devices made available via EFI boot + * services + * + * Copyright 2021 Google LLC + */ + +#include <common.h> +#include <blk.h> +#include <dm.h> +#include <efi.h> +#include <efi_api.h> + +struct efi_block_plat { + struct efi_block_io *blkio; +}; + +/** + * Read from block device + * + * @dev: device + * @blknr: first block to be read + * @blkcnt: number of blocks to read + * @buffer: output buffer + * Return: number of blocks transferred + */ +static ulong efi_bl_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + struct efi_block_plat *plat = dev_get_plat(dev); + struct efi_block_io *io = plat->blkio; + efi_status_t ret; + + log_debug("read buf=%p, block=%lx, count=%lx: ", buffer, (ulong)blknr, + (ulong)blkcnt); + ret = io->read_blocks(io, io->media->media_id, blknr, + blkcnt * io->media->block_size, buffer); + log_debug("ret=%lx (dec %ld)\n", ret & ~EFI_ERROR_MASK, + ret & ~EFI_ERROR_MASK); + if (ret) + return 0; + + return blkcnt; +} + +/** + * Write to block device + * + * @dev: device + * @blknr: first block to be write + * @blkcnt: number of blocks to write + * @buffer: input buffer + * Return: number of blocks transferred + */ +static ulong efi_bl_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +{ + struct efi_block_plat *plat = dev_get_plat(dev); + struct efi_block_io *io = plat->blkio; + efi_status_t ret; + + log_debug("write buf=%p, block=%lx, count=%lx: ", buffer, (ulong)blknr, + (ulong)blkcnt); + ret = io->write_blocks(io, io->media->media_id, blknr, + blkcnt * io->media->block_size, (void *)buffer); + log_debug("ret=%lx (dec %ld)\n", ret & ~EFI_ERROR_MASK, + ret & ~EFI_ERROR_MASK); + if (ret) + return 0; + + return blkcnt; +} + +/* Block device driver operators */ +static const struct blk_ops efi_blk_ops = { + .read = efi_bl_read, + .write = efi_bl_write, +}; + +U_BOOT_DRIVER(efi_block) = { + .name = "efi_block", + .id = UCLASS_BLK, + .ops = &efi_blk_ops, + .plat_auto = sizeof(struct efi_block_plat), +}; + +static int efi_media_bind(struct udevice *dev) +{ + struct efi_media_plat *plat = dev_get_plat(dev); + struct efi_block_plat *blk_plat; + struct udevice *blk; + int ret; + + ret = blk_create_devicef(dev, "efi_block", "blk", IF_TYPE_EFI_MEDIA, + dev_seq(dev), plat->blkio->media->block_size, + plat->blkio->media->last_block, &blk); + if (ret) { + debug("Cannot create block device\n"); + return ret; + } + blk_plat = dev_get_plat(blk); + blk_plat->blkio = plat->blkio; + + return 0; +} + +U_BOOT_DRIVER(efi_media) = { + .name = "efi_media", + .id = UCLASS_EFI_MEDIA, + .bind = efi_media_bind, + .plat_auto = sizeof(struct efi_media_plat), +}; diff --git a/drivers/block/sb_efi_media.c b/drivers/block/sb_efi_media.c new file mode 100644 index 0000000..52af155 --- /dev/null +++ b/drivers/block/sb_efi_media.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * EFI_MEDIA driver for sandbox + * + * Copyright 2021 Google LLC + */ + +#include <common.h> +#include <dm.h> + +static const struct udevice_id sandbox_efi_media_ids[] = { + { .compatible = "sandbox,efi-media" }, + { } +}; + +U_BOOT_DRIVER(sandbox_efi_media) = { + .name = "sandbox_efi_media", + .id = UCLASS_EFI_MEDIA, + .of_match = sandbox_efi_media_ids, +}; diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index bb5351e..6eb2b81 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -4,14 +4,17 @@ * Copyright 2019 NXP */ +#define LOG_CATEGORY UCLASS_CLK + #include <common.h> -#include <asm/io.h> -#include <malloc.h> +#include <clk.h> #include <clk-uclass.h> +#include <log.h> +#include <malloc.h> +#include <asm/io.h> #include <dm/device.h> #include <dm/devres.h> #include <linux/clk-provider.h> -#include <clk.h> #include <linux/err.h> #include "clk.h" diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 9df50a5..7e8e62f 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -9,14 +9,18 @@ * */ +#define LOG_CATEGORY UCLASS_CLK + #include <common.h> #include <asm/io.h> #include <malloc.h> #include <clk-uclass.h> +#include <log.h> #include <dm/device.h> #include <dm/devres.h> #include <dm/uclass.h> #include <dm/lists.h> +#include <dm/device_compat.h> #include <dm/device-internal.h> #include <linux/bug.h> #include <linux/clk-provider.h> @@ -190,7 +194,7 @@ static struct clk *_register_divider(struct device *dev, const char *name, if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { if (width + shift > 16) { - pr_warn("divider value exceeds LOWORD field\n"); + dev_warn(dev, "divider value exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); } } diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 8d9823b..2a44678 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -5,17 +5,22 @@ * * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> */ + +#define LOG_CATEGORY UCLASS_CLK + #include <common.h> -#include <malloc.h> +#include <clk.h> #include <clk-uclass.h> +#include <div64.h> +#include <log.h> +#include <malloc.h> #include <dm/device.h> #include <dm/devres.h> #include <linux/clk-provider.h> -#include <div64.h> -#include <clk.h> -#include "clk.h" #include <linux/err.h> +#include "clk.h" + #define UBOOT_DM_CLK_IMX_FIXED_FACTOR "ccf_clk_fixed_factor" static ulong clk_factor_recalc_rate(struct clk *clk) diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index 006d3b6..aa40daf 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -7,18 +7,23 @@ * Gated clock implementation */ +#define LOG_CATEGORY UCLASS_CLK + #include <common.h> -#include <asm/io.h> -#include <malloc.h> +#include <clk.h> +#include <log.h> #include <clk-uclass.h> +#include <malloc.h> +#include <asm/io.h> #include <dm/device.h> +#include <dm/device_compat.h> #include <dm/devres.h> #include <linux/bitops.h> #include <linux/clk-provider.h> -#include <clk.h> -#include "clk.h" #include <linux/err.h> +#include "clk.h" + #define UBOOT_DM_CLK_GATE "clk_gate" /** @@ -123,7 +128,7 @@ struct clk *clk_register_gate(struct device *dev, const char *name, if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { if (bit_idx > 15) { - pr_err("gate bit exceeds LOWORD field\n"); + dev_err(dev, "gate bit exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); } } diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index f1becd2..b49946f 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -21,17 +21,22 @@ * clock. */ +#define LOG_CATEGORY UCLASS_CLK + #include <common.h> #include <clk.h> #include <clk-uclass.h> +#include <log.h> +#include <malloc.h> +#include <asm/io.h> #include <dm/device.h> +#include <dm/device_compat.h> #include <dm/devres.h> #include <dm/uclass.h> #include <linux/bitops.h> -#include <malloc.h> -#include <asm/io.h> #include <linux/clk-provider.h> #include <linux/err.h> + #include "clk.h" #define UBOOT_DM_CLK_CCF_MUX "ccf_clk_mux" @@ -123,7 +128,7 @@ static int clk_mux_set_parent(struct clk *clk, struct clk *parent) index = clk_fetch_parent_index(clk, parent); if (index < 0) { - printf("Could not fetch index\n"); + log_err("Could not fetch index\n"); return index; } @@ -169,7 +174,7 @@ struct clk *clk_hw_register_mux_table(struct device *dev, const char *name, if (clk_mux_flags & CLK_MUX_HIWORD_MASK) { width = fls(mask) - ffs(mask) + 1; if (width + shift > 16) { - pr_err("mux value exceeds LOWORD field\n"); + dev_err(dev, "mux value exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); } } diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 493018b..f2d2642 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -16,6 +16,7 @@ #include <errno.h> #include <log.h> #include <malloc.h> +#include <asm/global_data.h> #include <dm/device_compat.h> #include <dm/device-internal.h> #include <dm/devres.h> @@ -23,7 +24,6 @@ #include <linux/bug.h> #include <linux/clk-provider.h> #include <linux/err.h> -#include <asm/global_data.h> static inline const struct clk_ops *clk_dev_ops(struct udevice *dev) { diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 1efb7fe..eff0fa1 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4,14 +4,16 @@ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de */ +#define LOG_CATEGORY UCLASS_CLK + #include <common.h> +#include <clk.h> #include <clk-uclass.h> #include <log.h> #include <dm/device.h> #include <dm/uclass.h> #include <dm/lists.h> #include <dm/device-internal.h> -#include <clk.h> int clk_register(struct clk *clk, const char *drv_name, const char *name, const char *parent_name) @@ -22,24 +24,24 @@ int clk_register(struct clk *clk, const char *drv_name, ret = uclass_get_device_by_name(UCLASS_CLK, parent_name, &parent); if (ret) { - printf("%s: failed to get %s device (parent of %s)\n", - __func__, parent_name, name); + log_err("%s: failed to get %s device (parent of %s)\n", + __func__, parent_name, name); } else { - debug("%s: name: %s parent: %s [0x%p]\n", __func__, name, - parent->name, parent); + log_debug("%s: name: %s parent: %s [0x%p]\n", __func__, name, + parent->name, parent); } drv = lists_driver_lookup_name(drv_name); if (!drv) { - printf("%s: %s is not a valid driver name\n", - __func__, drv_name); + log_err("%s: %s is not a valid driver name\n", + __func__, drv_name); return -ENOENT; } ret = device_bind(parent, drv, name, NULL, ofnode_null(), &clk->dev); if (ret) { - printf("%s: CLK: %s driver bind error [%d]!\n", __func__, name, - ret); + log_err("%s: CLK: %s driver bind error [%d]!\n", __func__, name, + ret); return ret; } diff --git a/drivers/clk/clk_fixed_factor.c b/drivers/clk/clk_fixed_factor.c index 41b0d9c..6c1139e 100644 --- a/drivers/clk/clk_fixed_factor.c +++ b/drivers/clk/clk_fixed_factor.c @@ -5,10 +5,13 @@ * Author: Anup Patel <anup.patel@wdc.com> */ +#define LOG_CATEGORY UCLASS_CLK + #include <common.h> #include <clk-uclass.h> #include <div64.h> #include <dm.h> +#include <log.h> #include <linux/err.h> struct clk_fixed_factor { diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c index c5a2a42..b5e78c7 100644 --- a/drivers/clk/clk_fixed_rate.c +++ b/drivers/clk/clk_fixed_rate.c @@ -3,9 +3,12 @@ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> */ +#define LOG_CATEGORY UCLASS_CLK + #include <common.h> #include <clk-uclass.h> #include <dm.h> +#include <log.h> #include <dm/device-internal.h> #include <linux/clk-provider.h> diff --git a/drivers/ddr/marvell/axp/ddr3_hw_training.h b/drivers/ddr/marvell/axp/ddr3_hw_training.h index 30daaa9..fcdef79 100644 --- a/drivers/ddr/marvell/axp/ddr3_hw_training.h +++ b/drivers/ddr/marvell/axp/ddr3_hw_training.h @@ -373,7 +373,6 @@ int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info); void ddr3_static_training_init(void); -u8 ddr3_get_eprom_fabric(void); void ddr3_set_performance_params(MV_DRAM_INFO *dram_info); int ddr3_dram_sram_burst(u32 src, u32 dst, u32 len); void ddr3_save_training(MV_DRAM_INFO *dram_info); diff --git a/drivers/ddr/marvell/axp/ddr3_init.c b/drivers/ddr/marvell/axp/ddr3_init.c index 607f3e1..a9dcb74 100644 --- a/drivers/ddr/marvell/axp/ddr3_init.c +++ b/drivers/ddr/marvell/axp/ddr3_init.c @@ -361,12 +361,18 @@ static u32 ddr3_init_main(void) __maybe_unused u32 ddr_width = BUS_WIDTH; __maybe_unused int status; __maybe_unused u32 win_backup[16]; + __maybe_unused struct udevice *udev; + __maybe_unused int ret; /* SoC/Board special Initializtions */ fab_opt = ddr3_get_fab_opt(); #ifdef CONFIG_SPD_EEPROM - i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + ret = i2c_get_chip_for_busnum(0, BUS_WIDTH_ECC_TWSI_ADDR, 1, &udev); + if (ret) { + printf("Cannot find SPD EEPROM\n"); + return MV_DDR3_TRAINING_ERR_BAD_DIMM_SETUP; + } #endif ddr3_print_version(); @@ -438,7 +444,7 @@ static u32 ddr3_init_main(void) #if defined(ECC_SUPPORT) && defined(AUTO_DETECTION_SUPPORT) ecc = 0; - if (ddr3_check_config(BUS_WIDTH_ECC_TWSI_ADDR, CONFIG_ECC)) + if (ddr3_check_config(udev, CONFIG_ECC)) ecc = 1; #endif @@ -483,7 +489,7 @@ static u32 ddr3_init_main(void) * Dynamically Set 32Bit and ECC for AXP (Relevant only for * Marvell DB boards) */ - if (ddr3_check_config(BUS_WIDTH_ECC_TWSI_ADDR, CONFIG_BUS_WIDTH)) { + if (ddr3_check_config(udev, CONFIG_BUS_WIDTH)) { ddr_width = 32; DEBUG_INIT_S("DDR3 Training Sequence - DRAM bus width 32Bit\n"); } @@ -904,7 +910,7 @@ void ddr3_static_mc_init(void) * Notes: Only Available for ArmadaXP/Armada 370 DB boards * Returns: None. */ -int ddr3_check_config(u32 twsi_addr, MV_CONFIG_TYPE config_type) +int ddr3_check_config(struct udevice *udev, MV_CONFIG_TYPE config_type) { #ifdef AUTO_DETECTION_SUPPORT u8 data = 0; @@ -916,7 +922,7 @@ int ddr3_check_config(u32 twsi_addr, MV_CONFIG_TYPE config_type) else offset = 0; - ret = i2c_read(twsi_addr, offset, 1, (u8 *)&data, 1); + ret = dm_i2c_read(udev, offset, &data, 1); if (!ret) { switch (config_type) { case CONFIG_ECC: @@ -943,30 +949,6 @@ int ddr3_check_config(u32 twsi_addr, MV_CONFIG_TYPE config_type) return 0; } -#if defined(DB_88F78X60_REV2) -/* - * Name: ddr3_get_eprom_fabric - Get Fabric configuration from EPROM - * Desc: - * Args: twsi Address - * Notes: Only Available for ArmadaXP DB Rev2 boards - * Returns: None. - */ -u8 ddr3_get_eprom_fabric(void) -{ -#ifdef AUTO_DETECTION_SUPPORT - u8 data = 0; - int ret; - - ret = i2c_read(NEW_FABRIC_TWSI_ADDR, 1, 1, (u8 *)&data, 1); - if (!ret) - return data & 0x1F; -#endif - - return 0; -} - -#endif - /* * Name: ddr3_cl_to_valid_cl - this return register matching CL value * Desc: diff --git a/drivers/ddr/marvell/axp/ddr3_init.h b/drivers/ddr/marvell/axp/ddr3_init.h index 569a14b..a26bd2a 100644 --- a/drivers/ddr/marvell/axp/ddr3_init.h +++ b/drivers/ddr/marvell/axp/ddr3_init.h @@ -98,11 +98,10 @@ int ddr3_hw_training(u32 target_freq, u32 ddr_width, void ddr3_print_version(void); void fix_pll_val(u8 target_fab); -u8 ddr3_get_eprom_fabric(void); u32 ddr3_get_fab_opt(void); u32 ddr3_get_cpu_freq(void); u32 ddr3_get_vco_freq(void); -int ddr3_check_config(u32 addr, MV_CONFIG_TYPE config_type); +int ddr3_check_config(struct udevice *udev, MV_CONFIG_TYPE config_type); u32 ddr3_get_static_mc_value(u32 reg_addr, u32 offset1, u32 mask1, u32 offset2, u32 mask2); u32 ddr3_cl_to_valid_cl(u32 cl); diff --git a/drivers/ddr/marvell/axp/ddr3_spd.c b/drivers/ddr/marvell/axp/ddr3_spd.c index dd772e6..4763403 100644 --- a/drivers/ddr/marvell/axp/ddr3_spd.c +++ b/drivers/ddr/marvell/axp/ddr3_spd.c @@ -209,13 +209,19 @@ static u32 ddr3_get_dimm_num(u32 *dimm_addr) /* Read the dimm eeprom */ for (dimm_cur_addr = MAX_DIMM_ADDR; dimm_cur_addr > MIN_DIMM_ADDR; dimm_cur_addr--) { + struct udevice *udev; + data[SPD_DEV_TYPE_BYTE] = 0; /* Far-End DIMM must be connected */ if ((dimm_num == 0) && (dimm_cur_addr < FAR_END_DIMM_ADDR)) return 0; - ret = i2c_read(dimm_cur_addr, 0, 1, (uchar *)data, 3); + ret = i2c_get_chip_for_busnum(0, dimm_cur_addr, 1, &udev); + if (ret) + continue; + + ret = dm_i2c_read(udev, 0, data, 3); if (!ret) { if (data[SPD_DEV_TYPE_BYTE] == SPD_MEM_TYPE_DDR3) { dimm_addr[dimm_num] = dimm_cur_addr; @@ -245,9 +251,15 @@ int ddr3_spd_init(MV_DIMM_INFO *info, u32 dimm_addr, u32 dimm_width) __maybe_unused u8 vendor_high, vendor_low; if (dimm_addr != 0) { + struct udevice *udev; + memset(spd_data, 0, SPD_SIZE * sizeof(u8)); - ret = i2c_read(dimm_addr, 0, 1, (uchar *)spd_data, SPD_SIZE); + ret = i2c_get_chip_for_busnum(0, dimm_addr, 1, &udev); + if (ret) + return MV_DDR3_TRAINING_ERR_TWSI_FAIL; + + ret = dm_i2c_read(udev, 0, spd_data, SPD_SIZE); if (ret) return MV_DDR3_TRAINING_ERR_TWSI_FAIL; } diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index b992e6f..798e3a3 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -604,7 +604,8 @@ static int first_loading_rbf_to_buffer(struct udevice *dev, if (strstr(uname, "fpga-periph") && (!is_fpgamgr_early_user_mode() || - is_fpgamgr_user_mode())) { + is_fpgamgr_user_mode() || + is_periph_program_force())) { fpga_node_name = uname; printf("FPGA: Start to program "); printf("peripheral/full bitstream ...\n"); diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 7c447a8..5482a4a 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -250,6 +250,12 @@ config SYS_I2C_MESON internal buffer holding up to 8 bytes for transfers and supports both 7-bit and 10-bit addresses. +config SYS_I2C_MICROCHIP + bool "Microchip I2C driver" + help + Add support for the Microchip I2C driver. This is operating on + standard mode up to 100 kbits/s and fast mode up to 400 kbits/s. + config SYS_I2C_MXC bool "NXP MXC I2C driver" help diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index fca6b15..9d41f37 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_SYS_I2C_IPROC) += iproc_i2c.o obj-$(CONFIG_SYS_I2C_KONA) += kona_i2c.o obj-$(CONFIG_SYS_I2C_LPC32XX) += lpc32xx_i2c.o obj-$(CONFIG_SYS_I2C_MESON) += meson_i2c.o +obj-$(CONFIG_SYS_I2C_MICROCHIP) += i2c-microchip.o obj-$(CONFIG_SYS_I2C_MV) += mv_i2c.o obj-$(CONFIG_SYS_I2C_MVTWSI) += mvtwsi.o obj-$(CONFIG_SYS_I2C_MXC) += mxc_i2c.o diff --git a/drivers/i2c/i2c-microchip.c b/drivers/i2c/i2c-microchip.c new file mode 100644 index 0000000..12f65d0 --- /dev/null +++ b/drivers/i2c/i2c-microchip.c @@ -0,0 +1,482 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Microchip I2C controller driver + * + * Copyright (C) 2021 Microchip Technology Inc. + * Padmarao Begari <padmarao.begari@microchip.com> + */ +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <i2c.h> +#include <asm/io.h> +#include <dm/device_compat.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/err.h> + +#define MICROCHIP_I2C_TIMEOUT (1000 * 60) + +#define MPFS_I2C_CTRL (0x00) +#define CTRL_CR0 (0x00) +#define CTRL_CR1 (0x01) +#define CTRL_AA BIT(2) +#define CTRL_SI BIT(3) +#define CTRL_STO BIT(4) +#define CTRL_STA BIT(5) +#define CTRL_ENS1 BIT(6) +#define CTRL_CR2 (0x07) +#define MPFS_I2C_STATUS (0x04) +#define STATUS_BUS_ERROR (0x00) +#define STATUS_M_START_SENT (0x08) +#define STATUS_M_REPEATED_START_SENT (0x10) +#define STATUS_M_SLAW_ACK (0x18) +#define STATUS_M_SLAW_NACK (0x20) +#define STATUS_M_TX_DATA_ACK (0x28) +#define STATUS_M_TX_DATA_NACK (0x30) +#define STATUS_M_ARB_LOST (0x38) +#define STATUS_M_SLAR_ACK (0x40) +#define STATUS_M_SLAR_NACK (0x48) +#define STATUS_M_RX_DATA_ACKED (0x50) +#define STATUS_M_RX_DATA_NACKED (0x58) +#define STATUS_S_SLAW_ACKED (0x60) +#define STATUS_S_ARB_LOST_SLAW_ACKED (0x68) +#define STATUS_S_GENERAL_CALL_ACKED (0x70) +#define STATUS_S_ARB_LOST_GENERAL_CALL_ACKED (0x78) +#define STATUS_S_RX_DATA_ACKED (0x80) +#define STATUS_S_RX_DATA_NACKED (0x88) +#define STATUS_S_GENERAL_CALL_RX_DATA_ACKED (0x90) +#define STATUS_S_GENERAL_CALL_RX_DATA_NACKED (0x98) +#define STATUS_S_RX_STOP (0xA0) +#define STATUS_S_SLAR_ACKED (0xA8) +#define STATUS_S_ARB_LOST_SLAR_ACKED (0xB0) +#define STATUS_S_TX_DATA_ACK (0xb8) +#define STATUS_S_TX_DATA_NACK (0xC0) +#define STATUS_LAST_DATA_ACK (0xC8) +#define STATUS_M_SMB_MASTER_RESET (0xD0) +#define STATUS_S_SCL_LOW_TIMEOUT (0xD8) +#define STATUS_NO_STATE_INFO (0xF8) +#define MPFS_I2C_DATA (0x08) +#define MPFS_I2C_SLAVE0_ADDR (0x0c) +#define MPFS_I2C_SMBUS (0x10) +#define MPFS_I2C_FREQ (0x14) +#define MPFS_I2C_GLITCHREG (0x18) +#define MPFS_I2C_SLAVE1_ADDR (0x1c) + +#define PCLK_DIV_256 ((0 << CTRL_CR0) | (0 << CTRL_CR1) | (0 << CTRL_CR2)) +#define PCLK_DIV_224 ((1 << CTRL_CR0) | (0 << CTRL_CR1) | (0 << CTRL_CR2)) +#define PCLK_DIV_192 ((0 << CTRL_CR0) | (1 << CTRL_CR1) | (0 << CTRL_CR2)) +#define PCLK_DIV_160 ((1 << CTRL_CR0) | (1 << CTRL_CR1) | (0 << CTRL_CR2)) +#define PCLK_DIV_960 ((0 << CTRL_CR0) | (0 << CTRL_CR1) | (1 << CTRL_CR2)) +#define PCLK_DIV_120 ((1 << CTRL_CR0) | (0 << CTRL_CR1) | (1 << CTRL_CR2)) +#define PCLK_DIV_60 ((0 << CTRL_CR0) | (1 << CTRL_CR1) | (1 << CTRL_CR2)) +#define BCLK_DIV_8 ((1 << CTRL_CR0) | (1 << CTRL_CR1) | (1 << CTRL_CR2)) +#define CLK_MASK ((1 << CTRL_CR0) | (1 << CTRL_CR1) | (1 << CTRL_CR2)) + +/* + * mpfs_i2c_bus - I2C bus context + * @base: pointer to register struct + * @msg_len: number of bytes transferred in msg + * @msg_err: error code for completed message + * @i2c_clk: clock reference for i2c input clock + * @clk_rate: current i2c bus clock rate + * @buf: ptr to msg buffer for easier use. + * @addr: i2c address. + * @isr_status: cached copy of local ISR status. + */ +struct mpfs_i2c_bus { + void __iomem *base; + size_t msg_len; + int msg_err; + struct clk i2c_clk; + u32 clk_rate; + u8 *buf; + u8 addr; + u32 isr_status; +}; + +static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg) +{ + return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0); +} + +static void mpfs_i2c_int_clear(struct mpfs_i2c_bus *bus) +{ + u8 ctrl = readl(bus->base + MPFS_I2C_CTRL); + + ctrl &= ~CTRL_SI; + writel(ctrl, bus->base + MPFS_I2C_CTRL); +} + +static void mpfs_i2c_core_disable(struct mpfs_i2c_bus *bus) +{ + u8 ctrl = readl(bus->base + MPFS_I2C_CTRL); + + ctrl &= ~CTRL_ENS1; + writel(ctrl, bus->base + MPFS_I2C_CTRL); +} + +static void mpfs_i2c_core_enable(struct mpfs_i2c_bus *bus) +{ + u8 ctrl = readl(bus->base + MPFS_I2C_CTRL); + + ctrl |= CTRL_ENS1; + writel(ctrl, bus->base + MPFS_I2C_CTRL); +} + +static void mpfs_i2c_reset(struct mpfs_i2c_bus *bus) +{ + mpfs_i2c_core_disable(bus); + mpfs_i2c_core_enable(bus); +} + +static inline void mpfs_i2c_stop(struct mpfs_i2c_bus *bus) +{ + u8 ctrl = readl(bus->base + MPFS_I2C_CTRL); + + ctrl |= CTRL_STO; + writel(ctrl, bus->base + MPFS_I2C_CTRL); +} + +static inline int mpfs_generate_divisor(u32 rate, u8 *code) +{ + int ret = 0; + + if (rate >= 960) + *code = PCLK_DIV_960; + else if (rate >= 256) + *code = PCLK_DIV_256; + else if (rate >= 224) + *code = PCLK_DIV_224; + else if (rate >= 192) + *code = PCLK_DIV_192; + else if (rate >= 160) + *code = PCLK_DIV_160; + else if (rate >= 120) + *code = PCLK_DIV_120; + else if (rate >= 60) + *code = PCLK_DIV_60; + else if (rate >= 8) + *code = BCLK_DIV_8; + else + ret = -EINVAL; + + return ret; +} + +static int mpfs_i2c_init(struct mpfs_i2c_bus *bus, struct udevice *dev) +{ + u32 clk_rate, divisor; + u8 clkval, ctrl; + int ret; + + ret = clk_get_by_index(dev, 0, &bus->i2c_clk); + if (ret) + return -EINVAL; + + ret = clk_enable(&bus->i2c_clk); + if (ret) + return ret; + + clk_rate = clk_get_rate(&bus->i2c_clk); + if (!clk_rate) + return -EINVAL; + + clk_free(&bus->i2c_clk); + + divisor = clk_rate / bus->clk_rate; + + ctrl = readl(bus->base + MPFS_I2C_CTRL); + + ctrl &= ~CLK_MASK; + + ret = mpfs_generate_divisor(divisor, &clkval); + if (ret) + return -EINVAL; + + ctrl |= clkval; + + writel(ctrl, bus->base + MPFS_I2C_CTRL); + + ctrl = readl(bus->base + MPFS_I2C_CTRL); + + /* Reset I2C core */ + mpfs_i2c_reset(bus); + + return 0; +} + +static void mpfs_i2c_transfer(struct mpfs_i2c_bus *bus, u32 data) +{ + if (bus->msg_len > 0) + writel(data, bus->base + MPFS_I2C_DATA); +} + +static void mpfs_i2c_empty_rx(struct mpfs_i2c_bus *bus) +{ + u8 ctrl; + u8 data_read; + + if (bus->msg_len > 0) { + data_read = readl(bus->base + MPFS_I2C_DATA); + *bus->buf++ = data_read; + bus->msg_len--; + } + + if (bus->msg_len == 0) { + ctrl = readl(bus->base + MPFS_I2C_CTRL); + ctrl &= ~CTRL_AA; + writel(ctrl, bus->base + MPFS_I2C_CTRL); + } +} + +static int mpfs_i2c_fill_tx(struct mpfs_i2c_bus *bus) +{ + mpfs_i2c_transfer(bus, *bus->buf++); + bus->msg_len--; + + return 0; +} + +static int mpfs_i2c_service_handler(struct mpfs_i2c_bus *bus) +{ + bool finish = false; + u32 status; + u8 ctrl; + + status = bus->isr_status; + + switch (status) { + case STATUS_M_START_SENT: + case STATUS_M_REPEATED_START_SENT: + ctrl = readl(bus->base + MPFS_I2C_CTRL); + ctrl &= ~CTRL_STA; + writel(bus->addr, bus->base + MPFS_I2C_DATA); + writel(ctrl, bus->base + MPFS_I2C_CTRL); + break; + case STATUS_M_SLAW_ACK: + case STATUS_M_TX_DATA_ACK: + if (bus->msg_len > 0) { + mpfs_i2c_fill_tx(bus); + } else { + /* On the last byte to be transmitted, send STOP */ + mpfs_i2c_stop(bus); + finish = true; + } + break; + case STATUS_M_SLAR_ACK: + ctrl = readl(bus->base + MPFS_I2C_CTRL); + ctrl |= CTRL_AA; + writel(ctrl, bus->base + MPFS_I2C_CTRL); + if (bus->msg_len == 0) { + /* On the last byte to be transmitted, send STOP */ + mpfs_i2c_stop(bus); + finish = true; + } + break; + case STATUS_M_RX_DATA_ACKED: + mpfs_i2c_empty_rx(bus); + if (bus->msg_len == 0) { + /* On the last byte to be transmitted, send STOP */ + mpfs_i2c_stop(bus); + finish = true; + } + break; + case STATUS_M_TX_DATA_NACK: + case STATUS_M_RX_DATA_NACKED: + case STATUS_M_SLAR_NACK: + case STATUS_M_SLAW_NACK: + bus->msg_err = -ENXIO; + mpfs_i2c_stop(bus); + finish = true; + break; + + case STATUS_M_ARB_LOST: + /* Handle Lost Arbitration */ + bus->msg_err = -EAGAIN; + finish = true; + break; + default: + break; + } + + if (finish) { + ctrl = readl(bus->base + MPFS_I2C_CTRL); + ctrl &= ~CTRL_AA; + writel(ctrl, bus->base + MPFS_I2C_CTRL); + return 0; + } + + return 1; +} + +static int mpfs_i2c_service(struct mpfs_i2c_bus *bus) +{ + int ret = 0; + int si_bit; + + si_bit = readl(bus->base + MPFS_I2C_CTRL); + if (si_bit & CTRL_SI) { + bus->isr_status = readl(bus->base + MPFS_I2C_STATUS); + ret = mpfs_i2c_service_handler(bus); + } + /* Clear the si flag */ + mpfs_i2c_int_clear(bus); + si_bit = readl(bus->base + MPFS_I2C_CTRL); + + return ret; +} + +static int mpfs_i2c_check_service_change(struct mpfs_i2c_bus *bus) +{ + u8 ctrl; + u32 count = 0; + + while (1) { + ctrl = readl(bus->base + MPFS_I2C_CTRL); + if (ctrl & CTRL_SI) + break; + udelay(1); + count += 1; + if (count == MICROCHIP_I2C_TIMEOUT) + return -ETIMEDOUT; + } + return 0; +} + +static int mpfs_i2c_poll_device(struct mpfs_i2c_bus *bus) +{ + int ret; + + while (1) { + ret = mpfs_i2c_check_service_change(bus); + if (ret) + return ret; + + ret = mpfs_i2c_service(bus); + if (!ret) + /* all messages have been transferred */ + return ret; + } +} + +static int mpfs_i2c_xfer_msg(struct mpfs_i2c_bus *bus, struct i2c_msg *msg) +{ + u8 ctrl; + int ret; + + if (!msg->len || !msg->buf) + return -EINVAL; + + bus->addr = i2c_8bit_addr_from_msg(msg); + bus->msg_len = msg->len; + bus->buf = msg->buf; + bus->msg_err = 0; + + mpfs_i2c_core_enable(bus); + + ctrl = readl(bus->base + MPFS_I2C_CTRL); + + ctrl |= CTRL_STA; + + writel(ctrl, bus->base + MPFS_I2C_CTRL); + + ret = mpfs_i2c_poll_device(bus); + if (ret) + return ret; + + return bus->msg_err; +} + +static int mpfs_i2c_xfer(struct udevice *dev, struct i2c_msg *msgs, int num_msgs) +{ + struct mpfs_i2c_bus *bus = dev_get_priv(dev); + int idx, ret; + + if (!msgs || !num_msgs) + return -EINVAL; + + for (idx = 0; idx < num_msgs; idx++) { + ret = mpfs_i2c_xfer_msg(bus, msgs++); + if (ret) + return ret; + } + + return ret; +} + +static int mpfs_i2c_probe_chip(struct udevice *dev, uint addr, uint flags) +{ + struct mpfs_i2c_bus *bus = dev_get_priv(dev); + int ret; + u8 ctrl, reg = 0; + + /* + * Send the chip address and verify that the + * address was <ACK>ed. + */ + bus->addr = addr << 1 | I2C_M_RD; + bus->buf = ® + bus->msg_len = 0; + bus->msg_err = 0; + + mpfs_i2c_core_enable(bus); + + ctrl = readl(bus->base + MPFS_I2C_CTRL); + + ctrl |= CTRL_STA; + + writel(ctrl, bus->base + MPFS_I2C_CTRL); + + ret = mpfs_i2c_poll_device(bus); + if (ret) + return ret; + + return bus->msg_err; +} + +static int mpfs_i2c_probe(struct udevice *dev) +{ + int ret; + u32 val; + struct mpfs_i2c_bus *bus = dev_get_priv(dev); + + bus->base = dev_read_addr_ptr(dev); + if (!bus->base) + return -EINVAL; + + val = dev_read_u32(dev, "clock-frequency", &bus->clk_rate); + if (val) { + printf("Default to 100kHz\n"); + /* default clock rate */ + bus->clk_rate = 100000; + } + + if (bus->clk_rate > 400000 || bus->clk_rate <= 0) { + printf("Invalid clock-frequency %d\n", bus->clk_rate); + return -EINVAL; + } + + ret = mpfs_i2c_init(bus, dev); + + return ret; +} + +static const struct dm_i2c_ops mpfs_i2c_ops = { + .xfer = mpfs_i2c_xfer, + .probe_chip = mpfs_i2c_probe_chip, +}; + +static const struct udevice_id mpfs_i2c_ids[] = { + {.compatible = "microchip,mpfs-i2c"}, + {} +}; + +U_BOOT_DRIVER(mpfs_i2c) = { + .name = "mpfs_i2c", + .id = UCLASS_I2C, + .of_match = mpfs_i2c_ids, + .ops = &mpfs_i2c_ops, + .probe = mpfs_i2c_probe, + .priv_auto = sizeof(struct mpfs_i2c_bus), +}; diff --git a/drivers/misc/fsl_portals.c b/drivers/misc/fsl_portals.c index 632430e..02bc3f8 100644 --- a/drivers/misc/fsl_portals.c +++ b/drivers/misc/fsl_portals.c @@ -106,7 +106,7 @@ static int fdt_qportal(void *blob, int off, int id, char *name, enum fsl_dpaa_dev dev, int create) { int childoff, dev_off, ret = 0; - u32 dev_handle; + unsigned int dev_handle; #ifdef CONFIG_FSL_CORENET int num; u32 liodns[2]; @@ -142,11 +142,9 @@ static int fdt_qportal(void *blob, int off, int id, char *name, if (childoff > 0) { dev_handle = fdt_get_phandle(blob, dev_off); if (dev_handle <= 0) { - dev_handle = fdt_alloc_phandle(blob); - ret = fdt_set_phandle(blob, dev_off, - dev_handle); - if (ret < 0) - return ret; + dev_handle = fdt_create_phandle(blob, dev_off); + if (!dev_handle) + return -FDT_ERR_NOPHANDLES; } ret = fdt_setprop(blob, childoff, "dev-handle", diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 5851018..22dad5b 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1045,16 +1045,10 @@ static int eqos_start(struct udevice *dev) eqos->tx_desc_idx = 0; eqos->rx_desc_idx = 0; - ret = eqos->config->ops->eqos_start_clks(dev); - if (ret < 0) { - pr_err("eqos_start_clks() failed: %d", ret); - goto err; - } - ret = eqos->config->ops->eqos_start_resets(dev); if (ret < 0) { pr_err("eqos_start_resets() failed: %d", ret); - goto err_stop_clks; + goto err; } udelay(10); @@ -1360,8 +1354,6 @@ err_shutdown_phy: phy_shutdown(eqos->phy); err_stop_resets: eqos->config->ops->eqos_stop_resets(dev); -err_stop_clks: - eqos->config->ops->eqos_stop_clks(dev); err: pr_err("FAILED: %d", ret); return ret; @@ -1416,7 +1408,6 @@ static void eqos_stop(struct udevice *dev) phy_shutdown(eqos->phy); } eqos->config->ops->eqos_stop_resets(dev); - eqos->config->ops->eqos_stop_clks(dev); debug("%s: OK\n", __func__); } @@ -1862,6 +1853,12 @@ static int eqos_probe(struct udevice *dev) goto err_remove_resources_core; } + ret = eqos->config->ops->eqos_start_clks(dev); + if (ret < 0) { + pr_err("eqos_start_clks() failed: %d", ret); + goto err_remove_resources_tegra; + } + #ifdef CONFIG_DM_ETH_PHY eqos->mii = eth_phy_get_mdio_bus(dev); #endif @@ -1870,7 +1867,7 @@ static int eqos_probe(struct udevice *dev) if (!eqos->mii) { pr_err("mdio_alloc() failed"); ret = -ENOMEM; - goto err_remove_resources_tegra; + goto err_stop_clks; } eqos->mii->read = eqos_mdio_read; eqos->mii->write = eqos_mdio_write; @@ -1893,6 +1890,8 @@ static int eqos_probe(struct udevice *dev) err_free_mdio: mdio_free(eqos->mii); +err_stop_clks: + eqos->config->ops->eqos_stop_clks(dev); err_remove_resources_tegra: eqos->config->ops->eqos_remove_resources(dev); err_remove_resources_core: @@ -1910,6 +1909,7 @@ static int eqos_remove(struct udevice *dev) mdio_unregister(eqos->mii); mdio_free(eqos->mii); + eqos->config->ops->eqos_stop_clks(dev); eqos->config->ops->eqos_remove_resources(dev); eqos_probe_resources_core(dev); diff --git a/drivers/net/eth-phy-uclass.c b/drivers/net/eth-phy-uclass.c index c04bab9..a9b358e 100644 --- a/drivers/net/eth-phy-uclass.c +++ b/drivers/net/eth-phy-uclass.c @@ -138,7 +138,7 @@ static int eth_phy_of_to_plat(struct udevice *dev) ret = gpio_request_by_name(dev, "reset-gpios", 0, &uc_priv->reset_gpio, GPIOD_IS_OUT); - if (ret != -ENOENT) + if (ret && ret != -ENOENT) return ret; uc_priv->reset_assert_delay = dev_read_u32_default(dev, "reset-assert-us", 0); diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 8c6461e..37eed59 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -1348,7 +1348,7 @@ static const struct macb_usrio_cfg macb_default_usrio = { .clken = MACB_BIT(CLKEN), }; -static const struct macb_config default_gem_config = { +static struct macb_config default_gem_config = { .dma_burst_length = 16, .hw_dma_cap = HW_DMA_CAP_32B, .clk_init = NULL, @@ -1383,8 +1383,13 @@ static int macb_eth_probe(struct udevice *dev) macb->is_big_endian = (cpu_to_be32(0x12345678) == 0x12345678); macb->config = (struct macb_config *)dev_get_driver_data(dev); - if (!macb->config) + if (!macb->config) { + if (IS_ENABLED(CONFIG_DMA_ADDR_T_64BIT)) { + if (GEM_BFEXT(DAW64, gem_readl(macb, DCFG6))) + default_gem_config.hw_dma_cap = HW_DMA_CAP_64B; + } macb->config = &default_gem_config; + } #ifdef CONFIG_CLK ret = macb_enable_clk(dev); @@ -1453,13 +1458,6 @@ static const struct macb_usrio_cfg sama7g5_usrio = { .clken = BIT(2), }; -static const struct macb_config microchip_config = { - .dma_burst_length = 16, - .hw_dma_cap = HW_DMA_CAP_64B, - .clk_init = NULL, - .usrio = &macb_default_usrio, -}; - static const struct macb_config sama5d4_config = { .dma_burst_length = 4, .hw_dma_cap = HW_DMA_CAP_32B, @@ -1502,8 +1500,6 @@ static const struct udevice_id macb_eth_ids[] = { { .compatible = "cdns,zynq-gem" }, { .compatible = "sifive,fu540-c000-gem", .data = (ulong)&sifive_config }, - { .compatible = "microchip,mpfs-mss-gem", - .data = (ulong)µchip_config }, { } }; diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c index 6953b72..1d1118c 100644 --- a/drivers/net/ravb.c +++ b/drivers/net/ravb.c @@ -129,7 +129,7 @@ struct ravb_priv { struct phy_device *phydev; struct mii_dev *bus; void __iomem *iobase; - struct clk clk; + struct clk_bulk clks; struct gpio_desc reset_gpio; }; @@ -485,7 +485,7 @@ static int ravb_probe(struct udevice *dev) iobase = map_physmem(pdata->iobase, 0x1000, MAP_NOCACHE); eth->iobase = iobase; - ret = clk_get_by_index(dev, 0, ð->clk); + ret = clk_get_bulk(dev, ð->clks); if (ret < 0) goto err_mdio_alloc; @@ -518,7 +518,7 @@ static int ravb_probe(struct udevice *dev) eth->bus = miiphy_get_dev_by_name(dev->name); /* Bring up PHY */ - ret = clk_enable(ð->clk); + ret = clk_enable_bulk(ð->clks); if (ret) goto err_mdio_register; @@ -533,7 +533,7 @@ static int ravb_probe(struct udevice *dev) return 0; err_mdio_reset: - clk_disable(ð->clk); + clk_release_bulk(ð->clks); err_mdio_register: mdio_free(mdiodev); err_mdio_alloc: @@ -545,7 +545,7 @@ static int ravb_remove(struct udevice *dev) { struct ravb_priv *eth = dev_get_priv(dev); - clk_disable(ð->clk); + clk_release_bulk(ð->clks); free(eth->phydev); mdio_unregister(eth->bus); diff --git a/drivers/pci/pci-aardvark.c b/drivers/pci/pci-aardvark.c index 6d73aab..22b6d8b 100644 --- a/drivers/pci/pci-aardvark.c +++ b/drivers/pci/pci-aardvark.c @@ -21,6 +21,7 @@ * * Author: Victor Gu <xigu@marvell.com> * Hezi Shahmoon <hezi.shahmoon@marvell.com> + * Pali Rohár <pali@kernel.org> * */ @@ -192,7 +193,7 @@ struct pcie_advk { int sec_busno; struct udevice *dev; struct gpio_desc reset_gpio; - u32 cfgcache[0x34 - 0x10]; + u32 cfgcache[(0x3c - 0x10) / 4]; bool cfgcrssve; }; @@ -379,20 +380,19 @@ static int pcie_advk_read_config(const struct udevice *bus, pci_dev_t bdf, } /* - * The configuration space of the PCI Bridge on primary (local) bus is + * The configuration space of the PCI Bridge on primary (first) bus is * not accessible via PIO transfers like all other PCIe devices. PCI * Bridge config registers are available directly in Aardvark memory - * space starting at offset zero. Moreover PCI Bridge registers in the - * range 0x10 - 0x34 are not available and register 0x38 (Expansion ROM - * Base Address) is at offset 0x30. - * We therefore read configuration space content of the primary PCI - * Bridge from our virtual cache. + * space starting at offset zero. The PCI Bridge config space is of + * Type 0, but the BAR registers (including ROM BAR) don't have the same + * meaning as in the PCIe specification. Therefore do not access BAR + * registers and non-common registers (those which have different + * meaning for Type 0 and Type 1 config space) of the primary PCI Bridge + * and instead read their content from driver virtual cfgcache[]. */ if (busno == pcie->first_busno) { - if (offset >= 0x10 && offset < 0x34) + if ((offset >= 0x10 && offset < 0x34) || (offset >= 0x38 && offset < 0x3c)) data = pcie->cfgcache[(offset - 0x10) / 4]; - else if ((offset & ~3) == PCI_ROM_ADDRESS1) - data = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG); else data = advk_readl(pcie, offset & ~3); @@ -566,23 +566,22 @@ static int pcie_advk_write_config(struct udevice *bus, pci_dev_t bdf, } /* - * As explained in pcie_advk_read_config(), for the configuration - * space of the primary PCI Bridge, we write the content into virtual - * cache. + * As explained in pcie_advk_read_config(), PCI Bridge config registers + * are available directly in Aardvark memory space starting at offset + * zero. Type 1 specific registers are not available, so we write their + * content only into driver virtual cfgcache[]. */ if (busno == pcie->first_busno) { - if (offset >= 0x10 && offset < 0x34) { + if ((offset >= 0x10 && offset < 0x34) || + (offset >= 0x38 && offset < 0x3c)) { data = pcie->cfgcache[(offset - 0x10) / 4]; data = pci_conv_size_to_32(data, value, offset, size); /* This PCI bridge does not have configurable bars */ if ((offset & ~3) == PCI_BASE_ADDRESS_0 || - (offset & ~3) == PCI_BASE_ADDRESS_1) + (offset & ~3) == PCI_BASE_ADDRESS_1 || + (offset & ~3) == PCI_ROM_ADDRESS1) data = 0x0; pcie->cfgcache[(offset - 0x10) / 4] = data; - } else if ((offset & ~3) == PCI_ROM_ADDRESS1) { - data = advk_readl(pcie, PCIE_CORE_EXP_ROM_BAR_REG); - data = pci_conv_size_to_32(data, value, offset, size); - advk_writel(pcie, data, PCIE_CORE_EXP_ROM_BAR_REG); } else { data = advk_readl(pcie, offset & ~3); data = pci_conv_size_to_32(data, value, offset, size); @@ -820,12 +819,20 @@ static int pcie_advk_setup_hw(struct pcie_advk *pcie) * * Note that this Aardvark PCI Bridge does not have a compliant Type 1 * Configuration Space and it even cannot be accessed via Aardvark's - * PCI config space access method. Something like config space is + * PCI config space access method. Aardvark PCI Bridge Config space is * available in internal Aardvark registers starting at offset 0x0 - * and is reported as Type 0. In range 0x10 - 0x34 it has totally - * different registers. So our driver reports Header Type as Type 1 and - * for the above mentioned range redirects access to the virtual - * cfgcache[] buffer, which avoids changing internal Aardvark registers. + * and has format of Type 0 config space. + * + * Moreover Type 0 BAR registers (ranges 0x10 - 0x28 and 0x30 - 0x34) + * have the same format in Marvell's specification as in PCIe + * specification, but their meaning is totally different (and not even + * the same meaning as explained in the corresponding comment in the + * pci_mvebu driver; aardvark is still different). + * + * So our driver converts Type 0 config space to Type 1 and reports + * Header Type as Type 1. Access to BAR registers and to non-existent + * Type 1 registers is redirected to the virtual cfgcache[] buffer, + * which avoids changing unrelated registers. */ reg = advk_readl(pcie, PCIE_CORE_DEV_REV_REG); reg &= ~0xffffff00; diff --git a/drivers/pci/pci_mvebu.c b/drivers/pci/pci_mvebu.c index 14cd82d..cc8ebff 100644 --- a/drivers/pci/pci_mvebu.c +++ b/drivers/pci/pci_mvebu.c @@ -7,6 +7,7 @@ * Ported to U-Boot by: * Anton Schubert <anton.schubert@gmx.de> * Stefan Roese <sr@denx.de> + * Pali Rohár <pali@kernel.org> */ #include <common.h> @@ -88,7 +89,7 @@ struct mvebu_pcie { unsigned int mem_attr; unsigned int io_target; unsigned int io_attr; - u32 cfgcache[0x34 - 0x10]; + u32 cfgcache[(0x3c - 0x10) / 4]; }; /* @@ -167,20 +168,20 @@ static int mvebu_pcie_read_config(const struct udevice *bus, pci_dev_t bdf, } /* - * mvebu has different internal registers mapped into PCI config space - * in range 0x10-0x34 for PCI bridge, so do not access PCI config space - * for this range and instead read content from driver virtual cfgcache + * The configuration space of the PCI Bridge on primary (first) bus is + * of Type 0 but the BAR registers (including ROM BAR) don't have the + * same meaning as in the PCIe specification. Therefore do not access + * BAR registers and non-common registers (those which have different + * meaning for Type 0 and Type 1 config space) of the PCI Bridge and + * instead read their content from driver virtual cfgcache[]. */ - if (busno == pcie->first_busno && offset >= 0x10 && offset < 0x34) { + if (busno == pcie->first_busno && ((offset >= 0x10 && offset < 0x34) || + (offset >= 0x38 && offset < 0x3c))) { data = pcie->cfgcache[(offset - 0x10) / 4]; debug("(addr,size,val)=(0x%04x, %d, 0x%08x) from cfgcache\n", offset, size, data); *valuep = pci_conv_32_to_size(data, offset, size); return 0; - } else if (busno == pcie->first_busno && - (offset & ~3) == PCI_ROM_ADDRESS1) { - /* mvebu has Expansion ROM Base Address (0x38) at offset 0x30 */ - offset -= PCI_ROM_ADDRESS1 - PCIE_EXP_ROM_BAR_OFF; } /* @@ -247,17 +248,21 @@ static int mvebu_pcie_write_config(struct udevice *bus, pci_dev_t bdf, } /* - * mvebu has different internal registers mapped into PCI config space - * in range 0x10-0x34 for PCI bridge, so do not access PCI config space - * for this range and instead write content to driver virtual cfgcache + * As explained in mvebu_pcie_read_config(), PCI Bridge Type 1 specific + * config registers are not available, so we write their content only + * into driver virtual cfgcache[]. + * And as explained in mvebu_pcie_probe(), mvebu has its own specific + * way for configuring primary and secondary bus numbers. */ - if (busno == pcie->first_busno && offset >= 0x10 && offset < 0x34) { + if (busno == pcie->first_busno && ((offset >= 0x10 && offset < 0x34) || + (offset >= 0x38 && offset < 0x3c))) { debug("Writing to cfgcache only\n"); data = pcie->cfgcache[(offset - 0x10) / 4]; data = pci_conv_size_to_32(data, value, offset, size); /* mvebu PCI bridge does not have configurable bars */ if ((offset & ~3) == PCI_BASE_ADDRESS_0 || - (offset & ~3) == PCI_BASE_ADDRESS_1) + (offset & ~3) == PCI_BASE_ADDRESS_1 || + (offset & ~3) == PCI_ROM_ADDRESS1) data = 0x0; pcie->cfgcache[(offset - 0x10) / 4] = data; /* mvebu has its own way how to set PCI primary bus number */ @@ -275,10 +280,6 @@ static int mvebu_pcie_write_config(struct udevice *bus, pci_dev_t bdf, pcie->sec_busno); } return 0; - } else if (busno == pcie->first_busno && - (offset & ~3) == PCI_ROM_ADDRESS1) { - /* mvebu has Expansion ROM Base Address (0x38) at offset 0x30 */ - offset -= PCI_ROM_ADDRESS1 - PCIE_EXP_ROM_BAR_OFF; } /* @@ -384,13 +385,20 @@ static int mvebu_pcie_probe(struct udevice *dev) * U-Boot cannot recognize as P2P Bridge. * * Note that this mvebu PCI Bridge does not have compliant Type 1 - * Configuration Space. Header Type is reported as Type 0 and in - * range 0x10-0x34 it has aliased internal mvebu registers 0x10-0x34 - * (e.g. PCIE_BAR_LO_OFF) and register 0x38 is reserved. + * Configuration Space. Header Type is reported as Type 0 and it + * has format of Type 0 config space. * - * Driver for this range redirects access to virtual cfgcache[] buffer - * which avoids changing internal mvebu registers. And changes Header - * Type response value to Type 1. + * Moreover Type 0 BAR registers (ranges 0x10 - 0x28 and 0x30 - 0x34) + * have the same format in Marvell's specification as in PCIe + * specification, but their meaning is totally different and they do + * different things: they are aliased into internal mvebu registers + * (e.g. PCIE_BAR_LO_OFF) and these should not be changed or + * reconfigured by pci device drivers. + * + * So our driver converts Type 0 config space to Type 1 and reports + * Header Type as Type 1. Access to BAR registers and to non-existent + * Type 1 registers is redirected to the virtual cfgcache[] buffer, + * which avoids changing unrelated registers. */ reg = readl(pcie->base + PCIE_DEV_REV_OFF); reg &= ~0xffffff00; diff --git a/drivers/pci/pcie_layerscape_fixup.c b/drivers/pci/pcie_layerscape_fixup.c index 8a2a0e1..a47c9ef 100644 --- a/drivers/pci/pcie_layerscape_fixup.c +++ b/drivers/pci/pcie_layerscape_fixup.c @@ -584,9 +584,9 @@ static void ft_pcie_rc_fix(void *blob, struct ls_pcie_rc *pcie_rc) return; if (pcie_rc->enabled && pcie->mode == PCI_HEADER_TYPE_BRIDGE) - fdt_set_node_status(blob, off, FDT_STATUS_OKAY, 0); + fdt_set_node_status(blob, off, FDT_STATUS_OKAY); else - fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED); } static void ft_pcie_ep_fix(void *blob, struct ls_pcie_rc *pcie_rc) @@ -600,9 +600,9 @@ static void ft_pcie_ep_fix(void *blob, struct ls_pcie_rc *pcie_rc) return; if (pcie_rc->enabled && pcie->mode == PCI_HEADER_TYPE_NORMAL) - fdt_set_node_status(blob, off, FDT_STATUS_OKAY, 0); + fdt_set_node_status(blob, off, FDT_STATUS_OKAY); else - fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED); } static void ft_pcie_ls_setup(void *blob, struct ls_pcie_rc *pcie_rc) diff --git a/drivers/pci/pcie_layerscape_gen4_fixup.c b/drivers/pci/pcie_layerscape_gen4_fixup.c index 7d11234..b2a45bf 100644 --- a/drivers/pci/pcie_layerscape_gen4_fixup.c +++ b/drivers/pci/pcie_layerscape_gen4_fixup.c @@ -193,9 +193,9 @@ static void ft_pcie_ep_layerscape_gen4_fix(void *blob, struct ls_pcie_g4 *pcie) } if (pcie->enabled && pcie->mode == PCI_HEADER_TYPE_NORMAL) - fdt_set_node_status(blob, off, FDT_STATUS_OKAY, 0); + fdt_set_node_status(blob, off, FDT_STATUS_OKAY); else - fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED); } static void ft_pcie_rc_layerscape_gen4_fix(void *blob, struct ls_pcie_g4 *pcie) @@ -214,9 +214,9 @@ static void ft_pcie_rc_layerscape_gen4_fix(void *blob, struct ls_pcie_g4 *pcie) } if (pcie->enabled && pcie->mode == PCI_HEADER_TYPE_BRIDGE) - fdt_set_node_status(blob, off, FDT_STATUS_OKAY, 0); + fdt_set_node_status(blob, off, FDT_STATUS_OKAY); else - fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + fdt_set_node_status(blob, off, FDT_STATUS_DISABLED); } static void ft_pcie_layerscape_gen4_setup(void *blob, struct ls_pcie_g4 *pcie) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 047c8bb..4104353 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -11,6 +11,7 @@ #include <asm/arch/cpu.h> #include <asm/arch/soc.h> #include <linux/delay.h> +#include <phy.h> #include "comphy_a3700.h" @@ -982,6 +983,138 @@ void comphy_dedicated_phys_init(void) debug_exit(); } +static int find_available_node_by_compatible(int offset, const char *compatible) +{ + do { + offset = fdt_node_offset_by_compatible(gd->fdt_blob, offset, + compatible); + } while (offset > 0 && !fdtdec_get_is_enabled(gd->fdt_blob, offset)); + + return offset; +} + +static bool comphy_a3700_find_lane(const int nodes[3], int node, + int port, int *lane, int *invert) +{ + int res, i, j; + + for (i = 0; ; i++) { + struct fdtdec_phandle_args args; + + res = fdtdec_parse_phandle_with_args(gd->fdt_blob, node, "phys", + "#phy-cells", 0, i, &args); + if (res) + return false; + + for (j = 0; j < 3; j++) { + if (nodes[j] >= 0 && args.node == nodes[j] && + (args.args_count >= 1 ? args.args[0] : 0) == port) { + *lane = j; + *invert = args.args_count >= 2 ? args.args[1] + : 0; + return true; + } + } + } + + return false; +} + +static void comphy_a3700_fill_cfg(struct chip_serdes_phy_config *cfg, + const int nodes[3], const char *compatible, + int type) +{ + int node, lane, port, speed, invert; + + port = (type == COMPHY_TYPE_SGMII1) ? 1 : 0; + + node = -1; + while (1) { + node = find_available_node_by_compatible(node, compatible); + if (node < 0) + return; + + if (comphy_a3700_find_lane(nodes, node, port, &lane, &invert)) + break; + } + + if (cfg->comphy_map_data[lane].type != COMPHY_TYPE_UNCONNECTED) { + printf("Error: More PHYs defined for lane %d, skipping\n", + lane); + return; + } + + if (type == COMPHY_TYPE_SGMII0 || type == COMPHY_TYPE_SGMII1) { + const char *phy_mode; + + phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL); + if (phy_mode && + !strcmp(phy_mode, + phy_string_for_interface(PHY_INTERFACE_MODE_2500BASEX))) + speed = COMPHY_SPEED_3_125G; + else + speed = COMPHY_SPEED_1_25G; + } else if (type == COMPHY_TYPE_SATA0) { + speed = COMPHY_SPEED_6G; + } else { + speed = COMPHY_SPEED_5G; + } + + cfg->comphy_map_data[lane].type = type; + cfg->comphy_map_data[lane].speed = speed; + cfg->comphy_map_data[lane].invert = invert; +} + +static const fdt32_t comphy_a3700_mux_lane_order[3] = { + __constant_cpu_to_be32(1), + __constant_cpu_to_be32(0), + __constant_cpu_to_be32(2), +}; + +int comphy_a3700_init_serdes_map(int node, struct chip_serdes_phy_config *cfg) +{ + int comphy_nodes[3]; + int child, i; + + for (i = 0; i < ARRAY_SIZE(comphy_nodes); i++) + comphy_nodes[i] = -FDT_ERR_NOTFOUND; + + fdt_for_each_subnode(child, gd->fdt_blob, node) { + if (!fdtdec_get_is_enabled(gd->fdt_blob, child)) + continue; + + i = fdtdec_get_int(gd->fdt_blob, child, "reg", -1); + if (i < 0 || i >= ARRAY_SIZE(comphy_nodes)) + continue; + + comphy_nodes[i] = child; + } + + for (i = 0; i < ARRAY_SIZE(comphy_nodes); i++) { + cfg->comphy_map_data[i].type = COMPHY_TYPE_UNCONNECTED; + cfg->comphy_map_data[i].speed = COMPHY_SPEED_INVALID; + } + + comphy_a3700_fill_cfg(cfg, comphy_nodes, "marvell,armada3700-u3d", + COMPHY_TYPE_USB3_DEVICE); + comphy_a3700_fill_cfg(cfg, comphy_nodes, "marvell,armada3700-xhci", + COMPHY_TYPE_USB3_HOST0); + comphy_a3700_fill_cfg(cfg, comphy_nodes, "marvell,armada-3700-pcie", + COMPHY_TYPE_PEX0); + comphy_a3700_fill_cfg(cfg, comphy_nodes, "marvell,armada-3700-ahci", + COMPHY_TYPE_SATA0); + comphy_a3700_fill_cfg(cfg, comphy_nodes, "marvell,armada-3700-neta", + COMPHY_TYPE_SGMII0); + comphy_a3700_fill_cfg(cfg, comphy_nodes, "marvell,armada-3700-neta", + COMPHY_TYPE_SGMII1); + + cfg->comphy_lanes_count = 3; + cfg->comphy_mux_bitcount = 4; + cfg->comphy_mux_lane_order = comphy_a3700_mux_lane_order; + + return 0; +} + int comphy_a3700_init(struct chip_serdes_phy_config *chip_cfg, struct comphy_map *serdes_map) { diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index 2c9d7b2..233a973 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -86,11 +86,8 @@ __weak int comphy_update_map(struct comphy_map *serdes_map, int count) static int comphy_probe(struct udevice *dev) { - const void *blob = gd->fdt_blob; int node = dev_of_offset(dev); struct chip_serdes_phy_config *chip_cfg = dev_get_priv(dev); - int subnode; - int lane; int last_idx = 0; static int current_idx; int res; @@ -104,30 +101,14 @@ static int comphy_probe(struct udevice *dev) if (IS_ERR(chip_cfg->hpipe3_base_addr)) return PTR_ERR(chip_cfg->hpipe3_base_addr); - chip_cfg->comphy_lanes_count = fdtdec_get_int(blob, node, - "max-lanes", 0); - if (chip_cfg->comphy_lanes_count <= 0) { - dev_err(dev, "comphy max lanes is wrong\n"); - return -EINVAL; - } - - chip_cfg->comphy_mux_bitcount = fdtdec_get_int(blob, node, - "mux-bitcount", 0); - if (chip_cfg->comphy_mux_bitcount <= 0) { - dev_err(dev, "comphy mux bit count is wrong\n"); - return -EINVAL; - } - - chip_cfg->comphy_mux_lane_order = - fdtdec_locate_array(blob, node, "mux-lane-order", - chip_cfg->comphy_lanes_count); - if (device_is_compatible(dev, "marvell,comphy-armada-3700")) { + chip_cfg->comphy_init_map = comphy_a3700_init_serdes_map; chip_cfg->ptr_comphy_chip_init = comphy_a3700_init; chip_cfg->rx_training = NULL; } if (device_is_compatible(dev, "marvell,comphy-cp110")) { + chip_cfg->comphy_init_map = comphy_cp110_init_serdes_map; chip_cfg->ptr_comphy_chip_init = comphy_cp110_init; chip_cfg->rx_training = comphy_cp110_sfi_rx_training; } @@ -141,39 +122,9 @@ static int comphy_probe(struct udevice *dev) return -ENODEV; } - lane = 0; - fdt_for_each_subnode(subnode, blob, node) { - /* Skip disabled ports */ - if (!fdtdec_get_is_enabled(blob, subnode)) - continue; - - chip_cfg->comphy_map_data[lane].type = - fdtdec_get_int(blob, subnode, "phy-type", - COMPHY_TYPE_INVALID); - - if (chip_cfg->comphy_map_data[lane].type == - COMPHY_TYPE_INVALID) { - printf("no phy type for lane %d, setting lane as unconnected\n", - lane + 1); - continue; - } - - chip_cfg->comphy_map_data[lane].speed = - fdtdec_get_int(blob, subnode, "phy-speed", - COMPHY_SPEED_INVALID); - - chip_cfg->comphy_map_data[lane].invert = - fdtdec_get_int(blob, subnode, "phy-invert", - COMPHY_POLARITY_NO_INVERT); - - chip_cfg->comphy_map_data[lane].clk_src = - fdtdec_get_bool(blob, subnode, "clk-src"); - - chip_cfg->comphy_map_data[lane].end_point = - fdtdec_get_bool(blob, subnode, "end_point"); - - lane++; - } + res = chip_cfg->comphy_init_map(node, chip_cfg); + if (res < 0) + return res; res = comphy_update_map(chip_cfg->comphy_map_data, chip_cfg->comphy_lanes_count); if (res < 0) diff --git a/drivers/phy/marvell/comphy_core.h b/drivers/phy/marvell/comphy_core.h index 9bbd7f8..d573776 100644 --- a/drivers/phy/marvell/comphy_core.h +++ b/drivers/phy/marvell/comphy_core.h @@ -32,6 +32,7 @@ struct comphy_mux_data { struct chip_serdes_phy_config { struct comphy_mux_data *mux_data; + int (*comphy_init_map)(int, struct chip_serdes_phy_config *); int (*ptr_comphy_chip_init)(struct chip_serdes_phy_config *, struct comphy_map *); int (*rx_training)(struct chip_serdes_phy_config *, u32); @@ -85,9 +86,20 @@ static inline void reg_set16(void __iomem *addr, u16 data, u16 mask) /* SoC specific init functions */ #ifdef CONFIG_ARMADA_3700 +int comphy_a3700_init_serdes_map(int node, struct chip_serdes_phy_config *cfg); int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg, struct comphy_map *serdes_map); #else +static inline int +comphy_a3700_init_serdes_map(int node, struct chip_serdes_phy_config *cfg) +{ + /* + * This function should never be called in this configuration, so + * lets return an error here. + */ + return -1; +} + static inline int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg, struct comphy_map *serdes_map) { @@ -100,11 +112,22 @@ static inline int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg, #endif #ifdef CONFIG_ARMADA_8K +int comphy_cp110_init_serdes_map(int node, struct chip_serdes_phy_config *cfg); int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, struct comphy_map *serdes_map); int comphy_cp110_sfi_rx_training(struct chip_serdes_phy_config *ptr_chip_cfg, u32 lane); #else +static inline int +comphy_cp110_init_serdes_map(int node, struct chip_serdes_phy_config *cfg) +{ + /* + * This function should never be called in this configuration, so + * lets return an error here. + */ + return -1; +} + static inline int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, struct comphy_map *serdes_map) { diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c index 4fe2dfc..e063b51 100644 --- a/drivers/phy/marvell/comphy_cp110.c +++ b/drivers/phy/marvell/comphy_cp110.c @@ -554,6 +554,64 @@ void comphy_dedicated_phys_init(void) debug_exit(); } +int comphy_cp110_init_serdes_map(int node, struct chip_serdes_phy_config *cfg) +{ + int lane, subnode; + + cfg->comphy_lanes_count = fdtdec_get_int(gd->fdt_blob, node, + "max-lanes", 0); + if (cfg->comphy_lanes_count <= 0) { + printf("comphy max lanes is wrong\n"); + return -EINVAL; + } + + cfg->comphy_mux_bitcount = fdtdec_get_int(gd->fdt_blob, node, + "mux-bitcount", 0); + if (cfg->comphy_mux_bitcount <= 0) { + printf("comphy mux bit count is wrong\n"); + return -EINVAL; + } + + cfg->comphy_mux_lane_order = fdtdec_locate_array(gd->fdt_blob, node, + "mux-lane-order", + cfg->comphy_lanes_count); + + lane = 0; + fdt_for_each_subnode(subnode, gd->fdt_blob, node) { + /* Skip disabled ports */ + if (!fdtdec_get_is_enabled(gd->fdt_blob, subnode)) + continue; + + cfg->comphy_map_data[lane].type = + fdtdec_get_int(gd->fdt_blob, subnode, "phy-type", + COMPHY_TYPE_INVALID); + + if (cfg->comphy_map_data[lane].type == COMPHY_TYPE_INVALID) { + printf("no phy type for lane %d, setting lane as unconnected\n", + lane + 1); + continue; + } + + cfg->comphy_map_data[lane].speed = + fdtdec_get_int(gd->fdt_blob, subnode, "phy-speed", + COMPHY_SPEED_INVALID); + + cfg->comphy_map_data[lane].invert = + fdtdec_get_int(gd->fdt_blob, subnode, "phy-invert", + COMPHY_POLARITY_NO_INVERT); + + cfg->comphy_map_data[lane].clk_src = + fdtdec_get_bool(gd->fdt_blob, subnode, "clk-src"); + + cfg->comphy_map_data[lane].end_point = + fdtdec_get_bool(gd->fdt_blob, subnode, "end_point"); + + lane++; + } + + return 0; +} + int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, struct comphy_map *serdes_map) { diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c index 6bca8e4..3e673bd 100644 --- a/drivers/serial/serial_mvebu_a3700.c +++ b/drivers/serial/serial_mvebu_a3700.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2016 Stefan Roese <sr@denx.de> + * Copyright (C) 2021 Pali Rohár <pali@kernel.org> */ #include <common.h> @@ -9,6 +10,7 @@ #include <serial.h> #include <asm/io.h> #include <asm/arch/cpu.h> +#include <mach/soc.h> struct mvebu_plat { void __iomem *base; @@ -213,6 +215,7 @@ static int mvebu_serial_remove(struct udevice *dev) u32 new_oversampling; u32 oversampling; u32 d1, d2; + u32 nb_rst; /* * Switch UART base clock back to XTAL because older Linux kernel @@ -260,12 +263,22 @@ static int mvebu_serial_remove(struct udevice *dev) return 0; } + /* wait until TX empty */ while (!(readl(base + UART_STATUS_REG) & UART_STATUS_TX_EMPTY)) ; + /* external reset of UART via North Bridge Peripheral */ + nb_rst = readl(MVEBU_REGISTER(0x12400)); + writel(nb_rst & ~BIT(3), MVEBU_REGISTER(0x12400)); + writel(nb_rst | BIT(3), MVEBU_REGISTER(0x12400)); + + /* set baudrate and oversampling */ writel(new_divider, base + UART_BAUD_REG); writel(new_oversampling, base + UART_POSSR_REG); + /* No Parity, 1 Stop */ + writel(0, base + UART_CTRL_REG); + return 0; } @@ -305,7 +318,6 @@ U_BOOT_DRIVER(serial_mvebu) = { #ifdef CONFIG_DEBUG_MVEBU_A3700_UART #include <debug_uart.h> -#include <mach/soc.h> static inline void _debug_uart_init(void) { diff --git a/drivers/tpm/tpm2_tis_core.c b/drivers/tpm/tpm2_tis_core.c index ec8c730..51392c4 100644 --- a/drivers/tpm/tpm2_tis_core.c +++ b/drivers/tpm/tpm2_tis_core.c @@ -378,8 +378,14 @@ out: int tpm_tis_cleanup(struct udevice *dev) { struct tpm_chip *chip = dev_get_priv(dev); + int ret; + + ret = tpm_tis_request_locality(dev, 0); + if (ret) + return ret; tpm_tis_ready(dev); + tpm_tis_release_locality(dev, chip->locality); return 0; diff --git a/drivers/tpm/tpm2_tis_mmio.c b/drivers/tpm/tpm2_tis_mmio.c index 9cedff2..a646ce4 100644 --- a/drivers/tpm/tpm2_tis_mmio.c +++ b/drivers/tpm/tpm2_tis_mmio.c @@ -118,10 +118,13 @@ iounmap: static int tpm_tis_remove(struct udevice *dev) { struct tpm_tis_chip_data *drv_data = (void *)dev_get_driver_data(dev); + int ret; + + ret = tpm_tis_cleanup(dev); iounmap(drv_data->iobase); - return tpm_tis_cleanup(dev); + return ret; } static const struct tpm_ops tpm_tis_ops = { diff --git a/include/blk.h b/include/blk.h index f0cc7ca..dde2173 100644 --- a/include/blk.h +++ b/include/blk.h @@ -34,9 +34,10 @@ enum if_type { IF_TYPE_SATA, IF_TYPE_HOST, IF_TYPE_NVME, - IF_TYPE_EFI, + IF_TYPE_EFI_LOADER, IF_TYPE_PVBLOCK, IF_TYPE_VIRTIO, + IF_TYPE_EFI_MEDIA, IF_TYPE_COUNT, /* Number of interface types */ }; diff --git a/include/clk.h b/include/clk.h index a928879..df5255e 100644 --- a/include/clk.h +++ b/include/clk.h @@ -389,7 +389,8 @@ int clk_free(struct clk *clk); * * @clk: A clock struct that was previously successfully requested by * clk_request/get_by_*(). - * @return clock rate in Hz, or -ve error code. + * @return clock rate in Hz on success, 0 for invalid clock, or -ve error code + * for other errors. */ ulong clk_get_rate(struct clk *clk); diff --git a/include/configs/ax25-ae350.h b/include/configs/ax25-ae350.h index bf3f34e..1c3f957 100644 --- a/include/configs/ax25-ae350.h +++ b/include/configs/ax25-ae350.h @@ -119,12 +119,23 @@ /* Increase max gunzip size */ #define CONFIG_SYS_BOOTM_LEN (64 << 20) +/* Support autoboot from RAM (kernel image is loaded via debug port) */ +#define KERNEL_IMAGE_ADDR "0x2000000 " +#define BOOTENV_DEV_NAME_RAM(devtypeu, devtypel, instance) \ + "ram " +#define BOOTENV_DEV_RAM(devtypeu, devtypel, instance) \ + "bootcmd_ram=" \ + "booti " \ + KERNEL_IMAGE_ADDR \ + "- $fdtcontroladdr\0" + /* When we use RAM as ENV */ /* Enable distro boot */ #define BOOT_TARGET_DEVICES(func) \ func(MMC, mmc, 0) \ - func(DHCP, dhcp, na) + func(DHCP, dhcp, na) \ + func(RAM, ram, na) #include <config_distro_bootcmd.h> #define CONFIG_EXTRA_ENV_SETTINGS \ diff --git a/include/configs/beacon-rzg2m.h b/include/configs/beacon-rzg2m.h index 320f78b..7eaafb0 100644 --- a/include/configs/beacon-rzg2m.h +++ b/include/configs/beacon-rzg2m.h @@ -23,7 +23,7 @@ "boot_fdt=try\0" \ "fdt_file=" CONFIG_DEFAULT_FDT_FILE "\0" \ "initrd_addr=0x43800000\0" \ - "mmcdev=0\0" \ + "mmcdev=1\0" \ "mmcpart=1\0" \ "mmcrootpart=2\0" \ "finduuid=part uuid mmc ${mmcdev}:${mmcrootpart} uuid\0" \ diff --git a/include/configs/rpi.h b/include/configs/rpi.h index bc907ac..d5e064f 100644 --- a/include/configs/rpi.h +++ b/include/configs/rpi.h @@ -136,7 +136,8 @@ #if CONFIG_IS_ENABLED(CMD_MMC) #define BOOT_TARGET_MMC(func) \ func(MMC, mmc, 0) \ - func(MMC, mmc, 1) + func(MMC, mmc, 1) \ + func(MMC, mmc, 2) #else #define BOOT_TARGET_MMC(func) #endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index fd139b9..0e26e1d 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -48,7 +48,8 @@ enum uclass_id { UCLASS_DMA, /* Direct Memory Access */ UCLASS_DSA, /* Distributed (Ethernet) Switch Architecture */ UCLASS_ECDSA, /* Elliptic curve cryptographic device */ - UCLASS_EFI, /* EFI managed devices */ + UCLASS_EFI_LOADER, /* Devices created by UEFI applications */ + UCLASS_EFI_MEDIA, /* Devices provided by UEFI firmware */ UCLASS_ETH, /* Ethernet device */ UCLASS_ETH_PHY, /* Ethernet PHY device */ UCLASS_FIRMWARE, /* Firmware */ diff --git a/include/dt-bindings/interrupt-controller/microchip-mpfs-plic.h b/include/dt-bindings/interrupt-controller/microchip-mpfs-plic.h new file mode 100644 index 0000000..eba1bac --- /dev/null +++ b/include/dt-bindings/interrupt-controller/microchip-mpfs-plic.h @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* Copyright (c) 2020-2021 Microchip Technology Inc */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_MICROCHIP_MPFS_PLIC_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_MICROCHIP_MPFS_PLIC_H + +#define PLIC_INT_INVALID 0 +#define PLIC_INT_L2_METADATA_CORR 1 +#define PLIC_INT_L2_METADATA_UNCORR 2 +#define PLIC_INT_L2_DATA_CORR 3 +#define PLIC_INT_L2_DATA_UNCORR 4 +#define PLIC_INT_DMA_CH0_DONE 5 +#define PLIC_INT_DMA_CH0_ERR 6 +#define PLIC_INT_DMA_CH1_DONE 7 +#define PLIC_INT_DMA_CH1_ERR 8 +#define PLIC_INT_DMA_CH2_DONE 9 +#define PLIC_INT_DMA_CH2_ERR 10 +#define PLIC_INT_DMA_CH3_DONE 11 +#define PLIC_INT_DMA_CH3_ERR 12 + +#define PLIC_INT_GPIO0_BIT0_OR_GPIO2_BIT0 13 +#define PLIC_INT_GPIO0_BIT1_OR_GPIO2_BIT1 14 +#define PLIC_INT_GPIO0_BIT2_OR_GPIO2_BIT2 15 +#define PLIC_INT_GPIO0_BIT3_OR_GPIO2_BIT3 16 +#define PLIC_INT_GPIO0_BIT4_OR_GPIO2_BIT4 17 +#define PLIC_INT_GPIO0_BIT5_OR_GPIO2_BIT5 18 +#define PLIC_INT_GPIO0_BIT6_OR_GPIO2_BIT6 19 +#define PLIC_INT_GPIO0_BIT7_OR_GPIO2_BIT7 20 +#define PLIC_INT_GPIO0_BIT8_OR_GPIO2_BIT8 21 +#define PLIC_INT_GPIO0_BIT9_OR_GPIO2_BIT9 22 +#define PLIC_INT_GPIO0_BIT10_OR_GPIO2_BIT10 23 +#define PLIC_INT_GPIO0_BIT11_OR_GPIO2_BIT11 24 +#define PLIC_INT_GPIO0_BIT12_OR_GPIO2_BIT12 25 +#define PLIC_INT_GPIO0_BIT13_OR_GPIO2_BIT13 26 +#define PLIC_INT_GPIO1_BIT0_OR_GPIO2_BIT14 27 +#define PLIC_INT_GPIO1_BIT1_OR_GPIO2_BIT15 28 +#define PLIC_INT_GPIO1_BIT2_OR_GPIO2_BIT16 29 +#define PLIC_INT_GPIO1_BIT3_OR_GPIO2_BIT17 30 +#define PLIC_INT_GPIO1_BIT4_OR_GPIO2_BIT18 31 +#define PLIC_INT_GPIO1_BIT5_OR_GPIO2_BIT19 32 +#define PLIC_INT_GPIO1_BIT6_OR_GPIO2_BIT20 33 +#define PLIC_INT_GPIO1_BIT7_OR_GPIO2_BIT21 34 +#define PLIC_INT_GPIO1_BIT8_OR_GPIO2_BIT22 35 +#define PLIC_INT_GPIO1_BIT9_OR_GPIO2_BIT23 36 +#define PLIC_INT_GPIO1_BIT10_OR_GPIO2_BIT24 37 +#define PLIC_INT_GPIO1_BIT11_OR_GPIO2_BIT25 38 +#define PLIC_INT_GPIO1_BIT12_OR_GPIO2_BIT26 39 +#define PLIC_INT_GPIO1_BIT13_OR_GPIO2_BIT27 40 +#define PLIC_INT_GPIO1_BIT14_OR_GPIO2_BIT28 41 +#define PLIC_INT_GPIO1_BIT15_OR_GPIO2_BIT29 42 +#define PLIC_INT_GPIO1_BIT16_OR_GPIO2_BIT30 43 +#define PLIC_INT_GPIO1_BIT17_OR_GPIO2_BIT31 44 +#define PLIC_INT_GPIO1_BIT18 45 +#define PLIC_INT_GPIO1_BIT19 46 +#define PLIC_INT_GPIO1_BIT20 47 +#define PLIC_INT_GPIO1_BIT21 48 +#define PLIC_INT_GPIO1_BIT22 49 +#define PLIC_INT_GPIO1_BIT23 50 +#define PLIC_INT_GPIO0_NON_DIRECT 51 +#define PLIC_INT_GPIO1_NON_DIRECT 52 +#define PLIC_INT_GPIO2_NON_DIRECT 53 +#define PLIC_INT_SPI0 54 +#define PLIC_INT_SPI1 55 +#define PLIC_INT_CAN0 56 +#define PLIC_INT_CAN1 57 +#define PLIC_INT_I2C0_MAIN 58 +#define PLIC_INT_I2C0_ALERT 59 +#define PLIC_INT_I2C0_SUS 60 +#define PLIC_INT_I2C1_MAIN 61 +#define PLIC_INT_I2C1_ALERT 62 +#define PLIC_INT_I2C1_SUS 63 +#define PLIC_INT_MAC0_INT 64 +#define PLIC_INT_MAC0_QUEUE1 65 +#define PLIC_INT_MAC0_QUEUE2 66 +#define PLIC_INT_MAC0_QUEUE3 67 +#define PLIC_INT_MAC0_EMAC 68 +#define PLIC_INT_MAC0_MMSL 69 +#define PLIC_INT_MAC1_INT 70 +#define PLIC_INT_MAC1_QUEUE1 71 +#define PLIC_INT_MAC1_QUEUE2 72 +#define PLIC_INT_MAC1_QUEUE3 73 +#define PLIC_INT_MAC1_EMAC 74 +#define PLIC_INT_MAC1_MMSL 75 +#define PLIC_INT_DDRC_TRAIN 76 +#define PLIC_INT_SCB_INTERRUPT 77 +#define PLIC_INT_ECC_ERROR 78 +#define PLIC_INT_ECC_CORRECT 79 +#define PLIC_INT_RTC_WAKEUP 80 +#define PLIC_INT_RTC_MATCH 81 +#define PLIC_INT_TIMER1 82 +#define PLIC_INT_TIMER2 83 +#define PLIC_INT_ENVM 84 +#define PLIC_INT_QSPI 85 +#define PLIC_INT_USB_DMA 86 +#define PLIC_INT_USB_MC 87 +#define PLIC_INT_MMC_MAIN 88 +#define PLIC_INT_MMC_WAKEUP 89 +#define PLIC_INT_MMUART0 90 +#define PLIC_INT_MMUART1 91 +#define PLIC_INT_MMUART2 92 +#define PLIC_INT_MMUART3 93 +#define PLIC_INT_MMUART4 94 +#define PLIC_INT_G5C_DEVRST 95 +#define PLIC_INT_G5C_MESSAGE 96 +#define PLIC_INT_USOC_VC_INTERRUPT 97 +#define PLIC_INT_USOC_SMB_INTERRUPT 98 +#define PLIC_INT_E51_0_MAINTENACE 99 +#define PLIC_INT_WDOG0_MRVP 100 +#define PLIC_INT_WDOG1_MRVP 101 +#define PLIC_INT_WDOG2_MRVP 102 +#define PLIC_INT_WDOG3_MRVP 103 +#define PLIC_INT_WDOG4_MRVP 104 +#define PLIC_INT_WDOG0_TOUT 105 +#define PLIC_INT_WDOG1_TOUT 106 +#define PLIC_INT_WDOG2_TOUT 107 +#define PLIC_INT_WDOG3_TOUT 108 +#define PLIC_INT_WDOG4_TOUT 109 +#define PLIC_INT_G5C_MSS_SPI 110 +#define PLIC_INT_VOLT_TEMP_ALARM 111 +#define PLIC_INT_ATHENA_COMPLETE 112 +#define PLIC_INT_ATHENA_ALARM 113 +#define PLIC_INT_ATHENA_BUS_ERROR 114 +#define PLIC_INT_USOC_AXIC_US 115 +#define PLIC_INT_USOC_AXIC_DS 116 +#define PLIC_INT_SPARE 117 +#define PLIC_INT_FABRIC_F2H_0 118 +#define PLIC_INT_FABRIC_F2H_1 119 +#define PLIC_INT_FABRIC_F2H_2 120 +#define PLIC_INT_FABRIC_F2H_3 121 +#define PLIC_INT_FABRIC_F2H_4 122 +#define PLIC_INT_FABRIC_F2H_5 123 +#define PLIC_INT_FABRIC_F2H_6 124 +#define PLIC_INT_FABRIC_F2H_7 125 +#define PLIC_INT_FABRIC_F2H_8 126 +#define PLIC_INT_FABRIC_F2H_9 127 +#define PLIC_INT_FABRIC_F2H_10 128 +#define PLIC_INT_FABRIC_F2H_11 129 +#define PLIC_INT_FABRIC_F2H_12 130 +#define PLIC_INT_FABRIC_F2H_13 131 +#define PLIC_INT_FABRIC_F2H_14 132 +#define PLIC_INT_FABRIC_F2H_15 133 +#define PLIC_INT_FABRIC_F2H_16 134 +#define PLIC_INT_FABRIC_F2H_17 135 +#define PLIC_INT_FABRIC_F2H_18 136 +#define PLIC_INT_FABRIC_F2H_19 137 +#define PLIC_INT_FABRIC_F2H_20 138 +#define PLIC_INT_FABRIC_F2H_21 139 +#define PLIC_INT_FABRIC_F2H_22 140 +#define PLIC_INT_FABRIC_F2H_23 141 +#define PLIC_INT_FABRIC_F2H_24 142 +#define PLIC_INT_FABRIC_F2H_25 143 +#define PLIC_INT_FABRIC_F2H_26 144 +#define PLIC_INT_FABRIC_F2H_27 145 +#define PLIC_INT_FABRIC_F2H_28 146 +#define PLIC_INT_FABRIC_F2H_29 147 +#define PLIC_INT_FABRIC_F2H_30 148 +#define PLIC_INT_FABRIC_F2H_31 149 +#define PLIC_INT_FABRIC_F2H_32 150 +#define PLIC_INT_FABRIC_F2H_33 151 +#define PLIC_INT_FABRIC_F2H_34 152 +#define PLIC_INT_FABRIC_F2H_35 153 +#define PLIC_INT_FABRIC_F2H_36 154 +#define PLIC_INT_FABRIC_F2H_37 155 +#define PLIC_INT_FABRIC_F2H_38 156 +#define PLIC_INT_FABRIC_F2H_39 157 +#define PLIC_INT_FABRIC_F2H_40 158 +#define PLIC_INT_FABRIC_F2H_41 159 +#define PLIC_INT_FABRIC_F2H_42 160 +#define PLIC_INT_FABRIC_F2H_43 161 +#define PLIC_INT_FABRIC_F2H_44 162 +#define PLIC_INT_FABRIC_F2H_45 163 +#define PLIC_INT_FABRIC_F2H_46 164 +#define PLIC_INT_FABRIC_F2H_47 165 +#define PLIC_INT_FABRIC_F2H_48 166 +#define PLIC_INT_FABRIC_F2H_49 167 +#define PLIC_INT_FABRIC_F2H_50 168 +#define PLIC_INT_FABRIC_F2H_51 169 +#define PLIC_INT_FABRIC_F2H_52 170 +#define PLIC_INT_FABRIC_F2H_53 171 +#define PLIC_INT_FABRIC_F2H_54 172 +#define PLIC_INT_FABRIC_F2H_55 173 +#define PLIC_INT_FABRIC_F2H_56 174 +#define PLIC_INT_FABRIC_F2H_57 175 +#define PLIC_INT_FABRIC_F2H_58 176 +#define PLIC_INT_FABRIC_F2H_59 177 +#define PLIC_INT_FABRIC_F2H_60 178 +#define PLIC_INT_FABRIC_F2H_61 179 +#define PLIC_INT_FABRIC_F2H_62 180 +#define PLIC_INT_FABRIC_F2H_63 181 +#define PLIC_INT_BUS_ERROR_UNIT_HART_0 182 +#define PLIC_INT_BUS_ERROR_UNIT_HART_1 183 +#define PLIC_INT_BUS_ERROR_UNIT_HART_2 184 +#define PLIC_INT_BUS_ERROR_UNIT_HART_3 185 +#define PLIC_INT_BUS_ERROR_UNIT_HART_4 186 + +#endif /* _DT_BINDINGS_INTERRUPT_CONTROLLER_MICROCHIP_MPFS_PLIC_H */ diff --git a/include/dt-bindings/interrupt-controller/riscv-hart.h b/include/dt-bindings/interrupt-controller/riscv-hart.h new file mode 100644 index 0000000..c4331b8 --- /dev/null +++ b/include/dt-bindings/interrupt-controller/riscv-hart.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* Copyright (c) 2020-2021 Microchip Technology Inc */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_RISCV_HART_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_RISCV_HART_H + +#define HART_INT_U_SOFT 0 +#define HART_INT_S_SOFT 1 +#define HART_INT_M_SOFT 3 +#define HART_INT_U_TIMER 4 +#define HART_INT_S_TIMER 5 +#define HART_INT_M_TIMER 7 +#define HART_INT_U_EXT 8 +#define HART_INT_S_EXT 9 +#define HART_INT_M_EXT 11 + +#endif /* _DT_BINDINGS_INTERRUPT_CONTROLLER_RISCV_HART_H */ diff --git a/include/efi.h b/include/efi.h index b583542..0ec5913 100644 --- a/include/efi.h +++ b/include/efi.h @@ -414,6 +414,17 @@ struct efi_priv { void *next_hdr; }; +/* + * EFI attributes of the udevice handled by efi_media driver + * + * @handle: handle of the controller on which this driver is installed + * @blkio: block io protocol proxied by this driver + */ +struct efi_media_plat { + efi_handle_t handle; + struct efi_block_io *blkio; +}; + /* Base address of the EFI image */ extern char image_base[]; diff --git a/include/efi_loader.h b/include/efi_loader.h index d52e399..f4860e8 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -525,6 +525,8 @@ efi_status_t efi_disk_register(void); efi_status_t efi_rng_register(void); /* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */ efi_status_t efi_tcg2_register(void); +/* Called by efi_init_obj_list() to do initial measurement */ +efi_status_t efi_tcg2_do_initial_measurement(void); /* measure the pe-coff image, extend PCR and add Event Log */ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size, struct efi_loaded_image_obj *handle, @@ -988,4 +990,6 @@ efi_status_t efi_esrt_register(void); */ efi_status_t efi_esrt_populate(void); efi_status_t efi_load_capsule_drivers(void); + +efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz); #endif /* _EFI_LOADER_H */ diff --git a/include/fdt_support.h b/include/fdt_support.h index 88d129c..8ec461a 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -228,6 +228,8 @@ void set_working_fdt_addr(ulong addr); int fdt_shrink_to_minimum(void *blob, uint extrasize); int fdt_increase_size(void *fdt, int add_len); +int fdt_delete_disabled_nodes(void *blob); + int fdt_fixup_nor_flash_size(void *blob); struct node_info; @@ -285,9 +287,13 @@ int fdt_get_dma_range(const void *blob, int node_offset, phys_addr_t *cpu, int fdt_node_offset_by_compat_reg(void *blob, const char *compat, phys_addr_t compat_off); -int fdt_alloc_phandle(void *blob); +int fdt_node_offset_by_pathf(void *blob, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); int fdt_set_phandle(void *fdt, int nodeoffset, uint32_t phandle); unsigned int fdt_create_phandle(void *fdt, int nodeoffset); +unsigned int fdt_create_phandle_by_compatible(void *fdt, const char *compat); +unsigned int fdt_create_phandle_by_pathf(void *fdt, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); int fdt_add_edid(void *blob, const char *compat, unsigned char *buf); int fdt_verify_alias_address(void *fdt, int anode, const char *alias, @@ -300,38 +306,61 @@ enum fdt_status { FDT_STATUS_OKAY, FDT_STATUS_DISABLED, FDT_STATUS_FAIL, - FDT_STATUS_FAIL_ERROR_CODE, }; -int fdt_set_node_status(void *fdt, int nodeoffset, - enum fdt_status status, unsigned int error_code); +int fdt_set_node_status(void *fdt, int nodeoffset, enum fdt_status status); static inline int fdt_status_okay(void *fdt, int nodeoffset) { - return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_OKAY, 0); + return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_OKAY); } static inline int fdt_status_disabled(void *fdt, int nodeoffset) { - return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_DISABLED, 0); + return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_DISABLED); } static inline int fdt_status_fail(void *fdt, int nodeoffset) { - return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_FAIL, 0); + return fdt_set_node_status(fdt, nodeoffset, FDT_STATUS_FAIL); } int fdt_set_status_by_alias(void *fdt, const char *alias, - enum fdt_status status, unsigned int error_code); + enum fdt_status status); static inline int fdt_status_okay_by_alias(void *fdt, const char *alias) { - return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_OKAY, 0); + return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_OKAY); } static inline int fdt_status_disabled_by_alias(void *fdt, const char *alias) { - return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_DISABLED, 0); + return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_DISABLED); } static inline int fdt_status_fail_by_alias(void *fdt, const char *alias) { - return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_FAIL, 0); + return fdt_set_status_by_alias(fdt, alias, FDT_STATUS_FAIL); } +int fdt_set_status_by_compatible(void *fdt, const char *compat, + enum fdt_status status); +static inline int fdt_status_okay_by_compatible(void *fdt, const char *compat) +{ + return fdt_set_status_by_compatible(fdt, compat, FDT_STATUS_OKAY); +} +static inline int fdt_status_disabled_by_compatible(void *fdt, + const char *compat) +{ + return fdt_set_status_by_compatible(fdt, compat, FDT_STATUS_DISABLED); +} +static inline int fdt_status_fail_by_compatible(void *fdt, const char *compat) +{ + return fdt_set_status_by_compatible(fdt, compat, FDT_STATUS_FAIL); +} + +int fdt_set_status_by_pathf(void *fdt, enum fdt_status status, const char *fmt, + ...) __attribute__ ((format (printf, 3, 4))); +#define fdt_status_okay_by_pathf(fdt, fmt, ...) \ + fdt_set_status_by_pathf((fdt), FDT_STATUS_OKAY, (fmt), ##__VA_ARGS__) +#define fdt_status_disabled_by_pathf(fdt, fmt, ...) \ + fdt_set_status_by_pathf((fdt), FDT_STATUS_DISABLED, (fmt), ##__VA_ARGS__) +#define fdt_status_fail_by_pathf(fdt, fmt, ...) \ + fdt_set_status_by_pathf((fdt), FDT_STATUS_FAIL, (fmt), ##__VA_ARGS__) + /* Helper to read a big number; size is in cells (not bytes) */ static inline u64 fdt_read_number(const fdt32_t *cell, int size) { diff --git a/include/linux/byteorder/swab.h b/include/linux/byteorder/swab.h index 4334fa7..5efc252 100644 --- a/include/linux/byteorder/swab.h +++ b/include/linux/byteorder/swab.h @@ -39,6 +39,10 @@ (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) +#define ___constant_swab16(x) ___swab16(x) +#define ___constant_swab32(x) ___swab32(x) +#define ___constant_swab64(x) ___swab64(x) + /* * provide defaults when no architecture-specific optimization is detected */ diff --git a/include/tpm-v2.h b/include/tpm-v2.h index ceff7d2..4e9dd52 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -512,13 +512,16 @@ u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data, * @dev TPM device * @idx Index of the PCR * @idx_min_sz Minimum size in bytes of the pcrSelect array + * @algorithm Algorithm used, defined in 'enum tpm2_algorithms' * @data Output buffer for contents of the named PCR + * @digest_len len of the data * @updates Optional out parameter: number of updates for this PCR * * @return code of the operation */ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz, - void *data, unsigned int *updates); + u16 algorithm, void *data, u32 digest_len, + unsigned int *updates); /** * Issue a TPM2_GetCapability command. This implementation is limited diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 0937e35..04cb3ef 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -147,7 +147,7 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) if (!obj) return -ENOENT; - devnum = blk_find_max_devnum(IF_TYPE_EFI); + devnum = blk_find_max_devnum(IF_TYPE_EFI_LOADER); if (devnum == -ENODEV) devnum = 0; else if (devnum < 0) @@ -159,8 +159,8 @@ static int efi_bl_bind(efi_handle_t handle, void *interface) sprintf(name, "efiblk#%d", devnum); /* Create driver model udevice for the EFI block io device */ - ret = blk_create_device(parent, "efi_blk", name, IF_TYPE_EFI, devnum, - io->media->block_size, + ret = blk_create_device(parent, "efi_blk", name, IF_TYPE_EFI_LOADER, + devnum, io->media->block_size, (lbaint_t)io->media->last_block, &bdev); if (ret) return ret; @@ -209,6 +209,6 @@ static const struct efi_driver_ops driver_ops = { /* Identify as EFI driver */ U_BOOT_DRIVER(efi_block) = { .name = "EFI block driver", - .id = UCLASS_EFI, + .id = UCLASS_EFI_LOADER, .ops = &driver_ops, }; diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index 382c2b4..b01ce89 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -308,7 +308,7 @@ efi_status_t efi_driver_init(void) log_debug("Initializing EFI driver framework\n"); for (drv = ll_entry_start(struct driver, driver); drv < ll_entry_end(struct driver, driver); ++drv) { - if (drv->id == UCLASS_EFI) { + if (drv->id == UCLASS_EFI_LOADER) { ret = efi_add_driver(drv); if (ret != EFI_SUCCESS) { log_err("Failed to add EFI driver %s\n", @@ -328,7 +328,7 @@ efi_status_t efi_driver_init(void) */ static int efi_uc_init(struct uclass *class) { - log_debug("Initializing UCLASS_EFI\n"); + log_debug("Initializing UCLASS_EFI_LOADER\n"); return 0; } @@ -340,13 +340,13 @@ static int efi_uc_init(struct uclass *class) */ static int efi_uc_destroy(struct uclass *class) { - log_debug("Destroying UCLASS_EFI\n"); + log_debug("Destroying UCLASS_EFI_LOADER\n"); return 0; } UCLASS_DRIVER(efi) = { .name = "efi", - .id = UCLASS_EFI, + .id = UCLASS_EFI_LOADER, .init = efi_uc_init, .destroy = efi_uc_destroy, }; diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 700dc83..24f9a2b 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -308,6 +308,8 @@ config EFI_TCG2_PROTOCOL bool "EFI_TCG2_PROTOCOL support" default y depends on TPM_V2 + # Sandbox TPM currently fails on GetCapabilities needed for TCG2 + depends on !SANDBOX select SHA1 select SHA256 select SHA384 diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 8492b73..20b6969 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -3016,9 +3016,12 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { ret = efi_tcg2_measure_efi_app_invocation(image_obj); - if (ret != EFI_SUCCESS) { - log_warning("tcg2 measurement fails(0x%lx)\n", - ret); + if (ret == EFI_SECURITY_VIOLATION) { + /* + * TCG2 Protocol is installed but no TPM device found, + * this is not expected. + */ + return EFI_EXIT(EFI_SECURITY_VIOLATION); } } } diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index eb95580..773bd06 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -934,9 +934,16 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, #if CONFIG_IS_ENABLED(EFI_TCG2_PROTOCOL) /* Measure an PE/COFF image */ - if (tcg2_measure_pe_image(efi, efi_size, handle, - loaded_image_info)) - log_err("PE image measurement failed\n"); + ret = tcg2_measure_pe_image(efi, efi_size, handle, loaded_image_info); + if (ret == EFI_SECURITY_VIOLATION) { + /* + * TCG2 Protocol is installed but no TPM device found, + * this is not expected. + */ + log_err("PE image measurement failed, no tpm device found\n"); + goto err; + } + #endif /* Copy PE headers */ diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 1aba71c..49172e3 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -241,6 +241,10 @@ efi_status_t efi_init_obj_list(void) ret = efi_tcg2_register(); if (ret != EFI_SUCCESS) goto out; + + ret = efi_tcg2_do_initial_measurement(); + if (ret == EFI_SECURITY_VIOLATION) + goto out; } /* Secure boot */ diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 8c1f22e..0ae07ef 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -153,6 +153,15 @@ static u16 alg_to_len(u16 hash_alg) return 0; } +static bool is_tcg2_protocol_installed(void) +{ + struct efi_handler *handler; + efi_status_t ret; + + ret = efi_search_protocol(efi_root, &efi_guid_tcg2_protocol, &handler); + return ret == EFI_SUCCESS; +} + static u32 tcg_event_final_size(struct tpml_digest_values *digest_list) { u32 len; @@ -199,6 +208,44 @@ static efi_status_t tcg2_pcr_extend(struct udevice *dev, u32 pcr_index, return EFI_SUCCESS; } +/* tcg2_pcr_read - Read PCRs for a TPM2 device for a given tpml_digest_values + * + * @dev: device + * @pcr_index: PCR index + * @digest_list: list of digest algorithms to extend + * + * @Return: status code + */ +static efi_status_t tcg2_pcr_read(struct udevice *dev, u32 pcr_index, + struct tpml_digest_values *digest_list) +{ + struct tpm_chip_priv *priv; + unsigned int updates, pcr_select_min; + u32 rc; + size_t i; + + priv = dev_get_uclass_priv(dev); + if (!priv) + return EFI_DEVICE_ERROR; + + pcr_select_min = priv->pcr_select_min; + + for (i = 0; i < digest_list->count; i++) { + u16 hash_alg = digest_list->digests[i].hash_alg; + u8 *digest = (u8 *)&digest_list->digests[i].digest; + + rc = tpm2_pcr_read(dev, pcr_index, pcr_select_min, + hash_alg, digest, alg_to_len(hash_alg), + &updates); + if (rc) { + EFI_PRINT("Failed to read PCR\n"); + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + /* put_event - Append an agile event to an eventlog * * @pcr_index: PCR index @@ -325,6 +372,45 @@ __weak efi_status_t platform_get_tpm2_device(struct udevice **dev) } /** + * platform_get_eventlog() - retrieve the eventlog address and size + * + * This function retrieves the eventlog address and size if the underlying + * firmware has done some measurements and passed them. + * + * This function may be overridden based on platform specific method of + * passing the eventlog address and size. + * + * @dev: udevice + * @addr: eventlog address + * @sz: eventlog size + * Return: status code + */ +__weak efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, + u32 *sz) +{ + const u64 *basep; + const u32 *sizep; + + basep = dev_read_prop(dev, "tpm_event_log_addr", NULL); + if (!basep) + return EFI_NOT_FOUND; + + *addr = be64_to_cpup((__force __be64 *)basep); + + sizep = dev_read_prop(dev, "tpm_event_log_size", NULL); + if (!sizep) + return EFI_NOT_FOUND; + + *sz = be32_to_cpup((__force __be32 *)sizep); + if (*sz == 0) { + log_debug("event log empty\n"); + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** * tpm2_get_max_command_size() - get the supported max command size * * @dev: TPM device @@ -886,9 +972,12 @@ efi_status_t tcg2_measure_pe_image(void *efi, u64 efi_size, IMAGE_NT_HEADERS32 *nt; struct efi_handler *handler; + if (!is_tcg2_protocol_installed()) + return EFI_SUCCESS; + ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) - return ret; + return EFI_SECURITY_VIOLATION; switch (handle->image_type) { case IMAGE_SUBSYSTEM_EFI_APPLICATION: @@ -1182,6 +1271,318 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = { }; /** + * parse_event_log_header() - Parse and verify the event log header fields + * + * @buffer: Pointer to the start of the eventlog + * @size: Size of the eventlog + * @pos: Return offset of the next event in buffer right + * after the event header i.e specID + * + * Return: status code + */ +static efi_status_t parse_event_log_header(void *buffer, u32 size, u32 *pos) +{ + struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer; + int i = 0; + + if (size < sizeof(*event_header)) + return EFI_COMPROMISED_DATA; + + if (get_unaligned_le32(&event_header->pcr_index) != 0 || + get_unaligned_le32(&event_header->event_type) != EV_NO_ACTION) + return EFI_COMPROMISED_DATA; + + for (i = 0; i < sizeof(event_header->digest); i++) { + if (event_header->digest[i]) + return EFI_COMPROMISED_DATA; + } + + *pos += sizeof(*event_header); + + return EFI_SUCCESS; +} + +/** + * parse_specid_event() - Parse and verify the specID Event in the eventlog + * + * @dev: udevice + * @buffer: Pointer to the start of the eventlog + * @log_size: Size of the eventlog + * @pos: [in] Offset of specID event in the eventlog buffer + * [out] Return offset of the next event in the buffer + * after the specID + * @digest_list: list of digests in the event + * + * Return: status code + * @pos Offset in the eventlog where the specID event ends + * @digest_list: list of digests in the event + */ +static efi_status_t parse_specid_event(struct udevice *dev, void *buffer, + u32 log_size, u32 *pos, + struct tpml_digest_values *digest_list) +{ + struct tcg_efi_spec_id_event *spec_event; + struct tcg_pcr_event *event_header = (struct tcg_pcr_event *)buffer; + size_t spec_event_size; + u32 active = 0, supported = 0, pcr_count = 0, alg_count = 0; + u32 spec_active = 0; + u16 hash_alg; + u8 vendor_sz; + int err, i; + + if (*pos >= log_size || (*pos + sizeof(*spec_event)) > log_size) + return EFI_COMPROMISED_DATA; + + /* Check specID event data */ + spec_event = (struct tcg_efi_spec_id_event *)((uintptr_t)buffer + *pos); + /* Check for signature */ + if (memcmp(spec_event->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03, + sizeof(TCG_EFI_SPEC_ID_EVENT_SIGNATURE_03))) { + log_err("specID Event: Signature mismatch\n"); + return EFI_COMPROMISED_DATA; + } + + if (spec_event->spec_version_minor != + TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MINOR_TPM2 || + spec_event->spec_version_major != + TCG_EFI_SPEC_ID_EVENT_SPEC_VERSION_MAJOR_TPM2) + return EFI_COMPROMISED_DATA; + + if (spec_event->number_of_algorithms > MAX_HASH_COUNT || + spec_event->number_of_algorithms < 1) { + log_err("specID Event: Number of algorithms incorrect\n"); + return EFI_COMPROMISED_DATA; + } + + alg_count = spec_event->number_of_algorithms; + + err = tpm2_get_pcr_info(dev, &supported, &active, &pcr_count); + if (err) + return EFI_DEVICE_ERROR; + + digest_list->count = 0; + /* + * We have to take care that the sequence of algorithms that we record + * in digest_list matches the sequence in eventlog. + */ + for (i = 0; i < alg_count; i++) { + hash_alg = + get_unaligned_le16(&spec_event->digest_sizes[i].algorithm_id); + + if (!(supported & alg_to_mask(hash_alg))) { + log_err("specID Event: Unsupported algorithm\n"); + return EFI_COMPROMISED_DATA; + } + digest_list->digests[digest_list->count++].hash_alg = hash_alg; + + spec_active |= alg_to_mask(hash_alg); + } + + /* + * TCG specification expects the event log to have hashes for all + * active PCR's + */ + if (spec_active != active) { + /* + * Previous stage bootloader should know all the active PCR's + * and use them in the Eventlog. + */ + log_err("specID Event: All active hash alg not present\n"); + return EFI_COMPROMISED_DATA; + } + + /* + * the size of the spec event and placement of vendor_info_size + * depends on supported algoriths + */ + spec_event_size = + offsetof(struct tcg_efi_spec_id_event, digest_sizes) + + alg_count * sizeof(spec_event->digest_sizes[0]); + + if (*pos + spec_event_size >= log_size) + return EFI_COMPROMISED_DATA; + + vendor_sz = *(uint8_t *)((uintptr_t)buffer + *pos + spec_event_size); + + spec_event_size += sizeof(vendor_sz) + vendor_sz; + *pos += spec_event_size; + + if (get_unaligned_le32(&event_header->event_size) != spec_event_size) { + log_err("specID event: header event size mismatch\n"); + /* Right way to handle this can be to call SetActive PCR's */ + return EFI_COMPROMISED_DATA; + } + + return EFI_SUCCESS; +} + +/** + * tcg2_parse_event() - Parse the event in the eventlog + * + * @dev: udevice + * @buffer: Pointer to the start of the eventlog + * @log_size: Size of the eventlog + * @offset: [in] Offset of the event in the eventlog buffer + * [out] Return offset of the next event in the buffer + * @digest_list: list of digests in the event + * @pcr Index of the PCR in the event + * + * Return: status code + */ +static efi_status_t tcg2_parse_event(struct udevice *dev, void *buffer, + u32 log_size, u32 *offset, + struct tpml_digest_values *digest_list, + u32 *pcr) +{ + struct tcg_pcr_event2 *event = NULL; + u32 count, size, event_size; + size_t pos; + + event_size = tcg_event_final_size(digest_list); + if (*offset >= log_size || *offset + event_size > log_size) { + log_err("Event exceeds log size\n"); + return EFI_COMPROMISED_DATA; + } + + event = (struct tcg_pcr_event2 *)((uintptr_t)buffer + *offset); + *pcr = get_unaligned_le32(&event->pcr_index); + + /* get the count */ + count = get_unaligned_le32(&event->digests.count); + if (count != digest_list->count) + return EFI_COMPROMISED_DATA; + + pos = offsetof(struct tcg_pcr_event2, digests); + pos += offsetof(struct tpml_digest_values, digests); + + for (int i = 0; i < digest_list->count; i++) { + u16 alg; + u16 hash_alg = digest_list->digests[i].hash_alg; + u8 *digest = (u8 *)&digest_list->digests[i].digest; + + alg = get_unaligned_le16((void *)((uintptr_t)event + pos)); + + if (alg != hash_alg) + return EFI_COMPROMISED_DATA; + + pos += offsetof(struct tpmt_ha, digest); + memcpy(digest, (void *)((uintptr_t)event + pos), alg_to_len(hash_alg)); + pos += alg_to_len(hash_alg); + } + + size = get_unaligned_le32((void *)((uintptr_t)event + pos)); + event_size += size; + pos += sizeof(u32); /* tcg_pcr_event2 event_size*/ + pos += size; + + /* make sure the calculated buffer is what we checked against */ + if (pos != event_size) + return EFI_COMPROMISED_DATA; + + if (pos > log_size) + return EFI_COMPROMISED_DATA; + + *offset += pos; + + return EFI_SUCCESS; +} + +/** + * tcg2_get_fw_eventlog() - Get the eventlog address and size + * + * If the previous firmware has passed some eventlog, this function get it's + * location and check for it's validity. + * + * @dev: udevice + * @log_buffer: eventlog address + * @log_sz: eventlog size + * + * Return: status code + */ +static efi_status_t tcg2_get_fw_eventlog(struct udevice *dev, void *log_buffer, + size_t *log_sz) +{ + struct tpml_digest_values digest_list; + void *buffer; + efi_status_t ret; + u32 pcr, pos; + u64 base; + u32 sz; + bool extend_pcr = false; + int i; + + ret = platform_get_eventlog(dev, &base, &sz); + if (ret != EFI_SUCCESS) + return ret; + + if (sz > TPM2_EVENT_LOG_SIZE) + return EFI_VOLUME_FULL; + + buffer = (void *)(uintptr_t)base; + pos = 0; + /* Parse the eventlog to check for its validity */ + ret = parse_event_log_header(buffer, sz, &pos); + if (ret) + return ret; + + ret = parse_specid_event(dev, buffer, sz, &pos, &digest_list); + if (ret) { + log_err("Error parsing SPEC ID Event\n"); + return ret; + } + + ret = tcg2_pcr_read(dev, 0, &digest_list); + if (ret) { + log_err("Error reading PCR 0\n"); + return ret; + } + + /* + * If PCR0 is 0, previous firmware didn't have the capability + * to extend the PCR. In this scenario, extend the PCR as + * the eventlog is parsed. + */ + for (i = 0; i < digest_list.count; i++) { + u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 }; + u16 hash_alg = digest_list.digests[i].hash_alg; + + if (!memcmp((u8 *)&digest_list.digests[i].digest, hash_buf, + alg_to_len(hash_alg))) + extend_pcr = true; + } + + while (pos < sz) { + ret = tcg2_parse_event(dev, buffer, sz, &pos, &digest_list, + &pcr); + if (ret) { + log_err("Error parsing event\n"); + return ret; + } + if (extend_pcr) { + ret = tcg2_pcr_extend(dev, pcr, &digest_list); + if (ret != EFI_SUCCESS) { + log_err("Error in extending PCR\n"); + return ret; + } + + /* Clear the digest for next event */ + for (i = 0; i < digest_list.count; i++) { + u16 hash_alg = digest_list.digests[i].hash_alg; + u8 *digest = + (u8 *)&digest_list.digests[i].digest; + + memset(digest, 0, alg_to_len(hash_alg)); + } + } + } + + memcpy(log_buffer, buffer, sz); + *log_sz = sz; + + return ret; +} + +/** * create_specid_event() - Create the first event in the eventlog * * @dev: tpm device @@ -1275,6 +1676,14 @@ void tcg2_uninit(void) event_log.buffer = NULL; efi_free_pool(event_log.final_buffer); event_log.final_buffer = NULL; + + if (!is_tcg2_protocol_installed()) + return; + + ret = efi_remove_protocol(efi_root, &efi_guid_tcg2_protocol, + (void *)&efi_tcg2_protocol); + if (ret != EFI_SUCCESS) + log_err("Failed to remove EFI TCG2 protocol\n"); } /** @@ -1313,69 +1722,6 @@ out: } /** - * efi_init_event_log() - initialize an eventlog - */ -static efi_status_t efi_init_event_log(void) -{ - /* - * vendor_info_size is currently set to 0, we need to change the length - * and allocate the flexible array member if this changes - */ - struct tcg_pcr_event *event_header = NULL; - struct udevice *dev; - size_t spec_event_size; - efi_status_t ret; - - ret = platform_get_tpm2_device(&dev); - if (ret != EFI_SUCCESS) - goto out; - - ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE, - (void **)&event_log.buffer); - if (ret != EFI_SUCCESS) - goto out; - - /* - * initialize log area as 0xff so the OS can easily figure out the - * last log entry - */ - memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE); - event_log.pos = 0; - event_log.last_event_size = 0; - event_log.get_event_called = false; - event_log.ebs_called = false; - event_log.truncated = false; - - /* - * The log header is defined to be in SHA1 event log entry format. - * Setup event header - */ - event_header = (struct tcg_pcr_event *)event_log.buffer; - put_unaligned_le32(0, &event_header->pcr_index); - put_unaligned_le32(EV_NO_ACTION, &event_header->event_type); - memset(&event_header->digest, 0, sizeof(event_header->digest)); - ret = create_specid_event(dev, (void *)((uintptr_t)event_log.buffer + sizeof(*event_header)), - &spec_event_size); - if (ret != EFI_SUCCESS) - goto free_pool; - put_unaligned_le32(spec_event_size, &event_header->event_size); - event_log.pos = spec_event_size + sizeof(*event_header); - event_log.last_event_size = event_log.pos; - - ret = create_final_event(); - if (ret != EFI_SUCCESS) - goto free_pool; - -out: - return ret; - -free_pool: - efi_free_pool(event_log.buffer); - event_log.buffer = NULL; - return ret; -} - -/** * tcg2_measure_event() - common function to add event log and extend PCR * * @dev: TPM device @@ -1428,6 +1774,93 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev) } /** + * efi_init_event_log() - initialize an eventlog + * + * Return: status code + */ +static efi_status_t efi_init_event_log(void) +{ + /* + * vendor_info_size is currently set to 0, we need to change the length + * and allocate the flexible array member if this changes + */ + struct tcg_pcr_event *event_header = NULL; + struct udevice *dev; + size_t spec_event_size; + efi_status_t ret; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return ret; + + ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE, + (void **)&event_log.buffer); + if (ret != EFI_SUCCESS) + return ret; + + /* + * initialize log area as 0xff so the OS can easily figure out the + * last log entry + */ + memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE); + + /* + * The log header is defined to be in SHA1 event log entry format. + * Setup event header + */ + event_header = (struct tcg_pcr_event *)event_log.buffer; + event_log.pos = 0; + event_log.last_event_size = 0; + event_log.get_event_called = false; + event_log.ebs_called = false; + event_log.truncated = false; + + /* + * Check if earlier firmware have passed any eventlog. Different + * platforms can use different ways to do so. + */ + ret = tcg2_get_fw_eventlog(dev, event_log.buffer, &event_log.pos); + /* + * If earlier firmware hasn't passed any eventlog, go ahead and + * create the eventlog header. + */ + if (ret == EFI_NOT_FOUND) { + put_unaligned_le32(0, &event_header->pcr_index); + put_unaligned_le32(EV_NO_ACTION, &event_header->event_type); + memset(&event_header->digest, 0, sizeof(event_header->digest)); + ret = create_specid_event(dev, + (void *)((uintptr_t)event_log.buffer + + sizeof(*event_header)), + &spec_event_size); + if (ret != EFI_SUCCESS) + goto free_pool; + put_unaligned_le32(spec_event_size, &event_header->event_size); + event_log.pos = spec_event_size + sizeof(*event_header); + event_log.last_event_size = event_log.pos; + + /* + * Add SCRTM version to the log if previous firmmware + * doesn't pass an eventlog. + */ + ret = efi_append_scrtm_version(dev); + } + + if (ret != EFI_SUCCESS) + goto free_pool; + + ret = create_final_event(); + if (ret != EFI_SUCCESS) + goto free_pool; + + return ret; + +free_pool: + efi_free_pool(event_log.buffer); + event_log.buffer = NULL; + return ret; +} + +/** * tcg2_measure_variable() - add variable event log and extend PCR * * @dev: TPM device @@ -1759,12 +2192,15 @@ efi_status_t efi_tcg2_measure_efi_app_invocation(struct efi_loaded_image_obj *ha u32 event = 0; struct smbios_entry *entry; + if (!is_tcg2_protocol_installed()) + return EFI_SUCCESS; + if (tcg2_efi_app_invoked) return EFI_SUCCESS; ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) - return ret; + return EFI_SECURITY_VIOLATION; ret = tcg2_measure_boot_variable(dev); if (ret != EFI_SUCCESS) @@ -1809,6 +2245,9 @@ efi_status_t efi_tcg2_measure_efi_app_exit(void) efi_status_t ret; struct udevice *dev; + if (!is_tcg2_protocol_installed()) + return EFI_SUCCESS; + ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) return ret; @@ -1834,6 +2273,12 @@ efi_tcg2_notify_exit_boot_services(struct efi_event *event, void *context) EFI_ENTRY("%p, %p", event, context); event_log.ebs_called = true; + + if (!is_tcg2_protocol_installed()) { + ret = EFI_SUCCESS; + goto out; + } + ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) goto out; @@ -1863,6 +2308,9 @@ efi_status_t efi_tcg2_notify_exit_boot_services_failed(void) struct udevice *dev; efi_status_t ret; + if (!is_tcg2_protocol_installed()) + return EFI_SUCCESS; + ret = platform_get_tpm2_device(&dev); if (ret != EFI_SUCCESS) goto out; @@ -1933,11 +2381,36 @@ error: } /** + * efi_tcg2_do_initial_measurement() - do initial measurement + * + * Return: status code + */ +efi_status_t efi_tcg2_do_initial_measurement(void) +{ + efi_status_t ret; + struct udevice *dev; + + if (!is_tcg2_protocol_installed()) + return EFI_SUCCESS; + + ret = platform_get_tpm2_device(&dev); + if (ret != EFI_SUCCESS) + return EFI_SECURITY_VIOLATION; + + ret = tcg2_measure_secure_boot_variable(dev); + if (ret != EFI_SUCCESS) + goto out; + +out: + return ret; +} + +/** * efi_tcg2_register() - register EFI_TCG2_PROTOCOL * * If a TPM2 device is available, the TPM TCG2 Protocol is registered * - * Return: An error status is only returned if adding the protocol fails. + * Return: status code */ efi_status_t efi_tcg2_register(void) { @@ -1960,10 +2433,6 @@ efi_status_t efi_tcg2_register(void) } ret = efi_init_event_log(); - if (ret != EFI_SUCCESS) - goto fail; - - ret = efi_append_scrtm_version(dev); if (ret != EFI_SUCCESS) { tcg2_uninit(); goto fail; @@ -1984,24 +2453,9 @@ efi_status_t efi_tcg2_register(void) goto fail; } - ret = tcg2_measure_secure_boot_variable(dev); - if (ret != EFI_SUCCESS) { - tcg2_uninit(); - goto fail; - } - return ret; fail: log_err("Cannot install EFI_TCG2_PROTOCOL\n"); - /* - * Return EFI_SUCCESS and don't stop the EFI subsystem. - * That's done for 2 reasons - * - If the protocol is not installed the PCRs won't be extended. So - * someone later in the boot flow will notice that and take the - * necessary actions. - * - The TPM sandbox is limited and we won't be able to run any efi - * related tests with TCG2 enabled - */ - return EFI_SUCCESS; + return ret; } diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index 2e7b27b..1bf6278 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -254,7 +254,8 @@ u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data, } u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz, - void *data, unsigned int *updates) + u16 algorithm, void *data, u32 digest_len, + unsigned int *updates) { u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8)); u8 command_v2[COMMAND_BUFFER_SIZE] = { @@ -264,7 +265,7 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz, /* TPML_PCR_SELECTION */ tpm_u32(1), /* Number of selections */ - tpm_u16(TPM2_ALG_SHA256), /* Algorithm of the hash */ + tpm_u16(algorithm), /* Algorithm of the hash */ idx_array_sz, /* Array size for selection */ /* bitmap(idx) Selected PCR bitmap */ }; @@ -283,10 +284,13 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz, if (ret) return ret; + if (digest_len > response_len) + return TPM_LIB_ERROR; + if (unpack_byte_string(response, response_len, "ds", 10, &counter, - response_len - TPM2_DIGEST_LEN, data, - TPM2_DIGEST_LEN)) + response_len - digest_len, data, + digest_len)) return TPM_LIB_ERROR; if (updates) diff --git a/test/dm/Makefile b/test/dm/Makefile index 548649f..d46552f 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_DMA) += dma.o obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi_host.o obj-$(CONFIG_DM_DSA) += dsa.o obj-$(CONFIG_ECDSA_VERIFY) += ecdsa.o +obj-$(CONFIG_EFI_MEDIA_SANDBOX) += efi_media.o obj-$(CONFIG_DM_ETH) += eth.o ifneq ($(CONFIG_EFI_PARTITION),) obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fastboot.o diff --git a/test/dm/efi_media.c b/test/dm/efi_media.c new file mode 100644 index 0000000..e343a0e --- /dev/null +++ b/test/dm/efi_media.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for EFI_MEDIA uclass + * + * Copyright 2021 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <asm/test.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that we can use the EFI_MEDIA uclass */ +static int dm_test_efi_media(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_EFI_MEDIA, &dev)); + + return 0; +} +DM_TEST(dm_test_efi_media, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py index 0161a6e..a48cd32 100644 --- a/test/py/tests/test_efi_selftest.py +++ b/test/py/tests/test_efi_selftest.py @@ -210,3 +210,23 @@ def test_efi_selftest_text_input_ex(u_boot_console): if m != 0: raise Exception('Failures occurred during the EFI selftest') u_boot_console.restart_uboot() + +@pytest.mark.buildconfigspec('cmd_bootefi_selftest') +@pytest.mark.buildconfigspec('efi_tcg2_protocol') +def test_efi_selftest_tcg2(u_boot_console): + """Test the EFI_TCG2 PROTOCOL + + :param u_boot_console: U-Boot console + + This function executes the 'tcg2' unit test. + """ + u_boot_console.restart_uboot() + u_boot_console.run_command(cmd='setenv efi_selftest list') + output = u_boot_console.run_command('bootefi selftest') + assert '\'tcg2\'' in output + u_boot_console.run_command(cmd='setenv efi_selftest tcg2') + u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False) + m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key']) + if m != 0: + raise Exception('Failures occurred during the EFI selftest') + u_boot_console.restart_uboot() diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index 7c89f5f..d2ad6f9 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -186,6 +186,7 @@ def test_tpm2_change_auth(u_boot_console): u_boot_console.run_command('tpm2 clear TPM2_RH_PLATFORM') assert output.endswith('0') +@pytest.mark.buildconfigspec('sandbox') @pytest.mark.buildconfigspec('cmd_tpm_v2') def test_tpm2_get_capability(u_boot_console): """Execute a TPM_GetCapability command. |