Merge branch '2021-04-13-assorted-improvements'

- A large assortment of bug fixes, code cleanups and a few feature
  enhancements.
This commit is contained in:
Tom Rini 2021-04-13 09:50:45 -04:00
commit a94ab561e2
81 changed files with 2145 additions and 742 deletions

View File

@ -201,7 +201,6 @@ dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
tegra124-venice2.dtb \ tegra124-venice2.dtb \
tegra186-p2771-0000-000.dtb \ tegra186-p2771-0000-000.dtb \
tegra186-p2771-0000-500.dtb \ tegra186-p2771-0000-500.dtb \
tegra210-e2220-1170.dtb \
tegra210-p2371-0000.dtb \ tegra210-p2371-0000.dtb \
tegra210-p2371-2180.dtb \ tegra210-p2371-2180.dtb \
tegra210-p2571.dtb \ tegra210-p2571.dtb \

View File

@ -1,63 +0,0 @@
/dts-v1/;
#include "tegra210.dtsi"
/ {
model = "NVIDIA E2220-1170";
compatible = "nvidia,e2220-1170", "nvidia,tegra210";
chosen {
stdout-path = &uarta;
};
aliases {
i2c0 = "/i2c@7000d000";
mmc0 = "/sdhci@700b0600";
mmc1 = "/sdhci@700b0000";
usb0 = "/usb@7d000000";
};
memory {
reg = <0x0 0x80000000 0x0 0xc0000000>;
};
sdhci@700b0000 {
status = "okay";
cd-gpios = <&gpio TEGRA_GPIO(Z, 1) GPIO_ACTIVE_LOW>;
power-gpios = <&gpio TEGRA_GPIO(Z, 4) GPIO_ACTIVE_HIGH>;
bus-width = <4>;
};
sdhci@700b0600 {
status = "okay";
bus-width = <8>;
non-removable;
};
i2c@7000d000 {
status = "okay";
clock-frequency = <400000>;
};
usb@7d000000 {
status = "okay";
dr_mode = "peripheral";
};
clocks {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <0>;
clk32k_in: clock@0 {
compatible = "fixed-clock";
reg = <0>;
#clock-cells = <0>;
clock-frequency = <32768>;
};
};
};
&uarta {
status = "okay";
};

View File

@ -16,7 +16,6 @@
#include <command.h> #include <command.h>
#include <cpu_func.h> #include <cpu_func.h>
#include <dm.h> #include <dm.h>
#include <hang.h>
#include <lmb.h> #include <lmb.h>
#include <log.h> #include <log.h>
#include <asm/global_data.h> #include <asm/global_data.h>
@ -249,8 +248,7 @@ static void boot_prep_linux(bootm_headers_t *images)
#ifdef CONFIG_OF_LIBFDT #ifdef CONFIG_OF_LIBFDT
debug("using: FDT\n"); debug("using: FDT\n");
if (image_setup_linux(images)) { if (image_setup_linux(images)) {
printf("FDT creation failed! hanging..."); panic("FDT creation failed!");
hang();
} }
#endif #endif
} else if (BOOTM_ENABLE_TAGS) { } else if (BOOTM_ENABLE_TAGS) {
@ -283,8 +281,7 @@ static void boot_prep_linux(bootm_headers_t *images)
setup_board_tags(&params); setup_board_tags(&params);
setup_end_tag(gd->bd); setup_end_tag(gd->bd);
} else { } else {
printf("FDT and ATAGS support not compiled in - hanging\n"); panic("FDT and ATAGS support not compiled in\n");
hang();
} }
board_prep_linux(images); board_prep_linux(images);

View File

@ -3,14 +3,6 @@ if TEGRA210
choice choice
prompt "Tegra210 board select" prompt "Tegra210 board select"
config TARGET_E2220_1170
bool "NVIDIA Tegra210 E2220-1170 board"
select BOARD_LATE_INIT
help
E2220-1170 is a Tegra210 bringup board with onboard SoC, DRAM,
eMMC, SD card slot, HDMI, USB micro-B port, and sockets for various
expansion modules.
config TARGET_P2371_0000 config TARGET_P2371_0000
bool "NVIDIA Tegra210 P2371-0000 board" bool "NVIDIA Tegra210 P2371-0000 board"
select BOARD_LATE_INIT select BOARD_LATE_INIT
@ -46,7 +38,6 @@ endchoice
config SYS_SOC config SYS_SOC
default "tegra210" default "tegra210"
source "board/nvidia/e2220-1170/Kconfig"
source "board/nvidia/p2371-0000/Kconfig" source "board/nvidia/p2371-0000/Kconfig"
source "board/nvidia/p2371-2180/Kconfig" source "board/nvidia/p2371-2180/Kconfig"
source "board/nvidia/p2571/Kconfig" source "board/nvidia/p2571/Kconfig"

View File

