Prepare v2022.01-rc4

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEEGjx/cOCPqxcHgJu/FHw5/5Y0tywFAmHArDwACgkQFHw5/5Y0
 tyzxyAv/SjZjoEwG8nu7ptVZqTsZfm+tVwwWmQEBAA40MXy/KSccDtbUwB5GCO6f
 Uvk+qFFDbCkbGZh5VKbQusMmUoB02Xu9zUoSxKxcXL4WfC6Bg5GV/UWN9s8G3Tm6
 4wcP0l8WFcQjjr89UfXugiZH58psvFu6PBbWVY4rMH9gZ5ds0AkNOF0L+HbdVmMR
 a5HBfrcySRY2kiTQuKF+RVlMW6BtaOqJp/XIyy8w6bH09ykMomj/u7z3JP3y9ZzL
 w3FXqCLlIEnvdDcqfWvfjoJ/gm0WcLulgSVpTFGS0jgJpnbeAURtZcuVgj6aPRUW
 FRon+u0tj3wpFjibs2cpyXWd+gw/bLLFpDXx78AUAPjxG31tEKbnR1j8R8wBZJ0B
 TqWZ3pCne/LPOT90y2KW2z6ty2n/yEn6qEFFT9MN9R4L0N+U0er//sYJC/nn/e6u
 fjvQ9OPLbnAfHVrad3ZeIkePrLOIF6XYwNQpsjt9aE2kU9IvV5sTa8TxZuQgasBU
 A46FgXtC
 =MEG2
 -----END PGP SIGNATURE-----

Merge tag 'v2022.01-rc4' into next

Prepare v2022.01-rc4
This commit is contained in:
Tom Rini 2021-12-20 17:12:04 -05:00
commit 4afab30cae
100 changed files with 3201 additions and 869 deletions

View file

@ -728,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>

View file

@ -3,7 +3,7 @@
VERSION = 2022
PATCHLEVEL = 01
SUBLEVEL =
EXTRAVERSION = -rc3
EXTRAVERSION = -rc4
NAME =
# *DOCUMENTATION*

View file

@ -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>;
};
};

View file

@ -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 = <&reg_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 {

View file

@ -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"

View file

@ -21,6 +21,9 @@
serial4 = &hscif2;
serial5 = &scif5;
ethernet0 = &avb;
mmc0 = &sdhi3;
mmc1 = &sdhi0;
mmc2 = &sdhi2;
};
chosen {

View file

@ -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"

View file

@ -22,6 +22,9 @@
serial5 = &scif5;
serial6 = &scif4;
ethernet0 = &avb;
mmc0 = &sdhi3;
mmc1 = &sdhi0;
mmc2 = &sdhi2;
};
chosen {

View file

@ -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"

View file

@ -22,6 +22,9 @@
serial5 = &scif5;
serial6 = &scif4;
ethernet0 = &avb;
mmc0 = &sdhi3;
mmc1 = &sdhi0;
mmc2 = &sdhi2;
};
chosen {

View file

@ -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;
};

View file

@ -13,7 +13,7 @@
/ {
aliases {
mmc0 = &mmc0;
#if CONFIG_MMC_SUNXI_EXTRA_SLOT == 2
#if CONFIG_MMC_SUNXI_SLOT_EXTRA == 2
mmc1 = &mmc2;
#endif
};

View file

@ -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_ */

View file

@ -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_ */

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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;

View file

@ -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;
};
};
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;
};
};
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;
};
};
};
refclk: refclk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <600000000>;
clock-output-names = "msspllclk";
};
ddr: memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x40000000>;
clocks = <&clkcfg CLK_DDRC>;
};
soc: soc {
#address-cells = <2>;
#size-cells = <2>;
compatible = "microchip,mpfs-icicle-kit", "simple-bus";
reserved-memory {
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";
#size-cells = <2>;
#address-cells = <2>;
#address-cells = <1>;
#size-cells = <0>;
phy-handle = <&phy0>;
phy0: ethernet-phy@8 {
reg = <8>;
ti,fifo-depth = <0x01>;
};
fabricbuf0: fabricbuf@0 {
compatible = "shared-dma-pool";
reg = <0x0 0xae000000 0x0 0x2000000>;
label = "fabricbuf0-ddr-c";
};
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";
#address-cells = <1>;
#size-cells = <0>;
phy-handle = <&phy1>;
phy1: ethernet-phy@9 {
reg = <9>;
ti,fifo-depth = <0x01>;
};
fabricbuf1: fabricbuf@1 {
compatible = "shared-dma-pool";
reg = <0x0 0xc0000000 0x0 0x8000000>;
label = "fabricbuf1-ddr-nc";
};
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";
fabricbuf2: fabricbuf@2 {
compatible = "shared-dma-pool";
reg = <0x0 0xd8000000 0x0 0x8000000>;
label = "fabricbuf2-ddr-nc-wcb";
};
};
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>;
};
ddrc_cache_lo: memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x2e000000>;
clocks = <&clkcfg CLK_DDRC>;
status = "okay";
};
ddrc_cache_hi: memory@1000000000 {
device_type = "memory";
reg = <0x10 0x0 0x0 0x40000000>;
clocks = <&clkcfg CLK_DDRC>;
status = "okay";
};
};
&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>;
};
};

View file

@ -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>;
};
};
};

View file