@ -497,6 +497,27 @@
reg = <0x16>; reg = <0x16>;
#reset-cells = <1>; #reset-cells = <1>;
}; };
protocol@17 {
reg = <0x17>;
regulators {
#address-cells = <1>;
#size-cells = <0>;
regul0_scmi0: reg@0 {
reg = <0>;
regulator-name = "sandbox-voltd0";
regulator-min-microvolt = <1100000>;
regulator-max-microvolt = <3300000>;
};
regul1_scmi0: reg@1 {
reg = <0x1>;
regulator-name = "sandbox-voltd1";
regulator-min-microvolt = <1800000>;
};
};
};
}; };
sandbox-scmi-agent@1 { sandbox-scmi-agent@1 {
@ -1264,6 +1285,8 @@
compatible = "sandbox,scmi-devices"; compatible = "sandbox,scmi-devices";
clocks = <&clk_scmi0 7>, <&clk_scmi0 3>, <&clk_scmi1 1>; clocks = <&clk_scmi0 7>, <&clk_scmi0 3>, <&clk_scmi1 1>;
resets = <&reset_scmi0 3>; resets = <&reset_scmi0 3>;
regul0-supply = <&regul0_scmi0>;
regul1-supply = <&regul1_scmi0>;
}; };
pinctrl { pinctrl {

View File

@ -24,6 +24,7 @@ struct sandbox_scmi_clk {
/** /**
* struct sandbox_scmi_reset - Simulated reset controller exposed by SCMI * struct sandbox_scmi_reset - Simulated reset controller exposed by SCMI
* @id: Identifier of the reset controller used in the SCMI protocol
* @asserted: Reset control state: true if asserted, false if desasserted * @asserted: Reset control state: true if asserted, false if desasserted
*/ */
struct sandbox_scmi_reset { struct sandbox_scmi_reset {
@ -31,13 +32,27 @@ struct sandbox_scmi_reset {
bool asserted; bool asserted;
}; };
/**
* struct sandbox_scmi_voltd - Simulated voltage regulator exposed by SCMI
* @id: Identifier of the voltage domain used in the SCMI protocol
* @enabled: Regulator state: true if on, false if off
* @voltage_uv: Regulator current voltage in microvoltd (uV)
*/
struct sandbox_scmi_voltd {
uint id;
bool enabled;
int voltage_uv;
};
/** /**
* struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent * struct sandbox_scmi_agent - Simulated SCMI service seen by SCMI agent
* @idx: Identifier for the SCMI agent, its index * @idx: Identifier for the SCMI agent, its index
* @clk: Simulated clocks * @clk: Simulated clocks
* @clk_count: Simulated clocks array size * @clk_count: Simulated clocks array size
* @clk: Simulated reset domains * @reset: Simulated reset domains
* @clk_count: Simulated reset domains array size * @reset_count: Simulated reset domains array size
* @voltd: Simulated voltage domains (regulators)
* @voltd_count: Simulated voltage domains array size
*/ */
struct sandbox_scmi_agent { struct sandbox_scmi_agent {
uint idx; uint idx;
@ -45,6 +60,8 @@ struct sandbox_scmi_agent {
size_t clk_count; size_t clk_count;
struct sandbox_scmi_reset *reset; struct sandbox_scmi_reset *reset;
size_t reset_count; size_t reset_count;
struct sandbox_scmi_voltd *voltd;
size_t voltd_count;
}; };
/** /**
@ -63,12 +80,16 @@ struct sandbox_scmi_service {
* @clk_count: Number of clock devices probed * @clk_count: Number of clock devices probed
* @reset: Array the reset controller devices * @reset: Array the reset controller devices
* @reset_count: Number of reset controller devices probed * @reset_count: Number of reset controller devices probed
* @regul: Array regulator devices
* @regul_count: Number of regulator devices probed
*/ */
struct sandbox_scmi_devices { struct sandbox_scmi_devices {
struct clk *clk; struct clk *clk;
size_t clk_count; size_t clk_count;
struct reset_ctl *reset; struct reset_ctl *reset;
size_t reset_count; size_t reset_count;
struct udevice **regul;
size_t regul_count;
}; };
#ifdef CONFIG_SCMI_FIRMWARE #ifdef CONFIG_SCMI_FIRMWARE

View File

@ -22,7 +22,14 @@ int cpu_qemu_get_desc(const struct udevice *dev, char *buf, int size)
static int cpu_qemu_get_count(const struct udevice *dev) static int cpu_qemu_get_count(const struct udevice *dev)
{ {
return qemu_fwcfg_online_cpus(); int ret;
struct udevice *qfw_dev;
ret = qfw_get_dev(&qfw_dev);
if (ret)
return ret;
return qfw_online_cpus(qfw_dev);
} }
static const struct cpu_ops cpu_qemu_ops = { static const struct cpu_ops cpu_qemu_ops = {

View File

@ -8,6 +8,7 @@
#include <init.h> #include <init.h>
#include <pci.h> #include <pci.h>
#include <qfw.h> #include <qfw.h>
#include <dm/platdata.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/post.h> #include <asm/post.h>
#include <asm/processor.h> #include <asm/processor.h>
@ -16,47 +17,9 @@
static bool i440fx; static bool i440fx;
#ifdef CONFIG_QFW #if CONFIG_IS_ENABLED(QFW_PIO)
U_BOOT_DRVINFO(x86_qfw_pio) = {
/* on x86, the qfw registers are all IO ports */ .name = "qfw_pio",
#define FW_CONTROL_PORT 0x510
#define FW_DATA_PORT 0x511
#define FW_DMA_PORT_LOW 0x514
#define FW_DMA_PORT_HIGH 0x518
static void qemu_x86_fwcfg_read_entry_pio(uint16_t entry,
uint32_t size, void *address)
{
uint32_t i = 0;
uint8_t *data = address;
/*
* writting FW_CFG_INVALID will cause read operation to resume at
* last offset, otherwise read will start at offset 0
*
* Note: on platform where the control register is IO port, the
* endianness is little endian.
*/
if (entry != FW_CFG_INVALID)
outw(cpu_to_le16(entry), FW_CONTROL_PORT);
/* the endianness of data register is string-preserving */
while (size--)
data[i++] = inb(FW_DATA_PORT);
}
static void qemu_x86_fwcfg_read_entry_dma(struct fw_cfg_dma_access *dma)
{
/* the DMA address register is big endian */
outl(cpu_to_be32((uintptr_t)dma), FW_DMA_PORT_HIGH);
while (be32_to_cpu(dma->control) & ~FW_CFG_DMA_ERROR)
__asm__ __volatile__ ("pause");
}
static struct fw_cfg_arch_ops fwcfg_x86_ops = {
.arch_read_pio = qemu_x86_fwcfg_read_entry_pio,
.arch_read_dma = qemu_x86_fwcfg_read_entry_dma
}; };
#endif #endif
@ -132,10 +95,6 @@ static void qemu_chipset_init(void)
enable_pm_ich9(); enable_pm_ich9();
} }
#ifdef CONFIG_QFW
qemu_fwcfg_init(&fwcfg_x86_ops);
#endif
} }
#if !CONFIG_IS_ENABLED(SPL_X86_32BIT_INIT) #if !CONFIG_IS_ENABLED(SPL_X86_32BIT_INIT)

View File

@ -18,7 +18,7 @@ int qemu_cpu_fixup(void)
int cpu_num; int cpu_num;
int cpu_online; int cpu_online;
struct uclass *uc; struct uclass *uc;
struct udevice *dev, *pdev; struct udevice *dev, *pdev, *qfwdev;
struct cpu_plat *plat; struct cpu_plat *plat;
char *cpu; char *cpu;
@ -39,6 +39,13 @@ int qemu_cpu_fixup(void)
return -ENODEV; return -ENODEV;
} }
/* get qfw dev */
ret = qfw_get_dev(&qfwdev);
if (ret) {
printf("unable to find qfw device\n");
return ret;
}
/* calculate cpus that are already bound */ /* calculate cpus that are already bound */
cpu_num = 0; cpu_num = 0;
for (uclass_find_first_device(UCLASS_CPU, &dev); for (uclass_find_first_device(UCLASS_CPU, &dev);
@ -48,7 +55,7 @@ int qemu_cpu_fixup(void)
} }
/* get actual cpu number */ /* get actual cpu number */
cpu_online = qemu_fwcfg_online_cpus(); cpu_online = qfw_online_cpus(qfwdev);
if (cpu_online < 0) { if (cpu_online < 0) {
printf("unable to get online cpu number: %d\n", cpu_online); printf("unable to get online cpu number: %d\n", cpu_online);
return cpu_online; return cpu_online;

View File

@ -5,6 +5,8 @@ config SYS_TEXT_BASE
config BOARD_SPECIFIC_OPTIONS # dummy config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y def_bool y
select CMD_QFW
select QFW_MMIO
imply VIRTIO_MMIO imply VIRTIO_MMIO
imply VIRTIO_PCI imply VIRTIO_PCI
imply VIRTIO_NET imply VIRTIO_NET

View File

@ -20,6 +20,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y def_bool y
select X86_RESET_VECTOR select X86_RESET_VECTOR
select QEMU select QEMU
select QFW_PIO
select BOARD_ROMSIZE_KB_1024 select BOARD_ROMSIZE_KB_1024
imply VIRTIO_PCI imply VIRTIO_PCI
imply VIRTIO_NET imply VIRTIO_NET

View File

@ -1,12 +0,0 @@
if TARGET_E2220_1170
config SYS_BOARD
default "e2220-1170"
config SYS_VENDOR
default "nvidia"
config SYS_CONFIG_NAME
default "e2220-1170"
endif

View File

@ -1,6 +0,0 @@
E2220-1170 BOARD
M: Tom Warren <twarren@nvidia.com>
S: Maintained
F: board/nvidia/e2220-1170/
F: include/configs/e2220-1170.h
F: configs/e2220-1170_defconfig

View File

@ -1,8 +0,0 @@
#
# (C) Copyright 2013-2015
# NVIDIA Corporation <www.nvidia.com>
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += e2220-1170.o

View File

@ -1,32 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2013-2019
* NVIDIA Corporation <www.nvidia.com>
*/
#include <common.h>
#include <i2c.h>
#include <log.h>
#include <asm/arch/gpio.h>
#include <asm/arch/pinmux.h>
#include "../p2571/max77620_init.h"
void pin_mux_mmc(void)
{
struct udevice *dev;
uchar val;
int ret;
/* Turn on MAX77620 LDO2 to 3.3V for SD card power */
debug("%s: Set LDO2 for VDDIO_SDMMC_AP power to 3.3V\n", __func__);
ret = i2c_get_chip_for_busnum(0, MAX77620_I2C_ADDR_7BIT, 1, &dev);
if (ret) {
printf("%s: Cannot find MAX77620 I2C chip\n", __func__);
return;
}
/* 0xF2 for 3.3v, enabled: bit7:6 = 11 = enable, bit5:0 = voltage */
val = 0xF2;
ret = dm_i2c_write(dev, MAX77620_CNFG1_L2_REG, &val, 1);
if (ret)
printf("i2c_write 0 0x3c 0x27 failed: %d\n", ret);
}

View File

@ -26,7 +26,6 @@
#include <mmc.h> #include <mmc.h>
#include <usb.h> #include <usb.h>
#include <power/pmic.h> #include <power/pmic.h>
#include <power/max77696_pmic.h>
DECLARE_GLOBAL_DATA_PTR; DECLARE_GLOBAL_DATA_PTR;
@ -45,6 +44,53 @@ DECLARE_GLOBAL_DATA_PTR;
PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \ PAD_CTL_DSE_40ohm | PAD_CTL_HYS | \
PAD_CTL_ODE | PAD_CTL_SRE_FAST) PAD_CTL_ODE | PAD_CTL_SRE_FAST)
#define CONFIG_POWER_MAX77696_I2C_ADDR 0x3C
enum {
L01_CNFG1 = 0x43,
L01_CNFG2,
L02_CNFG1,
L02_CNFG2,
L03_CNFG1,
L03_CNFG2,
L04_CNFG1,
L04_CNFG2,
L05_CNFG1,
L05_CNFG2,
L06_CNFG1,
L06_CNFG2,
L07_CNFG1,
L07_CNFG2,
L08_CNFG1,
L08_CNFG2,
L09_CNFG1,
L09_CNFG2,
L10_CNFG1,
L10_CNFG2,
LDO_INT1,
LDO_INT2,
LDO_INT1M,
LDO_INT2M,
LDO_CNFG3,
SW1_CNTRL,
SW2_CNTRL,
SW3_CNTRL,
SW4_CNTRL,
EPDCNFG,
EPDINTS,
EPDINT,
EPDINTM,
EPDVCOM,
EPDVEE,
EPDVNEG,
EPDVPOS,
EPDVDDH,
EPDSEQ,
EPDOKINTS,
CID = 0x9c,
PMIC_NUM_OF_REGS,
};
int dram_init(void) int dram_init(void)
{ {
gd->ram_size = imx_ddr_size(); gd->ram_size = imx_ddr_size();
@ -114,6 +160,26 @@ struct i2c_pads_info i2c_pad_info1 = {
}, },
}; };
static int power_max77696_init(unsigned char bus)
{
static const char name[] = "MAX77696";
struct pmic *p = pmic_alloc();
if (!p) {
printf("%s: POWER allocation error!\n", __func__);
return -ENOMEM;
}
p->name = name;
p->interface = PMIC_I2C;
p->number_of_regs = PMIC_NUM_OF_REGS;
p->hw.i2c.addr = CONFIG_POWER_MAX77696_I2C_ADDR;
p->hw.i2c.tx_num = 1;
p->bus = bus;
return 0;
}
int power_init_board(void) int power_init_board(void)
{ {
struct pmic *p; struct pmic *p;

View File

@ -65,7 +65,7 @@ config SYS_PROMPT_HUSH_PS2
to complete a command. Usually "> ". to complete a command. Usually "> ".
config SYS_XTRACE config SYS_XTRACE
string "Command execution tracer" bool "Command execution tracer"
depends on CMDLINE depends on CMDLINE
default y if CMDLINE default y if CMDLINE
help help

View File

@ -10,13 +10,10 @@
static int do_exit(struct cmd_tbl *cmdtp, int flag, int argc, static int do_exit(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[]) char *const argv[])
{ {
int r;
r = 0;
if (argc > 1) if (argc > 1)
r = simple_strtoul(argv[1], NULL, 10); return simple_strtoul(argv[1], NULL, 10);
return -r - 2; return 0;
} }
U_BOOT_CMD( U_BOOT_CMD(

View File

@ -8,19 +8,22 @@
#include <env.h> #include <env.h>
#include <errno.h> #include <errno.h>
#include <qfw.h> #include <qfw.h>
#include <dm.h>
static struct udevice *qfw_dev;
/* /*
* This function prepares kernel for zboot. It loads kernel data * This function prepares kernel for zboot. It loads kernel data
* to 'load_addr', initrd to 'initrd_addr' and kernel command * to 'load_addr', initrd to 'initrd_addr' and kernel command
* line using qemu fw_cfg interface. * line using qemu fw_cfg interface.
*/ */
static int qemu_fwcfg_setup_kernel(void *load_addr, void *initrd_addr) static int qemu_fwcfg_cmd_setup_kernel(void *load_addr, void *initrd_addr)
{ {
char *data_addr; char *data_addr;
uint32_t setup_size, kernel_size, cmdline_size, initrd_size; uint32_t setup_size, kernel_size, cmdline_size, initrd_size;
qemu_fwcfg_read_entry(FW_CFG_SETUP_SIZE, 4, &setup_size); qfw_read_entry(qfw_dev, FW_CFG_SETUP_SIZE, 4, &setup_size);
qemu_fwcfg_read_entry(FW_CFG_KERNEL_SIZE, 4, &kernel_size); qfw_read_entry(qfw_dev, FW_CFG_KERNEL_SIZE, 4, &kernel_size);
if (setup_size == 0 || kernel_size == 0) { if (setup_size == 0 || kernel_size == 0) {
printf("warning: no kernel available\n"); printf("warning: no kernel available\n");
@ -28,28 +31,28 @@ static int qemu_fwcfg_setup_kernel(void *load_addr, void *initrd_addr)
} }
data_addr = load_addr; data_addr = load_addr;
qemu_fwcfg_read_entry(FW_CFG_SETUP_DATA, qfw_read_entry(qfw_dev, FW_CFG_SETUP_DATA,
le32_to_cpu(setup_size), data_addr); le32_to_cpu(setup_size), data_addr);
data_addr += le32_to_cpu(setup_size); data_addr += le32_to_cpu(setup_size);
qemu_fwcfg_read_entry(FW_CFG_KERNEL_DATA, qfw_read_entry(qfw_dev, FW_CFG_KERNEL_DATA,
le32_to_cpu(kernel_size), data_addr); le32_to_cpu(kernel_size), data_addr);
data_addr += le32_to_cpu(kernel_size); data_addr += le32_to_cpu(kernel_size);
data_addr = initrd_addr; data_addr = initrd_addr;
qemu_fwcfg_read_entry(FW_CFG_INITRD_SIZE, 4, &initrd_size); qfw_read_entry(qfw_dev, FW_CFG_INITRD_SIZE, 4, &initrd_size);
if (initrd_size == 0) { if (initrd_size == 0) {
printf("warning: no initrd available\n"); printf("warning: no initrd available\n");
} else { } else {
qemu_fwcfg_read_entry(FW_CFG_INITRD_DATA, qfw_read_entry(qfw_dev, FW_CFG_INITRD_DATA,
le32_to_cpu(initrd_size), data_addr); le32_to_cpu(initrd_size), data_addr);
data_addr += le32_to_cpu(initrd_size); data_addr += le32_to_cpu(initrd_size);
} }
qemu_fwcfg_read_entry(FW_CFG_CMDLINE_SIZE, 4, &cmdline_size); qfw_read_entry(qfw_dev, FW_CFG_CMDLINE_SIZE, 4, &cmdline_size);
if (cmdline_size) { if (cmdline_size) {
qemu_fwcfg_read_entry(FW_CFG_CMDLINE_DATA, qfw_read_entry(qfw_dev, FW_CFG_CMDLINE_DATA,
le32_to_cpu(cmdline_size), data_addr); le32_to_cpu(cmdline_size), data_addr);
/* /*
* if kernel cmdline only contains '\0', (e.g. no -append * if kernel cmdline only contains '\0', (e.g. no -append
* when invoking qemu), do not update bootargs * when invoking qemu), do not update bootargs
@ -72,21 +75,20 @@ static int qemu_fwcfg_setup_kernel(void *load_addr, void *initrd_addr)
return 0; return 0;
} }
static int qemu_fwcfg_list_firmware(void) static int qemu_fwcfg_cmd_list_firmware(void)
{ {
int ret; int ret;
struct fw_cfg_file_iter iter; struct fw_cfg_file_iter iter;
struct fw_file *file; struct fw_file *file;
/* make sure fw_list is loaded */ /* make sure fw_list is loaded */
ret = qemu_fwcfg_read_firmware_list(); ret = qfw_read_firmware_list(qfw_dev);
if (ret) if (ret)
return ret; return ret;
for (file = qfw_file_iter_init(qfw_dev, &iter);
for (file = qemu_fwcfg_file_iter_init(&iter); !qfw_file_iter_end(&iter);
!qemu_fwcfg_file_iter_end(&iter); file = qfw_file_iter_next(&iter)) {
file = qemu_fwcfg_file_iter_next(&iter)) {
printf("%-56s\n", file->cfg.name); printf("%-56s\n", file->cfg.name);
} }
@ -96,7 +98,7 @@ static int qemu_fwcfg_list_firmware(void)
static int qemu_fwcfg_do_list(struct cmd_tbl *cmdtp, int flag, static int qemu_fwcfg_do_list(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[]) int argc, char *const argv[])
{ {
if (qemu_fwcfg_list_firmware() < 0) if (qemu_fwcfg_cmd_list_firmware() < 0)
return CMD_RET_FAILURE; return CMD_RET_FAILURE;
return 0; return 0;
@ -105,14 +107,7 @@ static int qemu_fwcfg_do_list(struct cmd_tbl *cmdtp, int flag,
static int qemu_fwcfg_do_cpus(struct cmd_tbl *cmdtp, int flag, static int qemu_fwcfg_do_cpus(struct cmd_tbl *cmdtp, int flag,
int argc, char *const argv[]) int argc, char *const argv[])
{ {
int ret = qemu_fwcfg_online_cpus(); printf("%d cpu(s) online\n", qfw_online_cpus(qfw_dev));
if (ret < 0) {
printf("QEMU fw_cfg interface not found\n");
return CMD_RET_FAILURE;
}
printf("%d cpu(s) online\n", qemu_fwcfg_online_cpus());
return 0; return 0;
} }
@ -153,7 +148,7 @@ static int qemu_fwcfg_do_load(struct cmd_tbl *cmdtp, int flag,
return CMD_RET_FAILURE; return CMD_RET_FAILURE;
} }
return qemu_fwcfg_setup_kernel(load_addr, initrd_addr); return qemu_fwcfg_cmd_setup_kernel(load_addr, initrd_addr);
} }
static struct cmd_tbl fwcfg_commands[] = { static struct cmd_tbl fwcfg_commands[] = {
@ -168,7 +163,8 @@ static int do_qemu_fw(struct cmd_tbl *cmdtp, int flag, int argc,
int ret; int ret;
struct cmd_tbl *fwcfg_cmd; struct cmd_tbl *fwcfg_cmd;
if (!qemu_fwcfg_present()) { ret = qfw_get_dev(&qfw_dev);
if (ret) {
printf("QEMU fw_cfg interface not found\n"); printf("QEMU fw_cfg interface not found\n");
return CMD_RET_USAGE; return CMD_RET_USAGE;
} }

View File

@ -25,7 +25,9 @@ int do_terminal(struct cmd_tbl *cmd, int flag, int argc, char *const argv[])
if (!dev) if (!dev)
return -1; return -1;
serial_reinit_all(); if (IS_ENABLED(CONFIG_SERIAL))
serial_reinit_all();
printf("Entering terminal mode for port %s\n", dev->name); printf("Entering terminal mode for port %s\n", dev->name);
puts("Use '~.' to leave the terminal and get back to u-boot\n"); puts("Use '~.' to leave the terminal and get back to u-boot\n");
@ -33,8 +35,8 @@ int do_terminal(struct cmd_tbl *cmd, int flag, int argc, char *const argv[])
int c; int c;
/* read from console and display on serial port */ /* read from console and display on serial port */
if (stdio_devices[0]->tstc()) { if (stdio_devices[0]->tstc(stdio_devices[0])) {
c = stdio_devices[0]->getc(); c = stdio_devices[0]->getc(stdio_devices[0]);
if (last_tilde == 1) { if (last_tilde == 1) {
if (c == '.') { if (c == '.') {
putc(c); putc(c);
@ -43,7 +45,7 @@ int do_terminal(struct cmd_tbl *cmd, int flag, int argc, char *const argv[])
} else { } else {
last_tilde = 0; last_tilde = 0;
/* write the delayed tilde */ /* write the delayed tilde */
dev->putc('~'); dev->putc(dev, '~');
/* fall-through to print current /* fall-through to print current
* character */ * character */
} }
@ -53,12 +55,12 @@ int do_terminal(struct cmd_tbl *cmd, int flag, int argc, char *const argv[])
puts("[u-boot]"); puts("[u-boot]");
putc(c); putc(c);
} }
dev->putc(c); dev->putc(dev, c);
} }
/* read from serial port and display on console */ /* read from serial port and display on console */
if (dev->tstc()) { if (dev->tstc(dev)) {
c = dev->getc(); c = dev->getc(dev);
putc(c); putc(c);
} }
} }

View File

@ -138,3 +138,5 @@ obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o
obj-$(CONFIG_AVB_VERIFY) += avb_verify.o obj-$(CONFIG_AVB_VERIFY) += avb_verify.o
obj-$(CONFIG_SCP03) += scp03.o obj-$(CONFIG_SCP03) += scp03.o
obj-$(CONFIG_QFW) += qfw.o

View File

@ -1673,7 +1673,7 @@ static int run_pipe_real(struct pipe *pi)
return -1; return -1;
} }
/* Process the command */ /* Process the command */
return cmd_process(flag, child->argc, child->argv, return cmd_process(flag, child->argc - i, child->argv + i,
&flag_repeat, NULL); &flag_repeat, NULL);
#endif #endif
} }

View File

@ -97,7 +97,7 @@ static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void
} }
#endif #endif
#if defined(CONFIG_SHA384) #if defined(CONFIG_SHA384) && !defined(CONFIG_SHA_PROG_HW_ACCEL)
static int hash_init_sha384(struct hash_algo *algo, void **ctxp) static int hash_init_sha384(struct hash_algo *algo, void **ctxp)
{ {
sha512_context *ctx = malloc(sizeof(sha512_context)); sha512_context *ctx = malloc(sizeof(sha512_context));
@ -125,7 +125,7 @@ static int hash_finish_sha384(struct hash_algo *algo, void *ctx, void
} }
#endif #endif
#if defined(CONFIG_SHA512) #if defined(CONFIG_SHA512) && !defined(CONFIG_SHA_PROG_HW_ACCEL)
static int hash_init_sha512(struct hash_algo *algo, void **ctxp) static int hash_init_sha512(struct hash_algo *algo, void **ctxp)
{ {
sha512_context *ctx = malloc(sizeof(sha512_context)); sha512_context *ctx = malloc(sizeof(sha512_context));
@ -260,10 +260,20 @@ static struct hash_algo hash_algo[] = {
.name = "sha384", .name = "sha384",
.digest_size = SHA384_SUM_LEN, .digest_size = SHA384_SUM_LEN,
.chunk_size = CHUNKSZ_SHA384, .chunk_size = CHUNKSZ_SHA384,
#ifdef CONFIG_SHA_HW_ACCEL
.hash_func_ws = hw_sha384,
#else
.hash_func_ws = sha384_csum_wd, .hash_func_ws = sha384_csum_wd,
#endif
#ifdef CONFIG_SHA_PROG_HW_ACCEL
.hash_init = hw_sha_init,
.hash_update = hw_sha_update,
.hash_finish = hw_sha_finish,
#else
.hash_init = hash_init_sha384, .hash_init = hash_init_sha384,
.hash_update = hash_update_sha384, .hash_update = hash_update_sha384,
.hash_finish = hash_finish_sha384, .hash_finish = hash_finish_sha384,
#endif
}, },
#endif #endif
#ifdef CONFIG_SHA512 #ifdef CONFIG_SHA512
@ -271,10 +281,20 @@ static struct hash_algo hash_algo[] = {
.name = "sha512", .name = "sha512",
.digest_size = SHA512_SUM_LEN, .digest_size = SHA512_SUM_LEN,
.chunk_size = CHUNKSZ_SHA512, .chunk_size = CHUNKSZ_SHA512,
#ifdef CONFIG_SHA_HW_ACCEL
.hash_func_ws = hw_sha512,
#else
.hash_func_ws = sha512_csum_wd, .hash_func_ws = sha512_csum_wd,
#endif
#ifdef CONFIG_SHA_PROG_HW_ACCEL
.hash_init = hw_sha_init,
.hash_update = hw_sha_update,
.hash_finish = hw_sha_finish,
#else
.hash_init = hash_init_sha512, .hash_init = hash_init_sha512,
.hash_update = hash_update_sha512, .hash_update = hash_update_sha512,
.hash_finish = hash_finish_sha512, .hash_finish = hash_finish_sha512,
#endif
}, },
#endif #endif
{ {

View File

@ -562,7 +562,7 @@ int image_setup_libfdt(bootm_headers_t *images, void *blob,
goto err; goto err;
} }
fdt_ret = optee_copy_fdt_nodes(gd->fdt_blob, blob); fdt_ret = optee_copy_fdt_nodes(blob);
if (fdt_ret) { if (fdt_ret) {
printf("ERROR: transfer of optee nodes to new fdt failed: %s\n", printf("ERROR: transfer of optee nodes to new fdt failed: %s\n",
fdt_strerror(fdt_ret)); fdt_strerror(fdt_ret));

104
common/qfw.c Normal file
View File

@ -0,0 +1,104 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
* (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
*/
#include <dm.h>
#include <dm/uclass.h>
#include <qfw.h>
#include <stdlib.h>
int qfw_get_dev(struct udevice **devp)
{
return uclass_first_device_err(UCLASS_QFW, devp);
}
int qfw_online_cpus(struct udevice *dev)
{
u16 nb_cpus;
qfw_read_entry(dev, FW_CFG_NB_CPUS, 2, &nb_cpus);
return le16_to_cpu(nb_cpus);
}
int qfw_read_firmware_list(struct udevice *dev)
{
int i;
u32 count;
struct fw_file *file;
struct list_head *entry;
struct qfw_dev *qdev = dev_get_uclass_priv(dev);
/* don't read it twice */
if (!list_empty(&qdev->fw_list))
return 0;
qfw_read_entry(dev, FW_CFG_FILE_DIR, 4, &count);
if (!count)
return 0;
count = be32_to_cpu(count);
for (i = 0; i < count; i++) {
file = malloc(sizeof(*file));
if (!file) {
printf("error: allocating resource\n");
goto err;
}
qfw_read_entry(dev, FW_CFG_INVALID,
sizeof(struct fw_cfg_file), &file->cfg);
file->addr = 0;
list_add_tail(&file->list, &qdev->fw_list);
}
return 0;
err:
list_for_each(entry, &qdev->fw_list) {
file = list_entry(entry, struct fw_file, list);
free(file);
}
return -ENOMEM;
}
struct fw_file *qfw_find_file(struct udevice *dev, const char *name)
{
struct list_head *entry;
struct fw_file *file;
struct qfw_dev *qdev = dev_get_uclass_priv(dev);
list_for_each(entry, &qdev->fw_list) {
file = list_entry(entry, struct fw_file, list);
if (!strcmp(file->cfg.name, name))
return file;
}
return NULL;
}
struct fw_file *qfw_file_iter_init(struct udevice *dev,
struct fw_cfg_file_iter *iter)
{
struct qfw_dev *qdev = dev_get_uclass_priv(dev);
iter->entry = qdev->fw_list.next;
iter->end = &qdev->fw_list;
return list_entry((struct list_head *)iter->entry,
struct fw_file, list);
}
struct fw_file *qfw_file_iter_next(struct fw_cfg_file_iter *iter)
{
iter->entry = ((struct list_head *)iter->entry)->next;
return list_entry((struct list_head *)iter->entry,
struct fw_file, list);
}
bool qfw_file_iter_end(struct fw_cfg_file_iter *iter)
{
return iter->entry == iter->end;
}

View File

@ -19,7 +19,7 @@ CONFIG_SILENT_U_BOOT_ONLY=y
# CONFIG_DISPLAY_CPUINFO is not set # CONFIG_DISPLAY_CPUINFO is not set
CONFIG_HUSH_PARSER=y CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="u-boot> " CONFIG_SYS_PROMPT="u-boot> "
CONFIG_SYS_XTRACE="n" CONFIG_SYS_XTRACE=n
CONFIG_CMD_GPT=y CONFIG_CMD_GPT=y
CONFIG_CMD_GPT_RENAME=y CONFIG_CMD_GPT_RENAME=y
CONFIG_CMD_MMC=y CONFIG_CMD_MMC=y

View File

@ -1,48 +0,0 @@
CONFIG_ARM=y
CONFIG_ARCH_TEGRA=y
CONFIG_SYS_TEXT_BASE=0x80080000
CONFIG_NR_DRAM_BANKS=2
CONFIG_ENV_SIZE=0x2000
CONFIG_ENV_OFFSET=0xFFFFE000
CONFIG_TEGRA210=y
CONFIG_DEFAULT_DEVICE_TREE="tegra210-e2220-1170"
CONFIG_OF_SYSTEM_SETUP=y
CONFIG_CONSOLE_MUX=y
CONFIG_SYS_STDIO_DEREGISTER=y
CONFIG_SYS_PROMPT="Tegra210 (E2220-1170) # "
# CONFIG_CMD_IMI is not set
CONFIG_CMD_DFU=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
CONFIG_CMD_USB_MASS_STORAGE=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_BOOTP_PREFER_SERVERIP=y
# CONFIG_CMD_NFS is not set
CONFIG_CMD_EXT4_WRITE=y
CONFIG_ENV_OVERWRITE=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SYS_MMC_ENV_PART=2
CONFIG_DFU_MMC=y
CONFIG_DFU_RAM=y
CONFIG_DFU_SF=y
CONFIG_SYS_I2C_TEGRA=y
CONFIG_SF_DEFAULT_MODE=0
CONFIG_SF_DEFAULT_SPEED=24000000
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SYS_NS16550=y
CONFIG_TEGRA114_SPI=y
CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_TEGRA=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="NVIDIA"
CONFIG_USB_GADGET_VENDOR_NUM=0x0955
CONFIG_USB_GADGET_PRODUCT_NUM=0x701a
CONFIG_CI_UDC=y
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_USB_HOST_ETHER=y
CONFIG_USB_ETHER_ASIX=y

View File

@ -219,6 +219,7 @@ CONFIG_DM_REGULATOR_FIXED=y
CONFIG_REGULATOR_RK8XX=y CONFIG_REGULATOR_RK8XX=y
CONFIG_REGULATOR_S5M8767=y CONFIG_REGULATOR_S5M8767=y
CONFIG_DM_REGULATOR_SANDBOX=y CONFIG_DM_REGULATOR_SANDBOX=y
CONFIG_DM_REGULATOR_SCMI=y
CONFIG_REGULATOR_TPS65090=y CONFIG_REGULATOR_TPS65090=y
CONFIG_DM_PWM=y CONFIG_DM_PWM=y
CONFIG_PWM_SANDBOX=y CONFIG_PWM_SANDBOX=y

View File

@ -73,7 +73,6 @@ CONFIG_CMD_EFIDEBUG=y
CONFIG_CMD_TIME=y CONFIG_CMD_TIME=y
CONFIG_CMD_TIMER=y CONFIG_CMD_TIMER=y
CONFIG_CMD_SOUND=y CONFIG_CMD_SOUND=y
CONFIG_CMD_QFW=y
CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_BOOTSTAGE=y
CONFIG_CMD_PMIC=y CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y CONFIG_CMD_REGULATOR=y

View File

@ -75,7 +75,6 @@ CONFIG_CMD_EFIDEBUG=y
CONFIG_CMD_TIME=y CONFIG_CMD_TIME=y
CONFIG_CMD_TIMER=y CONFIG_CMD_TIMER=y
CONFIG_CMD_SOUND=y CONFIG_CMD_SOUND=y
CONFIG_CMD_QFW=y
CONFIG_CMD_BOOTSTAGE=y CONFIG_CMD_BOOTSTAGE=y
CONFIG_CMD_PMIC=y CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y CONFIG_CMD_REGULATOR=y

View File

@ -44,7 +44,7 @@ CONFIG_SPL_NAND_BASE=y
CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_DM_SPI_FLASH=y
CONFIG_HUSH_PARSER=y CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="U-Boot> " CONFIG_SYS_PROMPT="U-Boot> "
CONFIG_SYS_XTRACE="n" CONFIG_SYS_XTRACE=n
# CONFIG_CMD_BDI is not set # CONFIG_CMD_BDI is not set
CONFIG_CMD_BOOTZ=y CONFIG_CMD_BOOTZ=y
# CONFIG_CMD_IMI is not set # CONFIG_CMD_IMI is not set

View File

@ -692,6 +692,15 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,
/* Free pte before allocating again */ /* Free pte before allocating again */
free(*gpt_pte); free(*gpt_pte);
/*
* Check that the alternate_lba entry points to the last LBA
*/
if (le64_to_cpu(gpt_head->alternate_lba) != (dev_desc->lba - 1)) {
printf("%s: *** ERROR: Misplaced Backup GPT ***\n",
__func__);
return -1;
}
if (is_gpt_valid(dev_desc, (dev_desc->lba - 1), if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
gpt_head, gpt_pte) != 1) { gpt_head, gpt_pte) != 1) {
printf("%s: *** ERROR: Invalid Backup GPT ***\n", printf("%s: *** ERROR: Invalid Backup GPT ***\n",

View File

@ -62,6 +62,20 @@ Required properties:
- #power-domain-cells : Should be 1. Contains the device or the power - #power-domain-cells : Should be 1. Contains the device or the power
domain ID value used by SCMI commands. domain ID value used by SCMI commands.
Regulator bindings for the SCMI Regulator based on SCMI Message Protocol
------------------------------------------------------------
An SCMI Regulator is permanently bound to a well defined SCMI Voltage Domain,
and should be always positioned as a root regulator.
It does not support any current operation.
SCMI Regulators are grouped under a 'regulators' node which in turn is a child
of the SCMI Voltage protocol node inside the desired SCMI instance node.
This binding uses the common regulator binding[6].
Required properties:
- reg : shall identify an existent SCMI Voltage Domain.
Sensor bindings for the sensors based on SCMI Message Protocol Sensor bindings for the sensors based on SCMI Message Protocol
-------------------------------------------------------------- --------------------------------------------------------------
SCMI provides an API to access the various sensors on the SoC. SCMI provides an API to access the various sensors on the SoC.
@ -105,6 +119,7 @@ Required sub-node properties:
[3] Documentation/devicetree/bindings/thermal/thermal.txt [3] Documentation/devicetree/bindings/thermal/thermal.txt
[4] Documentation/devicetree/bindings/sram/sram.yaml [4] Documentation/devicetree/bindings/sram/sram.yaml
[5] Documentation/devicetree/bindings/reset/reset.txt [5] Documentation/devicetree/bindings/reset/reset.txt
[6] Documentation/devicetree/bindings/regulator/regulator.yaml
Example: Example:
@ -169,6 +184,25 @@ firmware {
reg = <0x16>; reg = <0x16>;
#reset-cells = <1>; #reset-cells = <1>;
}; };
scmi_voltage: protocol@17 {
reg = <0x17>;
regulators {
regulator_devX: regulator@0 {
reg = <0x0>;
regulator-max-microvolt = <3300000>;
};
regulator_devY: regulator@9 {
reg = <0x9>;
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <4200000>;
};
...
};
};
}; };
}; };

View File

@ -40,7 +40,7 @@ static int raw_part_get_info_by_name(struct blk_desc *dev_desc,
/* check for raw partition descriptor */ /* check for raw partition descriptor */
strcpy(env_desc_name, "fastboot_raw_partition_"); strcpy(env_desc_name, "fastboot_raw_partition_");
strncat(env_desc_name, name, PART_NAME_LEN); strlcat(env_desc_name, name, PART_NAME_LEN);
raw_part_desc = strdup(env_get(env_desc_name)); raw_part_desc = strdup(env_get(env_desc_name));
if (raw_part_desc == NULL) if (raw_part_desc == NULL)
return -ENODEV; return -ENODEV;
@ -61,7 +61,7 @@ static int raw_part_get_info_by_name(struct blk_desc *dev_desc,
info->start = simple_strtoul(argv[0], NULL, 0); info->start = simple_strtoul(argv[0], NULL, 0);
info->size = simple_strtoul(argv[1], NULL, 0); info->size = simple_strtoul(argv[1], NULL, 0);
info->blksz = dev_desc->blksz; info->blksz = dev_desc->blksz;
strncpy((char *)info->name, name, PART_NAME_LEN); strlcpy((char *)info->name, name, PART_NAME_LEN);
if (raw_part_desc) { if (raw_part_desc) {
if (strcmp(strsep(&raw_part_desc, " "), "mmcpart") == 0) { if (strcmp(strsep(&raw_part_desc, " "), "mmcpart") == 0) {
@ -114,7 +114,7 @@ static int part_get_info_by_name_or_alias(struct blk_desc **dev_desc,
/* check for alias */ /* check for alias */
strcpy(env_alias_name, "fastboot_partition_alias_"); strcpy(env_alias_name, "fastboot_partition_alias_");
strncat(env_alias_name, name, PART_NAME_LEN); strlcat(env_alias_name, name, PART_NAME_LEN);
aliased_part_name = env_get(env_alias_name); aliased_part_name = env_get(env_alias_name);
if (aliased_part_name != NULL) if (aliased_part_name != NULL)
ret = do_get_part_info(dev_desc, aliased_part_name, ret = do_get_part_info(dev_desc, aliased_part_name,

View File

@ -20,17 +20,18 @@
* processing. It simulates few of the SCMI services for some of the * processing. It simulates few of the SCMI services for some of the
* SCMI protocols embedded in U-Boot. Currently: * SCMI protocols embedded in U-Boot. Currently:
* - SCMI clock protocol: emulate 2 agents each exposing few clocks * - SCMI clock protocol: emulate 2 agents each exposing few clocks
* - SCMI reset protocol: emulate 1 agents each exposing a reset * - SCMI reset protocol: emulate 1 agent exposing a reset controller
* - SCMI voltage domain protocol: emulate 1 agent exposing 2 regulators
* *
* Agent #0 simulates 2 clocks and 1 reset domain. * Agent #0 simulates 2 clocks, 1 reset domain and 1 voltage domain.
* See IDs in scmi0_clk[]/scmi0_reset[] and "sandbox-scmi-agent@0" in test.dts. * See IDs in scmi0_clk[]/scmi0_reset[] and "sandbox-scmi-agent@0" in test.dts.
* *
* Agent #1 simulates 1 clock. * Agent #1 simulates 1 clock.
* See IDs in scmi1_clk[] and "sandbox-scmi-agent@1" in test.dts. * See IDs in scmi1_clk[] and "sandbox-scmi-agent@1" in test.dts.
* *
* All clocks are default disabled and reset levels down. * All clocks and regulators are default disabled and reset controller down.
* *
* This Driver exports sandbox_scmi_service_ct() for the test sequence to * This Driver exports sandbox_scmi_service_ctx() for the test sequence to
* get the state of the simulated services (clock state, rate, ...) and * get the state of the simulated services (clock state, rate, ...) and
* check back-end device state reflects the request send through the * check back-end device state reflects the request send through the
* various uclass devices, as clocks and reset controllers. * various uclass devices, as clocks and reset controllers.
@ -47,6 +48,11 @@ static struct sandbox_scmi_reset scmi0_reset[] = {
{ .id = 3 }, { .id = 3 },
}; };
static struct sandbox_scmi_voltd scmi0_voltd[] = {
{ .id = 0, .voltage_uv = 3300000 },
{ .id = 1, .voltage_uv = 1800000 },
};
static struct sandbox_scmi_clk scmi1_clk[] = { static struct sandbox_scmi_clk scmi1_clk[] = {
{ .id = 1, .rate = 44 }, { .id = 1, .rate = 44 },
}; };
@ -83,6 +89,13 @@ static void debug_print_agent_state(struct udevice *dev, char *str)
agent->reset_count, agent->reset_count,
agent->reset_count ? agent->reset[0].asserted : -1, agent->reset_count ? agent->reset[0].asserted : -1,
agent->reset_count > 1 ? agent->reset[1].asserted : -1); agent->reset_count > 1 ? agent->reset[1].asserted : -1);
dev_dbg(dev, " scmi%u_voltd (%zu): %u/%d, %u/%d, ...\n",
agent->idx,
agent->voltd_count,
agent->voltd_count ? agent->voltd[0].enabled : -1,
agent->voltd_count ? agent->voltd[0].voltage_uv : -1,
agent->voltd_count ? agent->voltd[1].enabled : -1,
agent->voltd_count ? agent->voltd[1].voltage_uv : -1);
}; };
static struct sandbox_scmi_clk *get_scmi_clk_state(uint agent_id, uint clock_id) static struct sandbox_scmi_clk *get_scmi_clk_state(uint agent_id, uint clock_id)
@ -125,6 +138,20 @@ static struct sandbox_scmi_reset *get_scmi_reset_state(uint agent_id,
return NULL; return NULL;
} }
static struct sandbox_scmi_voltd *get_scmi_voltd_state(uint agent_id,
uint domain_id)
{
size_t n;
if (agent_id == 0) {
for (n = 0; n < ARRAY_SIZE(scmi0_voltd); n++)
if (scmi0_voltd[n].id == domain_id)
return scmi0_voltd + n;
}
return NULL;
}
/* /*
* Sandbox SCMI agent ops * Sandbox SCMI agent ops
*/ */
@ -292,6 +319,160 @@ static int sandbox_scmi_rd_reset(struct udevice *dev, struct scmi_msg *msg)
return 0; return 0;
} }
static int sandbox_scmi_voltd_attribs(struct udevice *dev, struct scmi_msg *msg)
{
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_attr_in *in = NULL;
struct scmi_voltd_attr_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
!msg->out_msg || msg->out_msg_sz < sizeof(*out))
return -EINVAL;
in = (struct scmi_voltd_attr_in *)msg->in_msg;
out = (struct scmi_voltd_attr_out *)msg->out_msg;
voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
out->status = SCMI_NOT_FOUND;
} else {
memset(out, 0, sizeof(*out));
snprintf(out->name, sizeof(out->name), "regu%u", in->domain_id);
out->status = SCMI_SUCCESS;
}
return 0;
}
static int sandbox_scmi_voltd_config_set(struct udevice *dev,
struct scmi_msg *msg)
{
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_config_set_in *in = NULL;
struct scmi_voltd_config_set_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
!msg->out_msg || msg->out_msg_sz < sizeof(*out))
return -EINVAL;
in = (struct scmi_voltd_config_set_in *)msg->in_msg;
out = (struct scmi_voltd_config_set_out *)msg->out_msg;
voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
out->status = SCMI_NOT_FOUND;
} else if (in->config & ~SCMI_VOLTD_CONFIG_MASK) {
dev_err(dev, "Invalid config value 0x%x\n", in->config);
out->status = SCMI_INVALID_PARAMETERS;
} else if (in->config != SCMI_VOLTD_CONFIG_ON &&
in->config != SCMI_VOLTD_CONFIG_OFF) {
dev_err(dev, "Unexpected custom value 0x%x\n", in->config);
out->status = SCMI_INVALID_PARAMETERS;
} else {
voltd_state->enabled = in->config == SCMI_VOLTD_CONFIG_ON;
out->status = SCMI_SUCCESS;
}
return 0;
}
static int sandbox_scmi_voltd_config_get(struct udevice *dev,
struct scmi_msg *msg)
{
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_config_get_in *in = NULL;
struct scmi_voltd_config_get_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
!msg->out_msg || msg->out_msg_sz < sizeof(*out))
return -EINVAL;
in = (struct scmi_voltd_config_get_in *)msg->in_msg;
out = (struct scmi_voltd_config_get_out *)msg->out_msg;
voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
out->status = SCMI_NOT_FOUND;
} else {
if (voltd_state->enabled)
out->config = SCMI_VOLTD_CONFIG_ON;
else
out->config = SCMI_VOLTD_CONFIG_OFF;
out->status = SCMI_SUCCESS;
}
return 0;
}
static int sandbox_scmi_voltd_level_set(struct udevice *dev,
struct scmi_msg *msg)
{
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_level_set_in *in = NULL;
struct scmi_voltd_level_set_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
!msg->out_msg || msg->out_msg_sz < sizeof(*out))
return -EINVAL;
in = (struct scmi_voltd_level_set_in *)msg->in_msg;
out = (struct scmi_voltd_level_set_out *)msg->out_msg;
voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
out->status = SCMI_NOT_FOUND;
} else {
voltd_state->voltage_uv = in->voltage_level;
out->status = SCMI_SUCCESS;
}
return 0;
}
static int sandbox_scmi_voltd_level_get(struct udevice *dev,
struct scmi_msg *msg)
{
struct sandbox_scmi_agent *agent = dev_get_priv(dev);
struct scmi_voltd_level_get_in *in = NULL;
struct scmi_voltd_level_get_out *out = NULL;
struct sandbox_scmi_voltd *voltd_state = NULL;
if (!msg->in_msg || msg->in_msg_sz < sizeof(*in) ||
!msg->out_msg || msg->out_msg_sz < sizeof(*out))
return -EINVAL;
in = (struct scmi_voltd_level_get_in *)msg->in_msg;
out = (struct scmi_voltd_level_get_out *)msg->out_msg;
voltd_state = get_scmi_voltd_state(agent->idx, in->domain_id);
if (!voltd_state) {
dev_err(dev, "Unexpected domain ID %u\n", in->domain_id);
out->status = SCMI_NOT_FOUND;
} else {
out->voltage_level = voltd_state->voltage_uv;
out->status = SCMI_SUCCESS;
}
return 0;
}
static int sandbox_scmi_test_process_msg(struct udevice *dev, static int sandbox_scmi_test_process_msg(struct udevice *dev,
struct scmi_msg *msg) struct scmi_msg *msg)
{ {
@ -318,6 +499,22 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev,
break; break;
} }
break; break;
case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
switch (msg->message_id) {
case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES:
return sandbox_scmi_voltd_attribs(dev, msg);
case SCMI_VOLTAGE_DOMAIN_CONFIG_SET:
return sandbox_scmi_voltd_config_set(dev, msg);
case SCMI_VOLTAGE_DOMAIN_CONFIG_GET:
return sandbox_scmi_voltd_config_get(dev, msg);
case SCMI_VOLTAGE_DOMAIN_LEVEL_SET:
return sandbox_scmi_voltd_level_set(dev, msg);
case SCMI_VOLTAGE_DOMAIN_LEVEL_GET:
return sandbox_scmi_voltd_level_get(dev, msg);
default:
break;
}
break;
case SCMI_PROTOCOL_ID_BASE: case SCMI_PROTOCOL_ID_BASE:
case SCMI_PROTOCOL_ID_POWER_DOMAIN: case SCMI_PROTOCOL_ID_POWER_DOMAIN:
case SCMI_PROTOCOL_ID_SYSTEM: case SCMI_PROTOCOL_ID_SYSTEM:
@ -369,6 +566,8 @@ static int sandbox_scmi_test_probe(struct udevice *dev)
.clk_count = ARRAY_SIZE(scmi0_clk), .clk_count = ARRAY_SIZE(scmi0_clk),
.reset = scmi0_reset, .reset = scmi0_reset,
.reset_count = ARRAY_SIZE(scmi0_reset), .reset_count = ARRAY_SIZE(scmi0_reset),
.voltd = scmi0_voltd,
.voltd_count = ARRAY_SIZE(scmi0_voltd),
}; };
break; break;
case '1': case '1':

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
/* /*
* Copyright (C) 2020, Linaro Limited * Copyright (C) 2020-2021, Linaro Limited
*/ */
#define LOG_CATEGORY UCLASS_MISC #define LOG_CATEGORY UCLASS_MISC
@ -8,11 +8,13 @@
#include <common.h> #include <common.h>
#include <clk.h> #include <clk.h>
#include <dm.h> #include <dm.h>
#include <log.h>
#include <malloc.h> #include <malloc.h>
#include <reset.h> #include <reset.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/scmi_test.h> #include <asm/scmi_test.h>
#include <dm/device_compat.h> #include <dm/device_compat.h>
#include <power/regulator.h>
/* /*
* Simulate to some extent a SCMI exchange. * Simulate to some extent a SCMI exchange.
@ -23,16 +25,19 @@
#define SCMI_TEST_DEVICES_CLK_COUNT 3 #define SCMI_TEST_DEVICES_CLK_COUNT 3
#define SCMI_TEST_DEVICES_RD_COUNT 1 #define SCMI_TEST_DEVICES_RD_COUNT 1
#define SCMI_TEST_DEVICES_VOLTD_COUNT 2
/* /*
* struct sandbox_scmi_device_priv - Storage for device handles used by test * struct sandbox_scmi_device_priv - Storage for device handles used by test
* @clk: Array of clock instances used by tests * @clk: Array of clock instances used by tests
* @reset_clt: Array of the reset controller instances used by tests * @reset_clt: Array of the reset controller instances used by tests
* @regulators: Array of regulator device references used by the tests
* @devices: Resources exposed by sandbox_scmi_devices_ctx() * @devices: Resources exposed by sandbox_scmi_devices_ctx()
*/ */
struct sandbox_scmi_device_priv { struct sandbox_scmi_device_priv {
struct clk clk[SCMI_TEST_DEVICES_CLK_COUNT]; struct clk clk[SCMI_TEST_DEVICES_CLK_COUNT];
struct reset_ctl reset_ctl[SCMI_TEST_DEVICES_RD_COUNT]; struct reset_ctl reset_ctl[SCMI_TEST_DEVICES_RD_COUNT];
struct udevice *regulators[SCMI_TEST_DEVICES_VOLTD_COUNT];
struct sandbox_scmi_devices devices; struct sandbox_scmi_devices devices;
}; };
@ -76,6 +81,8 @@ static int sandbox_scmi_devices_probe(struct udevice *dev)
.clk_count = SCMI_TEST_DEVICES_CLK_COUNT, .clk_count = SCMI_TEST_DEVICES_CLK_COUNT,
.reset = priv->reset_ctl, .reset = priv->reset_ctl,
.reset_count = SCMI_TEST_DEVICES_RD_COUNT, .reset_count = SCMI_TEST_DEVICES_RD_COUNT,
.regul = priv->regulators,
.regul_count = SCMI_TEST_DEVICES_VOLTD_COUNT,
}; };
for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) { for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) {
@ -94,8 +101,24 @@ static int sandbox_scmi_devices_probe(struct udevice *dev)
} }
} }
for (n = 0; n < SCMI_TEST_DEVICES_VOLTD_COUNT; n++) {
char name[32];
ret = snprintf(name, sizeof(name), "regul%zu-supply", n);
assert(ret >= 0 && ret < sizeof(name));
ret = device_get_supply_regulator(dev, name,
priv->devices.regul + n);
if (ret) {
dev_err(dev, "%s: Failed on voltd %zu\n", __func__, n);
goto err_regul;
}
}
return 0; return 0;
err_regul:
n = SCMI_TEST_DEVICES_RD_COUNT;
err_reset: err_reset:
for (; n > 0; n--) for (; n > 0; n--)
reset_free(priv->devices.reset + n - 1); reset_free(priv->devices.reset + n - 1);