@ -499,6 +499,10 @@
compatible = "sandbox,clk-ccf";
};
efi-media {
compatible = "sandbox,efi-media";
};
eth@10002000 {
compatible = "sandbox,eth";
reg = <0x10002000 0x1000>;

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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",

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -27,6 +27,7 @@
DECLARE_GLOBAL_DATA_PTR;
#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
/**
* image_get_ramdisk - get and verify ramdisk image
* @rd_addr: ramdisk image start address
@ -85,6 +86,7 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, u8 arch,
return rd_hdr;
}
#endif
/*****************************************************************************/
/* Shared dual-format routines */
@ -325,18 +327,16 @@ int genimg_has_config(bootm_headers_t *images)
static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch,
ulong *rd_datap, ulong *rd_lenp)
{
ulong rd_addr = 0;
ulong rd_addr;
char *buf;
const char *fit_uname_config = images->fit_uname_cfg;
const char *fit_uname_ramdisk = NULL;
bool processed;
int rd_noffset;
if (select) {
ulong default_addr;
bool done = true;
#if CONFIG_IS_ENABLED(FIT)
const char *fit_uname_config = images->fit_uname_cfg;
const char *fit_uname_ramdisk = NULL;
int rd_noffset;
if (CONFIG_IS_ENABLED(FIT)) {
if (select) {
ulong default_addr;
/*
* If the init ramdisk comes from the FIT image and
* the FIT image address is omitted in the command
@ -348,8 +348,8 @@ static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch,
else
default_addr = image_load_addr;
if (fit_parse_conf(select, default_addr, &rd_addr,
&fit_uname_config)) {
if (fit_parse_conf(select, default_addr,
&rd_addr, &fit_uname_config)) {
debug("* ramdisk: config '%s' from image at 0x%08lx\n",
fit_uname_config, rd_addr);
} else if (fit_parse_subimage(select, default_addr,
@ -357,58 +357,60 @@ static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch,
&fit_uname_ramdisk)) {
debug("* ramdisk: subimage '%s' from image at 0x%08lx\n",
fit_uname_ramdisk, rd_addr);
} else {
done = false;
} else
#endif
{
rd_addr = hextoul(select, NULL);
debug("* ramdisk: cmdline image address = 0x%08lx\n",
rd_addr);
}
#if CONFIG_IS_ENABLED(FIT)
} else {
/* use FIT configuration provided in first bootm
* command argument. If the property is not defined,
* quit silently (with -ENOPKG)
*/
rd_addr = map_to_sysmem(images->fit_hdr_os);
rd_noffset = fit_get_node_from_config(images,
FIT_RAMDISK_PROP,
rd_addr);
if (rd_noffset == -ENOENT)
return -ENOPKG;
else if (rd_noffset < 0)
return rd_noffset;
}
if (!done) {
rd_addr = hextoul(select, NULL);
debug("* ramdisk: cmdline image address = 0x%08lx\n",
rd_addr);
}
} else if (CONFIG_IS_ENABLED(FIT)) {
/* use FIT configuration provided in first bootm
* command argument. If the property is not defined,
* quit silently (with -ENOPKG )
*/
rd_addr = map_to_sysmem(images->fit_hdr_os);
rd_noffset = fit_get_node_from_config(images, FIT_RAMDISK_PROP,
rd_addr);
if (rd_noffset == -ENOENT)
return -ENOPKG;
else if (rd_noffset < 0)
return rd_noffset;
}
#endif
/*
* Check if there is an initrd image at the
* address provided in the second bootm argument
* check image type, for FIT images get FIT node.
*/
buf = map_sysmem(rd_addr, 0);
processed = false;
switch (genimg_get_format(buf)) {
case IMAGE_FORMAT_LEGACY:
if (CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)) {
/*
* Check if there is an initrd image at the
* address provided in the second bootm argument
* check image type, for FIT images get FIT node.
*/
buf = map_sysmem(rd_addr, 0);
switch (genimg_get_format(buf)) {
#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT)
case IMAGE_FORMAT_LEGACY: {
const image_header_t *rd_hdr;
printf("## Loading init Ramdisk from Legacy Image at %08lx ...\n",
rd_addr);
bootstage_mark(BOOTSTAGE_ID_CHECK_RAMDISK);
rd_hdr = image_get_ramdisk(rd_addr, arch, images->verify);
rd_hdr = image_get_ramdisk(rd_addr, arch,
images->verify);
if (!rd_hdr)
return -ENOENT;
*rd_datap = image_get_data(rd_hdr);
*rd_lenp = image_get_data_size(rd_hdr);
processed = true;
break;
}
break;
case IMAGE_FORMAT_FIT:
if (CONFIG_IS_ENABLED(FIT)) {
rd_noffset = fit_image_load(images, rd_addr,
&fit_uname_ramdisk,
#endif
#if CONFIG_IS_ENABLED(FIT)
case IMAGE_FORMAT_FIT:
rd_noffset = fit_image_load(images,
rd_addr, &fit_uname_ramdisk,
&fit_uname_config, arch,
IH_TYPE_RAMDISK,
BOOTSTAGE_ID_FIT_RD_START,
@ -420,36 +422,29 @@ static int select_ramdisk(bootm_headers_t *images, const char *select, u8 arch,
images->fit_hdr_rd = map_sysmem(rd_addr, 0);
images->fit_uname_rd = fit_uname_ramdisk;
images->fit_noffset_rd = rd_noffset;
processed = true;
}
break;
case IMAGE_FORMAT_ANDROID:
if (IS_ENABLED(CONFIG_ANDROID_BOOT_IMAGE)) {
break;
#endif
#ifdef CONFIG_ANDROID_BOOT_IMAGE
case IMAGE_FORMAT_ANDROID:
android_image_get_ramdisk((void *)images->os.start,
rd_datap, rd_lenp);
processed = true;
}
break;
}
break;
#endif
default:
if (IS_ENABLED(CONFIG_SUPPORT_RAW_INITRD)) {
char *end = NULL;
if (!processed) {
if (IS_ENABLED(CONFIG_SUPPORT_RAW_INITRD)) {
char *end = NULL;
if (select)
end = strchr(select, ':');
if (end) {
*rd_lenp = hextoul(++end, NULL);
*rd_datap = rd_addr;
processed = true;
if (select)
end = strchr(select, ':');
if (end) {
*rd_lenp = hextoul(++end, NULL);
*rd_datap = rd_addr;
break;
}
}
}
if (!processed) {
puts("Wrong Ramdisk Image Format\n");
return -EINVAL;
}
}
return 0;
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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",
@ -427,7 +430,8 @@ int blk_get_device_by_str(const char *ifname, const char *dev_hwpart_str,
* Always should be done, otherwise hw partition 0 will return stale
* data after displaying a non-zero hw partition.
*/
part_init(*dev_desc);
if ((*dev_desc)->if_type == IF_TYPE_MMC)
part_init(*dev_desc);
#endif
cleanup:

View file

@ -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

View file

@ -0,0 +1,78 @@
Calxeda Highbank/Midway board support
=====================================
The Calxeda ECX-1000 ("Highbank") and ECX-2000 ("Midway") were ARM based
servers, providing high-density cluster systems. A single motherboard could
host between 12 and 48 nodes, each with their own quad-core ARMv7
processor, private DRAM and peripherals, connected through a high-bandwith
and low-latency "fabric" network. Multiple motherboards could be connected
together, to extend this fabric.
For the purpose of U-Boot we just care about a single node, this can be
used as a single system, just using the fabric to connect to some Ethernet
network. Each node boots on its own, either from a local hard disk, or
via the network.
The earlier ECX-1000 nodes ("Highbank") contain four ARM Cortex-A9 cores,
a Cortex-M3 system controller, three 10GBit/s MACs and five SATA
controllers. The DRAM is limited to 4GB.
The later ECX-2000 nodes ("Midway") use four Cortex-A15 cores, alongside
two Cortex-A7 management cores, and support up to 32GB of DRAM, while
keeping the other peripherals.
For the purpose of U-Boot those two SoCs are very similar, so we offer
one build target. The subtle differences are handled at runtime.
Calxeda as a company is long defunct, and the remaining systems are
considered legacy at this point.
Bgilding U-Boot
---------------
There is only one defconfig to cover both systems::
$ make highbank_defconfig
$ make
This will create ``u-boot.bin``, which could become part of the firmware update
package, or could be chainloaded by the existing U-Boot, see below for more
details.
Boot process
------------
Upon powering up a node (which would be controlled by some BMC style
management controller on the motherboard), the system controller ("ECME")
would start and do some system initialisation (fabric registration,
DRAM init, clock setup). It would load the device tree binary, some secure
monitor code (``a9boot``/``a15boot``) and a U-Boot binary from SPI flash
into DRAM, then power up the actual application cores (ARM Cortex-A9/A15).
They would start executing ``a9boot``/``a15boot``, registering the PSCI SMC
handlers, then dropping into U-Boot, but in non-secure state (HYP mode on
the A15s).
U-Boot would act as a mere loader, trying to find some ``boot.scr`` file on
the local hard disks, or reverting to PXE boot.
Updating U-Boot
---------------
The U-Boot binary is loaded from SPI flash, which is controlled exclusively
by the ECME. This can be reached via IPMI using the LANplus transport protocol.
Updating the SPI flash content requires vendor specific additions to the
IPMI protocol, support for which was never upstreamed to ipmitool or
FreeIPMI. Some older repositories for `ipmitool`_, the `pyipmi`_ library and
a Python `management script`_ to update the SPI flash can be found on Github.
A simpler and safer way to get an up-to-date U-Boot running, is chainloading
it via the legacy U-Boot::
$ mkimage -A arm -O u-boot -T standalone -C none -a 0x8000 -e 0x8000 \
-n U-Boot -d u-boot.bin u-boot-highbank.img
Then load this image file, either from hard disk, or via TFTP, from the
existing U-Boot, and execute it with bootm::
=> tftpboot 0x8000 u-boot-highbank.img
=> bootm
.. _`ipmitool`: https://github.com/Cynerva/ipmitool
.. _`pyipmi`: https://pypi.org/project/pyipmi/
.. _`management script`: https://github.com/Cynerva/cxmanage

View file

@ -0,0 +1,9 @@
.. SPDX-License-Identifier: GPL-2.0+
Highbank
========
.. toctree::
:maxdepth: 2
highbank

View file

@ -16,6 +16,7 @@ Board-specific doc
coreboot/index
emulation/index
google/index
highbank/index
intel/index
kontron/index
microchip/index

View file

@ -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
~~~~~~~~~

View file

@ -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.

View file

@ -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::

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,
};
@ -670,6 +672,19 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name,
return 0;
}
int blk_probe_or_unbind(struct udevice *dev)
{
int ret;
ret = device_probe(dev);
if (ret) {
log_debug("probing %s failed\n", dev->name);
device_unbind(dev);
}
return ret;
}
int blk_unbind_all(int if_type)
{
struct uclass *uc;

View file

@ -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,
};

115
drivers/block/efi_blk.c Normal file
View file

@ -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),
};

View file

@ -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,
};

View file

@ -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"

View file

@ -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);
}
}

View file

@ -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)

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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)
{

View file

@ -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;
}

View file

@ -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 {

View file

@ -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>

View file

@ -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");

View file

@ -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

View file

@ -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

482
drivers/i2c/i2c-microchip.c Normal file
View file

@ -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 = &reg;
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),
};

View file

@ -860,6 +860,9 @@ static int mvtwsi_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
{
struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
struct i2c_msg *dmsg, *omsg, dummy;
u8 *addr_buf_ptr;
u8 addr_buf[4];
int i;
memset(&dummy, 0, sizeof(struct i2c_msg));
@ -873,12 +876,17 @@ static int mvtwsi_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
omsg = nmsgs == 1 ? &dummy : msg;
dmsg = nmsgs == 1 ? msg : msg + 1;
/* We need to swap the register address if its size is > 1 */
addr_buf_ptr = &addr_buf[0];
for (i = omsg->len; i > 0; i--)
*addr_buf_ptr++ = omsg->buf[i - 1];
if (dmsg->flags & I2C_M_RD)
return __twsi_i2c_read(dev->base, dmsg->addr, omsg->buf,
return __twsi_i2c_read(dev->base, dmsg->addr, addr_buf,
omsg->len, dmsg->buf, dmsg->len,
dev->tick);
else
return __twsi_i2c_write(dev->base, dmsg->addr, omsg->buf,
return __twsi_i2c_write(dev->base, dmsg->addr, addr_buf,
omsg->len, dmsg->buf, dmsg->len,
dev->tick);
}

View file

@ -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);

View file

@ -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);