View File

@ -80,6 +80,16 @@ static int scmi_bind_protocols(struct udevice *dev)
if (IS_ENABLED(CONFIG_RESET_SCMI)) if (IS_ENABLED(CONFIG_RESET_SCMI))
drv = DM_DRIVER_GET(scmi_reset_domain); drv = DM_DRIVER_GET(scmi_reset_domain);
break; break;
case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN:
if (IS_ENABLED(CONFIG_DM_REGULATOR_SCMI)) {
node = ofnode_find_subnode(node, "regulators");
if (!ofnode_valid(node)) {
dev_err(dev, "no regulators node\n");
return -ENXIO;
}
drv = DM_DRIVER_GET(scmi_voltage_domain);
}
break;
default: default:
break; break;
} }

View File

@ -41,8 +41,13 @@ int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt)
if (ret) if (ret)
return ret; return ret;
faddr = cpu_to_fdt32(resource.start); /* TEMP workaround for ofnode_read_resource translation issue */
paddr = ofnode_translate_address(args.node, &faddr); if (of_live_active()) {
paddr = resource.start;
} else {
faddr = cpu_to_fdt32(resource.start);
paddr = ofnode_translate_address(args.node, &faddr);
}
smt->size = resource_size(&resource); smt->size = resource_size(&resource);
if (smt->size < sizeof(struct scmi_smt_header)) { if (smt->size < sizeof(struct scmi_smt_header)) {
@ -56,8 +61,10 @@ int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt)
#ifdef CONFIG_ARM #ifdef CONFIG_ARM
if (dcache_status()) if (dcache_status())
mmu_set_region_dcache_behaviour((uintptr_t)smt->buf, mmu_set_region_dcache_behaviour(ALIGN_DOWN((uintptr_t)smt->buf, MMU_SECTION_SIZE),
smt->size, DCACHE_OFF); ALIGN(smt->size, MMU_SECTION_SIZE),
DCACHE_OFF);
#endif #endif
return 0; return 0;

View File

@ -713,17 +713,6 @@ int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags)
return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags); return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags);
} }
int dm_gpio_set_dir(struct gpio_desc *desc)
{
int ret;
ret = check_reserved(desc, "set_dir");
if (ret)
return ret;
return _dm_gpio_set_flags(desc, desc->flags);
}
int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr, int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr,
ulong set) ulong set)
{ {

View File

@ -48,12 +48,13 @@ static int i2c_gpio_sda_get(struct i2c_gpio_bus *bus)
static void i2c_gpio_sda_set(struct i2c_gpio_bus *bus, int bit) static void i2c_gpio_sda_set(struct i2c_gpio_bus *bus, int bit)
{ {
struct gpio_desc *sda = &bus->gpios[PIN_SDA]; struct gpio_desc *sda = &bus->gpios[PIN_SDA];
ulong flags;
if (bit) if (bit)
sda->flags = (sda->flags & ~GPIOD_IS_OUT) | GPIOD_IS_IN; flags = GPIOD_IS_IN;
else else
sda->flags = (sda->flags & (~GPIOD_IS_IN & ~GPIOD_IS_OUT_ACTIVE)) | GPIOD_IS_OUT; flags = GPIOD_IS_OUT;
dm_gpio_set_dir(sda); dm_gpio_clrset_flags(sda, GPIOD_MASK_DIR, flags);
} }
static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit) static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit)
@ -62,16 +63,14 @@ static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit)
int count = 0; int count = 0;
if (bit) { if (bit) {
scl->flags = (scl->flags & ~GPIOD_IS_OUT) | GPIOD_IS_IN; dm_gpio_clrset_flags(scl, GPIOD_MASK_DIR, GPIOD_IS_IN);
dm_gpio_set_dir(scl);
while (!dm_gpio_get_value(scl) && count++ < 100000) while (!dm_gpio_get_value(scl) && count++ < 100000)
udelay(1); udelay(1);
if (!dm_gpio_get_value(scl)) if (!dm_gpio_get_value(scl))
pr_err("timeout waiting on slave to release scl\n"); pr_err("timeout waiting on slave to release scl\n");
} else { } else {
scl->flags = (scl->flags & (~GPIOD_IS_IN & ~GPIOD_IS_OUT_ACTIVE)) | GPIOD_IS_OUT; dm_gpio_clrset_flags(scl, GPIOD_MASK_DIR, GPIOD_IS_OUT);
dm_gpio_set_dir(scl);
} }
} }
@ -79,11 +78,11 @@ static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit)
static void i2c_gpio_scl_set_output_only(struct i2c_gpio_bus *bus, int bit) static void i2c_gpio_scl_set_output_only(struct i2c_gpio_bus *bus, int bit)
{ {
struct gpio_desc *scl = &bus->gpios[PIN_SCL]; struct gpio_desc *scl = &bus->gpios[PIN_SCL];
scl->flags = (scl->flags & (~GPIOD_IS_IN & ~GPIOD_IS_OUT_ACTIVE)) | GPIOD_IS_OUT; ulong flags = GPIOD_IS_OUT;
if (bit) if (bit)
scl->flags |= GPIOD_IS_OUT_ACTIVE; flags |= GPIOD_IS_OUT_ACTIVE;
dm_gpio_set_dir(scl); dm_gpio_clrset_flags(scl, GPIOD_MASK_DIR, flags);
} }
static void i2c_gpio_write_bit(struct i2c_gpio_bus *bus, int delay, uchar bit) static void i2c_gpio_write_bit(struct i2c_gpio_bus *bus, int delay, uchar bit)