View file

@ -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)&microchip_config },
{ }
};

View file

@ -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, &eth->clk);
ret = clk_get_bulk(dev, &eth->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(&eth->clk);
ret = clk_enable_bulk(&eth->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(&eth->clk);
clk_release_bulk(&eth->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(&eth->clk);
clk_release_bulk(&eth->clks);
free(eth->phydev);
mdio_unregister(eth->bus);

View file

@ -193,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;
};
@ -380,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);
@ -567,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);
@ -821,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;

View file

@ -89,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];
};
/*
@ -168,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;
}
/*
@ -248,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 */
@ -276,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;
}
/*
@ -385,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;

View file

@ -10,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;
@ -214,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
@ -261,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;
}
@ -306,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)
{

View file

@ -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;

View file

@ -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 = {

View file

@ -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 */
};
@ -369,6 +370,18 @@ int blk_create_devicef(struct udevice *parent, const char *drv_name,
const char *name, int if_type, int devnum, int blksz,
lbaint_t lba, struct udevice **devp);
/**
* blk_probe_or_unbind() - Try to probe
*
* Try to probe the device, primarily for enumerating partitions.
* If it fails, the device itself is unbound since it means that it won't
* work any more.
*
* @dev: The device to probe
* Return: 0 if OK, -ve on error
*/
int blk_probe_or_unbind(struct udevice *dev);
/**
* blk_unbind_all() - Unbind all device of the given interface type
*

View file

@ -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);

View file

@ -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 \

View file

@ -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" \

View file

@ -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

View file

@ -971,8 +971,8 @@ static inline bool device_is_on_pci_bus(const struct udevice *dev)
* @parent: parent device to scan
*/
#define device_foreach_child_of_to_plat(pos, parent) \
for (int _ret = device_first_child_ofdata_err(parent, &dev); !_ret; \
_ret = device_next_child_ofdata_err(&dev))
for (int _ret = device_first_child_ofdata_err(parent, &pos); !_ret; \
_ret = device_next_child_ofdata_err(&pos))
/**
* device_foreach_child_probe() - iterate through children, probing them
@ -988,8 +988,8 @@ static inline bool device_is_on_pci_bus(const struct udevice *dev)
* @parent: parent device to scan
*/
#define device_foreach_child_probe(pos, parent) \
for (int _ret = device_first_child_err(parent, &dev); !_ret; \
_ret = device_next_child_err(&dev))
for (int _ret = device_first_child_err(parent, &pos); !_ret; \
_ret = device_next_child_err(&pos))
/**
* dm_scan_fdt_dev() - Bind child device in the device tree

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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[];

View file

@ -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 */