View File

@ -368,8 +368,22 @@ config WINBOND_W83627
config QFW config QFW
bool bool
help help
Hidden option to enable QEMU fw_cfg interface. This will be selected by Hidden option to enable QEMU fw_cfg interface and uclass. This will
either CONFIG_CMD_QFW or CONFIG_GENERATE_ACPI_TABLE. be selected by either CONFIG_CMD_QFW or CONFIG_GENERATE_ACPI_TABLE.
config QFW_PIO
bool
depends on QFW
help
Hidden option to enable PIO QEMU fw_cfg interface. This will be
selected by the appropriate QEMU board.
config QFW_MMIO
bool
depends on QFW
help
Hidden option to enable MMIO QEMU fw_cfg interface. This will be
selected by the appropriate QEMU board.
config I2C_EEPROM config I2C_EEPROM
bool "Enable driver for generic I2C-attached EEPROMs" bool "Enable driver for generic I2C-attached EEPROMs"

View File

@ -55,7 +55,12 @@ obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
obj-$(CONFIG_P2SB) += p2sb-uclass.o obj-$(CONFIG_P2SB) += p2sb-uclass.o
obj-$(CONFIG_PCA9551_LED) += pca9551_led.o obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
obj-$(CONFIG_QFW) += qfw.o ifdef CONFIG_QFW
obj-y += qfw.o
obj-$(CONFIG_QFW_PIO) += qfw_pio.o
obj-$(CONFIG_QFW_MMIO) += qfw_mmio.o
obj-$(CONFIG_SANDBOX) += qfw_sandbox.o
endif
obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o
obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o obj-$(CONFIG_SANDBOX) += syscon_sandbox.o misc_sandbox.o

View File