View file

@ -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

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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

View file

@ -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);
}
}
}

View file

@ -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 */

View file

@ -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 */

View file

@ -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
@ -324,6 +371,45 @@ __weak efi_status_t platform_get_tpm2_device(struct udevice **dev)
return EFI_NOT_FOUND;
}
/**
* 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
*
@ -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:
@ -1181,6 +1270,318 @@ static const struct efi_tcg2_protocol efi_tcg2_protocol = {
.get_result_of_set_active_pcr_banks = efi_tcg2_get_result_of_set_active_pcr_banks,
};
/**
* 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
*
@ -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");
}
/**
@ -1312,69 +1721,6 @@ out:
return ret;
}
/**
* 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
*
@ -1427,6 +1773,93 @@ static efi_status_t efi_append_scrtm_version(struct udevice *dev)
return ret;
}
/**
* 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
*
@ -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;
@ -1932,12 +2380,37 @@ error:
return ret;
}
/**
* 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;
}

View file

@ -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)

View file

@ -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

24
test/dm/efi_media.c Normal file
View file

@ -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);

View file

@ -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()

View file

@ -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.

15
tools/env/fw_env.c vendored
View file

@ -1083,12 +1083,6 @@ static int flash_write_buf(int dev, int fd, void *buf, size_t count)
}
erase.length = erasesize;
if (DEVTYPE(dev) != MTD_ABSENT) {
was_locked = ioctl(fd, MEMISLOCKED, &erase);
/* treat any errors as unlocked flash */
if (was_locked < 0)
was_locked = 0;
}
/* This only runs once on NOR flash and SPI-dataflash */
while (processed < write_total) {
@ -1108,6 +1102,10 @@ static int flash_write_buf(int dev, int fd, void *buf, size_t count)
if (DEVTYPE(dev) != MTD_ABSENT) {
erase.start = blockstart;
was_locked = ioctl(fd, MEMISLOCKED, &erase);
/* treat any errors as unlocked flash */
if (was_locked < 0)
was_locked = 0;
if (was_locked)
ioctl(fd, MEMUNLOCK, &erase);
/* These do not need an explicit erase cycle */
@ -1163,7 +1161,6 @@ static int flash_flag_obsolete(int dev, int fd, off_t offset)
char tmp = ENV_REDUND_OBSOLETE;
int was_locked; /* flash lock flag */
was_locked = ioctl(fd, MEMISLOCKED, &erase);
erase.start = DEVOFFSET(dev);
erase.length = DEVESIZE(dev);
/* This relies on the fact, that ENV_REDUND_OBSOLETE == 0 */
@ -1173,6 +1170,10 @@ static int flash_flag_obsolete(int dev, int fd, off_t offset)
DEVNAME(dev));
return rc;
}
was_locked = ioctl(fd, MEMISLOCKED, &erase);
/* treat any errors as unlocked flash */
if (was_locked < 0)
was_locked = 0;
if (was_locked)
ioctl(fd, MEMUNLOCK, &erase);
rc = write(fd, &tmp, sizeof(tmp));