@ -1,25 +1,22 @@
// SPDX-License-Identifier: GPL-2.0+ // SPDX-License-Identifier: GPL-2.0+
/* /*
* (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com> * (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
* (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
*/ */
#define LOG_CATEGORY UCLASS_QFW
#include <common.h> #include <common.h>
#include <command.h> #include <command.h>
#include <errno.h> #include <errno.h>
#include <log.h> #include <log.h>
#include <malloc.h> #include <malloc.h>
#include <qfw.h> #include <qfw.h>
#include <asm/io.h> #include <dm.h>
#include <misc.h>
#ifdef CONFIG_GENERATE_ACPI_TABLE #ifdef CONFIG_GENERATE_ACPI_TABLE
#include <asm/tables.h> #include <asm/tables.h>
#endif #endif
#include <linux/list.h>
static bool fwcfg_present;
static bool fwcfg_dma_present;
static struct fw_cfg_arch_ops *fwcfg_arch_ops;
static LIST_HEAD(fw_list);
#ifdef CONFIG_GENERATE_ACPI_TABLE #ifdef CONFIG_GENERATE_ACPI_TABLE
/* /*
@ -32,7 +29,8 @@ static LIST_HEAD(fw_list);
* be ignored. * be ignored.
* @return: 0 on success, or negative value on failure * @return: 0 on success, or negative value on failure
*/ */
static int bios_linker_allocate(struct bios_linker_entry *entry, ulong *addr) static int bios_linker_allocate(struct udevice *dev,
struct bios_linker_entry *entry, ulong *addr)
{ {
uint32_t size, align; uint32_t size, align;
struct fw_file *file; struct fw_file *file;
@ -45,7 +43,7 @@ static int bios_linker_allocate(struct bios_linker_entry *entry, ulong *addr)
return -EINVAL; return -EINVAL;
} }
file = qemu_fwcfg_find_file(entry->alloc.file); file = qfw_find_file(dev, entry->alloc.file);
if (!file) { if (!file) {
printf("error: can't find file %s\n", entry->alloc.file); printf("error: can't find file %s\n", entry->alloc.file);
return -ENOENT; return -ENOENT;
@ -75,8 +73,8 @@ static int bios_linker_allocate(struct bios_linker_entry *entry, ulong *addr)
debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n", debug("bios_linker_allocate: allocate file %s, size %u, zone %d, align %u, addr 0x%lx\n",
file->cfg.name, size, entry->alloc.zone, align, aligned_addr); file->cfg.name, size, entry->alloc.zone, align, aligned_addr);
qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select), qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size,
size, (void *)aligned_addr); (void *)aligned_addr);
file->addr = aligned_addr; file->addr = aligned_addr;
/* adjust address for low memory allocation */ /* adjust address for low memory allocation */
@ -94,16 +92,17 @@ static int bios_linker_allocate(struct bios_linker_entry *entry, ulong *addr)
* ACPI tables * ACPI tables
* @return: 0 on success, or negative value on failure * @return: 0 on success, or negative value on failure
*/ */
static int bios_linker_add_pointer(struct bios_linker_entry *entry) static int bios_linker_add_pointer(struct udevice *dev,
struct bios_linker_entry *entry)
{ {
struct fw_file *dest, *src; struct fw_file *dest, *src;
uint32_t offset = le32_to_cpu(entry->pointer.offset); uint32_t offset = le32_to_cpu(entry->pointer.offset);
uint64_t pointer = 0; uint64_t pointer = 0;
dest = qemu_fwcfg_find_file(entry->pointer.dest_file); dest = qfw_find_file(dev, entry->pointer.dest_file);
if (!dest || !dest->addr) if (!dest || !dest->addr)
return -ENOENT; return -ENOENT;
src = qemu_fwcfg_find_file(entry->pointer.src_file); src = qfw_find_file(dev, entry->pointer.src_file);
if (!src || !src->addr) if (!src || !src->addr)
return -ENOENT; return -ENOENT;
@ -127,13 +126,14 @@ static int bios_linker_add_pointer(struct bios_linker_entry *entry)
* checksums * checksums
* @return: 0 on success, or negative value on failure * @return: 0 on success, or negative value on failure
*/ */
static int bios_linker_add_checksum(struct bios_linker_entry *entry) static int bios_linker_add_checksum(struct udevice *dev,
struct bios_linker_entry *entry)
{ {
struct fw_file *file; struct fw_file *file;
uint8_t *data, cksum = 0; uint8_t *data, cksum = 0;
uint8_t *cksum_start; uint8_t *cksum_start;
file = qemu_fwcfg_find_file(entry->cksum.file); file = qfw_find_file(dev, entry->cksum.file);
if (!file || !file->addr) if (!file || !file->addr)
return -ENOENT; return -ENOENT;
@ -149,20 +149,27 @@ static int bios_linker_add_checksum(struct bios_linker_entry *entry)
/* This function loads and patches ACPI tables provided by QEMU */ /* This function loads and patches ACPI tables provided by QEMU */
ulong write_acpi_tables(ulong addr) ulong write_acpi_tables(ulong addr)
{ {
int i, ret = 0; int i, ret;
struct fw_file *file; struct fw_file *file;
struct bios_linker_entry *table_loader; struct bios_linker_entry *table_loader;
struct bios_linker_entry *entry; struct bios_linker_entry *entry;
uint32_t size; uint32_t size;
struct udevice *dev;
ret = qfw_get_dev(&dev);
if (ret) {
printf("error: no qfw\n");
return addr;
}
/* make sure fw_list is loaded */ /* make sure fw_list is loaded */
ret = qemu_fwcfg_read_firmware_list(); ret = qfw_read_firmware_list(dev);
if (ret) { if (ret) {
printf("error: can't read firmware file list\n"); printf("error: can't read firmware file list\n");
return addr; return addr;
} }
file = qemu_fwcfg_find_file("etc/table-loader"); file = qfw_find_file(dev, "etc/table-loader");
if (!file) { if (!file) {
printf("error: can't find etc/table-loader\n"); printf("error: can't find etc/table-loader\n");
return addr; return addr;
@ -180,24 +187,23 @@ ulong write_acpi_tables(ulong addr)
return addr; return addr;
} }
qemu_fwcfg_read_entry(be16_to_cpu(file->cfg.select), qfw_read_entry(dev, be16_to_cpu(file->cfg.select), size, table_loader);
size, table_loader);
for (i = 0; i < (size / sizeof(*entry)); i++) { for (i = 0; i < (size / sizeof(*entry)); i++) {
entry = table_loader + i; entry = table_loader + i;
switch (le32_to_cpu(entry->command)) { switch (le32_to_cpu(entry->command)) {
case BIOS_LINKER_LOADER_COMMAND_ALLOCATE: case BIOS_LINKER_LOADER_COMMAND_ALLOCATE:
ret = bios_linker_allocate(entry, &addr); ret = bios_linker_allocate(dev, entry, &addr);
if (ret) if (ret)
goto out; goto out;
break; break;
case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER: case BIOS_LINKER_LOADER_COMMAND_ADD_POINTER:
ret = bios_linker_add_pointer(entry); ret = bios_linker_add_pointer(dev, entry);
if (ret) if (ret)
goto out; goto out;
break; break;
case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM: case BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM:
ret = bios_linker_add_checksum(entry); ret = bios_linker_add_checksum(dev, entry);
if (ret) if (ret)
goto out; goto out;
break; break;
@ -209,9 +215,9 @@ ulong write_acpi_tables(ulong addr)
out: out:
if (ret) { if (ret) {
struct fw_cfg_file_iter iter; struct fw_cfg_file_iter iter;
for (file = qemu_fwcfg_file_iter_init(&iter); for (file = qfw_file_iter_init(dev, &iter);
!qemu_fwcfg_file_iter_end(&iter); !qfw_file_iter_end(&iter);
file = qemu_fwcfg_file_iter_next(&iter)) { file = qfw_file_iter_next(&iter)) {
if (file->addr) { if (file->addr) {
free((void *)file->addr); free((void *)file->addr);
file->addr = 0; file->addr = 0;
@ -225,170 +231,89 @@ out:
ulong acpi_get_rsdp_addr(void) ulong acpi_get_rsdp_addr(void)
{ {
int ret;
struct fw_file *file; struct fw_file *file;
struct udevice *dev;
file = qemu_fwcfg_find_file("etc/acpi/rsdp"); ret = qfw_get_dev(&dev);
if (ret) {
printf("error: no qfw\n");
return 0;
}
file = qfw_find_file(dev, "etc/acpi/rsdp");
return file->addr; return file->addr;
} }
#endif #endif
/* Read configuration item using fw_cfg PIO interface */ static void qfw_read_entry_io(struct qfw_dev *qdev, u16 entry, u32 size,
static void qemu_fwcfg_read_entry_pio(uint16_t entry, void *address)
uint32_t size, void *address)
{ {
debug("qemu_fwcfg_read_entry_pio: entry 0x%x, size %u address %p\n", struct dm_qfw_ops *ops = dm_qfw_get_ops(qdev->dev);
entry, size, address);
return fwcfg_arch_ops->arch_read_pio(entry, size, address); debug("%s: entry 0x%x, size %u address %p\n", __func__, entry, size,
address);
ops->read_entry_io(qdev->dev, entry, size, address);
} }
/* Read configuration item using fw_cfg DMA interface */ static void qfw_read_entry_dma(struct qfw_dev *qdev, u16 entry, u32 size,
static void qemu_fwcfg_read_entry_dma(uint16_t entry, void *address)
uint32_t size, void *address)
{ {
struct fw_cfg_dma_access dma; struct dm_qfw_ops *ops = dm_qfw_get_ops(qdev->dev);
dma.length = cpu_to_be32(size); struct qfw_dma dma = {
dma.address = cpu_to_be64((uintptr_t)address); .length = cpu_to_be32(size),
dma.control = cpu_to_be32(FW_CFG_DMA_READ); .address = cpu_to_be64((uintptr_t)address),
.control = cpu_to_be32(FW_CFG_DMA_READ),
};
/* /*
* writting FW_CFG_INVALID will cause read operation to resume at * writing FW_CFG_INVALID will cause read operation to resume at last
* last offset, otherwise read will start at offset 0 * offset, otherwise read will start at offset 0
*/ */
if (entry != FW_CFG_INVALID) if (entry != FW_CFG_INVALID)
dma.control |= cpu_to_be32(FW_CFG_DMA_SELECT | (entry << 16)); dma.control |= cpu_to_be32(FW_CFG_DMA_SELECT | (entry << 16));
barrier(); debug("%s: entry 0x%x, size %u address %p, control 0x%x\n", __func__,
debug("qemu_fwcfg_read_entry_dma: entry 0x%x, size %u address %p, control 0x%x\n",
entry, size, address, be32_to_cpu(dma.control)); entry, size, address, be32_to_cpu(dma.control));
fwcfg_arch_ops->arch_read_dma(&dma); barrier();
ops->read_entry_dma(qdev->dev, &dma);
} }
bool qemu_fwcfg_present(void) void qfw_read_entry(struct udevice *dev, u16 entry, u32 size, void *address)
{ {
return fwcfg_present; struct qfw_dev *qdev = dev_get_uclass_priv(dev);
}
bool qemu_fwcfg_dma_present(void) if (qdev->dma_present)
{ qfw_read_entry_dma(qdev, entry, size, address);
return fwcfg_dma_present;
}
void qemu_fwcfg_read_entry(uint16_t entry, uint32_t length, void *address)
{
if (fwcfg_dma_present)
qemu_fwcfg_read_entry_dma(entry, length, address);
else else
qemu_fwcfg_read_entry_pio(entry, length, address); qfw_read_entry_io(qdev, entry, size, address);
} }
int qemu_fwcfg_online_cpus(void) int qfw_register(struct udevice *dev)
{ {
uint16_t nb_cpus; struct qfw_dev *qdev = dev_get_uclass_priv(dev);
u32 qemu, dma_enabled;
if (!fwcfg_present) qdev->dev = dev;
INIT_LIST_HEAD(&qdev->fw_list);
qfw_read_entry_io(qdev, FW_CFG_SIGNATURE, 4, &qemu);
if (be32_to_cpu(qemu) != QEMU_FW_CFG_SIGNATURE)
return -ENODEV; return -ENODEV;
qemu_fwcfg_read_entry(FW_CFG_NB_CPUS, 2, &nb_cpus); qfw_read_entry_io(qdev, FW_CFG_ID, 1, &dma_enabled);
if (dma_enabled & FW_CFG_DMA_ENABLED)
return le16_to_cpu(nb_cpus); qdev->dma_present = true;
}
int qemu_fwcfg_read_firmware_list(void)
{
int i;
uint32_t count;
struct fw_file *file;
struct list_head *entry;
/* don't read it twice */
if (!list_empty(&fw_list))
return 0;
qemu_fwcfg_read_entry(FW_CFG_FILE_DIR, 4, &count);
if (!count)
return 0;
count = be32_to_cpu(count);
for (i = 0; i < count; i++) {
file = malloc(sizeof(*file));
if (!file) {
printf("error: allocating resource\n");
goto err;
}
qemu_fwcfg_read_entry(FW_CFG_INVALID,
sizeof(struct fw_cfg_file), &file->cfg);
file->addr = 0;
list_add_tail(&file->list, &fw_list);
}
return 0; return 0;
err:
list_for_each(entry, &fw_list) {
file = list_entry(entry, struct fw_file, list);
free(file);
}
return -ENOMEM;
} }
struct fw_file *qemu_fwcfg_find_file(const char *name) UCLASS_DRIVER(qfw) = {
{ .id = UCLASS_QFW,
struct list_head *entry; .name = "qfw",
struct fw_file *file; .per_device_auto = sizeof(struct qfw_dev),
};
list_for_each(entry, &fw_list) {
file = list_entry(entry, struct fw_file, list);
if (!strcmp(file->cfg.name, name))
return file;
}
return NULL;
}
struct fw_file *qemu_fwcfg_file_iter_init(struct fw_cfg_file_iter *iter)
{
iter->entry = fw_list.next;
return list_entry((struct list_head *)iter->entry,
struct fw_file, list);
}
struct fw_file *qemu_fwcfg_file_iter_next(struct fw_cfg_file_iter *iter)
{
iter->entry = ((struct list_head *)iter->entry)->next;
return list_entry((struct list_head *)iter->entry,
struct fw_file, list);
}
bool qemu_fwcfg_file_iter_end(struct fw_cfg_file_iter *iter)
{
return iter->entry == &fw_list;
}
void qemu_fwcfg_init(struct fw_cfg_arch_ops *ops)
{
uint32_t qemu;
uint32_t dma_enabled;
fwcfg_present = false;
fwcfg_dma_present = false;
fwcfg_arch_ops = NULL;
if (!ops || !ops->arch_read_pio || !ops->arch_read_dma)
return;
fwcfg_arch_ops = ops;
qemu_fwcfg_read_entry_pio(FW_CFG_SIGNATURE, 4, &qemu);
if (be32_to_cpu(qemu) == QEMU_FW_CFG_SIGNATURE)
fwcfg_present = true;
if (fwcfg_present) {
qemu_fwcfg_read_entry_pio(FW_CFG_ID, 1, &dma_enabled);
if (dma_enabled & FW_CFG_DMA_ENABLED)
fwcfg_dma_present = true;
}
}

119
drivers/misc/qfw_mmio.c Normal file
View File

@ -0,0 +1,119 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* MMIO interface for QFW
*
* (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
* (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
*/
#define LOG_CATEGORY UCLASS_QFW
#include <asm/types.h>
#include <asm/io.h>
#include <dm.h>
#include <dm/device.h>
#include <qfw.h>
struct qfw_mmio {
/*
* Each access to the 64-bit data register can be 8/16/32/64 bits wide.
*/
union {
u8 data8;
u16 data16;
u32 data32;
u64 data64;
};
u16 selector;
u8 padding[6];
u64 dma;
};
struct qfw_mmio_plat {
volatile struct qfw_mmio *mmio;
};
static void qfw_mmio_read_entry_io(struct udevice *dev, u16 entry, u32 size,
void *address)
{
struct qfw_mmio_plat *plat = dev_get_plat(dev);
/*
* writing FW_CFG_INVALID will cause read operation to resume at last
* offset, otherwise read will start at offset 0
*
* Note: on platform where the control register is MMIO, the register
* is big endian.
*/
if (entry != FW_CFG_INVALID)
plat->mmio->selector = cpu_to_be16(entry);
/* the endianness of data register is string-preserving */
while (size >= 8) {
*(u64 *)address = plat->mmio->data64;
address += 8;
size -= 8;
}
while (size >= 4) {
*(u32 *)address = plat->mmio->data32;
address += 4;
size -= 4;
}
while (size >= 2) {
*(u16 *)address = plat->mmio->data16;
address += 2;
size -= 2;
}
while (size >= 1) {
*(u8 *)address = plat->mmio->data8;
address += 1;
size -= 1;
}
}
/* Read configuration item using fw_cfg DMA interface */
static void qfw_mmio_read_entry_dma(struct udevice *dev, struct qfw_dma *dma)
{
struct qfw_mmio_plat *plat = dev_get_plat(dev);
/* the DMA address register is big-endian */
plat->mmio->dma = cpu_to_be64((uintptr_t)dma);
while (be32_to_cpu(dma->control) & ~FW_CFG_DMA_ERROR);
}
static int qfw_mmio_of_to_plat(struct udevice *dev)
{
struct qfw_mmio_plat *plat = dev_get_plat(dev);
plat->mmio = map_physmem(dev_read_addr(dev),
sizeof(struct qfw_mmio),
MAP_NOCACHE);
return 0;
}
static int qfw_mmio_probe(struct udevice *dev)
{
return qfw_register(dev);
}
static struct dm_qfw_ops qfw_mmio_ops = {
.read_entry_io = qfw_mmio_read_entry_io,
.read_entry_dma = qfw_mmio_read_entry_dma,
};
static const struct udevice_id qfw_mmio_ids[] = {
{ .compatible = "qemu,fw-cfg-mmio" },
{}
};
U_BOOT_DRIVER(qfw_mmio) = {
.name = "qfw_mmio",
.id = UCLASS_QFW,
.of_match = qfw_mmio_ids,
.plat_auto = sizeof(struct qfw_mmio_plat),
.of_to_plat = qfw_mmio_of_to_plat,
.probe = qfw_mmio_probe,
.ops = &qfw_mmio_ops,
};

69
drivers/misc/qfw_pio.c Normal file
View File

@ -0,0 +1,69 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* PIO interface for QFW
*
* (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
* (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
*/
#define LOG_CATEGORY UCLASS_QFW
#include <asm/io.h>
#include <dm/device.h>
#include <qfw.h>
/*
* PIO ports are correct for x86, which appears to be the only arch that uses
* PIO.
*/
#define FW_CONTROL_PORT 0x510
#define FW_DATA_PORT 0x511
#define FW_DMA_PORT_LOW 0x514
#define FW_DMA_PORT_HIGH 0x518
static void qfw_pio_read_entry_io(struct udevice *dev, u16 entry, u32 size,
void *address)
{
/*
* writing FW_CFG_INVALID will cause read operation to resume at last
* offset, otherwise read will start at offset 0
*
* Note: on platform where the control register is IO port, the
* endianness is little endian.
*/
if (entry != FW_CFG_INVALID)
outw(cpu_to_le16(entry), FW_CONTROL_PORT);
/* the endianness of data register is string-preserving */
u32 i = 0;
u8 *data = address;
while (size--)
data[i++] = inb(FW_DATA_PORT);
}
/* Read configuration item using fw_cfg DMA interface */
static void qfw_pio_read_entry_dma(struct udevice *dev, struct qfw_dma *dma)
{
/* the DMA address register is big-endian */
outl(cpu_to_be32((uintptr_t)dma), FW_DMA_PORT_HIGH);
while (be32_to_cpu(dma->control) & ~FW_CFG_DMA_ERROR);
}
static int qfw_pio_probe(struct udevice *dev)
{
return qfw_register(dev);
}
static struct dm_qfw_ops qfw_pio_ops = {
.read_entry_io = qfw_pio_read_entry_io,
.read_entry_dma = qfw_pio_read_entry_dma,
};
U_BOOT_DRIVER(qfw_pio) = {
.name = "qfw_pio",
.id = UCLASS_QFW,
.probe = qfw_pio_probe,
.ops = &qfw_pio_ops,
};

127
drivers/misc/qfw_sandbox.c Normal file
View File

@ -0,0 +1,127 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Sandbox interface for QFW
*
* (C) Copyright 2015 Miao Yan <yanmiaobest@gmail.com>
* (C) Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
*/
#define LOG_CATEGORY UCLASS_QFW
#include <asm/types.h>
#include <asm/io.h>
#include <dm.h>
#include <dm/device.h>
#include <qfw.h>
struct qfw_sandbox_plat {
u8 file_dir_offset;
};
static void qfw_sandbox_read_entry_io(struct udevice *dev, u16 entry, u32 size,
void *address)
{
debug("%s: entry 0x%x size %u address %p\n", __func__, entry, size,
address);
switch (entry) {
case FW_CFG_SIGNATURE:
if (size == 4)
*((u32 *)address) = cpu_to_be32(QEMU_FW_CFG_SIGNATURE);
break;
case FW_CFG_ID:
/* Advertise DMA support */
if (size == 1)
*((u8 *)address) = FW_CFG_DMA_ENABLED;
break;
default:
debug("%s got unsupported entry 0x%x\n", __func__, entry);
/*
* Sandbox driver doesn't support other entries here, assume we use DMA
* to read them -- the uclass driver will exclusively use it when
* advertised.
*/
}
}
static void qfw_sandbox_read_entry_dma(struct udevice *dev, struct qfw_dma *dma)
{
u16 entry;
u32 control = be32_to_cpu(dma->control);
void *address = (void *)be64_to_cpu(dma->address);
u32 length = be32_to_cpu(dma->length);
struct qfw_sandbox_plat *plat = dev_get_plat(dev);
struct fw_cfg_file *file;
debug("%s\n", __func__);
if (!(control & FW_CFG_DMA_READ))
return;
if (control & FW_CFG_DMA_SELECT) {
/* Start new read. */
entry = control >> 16;
/* Arbitrary values to be used by tests. */
switch (entry) {
case FW_CFG_NB_CPUS:
if (length == 2)
*((u16 *)address) = cpu_to_le16(5);
break;
case FW_CFG_FILE_DIR:
if (length == 4) {
*((u32 *)address) = cpu_to_be32(2);
plat->file_dir_offset = 1;
}
break;
default:
debug("%s got unsupported entry 0x%x\n", __func__,
entry);
}
} else if (plat->file_dir_offset && length == 64) {
file = address;
switch (plat->file_dir_offset) {
case 1:
file->size = cpu_to_be32(8);
file->select = cpu_to_be16(FW_CFG_FILE_FIRST);
strcpy(file->name, "test-one");
plat->file_dir_offset++;
break;
case 2:
file->size = cpu_to_be32(8);
file->select = cpu_to_be16(FW_CFG_FILE_FIRST + 1);
strcpy(file->name, "test-two");
plat->file_dir_offset++;
break;
}
}
/*
* Signal that we are finished. No-one checks this in sandbox --
* normally the platform-specific driver looks for it -- but let's
* replicate the behaviour in case someone relies on it later.
*/
dma->control = 0;
}
static int qfw_sandbox_probe(struct udevice *dev)
{
return qfw_register(dev);
}
static struct dm_qfw_ops qfw_sandbox_ops = {
.read_entry_io = qfw_sandbox_read_entry_io,
.read_entry_dma = qfw_sandbox_read_entry_dma,
};
U_BOOT_DRIVER(qfw_sandbox) = {
.name = "qfw_sandbox",
.id = UCLASS_QFW,
.plat_auto = sizeof(struct qfw_sandbox_plat),
.probe = qfw_sandbox_probe,
.ops = &qfw_sandbox_ops,
};
U_BOOT_DRVINFO(qfw_sandbox) = {
.name = "qfw_sandbox",
};

View File

@ -3559,6 +3559,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
__func__, page); __func__, page);
instr->state = MTD_ERASE_FAILED; instr->state = MTD_ERASE_FAILED;
instr->fail_addr =
((loff_t)page << chip->page_shift);
goto erase_exit; goto erase_exit;
} }

View File

@ -88,8 +88,9 @@ static void dm_pciauto_setup_device(struct udevice *dev, int bars_num,
else else
bar_res = mem; bar_res = mem;
debug("PCI Autoconfig: BAR %d, %s, size=0x%llx, ", debug("PCI Autoconfig: BAR %d, %s%s, size=0x%llx, ",
bar_nr, bar_res == prefetch ? "Prf" : "Mem", bar_nr, bar_res == prefetch ? "Prf" : "Mem",
found_mem64 ? "64" : "",
(unsigned long long)bar_size); (unsigned long long)bar_size);
} }

View File

@ -30,7 +30,6 @@ obj-$(CONFIG_$(SPL_)PMIC_LP87565) += lp87565.o
obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o obj-$(CONFIG_PMIC_STPMIC1) += stpmic1.o
obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o obj-$(CONFIG_POWER_LTC3676) += pmic_ltc3676.o
obj-$(CONFIG_POWER_MAX77696) += pmic_max77696.o
obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
obj-$(CONFIG_POWER_PCA9450) += pmic_pca9450.o obj-$(CONFIG_POWER_PCA9450) += pmic_pca9450.o
obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o

View File

@ -1,31 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
* Fabio Estevam <fabio.estevam@freescale.com>
*/
#include <common.h>
#include <errno.h>
#include <i2c.h>
#include <power/pmic.h>
#include <power/max77696_pmic.h>
int power_max77696_init(unsigned char bus)
{
static const char name[] = "MAX77696";
struct pmic *p = pmic_alloc();
if (!p) {
printf("%s: POWER allocation error!\n", __func__);
return -ENOMEM;
}
p->name = name;
p->interface = PMIC_I2C;
p->number_of_regs = PMIC_NUM_OF_REGS;
p->hw.i2c.addr = CONFIG_POWER_MAX77696_I2C_ADDR;
p->hw.i2c.tx_num = 1;
p->bus = bus;
return 0;
}

View File

@ -353,3 +353,11 @@ config DM_REGULATOR_TPS65941
TPS65941 series of PMICs have 5 single phase BUCKs that can also TPS65941 series of PMICs have 5 single phase BUCKs that can also
be configured in multi phase modes & 4 LDOs. The driver implements be configured in multi phase modes & 4 LDOs. The driver implements
get/set api for value and enable. get/set api for value and enable.
config DM_REGULATOR_SCMI
bool "Enable driver for SCMI voltage domain regulators"
depends on DM_REGULATOR
select SCMI_AGENT
help
Enable this option if you want to support regulators exposed through
the SCMI voltage domain protocol by a SCMI server.

View File

@ -30,3 +30,4 @@ obj-$(CONFIG_DM_REGULATOR_TPS65910) += tps65910_regulator.o
obj-$(CONFIG_DM_REGULATOR_TPS62360) += tps62360_regulator.o obj-$(CONFIG_DM_REGULATOR_TPS62360) += tps62360_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o obj-$(CONFIG_$(SPL_)DM_REGULATOR_STPMIC1) += stpmic1.o
obj-$(CONFIG_DM_REGULATOR_TPS65941) += tps65941_regulator.o obj-$(CONFIG_DM_REGULATOR_TPS65941) += tps65941_regulator.o
obj-$(CONFIG_DM_REGULATOR_SCMI) += scmi_regulator.o

View File

@ -0,0 +1,195 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2020-2021 Linaro Limited
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <scmi_agent.h>
#include <scmi_protocols.h>
#include <asm/types.h>
#include <dm/device.h>
#include <dm/device_compat.h>
#include <dm/device-internal.h>
#include <linux/kernel.h>
#include <power/regulator.h>
/**
* struct scmi_regulator_platdata - Platform data for a scmi voltage domain regulator
* @domain_id: ID representing the regulator for the related SCMI agent
*/
struct scmi_regulator_platdata {
u32 domain_id;
};
static int scmi_voltd_set_enable(struct udevice *dev, bool enable)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
struct scmi_voltd_config_set_in in = {
.domain_id = pdata->domain_id,
.config = enable ? SCMI_VOLTD_CONFIG_ON : SCMI_VOLTD_CONFIG_OFF,
};
struct scmi_voltd_config_set_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
SCMI_VOLTAGE_DOMAIN_CONFIG_SET,
in, out);
int ret;
ret = devm_scmi_process_msg(dev->parent->parent, &msg);
if (ret)
return ret;
ret = scmi_to_linux_errno(out.status);
if (ret)
return ret;
return ret;
}
static int scmi_voltd_get_enable(struct udevice *dev)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
struct scmi_voltd_config_get_in in = {
.domain_id = pdata->domain_id,
};
struct scmi_voltd_config_get_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
SCMI_VOLTAGE_DOMAIN_CONFIG_GET,
in, out);
int ret;
ret = devm_scmi_process_msg(dev->parent->parent, &msg);
if (ret < 0)
return ret;
ret = scmi_to_linux_errno(out.status);
if (ret < 0)
return ret;
return out.config == SCMI_VOLTD_CONFIG_ON;
}
static int scmi_voltd_set_voltage_level(struct udevice *dev, int uV)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
struct scmi_voltd_level_set_in in = {
.domain_id = pdata->domain_id,
.voltage_level = uV,
};
struct scmi_voltd_level_set_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
SCMI_VOLTAGE_DOMAIN_LEVEL_SET,
in, out);
int ret;
ret = devm_scmi_process_msg(dev->parent->parent, &msg);
if (ret < 0)
return ret;
return scmi_to_linux_errno(out.status);
}
static int scmi_voltd_get_voltage_level(struct udevice *dev)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
struct scmi_voltd_level_get_in in = {
.domain_id = pdata->domain_id,
};
struct scmi_voltd_level_get_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
SCMI_VOLTAGE_DOMAIN_LEVEL_GET,
in, out);
int ret;
ret = devm_scmi_process_msg(dev->parent->parent, &msg);
if (ret < 0)
return ret;
ret = scmi_to_linux_errno(out.status);
if (ret < 0)
return ret;
return out.voltage_level;
}
static int scmi_regulator_of_to_plat(struct udevice *dev)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
fdt_addr_t reg;
reg = dev_read_addr(dev);
if (reg == FDT_ADDR_T_NONE)
return -EINVAL;
pdata->domain_id = (u32)reg;
return 0;
}
static int scmi_regulator_probe(struct udevice *dev)
{
struct scmi_regulator_platdata *pdata = dev_get_plat(dev);
struct scmi_voltd_attr_in in = { 0 };
struct scmi_voltd_attr_out out = { 0 };
struct scmi_msg scmi_msg = {
.protocol_id = SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,
.message_id = SCMI_VOLTAGE_DOMAIN_ATTRIBUTES,
.in_msg = (u8 *)&in,
.in_msg_sz = sizeof(in),
.out_msg = (u8 *)&out,
.out_msg_sz = sizeof(out),
};
int ret;
/* Check voltage domain is known from SCMI server */
in.domain_id = pdata->domain_id;
ret = devm_scmi_process_msg(dev->parent->parent, &scmi_msg);
if (ret) {
dev_err(dev, "Failed to query voltage domain %u: %d\n",
pdata->domain_id, ret);
return -ENXIO;
}
return 0;
}
static const struct dm_regulator_ops scmi_voltd_ops = {
.get_value = scmi_voltd_get_voltage_level,
.set_value = scmi_voltd_set_voltage_level,
.get_enable = scmi_voltd_get_enable,
.set_enable = scmi_voltd_set_enable,
};
U_BOOT_DRIVER(scmi_regulator) = {
.name = "scmi_regulator",
.id = UCLASS_REGULATOR,
.ops = &scmi_voltd_ops,
.probe = scmi_regulator_probe,
.of_to_plat = scmi_regulator_of_to_plat,
.plat_auto = sizeof(struct scmi_regulator_platdata),
};
static int scmi_regulator_bind(struct udevice *dev)
{
struct driver *drv;
ofnode node;
int ret;
drv = DM_DRIVER_GET(scmi_regulator);
ofnode_for_each_subnode(node, dev_ofnode(dev)) {
ret = device_bind(dev, drv, ofnode_get_name(node),
NULL, node, NULL);
if (ret)
return ret;
}
return 0;
}
U_BOOT_DRIVER(scmi_voltage_domain) = {
.name = "scmi_voltage_domain",
.id = UCLASS_NOP,
.bind = scmi_regulator_bind,
};

View File

@ -102,6 +102,12 @@ config RTC_PCF8563
If you say yes here you get support for the Philips PCF8563 RTC If you say yes here you get support for the Philips PCF8563 RTC
and compatible chips. and compatible chips.
config RTC_RV3028
bool "Enable RV3028 driver"
depends on DM_RTC
help
The MicroCrystal RV3028 is a I2C Real Time Clock (RTC)
config RTC_RV3029 config RTC_RV3029
bool "Enable RV3029 driver" bool "Enable RV3029 driver"
depends on DM_RTC depends on DM_RTC

View File

@ -47,6 +47,7 @@ obj-$(CONFIG_RTC_PCF2127) += pcf2127.o
obj-$(CONFIG_RTC_PL031) += pl031.o obj-$(CONFIG_RTC_PL031) += pl031.o
obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
obj-$(CONFIG_RTC_RS5C372A) += rs5c372.o obj-$(CONFIG_RTC_RS5C372A) += rs5c372.o
obj-$(CONFIG_RTC_RV3028) += rv3028.o
obj-$(CONFIG_RTC_RV3029) += rv3029.o obj-$(CONFIG_RTC_RV3029) += rv3029.o
obj-$(CONFIG_RTC_RV8803) += rv8803.o obj-$(CONFIG_RTC_RV8803) += rv8803.o
obj-$(CONFIG_RTC_RX8025) += rx8025.o obj-$(CONFIG_RTC_RX8025) += rx8025.o

208
drivers/rtc/rv3028.c Normal file
View File

@ -0,0 +1,208 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* RTC driver for the Micro Crystal RV3028
*
* based on linux driver from
* Copyright (C) 2019 Micro Crystal SA
*
* Alexandre Belloni <alexandre.belloni@bootlin.com>
*
*/
#include <dm.h>
#include <i2c.h>
#include <rtc.h>
#define RV3028_SEC 0x00
#define RV3028_MIN 0x01
#define RV3028_HOUR 0x02
#define RV3028_WDAY 0x03
#define RV3028_DAY 0x04
#define RV3028_MONTH 0x05
#define RV3028_YEAR 0x06
#define RV3028_ALARM_MIN 0x07
#define RV3028_ALARM_HOUR 0x08
#define RV3028_ALARM_DAY 0x09
#define RV3028_STATUS 0x0E
#define RV3028_CTRL1 0x0F
#define RV3028_CTRL2 0x10
#define RV3028_EVT_CTRL 0x13
#define RV3028_TS_COUNT 0x14
#define RV3028_TS_SEC 0x15
#define RV3028_RAM1 0x1F
#define RV3028_EEPROM_ADDR 0x25
#define RV3028_EEPROM_DATA 0x26
#define RV3028_EEPROM_CMD 0x27
#define RV3028_CLKOUT 0x35
#define RV3028_OFFSET 0x36
#define RV3028_BACKUP 0x37
#define RV3028_STATUS_PORF BIT(0)
#define RV3028_STATUS_EVF BIT(1)
#define RV3028_STATUS_AF BIT(2)
#define RV3028_STATUS_TF BIT(3)
#define RV3028_STATUS_UF BIT(4)
#define RV3028_STATUS_BSF BIT(5)
#define RV3028_STATUS_CLKF BIT(6)
#define RV3028_STATUS_EEBUSY BIT(7)
#define RV3028_CLKOUT_FD_MASK GENMASK(2, 0)
#define RV3028_CLKOUT_PORIE BIT(3)
#define RV3028_CLKOUT_CLKSY BIT(6)
#define RV3028_CLKOUT_CLKOE BIT(7)
#define RV3028_CTRL1_EERD BIT(3)
#define RV3028_CTRL1_WADA BIT(5)
#define RV3028_CTRL2_RESET BIT(0)
#define RV3028_CTRL2_12_24 BIT(1)
#define RV3028_CTRL2_EIE BIT(2)
#define RV3028_CTRL2_AIE BIT(3)
#define RV3028_CTRL2_TIE BIT(4)
#define RV3028_CTRL2_UIE BIT(5)
#define RV3028_CTRL2_TSE BIT(7)
#define RV3028_EVT_CTRL_TSR BIT(2)
#define RV3028_EEPROM_CMD_UPDATE 0x11
#define RV3028_EEPROM_CMD_WRITE 0x21
#define RV3028_EEPROM_CMD_READ 0x22
#define RV3028_EEBUSY_POLL 10000
#define RV3028_EEBUSY_TIMEOUT 100000
#define RV3028_BACKUP_TCE BIT(5)
#define RV3028_BACKUP_TCR_MASK GENMASK(1, 0)
#define OFFSET_STEP_PPT 953674
#define RTC_RV3028_LEN 7
static int rv3028_rtc_get(struct udevice *dev, struct rtc_time *tm)
{
u8 regs[RTC_RV3028_LEN];
u8 status;
int ret;
ret = dm_i2c_read(dev, RV3028_STATUS, &status, 1);
if (ret < 0) {
printf("%s: error reading RTC status: %x\n", __func__, ret);
return -EIO;
}
if (status & RV3028_STATUS_PORF) {
printf("Voltage low, data is invalid.\n");
return -EINVAL;
}
ret = dm_i2c_read(dev, RV3028_SEC, regs, sizeof(regs));
if (ret < 0) {
printf("%s: error reading RTC: %x\n", __func__, ret);
return -EIO;
}
tm->tm_sec = bcd2bin(regs[RV3028_SEC] & 0x7f);
tm->tm_min = bcd2bin(regs[RV3028_MIN] & 0x7f);
tm->tm_hour = bcd2bin(regs[RV3028_HOUR] & 0x3f);
tm->tm_wday = regs[RV3028_WDAY] & 0x7;
tm->tm_mday = bcd2bin(regs[RV3028_DAY] & 0x3f);
tm->tm_mon = bcd2bin(regs[RV3028_MONTH] & 0x1f);
tm->tm_year = bcd2bin(regs[RV3028_YEAR]) + 2000;
tm->tm_yday = 0;
tm->tm_isdst = 0;
debug("%s: %4d-%02d-%02d (wday=%d) %2d:%02d:%02d\n",
__func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
return 0;
}
static int rv3028_rtc_set(struct udevice *dev, const struct rtc_time *tm)
{
u8 regs[RTC_RV3028_LEN];
u8 status;
int ret;
debug("%s: %4d-%02d-%02d (wday=%d( %2d:%02d:%02d\n",
__func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
if (tm->tm_year < 2000) {
printf("%s: year %d (before 2000) not supported\n",
__func__, tm->tm_year);
return -EINVAL;
}
regs[RV3028_SEC] = bin2bcd(tm->tm_sec);
regs[RV3028_MIN] = bin2bcd(tm->tm_min);
regs[RV3028_HOUR] = bin2bcd(tm->tm_hour);
regs[RV3028_WDAY] = tm->tm_wday;
regs[RV3028_DAY] = bin2bcd(tm->tm_mday);
regs[RV3028_MONTH] = bin2bcd(tm->tm_mon);
regs[RV3028_YEAR] = bin2bcd(tm->tm_year - 2000);
ret = dm_i2c_write(dev, RV3028_SEC, regs, sizeof(regs));
if (ret) {
printf("%s: set rtc error: %d\n", __func__, ret);
return ret;
}
ret = dm_i2c_read(dev, RV3028_STATUS, &status, 1);
if (ret < 0) {
printf("%s: error reading RTC status: %x\n", __func__, ret);
return -EIO;
}
status |= RV3028_STATUS_PORF;
return dm_i2c_write(dev, RV3028_STATUS, &status, 1);
}
static int rv3028_rtc_reset(struct udevice *dev)
{
return 0;
}
static int rv3028_rtc_read8(struct udevice *dev, unsigned int reg)
{
u8 data;
int ret;
ret = dm_i2c_read(dev, reg, &data, sizeof(data));
return ret < 0 ? ret : data;
}
static int rv3028_rtc_write8(struct udevice *dev, unsigned int reg, int val)
{
u8 data = val;
return dm_i2c_write(dev, reg, &data, 1);
}
static int rv3028_probe(struct udevice *dev)
{
i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
DM_I2C_CHIP_WR_ADDRESS);
return 0;
}
static const struct rtc_ops rv3028_rtc_ops = {
.get = rv3028_rtc_get,
.set = rv3028_rtc_set,
.read8 = rv3028_rtc_read8,
.write8 = rv3028_rtc_write8,
.reset = rv3028_rtc_reset,
};
static const struct udevice_id rv3028_rtc_ids[] = {
{ .compatible = "microcrystal,rv3028" },
{ }
};
U_BOOT_DRIVER(rtc_rv3028) = {
.name = "rtc-rv3028",
.id = UCLASS_RTC,
.probe = rv3028_probe,
.of_match = rv3028_rtc_ids,
.ops = &rv3028_rtc_ops,
};

View File

@ -624,14 +624,14 @@ static int optee_probe(struct udevice *dev)
u32 sec_caps; u32 sec_caps;
if (!is_optee_api(pdata->invoke_fn)) { if (!is_optee_api(pdata->invoke_fn)) {
debug("%s: OP-TEE api uid mismatch\n", __func__); dev_err(dev, "OP-TEE api uid mismatch\n");
return -ENOENT; return -ENOENT;
} }
print_os_revision(dev, pdata->invoke_fn); print_os_revision(dev, pdata->invoke_fn);
if (!api_revision_is_compatible(pdata->invoke_fn)) { if (!api_revision_is_compatible(pdata->invoke_fn)) {
debug("%s: OP-TEE api revision mismatch\n", __func__); dev_err(dev, "OP-TEE api revision mismatch\n");
return -ENOENT; return -ENOENT;
} }
@ -642,7 +642,7 @@ static int optee_probe(struct udevice *dev)
*/ */
if (!exchange_capabilities(pdata->invoke_fn, &sec_caps) || if (!exchange_capabilities(pdata->invoke_fn, &sec_caps) ||
!(sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)) { !(sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)) {
debug("%s: OP-TEE capabilities mismatch\n", __func__); dev_err(dev, "OP-TEE capabilities mismatch\n");
return -ENOENT; return -ENOENT;
} }

View File

@ -13,10 +13,4 @@
#define dev_WARN(dev, format, arg...) debug(format, ##arg) #define dev_WARN(dev, format, arg...) debug(format, ##arg)
static inline size_t strlcat(char *dest, const char *src, size_t n)
{
strcat(dest, src);
return strlen(dest) + strlen(src);
}
#endif #endif

View File

@ -706,17 +706,6 @@ int dm_gpio_get_value(const struct gpio_desc *desc);
int dm_gpio_set_value(const struct gpio_desc *desc, int value); int dm_gpio_set_value(const struct gpio_desc *desc, int value);
/**
* dm_gpio_set_dir() - Set the direction for a GPIO
*
* This sets up the direction according to the GPIO flags: desc->flags.
*
* @desc: GPIO description containing device, offset and flags,
* previously returned by gpio_request_by_name()
* @return 0 if OK, -ve on error
*/
int dm_gpio_set_dir(struct gpio_desc *desc);
/** /**
* dm_gpio_clrset_flags() - Update flags * dm_gpio_clrset_flags() - Update flags
* *

View File

@ -1,28 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2013-2015
* NVIDIA Corporation <www.nvidia.com>
*/
#ifndef _E2220_1170_H
#define _E2220_1170_H
#include <linux/sizes.h>
#include "tegra210-common.h"
/* High-level configuration options */
#define CONFIG_TEGRA_BOARD_STRING "NVIDIA E2220-1170"
/* Board-specific serial config */
#define CONFIG_TEGRA_ENABLE_UARTA
/* Environment in eMMC, at the end of 2nd "boot sector" */
/* SPI */
#define CONFIG_SPI_FLASH_SIZE (4 << 20)
#include "tegra-common-usb-gadget.h"
#include "tegra-common-post.h"
#endif /* _E2220_1170_H */

View File

@ -63,7 +63,6 @@
/* PMIC */ /* PMIC */
#define CONFIG_POWER #define CONFIG_POWER
#define CONFIG_POWER_I2C #define CONFIG_POWER_I2C
#define CONFIG_POWER_MAX77696
#define CONFIG_EXTRA_ENV_SETTINGS \ #define CONFIG_EXTRA_ENV_SETTINGS \
"script=boot.scr\0" \ "script=boot.scr\0" \

View File

@ -90,6 +90,7 @@ enum uclass_id {
UCLASS_POWER_DOMAIN, /* (SoC) Power domains */ UCLASS_POWER_DOMAIN, /* (SoC) Power domains */
UCLASS_PWM, /* Pulse-width modulator */ UCLASS_PWM, /* Pulse-width modulator */
UCLASS_PWRSEQ, /* Power sequence device */ UCLASS_PWRSEQ, /* Power sequence device */
UCLASS_QFW, /* QEMU firmware config device */
UCLASS_RAM, /* RAM controller */ UCLASS_RAM, /* RAM controller */
UCLASS_REGULATOR, /* Regulator device */ UCLASS_REGULATOR, /* Regulator device */
UCLASS_REMOTEPROC, /* Remote Processor device */ UCLASS_REMOTEPROC, /* Remote Processor device */

View File

@ -8,6 +8,32 @@
#define __HW_SHA_H #define __HW_SHA_H
#include <hash.h> #include <hash.h>
/**
* Computes hash value of input pbuf using h/w acceleration
*
* @param in_addr A pointer to the input buffer
* @param bufleni Byte length of input buffer
* @param out_addr A pointer to the output buffer. When complete
* 64 bytes are copied to pout[0]...pout[63]. Thus, a user
* should allocate at least 64 bytes at pOut in advance.
* @param chunk_size chunk size for sha512
*/
void hw_sha512(const uchar *in_addr, uint buflen, uchar *out_addr,
uint chunk_size);
/**
* Computes hash value of input pbuf using h/w acceleration
*
* @param in_addr A pointer to the input buffer
* @param bufleni Byte length of input buffer
* @param out_addr A pointer to the output buffer. When complete
* 48 bytes are copied to pout[0]...pout[47]. Thus, a user
* should allocate at least 48 bytes at pOut in advance.
* @param chunk_size chunk size for sha384
*/
void hw_sha384(const uchar *in_addr, uint buflen, uchar *out_addr,
uint chunk_size);
/** /**
* Computes hash value of input pbuf using h/w acceleration * Computes hash value of input pbuf using h/w acceleration
* *
@ -18,8 +44,8 @@
* should allocate at least 32 bytes at pOut in advance. * should allocate at least 32 bytes at pOut in advance.
* @param chunk_size chunk size for sha256 * @param chunk_size chunk size for sha256
*/ */
void hw_sha256(const uchar * in_addr, uint buflen, void hw_sha256(const uchar *in_addr, uint buflen, uchar *out_addr,
uchar * out_addr, uint chunk_size); uint chunk_size);
/** /**
* Computes hash value of input pbuf using h/w acceleration * Computes hash value of input pbuf using h/w acceleration
@ -31,8 +57,8 @@ void hw_sha256(const uchar * in_addr, uint buflen,
* should allocate at least 32 bytes at pOut in advance. * should allocate at least 32 bytes at pOut in advance.
* @param chunk_size chunk_size for sha1 * @param chunk_size chunk_size for sha1
*/ */
void hw_sha1(const uchar * in_addr, uint buflen, void hw_sha1(const uchar *in_addr, uint buflen, uchar *out_addr,
uchar * out_addr, uint chunk_size); uint chunk_size);
/* /*
* Create the context for sha progressive hashing using h/w acceleration * Create the context for sha progressive hashing using h/w acceleration
@ -56,7 +82,7 @@ int hw_sha_init(struct hash_algo *algo, void **ctxp);
* @return 0 if ok, -ve on error * @return 0 if ok, -ve on error
*/ */
int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf, int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf,
unsigned int size, int is_last); unsigned int size, int is_last);
/* /*
* Copy sha hash result at destination location * Copy sha hash result at destination location
@ -70,6 +96,6 @@ int hw_sha_update(struct hash_algo *algo, void *ctx, const void *buf,
* @return 0 if ok, -ve on error * @return 0 if ok, -ve on error
*/ */
int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf, int hw_sha_finish(struct hash_algo *algo, void *ctx, void *dest_buf,
int size); int size);
#endif #endif

View File

@ -35,6 +35,9 @@ extern char * strcat(char *, const char *);
#ifndef __HAVE_ARCH_STRNCAT #ifndef __HAVE_ARCH_STRNCAT
extern char * strncat(char *, const char *, __kernel_size_t); extern char * strncat(char *, const char *, __kernel_size_t);
#endif #endif
#ifndef __HAVE_ARCH_STRLCAT
size_t strlcat(char *, const char *, size_t);
#endif
#ifndef __HAVE_ARCH_STRCMP #ifndef __HAVE_ARCH_STRCMP
extern int strcmp(const char *,const char *); extern int strcmp(const char *,const char *);
#endif #endif

View File

@ -1,59 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
* Fabio Estevam <fabio.estevam@freescale.com>
*/
#ifndef __MAX77696_PMIC_H__
#define __MAX77696_PMIC_H__
#define CONFIG_POWER_MAX77696_I2C_ADDR 0x3C
enum {
L01_CNFG1 = 0x43,
L01_CNFG2,
L02_CNFG1,
L02_CNFG2,
L03_CNFG1,
L03_CNFG2,
L04_CNFG1,
L04_CNFG2,
L05_CNFG1,
L05_CNFG2,
L06_CNFG1,
L06_CNFG2,
L07_CNFG1,
L07_CNFG2,
L08_CNFG1,
L08_CNFG2,
L09_CNFG1,
L09_CNFG2,
L10_CNFG1,
L10_CNFG2,
LDO_INT1,
LDO_INT2,
LDO_INT1M,
LDO_INT2M,
LDO_CNFG3,
SW1_CNTRL,
SW2_CNTRL,
SW3_CNTRL,
SW4_CNTRL,
EPDCNFG,
EPDINTS,
EPDINT,
EPDINTM,
EPDVCOM,
EPDVEE,
EPDVNEG,
EPDVPOS,
EPDVDDH,
EPDSEQ,
EPDOKINTS,
CID = 0x9c,
PMIC_NUM_OF_REGS,
};
int power_max77696_init(unsigned char bus);
#endif

View File

@ -8,7 +8,12 @@
#include <linux/list.h> #include <linux/list.h>
enum qemu_fwcfg_items { /*
* List of firmware configuration item selectors. The official source of truth
* for these is the QEMU source itself; see
* https://github.com/qemu/qemu/blob/master/hw/nvram/fw_cfg.c
*/
enum {
FW_CFG_SIGNATURE = 0x00, FW_CFG_SIGNATURE = 0x00,
FW_CFG_ID = 0x01, FW_CFG_ID = 0x01,
FW_CFG_UUID = 0x02, FW_CFG_UUID = 0x02,
@ -66,8 +71,10 @@ enum {
#define FW_CFG_DMA_SKIP (1 << 2) #define FW_CFG_DMA_SKIP (1 << 2)
#define FW_CFG_DMA_SELECT (1 << 3) #define FW_CFG_DMA_SELECT (1 << 3)
/* Bit set in FW_CFG_ID response to indicate DMA interface availability. */
#define FW_CFG_DMA_ENABLED (1 << 1) #define FW_CFG_DMA_ENABLED (1 << 1)
/* Structs read from FW_CFG_FILE_DIR. */
struct fw_cfg_file { struct fw_cfg_file {
__be32 size; __be32 size;
__be16 select; __be16 select;
@ -82,19 +89,7 @@ struct fw_file {
}; };
struct fw_cfg_file_iter { struct fw_cfg_file_iter {
struct list_head *entry; /* structure to iterate file list */ struct list_head *entry, *end; /* structures to iterate file list */
};
struct fw_cfg_dma_access {
__be32 control;
__be32 length;
__be64 address;
};
struct fw_cfg_arch_ops {
void (*arch_read_pio)(uint16_t selector, uint32_t size,
void *address);
void (*arch_read_dma)(struct fw_cfg_dma_access *dma);
}; };
struct bios_linker_entry { struct bios_linker_entry {
@ -146,37 +141,178 @@ struct bios_linker_entry {
}; };
} __packed; } __packed;
/* DMA transfer control data between UCLASS_QFW and QEMU. */
struct qfw_dma {
__be32 control;
__be32 length;
__be64 address;
};
/* uclass per-device configuration information */
struct qfw_dev {
struct udevice *dev; /* Transport device */
bool dma_present; /* DMA interface usable? */
struct list_head fw_list; /* Cached firmware file list */
};
/* Ops used internally between UCLASS_QFW and its driver implementations. */
struct dm_qfw_ops {
/**
* read_entry_io() - Read a firmware config entry using the regular
* IO interface for the platform (either PIO or MMIO)
*
* Supply %FW_CFG_INVALID as the entry to continue a previous read. In
* this case, no selector will be issued before reading.
*
* @dev: Device to use
* @entry: Firmware config entry number (e.g. %FW_CFG_SIGNATURE)
* @size: Number of bytes to read
* @address: Target location for read
*/
void (*read_entry_io)(struct udevice *dev, u16 entry, u32 size,
void *address);
/**
* read_entry_dma() - Read a firmware config entry using the DMA
* interface
*
* Supply FW_CFG_INVALID as the entry to continue a previous read. In
* this case, no selector will be issued before reading.
*
* This method assumes DMA availability has already been confirmed.
*
* @dev: Device to use
* @dma: DMA transfer control struct
*/
void (*read_entry_dma)(struct udevice *dev, struct qfw_dma *dma);
};
#define dm_qfw_get_ops(dev) \
((struct dm_qfw_ops *)(dev)->driver->ops)
/** /**
* Initialize QEMU fw_cfg interface * qfw_register() - Called by a qfw driver after successful probe.
* @dev: Device registering itself with the uclass.
* *
* @ops: arch specific read operations * Used internally by driver implementations on successful probe.
*
* Return: 0 on success, negative otherwise.
*/ */
void qemu_fwcfg_init(struct fw_cfg_arch_ops *ops); int qfw_register(struct udevice *dev);
void qemu_fwcfg_read_entry(uint16_t entry, uint32_t length, void *address); struct udevice;
int qemu_fwcfg_read_firmware_list(void);
struct fw_file *qemu_fwcfg_find_file(const char *name);
/** /**
* Get system cpu number * qfw_get_dev() - Get QEMU firmware config device.
* @devp: Pointer to be filled with address of the qfw device.
* *
* @return: cpu number in system * Gets the active QEMU firmware config device, for use with qfw_read_entry()
* and others.
*
* Return: 0 on success, -ENODEV if the device is not available.
*/ */
int qemu_fwcfg_online_cpus(void); int qfw_get_dev(struct udevice **devp);
/* helper functions to iterate firmware file list */
struct fw_file *qemu_fwcfg_file_iter_init(struct fw_cfg_file_iter *iter);
struct fw_file *qemu_fwcfg_file_iter_next(struct fw_cfg_file_iter *iter);
bool qemu_fwcfg_file_iter_end(struct fw_cfg_file_iter *iter);
bool qemu_fwcfg_present(void);
bool qemu_fwcfg_dma_present(void);
/** /**
* qemu_cpu_fixup() - Fix up the CPUs for QEMU * qfw_read_entry() - Read a QEMU firmware config entry
* @dev: QFW device to use.
* @entry: Firmware config entry number (e.g. %FW_CFG_SIGNATURE).
* @size: Number of bytes to read.
* @address: Target location for read.
* *
* @return 0 if OK, -ENODEV if no CPUs, -ENOMEM if out of memory, other -ve on * Reads a QEMU firmware config entry using @dev. DMA will be used if the QEMU
* on other error * machine supports it, otherwise PIO/MMIO.
*/
void qfw_read_entry(struct udevice *dev, u16 entry, u32 size, void *address);
/**
* qfw_read_firmware_list() - Read and cache the QEMU firmware config file
* list.
* @dev: QFW device to use.
*
* Reads the QEMU firmware config file list, caching it against @dev for later
* use with qfw_find_file().
*
* If the list has already been read, does nothing and returns 0 (success).
*
* Return: 0 on success, -ENOMEM if unable to allocate.
*/
int qfw_read_firmware_list(struct udevice *dev);
/**
* qfw_find_file() - Find a file by name in the QEMU firmware config file
* list.
* @dev: QFW device to use.
* @name: Name of file to locate (e.g. "etc/table-loader").
*
* Finds a file by name in the QEMU firmware config file list cached against
* @dev. You must call qfw_read_firmware_list() successfully first for this to
* succeed.
*
* Return: Pointer to &struct fw_file if found, %NULL if not present.
*/
struct fw_file *qfw_find_file(struct udevice *dev, const char *name);
/**
* qfw_online_cpus() - Get number of CPUs in system from QEMU firmware config.
* @dev: QFW device to use.
*
* Asks QEMU to report how many CPUs it is emulating for the machine.
*
* Return: Number of CPUs in the system.
*/
int qfw_online_cpus(struct udevice *dev);
/**
* qfw_file_iter_init() - Start iterating cached firmware file list.
* @dev: QFW device to use.
* @iter: Iterator to be initialised.
*
* Starts iterating the cached firmware file list in @dev. You must call
* qfw_read_firmware_list() successfully first, otherwise you will always get
* an empty list.
*
* qfw_file_iter_init() returns the first &struct fw_file, but it may be
* invalid if the list is empty. Check that ``!qfw_file_iter_end(&iter)``
* first.
*
* Return: The first &struct fw_file item in the firmware file list, if any.
* Only valid when qfw_file_iter_end() is not true after the call.
*/
struct fw_file *qfw_file_iter_init(struct udevice *dev,
struct fw_cfg_file_iter *iter);
/**
* qfw_file_iter_next() - Iterate cached firmware file list.
* @iter: Iterator to use.
*
* Continues iterating the cached firmware file list in @dev. You must call
* qfw_file_iter_init() first to initialise it. Check that
* ``!qfw_file_iter_end(&iter)`` before using the return value of this
* function.
*
* Return: The next &struct fw_file item in the firmware file list. Only valid
* when qfw_file_iter_end() is not true after the call.
*/
struct fw_file *qfw_file_iter_next(struct fw_cfg_file_iter *iter);
/**
* qfw_file_iter_end() - Check if iter is at end of list.
* @iter: Iterator to use.
*
* Checks whether or not the iterator is at its end position. If so, the
* qfw_file_iter_init() or qfw_file_iter_next() call that immediately preceded
* returned invalid data.
*
* Return: True if the iterator is at its end; false otherwise.
*/
bool qfw_file_iter_end(struct fw_cfg_file_iter *iter);
/**
* qemu_cpu_fixup() - Fix up the CPUs for QEMU.
*
* Return: 0 on success, -ENODEV if no CPUs, -ENOMEM if out of memory, other <
* 0 on on other error.
*/ */
int qemu_cpu_fixup(void); int qemu_cpu_fixup(void);

View File

@ -23,6 +23,7 @@ enum scmi_std_protocol {
SCMI_PROTOCOL_ID_CLOCK = 0x14, SCMI_PROTOCOL_ID_CLOCK = 0x14,
SCMI_PROTOCOL_ID_SENSOR = 0x15, SCMI_PROTOCOL_ID_SENSOR = 0x15,
SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16, SCMI_PROTOCOL_ID_RESET_DOMAIN = 0x16,
SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN = 0x17,
}; };
enum scmi_status_code { enum scmi_status_code {
@ -176,4 +177,116 @@ struct scmi_rd_reset_out {
s32 status; s32 status;
}; };
/*
* SCMI Voltage Domain Protocol
*/
enum scmi_voltage_domain_message_id {
SCMI_VOLTAGE_DOMAIN_ATTRIBUTES = 0x3,
SCMI_VOLTAGE_DOMAIN_CONFIG_SET = 0x5,
SCMI_VOLTAGE_DOMAIN_CONFIG_GET = 0x6,
SCMI_VOLTAGE_DOMAIN_LEVEL_SET = 0x7,
SCMI_VOLTAGE_DOMAIN_LEVEL_GET = 0x8,
};
#define SCMI_VOLTD_NAME_LEN 16
#define SCMI_VOLTD_CONFIG_MASK GENMASK(3, 0)
#define SCMI_VOLTD_CONFIG_OFF 0
#define SCMI_VOLTD_CONFIG_ON 0x7
/**
* struct scmi_voltd_attr_in - Payload for VOLTAGE_DOMAIN_ATTRIBUTES message
* @domain_id: SCMI voltage domain ID
*/
struct scmi_voltd_attr_in {
u32 domain_id;
};
/**
* struct scmi_voltd_attr_out - Payload for VOLTAGE_DOMAIN_ATTRIBUTES response
* @status: SCMI command status
* @attributes: Retrieved attributes of the voltage domain
* @name: Voltage domain name
*/
struct scmi_voltd_attr_out {
s32 status;
u32 attributes;
char name[SCMI_VOLTD_NAME_LEN];
};
/**
* struct scmi_voltd_config_set_in - Message payload for VOLTAGE_CONFIG_SET cmd
* @domain_id: SCMI voltage domain ID
* @config: Configuration data of the voltage domain
*/
struct scmi_voltd_config_set_in {
u32 domain_id;
u32 config;
};
/**
* struct scmi_voltd_config_set_out - Response for VOLTAGE_CONFIG_SET command
* @status: SCMI command status
*/
struct scmi_voltd_config_set_out {
s32 status;
};
/**
* struct scmi_voltd_config_get_in - Message payload for VOLTAGE_CONFIG_GET cmd
* @domain_id: SCMI voltage domain ID
*/
struct scmi_voltd_config_get_in {
u32 domain_id;
};
/**
* struct scmi_voltd_config_get_out - Response for VOLTAGE_CONFIG_GET command
* @status: SCMI command status
* @config: Configuration data of the voltage domain
*/
struct scmi_voltd_config_get_out {
s32 status;
u32 config;
};
/**
* struct scmi_voltd_level_set_in - Message payload for VOLTAGE_LEVEL_SET cmd
* @domain_id: SCMI voltage domain ID
* @flags: Parameter flags for configuring target level
* @voltage_level: Target voltage level in microvolts (uV)
*/
struct scmi_voltd_level_set_in {
u32 domain_id;
u32 flags;
s32 voltage_level;
};
/**
* struct scmi_voltd_level_set_out - Response for VOLTAGE_LEVEL_SET command
* @status: SCMI command status
*/
struct scmi_voltd_level_set_out {
s32 status;
};
/**
* struct scmi_voltd_level_get_in - Message payload for VOLTAGE_LEVEL_GET cmd
* @domain_id: SCMI voltage domain ID
*/
struct scmi_voltd_level_get_in {
u32 domain_id;
};
/**
* struct scmi_voltd_level_get_out - Response for VOLTAGE_LEVEL_GET command
* @status: SCMI command status
* @voltage_level: Voltage level in microvolts (uV)
*/
struct scmi_voltd_level_get_out {
s32 status;
s32 voltage_level;
};
#endif /* _SCMI_PROTOCOLS_H */ #endif /* _SCMI_PROTOCOLS_H */

View File

@ -71,9 +71,9 @@ static inline int optee_verify_bootm_image(unsigned long image_addr,
#endif #endif
#if defined(CONFIG_OPTEE) && defined(CONFIG_OF_LIBFDT) #if defined(CONFIG_OPTEE) && defined(CONFIG_OF_LIBFDT)
int optee_copy_fdt_nodes(const void *old_blob, void *new_blob); int optee_copy_fdt_nodes(void *new_blob);
#else #else
static inline int optee_copy_fdt_nodes(const void *old_blob, void *new_blob) static inline int optee_copy_fdt_nodes(void *new_blob)
{ {
return 0; return 0;
} }

View File

@ -391,19 +391,18 @@ config SHA384
config SHA_HW_ACCEL config SHA_HW_ACCEL
bool "Enable hashing using hardware" bool "Enable hashing using hardware"
help help
This option enables hardware acceleration This option enables hardware acceleration for SHA hashing.
for SHA1/SHA256 hashing. This affects the 'hash' command and also the hash_lookup_algo()
This affects the 'hash' command and also the function.
hash_lookup_algo() function.
config SHA_PROG_HW_ACCEL config SHA_PROG_HW_ACCEL
bool "Enable Progressive hashing support using hardware" bool "Enable Progressive hashing support using hardware"
depends on SHA_HW_ACCEL depends on SHA_HW_ACCEL
help help
This option enables hardware-acceleration for This option enables hardware-acceleration for SHA progressive
SHA1/SHA256 progressive hashing. hashing.
Data can be streamed in a block at a time and the hashing Data can be streamed in a block at a time and the hashing is
is performed in hardware. performed in hardware.
config MD5 config MD5
bool "Support MD5 algorithm" bool "Support MD5 algorithm"

View File

@ -9,6 +9,8 @@
#include <image.h> #include <image.h>
#include <log.h> #include <log.h>
#include <malloc.h> #include <malloc.h>
#include <dm/ofnode.h>
#include <linux/ioport.h>
#include <linux/libfdt.h> #include <linux/libfdt.h>
#include <tee/optee.h> #include <tee/optee.h>
@ -70,17 +72,11 @@ error:
} }
#if defined(CONFIG_OF_LIBFDT) #if defined(CONFIG_OF_LIBFDT)
static int optee_copy_firmware_node(const void *old_blob, void *fdt_blob) static int optee_copy_firmware_node(ofnode node, void *fdt_blob)
{ {
int old_offs, offs, ret, len; int offs, ret, len;
const void *prop; const void *prop;
old_offs = fdt_path_offset(old_blob, "/firmware/optee");
if (old_offs < 0) {
debug("Original OP-TEE Device Tree node not found");
return old_offs;
}
offs = fdt_path_offset(fdt_blob, "/firmware"); offs = fdt_path_offset(fdt_blob, "/firmware");
if (offs < 0) { if (offs < 0) {
offs = fdt_path_offset(fdt_blob, "/"); offs = fdt_path_offset(fdt_blob, "/");
@ -97,7 +93,7 @@ static int optee_copy_firmware_node(const void *old_blob, void *fdt_blob)
return offs; return offs;
/* copy the compatible property */ /* copy the compatible property */
prop = fdt_getprop(old_blob, old_offs, "compatible", &len); prop = ofnode_get_property(node, "compatible", &len);
if (!prop) { if (!prop) {
debug("missing OP-TEE compatible property"); debug("missing OP-TEE compatible property");
return -EINVAL; return -EINVAL;
@ -108,7 +104,7 @@ static int optee_copy_firmware_node(const void *old_blob, void *fdt_blob)
return ret; return ret;
/* copy the method property */ /* copy the method property */
prop = fdt_getprop(old_blob, old_offs, "method", &len); prop = ofnode_get_property(node, "method", &len);
if (!prop) { if (!prop) {
debug("missing OP-TEE method property"); debug("missing OP-TEE method property");
return -EINVAL; return -EINVAL;
@ -121,19 +117,18 @@ static int optee_copy_firmware_node(const void *old_blob, void *fdt_blob)
return 0; return 0;
} }
int optee_copy_fdt_nodes(const void *old_blob, void *new_blob) int optee_copy_fdt_nodes(void *new_blob)
{ {
int nodeoffset, subnode, ret; ofnode node, subnode;
struct fdt_resource res; int ret;
struct resource res;
if (fdt_check_header(old_blob))
return -EINVAL;
if (fdt_check_header(new_blob)) if (fdt_check_header(new_blob))
return -EINVAL; return -EINVAL;
/* only proceed if there is an /firmware/optee node */ /* only proceed if there is an /firmware/optee node */
if (fdt_path_offset(old_blob, "/firmware/optee") < 0) { node = ofnode_path("/firmware/optee");
if (!ofnode_valid(node)) {
debug("No OP-TEE firmware node in old fdt, nothing to do"); debug("No OP-TEE firmware node in old fdt, nothing to do");
return 0; return 0;
} }
@ -148,20 +143,17 @@ int optee_copy_fdt_nodes(const void *old_blob, void *new_blob)
return 0; return 0;
} }
ret = optee_copy_firmware_node(old_blob, new_blob); ret = optee_copy_firmware_node(node, new_blob);
if (ret < 0) { if (ret < 0) {
printf("Failed to add OP-TEE firmware node\n"); printf("Failed to add OP-TEE firmware node\n");
return ret; return ret;
} }
/* optee inserts its memory regions as reserved-memory nodes */ /* optee inserts its memory regions as reserved-memory nodes */
nodeoffset = fdt_subnode_offset(old_blob, 0, "reserved-memory"); node = ofnode_path("/reserved-memory");
if (nodeoffset >= 0) { if (ofnode_valid(node)) {
for (subnode = fdt_first_subnode(old_blob, nodeoffset); ofnode_for_each_subnode(subnode, node) {
subnode >= 0; const char *name = ofnode_get_name(subnode);
subnode = fdt_next_subnode(old_blob, subnode)) {
const char *name = fdt_get_name(old_blob,
subnode, NULL);
if (!name) if (!name)
return -EINVAL; return -EINVAL;
@ -170,8 +162,7 @@ int optee_copy_fdt_nodes(const void *old_blob, void *new_blob)
continue; continue;
/* check if this subnode has a reg property */ /* check if this subnode has a reg property */
ret = fdt_get_resource(old_blob, subnode, "reg", 0, ret = ofnode_read_resource(subnode, 0, &res);
&res);
if (!ret) { if (!ret) {
struct fdt_memory carveout = { struct fdt_memory carveout = {
.start = res.start, .start = res.start,

View File

@ -114,17 +114,21 @@ char * strncpy(char * dest,const char *src,size_t count)
* NUL-terminated string that fits in the buffer (unless, * NUL-terminated string that fits in the buffer (unless,
* of course, the buffer size is zero). It does not pad * of course, the buffer size is zero). It does not pad
* out the result like strncpy() does. * out the result like strncpy() does.
*
* Return: the number of bytes copied
*/ */
size_t strlcpy(char *dest, const char *src, size_t size) size_t strlcpy(char *dest, const char *src, size_t size)
{ {
size_t ret = strlen(src);
if (size) { if (size) {
size_t len = (ret >= size) ? size - 1 : ret; size_t srclen = strlen(src);
size_t len = (srclen >= size) ? size - 1 : srclen;
memcpy(dest, src, len); memcpy(dest, src, len);
dest[len] = '\0'; dest[len] = '\0';
return len + 1;
} }
return ret;
return 0;
} }
#endif #endif
@ -176,6 +180,25 @@ char * strncat(char *dest, const char *src, size_t count)
} }
#endif #endif
#ifndef __HAVE_ARCH_STRLCAT
/**
* strlcat - Append a length-limited, %NUL-terminated string to another
* @dest: The string to be appended to
* @src: The string to append to it
* @size: The size of @dest
*
* Compatible with *BSD: the result is always a valid NUL-terminated string that
* fits in the buffer (unless, of course, the buffer size is zero). It does not
* write past @size like strncat() does.
*/
size_t strlcat(char *dest, const char *src, size_t size)
{
size_t len = strnlen(dest, size);
return len + strlcpy(dest + len, src, size - len);
}
#endif
#ifndef __HAVE_ARCH_STRCMP #ifndef __HAVE_ARCH_STRCMP
/** /**
* strcmp - Compare two strings * strcmp - Compare two strings

View File

@ -2365,6 +2365,12 @@ sub u_boot_line {
"Use 'if (IS_ENABLED(CONFIG...))' instead of '#if or #ifdef' where possible\n" . $herecurr); "Use 'if (IS_ENABLED(CONFIG...))' instead of '#if or #ifdef' where possible\n" . $herecurr);
} }
# prefer strl(cpy|cat) over strn(cpy|cat)
if ($line =~ /\bstrn(cpy|cat)\s*\(/) {
WARN("STRL",
"strl$1 is preferred over strn$1 because it always produces a nul-terminated string\n" . $herecurr);
}
# use defconfig to manage CONFIG_CMD options # use defconfig to manage CONFIG_CMD options
if ($line =~ /\+\s*#\s*(define|undef)\s+(CONFIG_CMD\w*)\b/) { if ($line =~ /\+\s*#\s*(define|undef)\s+(CONFIG_CMD\w*)\b/) {
ERROR("DEFINE_CONFIG_CMD", ERROR("DEFINE_CONFIG_CMD",

View File

@ -34,6 +34,8 @@ static struct test_data echo_data[] = {
*/ */
{"setenv jQx X; echo \"a)\" ${jQx} 'b)' '${jQx}' c) ${jQx}; setenv jQx", {"setenv jQx X; echo \"a)\" ${jQx} 'b)' '${jQx}' c) ${jQx}; setenv jQx",
"a) X b) ${jQx} c) X"}, "a) X b) ${jQx} c) X"},
/* Test shell variable assignments without substitutions */
{"foo=bar echo baz", "baz"},
/* Test handling of shell variables. */ /* Test handling of shell variables. */
{"setenv jQx; for jQx in 1 2 3; do echo -n \"${jQx}, \"; done; echo;", {"setenv jQx; for jQx in 1 2 3; do echo -n \"${jQx}, \"; done; echo;",
"1, 2, 3, "}, "1, 2, 3, "},

View File

@ -98,5 +98,6 @@ endif
ifneq ($(CONFIG_EFI_PARTITION),) ifneq ($(CONFIG_EFI_PARTITION),)
obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fastboot.o obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fastboot.o
endif endif
obj-$(CONFIG_QFW) += qfw.o
endif endif
endif # !SPL endif # !SPL

42
test/dm/qfw.c Normal file
View File

@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2021 Asherah Connor <ashe@kivikakk.ee>
*/
#include <common.h>
#include <qfw.h>
#include <dm.h>
#include <asm/test.h>
#include <dm/test.h>
#include <test/ut.h>
/*
* Exercise the device enough to be satisfied the initialisation and DMA
* interfaces work.
*/
static int dm_test_qfw_cpus(struct unit_test_state *uts)
{
struct udevice *dev;
ut_assertok(uclass_first_device_err(UCLASS_QFW, &dev));
ut_asserteq(5, qfw_online_cpus(dev));
return 0;
}
DM_TEST(dm_test_qfw_cpus, UT_TESTF_SCAN_PDATA);
static int dm_test_qfw_firmware_list(struct unit_test_state *uts)
{
struct udevice *dev;
struct fw_file *file;
ut_assertok(uclass_first_device_err(UCLASS_QFW, &dev));
ut_assertok(qfw_read_firmware_list(dev));
ut_assertok_ptr((file = qfw_find_file(dev, "test-one")));
return 0;
}
DM_TEST(dm_test_qfw_firmware_list, UT_TESTF_SCAN_PDATA);

View File

@ -20,6 +20,7 @@
#include <dm/device-internal.h> #include <dm/device-internal.h>
#include <dm/test.h> #include <dm/test.h>
#include <linux/kconfig.h> #include <linux/kconfig.h>
#include <power/regulator.h>
#include <test/ut.h> #include <test/ut.h>
static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts) static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts)
@ -38,30 +39,35 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
{ {
struct sandbox_scmi_devices *scmi_devices; struct sandbox_scmi_devices *scmi_devices;
struct sandbox_scmi_service *scmi_ctx; struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent0;
struct sandbox_scmi_agent *agent1;
/* Device references to check context against test sequence */ /* Device references to check context against test sequence */
scmi_devices = sandbox_scmi_devices_ctx(dev); scmi_devices = sandbox_scmi_devices_ctx(dev);
ut_assertnonnull(scmi_devices); ut_assertnonnull(scmi_devices);
if (IS_ENABLED(CONFIG_CLK_SCMI)) ut_asserteq(3, scmi_devices->clk_count);
ut_asserteq(3, scmi_devices->clk_count); ut_asserteq(1, scmi_devices->reset_count);
if (IS_ENABLED(CONFIG_RESET_SCMI)) ut_asserteq(2, scmi_devices->regul_count);
ut_asserteq(1, scmi_devices->reset_count);
/* State of the simulated SCMI server exposed */ /* State of the simulated SCMI server exposed */
scmi_ctx = sandbox_scmi_service_ctx(); scmi_ctx = sandbox_scmi_service_ctx();
agent0 = scmi_ctx->agent[0];
agent1 = scmi_ctx->agent[1];
ut_asserteq(2, scmi_ctx->agent_count); ut_asserteq(2, scmi_ctx->agent_count);
ut_assertnonnull(scmi_ctx->agent[0]); ut_assertnonnull(agent0);
ut_asserteq(2, scmi_ctx->agent[0]->clk_count); ut_asserteq(2, agent0->clk_count);
ut_assertnonnull(scmi_ctx->agent[0]->clk); ut_assertnonnull(agent0->clk);
ut_asserteq(1, scmi_ctx->agent[0]->reset_count); ut_asserteq(1, agent0->reset_count);
ut_assertnonnull(scmi_ctx->agent[0]->reset); ut_assertnonnull(agent0->reset);
ut_asserteq(2, agent0->voltd_count);
ut_assertnonnull(agent0->voltd);
ut_assertnonnull(scmi_ctx->agent[1]); ut_assertnonnull(agent1);
ut_assertnonnull(scmi_ctx->agent[1]->clk); ut_assertnonnull(agent1->clk);
ut_asserteq(1, scmi_ctx->agent[1]->clk_count); ut_asserteq(1, agent1->clk_count);
return 0; return 0;
} }
@ -106,26 +112,26 @@ static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
return ret; return ret;
} }
DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT); DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT);
static int dm_test_scmi_clocks(struct unit_test_state *uts) static int dm_test_scmi_clocks(struct unit_test_state *uts)
{ {
struct sandbox_scmi_devices *scmi_devices; struct sandbox_scmi_devices *scmi_devices;
struct sandbox_scmi_service *scmi_ctx; struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent0;
struct sandbox_scmi_agent *agent1;
struct udevice *dev = NULL; struct udevice *dev = NULL;
int ret_dev; int ret_dev;
int ret; int ret;
if (!IS_ENABLED(CONFIG_CLK_SCMI))
return 0;
ret = load_sandbox_scmi_test_devices(uts, &dev); ret = load_sandbox_scmi_test_devices(uts, &dev);
if (ret) if (ret)
return ret; return ret;
scmi_devices = sandbox_scmi_devices_ctx(dev); scmi_devices = sandbox_scmi_devices_ctx(dev);
scmi_ctx = sandbox_scmi_service_ctx(); scmi_ctx = sandbox_scmi_service_ctx();
agent0 = scmi_ctx->agent[0];
agent1 = scmi_ctx->agent[1];
/* Test SCMI clocks rate manipulation */ /* Test SCMI clocks rate manipulation */
ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0])); ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0]));
@ -135,9 +141,9 @@ static int dm_test_scmi_clocks(struct unit_test_state *uts)
ret_dev = clk_set_rate(&scmi_devices->clk[1], 1088); ret_dev = clk_set_rate(&scmi_devices->clk[1], 1088);
ut_assert(!ret_dev || ret_dev == 1088); ut_assert(!ret_dev || ret_dev == 1088);
ut_asserteq(1000, scmi_ctx->agent[0]->clk[0].rate); ut_asserteq(1000, agent0->clk[0].rate);
ut_asserteq(1088, scmi_ctx->agent[0]->clk[1].rate); ut_asserteq(1088, agent0->clk[1].rate);
ut_asserteq(44, scmi_ctx->agent[1]->clk[0].rate); ut_asserteq(44, agent1->clk[0].rate);
ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0])); ut_asserteq(1000, clk_get_rate(&scmi_devices->clk[0]));
ut_asserteq(1088, clk_get_rate(&scmi_devices->clk[1])); ut_asserteq(1088, clk_get_rate(&scmi_devices->clk[1]));
@ -148,56 +154,107 @@ static int dm_test_scmi_clocks(struct unit_test_state *uts)
ut_assert(!ret_dev || ret_dev == 333); ut_assert(!ret_dev || ret_dev == 333);
/* Test SCMI clocks gating manipulation */ /* Test SCMI clocks gating manipulation */
ut_assert(!scmi_ctx->agent[0]->clk[0].enabled); ut_assert(!agent0->clk[0].enabled);
ut_assert(!scmi_ctx->agent[0]->clk[1].enabled); ut_assert(!agent0->clk[1].enabled);
ut_assert(!scmi_ctx->agent[1]->clk[0].enabled); ut_assert(!agent1->clk[0].enabled);
ut_asserteq(0, clk_enable(&scmi_devices->clk[1])); ut_asserteq(0, clk_enable(&scmi_devices->clk[1]));
ut_asserteq(0, clk_enable(&scmi_devices->clk[2])); ut_asserteq(0, clk_enable(&scmi_devices->clk[2]));
ut_assert(!scmi_ctx->agent[0]->clk[0].enabled); ut_assert(!agent0->clk[0].enabled);
ut_assert(scmi_ctx->agent[0]->clk[1].enabled); ut_assert(agent0->clk[1].enabled);
ut_assert(scmi_ctx->agent[1]->clk[0].enabled); ut_assert(agent1->clk[0].enabled);
ut_assertok(clk_disable(&scmi_devices->clk[1])); ut_assertok(clk_disable(&scmi_devices->clk[1]));
ut_assertok(clk_disable(&scmi_devices->clk[2])); ut_assertok(clk_disable(&scmi_devices->clk[2]));
ut_assert(!scmi_ctx->agent[0]->clk[0].enabled); ut_assert(!agent0->clk[0].enabled);
ut_assert(!scmi_ctx->agent[0]->clk[1].enabled); ut_assert(!agent0->clk[1].enabled);
ut_assert(!scmi_ctx->agent[1]->clk[0].enabled); ut_assert(!agent1->clk[0].enabled);
return release_sandbox_scmi_test_devices(uts, dev); return release_sandbox_scmi_test_devices(uts, dev);
} }
DM_TEST(dm_test_scmi_clocks, UT_TESTF_SCAN_FDT); DM_TEST(dm_test_scmi_clocks, UT_TESTF_SCAN_FDT);
static int dm_test_scmi_resets(struct unit_test_state *uts) static int dm_test_scmi_resets(struct unit_test_state *uts)
{ {
struct sandbox_scmi_devices *scmi_devices; struct sandbox_scmi_devices *scmi_devices;
struct sandbox_scmi_service *scmi_ctx; struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent0;
struct udevice *dev = NULL; struct udevice *dev = NULL;
int ret; int ret;
if (!IS_ENABLED(CONFIG_RESET_SCMI))
return 0;
ret = load_sandbox_scmi_test_devices(uts, &dev); ret = load_sandbox_scmi_test_devices(uts, &dev);
if (ret) if (ret)
return ret; return ret;
scmi_devices = sandbox_scmi_devices_ctx(dev); scmi_devices = sandbox_scmi_devices_ctx(dev);
scmi_ctx = sandbox_scmi_service_ctx(); scmi_ctx = sandbox_scmi_service_ctx();
agent0 = scmi_ctx->agent[0];
/* Test SCMI resect controller manipulation */ /* Test SCMI resect controller manipulation */
ut_assert(!scmi_ctx->agent[0]->reset[0].asserted) ut_assert(!agent0->reset[0].asserted)
ut_assertok(reset_assert(&scmi_devices->reset[0])); ut_assertok(reset_assert(&scmi_devices->reset[0]));
ut_assert(scmi_ctx->agent[0]->reset[0].asserted) ut_assert(agent0->reset[0].asserted)
ut_assertok(reset_deassert(&scmi_devices->reset[0])); ut_assertok(reset_deassert(&scmi_devices->reset[0]));
ut_assert(!scmi_ctx->agent[0]->reset[0].asserted); ut_assert(!agent0->reset[0].asserted);
return release_sandbox_scmi_test_devices(uts, dev); return release_sandbox_scmi_test_devices(uts, dev);
} }
DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT); DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT);
static int dm_test_scmi_voltage_domains(struct unit_test_state *uts)
{
struct sandbox_scmi_devices *scmi_devices;
struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent0;
struct dm_regulator_uclass_plat *uc_pdata;
struct udevice *dev;
struct udevice *regul0_dev;
ut_assertok(load_sandbox_scmi_test_devices(uts, &dev));
scmi_devices = sandbox_scmi_devices_ctx(dev);
scmi_ctx = sandbox_scmi_service_ctx();
agent0 = scmi_ctx->agent[0];
/* Set/Get an SCMI voltage domain level */
regul0_dev = scmi_devices->regul[0];
ut_assert(regul0_dev);
uc_pdata = dev_get_uclass_plat(regul0_dev);
ut_assert(uc_pdata);
ut_assertok(regulator_set_value(regul0_dev, uc_pdata->min_uV));
ut_asserteq(agent0->voltd[0].voltage_uv, uc_pdata->min_uV);
ut_assert(regulator_get_value(regul0_dev) == uc_pdata->min_uV);
ut_assertok(regulator_set_value(regul0_dev, uc_pdata->max_uV));
ut_asserteq(agent0->voltd[0].voltage_uv, uc_pdata->max_uV);
ut_assert(regulator_get_value(regul0_dev) == uc_pdata->max_uV);
/* Enable/disable SCMI voltage domains */
ut_assertok(regulator_set_enable(scmi_devices->regul[0], false));
ut_assertok(regulator_set_enable(scmi_devices->regul[1], false));
ut_assert(!agent0->voltd[0].enabled);
ut_assert(!agent0->voltd[1].enabled);
ut_assertok(regulator_set_enable(scmi_devices->regul[0], true));
ut_assert(agent0->voltd[0].enabled);
ut_assert(!agent0->voltd[1].enabled);
ut_assertok(regulator_set_enable(scmi_devices->regul[1], true));
ut_assert(agent0->voltd[0].enabled);
ut_assert(agent0->voltd[1].enabled);
ut_assertok(regulator_set_enable(scmi_devices->regul[0], false));
ut_assert(!agent0->voltd[0].enabled);
ut_assert(agent0->voltd[1].enabled);
return release_sandbox_scmi_test_devices(uts, dev);
}
DM_TEST(dm_test_scmi_voltage_domains, UT_TESTF_SCAN_FDT);

View File

@ -11,6 +11,7 @@ obj-y += longjmp.o
obj-$(CONFIG_CONSOLE_RECORD) += test_print.o obj-$(CONFIG_CONSOLE_RECORD) += test_print.o
obj-$(CONFIG_SSCANF) += sscanf.o obj-$(CONFIG_SSCANF) += sscanf.o
obj-y += string.o obj-y += string.o
obj-y += strlcat.o
obj-$(CONFIG_ERRNO_STR) += test_errno_str.o obj-$(CONFIG_ERRNO_STR) += test_errno_str.o
obj-$(CONFIG_UT_LIB_ASN1) += asn1.o obj-$(CONFIG_UT_LIB_ASN1) += asn1.o
obj-$(CONFIG_UT_LIB_RSA) += rsa.o obj-$(CONFIG_UT_LIB_RSA) += rsa.o

126
test/lib/strlcat.c Normal file
View File

@ -0,0 +1,126 @@
// SPDX-License-Identifier: GPL-2.1+
/*
* Copyright (C) 2021 Sean Anderson <seanga2@gmail.com>
* Copyright (C) 2011-2021 Free Software Foundation, Inc.
*
* These tests adapted from glibc's string/test-strncat.c
*/
#include <common.h>
#include <test/lib.h>
#include <test/test.h>
#include <test/ut.h>
#define BUF_SIZE 4096
char buf1[BUF_SIZE], buf2[BUF_SIZE];
static int do_test_strlcat(struct unit_test_state *uts, int line, size_t align1,
size_t align2, size_t len1, size_t len2, size_t n)
{
char *s1, *s2;
size_t i, len, expected, actual;
align1 &= 7;
if (align1 + len1 >= BUF_SIZE)
return 0;
if (align1 + n > BUF_SIZE)
return 0;
align2 &= 7;
if (align2 + len1 + len2 >= BUF_SIZE)
return 0;
if (align2 + len1 + n > BUF_SIZE)
return 0;
s1 = buf1 + align1;
s2 = buf2 + align2;
for (i = 0; i < len1 - 1; i++)
s1[i] = 32 + 23 * i % (127 - 32);
s1[len1 - 1] = '\0';
for (i = 0; i < len2 - 1; i++)
s2[i] = 32 + 23 * i % (127 - 32);
s2[len2 - 1] = '\0';
expected = len2 < n ? min(len1 + len2 - 1, n) : n;
actual = strlcat(s2, s1, n);
if (expected != actual) {
ut_failf(uts, __FILE__, line, __func__,
"strlcat(s2, s1, 2) == len2 < n ? min(len1 + len2, n) : n",
"Expected %#lx (%ld), got %#lx (%ld)",
expected, expected, actual, actual);
return CMD_RET_FAILURE;
}
len = min3(len1, n - len2, (size_t)0);
if (memcmp(s2 + len2, s1, len)) {
ut_failf(uts, __FILE__, line, __func__,
"s2 + len1 == s1",
"Expected \"%.*s\", got \"%.*s\"",
(int)len, s1, (int)len, s2 + len2);
return CMD_RET_FAILURE;
}
i = min(n, len1 + len2 - 1) - 1;
if (len2 < n && s2[i] != '\0') {
ut_failf(uts, __FILE__, line, __func__,
"n < len1 && s2[len2 + n] == '\\0'",
"Expected s2[%ld] = '\\0', got %d ('%c')",
i, s2[i], s2[i]);
return CMD_RET_FAILURE;
}
return 0;
}
#define test_strlcat(align1, align2, len1, len2, n) do { \
int ret = do_test_strlcat(uts, __LINE__, align1, align2, len1, len2, \
n); \
if (ret) \
return ret; \
} while (0)
static int lib_test_strlcat(struct unit_test_state *uts)
{
size_t i, n;
test_strlcat(0, 2, 2, 2, SIZE_MAX);
test_strlcat(0, 0, 4, 4, SIZE_MAX);
test_strlcat(4, 0, 4, 4, SIZE_MAX);
test_strlcat(0, 0, 8, 8, SIZE_MAX);
test_strlcat(0, 8, 8, 8, SIZE_MAX);
for (i = 1; i < 8; i++) {
test_strlcat(0, 0, 8 << i, 8 << i, SIZE_MAX);
test_strlcat(8 - i, 2 * i, 8 << i, 8 << i, SIZE_MAX);
test_strlcat(0, 0, 8 << i, 2 << i, SIZE_MAX);
test_strlcat(8 - i, 2 * i, 8 << i, 2 << i, SIZE_MAX);
test_strlcat(i, 2 * i, 8 << i, 1, SIZE_MAX);
test_strlcat(2 * i, i, 8 << i, 1, SIZE_MAX);
test_strlcat(i, i, 8 << i, 10, SIZE_MAX);
}
for (n = 2; n <= 2048; n *= 4) {
test_strlcat(0, 2, 2, 2, n);
test_strlcat(0, 0, 4, 4, n);
test_strlcat(4, 0, 4, 4, n);
test_strlcat(0, 0, 8, 8, n);
test_strlcat(0, 8, 8, 8, n);
for (i = 1; i < 8; i++) {
test_strlcat(0, 0, 8 << i, 8 << i, n);
test_strlcat(8 - i, 2 * i, 8 << i, 8 << i, n);
test_strlcat(0, 0, 8 << i, 2 << i, n);
test_strlcat(8 - i, 2 * i, 8 << i, 2 << i, n);
test_strlcat(i, 2 * i, 8 << i, 1, n);
test_strlcat(2 * i, i, 8 << i, 1, n);
test_strlcat(i, i, 8 << i, 10, n);
}
}
return 0;
}
LIB_TEST(lib_test_strlcat, 0);

26
test/py/tests/test_qfw.py Normal file
View File

@ -0,0 +1,26 @@
# SPDX-License-Identifier: GPL-2.0+
# Copyright (c) 2021, Asherah Connor <ashe@kivikakk.ee>
# Test qfw command implementation
import pytest
@pytest.mark.buildconfigspec('cmd_qfw')
def test_qfw_cpus(u_boot_console):
"Test QEMU firmware config reports the CPU count."
output = u_boot_console.run_command('qfw cpus')
# The actual number varies depending on the board under test, so only
# assert a non-zero output.
assert 'cpu(s) online' in output
assert '0 cpu(s) online' not in output
@pytest.mark.buildconfigspec('cmd_qfw')
def test_qfw_list(u_boot_console):
"Test QEMU firmware config lists devices."
output = u_boot_console.run_command('qfw list')
# Assert either:
# 1) 'test-one', from the sandbox driver, or
# 2) 'bootorder', found in every real QEMU implementation.
assert ("bootorder" in output) or ("test-one" in output)

View File

@ -679,7 +679,7 @@ def cleanup_headers(configs, options):
continue continue
for filename in filenames: for filename in filenames:
if not filename.endswith(('~', '.dts', '.dtsi', '.bin', if not filename.endswith(('~', '.dts', '.dtsi', '.bin',
'.elf')): '.elf','.aml','.dat')):
header_path = os.path.join(dirpath, filename) header_path = os.path.join(dirpath, filename)
# This file contains UTF-16 data and no CONFIG symbols # This file contains UTF-16 data and no CONFIG symbols
if header_path == 'include/video_font_data.h': if header_path == 'include/video_font_data.h':

View File

@ -353,7 +353,7 @@ index 0000000..2234c87
Args: Args:
pm: PatchMaker object to use pm: PatchMaker object to use
msg" Expected message (e.g. 'LIVETREE') msg: Expected message (e.g. 'LIVETREE')
pmtype: Type of problem ('error', 'warning') pmtype: Type of problem ('error', 'warning')
""" """
result = pm.run_checkpatch() result = pm.run_checkpatch()
@ -439,6 +439,18 @@ index 0000000..2234c87
self.check_struct('per_device_auto', '_priv', 'DEVICE_PRIV_AUTO') self.check_struct('per_device_auto', '_priv', 'DEVICE_PRIV_AUTO')
self.check_struct('per_device_plat_auto', '_plat', 'DEVICE_PLAT_AUTO') self.check_struct('per_device_plat_auto', '_plat', 'DEVICE_PLAT_AUTO')
def check_strl(self, func):
"""Check one of the checks for strn(cpy|cat)"""
pm = PatchMaker()
pm.add_line('common/main.c', "strn%s(foo, bar, sizeof(foo));" % func)
self.checkSingleMessage(pm, "STRL",
"strl%s is preferred over strn%s because it always produces a nul-terminated string\n"
% (func, func))
def testStrl(self):
"""Check for uses of strn(cat|cpy)"""
self.check_strl("cat");
self.check_strl("cpy");
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()